How to write plugins

From phpCMS

Jump to: navigation, search

Contents

[edit] First Considerations

Before starting on a plugin, you should know:

  • what your pluging shall do - but if you don't know about that already, you most likely don't want to write a plugin at all.
  • how your plugin shall be named - the chosen name should be unique and descriptive

[edit] Starting to write a new plugin

Create a subdirectory with the plugin's name within the parser/plugs/ directory. This is not mandatory, but really eases maintenance. Even if your plugin itself only has one file - think about adding a documentation or an example content file, and you know why an own directory makes sense. This directory should preferably be named like the plugin you want to write - the plugin file itself can then be named plugin.php or something like that.

[edit] Plugin features offered by phpCMS

As writing a plugin is in fact identical to writing a PHP script, you should know how to write a PHP program prior to writing a new phpCMS plugin.

Here are a few things you might want to know:

[edit] Available Variables

Plugin are able to access all variables available in the global scope, which includes values submitted to the site with a GET- or POST-Request. Remember to use the superglobal-arrays $_GET, $_POST, $_SERVER and so on instead of relying on automatically registered variables.

In addition, the parser provides the following variables to the plugin (the values can be changed by the plugin):

$PageContent 
This variable contains the entire contents of the content file. The variable has the type OBJECT of ARRAY of STRING. You can access a field value in the content file by its field name. For example, if there's a field {TITLE} in the content file, you can access its first line by using $PageContent->TITLE[0]. You have always to specify the array index, even when a field contains only one single line. When you need the complete contents of a multi-line field, use the implode function.
$CacheState 
This variable contains a STRING and can have the value on or off, defining the behaviour of the phpCMS cache. In case the variable is set to on, the content of the document will be stored in the cache of phpCMS after parsing, otherwise not. Setting this variable to off does not imply the deletion of previously cached pages.
$ClientCache 
Another STRING, again settable to on or off. In case it's set to on, the visitor's browser or proxys on the way are allowed to cache the result, otherwise they're forbidden to do so.
$ProxyCacheTime 
The content of this variable is interpreted as a number of seconds and defines the time a page is allowed to be cached client-side.
$Tags 
This variable is of type ARRAY of ARRAY of STRING, it's content are the tags read from the tagfile. Additionally you can find some tags provided by phpCMS. Your plugin can add own tags to the end of the list. In any case, $Tags[COUNTER][0] should contain the value that should be replaced, and $Tags[COUNTER][1] must contain the replacement. In this example, COUNTER is the number of the tag in the array. If you want to append a tag, you can even use $Tags[] = array("to_replace","with_replacement");
This Var is not defined if you load a Plugin in a Contentfile!!
$PluginBuffer 
A variable of type ARRAY of STRING and is used to return plugin-output back to the phpCMS. Even if you only pass one value, you need to use the first element of this array.
$CHECK_PAGE->path 
Path to the file currently parsed, relative to the webserver root directory.
$CHECK_PAGE->name 
Name of the file currently parsed.

[edit] phpCMS-supplied function

In addition to the abovementioned variables, phpCMS also offers a few functions for use in plugins:

$PHP->GetDocRoot() 
Contains the web-server document root.
$PHP->Version($number) 
Contains the PHP version number. $number is a value from 1 to 4 and controls the returned value - either major-, minor- or patchlevel-number of PHP.
$PHP->API() 
If mod is returned, PHP is running as server-module, if cgi is returned, PHP is set up as CGI.
$PHP->OS() 
Returns the operating system PHP (and thus phpCMS) is running on. This is either win for a windows-based system, nix for a POSIX-based system or an empty string in case the operating system couldn't be determined.

[edit] Plugin Output

As already mentioned in the user-side explanation, plugins can modify the pages in three different ways:

using Tags 
If you want to modify the tags used on your page, you need to access the abovementioned variable $Tags.
direct changes 
For this, the variable $PageContent is what you're looking for. Note that you have full read/write access, and each string in said variable represents a whole line in the resulting page.
plugin output 
All plugin output has to be written into the plugin buffer, represented by the variable $PluginBuffer. Note that this variable needs to be an array - so if you just have one line of output, put it into the first element ($PluginBuffer[0]).

[edit] Example 1

The first example plugin we'll be writing here will be modifying the resulting page by providing tag rewrite-rules. For demonstration, the plugin will be split up into two PHP files - this is of course not really needed for a plugin this short.

