HTML Logo by World Wide Web Consortium ( Click to learn more about our commitment to accessibility and standards.

Moving forward with Composr

ocPortal has been relaunched as Composr CMS. ocPortal 9 is superseded by Composr 10.

Head over to for our new site, and to our migration roadmap. Existing ocPortal member accounts have been mirrored.

ocPortal Tutorial: Making an addon (part 1)

Written by Chris Graham, ocProducts
At ocProducts we really want to encourage users of ocPortal to start making addons and releasing them in an Open Source code ecosystem. In order to get the ball rolling we've done a number of things:
  • Made a powerful framework for customising ocPortal and releasing addons
  • Written a huge devguide, which explains all ocPortal's conventions, systems, and APIs
  • Written a number of tutorials, such as these
  • Released our own semi-official addons, as examples
  • Assisted, answering technical questions
  • Provided a distribution system
  • Made ocPortal Open Source
However, at the end of the day addon-making is in the hands of users – whilst we can empower, we cannot write all the actual addons ourselves unless we're paid to do so. Therefore users who need addons need to 'carry the torch', promoting and being active in the ocPortal community. The more everyone puts in, the more everyone gets out – our users together are stronger than we are.

The 'Making an addon' series of tutorials are highly technical, intended for those who already know PHP programming and the basics of ocPortal's modularity. Fortunately we explain these things in other tutorials (yes, we even teach programming to an extent), and there's a massive amount of PHP educational material on the web.

If you have any questions or want to discuss solutions, we've created forums on our website for each tutorial in this series. Please ask questions there, even if they seem basic.


Thumbnail: Use an environment you're comfortable in

Use an environment you're comfortable in

Thumbnail: To be able to search through files efficiently is essential

To be able to search through files efficiently is essential

Personally I develop ocPortal on my own computer under Windows. I have a PHP webserver setup and I manipulate files directly on my hard disk. I have cacheing disabled on my ocPortal install so that I don't have to mess around decacheing when I change files directly.

One of the most handy things about developing on the desktop is to be able to quickly run file contents searches in Windows to find out where stuff is done. Unfortunately though, by default Windows will not search inside most non-Microsoft file types unless you do some special set up. Here is a guide to what to do to fix this – use the technique for the ".php", ".css" and ".tpl" file types.
Once this is done you'll be able to quickly find things by opening up an explorer window and hitting F3.
Alternatively, you can use an alternate search tool such as Agent Ransack.

ocPortal might seem a bit daunting with its (approximately) 4,000 files, but remember they are just files, and you don't need to understand everything to make changes – you only need an understanding of the core stuff, and the stuff your changes interact with. If you take backups of a file, you can restore that file to a prior state just by restoring your backup. If you add a file and it breaks things, you can delete it if you really need to.

PHP is a really fantastic language for beginners to develop for because you don't need to worry about compiling your code – you just make edits and test them directly. Just use the simple Edit-Save-Refresh sequence.
Thumbnail: A good editor is essential

A good editor is essential

Thumbnail: Firefox is probably the best browser to develop in, thanks to the great selection of powerful extensions

Firefox is probably the best browser to develop in, thanks to the great selection of powerful extensions

Making a counter block

We're going to be making a new ocPortal block that does 'counting down' or 'counting up' to a date/time given as a parameter to that block. I won't be explaining how code works in these addon making tutorials, as it is assumed you already know the basics of PHP – if you don't, you can always go back and forth between these tutorials and whatever you're learning PHP from. Or if you have natural talent, you might be able to pick it up as you go along.

So, we know what we want to do, but where do we start? Well for this particular example it's fairly obvious because we know that we're making a block, and those are almost always completely self-contained.

As this is the first example, I'm going to make this as simple as possible. The simplest way to make a block is to make it as a 'miniblock'. Let's call out block 'main_count'. To create the block we need to create the PHP file that contains the code, and this will be sources_custom/miniblocks/main_count.php.
Putting this code in that file should make the block for us…



if (!is_numeric($target)) $target=strtotime($target); else $target=intval($target); // Let's accept either a timestamp or human strings that PHP's 'strtotime' can understand
if ($seconds_to_go>=0) $positive_seconds_to_go=$seconds_to_go; else $positive_seconds_to_go=-$seconds_to_go;
if ($seconds_to_go>=0)
echo <<<END
{$time} hours to go.
echo <<<END
{$time} hours since.

This is just an addon, so we don't need to worry about making templates or new language files – this is just something for our own purposes, so it doesn't have to meet the same quality as the ocPortal code itself does.

Now to use our block, we just need to put some Comcode into the page that we want it on:


Some famous event...
[block="5 Apr 2063"]main_count[/block]

Thumbnail: A very simple countdown block -- but it'd be easy to style it and put it to work on useful tasks!

A very simple countdown block -- but it'd be easy to style it and put it to work on useful tasks!


At the end of each of the tutorial in this series I will be releasing some exercises out. If you complete them, or have trouble completing them, post about it in the forum for this tutorial!

Hit counter

Make a block that acts as a good old-style hit counter. To do this you'll probably want to use the 'get_value' and 'set_value' functions. I'm not going to tell you where they are because you can find them yourself by doing a file search for 'function get_value(' – once you do, you can view the actual source code for the functions in your text editor.

Post requestor

Make a block that detects if the current logged in member has ever posted on the forum. If they have, don't do any output, but if they haven't output a suggestion that they make a post.
You might go about this in one of two ways:
  • Writing it by checking post count, which can be read via the ocPortal forum driver system ($count=$GLOBALS['FORUM_DRIVER']->get_post_count(get_member());
  • Assuming a forum type, such as OCF, and querying the database ($count=$GLOBALS['FORUM_DB']->query_value('<post table name>','COUNT(*)',array('<poster field id>'=>get_member()));)

The second is more adventurous and help you get used to using the database, which is always helpful.

Points challenge

10 points will be given to the first member to explain a yet-unexplained bug in this code…

PHP code

$output=new ocp_tempcode();
$output.='<p>First paragraph</p>';
$output.='<p>Some data: '.$data.'</p>';
$GLOBALS['SITE_DB']->query('UPDATE ocp2_whatever_table SET whatever_property='.get_param('sent_value'));

The race is on.

1 point will be automatically given to anybody who posts on our forum because you get a point for each forum post anyway ;). Please do use our forum!

See also