aboutsummaryrefslogtreecommitdiff
path: root/engine/classes
diff options
context:
space:
mode:
authorbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>2010-11-30 03:56:34 +0000
committerbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>2010-11-30 03:56:34 +0000
commit8173f672f06ad2783d3d0112e7b285d2240f488b (patch)
tree283496b227e083fb18ee628f9a6b8b40a0b24edb /engine/classes
parentcaef932790b72de1efa5b8ef2065dd3ca3b9eb5a (diff)
downloadelgg-8173f672f06ad2783d3d0112e7b285d2240f488b.tar.gz
elgg-8173f672f06ad2783d3d0112e7b285d2240f488b.tar.bz2
Refs #1986 #2170 #2225 Added ElggPluginManifest, ElggPluginManifestParser, and its parser classes for 1.7 and 1.8 style manifests. Changed load_plugin_manifest() to use new parser. Added initial unit tests.
git-svn-id: http://code.elgg.org/elgg/trunk@7481 36083f99-b078-4883-b0ff-0f9b5a30f544
Diffstat (limited to 'engine/classes')
-rw-r--r--engine/classes/ElggPlugin.php1
-rw-r--r--engine/classes/ElggPluginManifest.php287
-rw-r--r--engine/classes/ElggPluginManifestParser.php91
-rw-r--r--engine/classes/ElggPluginManifestParser17.php54
-rw-r--r--engine/classes/ElggPluginManifestParser18.php119
5 files changed, 552 insertions, 0 deletions
diff --git a/engine/classes/ElggPlugin.php b/engine/classes/ElggPlugin.php
index 76276181b..887eb667f 100644
--- a/engine/classes/ElggPlugin.php
+++ b/engine/classes/ElggPlugin.php
@@ -21,6 +21,7 @@ class ElggPlugin extends ElggObject {
$this->attributes['subtype'] = "plugin";
}
+
/**
* Get a value from private settings.
*
diff --git a/engine/classes/ElggPluginManifest.php b/engine/classes/ElggPluginManifest.php
new file mode 100644
index 000000000..395208c95
--- /dev/null
+++ b/engine/classes/ElggPluginManifest.php
@@ -0,0 +1,287 @@
+<?php
+/**
+ * Parses Elgg manifest.xml files.
+ *
+ * This requires an ElggPluginManifestParser class implementation
+ * as $this->parser.
+ *
+ * @package Elgg.Core
+ * @subpackage Plugins
+ */
+class ElggPluginManifest {
+
+ /**
+ * The parser object
+ */
+ protected $parser;
+
+ /**
+ * The API version of the manifest.
+ *
+ * @var int
+ */
+ protected $apiVersion;
+
+ /**
+ * The optional plugin id this manifest belongs to.
+ *
+ * @var string
+ */
+ protected $pluginID;
+
+ /**
+ * Load a manifest file, XmlElement or path to manifest.xml file
+ *
+ * @param mixed $manifest A string, XmlElement, or path of a manifest file.
+ * @param string $plugin_id Optional ID of the owning plugin. Used to
+ * fill in some values automatically.
+ */
+ public function __construct($manifest, $plugin_id = null) {
+ if ($plugin_id) {
+ $this->pluginID = $plugin_id;
+ }
+
+ // see if we need to construct the xml object.
+ if ($manifest instanceof XmlElement) {
+ $manifest_obj = $manifest;
+ } else {
+ if (substr(trim($manifest), 0, 1) == '<') {
+ // this is a string
+ $raw_xml = $manifest;
+ } elseif (is_readable($manifest)) {
+ // this is a file
+ $raw_xml = file_get_contents($manifest);
+ }
+
+ $manifest_obj = xml_to_object($raw_xml);
+ }
+
+ if (!$manifest_obj) {
+ 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'];
+ } else {
+ $this->apiVersion = 1.7;
+ }
+
+ switch ($this->apiVersion) {
+ case 1.8:
+ $this->parser = new ElggPluginManifestParser18($manifest_obj, $this);
+ break;
+
+ case 1.7:
+ $this->parser = new ElggPluginManifestParser17($manifest_obj, $this);
+ break;
+
+ default:
+ throw new PluginException(elgg_echo('PluginException:NoAvailableParser',
+ array($this->apiVersion, $this->getPluginID())));
+ break;
+ }
+
+ if (!$this->parser->parse()) {
+ throw new PluginException(elgg_echo('PluginException:ParserError',
+ array($this->apiVersion, $this->getPluginID())));
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the API version in use.
+ *
+ * @return int
+ */
+ public function getApiVersion() {
+ return $this->apiVersion;
+ }
+
+ /**
+ * Returns the plugin ID.
+ *
+ * @return string
+ */
+ public function getPluginID() {
+ if ($this->pluginID) {
+ return $this->pluginID;
+ } else {
+ return elgg_echo('unknown');
+ }
+ }
+
+ /**
+ * Returns the manifest array.
+ *
+ * Used for backward compatibility. Specific
+ * methods should be called instead.
+ *
+ * @return array
+ */
+ public function getManifest() {
+ 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;
+ }
+
+ /**
+ * Returns the plugin name
+ *
+ * @return string
+ */
+ public function getName() {
+ $name = $this->parser->getAttribute('name');
+
+ if (!$name && $this->pluginID) {
+ $name = ucwords(str_replace('_', ' ', $pluginID));
+ }
+
+ return $name;
+ }
+
+ /**
+ * Return the description
+ *
+ * @return string
+ */
+ public function getDescription() {
+ return $this->parser->getAttribute('description');
+ }
+
+ /**
+ * Return the short description
+ *
+ * @return string
+ */
+ public function getBlurb() {
+ $blurb = $this->parser->getAttribute('blurb');
+
+ if (!$blurb) {
+ $blurb = elgg_get_excerpt($this->getDescription());
+ }
+
+ return $blurb;
+ }
+
+ /**
+ * Returns the license
+ *
+ * @return sting
+ */
+ public function getLicense() {
+ return $this->parser->getAttribute('license');
+ }
+
+
+ /**
+ * Returns the version of the plugin.
+ *
+ * @return float
+ */
+ public function getVersion() {
+ return $this->parser->getAttribute('version');
+ }
+
+ /**
+ * Returns the plugin author.
+ *
+ * @return string
+ */
+ public function getAuthor() {
+ return $this->parser->getAttribute('author');
+ }
+
+ /**
+ * Return the copyright
+ *
+ * @return string
+ */
+ public function getCopyright() {
+ return $this->parser->getAttribute('copyright');
+ }
+
+ /**
+ * Return the website
+ *
+ * @return string
+ */
+ public function getWebsite() {
+ return $this->parser->getAttribute('website');
+ }
+
+ /**
+ * Return the categories listed for this plugin
+ *
+ * @return array
+ */
+ public function getCategories() {
+ $cats = $this->parser->getAttribute('categories');
+
+ if (!is_array($cats)) {
+ $cats = array();
+ }
+
+ return $cats;
+ }
+
+ /**
+ * Return the screenshots listed.
+ *
+ * @return array
+ */
+ public function getScreenshots() {
+ $ss = $this->parser->getAttribute('screenshots');
+
+ if (!is_array($ss)) {
+ $ss = array();
+ }
+
+ return $ss;
+ }
+
+ /**
+ * Return the list of provides by this plugin.
+ *
+ * @return array
+ */
+ public function getProvides() {
+ $provides = $this->parser->getAttribute('provides');
+
+ // always provide ourself if we can
+ if ($this->pluginID) {
+ $provides[] = array('name' => $this->getPluginID(), 'version' => $this->getVersion);
+ }
+
+ return $provides;
+ }
+} \ No newline at end of file
diff --git a/engine/classes/ElggPluginManifestParser.php b/engine/classes/ElggPluginManifestParser.php
new file mode 100644
index 000000000..0ce3e3024
--- /dev/null
+++ b/engine/classes/ElggPluginManifestParser.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Parent class for manifest parsers.
+ *
+ * @package Elgg.Core
+ * @subpackage Plugins
+ *
+ */
+abstract class ElggPluginManifestParser {
+ /**
+ * The XmlElement object
+ *
+ * @var XmlElement
+ */
+ protected $manifestObject;
+
+ /**
+ * The manifest array
+ *
+ * @var array
+ */
+ protected $manifest;
+
+ /**
+ * All valid manifest attributes with default values.
+ *
+ * @var array
+ */
+ protected $validAttributes;
+
+ /**
+ * The object we're doing parsing for.
+ *
+ * @var object
+ */
+ protected $caller;
+
+ /**
+ * Loads the manifest XML to be parsed.
+ *
+ * @param XmlElement $xml The Manifest XML to be parsed
+ * @param object $caller The object calling this parser.
+ */
+ public function __construct(XmlElement $xml, $caller) {
+ $this->manifestObject = $xml;
+ $this->caller = $caller;
+ }
+
+ /**
+ * Returns the manifest XML object
+ *
+ * @return XmlElement
+ */
+ public function getManifestObject() {
+ return $this->manifestObject;
+ }
+
+ /**
+ * Return the parsed manifest array
+ *
+ * @return array
+ */
+ public function getManifest() {
+ return $this->manifest;
+ }
+
+ /**
+ * Return an attribute in the manifest.
+ *
+ * @param string $name Attribute name
+ * @return mixed
+ */
+ public function getAttribute($name) {
+ if (array_key_exists($name, $this->validAttributes)) {
+ if (isset($this->manifest[$name])) {
+ return $this->manifest[$name];
+ } else {
+ return $this->validAttributes[$name];
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Parse the XML object into an array
+ *
+ * @return bool
+ */
+ abstract public function parse();
+} \ No newline at end of file
diff --git a/engine/classes/ElggPluginManifestParser17.php b/engine/classes/ElggPluginManifestParser17.php
new file mode 100644
index 000000000..49b91ef52
--- /dev/null
+++ b/engine/classes/ElggPluginManifestParser17.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Plugin manifest.xml parser for Elgg 1.7 and lower.
+ *
+ * @package Elgg.Core
+ * @subpackage Plugins
+ */
+class ElggPluginManifestParser17 extends ElggPluginManifestParser {
+ /**
+ * The valid top level attributes and defaults for a 1.7 manifest
+ */
+ protected $validAttributes = array(
+ 'author' => null,
+ 'version' => null,
+ 'description' => null,
+ 'website' => null,
+ 'copyright' => null,
+ 'license' => 'GNU Public License version 2',
+ 'elgg_version' => null,
+
+ // were never really used and not enforced in code.
+ 'requires' => null,
+ 'recommends' => null,
+ 'conflicts' => null
+ );
+
+ /**
+ * Parse a manifest object from 1.7 or earlier.
+ *
+ * @return void
+ */
+ public function parse() {
+ foreach ($this->manifestObject->children as $element) {
+ $key = $element->attributes['key'];
+ $value = $element->attributes['value'];
+
+ // create arrays if multiple fields are set
+ if (array_key_exists($key, $elements)) {
+ if (!is_array($elements[$key])) {
+ $orig = $elements[$key];
+ $elements[$key] = array($orig);
+ }
+
+ $elements[$key][] = $value;
+ } else {
+ $elements[$key] = $value;
+ }
+ }
+
+ $this->manifest = $elements;
+
+ return true;
+ }
+} \ No newline at end of file
diff --git a/engine/classes/ElggPluginManifestParser18.php b/engine/classes/ElggPluginManifestParser18.php
new file mode 100644
index 000000000..1d4e9daed
--- /dev/null
+++ b/engine/classes/ElggPluginManifestParser18.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * Plugin manifest.xml parser for Elgg 1.8 and above.
+ *
+ * @package Elgg.Core
+ * @subpackage Plugins
+ */
+class ElggPluginManifestParser18 extends ElggPluginManifestParser {
+ /**
+ * The valid top level attributes and defaults for a 1.8 manifest array.
+ *
+ * @var array
+ */
+ protected $validAttributes = array(
+ 'name' => null,
+ 'author' => null,
+ 'version' => null,
+ 'blurb' => null,
+ 'description' => null,
+ 'website' => null,
+ 'copyright' => null,
+ 'license' => 'GNU Public License version 2',
+ 'depends' => array(),
+ 'screenshots' => array(),
+ 'conflicts' => array(),
+ 'provides' => array(),
+ 'admin' => array(
+ 'on_enable' => null,
+ 'on_disable' => null,
+ 'interface_type' => 'advanced'
+ )
+ );
+
+ /**
+ * Required attributes for a valid 1.8 manifest
+ *
+ * @var array
+ */
+ protected $requiredAttributes = array(
+ 'name', 'author', 'version', 'description', 'depends'
+ );
+
+ /**
+ * Parse a manifest object from 1.8 and later
+ *
+ * @return void
+ */
+ public function parse() {
+ $parsed = array();
+ foreach ($this->manifestObject->children as $element) {
+ switch ($element->name) {
+ // single elements
+ // translatable
+ case 'blurb':
+ case 'description':
+ $element->content = elgg_echo($element->content);
+
+ case 'name':
+ case 'author':
+ case 'version':
+ case 'website':
+ case 'copyright':
+ case 'license':
+ $parsed[$element->name] = $element->content;
+ break;
+
+ // arrays
+ case 'screenshot':
+ if (isset($element->attributes['description'])) {
+ $description = elgg_echo($element->attributes['description']);
+ }
+ $parsed['screenshots'][] = array(
+ 'description' => $description,
+ 'path' => $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;
+ }
+
+ break;
+
+ case 'provides':
+ case 'conflicts':
+ case 'depends':
+ if (!isset($element->children)) {
+ return false;
+ }
+
+ $info = array();
+ foreach ($element->children as $child_element) {
+ $info[$child_element->name] = $child_element->content;
+ }
+
+ $parsed[$element->name][] = $info;
+ break;
+ }
+ }
+
+ // check we have all the required fields
+ foreach ($this->requiredAttributes as $attr) {
+ if (!array_key_exists($attr, $parsed)) {
+ throw new PluginException(elgg_echo('PluginException:ParserErrorMissingRequiredAttribute',
+ array($attr, $this->caller->getPluginID())));
+ }
+ }
+
+ $this->manifest = $parsed;
+
+ return true;
+ }
+} \ No newline at end of file