The plugin's purpose is to find specific Tags and replace them, printing their content in a different HTML-formatting.

[edit] The Plugin file

<?php
// Make sure, that the constant will be defined only once, 
// even if the plugin is loaded several times
if (!defined('PLUGIN_INC'))
{
  define('PLUGIN_INC', dirname(__FILE__) . '/');
}

// Make sure that the functions will be defined only once, 
// even if plugin is loaded several times

if (!defined('PLUGIN_FUNC'))
{
  require_once(PLUGIN_INC.'pluginfunc.inc.php');
}

// Search within the content for plugin tags with parameter
$lines=count($PageContent->CONTENT);

for($ln=0;($ln<$lines);$ln++)
{
  if (preg_match_all(
     "/<!-- PLUGIN ([a-zA-Z0-9\(\)\@_,:~#=\|\-\+\.\*\s]+) -->/",
     $PageContent->CONTENT[$ln],  $matches))
  {
    foreach ($matches[1] as $thismatch)
    {
      $current = count($Tags);
      // Append new tag
      $Tags[$current][0] = "<!-- PLUGIN $thismatch -->";
      $Tags[$current][1] = genPlugin($thismatch);
    }
  }
}
?>

Important: Any Whitespaces before or after the PHP tags are fatal!

[edit] The Functions file

<?php
function genPlugin($S_Param)
{
  return '<i>' . $S_Param . '</i>';
}
?>

[edit] The Contents file

{PLUGIN FILE="$plugindir/plugin/plugin.php" TYPE="DYNAMIC"}
{PROJECT}
./template/home.ini

{MENU}
00.09

{TITLE}
Pictures

{CONTENT}
<!-- PLUGIN Test -->

[edit] The Result

Now there should be displayed an italic Test.

[edit] Example 2

The second example plugin is a swear-word filter. It directly modifies the resulting page, removing found words and replacing them with a *BEEP*. Because the plugin itself is very short (and easy), it is given as a single file

[edit] The Plugin file

<?php

// Still, we have to make sure the function only gets defined once
if (!defined("DONT_SWEAR"))
{
  define("DONT_SWEAR", 1);

  function replace_swearwords_in($line)
  {
    static $swearwords;

    // Yes, I know - those are usually not what you expected here,
    // but this is only an example, and I bet you know what words
    // would usually fill that array...
    if (!isset($swearwords))
      $swearwords = array("doh!", "foo", "bar", "grmpf");
    return str_replace($swearwords,"*BEEP*",$line);
  }
}

$lines=count($PageContent->CONTENT);

for($ln=0;($ln<$lines);$ln++)
{
  $PageContent->CONTENT[$ln] = replace_swearwords_in($PageContent->CONTENT[$ln]);
}
?>

[edit] The Contents file

{PLUGIN FILE="$plugindir/no_swear/plugin.php" TYPE="DYNAMIC"}
{PROJECT}
./template/home.ini

{MENU}
00.09

{TITLE}
Pictures

{CONTENT}
This is so doh!. That foo bar example is nothing but grmpf....

[edit] The Result

Swearing like this should be blocked, shouldn't it? Well - the output of that content file would be something like:

This is so *BEEP*. That *BEEP* *BEEP* example is nothing but *BEEP*....

[edit] Hints

[edit] Output & Editor

If you have written a STATIC-plugin, that reads the content-file and writes e.g. a list of pagecontent made from the various headlines at the beginning of the content, it will work fine. The code would look like ...

$out = .....; /* HTML-code */
$PageContent->CONTENT[0] = $out . $PageContent->CONTENT[0];

But if you edit the page via the online-editor, you run into a problem. The pagecontent is part of the editable area. And to make things worse, after saving there are two pagecontents !!!!

As Guandalug suggested: [...]Easiest (*lol*) solution would be to teach your plugin not to work in Edit-Mode. Sounds logical, doesn't it?

Here's the catch: Determining whether you're in edit-mode or not is a funny thing to do right now. This will change with a future version of phpCMS, where Plugins will have access to a much more detailed API and need to use less internal code.[...]

 
if (isset($DEFAULTS->EDIT) && ($DEFAULTS->EDIT == 'on')) {
  // edit-mode - no action
} else {
  // THE code
}


Main Page: Main Page | Top Page: Developer Documentation MainPage

Personal tools