<?php
/*
 * File: ratatoeskr/sys/plugin_api.php
 * Plugin API contains the plugin base class and other interfaces to Ratatöskr.
 *
 * License:
 * This file is part of Ratatöskr.
 * Ratatöskr is licensed unter the MIT / X11 License.
 * See "ratatoeskr/licenses/ratatoeskr" for more information.
 */

require_once(dirname(__FILE__) . "/models.php");
require_once(dirname(__FILE__) . "/textprocessors.php");
require_once(dirname(__FILE__) . "/../frontend.php");

/*
 * Constant: APIVERSION
 * The current API version (6).
 */
define("APIVERSION", 6);

/*
 * Array: $api_compat
 * Array of API versions, this version is compatible to (including itself).
 */
$api_compat = array(3, 4, 5, 6);

$url_handlers = array(); /* master URL handler */

/*
 * Function: register_url_handler
 * Register an URL handler. See <ratatoeskr/sys/urlprocess.php> for more details.
 *
 * Parameters:
 *  $name - The name of the new URL
 *  $callback - The Function to be called (see <url_process>).
 */
function register_url_handler($name, $callback)
{
    global $url_handlers;
    $url_handlers[$name] = $callback;
}

$pluginpages_handlers = array();

$articleeditor_plugins = array();

/*
 * Class: RatatoeskrPlugin
 * An abstract class to be extended in order to write your own Plugin.
 */
abstract class RatatoeskrPlugin
{
    private $id;

    /*
     * Variables: Protected variables
     *
     * $kvstorage - The Key-Value-Storage for the Plugin.
     * $ste - Access to the global STECore object.
     * $rel_path_to_root - Relative URL to the root of the page.
     */
    protected $kvstorage;
    protected $ste;
    protected $rel_path_to_root;

    /*
     * Constructor: __construct
     * Performing some neccessary initialisation stuff.
     * If you are overwriting this function, you *really* should call parent::__construct!
     *
     * Parameters:
     *  $id - The ID of the plugin (not the name).
     */
    public function __construct($id)
    {
        global $ste, $rel_path_to_root;
        $this->id        = $id;

        $this->kvstorage        = new PluginKVStorage($id);
        $this->ste              = $ste;
        $this->rel_path_to_root = $rel_path_to_root;
    }

