<?PHP

/**
* Base class for all plugins.
*/
abstract class Plugin {

    # ----- PUBLIC INTERFACE -------------------------------------------------

    /**
    * Set the plugin attributes.  At minimum this method MUST set $this->Name
    * and $this->Version.  This is called when the plugin is initially loaded.
    */
    abstract function Register();

    /**
    * Initialize the plugin.  This is called after all plugins have been loaded
    * but before any methods for this plugin (other than Register() or Initialize()) 
    * have been called.
    * @return NULL if initialization was successful, otherwise a string containing
    *       an error message indicating why initialization failed.
    */
    function Initialize()
    {
        return NULL;
    }

    /**
    * Hook methods to be called when specific events occur.
    * For events declared by other plugins the name string should start with
    * the plugin base (class) name followed by "::" and then the event name.
    * @return Array of method names to hook indexed by the event constants
    *       or names to hook them to.
    */
    function HookEvents()
    {
        return array();
    }

    /**
    * Declare events defined by this plugin.  This is used when a plugin defines
    * new events that it signals or responds to.  Names of these events should
    * begin with the plugin base name, followed by "_EVENT_" and the event name
    * in all caps (for example "MyPlugin_EVENT_MY_EVENT").
    * @return Array with event names for the index and event types for the values.
    */
    function DeclareEvents()
    {
        return array();
    }

    /**
    * Perform any work needed when the plugin is first installed (for example,
    * creating database tables).
    * @return NULL if installation succeeded, otherwise a string containing
    *       an error message indicating why installation failed.
    */
    function Install()
    {
        return NULL;
    }

    /**
    * Perform any work needed when the plugin is upgraded to a new version
    * (for example, adding fields to database tables).
    * @param PreviousVersion The version number of this plugin that was
    *       previously installed.
    * @return NULL if upgrade succeeded, otherwise a string containing
    *       an error message indicating why upgrade failed.
    */
    function Upgrade($PreviousVersion)
    {
        return NULL;
    }

    /**
    * Perform any work needed when the plugin is uninstalled.
    * @param RemoveData If TRUE, any data created by the plugin should
    *       be removed.
    * @return NULL if uninstall succeeded, otherwise a string containing
    *       an error message indicating why uninstall failed.
    */
    function Uninstall($RemoveData)
    {
        return NULL;
    }

    /**
    * Retrieve plugin information.
    * @return Array of attribute values indexed by attribute names. 
    */
    final function GetAttributes()
    {
        return array(
                "Name" => $this->Name,
                "Version" => $this->Version,
                "Description" => $this->Description,
                "Author" => $this->Author,
                "Url" => $this->Url,
                "Email" => $this->Email,
                "EnabledByDefault" => $this->EnabledByDefault,
                "Requires" => $this->Requires,
                "CfgSetup" => $this->CfgSetup,
                "CfgPage" => $this->CfgPage,
                "Instructions" => $this->Instructions,
                );
    }

    /**
    * Get/set plugin configuration setting.
    * @param SettingName Name of configuration value.
    * @param NewValue New setting value.
    * @return Requested value, or NULL if value was not set or there was no
    *       configuration value with the specified name.
    */
    final function ConfigSetting($SettingName, $NewValue = NULL)
    {
        if (func_num_args() > 1)
        {
            if ($NewValue === NULL)
            {
                unset($this->Cfg[$SettingName]);
            }
            else
            {
                $this->Cfg[$SettingName] = $NewValue;
            }
            if (is_callable($this->CfgSaveCallback))
            {
                call_user_func_array($this->CfgSaveCallback, 
                        array(get_class($this), $this->Cfg));
            }
        }
        return isset($this->Cfg[$SettingName]) ? $this->Cfg[$SettingName] : NULL;
    }


    # ----- PROTECTED INTERFACE ----------------------------------------------

    /** Proper (human-readable) name of plugin. */
    protected $Name = NULL;
    /** Version number of plugin in the format X.X.X (for example: 1.2.12). */
    protected $Version = NULL;
    /** Text description of the plugin. */
    protected $Description = NULL;
    /** Name of the plugin's author. */
    protected $Author = NULL;
    /** Web address for more information about the plugin. */
    protected $Url = NULL;
    /** Contact email for the plugin's author. */
    protected $Email = NULL;
    /** Instructions for configuring the plugin (displayed on the
            automatically-generated configuration page if configuration
            values are supplied). */
    protected $Instructions = NULL;
    /** Whether the plugin should be enabled by default when installed */
    protected $EnabledByDefault = FALSE;

    /**
    * Array with plugin base (class) names for the index and minimum version
    * numbers for the values.  Special indexes of "PHP" may be used to
    * specify a minimum required PHP version or "PHPX_xxx" to specify a required
    * PHP extension, where "xxx" is the extension name (e.g. "PHPX_GD").  The
    * version number value is ignored for PHP extensions.
    */
    protected $Requires = array();

    /**
    * Associative array describing the configuration values for the plugin.  
    * The first index is the name of the configuration setting, and the second
    * indicates the type of information about that setting.  For more information
    * please see <a href="implementingplugins.html">Implementing
    * CWIS Plugins</a>.
    */
    protected $CfgSetup = array();

    /**
    * Name of configuration page for plugin.
    */
    protected $CfgPage = NULL;


    # ----- PRIVATE INTERFACE ------------------------------------------------

    /** Plugin configuration values. */
    private $Cfg;
    /** Callback to invoke when configuration value changes. */
    private $CfgSaveCallback;

    /** @cond */
    /**
    * Set all configuration values (only for use by PluginManager).
    * @param NewValues Array of new configuration values.
    */
    final public function SetAllCfg($NewValues)
    {
        $this->Cfg = $NewValues;
    }
    /** @endcond */

    /** @cond */
    /**
    * Set callback to be invoked when configuration values change (only for use
    *       by PluginManager)..
    * @param Callback Callback function or method.
    */
    final public function SetCfgSaveCallback($Callback)
    {
        $this->CfgSaveCallback = $Callback;
    }
    /** @endcond */
}

?>
