Introduction to extension development

First steps in writing plugins and modules for Cotonti

#1. Introduction

So you want to write your own extensions? This is the first in a series of articles to help you use the Cotonti modules and plugins system. Each article in the series will discuss a specific subject concerning plugin development.

  1. Extension types and initial setup (this article)
  2. Using and understanding hooks
  3. Setting config values and using them
  4. XTemplate system (tags, blocks, rows) and it's advanced features
  5. Localisation and resources
  6. Optimisation and best practices

#2. Choosing the extension type

The first step in the process of developing an extention is choosing what type you're going to develop. There are two types of extensions: modules and plugins. Modules are stand-alone applications within your website, such as forums, private messaging, file management and so on. Plugins are usually smaller and provide additional functionality. In short: plugins extend existing modules or core features, while modules add completely new stand-alone features to the system. In practice there is a very thin line between modules and plugins. They offer more or less the same possiblities, are developed in mostly the same way, and in some cases one could argue about the type of extension to choose. Here's an overview of criteria and differences, so you get a better idea of what type to choose:

Module Plugin
Provides stand-alone functionality Extends existing module or core
Usually doesn't use many hooks May consist of many parts, each hooking in in another area
Provides hooks for plugins May provide hooks, but usually doesn't
More likely to have its own database tables Doesn't normally use its own database tables.
Can have custom permissions for contained items Permissions are set for enitre plugin
Can have its own structure in site's categories tree Doesn't have own categories

In some specific cases you will be forced to use a module, since plugin loader provides limited flexibility. For example, if you want to bypass Cotonti's common.php (which handles user authentication, the database connection etc.) you will have to use a module so you can use your own version of common.php.

Remember that there is no golden rule here. You are free to choose what type you want. Right now there isn't much difference as far as coding style and flexibility goes, however this may change in the future.

#3. Setting up your extension

Next step is setting up the directory structure and creating some default files. Modules go in the 'modules' directory, while plugins (you guessed it) go in the 'plugins' folder. Your directory structure should look like this:

If the extension you will be writing is not going to use template files (tpl), setup scripts (setup) and/or language strings (lang), you are free to omit the respective folders. If you want to get started really fast, it's often easiest to copy another plugin (preferable one of some quality) and modify that.

Your extension code ('myext' in the example) should:

  • be unique
  • be all lowercase
  • consist of only letters, numbers and underscores (_)

It is not allowed to use the same extension code for both a module and a plugin because it may cause conflicts between the plugin and the module.

All files inside your extension folder have a predefined code structure:


/* ====================
==================== */

defined('COT_CODE') or die('Wrong URL.');

// Your plugin code


The first part contains details used by Cotonti to setup the extension when it's installed through the admin panel. While in previous Cotonti releases there were much more values, in Siena only Hooks is required for your regular extension files. Hooks is a comma-separated list of system hook names. This determines the location where your code will be included. Usually you use only one hook for each file. If you specify 'standalone' as hook (for plugins only), the code will be executed when you call the plugin using index.php?e=myext. However, if the core of your plugin uses the 'standalone' hook, you should consider writing a module instead.

Every extension must have a setup file. This file specifies the plugin details as displayed by the admin panel. The file must be named like myext.setup.php (where myext is the extension code) and look like this:


/* ====================
Name=My Extension
Description=This is my first Cotonti extension
Copyright=Your company

config_name=01:string::Default value:Description
==================== */

 * This is my first Cotonti extension
 * @package My Extension
 * @version 1.0
 * @author You
 * @copyright Your company
 * @license BSD

defined('COT_CODE') or die('Wrong URL.');

  • Code: must match the folder name / first part of filename. Lowercase and alphanumeric.
  • Name: the name of the plugin as displayed by the admin panel.
  • Description: displayed in the admin panel. Usually one or two lines discribing the features provided by the extension.
  • Version: a version number used by Cotonti to detect upgrades. Should be formatted to be accepted by version_compare().
  • Date: Production date (today). Not really used by anything, it's for your own reference.
  • Author: Your name
  • Copyright: Name of your company, or your name
  • Notes: often used to specify the code license, but can be used for anything.
  • Auth_guests: default rights for guests
  • Lock_guests: rights for guests which cannot be modified (default is forced)
  • Auth_members: default rights for logged in users
  • Lock_members: rights for registered users which cannot be modified (default is forced)

The configuration format is described here.

A module always comes with a main part which is an entry-point. It is located in the module's folder and is called like myext.php. Similarly to 'standalone' parts of plugins, main module part is called when accessing index.php?e=myext. But it gives you more freedom in settting the script environment than standalone plugins. An entry-point script usually looks like this:

/* ====================
==================== */

 * My Extension
 * @version 1.0
 * @author You
 * @copyright Your Company

defined('COT_CODE') or die('Wrong URL.');

// Environment setup
define('COT_MYEXT', TRUE);
$env['location'] = 'myext';

// Load module functions
require_once cot_incfile('myext', 'module');

// Your code here

You have full flexibility here to handle incoming requests the way you want to. Often you will use a switch to determine what part of the module to load. If you do that it's recommended to use the cot_incfile function as shown above. You can specify a third parameter in cot_incfile to load a specific file from modules/myext/inc/. The default value is 'functions', which will load modules/myext/inc/myext.functions.php.

1. diiagma  2011-08-31 09:47

You guys rock ! Congrats for your open source solution this is great. I finished the install part and I will start to develop some plugins and modules soon, thanks for your 1st tutorial it is presious help for a newbie like me.



2. Macik  2015-09-10 18:01

Some tutorial [in russian] you can find here: forums?m=posts&q=7887
Пошаговая инструкция по созданию плагина от одного из пользователейforums?m=posts&q=7887

Only registered users can post new comments