aboutsummaryrefslogtreecommitdiff
path: root/engine/lib/plugins.php
diff options
context:
space:
mode:
Diffstat (limited to 'engine/lib/plugins.php')
-rw-r--r--engine/lib/plugins.php1405
1 files changed, 927 insertions, 478 deletions
diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php
index 0c8af5497..d5d3db466 100644
--- a/engine/lib/plugins.php
+++ b/engine/lib/plugins.php
@@ -3,290 +3,562 @@
* Elgg plugins library
* Contains functions for managing plugins
*
- * @package Elgg
- * @subpackage Core
- * @author Curverider Ltd
- * @link http://elgg.org/
+ * @package Elgg.Core
+ * @subpackage Plugins
*/
+/**
+ * Tells ElggPlugin::start() to include the start.php file.
+ */
+define('ELGG_PLUGIN_INCLUDE_START', 1);
+
+/**
+ * Tells ElggPlugin::start() to automatically register the plugin's views.
+ */
+define('ELGG_PLUGIN_REGISTER_VIEWS', 2);
-/// Cache enabled plugins per page
-$ENABLED_PLUGINS_CACHE = NULL;
+/**
+ * Tells ElggPlugin::start() to automatically register the plugin's languages.
+ */
+define('ELGG_PLUGIN_REGISTER_LANGUAGES', 4);
+
+/**
+ * Tells ElggPlugin::start() to automatically register the plugin's classes.
+ */
+define('ELGG_PLUGIN_REGISTER_CLASSES', 8);
/**
- * PluginException
+ * Prefix for plugin setting names
*
- * A plugin Exception, thrown when an Exception occurs relating to the plugin mechanism. Subclass for specific plugin Exceptions.
+ * @todo Can't namespace these because many plugins directly call
+ * private settings via $entity->$name.
+ */
+//define('ELGG_PLUGIN_SETTING_PREFIX', 'plugin:setting:');
+
+/**
+ * Prefix for plugin user setting names
+ */
+define('ELGG_PLUGIN_USER_SETTING_PREFIX', 'plugin:user_setting:');
+
+/**
+ * Internal settings prefix
*
- * @package Elgg
- * @subpackage Exceptions
+ * @todo This could be resolved by promoting ElggPlugin to a 5th type.
*/
-class PluginException extends Exception {}
+define('ELGG_PLUGIN_INTERNAL_PREFIX', 'elgg:internal:');
+
/**
- * @class ElggPlugin Object representing a plugin's settings for a given site.
- * This class is currently a stub, allowing a plugin to saving settings in an object's metadata for each site.
- * @author Curverider Ltd
+ * Returns a list of plugin IDs (dir names) from a dir.
+ *
+ * @param string $dir A dir to scan for plugins. Defaults to config's plugins_path.
+ *
+ * @return array
+ * @since 1.8.0
+ * @access private
*/
-class ElggPlugin extends ElggObject {
- protected function initialise_attributes() {
- parent::initialise_attributes();
+function elgg_get_plugin_ids_in_dir($dir = null) {
+ if (!$dir) {
+ $dir = elgg_get_plugins_path();
+ }
- $this->attributes['subtype'] = "plugin";
+ $plugin_ids = array();
+ $handle = opendir($dir);
+
+ if ($handle) {
+ while ($plugin_id = readdir($handle)) {
+ // must be directory and not begin with a .
+ if (substr($plugin_id, 0, 1) !== '.' && is_dir($dir . $plugin_id)) {
+ $plugin_ids[] = $plugin_id;
+ }
+ }
}
- public function __construct($guid = null) {
- parent::__construct($guid);
+ sort($plugin_ids);
+
+ return $plugin_ids;
+}
+
+/**
+ * Discovers plugins in the plugins_path setting and creates ElggPlugin
+ * entities for them if they don't exist. If there are plugins with entities
+ * but not actual files, will disable the ElggPlugin entities and mark as inactive.
+ * The ElggPlugin object holds config data, so don't delete.
+ *
+ * @todo Crappy name?
+ * @return bool
+ * @since 1.8.0
+ * @access private
+ */
+function elgg_generate_plugin_entities() {
+ // @todo $site unused, can remove?
+ $site = get_config('site');
+
+ $dir = elgg_get_plugins_path();
+ $db_prefix = elgg_get_config('dbprefix');
+
+ $options = array(
+ 'type' => 'object',
+ 'subtype' => 'plugin',
+ 'selects' => array('plugin_oe.*'),
+ 'joins' => array("JOIN {$db_prefix}objects_entity plugin_oe on plugin_oe.guid = e.guid"),
+ 'limit' => ELGG_ENTITIES_NO_VALUE
+ );
+
+ $old_ia = elgg_set_ignore_access(true);
+ $old_access = access_get_show_hidden_status();
+ access_show_hidden_entities(true);
+ $known_plugins = elgg_get_entities_from_relationship($options);
+ /* @var ElggPlugin[] $known_plugins */
+
+ if (!$known_plugins) {
+ $known_plugins = array();
}
- /**
- * Override entity get and sets in order to save data to private data store.
- */
- public function get($name) {
- // See if its in our base attribute
- if (isset($this->attributes[$name])) {
- return $this->attributes[$name];
+ // map paths to indexes
+ $id_map = array();
+ foreach ($known_plugins as $i => $plugin) {
+ // if the ID is wrong, delete the plugin because we can never load it.
+ $id = $plugin->getID();
+ if (!$id) {
+ $plugin->delete();
+ unset($known_plugins[$i]);
+ continue;
}
+ $id_map[$plugin->getID()] = $i;
+ }
- // No, so see if its in the private data store.
- // get_private_setting() returns false if it doesn't exist
- $meta = get_private_setting($this->guid, $name);
+ $physical_plugins = elgg_get_plugin_ids_in_dir($dir);
- if ($meta === false) {
- // Can't find it, so return null
- return NULL;
- }
-
- return $meta;
- }
-
- /**
- * Override entity get and sets in order to save data to private data store.
- */
- public function set($name, $value) {
- if (array_key_exists($name, $this->attributes)) {
- // Check that we're not trying to change the guid!
- if ((array_key_exists('guid', $this->attributes)) && ($name=='guid')) {
- return false;
+ if (!$physical_plugins) {
+ return false;
+ }
+
+ // check real plugins against known ones
+ foreach ($physical_plugins as $plugin_id) {
+ // is this already in the db?
+ if (array_key_exists($plugin_id, $id_map)) {
+ $index = $id_map[$plugin_id];
+ $plugin = $known_plugins[$index];
+ // was this plugin deleted and its entity disabled?
+ if (!$plugin->isEnabled()) {
+ $plugin->enable();
+ $plugin->deactivate();
+ $plugin->setPriority('last');
}
- $this->attributes[$name] = $value;
+ // remove from the list of plugins to disable
+ unset($known_plugins[$index]);
} else {
- return set_private_setting($this->guid, $name, $value);
+ // add new plugins
+ // priority is force to last in save() if not set.
+ $plugin = new ElggPlugin($plugin_id);
+ $plugin->save();
}
+ }
- return true;
+ // everything remaining in $known_plugins needs to be disabled
+ // because they are entities, but their dirs were removed.
+ // don't delete the entities because they hold settings.
+ foreach ($known_plugins as $plugin) {
+ if ($plugin->isActive()) {
+ $plugin->deactivate();
+ }
+ // remove the priority.
+ $name = elgg_namespace_plugin_private_setting('internal', 'priority');
+ remove_private_setting($plugin->guid, $name);
+ $plugin->disable();
}
+
+ access_show_hidden_entities($old_access);
+ elgg_set_ignore_access($old_ia);
+
+ elgg_reindex_plugin_priorities();
+
+ return true;
}
/**
- * Returns a list of plugins to load, in the order that they should be loaded.
- *
- * @return array List of plugins
+ * Cache a reference to this plugin by its ID
+ *
+ * @param ElggPlugin $plugin
+ *
+ * @access private
*/
-function get_plugin_list() {
- global $CONFIG;
+function _elgg_cache_plugin_by_id(ElggPlugin $plugin) {
+ $map = (array) elgg_get_config('plugins_by_id_map');
+ $map[$plugin->getID()] = $plugin;
+ elgg_set_config('plugins_by_id_map', $map);
+}
- if (!empty($CONFIG->pluginlistcache)) {
- return $CONFIG->pluginlistcache;
+/**
+ * Returns an ElggPlugin object with the path $path.
+ *
+ * @param string $plugin_id The id (dir name) of the plugin. NOT the guid.
+ * @return ElggPlugin|false
+ * @since 1.8.0
+ */
+function elgg_get_plugin_from_id($plugin_id) {
+ $map = (array) elgg_get_config('plugins_by_id_map');
+ if (isset($map[$plugin_id])) {
+ return $map[$plugin_id];
}
- if ($site = get_entity($CONFIG->site_guid)) {
- $pluginorder = $site->pluginorder;
- if (!empty($pluginorder)) {
- $plugins = unserialize($pluginorder);
+ $plugin_id = sanitize_string($plugin_id);
+ $db_prefix = get_config('dbprefix');
- $CONFIG->pluginlistcache = $plugins;
- return $plugins;
- } else {
- $plugins = array();
-
- if ($handle = opendir($CONFIG->pluginspath)) {
- while ($mod = readdir($handle)) {
- if (!in_array($mod,array('.','..','.svn','CVS')) && is_dir($CONFIG->pluginspath . "/" . $mod)) {
- $plugins[] = $mod;
- }
- }
- }
+ $options = array(
+ 'type' => 'object',
+ 'subtype' => 'plugin',
+ 'joins' => array("JOIN {$db_prefix}objects_entity oe on oe.guid = e.guid"),
+ 'selects' => array("oe.title", "oe.description"),
+ 'wheres' => array("oe.title = '$plugin_id'"),
+ 'limit' => 1
+ );
- sort($plugins);
+ $plugins = elgg_get_entities($options);
- $CONFIG->pluginlistcache = $plugins;
- return $plugins;
- }
+ if ($plugins) {
+ return $plugins[0];
}
return false;
}
/**
- * Regenerates the list of known plugins and saves it to the current site
+ * Returns if a plugin exists in the system.
*
- * Important: You should regenerate simplecache and the viewpath cache after executing this function
- * otherwise you may experience view display artifacts. Do this with the following code:
+ * @warning This checks only plugins that are registered in the system!
+ * If the plugin cache is outdated, be sure to regenerate it with
+ * {@link elgg_generate_plugin_objects()} first.
*
- * elgg_view_regenerate_simplecache();
- * elgg_filepath_cache_reset();
+ * @param string $id The plugin ID.
+ * @since 1.8.0
+ * @return bool
+ */
+function elgg_plugin_exists($id) {
+ $plugin = elgg_get_plugin_from_id($id);
+
+ return ($plugin) ? true : false;
+}
+
+/**
+ * Returns the highest priority of the plugins
*
- * @param array $pluginorder Optionally, a list of existing plugins and their orders
- * @return array The new list of plugins and their orders
+ * @return int
+ * @since 1.8.0
+ * @access private
*/
-function regenerate_plugin_list($pluginorder = false) {
- global $CONFIG;
+function elgg_get_max_plugin_priority() {
+ $db_prefix = get_config('dbprefix');
+ $priority = elgg_namespace_plugin_private_setting('internal', 'priority');
+ $plugin_subtype = get_subtype_id('object', 'plugin');
+
+ $q = "SELECT MAX(CAST(ps.value AS unsigned)) as max
+ FROM {$db_prefix}entities e, {$db_prefix}private_settings ps
+ WHERE ps.name = '$priority'
+ AND ps.entity_guid = e.guid
+ AND e.type = 'object' and e.subtype = $plugin_subtype";
+
+ $data = get_data($q);
+ if ($data) {
+ $max = $data[0]->max;
+ } else {
+ $max = 1;
+ }
- $CONFIG->pluginlistcache = null;
+ // can't have a priority of 0.
+ return ($max) ? $max : 1;
+}
- if ($site = get_entity($CONFIG->site_guid)) {
- if (empty($pluginorder)) {
- $pluginorder = $site->pluginorder;
- $pluginorder = unserialize($pluginorder);
- } else {
- ksort($pluginorder);
- }
+/**
+ * Returns if a plugin is active for a current site.
+ *
+ * @param string $plugin_id The plugin ID
+ * @param int $site_guid The site guid
+ * @since 1.8.0
+ * @return bool
+ */
+function elgg_is_active_plugin($plugin_id, $site_guid = null) {
+ if ($site_guid) {
+ $site = get_entity($site_guid);
+ } else {
+ $site = elgg_get_site_entity();
+ }
- if (empty($pluginorder)) {
- $pluginorder = array();
- }
+ if (!($site instanceof ElggSite)) {
+ return false;
+ }
- $max = 0;
- if (sizeof($pluginorder)) {
- foreach($pluginorder as $key => $plugin) {
- if (is_dir($CONFIG->pluginspath . "/" . $plugin)) {
- if ($key > $max)
- $max = $key;
- } else {
- unset($pluginorder[$key]);
- }
- }
- }
- // Add new plugins to the end
- if ($handle = opendir($CONFIG->pluginspath)) {
- while ($mod = readdir($handle)) {
- if (!in_array($mod,array('.','..','.svn','CVS')) && is_dir($CONFIG->pluginspath . "/" . $mod)) {
- if (!in_array($mod, $pluginorder)) {
- $max = $max + 10;
- $pluginorder[$max] = $mod;
- }
- }
- }
+ $plugin = elgg_get_plugin_from_id($plugin_id);
+
+ if (!$plugin) {
+ return false;
+ }
+
+ return $plugin->isActive($site->guid);
+}
+
+/**
+ * Loads all active plugins in the order specified in the tool admin panel.
+ *
+ * @note This is called on every page load. If a plugin is active and problematic, it
+ * will be disabled and a visible error emitted. This does not check the deps system because
+ * that was too slow.
+ *
+ * @return bool
+ * @since 1.8.0
+ * @access private
+ */
+function elgg_load_plugins() {
+ $plugins_path = elgg_get_plugins_path();
+ $start_flags = ELGG_PLUGIN_INCLUDE_START |
+ ELGG_PLUGIN_REGISTER_VIEWS |
+ ELGG_PLUGIN_REGISTER_LANGUAGES |
+ ELGG_PLUGIN_REGISTER_CLASSES;
+
+ if (!$plugins_path) {
+ return false;
+ }
+
+ // temporary disable all plugins if there is a file called 'disabled' in the plugin dir
+ if (file_exists("$plugins_path/disabled")) {
+ if (elgg_is_admin_logged_in() && elgg_in_context('admin')) {
+ system_message(elgg_echo('plugins:disabled'));
}
+ return false;
+ }
- ksort($pluginorder);
+ if (elgg_get_config('system_cache_loaded')) {
+ $start_flags = $start_flags & ~ELGG_PLUGIN_REGISTER_VIEWS;
+ }
+
+ if (elgg_get_config('i18n_loaded_from_cache')) {
+ $start_flags = $start_flags & ~ELGG_PLUGIN_REGISTER_LANGUAGES;
+ }
- // Now reorder the keys ..
- $key = 10;
- $plugins = array();
- if (sizeof($pluginorder)) {
- foreach($pluginorder as $plugin) {
- $plugins[$key] = $plugin;
- $key = $key + 10;
+ $return = true;
+ $plugins = elgg_get_plugins('active');
+ if ($plugins) {
+ foreach ($plugins as $plugin) {
+ try {
+ $plugin->start($start_flags);
+ } catch (Exception $e) {
+ $plugin->deactivate();
+ $msg = elgg_echo('PluginException:CannotStart',
+ array($plugin->getID(), $plugin->guid, $e->getMessage()));
+ elgg_add_admin_notice('cannot_start' . $plugin->getID(), $msg);
+ $return = false;
+
+ continue;
}
}
+ }
- $plugins = serialize($plugins);
-
- $site->pluginorder = $plugins;
+ return $return;
+}
- // Regenerate caches
- elgg_view_regenerate_simplecache();
- elgg_filepath_cache_reset();
+/**
+ * Returns an ordered list of plugins
+ *
+ * @param string $status The status of the plugins. active, inactive, or all.
+ * @param mixed $site_guid Optional site guid
+ * @return ElggPlugin[]
+ * @since 1.8.0
+ * @access private
+ */
+function elgg_get_plugins($status = 'active', $site_guid = null) {
+ $db_prefix = get_config('dbprefix');
+ $priority = elgg_namespace_plugin_private_setting('internal', 'priority');
- return $plugins;
+ if (!$site_guid) {
+ $site = get_config('site');
+ $site_guid = $site->guid;
+ }
+ // grab plugins
+ $options = array(
+ 'type' => 'object',
+ 'subtype' => 'plugin',
+ 'limit' => ELGG_ENTITIES_NO_VALUE,
+ 'selects' => array('plugin_oe.*'),
+ 'joins' => array(
+ "JOIN {$db_prefix}private_settings ps on ps.entity_guid = e.guid",
+ "JOIN {$db_prefix}objects_entity plugin_oe on plugin_oe.guid = e.guid"
+ ),
+ 'wheres' => array("ps.name = '$priority'"),
+ 'order_by' => "CAST(ps.value as unsigned), e.guid"
+ );
+
+ switch ($status) {
+ case 'active':
+ $options['relationship'] = 'active_plugin';
+ $options['relationship_guid'] = $site_guid;
+ $options['inverse_relationship'] = true;
+ break;
+
+ case 'inactive':
+ $options['wheres'][] = "NOT EXISTS (
+ SELECT 1 FROM {$db_prefix}entity_relationships active_er
+ WHERE active_er.guid_one = e.guid
+ AND active_er.relationship = 'active_plugin'
+ AND active_er.guid_two = $site_guid)";
+ break;
+
+ case 'all':
+ default:
+ break;
}
- return false;
-}
+ $old_ia = elgg_set_ignore_access(true);
+ $plugins = elgg_get_entities_from_relationship($options);
+ elgg_set_ignore_access($old_ia);
+ return $plugins;
+}
/**
- * For now, loads plugins directly
+ * Reorder plugins to an order specified by the array.
+ * Plugins not included in this array will be appended to the end.
+ *
+ * @note This doesn't use the ElggPlugin->setPriority() method because
+ * all plugins are being changed and we don't want it to automatically
+ * reorder plugins.
*
- * @todo Add proper plugin handler that launches plugins in an admin-defined order and activates them on admin request
- * @package Elgg
- * @subpackage Core
+ * @param array $order An array of plugin ids in the order to set them
+ * @return bool
+ * @since 1.8.0
+ * @access private
*/
-function load_plugins() {
- global $CONFIG;
+function elgg_set_plugin_priorities(array $order) {
+ $name = elgg_namespace_plugin_private_setting('internal', 'priority');
- if (!empty($CONFIG->pluginspath)) {
- // See if we have cached values for things
- $cached_view_paths = elgg_filepath_cache_load();
- if ($cached_view_paths) {
- $CONFIG->views = unserialize($cached_view_paths);
+ $plugins = elgg_get_plugins('any');
+ if (!$plugins) {
+ return false;
+ }
+
+ $return = true;
+
+ // reindex to get standard counting. no need to increment by 10.
+ // though we do start with 1
+ $order = array_values($order);
+
+ $missing_plugins = array();
+ foreach ($plugins as $plugin) {
+ $plugin_id = $plugin->getID();
+
+ if (!in_array($plugin_id, $order)) {
+ $missing_plugins[] = $plugin;
+ continue;
}
- // temporary disable all plugins if there is a file called 'disabled' in the plugin dir
- if (file_exists($CONFIG->pluginspath . "disabled")) {
- return;
+ $priority = array_search($plugin_id, $order) + 1;
+
+ if (!$plugin->set($name, $priority)) {
+ $return = false;
+ break;
}
+ }
- $plugins = get_plugin_list();
-
- if (sizeof($plugins)) {
- foreach($plugins as $mod) {
- if (is_plugin_enabled($mod)) {
- if (file_exists($CONFIG->pluginspath . $mod)) {
- if (!include($CONFIG->pluginspath . $mod . "/start.php")) {
- throw new PluginException(sprintf(elgg_echo('PluginException:MisconfiguredPlugin'), $mod));
- }
-
- if (!$cached_view_paths) {
- if (is_dir($CONFIG->pluginspath . $mod . "/views")) {
- if ($handle = opendir($CONFIG->pluginspath . $mod . "/views")) {
- while ($viewtype = readdir($handle)) {
- if (!in_array($viewtype,array('.','..','.svn','CVS')) && is_dir($CONFIG->pluginspath . $mod . "/views/" . $viewtype)) {
- autoregister_views("",$CONFIG->pluginspath . $mod . "/views/" . $viewtype,$CONFIG->pluginspath . $mod . "/views/", $viewtype);
- }
- }
- }
- }
- }
-
- if (is_dir($CONFIG->pluginspath . $mod . "/languages")) {
- register_translations($CONFIG->pluginspath . $mod . "/languages/");
- }
- }
- }
+ // set the missing plugins' priorities
+ if ($return && $missing_plugins) {
+ if (!isset($priority)) {
+ $priority = 0;
+ }
+ foreach ($missing_plugins as $plugin) {
+ $priority++;
+ if (!$plugin->set($name, $priority)) {
+ $return = false;
+ break;
}
}
+ }
- // Cache results
- if (!$cached_view_paths) {
- elgg_filepath_cache_save(serialize($CONFIG->views));
- }
+ return $return;
+}
+
+/**
+ * Reindexes all plugin priorities starting at 1.
+ *
+ * @todo Can this be done in a single sql command?
+ * @return bool
+ * @since 1.8.0
+ * @access private
+ */
+function elgg_reindex_plugin_priorities() {
+ return elgg_set_plugin_priorities(array());
+}
+
+/**
+ * Namespaces a string to be used as a private setting for a plugin.
+ *
+ * @param string $type The type of value: user_setting or internal.
+ * @param string $name The name to namespace.
+ * @param string $id The plugin's ID to namespace with. Required for user_setting.
+ * @return string
+ * @since 1.8.0
+ * @access private
+ */
+function elgg_namespace_plugin_private_setting($type, $name, $id = null) {
+ switch ($type) {
+ // commented out because it breaks $plugin->$name access to variables
+ //case 'setting':
+ // $name = ELGG_PLUGIN_SETTING_PREFIX . $name;
+ // break;
+
+ case 'user_setting':
+ if (!$id) {
+ $id = elgg_get_calling_plugin_id();
+ }
+ $name = ELGG_PLUGIN_USER_SETTING_PREFIX . "$id:$name";
+ break;
+
+ case 'internal':
+ $name = ELGG_PLUGIN_INTERNAL_PREFIX . $name;
+ break;
}
+
+ return $name;
}
/**
- * Get the name of the most recent plugin to be called in the call stack (or the plugin that owns the current page, if any).
+ * Get the name of the most recent plugin to be called in the
+ * call stack (or the plugin that owns the current page, if any).
*
- * i.e., if the last plugin was in /mod/foobar/, get_plugin_name would return foo_bar.
+ * i.e., if the last plugin was in /mod/foobar/, this would return foo_bar.
+ *
+ * @param boolean $mainfilename If set to true, this will instead determine the
+ * context from the main script filename called by
+ * the browser. Default = false.
*
- * @param boolean $mainfilename If set to true, this will instead determine the context from the main script filename called by the browser. Default = false.
* @return string|false Plugin name, or false if no plugin name was called
+ * @since 1.8.0
+ * @access private
+ *
+ * @todo get rid of this
*/
-function get_plugin_name($mainfilename = false) {
+function elgg_get_calling_plugin_id($mainfilename = false) {
if (!$mainfilename) {
if ($backtrace = debug_backtrace()) {
- foreach($backtrace as $step) {
+ foreach ($backtrace as $step) {
$file = $step['file'];
- $file = str_replace("\\","/",$file);
- $file = str_replace("//","/",$file);
- if (preg_match("/mod\/([a-zA-Z0-9\-\_]*)\/start\.php$/",$file,$matches)) {
+ $file = str_replace("\\", "/", $file);
+ $file = str_replace("//", "/", $file);
+ if (preg_match("/mod\/([a-zA-Z0-9\-\_]*)\/start\.php$/", $file, $matches)) {
return $matches[1];
}
}
}
} else {
- //if (substr_count($file,'handlers/pagehandler')) {
- if (preg_match("/pg\/([a-zA-Z0-9\-\_]*)\//",$_SERVER['REQUEST_URI'],$matches)) {
- return $matches[1];
+ //@todo this is a hack -- plugins do not have to match their page handler names!
+ if ($handler = get_input('handler', FALSE)) {
+ return $handler;
} else {
$file = $_SERVER["SCRIPT_NAME"];
- $file = str_replace("\\","/",$file);
- $file = str_replace("//","/",$file);
- if (preg_match("/mod\/([a-zA-Z0-9\-\_]*)\//",$file,$matches)) {
+ $file = str_replace("\\", "/", $file);
+ $file = str_replace("//", "/", $file);
+ if (preg_match("/mod\/([a-zA-Z0-9\-\_]*)\//", $file, $matches)) {
return $matches[1];
}
}
@@ -295,436 +567,613 @@ function get_plugin_name($mainfilename = false) {
}
/**
- * Load and parse a plugin manifest from a plugin XML file.
+ * Returns an array of all provides from all active plugins.
*
- * Example file:
+ * Array in the form array(
+ * 'provide_type' => array(
+ * 'provided_name' => array(
+ * 'version' => '1.8',
+ * 'provided_by' => 'provider_plugin_id'
+ * )
+ * )
+ * )
*
- * <plugin_manifest>
- * <field key="author" value="Curverider Ltd" />
- * <field key="version" value="1.0" />
- * <field key="description" value="My plugin description, keep it short" />
- * <field key="website" value="http://www.elgg.org/" />
- * <field key="copyright" value="(C) Curverider 2008-2009" />
- * <field key="licence" value="GNU Public License version 2" />
- * </plugin_manifest>
+ * @param string $type The type of provides to return
+ * @param string $name A specific provided name to return. Requires $provide_type.
*
- * @param string $plugin Plugin name.
- * @return array of values
+ * @return array
+ * @since 1.8.0
+ * @access private
*/
-function load_plugin_manifest($plugin) {
- global $CONFIG;
-
- $xml = xml_to_object(file_get_contents($CONFIG->pluginspath . $plugin. "/manifest.xml"));
-
- if ($xml) {
- $elements = array();
-
- foreach ($xml->children as $element) {
- $key = $element->attributes['key'];
- $value = $element->attributes['value'];
-
- $elements[$key] = $value;
+function elgg_get_plugins_provides($type = null, $name = null) {
+ static $provides = null;
+ $active_plugins = elgg_get_plugins('active');
+
+ if (!isset($provides)) {
+ $provides = array();
+
+ foreach ($active_plugins as $plugin) {
+ $plugin_provides = array();
+ $manifest = $plugin->getManifest();
+ if ($manifest instanceof ElggPluginManifest) {
+ $plugin_provides = $plugin->getManifest()->getProvides();
+ }
+ if ($plugin_provides) {
+ foreach ($plugin_provides as $provided) {
+ $provides[$provided['type']][$provided['name']] = array(
+ 'version' => $provided['version'],
+ 'provided_by' => $plugin->getID()
+ );
+ }
+ }
}
+ }
- return $elements;
+ if ($type && $name) {
+ if (isset($provides[$type][$name])) {
+ return $provides[$type][$name];
+ } else {
+ return false;
+ }
+ } elseif ($type) {
+ if (isset($provides[$type])) {
+ return $provides[$type];
+ } else {
+ return false;
+ }
}
- return false;
+ return $provides;
}
/**
- * This function checks a plugin manifest 'elgg_version' value against the current install
- * returning TRUE if the elgg_version is <= the current install's version.
- * @param $manifest_elgg_version_string The build version (eg 2009010201).
- * @return bool
+ * Checks if a plugin is currently providing $type and $name, and optionally
+ * checking a version.
+ *
+ * @param string $type The type of the provide
+ * @param string $name The name of the provide
+ * @param string $version A version to check against
+ * @param string $comparison The comparison operator to use in version_compare()
+ *
+ * @return array An array in the form array(
+ * 'status' => bool Does the provide exist?,
+ * 'value' => string The version provided
+ * )
+ * @since 1.8.0
+ * @access private
*/
-function check_plugin_compatibility($manifest_elgg_version_string) {
- $version = get_version();
-
- if (strpos($manifest_elgg_version_string, '.') === false) {
- // Using version
- $req_version = (int)$manifest_elgg_version_string;
+function elgg_check_plugins_provides($type, $name, $version = null, $comparison = 'ge') {
+ $provided = elgg_get_plugins_provides($type, $name);
+ if (!$provided) {
+ return array(
+ 'status' => false,
+ 'version' => ''
+ );
+ }
- return ($version >= $req_version);
+ if ($version) {
+ $status = version_compare($provided['version'], $version, $comparison);
+ } else {
+ $status = true;
}
- return false;
+ return array(
+ 'status' => $status,
+ 'value' => $provided['version']
+ );
}
/**
- * Shorthand function for finding the plugin settings.
+ * Returns an array of parsed strings for a dependency in the
+ * format: array(
+ * 'type' => requires, conflicts, or provides.
+ * 'name' => The name of the requirement / conflict
+ * 'value' => A string representing the expected value: <1, >=3, !=enabled
+ * 'local_value' => The current value, ("Not installed")
+ * 'comment' => Free form text to help resovle the problem ("Enable / Search for plugin <link>")
+ * )
*
- * @param string $plugin_name Optional plugin name, if not specified then it is detected from where you
- * are calling from.
+ * @param array $dep An ElggPluginPackage dependency array
+ * @return array
+ * @since 1.8.0
+ * @access private
*/
-function find_plugin_settings($plugin_name = "") {
- $options = array('type' => 'object', 'subtype' => 'plugin', 'limit' => 9999);
- $plugins = elgg_get_entities($options);
- $plugin_name = sanitise_string($plugin_name);
- if (!$plugin_name) {
- $plugin_name = get_plugin_name();
+function elgg_get_plugin_dependency_strings($dep) {
+ $dep_system = elgg_extract('type', $dep);
+ $info = elgg_extract('dep', $dep);
+ $type = elgg_extract('type', $info);
+
+ if (!$dep_system || !$info || !$type) {
+ return false;
}
- if ($plugins) {
- foreach ($plugins as $plugin) {
- if (strcmp($plugin->title, $plugin_name)==0) {
- return $plugin;
+ // rewrite some of these to be more readable
+ switch($info['comparison']) {
+ case 'lt':
+ $comparison = '<';
+ break;
+ case 'gt':
+ $comparison = '>';
+ break;
+ case 'ge':
+ $comparison = '>=';
+ break;
+ case 'le':
+ $comparison = '<=';
+ break;
+ default;
+ $comparison = $info['comparison'];
+ break;
+ }
+
+ /*
+ 'requires' 'plugin oauth_lib' <1.3 1.3 'downgrade'
+ 'requires' 'php setting bob' >3 3 'change it'
+ 'conflicts' 'php setting' >3 4 'change it'
+ 'conflicted''plugin profile' any 1.8 'disable profile'
+ 'provides' 'plugin oauth_lib' 1.3 -- --
+ 'priority' 'before blog' -- after 'move it'
+ */
+ $strings = array();
+ $strings['type'] = elgg_echo('ElggPlugin:Dependencies:' . ucwords($dep_system));
+
+ switch ($type) {
+ case 'elgg_version':
+ case 'elgg_release':
+ // 'Elgg Version'
+ $strings['name'] = elgg_echo('ElggPlugin:Dependencies:Elgg');
+ $strings['expected_value'] = "$comparison {$info['version']}";
+ $strings['local_value'] = $dep['value'];
+ $strings['comment'] = '';
+ break;
+
+ case 'php_extension':
+ // PHP Extension %s [version]
+ $strings['name'] = elgg_echo('ElggPlugin:Dependencies:PhpExtension', array($info['name']));
+ if ($info['version']) {
+ $strings['expected_value'] = "$comparison {$info['version']}";
+ $strings['local_value'] = $dep['value'];
+ } else {
+ $strings['expected_value'] = '';
+ $strings['local_value'] = '';
}
+ $strings['comment'] = '';
+ break;
+
+ case 'php_ini':
+ $strings['name'] = elgg_echo('ElggPlugin:Dependencies:PhpIni', array($info['name']));
+ $strings['expected_value'] = "$comparison {$info['value']}";
+ $strings['local_value'] = $dep['value'];
+ $strings['comment'] = '';
+ break;
+
+ case 'plugin':
+ $strings['name'] = elgg_echo('ElggPlugin:Dependencies:Plugin', array($info['name']));
+ $expected = $info['version'] ? "$comparison {$info['version']}" : elgg_echo('any');
+ $strings['expected_value'] = $expected;
+ $strings['local_value'] = $dep['value'] ? $dep['value'] : '--';
+ $strings['comment'] = '';
+ break;
+
+ case 'priority':
+ $expected_priority = ucwords($info['priority']);
+ $real_priority = ucwords($dep['value']);
+ $strings['name'] = elgg_echo('ElggPlugin:Dependencies:Priority');
+ $strings['expected_value'] = elgg_echo("ElggPlugin:Dependencies:Priority:$expected_priority", array($info['plugin']));
+ $strings['local_value'] = elgg_echo("ElggPlugin:Dependencies:Priority:$real_priority", array($info['plugin']));
+ $strings['comment'] = '';
+ break;
+ }
+
+ if ($dep['type'] == 'suggests') {
+ if ($dep['status']) {
+ $strings['comment'] = elgg_echo('ok');
+ } else {
+ $strings['comment'] = elgg_echo('ElggPlugin:Dependencies:Suggests:Unsatisfied');
+ }
+ } else {
+ if ($dep['status']) {
+ $strings['comment'] = elgg_echo('ok');
+ } else {
+ $strings['comment'] = elgg_echo('error');
}
}
- return false;
+ return $strings;
}
/**
- * Find the plugin settings for a user.
+ * Returns the ElggPlugin entity of the last plugin called.
*
- * @param string $plugin_name Plugin name.
- * @param int $user_guid The guid who's settings to retrieve.
- * @return array of settings in an associative array minus prefix.
+ * @return mixed ElggPlugin or false
+ * @since 1.8.0
+ * @access private
*/
-function find_plugin_usersettings($plugin_name = "", $user_guid = 0) {
- $plugin_name = sanitise_string($plugin_name);
- $user_guid = (int)$user_guid;
+function elgg_get_calling_plugin_entity() {
+ $plugin_id = elgg_get_calling_plugin_id();
- if (!$plugin_name) {
- $plugin_name = get_plugin_name();
+ if ($plugin_id) {
+ return elgg_get_plugin_from_id($plugin_id);
}
- if ($user_guid == 0) {
- $user_guid = get_loggedin_userid();
+ return false;
+}
+
+/**
+ * Returns an array of all plugin settings for a user.
+ *
+ * @param mixed $user_guid The user GUID or null for the currently logged in user.
+ * @param string $plugin_id The plugin ID
+ * @param bool $return_obj Return settings as an object? This can be used to in reusable
+ * views where the settings are passed as $vars['entity'].
+ * @return array
+ * @since 1.8.0
+ */
+function elgg_get_all_plugin_user_settings($user_guid = null, $plugin_id = null, $return_obj = false) {
+ if ($plugin_id) {
+ $plugin = elgg_get_plugin_from_id($plugin_id);
+ } else {
+ $plugin = elgg_get_calling_plugin_entity();
}
- // Get metadata for user
- $all_metadata = get_all_private_settings($user_guid); //get_metadata_for_entity($user_guid);
- if ($all_metadata) {
- $prefix = "plugin:settings:$plugin_name:";
- $return = new stdClass;
+ if (!$plugin instanceof ElggPlugin) {
+ return false;
+ }
- foreach ($all_metadata as $key => $meta) {
- $name = substr($key, strlen($prefix));
- $value = $meta;
+ $settings = $plugin->getAllUserSettings($user_guid);
- if (strpos($key, $prefix) === 0) {
- $return->$name = $value;
- }
+ if ($settings && $return_obj) {
+ $return = new stdClass;
+
+ foreach ($settings as $k => $v) {
+ $return->$k = $v;
}
return $return;
+ } else {
+ return $settings;
}
-
- return false;
}
/**
* Set a user specific setting for a plugin.
*
- * @param string $name The name - note, can't be "title".
- * @param mixed $value The value.
- * @param int $user_guid Optional user.
- * @param string $plugin_name Optional plugin name, if not specified then it is detected from where you are calling from.
+ * @param string $name The name - note, can't be "title".
+ * @param mixed $value The value.
+ * @param int $user_guid Optional user.
+ * @param string $plugin_id Optional plugin name, if not specified then it
+ * is detected from where you are calling from.
+ *
+ * @return bool
+ * @since 1.8.0
*/
-function set_plugin_usersetting($name, $value, $user_guid = 0, $plugin_name = "") {
- $plugin_name = sanitise_string($plugin_name);
- $user_guid = (int)$user_guid;
- $name = sanitise_string($name);
-
- if (!$plugin_name) {
- $plugin_name = get_plugin_name();
+function elgg_set_plugin_user_setting($name, $value, $user_guid = null, $plugin_id = null) {
+ if ($plugin_id) {
+ $plugin = elgg_get_plugin_from_id($plugin_id);
+ } else {
+ $plugin = elgg_get_calling_plugin_entity();
}
- $user = get_entity($user_guid);
- if (!$user) {
- $user = get_loggedin_user();
+ if (!$plugin) {
+ return false;
}
- if (($user) && ($user instanceof ElggUser)) {
- $prefix = "plugin:settings:$plugin_name:$name";
- //$user->$prefix = $value;
- //$user->save();
+ return $plugin->setUserSetting($name, $value, $user_guid);
+}
- // Hook to validate setting
- $value = trigger_plugin_hook('plugin:usersetting', 'user', array(
- 'user' => $user,
- 'plugin' => $plugin_name,
- 'name' => $name,
- 'value' => $value
- ), $value);
+/**
+ * Unsets a user-specific plugin setting
+ *
+ * @param string $name Name of the setting
+ * @param int $user_guid Defaults to logged in user
+ * @param string $plugin_id Defaults to contextual plugin name
+ *
+ * @return bool
+ * @since 1.8.0
+ */
+function elgg_unset_plugin_user_setting($name, $user_guid = null, $plugin_id = null) {
+ if ($plugin_id) {
+ $plugin = elgg_get_plugin_from_id($plugin_id);
+ } else {
+ $plugin = elgg_get_calling_plugin_entity();
+ }
- return set_private_setting($user->guid, $prefix, $value);
+ if (!$plugin) {
+ return false;
}
- return false;
+ return $plugin->unsetUserSetting($name, $user_guid);
}
/**
* Get a user specific setting for a plugin.
*
- * @param string $name The name.
- * @param string $plugin_name Optional plugin name, if not specified then it is detected from where you are calling from.
+ * @param string $name The name of the setting.
+ * @param int $user_guid Guid of owning user
+ * @param string $plugin_id Optional plugin name, if not specified
+ * it is detected from where you are calling.
+ *
+ * @return mixed
+ * @since 1.8.0
*/
-function get_plugin_usersetting($name, $user_guid = 0, $plugin_name = "") {
- $plugin_name = sanitise_string($plugin_name);
- $user_guid = (int)$user_guid;
- $name = sanitise_string($name);
-
- if (!$plugin_name) {
- $plugin_name = get_plugin_name();
- }
-
- $user = get_entity($user_guid);
- if (!$user) {
- $user = get_loggedin_user();
+function elgg_get_plugin_user_setting($name, $user_guid = null, $plugin_id = null) {
+ if ($plugin_id) {
+ $plugin = elgg_get_plugin_from_id($plugin_id);
+ } else {
+ $plugin = elgg_get_calling_plugin_entity();
}
- if (($user) && ($user instanceof ElggUser)) {
- $prefix = "plugin:settings:$plugin_name:$name";
- return get_private_setting($user->guid, $prefix); //$user->$prefix;
+ if (!$plugin) {
+ return false;
}
- return false;
+ return $plugin->getUserSetting($name, $user_guid);
}
/**
* Set a setting for a plugin.
*
- * @param string $name The name - note, can't be "title".
- * @param mixed $value The value.
- * @param string $plugin_name Optional plugin name, if not specified then it is detected from where you are calling from.
+ * @param string $name The name of the setting - note, can't be "title".
+ * @param mixed $value The value.
+ * @param string $plugin_id Optional plugin name, if not specified
+ * then it is detected from where you are calling from.
+ *
+ * @return bool
+ * @since 1.8.0
*/
-function set_plugin_setting($name, $value, $plugin_name = "") {
- if (!$plugin_name) {
- $plugin_name = get_plugin_name();
+function elgg_set_plugin_setting($name, $value, $plugin_id = null) {
+ if ($plugin_id) {
+ $plugin = elgg_get_plugin_from_id($plugin_id);
+ } else {
+ $plugin = elgg_get_calling_plugin_entity();
}
- $plugin = find_plugin_settings($plugin_name);
if (!$plugin) {
- $plugin = new ElggPlugin();
- }
-
- if ($name!='title') {
- // Hook to validate setting
- $value = trigger_plugin_hook('plugin:setting', 'plugin', array(
- 'plugin' => $plugin_name,
- 'name' => $name,
- 'value' => $value
- ), $value);
-
- $plugin->title = $plugin_name;
- $plugin->access_id = ACCESS_PUBLIC;
- $plugin->save();
- $plugin->$name = $value;
-
- return $plugin->getGUID();
+ return false;
}
- return false;
+ return $plugin->setSetting($name, $value);
}
/**
* Get setting for a plugin.
*
- * @param string $name The name.
- * @param string $plugin_name Optional plugin name, if not specified then it is detected from where you are calling from.
+ * @param string $name The name of the setting.
+ * @param string $plugin_id Optional plugin name, if not specified
+ * then it is detected from where you are calling from.
+ *
+ * @return mixed
+ * @since 1.8.0
+ * @todo make $plugin_id required in future version
*/
-function get_plugin_setting($name, $plugin_name = "") {
- $plugin = find_plugin_settings($plugin_name);
+function elgg_get_plugin_setting($name, $plugin_id = null) {
+ if ($plugin_id) {
+ $plugin = elgg_get_plugin_from_id($plugin_id);
+ } else {
+ $plugin = elgg_get_calling_plugin_entity();
+ }
- if ($plugin) {
- return $plugin->$name;
+ if (!$plugin) {
+ return false;
}
- return false;
+ return $plugin->getSetting($name);
}
/**
- * Clear a plugin setting.
+ * Unsets a plugin setting.
+ *
+ * @param string $name The name of the setting.
+ * @param string $plugin_id Optional plugin name, if not specified
+ * then it is detected from where you are calling from.
*
- * @param string $name The name.
- * @param string $plugin_name Optional plugin name, if not specified then it is detected from where you are calling from.
+ * @return bool
+ * @since 1.8.0
*/
-function clear_plugin_setting($name, $plugin_name = "") {
- $plugin = find_plugin_settings($plugin_name);
+function elgg_unset_plugin_setting($name, $plugin_id = null) {
+ if ($plugin_id) {
+ $plugin = elgg_get_plugin_from_id($plugin_id);
+ } else {
+ $plugin = elgg_get_calling_plugin_entity();
+ }
- if ($plugin) {
- //$plugin->clearMetaData($name);
- return remove_all_private_settings($plugin->guid);
+ if (!$plugin) {
+ return false;
}
- return false;
+ return $plugin->unsetSetting($name);
}
/**
- * Return an array of installed plugins.
+ * Unsets all plugin settings for a plugin.
+ *
+ * @param string $plugin_id Optional plugin name, if not specified
+ * then it is detected from where you are calling from.
+ *
+ * @return bool
+ * @since 1.8.0
*/
-function get_installed_plugins() {
- global $CONFIG;
-
- $installed_plugins = array();
-
- if (!empty($CONFIG->pluginspath)) {
- $plugins = get_plugin_list();
+function elgg_unset_all_plugin_settings($plugin_id = null) {
+ if ($plugin_id) {
+ $plugin = elgg_get_plugin_from_id($plugin_id);
+ } else {
+ $plugin = elgg_get_calling_plugin_entity();
+ }
- foreach($plugins as $mod) {
- $installed_plugins[$mod] = array();
- $installed_plugins[$mod]['active'] = is_plugin_enabled($mod);
- $installed_plugins[$mod]['manifest'] = load_plugin_manifest($mod);
- }
+ if (!$plugin) {
+ return false;
}
- return $installed_plugins;
+ return $plugin->unsetAllSettings();
}
/**
- * Enable a plugin for a site (default current site)
+ * Returns entities based upon plugin settings.
+ * Takes all the options for {@see elgg_get_entities_from_private_settings()}
+ * in addition to the ones below.
+ *
+ * @param array $options Array in the format:
+ *
+ * plugin_id => NULL|STR The plugin id. Defaults to calling plugin
+ *
+ * plugin_user_setting_names => NULL|ARR private setting names
*
- * Important: You should regenerate simplecache and the viewpath cache after executing this function
- * otherwise you may experience view display artifacts. Do this with the following code:
+ * plugin_user_setting_values => NULL|ARR metadata values
*
- * elgg_view_regenerate_simplecache();
- * elgg_filepath_cache_reset();
+ * plugin_user_setting_name_value_pairs => NULL|ARR (
+ * name => 'name',
+ * value => 'value',
+ * 'operand' => '=',
+ * )
+ * Currently if multiple values are sent via
+ * an array (value => array('value1', 'value2')
+ * the pair's operand will be forced to "IN".
*
- * @param string $plugin The plugin name.
- * @param int $site_guid The site id, if not specified then this is detected.
+ * plugin_user_setting_name_value_pairs_operator => NULL|STR The operator to use for combining
+ * (name = value) OPERATOR (name = value); default AND
+ *
+ * @return mixed int If count, int. If not count, array. false on errors.
*/
-function enable_plugin($plugin, $site_guid = 0) {
- global $CONFIG, $ENABLED_PLUGINS_CACHE;
-
- $plugin = sanitise_string($plugin);
- $site_guid = (int) $site_guid;
- if ($site_guid == 0) {
- $site_guid = $CONFIG->site_guid;
+function elgg_get_entities_from_plugin_user_settings(array $options = array()) {
+ // if they're passing it don't bother
+ if (!isset($options['plugin_id'])) {
+ $options['plugin_id'] = elgg_get_calling_plugin_id();
}
- $site = get_entity($site_guid);
- if (!($site instanceof ElggSite)) {
- throw new InvalidClassException(sprintf(elgg_echo('InvalidClassException:NotValidElggStar'), $site_guid, "ElggSite"));
- }
+ $singulars = array('plugin_user_setting_name', 'plugin_user_setting_value',
+ 'plugin_user_setting_name_value_pair');
+
+ $options = elgg_normalise_plural_options_array($options, $singulars);
- $enabled = $site->getMetaData('enabled_plugins');
- $new_enabled = array();
- if ($enabled) {
- if (!is_array($enabled)) {
- $new_enabled[] = $enabled;
+ // rewrite plugin_user_setting_name_* to the right PS ones.
+ $map = array(
+ 'plugin_user_setting_names' => 'private_setting_names',
+ 'plugin_user_setting_values' => 'private_setting_values',
+ 'plugin_user_setting_name_value_pairs' => 'private_setting_name_value_pairs',
+ 'plugin_user_setting_name_value_pairs_operator' => 'private_setting_name_value_pairs_operator'
+ );
+
+ foreach ($map as $plugin => $private) {
+ if (!isset($options[$plugin])) {
+ continue;
+ }
+
+ if (isset($options[$private])) {
+ if (!is_array($options[$private])) {
+ $options[$private] = array($options[$private]);
+ }
+
+ $options[$private] = array_merge($options[$private], $options[$plugin]);
} else {
- $new_enabled = $enabled;
+ $options[$private] = $options[$plugin];
}
}
- $new_enabled[] = $plugin;
- $new_enabled = array_unique($new_enabled);
- $return = $site->setMetaData('enabled_plugins', $new_enabled);
- $ENABLED_PLUGINS_CACHE = $new_enabled;
- return $return;
+ $plugin_id = $options['plugin_id'];
+ $prefix = elgg_namespace_plugin_private_setting('user_setting', '', $plugin_id);
+ $options['private_setting_name_prefix'] = $prefix;
+
+ return elgg_get_entities_from_private_settings($options);
}
/**
- * Disable a plugin for a site (default current site)
+ * Register object, plugin entities as ElggPlugin classes
*
- * Important: You should regenerate simplecache and the viewpath cache after executing this function
- * otherwise you may experience view display artifacts. Do this with the following code:
+ * @return void
+ * @access private
+ */
+function plugin_run_once() {
+ add_subtype("object", "plugin", "ElggPlugin");
+}
+
+/**
+ * Runs unit tests for the entity objects.
*
- * elgg_view_regenerate_simplecache();
- * elgg_filepath_cache_reset();
+ * @param string $hook unit_test
+ * @param string $type system
+ * @param mixed $value Array of tests
+ * @param mixed $params Params
*
- * @param string $plugin The plugin name.
- * @param int $site_guid The site id, if not specified then this is detected.
+ * @return array
+ * @access private
*/
-function disable_plugin($plugin, $site_guid = 0) {
- global $CONFIG, $ENABLED_PLUGINS_CACHE;
-
- $plugin = sanitise_string($plugin);
- $site_guid = (int) $site_guid;
- if ($site_guid == 0) {
- $site_guid = $CONFIG->site_guid;
- }
-
- $site = get_entity($site_guid);
- if (!($site instanceof ElggSite)) {
- throw new InvalidClassException(sprintf(elgg_echo('InvalidClassException:NotValidElggStar'), $site_guid, "ElggSite"));
- }
-
- $enabled = $site->getMetaData('enabled_plugins');
- $new_enabled = array();
-
- foreach ($enabled as $plug) {
- if ($plugin != $plug) {
- $new_enabled[] = $plug;
- }
- }
-
- $return = $site->setMetaData('enabled_plugins', $new_enabled);
- $ENABLED_PLUGINS_CACHE = $new_enabled;
-
- return $return;
+function plugins_test($hook, $type, $value, $params) {
+ global $CONFIG;
+ $value[] = $CONFIG->path . 'engine/tests/api/plugins.php';
+ return $value;
}
/**
- * Return whether a plugin is enabled or not.
+ * Checks on deactivate plugin event if disabling it won't create unmet dependencies and blocks disable in such case.
*
- * @param string $plugin The plugin name.
- * @param int $site_guid The site id, if not specified then this is detected.
- * @return bool
+ * @param string $event deactivate
+ * @param string $type plugin
+ * @param array $params Parameters array containing entry with ELggPlugin instance under 'plugin_entity' key
+ * @return bool false to block plugin deactivation action
+ *
+ * @access private
*/
-function is_plugin_enabled($plugin, $site_guid = 0) {
- global $CONFIG, $ENABLED_PLUGINS_CACHE;
+function _plugins_deactivate_dependency_check($event, $type, $params) {
+ $plugin_id = $params['plugin_entity']->getManifest()->getPluginID();
+ $plugin_name = $params['plugin_entity']->getManifest()->getName();
- if (!file_exists($CONFIG->pluginspath . $plugin)) {
- return false;
- }
+ $active_plugins = elgg_get_plugins();
- $site_guid = (int) $site_guid;
- if ($site_guid == 0) {
- $site_guid = $CONFIG->site_guid;
- }
+ $dependents = array();
+ foreach ($active_plugins as $plugin) {
+ $manifest = $plugin->getManifest();
+ $requires = $manifest->getRequires();
-
- if (!$ENABLED_PLUGINS_CACHE) {
- $site = get_entity($site_guid);
- if (!($site instanceof ElggSite)) {
- throw new InvalidClassException(sprintf(elgg_echo('InvalidClassException:NotValidElggStar'), $site_guid, "ElggSite"));
+ foreach ($requires as $required) {
+ if ($required['type'] == 'plugin' && $required['name'] == $plugin_id) {
+ // there are active dependents
+ $dependents[$manifest->getPluginID()] = $plugin;
+ }
}
-
- $ENABLED_PLUGINS_CACHE = $site->enabled_plugins;
}
- foreach ($ENABLED_PLUGINS_CACHE as $e) {
- if ($e == $plugin) {
- return true;
+ if ($dependents) {
+ $list = '<ul>';
+ // construct error message and prevent disabling
+ foreach ($dependents as $dependent) {
+ $list .= '<li>' . $dependent->getManifest()->getName() . '</li>';
}
- }
+ $list .= '</ul>';
- return false;
-}
+ register_error(elgg_echo('ElggPlugin:Dependencies:ActiveDependent', array($plugin_name, $list)));
-/**
- * Run once and only once.
- */
-function plugin_run_once() {
- // Register a class
- add_subtype("object", "plugin", "ElggPlugin");
+ return false;
+ }
}
/**
- * Initialise the file modules.
- * Listens to system boot and registers any appropriate file types and classes
+ * Initialize the plugin system
+ * Listens to system init and registers actions
+ *
+ * @return void
+ * @access private
*/
function plugin_init() {
- // Now run this stuff, but only once
run_function_once("plugin_run_once");
- // Register some actions
- register_action("plugins/settings/save", false, "", true);
- register_action("plugins/usersettings/save");
+ elgg_register_plugin_hook_handler('unit_test', 'system', 'plugins_test');
+
+ // note - plugins are booted by the time this handler is registered
+ // deactivation due to error may have already occurred
+ elgg_register_event_handler('deactivate', 'plugin', '_plugins_deactivate_dependency_check');
+
+ elgg_register_action("plugins/settings/save", '', 'admin');
+ elgg_register_action("plugins/usersettings/save");
+
+ elgg_register_action('admin/plugins/activate', '', 'admin');
+ elgg_register_action('admin/plugins/deactivate', '', 'admin');
+ elgg_register_action('admin/plugins/activate_all', '', 'admin');
+ elgg_register_action('admin/plugins/deactivate_all', '', 'admin');
- register_action('admin/plugins/enable', false, "", true); // Enable
- register_action('admin/plugins/disable', false, "", true); // Disable
- register_action('admin/plugins/enableall', false, "", true); // Enable all
- register_action('admin/plugins/disableall', false, "", true); // Disable all
+ elgg_register_action('admin/plugins/set_priority', '', 'admin');
- register_action('admin/plugins/reorder', false, "", true); // Reorder
+ elgg_register_library('elgg:markdown', elgg_get_root_path() . 'vendors/markdown/markdown.php');
}
-// Register a startup event
-register_elgg_event_handler('init','system','plugin_init'); \ No newline at end of file
+elgg_register_event_handler('init', 'system', 'plugin_init');