diff options
Diffstat (limited to 'engine/classes/ElggPluginManifest.php')
| -rw-r--r-- | engine/classes/ElggPluginManifest.php | 485 |
1 files changed, 427 insertions, 58 deletions
diff --git a/engine/classes/ElggPluginManifest.php b/engine/classes/ElggPluginManifest.php index 395208c95..6912c2b08 100644 --- a/engine/classes/ElggPluginManifest.php +++ b/engine/classes/ElggPluginManifest.php @@ -2,11 +2,18 @@ /** * Parses Elgg manifest.xml files. * + * Normalizes the values from the ElggManifestParser object. + * * This requires an ElggPluginManifestParser class implementation * as $this->parser. * + * To add new parser versions, name them ElggPluginManifestParserXX + * where XX is the version specified in the top-level <plugin_manifest> + * tag's XML namespace. + * * @package Elgg.Core * @subpackage Plugins + * @since 1.8 */ class ElggPluginManifest { @@ -16,6 +23,87 @@ class ElggPluginManifest { protected $parser; /** + * The root for plugin manifest namespaces. + * This is in the format http://www.elgg.org/plugin_manifest/<version> + */ + protected $namespace_root = 'http://www.elgg.org/plugin_manifest/'; + + /** + * The expected structure of a plugins requires element + */ + private $depsStructPlugin = array( + 'type' => '', + 'name' => '', + 'version' => '', + 'comparison' => 'ge' + ); + + /** + * The expected structure of a priority element + */ + private $depsStructPriority = array( + 'type' => '', + 'priority' => '', + 'plugin' => '' + ); + + /* + * The expected structure of elgg_version and elgg_release requires element + */ + private $depsStructElgg = array( + 'type' => '', + 'version' => '', + 'comparison' => 'ge' + ); + + /** + * The expected structure of a requires php_ini dependency element + */ + private $depsStructPhpIni = array( + 'type' => '', + 'name' => '', + 'value' => '', + 'comparison' => '=' + ); + + /** + * The expected structure of a requires php_extension dependency element + */ + private $depsStructPhpExtension = array( + 'type' => '', + 'name' => '', + 'version' => '', + 'comparison' => '=' + ); + + /** + * The expected structure of a conflicts depedency element + */ + private $depsConflictsStruct = array( + 'type' => '', + 'name' => '', + 'version' => '', + 'comparison' => '=' + ); + + /** + * The expected structure of a provides dependency element. + */ + private $depsProvidesStruct = array( + 'type' => '', + 'name' => '', + 'version' => '' + ); + + /** + * The expected structure of a screenshot element + */ + private $screenshotStruct = array( + 'description' => '', + 'path' => '' + ); + + /** * The API version of the manifest. * * @var int @@ -42,13 +130,13 @@ class ElggPluginManifest { } // see if we need to construct the xml object. - if ($manifest instanceof XmlElement) { + if ($manifest instanceof ElggXMLElement) { $manifest_obj = $manifest; } else { if (substr(trim($manifest), 0, 1) == '<') { // this is a string $raw_xml = $manifest; - } elseif (is_readable($manifest)) { + } elseif (is_file($manifest)) { // this is a file $raw_xml = file_get_contents($manifest); } @@ -57,29 +145,34 @@ class ElggPluginManifest { } if (!$manifest_obj) { - throw new PluginException(elgg_echo('PluginException:InvalidManifest', array($this->getPluginID()))); + throw new PluginException(elgg_echo('PluginException:InvalidManifest', + array($this->getPluginID()))); } // set manifest api version - if (isset($manifest_obj->attributes['version'])) { - $this->apiVersion = (float)$manifest_obj->attributes['version']; + if (isset($manifest_obj->attributes['xmlns'])) { + $namespace = $manifest_obj->attributes['xmlns']; + $version = str_replace($this->namespace_root, '', $namespace); } else { - $this->apiVersion = 1.7; + $version = 1.7; } - switch ($this->apiVersion) { - case 1.8: - $this->parser = new ElggPluginManifestParser18($manifest_obj, $this); - break; + $this->apiVersion = $version; - case 1.7: - $this->parser = new ElggPluginManifestParser17($manifest_obj, $this); - break; + $parser_class_name = 'ElggPluginManifestParser' . str_replace('.', '', $this->apiVersion); - default: - throw new PluginException(elgg_echo('PluginException:NoAvailableParser', + // @todo currently the autoloader freaks out if a class doesn't exist. + try { + $class_exists = class_exists($parser_class_name); + } catch (Exception $e) { + $class_exists = false; + } + + if ($class_exists) { + $this->parser = new $parser_class_name($manifest_obj, $this); + } else { + throw new PluginException(elgg_echo('PluginException:NoAvailableParser', array($this->apiVersion, $this->getPluginID()))); - break; } if (!$this->parser->parse()) { @@ -124,35 +217,9 @@ class ElggPluginManifest { return $this->parser->getManifest(); } - /** - * Returns the dependencies listed. - * - * @return array - */ - public function getDepends() { - $deps = $this->parser->getAttribute('depends'); - - if (!is_array($deps)) { - $deps = array(); - } - - return $deps; - } - - /** - * Returns the conflicts listed - * - * @return array - */ - public function getConflicts() { - $conflicts = $this->parser->getAttribute('conflicts'); - - if (!is_array($conflicts)) { - $conflicts = array(); - } - - return $conflicts; - } + /*************************************** + * Parsed and Normalized Manifest Data * + ***************************************/ /** * Returns the plugin name @@ -163,12 +230,13 @@ class ElggPluginManifest { $name = $this->parser->getAttribute('name'); if (!$name && $this->pluginID) { - $name = ucwords(str_replace('_', ' ', $pluginID)); + $name = ucwords(str_replace('_', ' ', $this->pluginID)); } return $name; } + /** * Return the description * @@ -196,12 +264,44 @@ class ElggPluginManifest { /** * Returns the license * - * @return sting + * @return string */ public function getLicense() { - return $this->parser->getAttribute('license'); + // license vs licence. Use license. + $en_us = $this->parser->getAttribute('license'); + if ($en_us) { + return $en_us; + } else { + return $this->parser->getAttribute('licence'); + } } + /** + * Returns the repository url + * + * @return string + */ + public function getRepositoryURL() { + return $this->parser->getAttribute('repository'); + } + + /** + * Returns the bug tracker page + * + * @return string + */ + public function getBugTrackerURL() { + return $this->parser->getAttribute('bugtracker'); + } + + /** + * Returns the donations page + * + * @return string + */ + public function getDonationsPageURL() { + return $this->parser->getAttribute('donations'); + } /** * Returns the version of the plugin. @@ -245,12 +345,26 @@ class ElggPluginManifest { * @return array */ public function getCategories() { - $cats = $this->parser->getAttribute('categories'); - - if (!is_array($cats)) { + $bundled_plugins = array('blog', 'bookmarks', 'categories', + 'custom_index', 'dashboard', 'developers', 'diagnostics', + 'embed', 'externalpages', 'file', 'garbagecollector', + 'groups', 'htmlawed', 'invitefriends', 'likes', + 'logbrowser', 'logrotate', 'members', 'messageboard', + 'messages', 'notifications', 'oauth_api', 'pages', 'profile', + 'reportedcontent', 'search', 'tagcloud', 'thewire', 'tinymce', + 'twitter', 'twitter_api', 'uservalidationbyemail', 'zaudio', + ); + + $cats = $this->parser->getAttribute('category'); + + if (!$cats) { $cats = array(); } + if (in_array('bundled', $cats) && !in_array($this->getPluginID(), $bundled_plugins)) { + unset($cats[array_search('bundled', $cats)]); + } + return $cats; } @@ -260,13 +374,18 @@ class ElggPluginManifest { * @return array */ public function getScreenshots() { - $ss = $this->parser->getAttribute('screenshots'); + $ss = $this->parser->getAttribute('screenshot'); - if (!is_array($ss)) { + if (!$ss) { $ss = array(); } - return $ss; + $normalized = array(); + foreach ($ss as $s) { + $normalized[] = $this->buildStruct($this->screenshotStruct, $s); + } + + return $normalized; } /** @@ -275,13 +394,263 @@ class ElggPluginManifest { * @return array */ public function getProvides() { - $provides = $this->parser->getAttribute('provides'); + // normalize for 1.7 + if ($this->getApiVersion() < 1.8) { + $provides = array(); + } else { + $provides = $this->parser->getAttribute('provides'); + } + + if (!$provides) { + $provides = array(); + } // always provide ourself if we can if ($this->pluginID) { - $provides[] = array('name' => $this->getPluginID(), 'version' => $this->getVersion); + $provides[] = array( + 'type' => 'plugin', + 'name' => $this->getPluginID(), + 'version' => $this->getVersion() + ); } - return $provides; + $normalized = array(); + foreach ($provides as $provide) { + $normalized[] = $this->buildStruct($this->depsProvidesStruct, $provide); + } + + return $normalized; + } + + /** + * Returns the dependencies listed. + * + * @return array + */ + public function getRequires() { + // rewrite the 1.7 style elgg_version as a real requires. + if ($this->apiVersion < 1.8) { + $elgg_version = $this->parser->getAttribute('elgg_version'); + if ($elgg_version) { + $reqs = array( + array( + 'type' => 'elgg_version', + 'version' => $elgg_version, + 'comparison' => 'ge' + ) + ); + } else { + $reqs = array(); + } + } else { + $reqs = $this->parser->getAttribute('requires'); + } + + if (!$reqs) { + $reqs = array(); + } + + $normalized = array(); + foreach ($reqs as $req) { + $normalized[] = $this->normalizeDep($req); + } + + return $normalized; + } + + /** + * Returns the suggests elements. + * + * @return array + */ + public function getSuggests() { + $suggests = $this->parser->getAttribute('suggests'); + + if (!$suggests) { + $suggests = array(); + } + + $normalized = array(); + foreach ($suggests as $suggest) { + $normalized[] = $this->normalizeDep($suggest); + } + + return $normalized; + } + + /** + * Normalizes a dependency array using the defined structs. + * Can be used with either requires or suggests. + * + * @param array $dep A dependency array. + * @return array The normalized deps array. + */ + private function normalizeDep($dep) { + switch ($dep['type']) { + case 'elgg_version': + case 'elgg_release': + $struct = $this->depsStructElgg; + break; + + case 'plugin': + $struct = $this->depsStructPlugin; + break; + + case 'priority': + $struct = $this->depsStructPriority; + break; + + case 'php_extension': + $struct = $this->depsStructPhpExtension; + break; + + case 'php_ini': + $struct = $this->depsStructPhpIni; + + // also normalize boolean values + if (isset($dep['value'])) { + switch (strtolower($dep['value'])) { + case 'yes': + case 'true': + case 'on': + case 1: + $dep['value'] = 1; + break; + + case 'no': + case 'false': + case 'off': + case 0: + case '': + $dep['value'] = 0; + break; + } + } + break; + default: + // unrecognized so we just return the raw dependency + return $dep; + } + + $normalized_dep = $this->buildStruct($struct, $dep); + + // normalize comparison operators + if (isset($normalized_dep['comparison'])) { + switch ($normalized_dep['comparison']) { + case '<': + $normalized_dep['comparison'] = 'lt'; + break; + + case '<=': + $normalized_dep['comparison'] = 'le'; + break; + + case '>': + $normalized_dep['comparison'] = 'gt'; + break; + + case '>=': + $normalized_dep['comparison'] = 'ge'; + break; + + case '==': + case 'eq': + $normalized_dep['comparison'] = '='; + break; + + case '<>': + case 'ne': + $normalized_dep['comparison'] = '!='; + break; + } + } + + return $normalized_dep; + } + + /** + * Returns the conflicts listed + * + * @return array + */ + public function getConflicts() { + // normalize for 1.7 + if ($this->getApiVersion() < 1.8) { + $conflicts = array(); + } else { + $conflicts = $this->parser->getAttribute('conflicts'); + } + + if (!$conflicts) { + $conflicts = array(); + } + + $normalized = array(); + + foreach ($conflicts as $conflict) { + $normalized[] = $this->buildStruct($this->depsConflictsStruct, $conflict); + } + + return $normalized; + } + + /** + * Should this plugin be activated when Elgg is installed + * + * @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. + * @param array $array The array + * + * @return array + */ + protected function buildStruct(array $struct, array $array) { + $return = array(); + + foreach ($struct as $index => $default) { + $return[$index] = elgg_extract($index, $array, $default); + } + + return $return; + } + + /** + * Returns a category's friendly name. This can be localized by + * defining the string 'admin:plugins:category:<category>'. If no + * localization is found, returns the category with _ and - converted to ' ' + * and then ucwords()'d. + * + * @param str $category The category as defined in the manifest. + * @return str A human-readable category + */ + static public function getFriendlyCategory($category) { + $cat_raw_string = "admin:plugins:category:$category"; + $cat_display_string = elgg_echo($cat_raw_string); + if ($cat_display_string == $cat_raw_string) { + $category = str_replace(array('-', '_'), ' ', $category); + $cat_display_string = ucwords($category); + } + return $cat_display_string; } -}
\ No newline at end of file +} |
