Try CumulusClips Cloud Hosting

Plugin Guide

Plugins grant you the ability to add custom functionality to CumulusClips without having to modify the core files. This is important because most of the core files are overwritten during the update process, thus any changes made to these files would be lost.

Overview

Plugins in the CumulusClips world are PHP clases. They contain functions which execute the developer's custom code. CumulusClips uses an event based plugin system. This means that functions within your plugins can be ordered to run when certain events are triggered by the system. When the system encounters an event hook all the plugin methods that were attached to that event hook are executed. Event hooks are dispersed throughout the entire codebase at locations our team feels would be most beneficial to developers. Plugins and themes can even define their own custom events.

Plugin Hook Types

Plugin hooks come in two forms, events and filters. Both behave almost identically. They are sometimes passed parameters depending on the context. These parameters are in turn passed along to any plugin code attached to the hooks. Where the two differ is that plugin methods attached to filters, are expected to return the first parameter passed. This is so that the filtered parameter can then be passed along to the next plugin or the rest of the codebase. Plugin methods attached to events are not expected to have a return value.

Events

// In CumulusClips
Plugin::triggerEvent('sample.event', 'foo');

// In your plugin
public function myPluginMethod($param)
{
    // $param has a value of 'foo'.
    // Do some stuff with foo
    $param;
}

Filters

// In CumulusClips
$variable = Plugin::triggerFilter('sample.filter', 'foo');

// In your plugin
public function myPluginMethod($param)
{
    // $param has an initial value of 'foo'
    // Convert foo to foobar and return it to continue the chain
    return $param . 'bar';
}

Structure & Naming Conventions

Plugins are merely PHP classes. They extend the PluginAbstract class, i.e.

class MyPlugin extends PluginAbstract
{
    // Plugin code
}

The plugin class can have several public properties which are recognized by CumulusClips. Of course you can add your own additional one's, but these are the ones used internally by the system:

Property Name Type Required Description
name string True The name of your plugin. This is displayed in the Admin Panel
description string false A short description or notes for your plugin. This is displayed in the Admin Panel
author string false The plugin's author
url string false Fully qualified URL to the plugin's website
version string true Current version of the plugin, using semantic versioning, i.e. x.x.x

Here is an example of the built-in plugin properties in code:

class MyPlugin extends PluginAbstract
{
    /**
     * @var string Name of plugin
     */
    public $name = 'My Plugin';

    /**
     * @var string Description of plugin
     */
    public $description = 'Sample description';

    /**
     * @var string Name of plugin author
     */
    public $author = 'CumulusClips';

    /**
     * @var string URL to plugin's website
     */
    public $url = 'http://cumulusclips.org/';

    /**
     * @var string Current version of plugin
     */
    public $version = '1.0.0';
}

Plugin Structure

Plugins are stored in the /cc-content/plugins directory. Each plugin has it's own directory containing the plugin class file and any related files or dependencies. The plugin's parent directory, the plugin class file, and the class itself have the same name. This is very important, the directory, filename and class name always match. Consider the following example with a plugin name HelloWorld i.e.

/cc-content
  /plugins
    /HelloWorld
      HelloWorld.php

        class HelloWorld extends PluginAbstract
        {
          // Plugin code
        }

Installing Plugins

To install a plugin, just drop it's directory, containing the plugin class and files, inside of /cc-content/plugins. Your plugin will be now be listed in the plugins section (Admin Panel -> Plugins). The listing will display information about the plugin, as provided by the plugin class, such as the name, author, and status. If the plugin requires further installation there will be link saying 'Install' which will trigger the internal installation process for it. Otherwise there will be merely a link asking you to 'Activate' the plugin.

It is also possible to install a plugin within a .zip archive via the Add Plugin page in the Admin Panel. On this page you can upload a plugin and are given the option to automatically enable/install the plugin or just simply upload and leave it disabled.

Plugin Methods

Plugins can contain several methods  (a.k.a. functions) that are recognized by CumulusClips to perform certain actions to the plugin. These special methods are the following:

Method Name Required Description
load true Called when the plugin is initially loaded during each page load
settings false Handles and displays the plugin's settings page
install false Performs custom operations when the plugin is installed
uninstall false Performs custom operations when the plugin is uninstalled

Load Method

The load method is called on every plugin during the bootstrap phase of the application, on every request. This is a plugin's opportunity to attach to any event hooks in the system. Though it's technically possible to attach to event hooks in other places, i.e. constructor, this is the recommended location for attaching to event hooks. Here is a sample load method:

public function load()
{
    // Hook attachments go here
    Plugin::attachEvent('app.init', array($this, 'myCustomMethod'));
}

To attach to events you must use Plugin::attachEvent method.