    /*
     * Functions: Some getters
     *
     * get_id - get the Plugin-ID
     * get_custompriv_dir - Get path to the custompriv directory of your plugin.
     * get_custompub_dir - Get path to the custompub directory of your plugin.
     * get_custompub_url - Get URL (can be accessed from the web) to the custompub directory of your plugin.
     * get_template_dir - Get path to your template directory to be used with STE.
     */
    final public function    get_id()             { return $this->id;                                                                         }
    final protected function get_custompriv_dir() { return SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/private/" . $this->id;              }
    final protected function get_custompub_dir()  { return SITE_BASE_PATH . "/ratatoeskr/plugin_extradata/public/" . $this->id;               }
    final protected function get_custompub_url()  { return $GLOBALS["rel_path_to_root"] . "/ratatoeskr/plugin_extradata/public/" . $this->id; }
    final protected function get_template_dir()   { return "/plugintemplates/" . $this->id;                                                   }

    /*
     * Function: register_url_handler
     * Register a URL handler
     *
     * Parameters:
     *  $name - Name of URL
     *  $fx   - The function.
     */
    final protected function register_url_handler($name, $fx)
    {
        register_url_handler($name, $fx);
    }

    /*
     * Function: register_ste_tag
     * Register a custom STE tag.
     *
     * Parameters:
     *  $name - Name of your new STE tag.
     *  $fx   - Function to register with this tag.
     */
    final protected function register_ste_tag($name, $fx)
    {
        $this->ste->register_tag($name, $fx);
    }

    /*
     * Function: register_textprocessor
     * Register a textprocessor.
     *
     * Parameters:
     *  $name               - The name of the textprocessor-
     *  $fx                 - Function to register (function($input), returns HTML).
     *  $visible_in_backend - Should this textprocessor be visible in the backend? Defaults to True.
     */
    final protected function register_textprocessor($name, $fx, $visible_in_backend=True)
    {
        textprocessor_register($name, $fx, $visible_in_backend);
    }

    /*
     * Function: register_comment_validator
     * Register a comment validator.
     *
     * A comment validator is a function, that checks the $_POST fields and decides whether a comment should be stored or not (throws an <CommentRejected> exception with the rejection reason as the message).
     *
     * Parameters:
     *  $fx - Validator function.
     */
    final protected function register_comment_validator($fx)
    {
        global $comment_validators;
        $comment_validators[] = $fx;
    }
    /*
     * Function: register_on_comment_store
     * Register a function that will be called, after a comment was saved.
     *
     * Parameters:
     *  $fx - Function, that accepts one parameter (a <Comment> object).
     */
    final protected function register_on_comment_store($fx)
    {
        global $on_comment_store;
        $on_comment_store[] = $fx;
    }

    /*
     * Function: register_backend_pluginpage
     * Register a backend subpage for your plugin.
     *
     * Parameters:
     *  $label - The label for the page.
     *  $fx    - A function for <url_process>.
     *
     * Your $fx should output output the result of a STE template, which should load "/systemtemplates/master.html" and overwrite the "content" section.
     *
     * If you need a URL to your pluginpage, you can use <get_backend_pluginpage_url> and the STE variable $rel_path_to_pluginpage.
     *
     * See also:
     *  <prepare_backend_pluginpage>
     */
    final protected function register_backend_pluginpage($label, $fx)
    {
        global $pluginpages_handlers;

        $this->ste->vars["pluginpages"][$this->id] = $label;
        asort($this->ste->vars["pluginpages"]);
        $pluginid = $this->id;
        $pluginpages_handlers["p{$this->id}"] = function(&$data, $url_now, &$url_next) use($pluginid, $fx)
        {
            global $ste, $rel_path_to_root;
            $ste->vars["rel_path_to_pluginpage"] = "$rel_path_to_root/backend/pluginpages/p$pluginid";
            $rv = call_user_func_array($fx, array(&$data, $url_now, &$url_next));
            unset($ste->vars["rel_path_to_pluginpage"]);
            return $rv;
        };
    }

    /*
     * Function: register_articleeditor_plugin
     * Register a plugin for the article editor in the backend.
     *
     * Parameters:
     *  $label    - The label for the plugin.
     *  $fx       - A function that will be called during the articleeditor.
     *              This function must accept these parameters:
     *              * $article       - An <Article> object or NULL, if no Article is edited right now.
     *              * $about_to_save - If True, the article is about to be saved.
     *                                 If you want to veto the saving, return the rejection reason as a string.
     *                                 If everything is okay and you need to save additional data, return a callback function that accepts the saved <Article> object (that callback should also write data back to the template, if necessary).
     *                                 If everything is okay and you do not need to save additional data, return NULL.
     *  $template - The name of the template to display in the editor, relative to your template directory. If you do not want to display anything, you can set ths to NULL.
     */
    final protected function register_articleeditor_plugin($label, $fx, $template)
    {
        global $articleeditor_plugins;

        $articleeditor_plugins[] = array(
            "label"    => $label,
            "fx"       => $fx,
            "template" => $this->get_template_dir() . "/" . $template,
            "display"  => $template != NULL
        );
    }

    /*
     * Function: get_backend_pluginpage_url
     * Get the URL to your backend plugin page.
     *
     * Returns:
     *  The URL to your backend plugin page.
     */
    final protected function get_backend_pluginpage_url()
    {
        global $rel_path_to_root;
        return "$rel_path_to_root/backend/pluginpages/p{$this->id}";
    }

    /*
     * Function: get_article_extradata
     * Get the <ArticleExtradata> object for this plugin and the given article.
     *
     * Parameters:
     *  $article - An <Article> object.
     *
     * Returns:
     *  An <ArticleExtradata> object for this plugin and the given article.
     */
    final protected function get_article_extradata($article)
    {
        return new ArticleExtradata($article->get_id(), $this->id);
    }

    /*
     * Function: prepare_backend_pluginpage
     * Automatically sets the page title and highlights the menu-entry of your backend subpage.
     */
    final protected function prepare_backend_pluginpage()
    {
        $this->ste->vars["section"]   = "plugins";
        $this->ste->vars["submenu"]   = "plugin" . $this->id;
        $this->ste->vars["pagetitle"] = $this->ste->vars["pluginpages"][$this->id];
    }

    /*
     * Functions: Functions that are called at special events
     *
     * init      - Will be called after plugin is loaded. You should register your stuff here.
     * atexit    - Will be called, when Ratatöskr will exit.
     * install   - Will be called after installation. If your plugin needs to initialize some database stuff or generate files, this is the right function.
     * uninstall - Will be called during uninstallation. If you used the install function you should undo your custom installation stuff.
     * update    - Will be called after your plugin was updated to a new version.
     */
    public function init() {}
    public function atexit() {}
    public function install() {}
    public function uninstall() {}
    public function update() {}
}