diff options
-rw-r--r-- | engine/lib/export.php | 169 |
1 files changed, 149 insertions, 20 deletions
diff --git a/engine/lib/export.php b/engine/lib/export.php index 279d3e8a6..93c7dc129 100644 --- a/engine/lib/export.php +++ b/engine/lib/export.php @@ -61,12 +61,11 @@ class ImportException extends DataFormatException {} /** - * Open Data Definition (ODD) superclass. - * @package Elgg - * @subpackage Core + * @class ODDDocument ODD Document container. + * This class is used during import and export to construct. * @author Marcus Povey */ - abstract class ODD + class ODDDocument { /** * ODD Version @@ -76,6 +75,88 @@ private $ODDSupportedVersion = "1.0"; /** + * Elements of the document. + */ + private $elements; + + public function __construct(array $elements = NULL) + { + if ($elements) + $this->elements = $elements; + else + $this->elements = array(); + } + + /** + * Return the version of ODD being used. + * + * @return string + */ + public function getVersion() { return $this->ODDSupportedVersion; } + + public function addElement(ODD $element) { $this->elements[] = $element; } + public function addElements(array $elements) + { + foreach ($elements as $element) + $this->addElement($element); + } + + public function getElements() { return $this->elements; } + + /** + * Magic function to generate valid ODD XML for this item. + */ + public function __toString() + { + $xml = ""; + $namespaces = ""; + $elements_xml = ""; + + // Get XML and catalog namespaces + foreach ($this->elements as $element) + { + $elements_xml .= "$element"; + + // Lookup namespace and get prefix + $ns = $element->getNamespace(); + if (($ns) && (strpos($namespaces, $ns)===false)) + { + $prefix = register_odd_extension_namespace($ns); // cheating... will return a prefix no matter what. + $namespaces .= " xmlns:$prefix=\"$ns\""; + } + else + trigger_error("'".get_class($element)."' has no namespace attached.", E_USER_WARNING); + } + + // Output begin tag + $generated = date("r"); + $xml .= "<odd version=\"{$this->ODDSupportedVersion}\" generated=\"$generated\" $namespaces>\n"; + + // output elements + $xml .= $elements_xml; + + // Output end tag + $xml .= "</odd>\n"; + + return $xml; + } + } + + + /** + * Open Data Definition (ODD) superclass. + * @package Elgg + * @subpackage Core + * @author Marcus Povey + */ + abstract class ODD + { + /** + * Namespace defining the ODD extension being used, optional but highly recommended. + */ + private $namespace; + + /** * Attributes. */ private $attributes = array(); @@ -103,13 +184,8 @@ } public function setBody($value) { $this->body = $value; } public function getBody() { return $this->body; } - - /** - * Return the version of ODD being used. - * - * @return real - */ - public function getVersion() { return $this->ODDSupportedVersion; } + public function setNamespace($namespace) { $this->namespace = $namespace; } + public function getNamespace() { return $this->namespace; } /** * For serialisation, implement to return a string name of the tag eg "header" or "metadata". @@ -122,6 +198,11 @@ */ public function __toString() { + // Namespace mapping + $ns = ""; + if ($this->getNamespace()!="") + $ns = register_odd_extension_namespace($this->getNamespace()) . ":"; // Short way: if it has been registered already we'll get back a prefix, if not it'll generate one and return. + // Construct attributes $attr = ""; foreach ($this->attributes as $k => $v) @@ -132,9 +213,9 @@ $end = "/>"; if ($body!="") - $end = ">$body</$tag>"; + $end = ">$body</{$ns}{$tag}>"; - return "<$tag $attr" . $end . "\n"; + return "<{$ns}{$tag} $attr" . $end . "\n"; } } @@ -233,6 +314,59 @@ return $odd; } + /** ODD Namespaces & registered extension **/ + $ODD_EXTENSION_NAMESPACES = array(); + + /** + * This function registers a namespace prefix with a given extension. + * Use this function to register a friendly prefix against a namespace. Namespaces will + * still function if you don't use this function however this gives you the opportunity to + * register a more human readable name. + * + * @param string $extension_url The namespace URL as given in the extension spec. + * @param string $namespace_prefix The chosen prefix, if this is blank then one is generated. + * @return string The extension prefix to be used, either $namespace_prefix, an already registered prefix or a generated one. + */ + function register_odd_extension_namespace($extension_url, $namespace_prefix = "") + { + global $ODD_EXTENSION_NAMESPACES; + + if (isset($ODD_EXTENSION_NAMESPACES[$extension_url])) + return $ODD_EXTENSION_NAMESPACES[$extension_url]; + + if ($namespace_prefix == "") + { + do + { + $namespace_prefix = substr(strtolower(base64_encode(md5(mt_rand()))), 0, 8); + } + while ( + (array_key_exists($namespace_prefix, $ODD_EXTENSION_NAMESPACES)) || + (is_numeric($namespace_prefix[0])) + ); // TODO: Do this better, but i'm quite tired now... + } + + $ODD_EXTENSION_NAMESPACES[$extension_url] = $namespace_prefix; + + return $ODD_EXTENSION_NAMESPACES[$extension_url]; + } + + /** + * Get a named prefix. + * + * @param string $extension_url The namespace URL as given in the extension spec. + * @return mixed The prefix associated with the given extension or false; + */ + function get_odd_namespace_prefix($extension_url) + { + global $ODD_EXTENSION_NAMESPACES; + + if (isset($ODD_EXTENSION_NAMESPACES[$extension_url])) + return $ODD_EXTENSION_NAMESPACES[$extension_url]; + + return false; + } + /** Relationship verb mapping */ $ODD_RELATIONSHIP_VERBS = array(); @@ -401,14 +535,9 @@ // Sanity check if ((!is_array($to_be_serialised)) || (count($to_be_serialised)==0)) throw new ExportException("No such entity GUID:$guid"); - $output = "<odd>\n"; - - foreach ($to_be_serialised as $odd) - $output .= "$odd"; - - $output .= "</odd>\n"; + $odd = new ODDDocument($to_be_serialised); - return $output; + return "$odd"; } /** |