Plugin::attachEvent('EVENT_NAME', array($this, 'INTERNAL_METHOD_NAME'));

To attach to filters you must use Plugin::attachFilter method.

Plugin::attachEvent('EVENT_NAME', array($this, 'INTERNAL_METHOD_NAME'));

The Plugin::attachEvent method accepts two parameters. The first is the name of the event being attached to, the second is a function name, or callable array as defined by the PHP call_user_func function.

A plugin can attach to as many event hooks as it neccessary. By placing all event hook attachments in the load method any developer can quickly see what events a plugin is attaching to. This example shows a complete load method with several event hook attachments:

public function load()
{
    Plugin::attachEvent('app.start', array($this, 'myCustomMethod'));
    Plugin::attachEvent('index.start', array($this, 'customRetrieveVideos'));
    Plugin::attachEvent('index.before_render', array($this, 'CcustomOrderVideos'));
}

Settings Method

Plugins can optionally display their own settings page. This can be used when the plugin has settings that can be configured by the user. When a plugin defines a public settings method, the system enables a settings page for the plugin and displays a "Settings" link next to the plugin in the Admin Panel.

The settings method is executed on the plugin's settings page. It is called before any headers are sent. This is useful for any pre-processing such as creating session values, handling form requests, and any other logic. The settings method is expected to output the HTML for the body of the plugin's settings page. Here's a sample settings() method which outputs a form with various settings for the plugin:

MyPlugin.php
public function settings()
{
    $this->handleFormRequest();

    echo "<form method="post">"
        . "<label>Setting Name:</label> <input type="text" name="setting_name" value="" />"
        . "<label>Setting Value:</label> <input type="text" name="setting_value" value="" />"
        . "<input type="submit" name="submit" value="Update Plugin Settings" />"
        . "</form>";
}

That would most definitely work, but we recommend moving HTML to a seperate file, i.e. settings_page.html, and including it. This would be a much cleaner approach:

MyPlugin.php
public function settings()
{
    $this->handleFormRequest();

    include('./settings_page.html');
}
settings_page.html
<form method="post">

<label>Setting Name:</label> <input type="text" name="setting_name" value="" />
<label>Setting Value:</label> <input type="text" name="setting_value" value="" />"
<input type="submit" name="submit" value="Update Plugin Settings" />

<form>

You can use this method to display the settings page with a form for your plugin, as well as validate and process the form when submitted.

NOTE: The settings method is expected to output (or echo) it's content directly to buffer, not return it.

Install Method

Plugins that need to perform any additional installation operations when installed can define a public install method. This can be used for example to make database modifications, create files, change files, etc. The Install method is called when a plugin is enabled for the first time. Once this method has been called on a plugin (if it’s provided) it will never be called again. Unless the plugin is uninstalled and then re-installed.

This method is not required and can be omitted. It will only execute if it exists during plugin enablement. Here’s a sample install method:

public function install()
{
    $db = Database::getInstance();
    $query = "INSERT INTO settings (name,value) VALUES ('plugin_setting','setting_value')";
    $db->query($qeury);
}

Uninstall Method

To revert any additional actions made by the plugin during it’s installation you can use the uninstall method. This method is called when a plugin is deleted via the Admin Panel. This is where you would for example remove any database tables or delete files, etc. This method is not required and can be omitted. It will only execute if it exists during plugin deletion.

public function uninstall()
{
    $db = Database::GetInstance();
    $query = "DELETE FROM settings WHERE name LIKE 'custom_plugin%'";
    $db->query($qeury);
}

NOTE: Keep in mind that it’s always possible for a user to physically remove a plugin file instead of correctly doing so via the Admin Panel. This situation may present unexpected situations for you as a plugin developer. It’s important you write your code in a way that can handle this situation if it does occur.

Sample Plugin

For your reference here is a complete plugin. You can copy and save it to your computer. Make sure you rename the class to match whatever named the plugin file, also update the event name to whatever hook you wish to attach to.

<?php

class MyPlugin extends PluginAbstract
{
    /**
     * @var string Name of plugin
     */
    public $name = 'My Plugin';

    /**
     * @var string Description of plugin
     */
    public $description = 'Sample description';

    /**
     * @var string Name of plugin author
     */
    public $author = 'CumulusClips';

    /**
     * @var string URL to plugin's website
     */
    public $url = 'http://cumulusclips.org/';

    /**
     * @var string Current version of plugin
     */
    public $version = '1.0.0';

    /**
     * Attaches plugin methods to hooks in code base
     */
    public function load()
    {
        Plugin::Attach('event.name', array(__CLASS__, 'myCustomCode'));
    }

    /*
     * Executes custom code
     */
    public function myCustomCode()
    {
         // Plugin code
    }
}