$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 * * @todo This could be resolved by promoting ElggPlugin to a 5th type. */ define('ELGG_PLUGIN_INTERNAL_PREFIX', 'elgg:internal:'); /** * 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 */ function elgg_get_plugin_ids_in_dir($dir = null) { if (!$dir) { $dir = elgg_get_plugins_path(); } $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; } } } 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(); } // 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; } $physical_plugins = elgg_get_plugin_ids_in_dir($dir); 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'); } // remove from the list of plugins to disable unset($known_plugins[$index]); } else { // add new plugins // priority is force to last in save() if not set. $plugin = new ElggPlugin($plugin_id); $plugin->save(); } } // 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; } /** * Cache a reference to this plugin by its ID * * @param ElggPlugin $plugin * * @access private */ 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); } /** * 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]; } $plugin_id = sanitize_string($plugin_id); $db_prefix = get_config('dbprefix'); $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 ); $plugins = elgg_get_entities($options); if ($plugins) { return $plugins[0]; } return false; } /** * Returns if a plugin exists in the system. * * @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. * * @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 * * @return int * @since 1.8.0 * @access private */ 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; } // can't have a priority of 0. return ($max) ? $max : 1; } /** * 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 (!($site instanceof ElggSite)) { return false; } $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; } 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; } $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; } } } return $return; } /** * 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'); 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; } $old_ia = elgg_set_ignore_access(true); $plugins = elgg_get_entities_from_relationship($options); elgg_set_ignore_access($old_ia); return $plugins; } /** * 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. * * @param array $order An array of plugin ids in the order to set them * @return bool * @since 1.8.0 * @access private */ function elgg_set_plugin_priorities(array $order) { $name = elgg_namespace_plugin_private_setting('internal', 'priority'); $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; } $priority = array_search($plugin_id, $order) + 1; if (!$plugin->set($name, $priority)) { $return = false; break; } } // 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; } } } 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). * * 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. * * @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 elgg_get_calling_plugin_id($mainfilename = false) { if (!$mainfilename) { if ($backtrace = debug_backtrace()) { 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)) { return $matches[1]; } } } } else { //@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)) { return $matches[1]; } } } return false; } /** * Returns an array of all provides from all active plugins. * * Array in the form array( * 'provide_type' => array( * 'provided_name' => array( * 'version' => '1.8', * 'provided_by' => 'provider_plugin_id' * ) * ) * ) * * @param string $type The type of provides to return * @param string $name A specific provided name to return. Requires $provide_type. * * @return array * @since 1.8.0 * @access private */ 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() ); } } } } 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 $provides; } /** * 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 elgg_check_plugins_provides($type, $name, $version = null, $comparison = 'ge') { $provided = elgg_get_plugins_provides($type, $name); if (!$provided) { return array( 'status' => false, 'version' => '' ); } if ($version) { $status = version_compare($provided['version'], $version, $comparison); } else { $status = true; } return array( 'status' => $status, 'value' => $provided['version'] ); } /** * 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 ") * ) * * @param array $dep An ElggPluginPackage dependency array * @return array * @since 1.8.0 * @access private */ 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; } // 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 $strings; } /** * Returns the ElggPlugin entity of the last plugin called. * * @return mixed ElggPlugin or false * @since 1.8.0 * @access private */ function elgg_get_calling_plugin_entity() { $plugin_id = elgg_get_calling_plugin_id(); if ($plugin_id) { return elgg_get_plugin_from_id($plugin_id); } 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(); } if (!$plugin instanceof ElggPlugin) { return false; } $settings = $plugin->getAllUserSettings($user_guid); if ($settings && $return_obj) { $return = new stdClass; foreach ($settings as $k => $v) { $return->$k = $v; } return $return; } else { return $settings; } } /** * 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_id Optional plugin name, if not specified then it * is detected from where you are calling from. * * @return bool * @since 1.8.0 */ 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(); } if (!$plugin) { return false; } return $plugin->setUserSetting($name, $value, $user_guid); } /** * 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(); } if (!$plugin) { return false; } return $plugin->unsetUserSetting($name, $user_guid); } /** * Get a user specific setting for a plugin. * * @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 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 (!$plugin) { return false; } return $plugin->getUserSetting($name, $user_guid); } /** * Set a setting for a plugin. * * @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 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(); } if (!$plugin) { return false; } return $plugin->setSetting($name, $value); } /** * Get setting for a plugin. * * @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 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 false; } return $plugin->getSetting($name); } /** * 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. * * @return bool * @since 1.8.0 */ 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) { return false; } return $plugin->unsetSetting($name); } /** * 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 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(); } if (!$plugin) { return false; } return $plugin->unsetAllSettings(); } /** * 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 * * plugin_user_setting_values => NULL|ARR metadata values * * 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". * * 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 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(); } $singulars = array('plugin_user_setting_name', 'plugin_user_setting_value', 'plugin_user_setting_name_value_pair'); $options = elgg_normalise_plural_options_array($options, $singulars); // 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 { $options[$private] = $options[$plugin]; } } $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); } /** * Register object, plugin entities as ElggPlugin classes * * @return void * @access private */ function plugin_run_once() { add_subtype("object", "plugin", "ElggPlugin"); } /** * Runs unit tests for the entity objects. * * @param string $hook unit_test * @param string $type system * @param mixed $value Array of tests * @param mixed $params Params * * @return array * @access private */ function plugins_test($hook, $type, $value, $params) { global $CONFIG; $value[] = $CONFIG->path . 'engine/tests/api/plugins.php'; return $value; } /** * Checks on deactivate plugin event if disabling it won't create unmet dependencies and blocks disable in such case. * * @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 _plugins_deactivate_dependency_check($event, $type, $params) { $plugin_id = $params['plugin_entity']->getManifest()->getPluginID(); $plugin_name = $params['plugin_entity']->getManifest()->getName(); $active_plugins = elgg_get_plugins(); $dependents = array(); foreach ($active_plugins as $plugin) { $manifest = $plugin->getManifest(); $requires = $manifest->getRequires(); foreach ($requires as $required) { if ($required['type'] == 'plugin' && $required['name'] == $plugin_id) { // there are active dependents $dependents[$manifest->getPluginID()] = $plugin; } } } if ($dependents) { $list = ''; register_error(elgg_echo('ElggPlugin:Dependencies:ActiveDependent', array($plugin_name, $list))); return false; } } /** * Initialize the plugin system * Listens to system init and registers actions * * @return void * @access private */ function plugin_init() { run_function_once("plugin_run_once"); 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'); elgg_register_action('admin/plugins/set_priority', '', 'admin'); elgg_register_library('elgg:markdown', elgg_get_root_path() . 'vendors/markdown/markdown.php'); } elgg_register_event_handler('init', 'system', 'plugin_init');