diff options
Diffstat (limited to 'engine')
| -rw-r--r-- | engine/classes/ElggPlugin.php | 739 | ||||
| -rw-r--r-- | engine/classes/ElggPluginManifest.php | 71 | ||||
| -rw-r--r-- | engine/classes/ElggPluginManifestParser18.php | 22 | ||||
| -rw-r--r-- | engine/classes/ElggPluginPackage.php | 25 | ||||
| -rw-r--r-- | engine/lib/plugins.php | 1134 | ||||
| -rw-r--r-- | engine/lib/upgrades/2011010101.php | 75 | ||||
| -rw-r--r-- | engine/tests/api/plugins.php | 28 | ||||
| -rw-r--r-- | engine/tests/test_files/plugin_18/manifest.xml | 11 | 
8 files changed, 1611 insertions, 494 deletions
| diff --git a/engine/classes/ElggPlugin.php b/engine/classes/ElggPlugin.php index 887eb667f..fb9138ab9 100644 --- a/engine/classes/ElggPlugin.php +++ b/engine/classes/ElggPlugin.php @@ -9,6 +9,11 @@   * @subpackage Plugins.Settings   */  class ElggPlugin extends ElggObject { +	public $package; +	public $manifest; + +	private $path; +	private $pluginID;  	/**  	 * Set subtype to 'plugin' @@ -19,10 +24,704 @@ class ElggPlugin extends ElggObject {  		parent::initializeAttributes();  		$this->attributes['subtype'] = "plugin"; + +		// plugins must be public. +		$this->access_id = ACCESS_PUBLIC; +	} + + +	/** +	 * Loads the plugin by GUID or path. +	 * +	 * @warning Unlike other ElggEntity objects, you cannot null instantiate +	 *          ElggPlugin. You must point it to an actual plugin GUID or location. +	 * +	 * @param mixed $plugin The GUID of the ElggPlugin object or the path of +	 *                      the plugin to load. +	 */ +	public function __construct($plugin) { +		if (!$plugin) { +			throw new PluginException(elgg_echo('PluginException:NullInstantiated')); +		} + +		// ElggEntity can be instantiated with a guid or an object. +		// @todo plugins w/id 12345 +		if (is_numeric($plugin) || is_object($plugin)) { +			parent::__construct($plugin); +			$this->path = get_config('plugins_path') . $this->getID(); +		} else { +			// not a full path, so assume an id +			// use the default path +			if (substr($plugin, 0, 1) != '/') { +				$plugin = elgg_get_plugin_path() . $plugin; +			} + +			// path checking is done in the package +			$plugin = sanitise_filepath($plugin); +			$this->path = $plugin; +			$path_parts = explode('/', rtrim($plugin, '/')); +			$plugin_id = array_pop($path_parts); +			$this->pluginID = $plugin_id; + +			// check if we're loading an existing plugin +			$existing_plugin = elgg_get_plugin_from_id($this->pluginID); +			$existing_guid = null; + +			if ($existing_plugin) { +				$existing_guid = $existing_plugin->guid; +			} + +			// load the rest of the plugin +			parent::__construct($existing_guid); +		} + +		// We have to let the entity load so we can manipulate it with the API. +		// If the path is wrong or would cause an exception, catch it, +		// disable the plugin, and emit an error. +		try { +			$this->package = new ElggPluginPackage($this->path, false); +			$this->manifest = $this->package->getManifest(); +		} catch (Exception $e) { +			// we always have to allow the entity to load. +		} +	} + + +	/** +	 * Save the plugin object.  Make sure required values exist. +	 * +	 * @see ElggObject::save() +	 * @return bool +	 */ +	public function save() { +		// own by the current site so users can be deleted without affecting plugins +		$site = get_config('site'); +		$this->attributes['site_guid'] = $site->guid; +		$this->attributes['owner_guid'] = $site->guid; +		$this->attributes['container_guid'] = $site->guid; +		$this->attributes['title'] = $this->pluginID; + +		if (parent::save()) { +			// make sure we have a priority +			$priority = $this->getPriority(); +			if ($priority === FALSE || $priority === NULL) { +				return $this->setPriority('last'); +			} +		} else { +			return false; +		} +	} + + +	// Plugin ID + +	/** +	 * Returns the ID (dir name) of this plugin +	 * +	 * @return string +	 */ +	public function getID() { +		return $this->title; +	} + + +	/** +	 * Sets the location of this plugin. +	 * +	 * @param path $id The path to the plugin's dir. +	 * @return bool +	 */ +	public function setID($id) { +		return $this->attributes['title'] = $id; +	} + + +	// Load Priority + +	/** +	 * Gets the plugin's load priority. +	 * +	 * @return int +	 */ +	public function getPriority() { +		$name = elgg_namespace_plugin_private_setting('internal', 'priority'); +		return $this->$name; +	} + + +	/** +	 * Sets the priority of the plugin +	 * +	 * @param mixed $priority  The priority to set. One of +1, -1, first, last, or a number. +	 *                         If given a number, this will displace all plugins at that number +	 *                         and set their priorities +1 +	 * @param mixed $site_guid Optional site GUID. +	 * @return bool +	 */ +	public function setPriority($priority, $site_guid = null) { +		if (!$this->guid) { +			return false; +		} + +		$db_prefix = get_config('dbprefix'); +		$name = elgg_namespace_plugin_private_setting('internal', 'priority'); +		// if no priority assume a priority of 0 +		$old_priority = (int) $this->getPriority(); +		$max_priority = elgg_get_max_plugin_priority(); + +		if ($priority == $old_priority) { +			return false; +		} + +		// there's nothing above the max. +		if ($priority > $max_priority) { +			$priority = $max_priority; +		} + +		// there's nothing below 1. +		if ($priority < 1) { +			$priority = 1; +		} + +		// (int) 0 matches (string) first, so cast to string. +		$priority = (string) $priority; + +		switch ($priority) { +			case '+1': +				$priority = $old_priority + 1; +				break; + +			case '-1': +				$priority = $old_priority - 1; +				break; + +			case 'first': +				$priority = 1; +				break; + +			case 'last': +				$priority = $max_priority; +				break; +		} + +		// should be a number by now +		if ($priority) { +			if (!is_numeric($priority)) { +				return false; +			} + +			if ($priority > $old_priority) { +				$op = '-'; +				$where = "CAST(value as unsigned) BETWEEN $old_priority AND $priority"; +			} else { +				$op = '+'; +				$where = "CAST(value as unsigned) BETWEEN $priority AND $old_priority"; +			} + +			// displace the ones affected by this change +			$q = "UPDATE {$db_prefix}private_settings +				SET value = CAST(value as unsigned) $op 1 +				WHERE entity_guid != $this->guid +				AND name = '$name' +				AND $where"; + +			if (!update_data($q)) { +				return false; +			} + +			// set this priority +			if ($this->set($name, $priority)) { +				//return elgg_plugins_reindex_priorities(); +				return true; +			} else { +				return false; +			} +		} + +		return false; +	} + + +	// Plugin settings + +	/** +	 * Returns a plugin setting +	 * +	 * @todo These need to be namespaced +	 * +	 * @param string $name The setting name +	 * @return mixed +	 */ +	public function getSetting($name) { +		return $this->$name; +	} + + +	/** +	 * Set a plugin setting for the plugin +	 * +	 * @todo This will only work once the plugin has a GUID. +	 * @todo These need to be namespaced. +	 * +	 * @param string $name  The name to set +	 * @param string $value The value to set +	 * +	 * @return bool +	 */ +	public function setSetting($name, $value) { +		if ($this->guid) { +			return false; +		} +		// Hook to validate setting +		$value = elgg_trigger_plugin_hook('plugin:setting', 'plugin', array( +			'plugin' => $this->pluginID, +			'plugin_object' => $this, +			'name' => $name, +			'value' => $value +		), $value); + +		return $this->$name = $value;  	}  	/** +	 * Removes a plugin setting name and value. +	 * +	 * @param string $name The setting name to remove +	 * +	 * @return bool +	 */ +	public function removeSetting($name) { +		return remove_private_setting($this->guid, $name); +	} + + +	/** +	 * Removes all settings for this plugin. +	 * +	 * @todo Should be a better way to do this without dropping to raw SQL. +	 * @todo If we could namespace the plugin settings this would be cleaner. +	 * @return bool +	 */ +	public function removeAllSettings() { +		$db_prefix = get_config('dbprefix'); +		$ps_prefix = elgg_namespace_plugin_private_setting('setting', ''); + +		$q = "DELETE FROM {$db_prefix}private_settings +			WHERE entity_guid = $this->guid +			AND name NOT LIKE '$ps_prefix%'"; + +		return delete_data($q); +	} + + +	// User settings + +	/** +	 * Returns a user's setting for this plugin +	 * +	 * @param int    $user_guid The user GUID +	 * @param string $name      The setting name +	 * +	 * @return mixed The setting string value or false +	 */ +	public function getUserSetting($user_guid, $name) { +		$name = elgg_namespace_plugin_private_setting('user_setting', $name, $this->getID()); +		return get_private_setting($user_guid, $name); +	} + +	/** +	 * Sets a user setting for a plugin +	 * +	 * @param int    $user_guid The user GUID +	 * @param string $name      The setting name +	 * @param string $value     The setting value +	 * +	 * @return mixed The new setting ID or false +	 */ +	public function setUserSetting($user_guid, $name, $value) { +		$name = elgg_namespace_plugin_private_setting('user_setting', $name, $this->getID()); +		return set_private_setting($user_guid, $name, $value); +	} + + +	/** +	 * Removes a user setting name and value. +	 * +	 * @param int    $user_guid The user GUID +	 * @param string $name      The user setting name +	 * +	 * @return bool +	 */ +	public function removeUserSetting($user_guid, $name) { +		$name = elgg_namespace_plugin_private_setting('user_setting', $name, $this->getID()); +		return remove_private_setting($user_guid, $name); +	} + + +	/** +	 * Removes all User Settings for this plugin +	 * +	 * Use {@link removeAllUsersSettings()} to remove all user +	 * settings for all users.  (Note the plural 'Users'.) +	 * +	 * @param int $user_guid The user GUID to remove user settings. +	 * @return bool +	 */ +	public function removeAllUserSettings($user_guid) { +		$db_prefix = get_config('dbprefix'); +		$ps_prefix = elgg_namespace_plugin_private_setting('user_setting', '', $this->getID()); + +		$q = "DELETE FROM {$db_prefix}private_settings +			WHERE entity_guid = $user_guid +			AND name LIKE '$ps_prefix%'"; + +		return delete_data($q); +	} + + +	/** +	 * Removes this plugin's user settings for all users. +	 * +	 * Use {@link removeAllUserSettings()} if you just want to remove +	 * settings for a single user. +	 * +	 * @return bool +	 */ +	public function removeAllUsersSettings() { +		$db_prefix = get_config('dbprefix'); +		$ps_prefix = elgg_namespace_plugin_private_setting('user_setting', '', $this->getID()); + +		$q = "DELETE FROM {$db_prefix}private_settings +			WHERE name LIKE '$ps_prefix%'"; + +		return delete_data($q); +	} + + +	// validation + +	/** +	 * Returns if the plugin is complete, meaning has all required files +	 * and Elgg can read them and they make sense. +	 * +	 * @todo bad name? This could be confused with isValid() from ElggPackage. +	 * +	 * @return bool +	 */ +	public function isValid() { +		if (!$this->getID()) { +			return false; +		} + +		if (!$this->package instanceof ElggPluginPackage) { +			return false; +		} + +		if (!$this->package->isValid()) { +			return false; +		} + +		return true; +	} + + +	/** +	 * Is this plugin active? +	 * +	 * @param int $site_guid Optional site guid. +	 * @return bool +	 */ +	public function isActive($site_guid = null) { +		if (!$this->guid) { +			return false; +		} + +		if ($site_guid) { +			$site = get_entity($site_guid); + +			if (!($site instanceof ElggSite)) { +				return false; +			} +		} else { +			$site = get_config('site'); +		} + +		return check_entity_relationship($this->guid, 'active_plugin', $site->guid); +	} + + +	/** +	 * Checks if this plugin can be activated on the current +	 * Elgg installation. +	 * +	 * @param mixed $site_guid Optional site guid +	 * @return bool +	 */ +	public function canActivate($site_guid = null) { +		if ($this->package) { +			return $this->package->isValid() && $this->package->checkDependencies(); +		} + +		return false; +	} + + +	// activating and deactivating + +	/** +	 * Actives the plugin for the current site. +	 * +	 * @param mixed $site_guid Optional site GUID. +	 * @return bool +	 */ +	public function activate($site_guid = null) { +		if ($this->isActive($site_guid)) { +			return false; +		} +		// set in the db, now perform tasks and emit events +		if ($this->setStatus(true, $site_guid)) { +			// emit an event. returning false will make this not be activated. +			// we need to do this after it's been fully activated +			// or the deactivate will be confused. +			$params = array( +				'plugin_id' => $this->pluginID, +				'plugin_entity' => $this +			); + +			$return = elgg_trigger_event('activate', 'plugin', $params); + +			// if there are any on_enable functions, start the plugin now and run them +			// Note: this will not run re-run the init hooks! +			$functions = $this->manifest->getOnActivate(); +			if ($return && $functions) { +				$flags = ELGG_PLUGIN_INCLUDE_START | ELGG_PLUGIN_REGISTER_CLASSES +						| ELGG_PLUGIN_REGISTER_LANGUAGES | ELGG_PLUGIN_REGISTER_VIEWS; + +				$this->start($flags); +				foreach ($functions as $function) { +					if (!is_callable($function)) { +						$return = false; +					} else { +						$on_enable = call_user_func($function); +						// allow null to mean "I don't care" like other subsystems +						$return = ($on_disable === false) ? false: true; +					} + +					if ($return === false) { +						break; +					} +				} +			} + +			if ($return === false) { +				$this->deactivate($site_guid); +			} + +			return $return; +		} + +		return false; +	} + + +	/** +	 * Deactivates the plugin. +	 * +	 * @param mixed $site_guid Optional site GUID. +	 * @return bool +	 */ +	public function deactivate($site_guid = null) { +		if (!$this->isActive($site_guid)) { +			return false; +		} + +		// emit an event. returning false will cause this to not be deactivated. +		$params = array( +			'plugin_id' => $this->pluginID, +			'plugin_entity' => $this +		); + +		$return = elgg_trigger_event('deactivate', 'plugin', $params); + +		// run any deactivate functions +		// check for the manifest in case we haven't fully loaded the plugin. +		if ($this->manifest) { +			$functions = $this->manifest->getOnDeactivate(); +		} else { +			$functions = array(); +		} + +		if ($return && $functions) { +			foreach ($functions as $function) { +				if (!is_callable($function)) { +					$return = false; +				} else { +					$on_enable = call_user_func($function); +					// allow null to mean "I don't care" like other subsystems +					$return = ($on_disable === false) ? false : true; +				} + +				if ($return === false) { +					break; +				} +			} +		} + +		if ($return === false) { +			return false; +		} else { +			return $this->setStatus(false, $site_guid); +		} +	} + + +	/** +	 * Start the plugin. +	 * +	 * @param int $flags Start flags for the plugin. See the constants in lib/plugins.php for details. +	 * @return true +	 * @throws PluginException +	 */ +	public function start($flags) { +		if (!$this->canActivate()) { +			return false; +		} + +		// include start file +		if ($flags & ELGG_PLUGIN_INCLUDE_START) { +			$this->includeStart(); +		} + +		// include views +		if ($flags & ELGG_PLUGIN_REGISTER_VIEWS) { +			$this->registerViews(); +		} + +		// include languages +		if ($flags & ELGG_PLUGIN_REGISTER_LANGUAGES) { +			$this->registerLanguages(); +		} + +		// include classes +		if ($flags & ELGG_PLUGIN_REGISTER_CLASSES) { +			$this->registerClasses(); +		} + +		return true; +	} + + +	// start helpers + +	/** +	 * Includes the plugin's start file +	 * +	 * @throws PluginException +	 * @return true +	 */ +	protected function includeStart() { +		$start = "$this->path/start.php"; +		if (!include($start)) { +			$msg = elgg_echo('ElggPlugin:Exception:CannotIncludeStart', +							array($this->getID(), $this->guid, $this->path)); +			throw new PluginException($msg); +		} + +		return true; +	} + +	/** +	 * Registers the plugin's views +	 * +	 * @throws PluginException +	 * @return true +	 */ +	protected function registerViews() { +		$view_dir = "$this->path/views/"; + +		// plugins don't have to have views. +		if (!is_dir($view_dir)) { +			return true; +		} + +		// but if they do, they have to be readable +		$handle = opendir($view_dir); +		if (!$handle) { +			$msg = elgg_echo('ElggPlugin:Exception:CannotRegisterViews', +							array($this->getID(), $this->guid, $view_dir)); +			throw new PluginException($msg); +		} + +		while (FALSE !== ($view_type = readdir($handle))) { +			$view_type_dir = $view_dir . $view_type; + +			if ('.' !== substr($view_type, 0, 1) && is_dir($view_type_dir)) { +				if (autoregister_views('', $view_type_dir, $view_dir, $view_type)) { +					elgg_register_viewtype($view_type); +				} else { +					$msg = elgg_echo('ElggPlugin:Exception:CannotRegisterViews', +									array($this->getID(), $view_type_dir)); +					throw new PluginException($msg); +				} +			} +		} + +		return true; +	} + +	/** +	 * Registers the plugin's languages +	 * +	 * @throws PluginException +	 * @return true +	 */ +	protected function registerLanguages() { +		$languages_path = "$this->path/languages"; + +		// don't need to have classes +		if (!is_dir($languages_path)) { +			return true; +		} + +		// but need to have working ones. +		if (!register_translations($languages_path)) { +			$msg = elgg_echo('ElggPlugin:Exception:CannotRegisterLanguages', +							array($this->getID(), $this->guid, $languages_path)); +			throw new PluginException($msg); +		} + +		return true; +	} + +	/** +	 * Registers the plugin's classes +	 * +	 * @throws PluginException +	 * @return true +	 */ +	protected function registerClasses() { +		$classes_path = "$this->path/classes"; + +		// don't need to have classes +		if (!is_dir($classes_path)) { +			return true; +		} + +		// but need to have working ones. +		if (!elgg_register_classes($classes_path)) { +			$msg = elgg_echo('ElggPlugin:Exception:CannotRegisterClasses', +							array($this->getID(), $this->guid, $classes_path)); +			throw new PluginException($msg); +		} + +		return true; +	} + + +	// generic helpers and overrides + +	/**  	 * Get a value from private settings.  	 *  	 * @param string $name Name @@ -30,8 +729,16 @@ class ElggPlugin extends ElggObject {  	 * @return mixed  	 */  	public function get($name) { +		// rewrite for old and inaccurate plugin:setting +		if (strstr($name, 'plugin:setting:')) { +			$msg = 'Direct access of user settings is deprecated. Use ElggPlugin->getUserSetting()'; +			elgg_deprecated_notice($msg, 1.8); +			$name = str_replace('plugin:setting:', '', $name); +			$name = elgg_namespace_plugin_private_setting('user_setting', $name); +		} +  		// See if its in our base attribute -		if (isset($this->attributes[$name])) { +		if (array_key_exists($name, $this->attributes)) {  			return $this->attributes[$name];  		} @@ -69,4 +776,34 @@ class ElggPlugin extends ElggObject {  		return true;  	} + +	/** +	 * Sets the plugin to active or inactive for $site_guid. +	 * +	 * @param bool  $active    Set to active or inactive +	 * @param mixed $site_guid Int for specific site, null for current site. +	 * +	 * @return bool +	 */ +	private function setStatus($active, $site_guid = null) { +		if (!$this->guid) { +			return false; +		} + +		if ($site_guid) { +			$site = get_entity($site_guid); + +			if (!($site instanceof ElggSite)) { +				return false; +			} +		} else { +			$site = get_config('site'); +		} + +		if ($active) { +			return add_entity_relationship($this->guid, 'active_plugin', $site->guid); +		} else { +			return remove_entity_relationship($this->guid, 'active_plugin', $site->guid); +		} +	}  }
\ No newline at end of file diff --git a/engine/classes/ElggPluginManifest.php b/engine/classes/ElggPluginManifest.php index 801769eb9..9fcdaaf55 100644 --- a/engine/classes/ElggPluginManifest.php +++ b/engine/classes/ElggPluginManifest.php @@ -481,6 +481,77 @@ class ElggPluginManifest {  	}  	/** +	 * Returns the functions to run upon activation +	 * +	 *  @return array +	 */ +	public function getOnActivate() { +		$functions = $this->parser->getAttribute('on_activate'); + +		if (!$functions) { +			$functions = array(); +		} + +		return $functions; +	} + +	/** +	 * Returns the functions to run upon deactivation +	 * +	 *  @return array +	 */ +	public function getOnDeactivate() { +		$functions = $this->parser->getAttribute('on_deactivate'); + +		if (!$functions) { +			$functions = array(); +		} + +		return $functions; +	} + +	/** +	 * Returns the admin interface to use. +	 * +	 *  @return string simple or advanced +	 */ +	public function getAdminInterface() { +		$interface = $this->parser->getAttribute('admin_interface'); + +		switch ($interface) { +			case 'simple': +			case 'advanced': +				return $interface; + +			default: +				return 'advanced'; +		} +	} + +	/** +	 * Returns the admin interface to use. +	 * +	 *  @return bool +	 */ +	public function getActivateOnInstall() { +		$activate = $this->parser->getAttribute('activate_on_install'); +		switch (strtolower($activate)) { +			case 'yes': +			case 'true': +			case 'on': +			case 1: +				return true; + +			case 'no': +			case 'false': +			case 'off': +			case 0: +			case '': +				return false; +		} +	} + +	/**  	 * Normalizes an array into the structure specified  	 *  	 * @param array $struct The struct to normalize $element to. diff --git a/engine/classes/ElggPluginManifestParser18.php b/engine/classes/ElggPluginManifestParser18.php index 9a4cfb2b7..1f5b51bb5 100644 --- a/engine/classes/ElggPluginManifestParser18.php +++ b/engine/classes/ElggPluginManifestParser18.php @@ -15,7 +15,8 @@ class ElggPluginManifestParser18 extends ElggPluginManifestParser {  	protected $validAttributes = array(  		'name', 'author', 'version', 'blurb', 'description',  		'website', 'copyright', 'license', 'requires', 'screenshot', -		'category', 'conflicts', 'provides', 'admin' +		'category', 'conflicts', 'provides', 'on_activate', 'on_deactivate', +		'admin_interface', 'activate_on_install'  	);  	/** @@ -45,26 +46,19 @@ class ElggPluginManifestParser18 extends ElggPluginManifestParser {  				case 'website':  				case 'copyright':  				case 'license': +				case 'admin_interface': +				case 'activate_on_install':  					$parsed[$element->name] = $element->content;  					break;  				// arrays +				case 'on_activate': +				case 'on_deactivate':  				case 'category': -					$parsed['category'][] = $element->content; -					break; - -				case 'admin': -					$parsed['admin'] = array(); -					if (!isset($element->children)) { -						return false; -					} - -					foreach ($element->children as $child_element) { -						$parsed['admin'][$child_element->name] = $child_element->content; -					} - +					$parsed[$element->name][] = $element->content;  					break; +				// 3d arrays  				case 'screenshot':  				case 'provides':  				case 'conflicts': diff --git a/engine/classes/ElggPluginPackage.php b/engine/classes/ElggPluginPackage.php index 8bbacce22..6301ad1f2 100644 --- a/engine/classes/ElggPluginPackage.php +++ b/engine/classes/ElggPluginPackage.php @@ -239,16 +239,6 @@ class ElggPluginPackage {  		return true;  	} -	/** -	 * Checks if this plugin can be activated on the current -	 * Elgg installation. -	 * -	 * @return bool -	 */ -	public function canActivate() { -		return $this->checkDependencies(); -	} -  	/************  	 * Manifest * @@ -261,7 +251,9 @@ class ElggPluginPackage {  	 */  	public function getManifest() {  		if (!$this->manifest) { -			$this->loadManifest(); +			if (!$this->loadManifest()) { +				return false; +			}  		}  		return $this->manifest; @@ -275,9 +267,14 @@ class ElggPluginPackage {  	 */  	private function loadManifest() {  		$file = $this->path . 'manifest.xml'; -		$this->manifest = new ElggPluginManifest($file, $this->id); -		if ($this->manifest) { +		try { +			$this->manifest = new ElggPluginManifest($file, $this->id); +		} catch (Exception $e) { +			return false; +		} + +		if ($this->manifest instanceof ElggPluginManifest) {  			return true;  		} @@ -307,7 +304,7 @@ class ElggPluginPackage {  	public function checkDependencies($full_report = false) {  		$requires = $this->getManifest()->getRequires();  		$conflicts = $this->getManifest()->getConflicts(); -		$enabled_plugins = get_installed_plugins('enabled'); +		$enabled_plugins = elgg_get_plugins('active');  		$report = array();  		foreach (array('requires', 'conflicts') as $dep_type) { diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php index 29f55926c..cd74353de 100644 --- a/engine/lib/plugins.php +++ b/engine/lib/plugins.php @@ -7,202 +7,296 @@   * @subpackage Plugins   */ -/// Cache enabled plugins per page -$ENABLED_PLUGINS_CACHE = NULL; +/** + * Tells ElggPlugin::start() to include the start.php file. + */ +define('ELGG_PLUGIN_INCLUDE_START', 1);  /** - * Returns a list of plugins to load, in the order that they should be loaded. + * Tells ElggPlugin::start() to automatically register the plugin's views. + */ +define('ELGG_PLUGIN_REGISTER_VIEWS', 2); + +/** + * 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); + +/** + * Prefix for plugin setting names   * - * @return array List of plugins + * @todo Can't namespace these because many plugins directly call + * private settings via $entity->$name.   */ -function get_plugin_list() { -	global $CONFIG; +//define('ELGG_PLUGIN_SETTING_PREFIX', 'plugin:setting:'); -	if (!empty($CONFIG->pluginlistcache)) { -		return $CONFIG->pluginlistcache; -	} +/** + * Prefix for plugin user setting names + */ +define('ELGG_PLUGIN_USER_SETTING_PREFIX', 'plugin:user_setting:'); -	if ($site = get_entity($CONFIG->site_guid)) { -		$pluginorder = $site->pluginorder; -		if (!empty($pluginorder)) { -			$plugins = unserialize($pluginorder); +/** + * Internal settings prefix + * + * @todo This could be resolved by promoting ElggPlugin to a 5th type. + */ +define('ELGG_PLUGIN_INTERNAL_PREFIX', 'elgg:internal:'); -			$CONFIG->pluginlistcache = $plugins; -			return $plugins; -		} else { -			// this only runs on install, otherwise uses serialized plugin order -			$plugins = array(); - -			if ($handle = opendir($CONFIG->pluginspath)) { -				while ($mod = readdir($handle)) { -					// must be directory and not begin with a . -					if (substr($mod, 0, 1) !== '.' && is_dir($CONFIG->pluginspath . "/" . $mod)) { -						$plugins[] = $mod; -					} -				} -			} -			sort($plugins); +/** + * 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 + */ +function elgg_get_plugin_ids_in_dir($dir = null) { +	if (!$dir) { +		$dir = elgg_get_plugin_path(); +	} + +	$plugin_idss = array(); +	$handle = opendir($dir); -			$CONFIG->pluginlistcache = $plugins; -			return $plugins; +	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; +			}  		}  	} -	return false; +	sort($plugin_ids); + +	return $plugin_ids;  }  /** - * Regenerates the list of known plugins and saves it to the current site - * - * 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: + * 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.   * - * 		elgg_view_regenerate_simplecache(); - *		elgg_filepath_cache_reset(); - * - * @param array $pluginorder Optionally, a list of existing plugins and their orders - * - * @return array The new list of plugins and their orders + * @todo Crappy name? + * @return bool   */ -function regenerate_plugin_list($pluginorder = FALSE) { -	global $CONFIG; - -	$CONFIG->pluginlistcache = NULL; +function elgg_generate_plugin_entities() { +	$site = get_config('site'); +	$dir = elgg_get_plugin_path(); + +	$options = array( +		'type' => 'object', +		'subtype' => 'plugin', +		'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); + +	if (!$known_plugins) { +		$known_plugins = array(); +	} -	if ($site = get_entity($CONFIG->site_guid)) { -		if (empty($pluginorder)) { -			$pluginorder = $site->pluginorder; -			$pluginorder = unserialize($pluginorder); -		} else { -			ksort($pluginorder); +	// 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; +	} -		if (empty($pluginorder)) { -			$pluginorder = array(); -		} +	$physical_plugins = elgg_get_plugin_ids_in_dir($dir); -		$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)) { -				// must be directory and not begin with a . -				if (substr($mod, 0, 1) !== '.' && is_dir($CONFIG->pluginspath . "/" . $mod)) { -					if (!in_array($mod, $pluginorder)) { -						$max = $max + 10; -						$pluginorder[$max] = $mod; -					} -				} +	if (!$physical_plugins) { +		return false; +	} + +	$new_plugin_priority = elgg_get_max_plugin_priority() + 1; + +	// 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->enabled != 'yes') { +				$plugin->enable(); +				$plugin->deactivate();  			} -		} -		ksort($pluginorder); +			// remove from the list of plugins to disable +			unset($known_plugins[$index]); +		} else { +			// add new plugins +			$plugin = new ElggPlugin($plugin_id); +			$plugin->save(); +			$plugin->setPriority($new_plugin_priority); -		// Now reorder the keys .. -		$key = 10; -		$plugins = array(); -		if (sizeof($pluginorder)) { -			foreach ($pluginorder as $plugin) { -				$plugins[$key] = $plugin; -				$key = $key + 10; -			} +			$new_plugin_priority++;  		} +	} -		$plugins = serialize($plugins); +	// 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) { +		$plugin->deactivate(); +		$plugin->disable(); +	} + +	access_show_hidden_entities($old_access); +	elgg_set_ignore_access($old_ia); -		$site->pluginorder = $plugins; +	return true; +} -		return $plugins; +/** + * Returns an ElggPlugin object with the path $path. + * + * @param string $id The id (dir name) of the plugin. NOT the guid. + * @return mixed ElggPlugin or false. + */ +function elgg_get_plugin_from_id($id) { +	$id = sanitize_string($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"), +		'wheres' => array("oe.title = '$id'"), +		'limit' => 1 +	); + +	$plugins = elgg_get_entities($options); + +	if ($plugins) { +		return $plugins[0];  	} -	return FALSE; +	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. + * @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 + */ +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) { +		return $data[0]->max; +	} + +	// can't have a priority of 0. +	return 1; +}  /** - * For now, loads plugins directly + * Loads all active plugins in the order specified in the tool admin panel.   * - * @todo Add proper plugin handler that launches plugins in an - * admin-defined order and activates them on admin request + * @note This is called on every page load and includes additional checking that plugins + * are fit to be loaded.  If a plugin is active and problematic, it will be disabled + * and a visible error emitted.   * - * @return void + * @return bool   */ -function load_plugins() { +function elgg_load_plugins() {  	global $CONFIG; -	if (empty($CONFIG->pluginspath)) { -		return; +	$plugins_path = elgg_get_plugin_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($CONFIG->pluginspath . "disabled")) { -		return; +	if (file_exists("$plugins_path/disabled")) { +		return false;  	} -	 -	// See if we have cached values for things + +	// Load view caches if available  	$cached_view_paths = elgg_filepath_cache_load('views');  	$cached_view_types = elgg_filepath_cache_load('view_types');  	$cached_view_info = is_string($cached_view_paths) && is_string($cached_view_types); +  	if ($cached_view_info) {  		$CONFIG->views = unserialize($cached_view_paths);  		$CONFIG->view_types = unserialize($cached_view_types); + +		// don't need to register views +		$start_flags = $start_flags & ~ELGG_PLUGIN_REGISTER_VIEWS;  	} -	$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")) { -						// automatically disable the bad plugin -						disable_plugin($mod); - -						// register error rather than rendering the site unusable with exception -						register_error(sprintf(elgg_echo('PluginException:MisconfiguredPlugin'), $mod)); - -						// continue loading remaining plugins -						continue; -					} - -					if (!$cached_view_info) { -						$view_dir = $CONFIG->pluginspath . $mod . '/views/'; - -						if (is_dir($view_dir) && ($handle = opendir($view_dir))) { -							while (FALSE !== ($view_type = readdir($handle))) { -								$view_type_dir = $view_dir . $view_type; - -								if ('.' !== substr($view_type, 0, 1) && is_dir($view_type_dir)) { -									if (autoregister_views('', $view_type_dir, $view_dir, $view_type)) { -										// add the valid view type. -										if (!in_array($view_type, $CONFIG->view_types)) { -											$CONFIG->view_types[] = $view_type; -										} -									} -								} -							} -						} -					} - -					if (is_dir($CONFIG->pluginspath . "$mod/classes")) { -						elgg_register_classes($CONFIG->pluginspath . "$mod/classes"); -					} - -					if (is_dir($CONFIG->pluginspath . $mod . "/languages")) { -						register_translations($CONFIG->pluginspath . $mod . "/languages/"); -					} -				} +	$return = true; +	$plugins = elgg_get_plugins('active'); +	if ($plugins) { +		foreach ($plugins as $plugin) { +			// check if plugin can be started and try to start it. +			// if anything is bad, disable it and emit a message. +			if (!$plugin->isValid()) { +				$plugin->deactivate(); +				$msg = elgg_echo('PluginException:MisconfiguredPlugin', array($plugin->getID(), $plugin->guid)); +				register_error($msg); +				$return = false; + +				continue; +			} + +			try { +				$plugin->start($start_flags); +			} catch (Exception $e) { +				$plugin->deactivate(); +				$msg = elgg_echo('PluginException:CannotStart', +								array($plugin->getID(), $plugin->guid, $e->getMessage())); +				register_error($msg); +				$return = false; + +				continue;  			}  		}  	} @@ -212,21 +306,257 @@ function load_plugins() {  		elgg_filepath_cache_save('views', serialize($CONFIG->views));  		elgg_filepath_cache_save('view_types', serialize($CONFIG->view_types));  	} + +	return $return; +} + +/** + * Returns an ordered list of plugins + * + * @param string $status          The status of the plugins. active, inactive, or all. + * @param bool   $include_deleted Include physically deleted (and so inactive and disabled) plugins? + * @param mixed  $site_guid       Optional site guid + * @return array + */ +function elgg_get_plugins($status = 'active', $include_deleted = false, $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, +		'joins' => array("JOIN {$db_prefix}private_settings ps on ps.entity_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; +	} + +	if ($include_deleted) { +		$old_id = elgg_set_ignore_access(true); +	} + +	$plugins = elgg_get_entities_from_relationship($options); + +	if ($include_deleted) { +		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 + */ +function elgg_set_plugin_priorities(array $order) { +	$name = elgg_namespace_plugin_private_setting('internal', 'priority'); + +	$plugins = elgg_get_plugins('any', true); +	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); + +	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 (!$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 + */ +function elgg_plugins_reindex_priorities() { +	return elgg_set_plugin_priorities(array()); +} + +/** + * Returns a list of plugins to load, in the order that they should be loaded. + * + * @deprecated 1.8 + * + * @return array List of plugins + */ +function get_plugin_list() { +	elgg_deprecated_notice('get_plugin_list() is deprecated by elgg_get_plugin_ids_in_dir() or elgg_get_plugins()', 1.8); + +	$plugins = elgg_get_plugins('any'); + +	$list = array(); +	if ($plugins) { +		foreach ($plugins as $i => $plugin) { +			// in <=1.7 this returned indexed by multiples of 10. +			// uh...sure...why not. +			$index = ($i + 1) * 10; +			$list[$index] = $plugin->getID(); +		} +	} + +	return $list; +} + +/** + * Regenerates the list of known plugins and saves it to the current site + * + * 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: + * + * 		elgg_view_regenerate_simplecache(); + *		elgg_filepath_cache_reset(); + * + * @deprecated 1.8 + * + * @param array $pluginorder Optionally, a list of existing plugins and their orders + * + * @return array The new list of plugins and their orders + */ +function regenerate_plugin_list($pluginorder = FALSE) { +	$msg = 'regenerate_plugin_list() is (sorta) deprecated by elgg_generate_plugin_entities() and' +			. ' elgg_set_plugin_priorities().'; +	elgg_deprecated_notice($msg, 1.8); + +	// they're probably trying to set it? +	if ($pluginorder) { +		if (elgg_generate_plugin_entities()) { +			// sort the plugins by the index numerically since we used +			// weird indexes in the old system. +			ksort($pluginorder, SORT_NUMERIC); +			return elgg_set_plugin_priorities($pluginorder); +		} +		return false; +	} else { +		// they're probably trying to regenerate from disk? +		return elgg_generate_plugin_entities(); +	} +} + + +/** + * Loads plugins + * + * @deprecate 1.8 + * + * @return bool + */ +function load_plugins() { +	elgg_deprecated_notice('load_plugins() is deprecated by elgg_load_plugins()', 1.8); + +	return elgg_load_plugins(); +} + + +/** + * 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 + */ +function elgg_namespace_plugin_private_setting($type, $name, $id = null) { +	switch ($type) { +//		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/, 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.   * + * @since 1.8 + *   * @return string|false Plugin name, or false if no plugin name was called   */ -function get_plugin_name($mainfilename = false) { +function elgg_get_calling_plugin_id($mainfilename = false) {  	if (!$mainfilename) {  		if ($backtrace = debug_backtrace()) {  			foreach ($backtrace as $step) { @@ -254,31 +584,38 @@ function get_plugin_name($mainfilename = false) {  }  /** - * Load and parse a plugin manifest from a plugin XML file. + * 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).   * - * Example file: + * i.e., if the last plugin was in /mod/foobar/, get_plugin_name would return foo_bar.   * - *	<plugin_manifest> - *		<!-- Basic information --> - *		<field key="name" value="My Plugin" /> - *		<field key="description" value="My Plugin's concise description" /> - *		<field key="version" value="1.0" /> - *		<field key="category" value="theme" /> - *		<field key="category" value="bundled" /> - *		<field key="screenshot" value="path/relative/to/my_plugin.jpg" /> - *		<field key="screenshot" value="path/relative/to/my_plugin_2.jpg" /> + * @deprecated 1.8   * - *		<field key="author" value="Curverider Ltd" /> - *		<field key="website" value="http://www.elgg.org/" /> - *		<field key="copyright" value="(C) Curverider 2008-2010" /> - *		<field key="licence" value="GNU Public License version 2" /> - *	</plugin_manifest> + * @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 string $plugin Plugin name. + * @return string|false Plugin name, or false if no plugin name was called + */ +function get_plugin_name($mainfilename = false) { +	elgg_deprecated_notice('get_plugin_name() is deprecated by elgg_get_calling_plugin_id()', 1.8); + +	return elgg_get_calling_plugin_id($mainfilename); +} + +/** + * Load and parse a plugin manifest from a plugin XML file. + * + * @example plugins/manifest.xml Example 1.8-style manifest file. + * + * @deprecated 1.8   * + * @param string $plugin Plugin name.   * @return array of values   */  function load_plugin_manifest($plugin) { +	elgg_deprecated_notice('load_plugin_manifest() is deprecated by ElggPlugin->getManifest()', 1.8); +  	$xml_file = elgg_get_plugin_path() . "$plugin/manifest.xml";  	try { @@ -294,11 +631,14 @@ function load_plugin_manifest($plugin) {   * 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 string $manifest_elgg_version_string The build version (eg 2009010201). + * @deprecated 1.8   * + * @param string $manifest_elgg_version_string The build version (eg 2009010201).   * @return bool   */  function check_plugin_compatibility($manifest_elgg_version_string) { +	elgg_deprecated_notice('check_plugin_compatibility() is deprecated by ElggPlugin->canActivate()', 1.8); +  	$version = get_version();  	if (strpos($manifest_elgg_version_string, '.') === false) { @@ -327,6 +667,7 @@ function check_plugin_compatibility($manifest_elgg_version_string) {   * @param string $name A specific provided name to return. Requires $provide_type.   *   * @return array + * @since 1.8   */  function elgg_get_plugins_provides($type = null, $name = null) {  	static $provides = null; @@ -377,6 +718,7 @@ function elgg_get_plugins_provides($type = null, $name = null) {   * @param string $comparison The comparison operator to use in version_compare()   *   * @return bool + * @since 1.8   */  function elgg_check_plugins_provides($type, $name, $version = null, $comparison = 'ge') {  	if (!$provided = elgg_get_plugins_provides($type, $name)) { @@ -395,25 +737,33 @@ function elgg_check_plugins_provides($type, $name, $version = null, $comparison  /**   * Shorthand function for finding the plugin settings.   * - * @param string $plugin_name Optional plugin name, if not specified - *                            then it is detected from where you are calling from. + * @deprecated 1.8 + * + * @param string $plugin_id Optional plugin id, if not specified + *                          then it is detected from where you are calling.   *   * @return mixed   */ -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 find_plugin_settings($plugin_id = null) { +	elgg_deprecated_notice('find_plugin_setting() is deprecated by elgg_get_calling_plugin_entity() or elgg_get_plugin_from_id()', 1.8); +	if ($plugin_id) { +		return elgg_get_plugin_from_id($plugin_id); +	} else { +		return elgg_get_calling_plugin_entity();  	} +} -	if ($plugins) { -		foreach ($plugins as $plugin) { -			if (strcmp($plugin->title, $plugin_name) == 0) { -				return $plugin; -			} -		} +/** + * Returns the ElggPlugin entity of the last plugin called. + * + * @return mixed ElggPlugin or false + * @since 1.8 + */ +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; @@ -422,34 +772,41 @@ function find_plugin_settings($plugin_name = "") {  /**   * Find the plugin settings for a user.   * - * @param string $plugin_name Plugin name. - * @param int    $user_guid   The guid who's settings to retrieve. + * @param string $plugin_id Plugin name. + * @param int    $user_guid The guid who's settings to retrieve.   *   * @return array of settings in an associative array minus prefix.   */ -function find_plugin_usersettings($plugin_name = "", $user_guid = 0) { -	$plugin_name = sanitise_string($plugin_name); +function find_plugin_usersettings($plugin_id = null, $user_guid = 0) { +	$plugin_id = sanitise_string($plugin_id);  	$user_guid = (int)$user_guid; +	$db_prefix = get_config('db_prefix'); +	$ps_prefix = elgg_namespace_plugin_private_setting('user_setting', "$plugin_id:"); +	$ps_prefix_len = strlen($ps_prefix); -	if (!$plugin_name) { -		$plugin_name = get_plugin_name(); +	if (!$plugin_id) { +		$plugin_id = elgg_get_calling_plugin_id();  	}  	if ($user_guid == 0) {  		$user_guid = get_loggedin_userid();  	} -	// 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:"; +	// Get private settings for user +	$q = "SELECT * FROM {$db_prefix}private_settings +		WHERE entity_guid = $user_guid +		AND name LIKE '$ps_prefix$plugin_id'"; + +	$private_settings = get_data($q); +	if ($private_settings) {  		$return = new stdClass; -		foreach ($all_metadata as $key => $meta) { -			$name = substr($key, strlen($prefix)); -			$value = $meta; +		foreach ($private_settings as $setting) { +			$name = substr($setting->name, $ps_prefix_len); +			$value = $setting->value; -			if (strpos($key, $prefix) === 0) { +			// @todo why? +			if (strpos($key, $ps_prefix) === 0) {  				$return->$name = $value;  			}  		} @@ -463,21 +820,21 @@ function find_plugin_usersettings($plugin_name = "", $user_guid = 0) {  /**   * 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   */ -function set_plugin_usersetting($name, $value, $user_guid = 0, $plugin_name = "") { -	$plugin_name = sanitise_string($plugin_name); +function set_plugin_usersetting($name, $value, $user_guid = 0, $plugin_id = "") { +	$plugin_id = sanitise_string($plugin_id);  	$user_guid = (int)$user_guid;  	$name = sanitise_string($name); -	if (!$plugin_name) { -		$plugin_name = get_plugin_name(); +	if (!$plugin_id) { +		$plugin_id = elgg_get_calling_plugin_id();  	}  	$user = get_entity($user_guid); @@ -486,19 +843,17 @@ function set_plugin_usersetting($name, $value, $user_guid = 0, $plugin_name = ""  	}  	if (($user) && ($user instanceof ElggUser)) { -		$prefix = "plugin:settings:$plugin_name:$name"; -		//$user->$prefix = $value; -		//$user->save(); +		$name = elgg_namespace_plugin_private_setting('user_setting', "$plugin_id:$name");  		// Hook to validate setting  		$value = elgg_trigger_plugin_hook('plugin:usersetting', 'user', array(  			'user' => $user, -			'plugin' => $plugin_name, +			'plugin' => $plugin_id,  			'name' => $name,  			'value' => $value  		), $value); -		return set_private_setting($user->guid, $prefix, $value); +		return set_private_setting($user->guid, $name, $value);  	}  	return false; @@ -507,18 +862,18 @@ function set_plugin_usersetting($name, $value, $user_guid = 0, $plugin_name = ""  /**   * Clears a user-specific plugin setting   * - * @param str $name        Name of the plugin setting - * @param int $user_guid   Defaults to logged in user - * @param str $plugin_name Defaults to contextual plugin name + * @param str $name      Name of the plugin setting + * @param int $user_guid Defaults to logged in user + * @param str $plugin_id Defaults to contextual plugin name   *   * @return bool Success   */ -function clear_plugin_usersetting($name, $user_guid = 0, $plugin_name = '') { -	$plugin_name = sanitise_string($plugin_name); +function clear_plugin_usersetting($name, $user_guid = 0, $plugin_id = '') { +	$plugin_id = sanitise_string($plugin_id);  	$name = sanitise_string($name); -	if (!$plugin_name) { -		$plugin_name = get_plugin_name(); +	if (!$plugin_id) { +		$plugin_id = elgg_get_calling_plugin_id();  	}  	$user = get_entity((int) $user_guid); @@ -527,7 +882,7 @@ function clear_plugin_usersetting($name, $user_guid = 0, $plugin_name = '') {  	}  	if (($user) && ($user instanceof ElggUser)) { -		$prefix = "plugin:settings:$plugin_name:$name"; +		$prefix = elgg_namespace_plugin_private_setting('user_setting', "$plugin_id:$name");  		return remove_private_setting($user->getGUID(), $prefix);  	} @@ -538,20 +893,20 @@ function clear_plugin_usersetting($name, $user_guid = 0, $plugin_name = '') {  /**   * Get a user specific setting for a plugin.   * - * @param string $name        The name. - * @param int    $user_guid   Guid of owning user - * @param string $plugin_name Optional plugin name, if not specified + * @param string $name      The name. + * @param int    $user_guid Guid of owning user + * @param string $plugin_id Optional plugin name, if not specified   *                            then it is detected from where you are calling from.   *   * @return mixed   */ -function get_plugin_usersetting($name, $user_guid = 0, $plugin_name = "") { -	$plugin_name = sanitise_string($plugin_name); +function get_plugin_usersetting($name, $user_guid = 0, $plugin_id = "") { +	$plugin_id = sanitise_string($plugin_id);  	$user_guid = (int)$user_guid;  	$name = sanitise_string($name); -	if (!$plugin_name) { -		$plugin_name = get_plugin_name(); +	if (!$plugin_id) { +		$plugin_id = elgg_get_calling_plugin_id();  	}  	$user = get_entity($user_guid); @@ -560,8 +915,8 @@ function get_plugin_usersetting($name, $user_guid = 0, $plugin_name = "") {  	}  	if (($user) && ($user instanceof ElggUser)) { -		$prefix = "plugin:settings:$plugin_name:$name"; -		return get_private_setting($user->guid, $prefix); +		$name = elgg_namespace_plugin_private_setting('user_setting', "$plugin_id:$name"); +		return get_private_setting($user->guid, $name);  	}  	return false; @@ -570,143 +925,126 @@ function get_plugin_usersetting($name, $user_guid = 0, $plugin_name = "") {  /**   * 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 - 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 int|false   */ -function set_plugin_setting($name, $value, $plugin_name = "") { -	if (!$plugin_name) { -		$plugin_name = get_plugin_name(); +function 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 = elgg_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. + * @param string $plugin_id Optional plugin name, if not specified + *                          then it is detected from where you are calling from.   *   * @return mixed   */ -function get_plugin_setting($name, $plugin_name = "") { -	$plugin = find_plugin_settings($plugin_name); +function get_plugin_setting($name, $plugin_id = "") { +	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.   * - * @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. + * @param string $plugin_id Optional plugin name, if not specified + *                          then it is detected from where you are calling from.   *   * @return bool   */ -function clear_plugin_setting($name, $plugin_name = "") { -	$plugin = find_plugin_settings($plugin_name); +function clear_plugin_setting($name, $plugin_id = "") { +	if ($plugin_id) { +		$plugin = elgg_get_plugin_from_id($plugin_id); +	} else { +		$plugin = elgg_get_calling_plugin_entity(); +	} -	if ($plugin) { -		return remove_private_setting($plugin->guid, $name); +	if (!$plugin) { +		return false;  	} -	return FALSE; +	return $plugin->removeSetting($name);  }  /**   * Clear all plugin settings.   * - * @param string $plugin_name Optional plugin name, if not specified - *                            then it is detected from where you are calling from. + * @param string $plugin_id Optional plugin name, if not specified + *                          then it is detected from where you are calling from.   *   * @return bool   * @since 1.7.0   */ -function clear_all_plugin_settings($plugin_name = "") { -	$plugin = find_plugin_settings($plugin_name); +function clear_all_plugin_settings($plugin_id = "") { +	if ($plugin_id) { +		$plugin = elgg_get_plugin_from_id($plugin_id); +	} else { +		$plugin = elgg_get_calling_plugin_entity(); +	}  	if ($plugin) { -		return remove_all_private_settings($plugin->guid); +		$plugin->removeAllSettings();  	} -	return FALSE; +	return false;  }  /**   * Return an array of installed plugins.   * + * @deprecated 1.8 + *   * @param string $status any|enabled|disabled   * @return array   */ -function get_installed_plugins($status = 'any') { +function get_installed_plugins($status = 'all') {  	global $CONFIG; -	$installed_plugins = array(); +	elgg_deprecated_notice('get_installed_plugins() was deprecated by elgg_get_plugins()', 1.8); -	if (!empty($CONFIG->pluginspath)) { -		$plugins = get_plugin_list(); +	$plugins = elgg_get_plugins($status); -		foreach ($plugins as $mod) { -			// require manifest. -			if (!$manifest = load_plugin_manifest($mod)) { -				continue; -			} - -			$enabled = is_plugin_enabled($mod); - -			switch ($status) { -				case 'enabled': -					if ($enabled != true) { -						continue 2; -					} -					break; - -				case 'disabled': -					if ($enabled == true) { -						continue 2; -					} -					break; +	if (!$plugins) { +		return array(); +	} -				case 'any': -				default: -					break; -			} +	$installed_plugins = array(); -			$installed_plugins[$mod] = array(); -			$installed_plugins[$mod]['active'] = $enabled; -			$installed_plugins[$mod]['manifest'] = $manifest; +	foreach ($plugins as $plugin) { +		if (!$plugin->isValid()) { +			continue;  		} + +		$installed_plugins[$plugin->getID()] = array( +			'active' => $plugin->isActive(), +			'manifest' => $plugin->manifest->getManifest() +		);  	}  	return $installed_plugins; @@ -721,82 +1059,36 @@ function get_installed_plugins($status = 'any') {   * 		elgg_view_regenerate_simplecache();   *		elgg_filepath_cache_reset();   * + * @deprecated 1.8 + *   * @param string $plugin    The plugin name.   * @param int    $site_guid The site id, if not specified then this is detected.   *   * @return array   * @throws InvalidClassException   */ -function enable_plugin($plugin, $site_guid = 0) { -	global $CONFIG, $ENABLED_PLUGINS_CACHE; +function enable_plugin($plugin, $site_guid = null) { +	elgg_deprecated_notice('enable_plugin() was deprecated by ElggPlugin->activate()', 1.8);  	$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)) { -		$msg = elgg_echo('InvalidClassException:NotValidElggStar', array($site_guid, "ElggSite")); -		throw new InvalidClassException($msg); -	} - -	if (!$plugin_info = load_plugin_manifest($plugin)) { -		return FALSE; +	$site_guid = (int) $site_guid; +	if (!$site_guid) { +		$site = get_config('site'); +		$site_guid = $site->guid;  	} -	// getMetadata() doesn't return an array if only one plugin is enabled -	if ($enabled = $site->enabled_plugins) { -		if (!is_array($enabled)) { -			$enabled = array($enabled); -		} -	} else { -		$enabled = array(); +	try { +		$plugin = new ElggPlugin($plugin); +	} catch(Exception $e) { +		return false;  	} -	$enabled[] = $plugin; -	$enabled = array_unique($enabled); - -	if ($return = $site->setMetaData('enabled_plugins', $enabled)) { - -		// for other plugins that want to hook into this. -		$params = array('plugin' => $plugin, 'manifest' => $plugin_info); -		if ($return && !elgg_trigger_event('enable', 'plugin', $params)) { -			$return = FALSE; -		} - -		// for this plugin's on_enable -		if ($return && isset($plugin_info['on_enable'])) { -			// pull in the actual plugin's start so the on_enable function is callable -			// NB: this will not run re-run the init hooks! -			$start = "{$CONFIG->pluginspath}$plugin/start.php"; -			if (!file_exists($start) || !include($start)) { -				$return = FALSE; -			} - -			// need language files for the messages -			$translations = "{$CONFIG->pluginspath}$plugin/languages/"; -			register_translations($translations); -			if (!is_callable($plugin_info['on_enable'])) { -				$return = FALSE; -			} else { -				$on_enable = call_user_func($plugin_info['on_enable']); -				// allow null to mean "I don't care" like other subsystems -				$return = ($on_disable === FALSE) ? FALSE : TRUE; -			} -		} - -		// disable the plugin if the on_enable or trigger results failed -		if (!$return) { -			array_pop($enabled); -			$site->setMetaData('enabled_plugins', $enabled); -		} - -		$ENABLED_PLUGINS_CACHE = $enabled; +	if (!$plugin->canActivate($site_guid)) { +		return false;  	} -	return $return; +	return $plugin->activate($site_guid);  }  /** @@ -808,6 +1100,8 @@ function enable_plugin($plugin, $site_guid = 0) {   * 		elgg_view_regenerate_simplecache();   *		elgg_filepath_cache_reset();   * + * @deprecated 1.8 + *   * @param string $plugin    The plugin name.   * @param int    $site_guid The site id, if not specified then this is detected.   * @@ -815,118 +1109,53 @@ function enable_plugin($plugin, $site_guid = 0) {   * @throws InvalidClassException   */  function disable_plugin($plugin, $site_guid = 0) { -	global $CONFIG, $ENABLED_PLUGINS_CACHE; +	elgg_deprecated_notice('disable_plugin() was deprecated by ElggPlugin->deactivate()', 1.8);  	$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)) { -		$msg = elgg_echo('InvalidClassException:NotValidElggStar', array($site_guid, "ElggSite")); -		throw new InvalidClassException(); -	} -	if (!$plugin_info = load_plugin_manifest($plugin)) { -		return FALSE; -	} - -	// getMetadata() doesn't return an array if only one plugin is enabled -	if ($enabled = $site->enabled_plugins) { -		if (!is_array($enabled)) { -			$enabled = array($enabled); -		} -	} else { -		$enabled = array(); -	} - -	$old_enabled = $enabled; - -	// remove the disabled plugin from the array -	if (FALSE !== $i = array_search($plugin, $enabled)) { -		unset($enabled[$i]); +	$site_guid = (int) $site_guid; +	if (!$site_guid) { +		$site = get_config('site'); +		$site_guid = $site->guid;  	} -	// if we're unsetting all the plugins, this will return an empty array. -	// it will fail with FALSE, though. -	$return = (FALSE === $site->enabled_plugins = $enabled) ? FALSE : TRUE; - -	if ($return) { -		// for other plugins that want to hook into this. -		$params = array('plugin' => $plugin, 'manifest' => $plugin_info); -		if ($return && !elgg_trigger_event('disable', 'plugin', $params)) { -			$return = FALSE; -		} - -		// for this plugin's on_disable -		if ($return && isset($plugin_info['on_disable'])) { -			if (!is_callable($plugin_info['on_disable'])) { -				$return = FALSE; -			} else { -				$on_disable = call_user_func($plugin_info['on_disable']); -				// allow null to mean "I don't care" like other subsystems -				$return = ($on_disable === FALSE) ? FALSE : TRUE; -			} -		} - -		// disable the plugin if the on_enable or trigger results failed -		if (!$return) { -			$site->enabled_plugins = $old_enabled; -			$ENABLED_PLUGINS_CACHE = $old_enabled; -		} else { -			$ENABLED_PLUGINS_CACHE = $enabled; -		} +	try { +		$plugin = new ElggPlugin($plugin); +	} catch(Exception $e) { +		return false;  	} -	return $return; +	return $plugin->deactivate($site_guid);  }  /**   * Return whether a plugin is enabled or not.   * + * @deprecated 1.8 + *   * @param string $plugin    The plugin name.   * @param int    $site_guid The site id, if not specified then this is detected.   *   * @return bool - * @throws InvalidClassException   */  function is_plugin_enabled($plugin, $site_guid = 0) { -	global $CONFIG, $ENABLED_PLUGINS_CACHE; +	elgg_deprecated_notice('is_plugin_enabled() was deprecated by ElggPlugin->isActive()', 1.8); -	if (!file_exists($CONFIG->pluginspath . $plugin)) { -		return false; -	} +	$plugin = sanitise_string($plugin);  	$site_guid = (int) $site_guid; -	if ($site_guid == 0) { -		$site_guid = $CONFIG->site_guid; +	if (!$site_guid) { +		$site = get_config('site'); +		$site_guid = $site->guid;  	} -	if (!$ENABLED_PLUGINS_CACHE) { -		$site = get_entity($site_guid); -		if (!($site instanceof ElggSite)) { -			$msg = elgg_echo('InvalidClassException:NotValidElggStar', array($site_guid, "ElggSite")); -			throw new InvalidClassException($msg); -		} - -		$enabled_plugins = $site->enabled_plugins; -		if ($enabled_plugins && !is_array($enabled_plugins)) { -			$enabled_plugins = array($enabled_plugins); -		} -		$ENABLED_PLUGINS_CACHE = $enabled_plugins; -	} - -	if (is_array($ENABLED_PLUGINS_CACHE)) { -		foreach ($ENABLED_PLUGINS_CACHE as $e) { -			if ($e == $plugin) { -				return true; -			} -		} +	try { +		$plugin = new ElggPlugin($plugin); +	} catch(Exception $e) { +		return false;  	} -	return false; +	return $plugin->isActive($site_guid);  }  /** @@ -935,7 +1164,6 @@ function is_plugin_enabled($plugin, $site_guid = 0) {   *  @return void   */  function plugin_run_once() { -	// Register a class  	add_subtype("object", "plugin", "ElggPlugin");  } @@ -978,4 +1206,4 @@ function plugin_init() {  	elgg_register_action('admin/plugins/reorder', '', 'admin');  } -elgg_register_event_handler('init', 'system', 'plugin_init'); +elgg_register_event_handler('init', 'system', 'plugin_init');
\ No newline at end of file diff --git a/engine/lib/upgrades/2011010101.php b/engine/lib/upgrades/2011010101.php new file mode 100644 index 000000000..eac5810c4 --- /dev/null +++ b/engine/lib/upgrades/2011010101.php @@ -0,0 +1,75 @@ +<?php +/** + * Migrate plugins to the new system using ElggPlugin and private settings + */ + +$old_ia = elgg_set_ignore_access(true); + +$site = get_config('site'); +$old_plugin_order = unserialize($site->pluginorder); +$old_enabled_plugins = $site->enabled_plugins; + +$db_prefix = get_config('dbprefix'); +$plugin_subtype_id = get_subtype_id('object', 'plugin'); + +// easy one first: make sure the the site owns all plugin entities. +$q = "UPDATE {$db_prefix}entities e +	SET owner_guid = $site->guid, container_guid = $site->guid +	WHERE e.type = 'object' AND e.subtype = $plugin_subtype_id"; + +$r = update_data($q); + +// rewrite all plugin:setting:* to ELGG_PLUGIN_USER_SETTING_PREFIX . * +$q = "UPDATE {$db_prefix}private_settings +	SET name = replace(name, 'plugin:setting', '" . ELGG_PLUGIN_USER_SETTING_PREFIX . "') +	WHERE name LIKE 'plugin:setting:%'"; + +$r = update_data($q); + +// grab current plugin GUIDs to add a temp priority +$q = "SELECT * FROM {$db_prefix}entities e +	JOIN {$db_prefix}objects_entity oe ON e.guid = oe.guid +	WHERE e.type = 'object' AND e.subtype = $plugin_subtype_id"; + +$plugins = get_data($q); + +foreach ($plugins as $plugin) { +	$priority = elgg_namespace_plugin_private_setting('internal', 'priority'); +	set_private_setting($plugin->guid, $priority, 0); +} + +// force regenerating plugin entities +elgg_generate_plugin_entities(); + +// set the priorities for all plugins +// this function rewrites it to a normal index so use the current one. +elgg_set_plugin_priorities($old_plugin_order); + +// add relationships for enabled plugins +if ($old_enabled_plugins) { +	// they might only have one plugin enabled. +	if (!is_array($old_enabled_plugins)) { +		$old_enabled_plugins = array($old_enabled_plugins); +	} + +	// sometimes there were problems and you'd get 1000s of enabled plugins. +	$old_enabled_plugins = array_unique($old_enabled_plugins); + +	foreach ($old_enabled_plugins as $plugin_id) { +		$plugin = elgg_get_plugin_from_id($plugin_id); + +		if ($plugin) { +			$plugin->activate(); +		} +	} +} + +// invalidate caches +elgg_invalidate_simplecache(); +elgg_filepath_cache_reset(); + +// clean up. +remove_metadata($site->guid, 'pluginorder'); +remove_metadata($site->guid, 'enabled_plugins'); + +elgg_set_ignore_access($old_id);
\ No newline at end of file diff --git a/engine/tests/api/plugins.php b/engine/tests/api/plugins.php index c99609559..997d69fb7 100644 --- a/engine/tests/api/plugins.php +++ b/engine/tests/api/plugins.php @@ -100,11 +100,10 @@ class ElggCorePluginsAPITest extends ElggCoreUnitTest {  				array('type' => 'php_extension', 'name' => 'big_math', 'version' => 1.0)  			), -			'admin' => array( -				'on_enable' => 'setup_function', -				'on_disable' => 'teardown_function', -				'interface_type' => 'simple' -			) +			'on_activate' => array('setup_function'), +			'on_deactivate' => array('teardown_function'), +			'admin_interface' => 'simple', +			'activate_on_install' => true  		);  		$this->assertEqual($this->manifest18->getManifest(), $manifest_array); @@ -118,7 +117,8 @@ class ElggCorePluginsAPITest extends ElggCoreUnitTest {  			'website' => 'http://www.elgg.org/',  			'copyright' => '(C) Elgg 2010',  			'license' => 'GNU Public License version 2', -			'elgg_version' => '2009030702' +			'elgg_version' => '2009030702', +			'name' => 'Plugin Test 17',  		);  		$this->assertEqual($this->manifest17->getManifest(), $manifest_array); @@ -261,6 +261,22 @@ class ElggCorePluginsAPITest extends ElggCoreUnitTest {  		$this->assertEqual($this->manifest17->getConflicts(), array());  	} +	public function testElggPluginManifestGetOnActivate() { +		$this->assertEqual($this->manifest18->getOnActivate(), array('setup_function')); +	} + +	public function testElggPluginManifestGetOnDeactivate() { +		$this->assertEqual($this->manifest18->getOnDeactivate(), array('teardown_function')); +	} + +	public function testElggPluginManifestGetAdminInterface() { +		$this->assertEqual($this->manifest18->getAdminInterface(), 'simple'); +	} + +	public function testElggPluginManifestGetActivateOnInstall() { +		$this->assertEqual($this->manifest18->getActivateOnInstall(), true); +	} +  	// ElggPluginPackage  	public function testElggPluginPackageDetectIDFromPath() {  		$this->assertEqual($this->package18->getID(), 'plugin_18'); diff --git a/engine/tests/test_files/plugin_18/manifest.xml b/engine/tests/test_files/plugin_18/manifest.xml index 454a418f6..69166c89c 100644 --- a/engine/tests/test_files/plugin_18/manifest.xml +++ b/engine/tests/test_files/plugin_18/manifest.xml @@ -34,11 +34,10 @@  	<category>ServiceAPI</category> -	<admin> -		<on_enable>setup_function</on_enable> -		<on_disable>teardown_function</on_disable> -		<interface_type>simple</interface_type> -	</admin> +	<on_activate>setup_function</on_activate> +	<on_deactivate>teardown_function</on_deactivate> +	<admin_interface>simple</admin_interface> +	<activate_on_install>true</activate_on_install>  	<requires>  		<type>php_extension</type> @@ -94,4 +93,4 @@  		<version>1.0</version>  	</provides> -</plugin_manifest>
\ No newline at end of file +</plugin_manifest> | 
