/system/classes/pluggable.php
PHP | 357 lines | 218 code | 22 blank | 117 comment | 46 complexity | e9057f3d6fd2577b440a582d42333634 MD5 | raw file
Possible License(s): Apache-2.0
- <?php
- /**
- * @package Habari
- *
- */
- /**
- * Pluggable class
- * Implements methods that allow descendant classes to register functions to plugin hooks
- *
- * @version $Id$
- * @copyright 2008
- */
- abstract class Pluggable
- {
- private $_class_name = null;
- public $info;
- public $plugin_id;
- private $_new_rules = array();
- protected $_added_templates = array();
- /**
- * Pluggable constructor.
- * This function creates some internal structures that are required for plugin processing
- * Plugins should not define their own constructors, because they are instantiated
- * to extract plugin info. Instead, include a sink for a "init" hook
- * which is executed immediately after the plugin is loaded during normal execution.
- */
- public function __construct()
- {
- $this->info = $this->info();
- $this->plugin_id = $this->plugin_id();
- }
- /**
- * Gets the filename that contains this pluggable class
- * @return string The filename of the file that contains the pluggable class.
- */
- final public function get_file()
- {
- if ( empty( $this->_class_name ) ) {
- $class = new ReflectionClass( get_class( $this ) );
- $this->_class_name = $class->getFileName();
- }
- return $this->_class_name;
- }
- /**
- * Gets a database schema associated with this pluggable
- * @return string The database schema
- */
- final public function get_db_schema()
- {
- $db = DB::get_driver_name();
- $schema = dirname( $this->get_file() ) . '/schema/' . $db . '.sql';
- return file_get_contents( $schema );
- }
- /**
- * Get a fully-qualified URL directory that contains this pluggable class
- *
- * @param bool whether to include a trailing slash. Default: No
- * @return string URL
- */
- public function get_url( $trail = false )
- {
- return URL::get_from_filesystem( $this->get_file(), $trail );
- }
- /**
- * Returns a unique id for this pluggable
- * @return string A plugin id
- */
- final public function plugin_id()
- {
- static $id;
- if ( !isset( $id ) ) {
- $id = Plugins::id_from_file( str_replace( '\\', '/', $this->get_file() ) );
- }
- return $id;
- }
- /**
- * Load a translation domain/file for this pluggable
- * @return boolean true if data was successfully loaded, false otherwise
- */
- public function load_text_domain( $domain )
- {
- $base_dir = realpath( dirname( $this->get_file() ) );
- return HabariLocale::load_pluggable_domain( $domain, $base_dir );
- }
-
- /**
- * Registers all of this class' action_ and filter_ functions with the Plugins dispatcher
- * Registers xmlrpc_ functions with the Plugins dispatcher, and turns '__' into '.'
- * for the purposes of matching dotted XMLRPC requests.
- * If the class is an instance of Pluggable, registers the hooks with a plugin id also.
- * @param mixed $object The object or class name to register the hooks of
- **/
- public static function load_hooks($object)
- {
- static $registered = array();
- if(is_object($object)) {
- $hash = spl_object_hash($object);
- if(isset($registered[$hash])) {
- return;
- }
- else {
- $registered[$hash] = true;
- }
- }
- else {
- $registered[$object] = true;
- }
-
- // combine the array so we can have hooks => function
- $methods = get_class_methods( $object );
- $methods = array_combine( $methods, $methods );
- // get the specific priority values for functions, as needed
- if ( method_exists( $object, 'set_priorities' ) ) {
- $priorities = $object->set_priorities();
- }
- // get the aliases.
- if ( method_exists( $object, 'alias' ) ) {
- $methods = array_merge_recursive( $methods, $object->alias() );
- }
- // loop over all the methods in this class
- foreach ( $methods as $fn => $hooks ) {
- // loop hooks and register callback for each
- foreach ( (array) $hooks as $hook ) {
- // make sure the method name is of the form
- // action_foo or filter_foo of xmlrpc_foo or theme_foo
- if ( preg_match( '#^(action|filter|xmlrpc|theme)_#i', $hook ) ) {
- $priority = 8;
- if(isset($priorities[$hook])) {
- $priority = $priorities[$hook];
- }
- elseif(preg_match('#^(.+)_(\d+)$#', $hook, $priority_match)) {
- $hook = $priority_match[1];
- $priority = intval($priority_match[2]);
- }
- elseif(isset( $priorities[$fn])) {
- $priority = $priorities[$fn];
- }
- list( $type, $hook ) = explode( '_', $hook, 2 );
- if ( $type === 'xmlrpc' ) {
- $hook = str_replace( '__', '.', $hook );
- }
- Plugins::register( array( $object, $fn ), $type, $hook, $priority );
- if($object instanceof Pluggable) {
- Plugins::register( array( $object, $fn ), $type, $hook . ':' . $object->plugin_id(), $priority );
- }
- }
- }
- }
- }
- /**
- * Called when a pluggable is loaded to register its actions and filters.
- */
- public function load()
- {
- self::load_hooks($this);
- // look for help with this
- if ( method_exists( $this, 'help' ) ) {
- Plugins::register( array( $this, '_help_plugin_config' ), 'filter', 'plugin_config:' . $this->plugin_id(), 8 );
- Plugins::register( array( $this, '_help_plugin_ui' ), 'action', 'plugin_ui:' . $this->plugin_id(), 8 );
- }
- // look for a basic configure method
- if ( method_exists( $this, 'configure' ) ) {
- Plugins::register( array( $this, '_configure_plugin_config' ), 'filter', 'plugin_config:' . $this->plugin_id(), 8 );
- Plugins::register( array( $this, '_configure_plugin_ui' ), 'action', 'plugin_ui:' . $this->plugin_id(), 8 );
- }
- }
- /**
- * Registered to the plugin_config hook to supply help via a plugin's help() method
- *
- * @param array $actions An array of actions applicable to this plugin
- * @param string $plugin_id The plugin id to which the actions belong
- * @return array The modified array of actions
- */
- public function _help_plugin_config( $actions, $plugin_id )
- {
- if ( $plugin_id == $this->plugin_id() ) {
- $actions['_help'] = _t( '?' );
- }
- return $actions;
- }
- /**
- * Registered to the plugin_ui hook to supply help via a plugin's help() method
- *
- * @param string $plugin_id The id of the plugin whose action was triggered
- * @param string $action The action triggered
- */
- public function _help_plugin_ui( $plugin_id, $action )
- {
- if ( $plugin_id == $this->plugin_id() && $action == '_help' ) {
- $output = $this->help();
- if ( $output instanceof FormUI ) {
- $output->out();
- }
- else {
- echo "<div class=\"help\">{$output}</div>";
- }
- }
- }
- /**
- * Registered to the plugin_config hook to supply a config via a plugin's configure() method
- *
- * @param array $actions An array of actions applicable to this plugin
- * @param string $plugin_id The plugin id to which the actions belong
- * @return array The modified array of actions
- */
- public function _configure_plugin_config( $actions, $plugin_id )
- {
- if ( $plugin_id == $this->plugin_id() ) {
- $actions['_configure'] = _t( 'Configure' );
- }
- return $actions;
- }
- /**
- * Registered to the plugin_ui hook to supply a config via a plugin's configure() method
- *
- * @param string $plugin_id The id of the plugin whose action was triggered
- * @param string $action The action triggered
- */
- public function _configure_plugin_ui( $plugin_id, $action )
- {
- if ( $plugin_id == $this->plugin_id() && $action == '_configure' ) {
- $output = $this->configure();
- if ( $output instanceof FormUI ) {
- $output->out();
- }
- else {
- echo $output;
- }
- }
- }
- /**
- * Add a rewrite rule that dispatches entirely to a plugin hook
- *
- * @param mixed $rule An old-style rewrite rule string, where quoted segments are literals and unquoted segments are variable names, OR a RewriteRule object
- * @param string $hook The suffix of the hook function: action_plugin_act_{$suffix}
- */
- public function add_rule( $rule, $hook )
- {
- if ( count( $this->_new_rules ) == 0 ) {
- Plugins::register( array( $this, '_filter_rewrite_rules' ), 'filter', 'rewrite_rules', 7 );
- }
- if ( $rule instanceof RewriteRule ) {
- $this->_new_rules[] = $rule;
- }
- else {
- $this->_new_rules[] = RewriteRule::create_url_rule( $rule, 'PluginHandler', $hook );
- }
- }
- /**
- * Add the rewrite rules queued by add_rule() to the full rule set
- *
- * @param array $rules The array of current RewriteRules
- * @return array The appended array of RewriteRules
- */
- public function _filter_rewrite_rules( $rules )
- {
- $rules = array_merge( $rules, $this->_new_rules );
- return $rules;
- }
- /**
- * Adds a template to the default theme that is stored in a specified path.
- * Use this function as a shortcut to make available additional templates to a theme
- * from within the plugin directory.
- *
- * @param string $name The name of the template that will be displayed, sans extension
- * @param string $filename The full path of the template file used for the specified name
- * @param boolean $override If false, allow a template with the same name in the active theme directory to override this one.
- * If true, always override the active theme's template with this one.
- */
- protected function add_template( $name, $filename, $override = false )
- {
- if ( count( $this->_added_templates ) == 0 ) {
- Plugins::register( array( &$this, '_plugin_available_templates' ), 'filter', 'available_templates' );
- Plugins::register( array( &$this, '_plugin_include_template_file' ), 'filter', 'include_template_file' );
- }
- $this->_added_templates[$name] = array( $filename, $override );
- }
- /**
- * Add plugin templates to the list of templates that are present in the current theme
- *
- * @param array $list List of template names in the current theme
- * @return array The modified list of template names
- */
- public function _plugin_available_templates( $list )
- {
- $list = array_merge( $list, array_keys( $this->_added_templates ) );
- return $list;
- }
- /**
- * Potentially serve a different file for the requested template name
- *
- * @param string $file The filename of the template the theme will display
- * @param string $name The name of the template requested
- * @return string The potentially modified filename to use for the requested template.
- */
- public function _plugin_include_template_file( $file, $name )
- {
- if ( isset( $this->_added_templates[$name] ) ) {
- if ( $this->_added_templates[$name][1] || !file_exists( $file ) ) {
- $file = $this->_added_templates[$name][0];
- }
- }
- return $file;
- }
- /**
- * Provide a method to return the version number from a pluggable's info
- * @return string The version of the pluggable
- **/
- public abstract function get_version();
-
- /**
- * Execute the upgrade action on any pluggable that has a version number change
- * Update the version number of the pluggable in the database to what is installed
- */
- public function upgrade()
- {
- if(DB::is_connected() && @ Options::get( 'installed' )) {
- $pluggable_class = get_class($this);
- $versions = Options::get( 'pluggable_versions' );
- if(isset($versions[$pluggable_class])) {
- $old_version = $versions[$pluggable_class];
- if($old_version != $this->get_version()) {
- Plugins::act_id('upgrade', $this->plugin_id(), $old_version);
- $versions[$pluggable_class] = $this->get_version();
- Options::set( 'pluggable_versions', $versions );
- }
- }
- else {
- $versions[$pluggable_class] = $this->get_version();
- Options::set( 'pluggable_versions', $versions );
- }
- }
- }
- }
- ?>