diff options
Diffstat (limited to 'engine/lib/export.php')
| -rw-r--r-- | engine/lib/export.php | 650 |
1 files changed, 208 insertions, 442 deletions
diff --git a/engine/lib/export.php b/engine/lib/export.php index a578b041e..ecc894e63 100644 --- a/engine/lib/export.php +++ b/engine/lib/export.php @@ -1,457 +1,223 @@ <?php - /** - * Elgg Data import export functionality. - * - * @package Elgg - * @subpackage Core - * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2 - * @author Marcus Povey - * @copyright Curverider Ltd 2008 - * @link http://elgg.org/ - */ - - /** - * Define an interface for all exportable objects. - * - * @package Elgg - * @subpackage Core - * @author Marcus Povey - */ - interface Exportable - { - /** - * This must take the contents of the object and convert it to exportable class(es). - * @return object or array of objects. - */ - public function export(); - } - - /** - * Define an interface for all importable objects. - * @author Marcus Povey - */ - interface Importable - { - /** - * Accepts an array of data to import, this data is parsed from the XML produced by export. - * The function should return the constructed object data, or NULL. - * - * @param ODD $data - * @return bool - * @throws ImportException if there was a critical error importing data. - */ - public function import(ODD $data); - } +/** + * Elgg Data import export functionality. + * + * @package Elgg.Core + * @subpackage DataModel.Export + */ - /** - * Export exception - * - * @package Elgg - * @subpackage Exceptions - * - */ - class ExportException extends DataFormatException {} - - /** - * Import exception - * - * @package Elgg - * @subpackage Exceptions - */ - class ImportException extends DataFormatException {} - - /** - * Open Data Definition (ODD) superclass. - * @package Elgg - * @subpackage Core - * @author Marcus Povey - */ - abstract class ODD - { - /** - * ODD Version - * - * @var string - */ - private $ODDSupportedVersion = "1.0"; - - /** - * Attributes. - */ - private $attributes = array(); - - /** - * Optional body. - */ - private $body; - - /** - * Construct an ODD document with initial values. - */ - public function __construct() - { - $this->body = ""; - } - - public function setAttribute($key, $value) { $this->attributes[$key] = $value; } - public function getAttribute($key) - { - if (isset($this->attributes[$key])) - return $this->attributes[$key]; - - return NULL; - } - 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; } - - /** - * For serialisation, implement to return a string name of the tag eg "header" or "metadata". - * @return string - */ - abstract protected function getTagName(); - - /** - * Magic function to generate valid ODD XML for this item. - */ - public function __toString() - { - // Construct attributes - $attr = ""; - foreach ($this->attributes as $k => $v) - $attr .= ($v!="") ? "$k=\"$v\" " : ""; - - $body = $this->getBody(); - $tag = $this->getTagName(); - - $end = "/>"; - if ($body!="") - $end = ">$body</$tag>"; - - return "<$tag $attr" . $end . "\n"; - } - } - - /** - * ODD Header class. - * @package Elgg - * @subpackage Core - * @author Marcus Povey - */ - class ODDHeader extends ODD - { - - function __construct($extension = "SN1.0") - { - parent::__construct(); - - $this->setAttribute('version', $this->getVersion()); - $this->setAttribute('extension', $extension); - } - - protected function getTagName() { return "header"; } - } - - /** - * ODD Entity class. - * @package Elgg - * @subpackage Core - * @author Marcus Povey - */ - class ODDEntity extends ODD - { - function __construct($uuid, $class, $subclass = "") - { - parent::__construct(); - - $this->setAttribute('uuid', $uuid); - $this->setAttribute('class', $class); - $this->setAttribute('subclass', $subclass); - } - - protected function getTagName() { return "entity"; } - } - - /** - * ODD Metadata class. - * @package Elgg - * @subpackage Core - * @author Marcus Povey - */ - class ODDMetaData extends ODD - { - function __construct($uuid, $entity_uuid, $name, $value, $type = "", $owner_uuid = "") - { - parent::__construct(); - - $this->setAttribute('uuid', $uuid); - $this->setAttribute('entity_uuid', $entity_uuid); - $this->setAttribute('name', $name); - $this->setAttribute('type', $type); - $this->setAttribute('owner_uuid', $owner_uuid); - $this->setBody($value); - } - - protected function getTagName() { return "metadata"; } - } - - /** - * ODD Relationship class. - * @package Elgg - * @subpackage Core - * @author Marcus Povey - */ - class ODDRelationship extends ODD - { - function __construct($uuid1, $verb, $uuid2) - { - parent::__construct(); - - $this->setAttribute('uuid1', $uuid1); - $this->setAttribute('verb', $verb); - $this->setAttribute('uuid2', $uuid2); - } - - protected function getTagName() { return "relationship"; } - } - - /** - * Attempt to construct an ODD object out of a XmlElement or sub-elements. - * - * @param XmlElement $element The element(s) - * @return mixed An ODD object if the element can be handled, or false. - */ - function ODD_factory(XmlElement $element) - { - $name = $element->name; - $odd = false; - - switch ($name) - { - case 'entity' : $odd = new ODDEntity("","",""); break; - case 'metadata' : $odd = new ODDMetaData("","","",""); break; - case 'relationship' : $odd = new ODDRelationship("","",""); break; - } - - // Now populate values - if ($odd) - { - // Attributes - foreach ($element->attributes as $k => $v) - $odd->setAttribute($k,$v); - - // Body - $odd->setBody($element->content); +/** + * Get a UUID from a given object. + * + * @param mixed $object The object either an ElggEntity, ElggRelationship or ElggExtender + * + * @return string|false the UUID or false + */ +function get_uuid_from_object($object) { + if ($object instanceof ElggEntity) { + return guid_to_uuid($object->guid); + } else if ($object instanceof ElggExtender) { + $type = $object->type; + if ($type == 'volatile') { + $uuid = guid_to_uuid($object->entity_guid) . $type . "/{$object->name}/"; + } else { + $uuid = guid_to_uuid($object->entity_guid) . $type . "/{$object->id}/"; } - - return $odd; - } - - /** Relationship verb mapping */ - $ODD_RELATIONSHIP_VERBS = array(); - - /** - * This function provides a mapping between entity relationships and ODD relationship verbs. - * @param string $relationship The relationship as stored in the database, eg "friend" or "member of" - * @param string $verb The verb, eg "friends" or "joins" - */ - function register_odd_relationship_mapping($relationship, $verb) - { - global $ODD_RELATIONSHIP_VERBS; - - $ODD_RELATIONSHIP_VERBS[$relationship] = $verb; - } - - /** - * Return a mapping for relationship to a pre-registered ODD verb, or false. - * @param string $relationship The relationship - */ - function get_verb_from_relationship($relationship) - { - global $ODD_RELATIONSHIP_VERBS; - - if (isset($ODD_RELATIONSHIP_VERBS[$relationship])) - return $ODD_RELATIONSHIP_VERBS[$relationship]; - - return false; + + return $uuid; + } else if ($object instanceof ElggRelationship) { + return guid_to_uuid($object->guid_one) . "relationship/{$object->id}/"; } - - /** - * Return the relationship registered with a given verb, or false. - * @param string $verb The verb. - */ - function get_relationship_from_verb($verb) - { - global $ODD_RELATIONSHIP_VERBS; - - foreach ($ODD_RELATIONSHIP_VERBS as $k => $v) - if ($v == $verb) return $k; - - return false; + + return false; +} + +/** + * Generate a UUID from a given GUID. + * + * @param int $guid The GUID of an object. + * + * @return string + */ +function guid_to_uuid($guid) { + return elgg_get_site_url() . "export/opendd/$guid/"; +} + +/** + * Test to see if a given uuid is for this domain, returning true if so. + * + * @param string $uuid A unique ID + * + * @return bool + */ +function is_uuid_this_domain($uuid) { + if (strpos($uuid, elgg_get_site_url()) === 0) { + return true; } - - /** - * Generate a UUID from a given GUID. - * - * @param int $guid The GUID of an object. - */ - function guid_to_uuid($guid) - { - global $CONFIG; - - return $CONFIG->wwwroot . "odd/$guid/"; + + return false; +} + +/** + * This function attempts to retrieve a previously imported entity via its UUID. + * + * @param string $uuid A unique ID + * + * @return ElggEntity|false + */ +function get_entity_from_uuid($uuid) { + $uuid = sanitise_string($uuid); + + $options = array('metadata_name' => 'import_uuid', 'metadata_value' => $uuid); + $entities = elgg_get_entities_from_metadata($options); + + if ($entities) { + return $entities[0]; } - - /** - * Test to see if a given uuid is for this domain, returning true if so. - * @param $uuid - * @return bool - */ - function is_uuid_this_domain($uuid) - { - global $CONFIG; - - if (strpos($uuid, $CONFIG->wwwroot) === 0) + + return false; +} + +/** + * Tag a previously created guid with the uuid it was imported on. + * + * @param int $guid A GUID + * @param string $uuid A Unique ID + * + * @return bool + */ +function add_uuid_to_guid($guid, $uuid) { + $guid = (int)$guid; + $uuid = sanitise_string($uuid); + + $result = create_metadata($guid, "import_uuid", $uuid); + return (bool)$result; +} + + +$IMPORTED_DATA = array(); +$IMPORTED_OBJECT_COUNTER = 0; + +/** + * This function processes an element, passing elements to the plugin stack to see if someone will + * process it. + * + * If nobody processes the top level element, the sub level elements are processed. + * + * @param ODD $odd The odd element to process + * + * @return bool + * @access private + */ +function _process_element(ODD $odd) { + global $IMPORTED_DATA, $IMPORTED_OBJECT_COUNTER; + + // See if anyone handles this element, return true if it is. + $to_be_serialised = null; + if ($odd) { + $handled = elgg_trigger_plugin_hook("import", "all", array("element" => $odd), $to_be_serialised); + + // If not, then see if any of its sub elements are handled + if ($handled) { + // Increment validation counter + $IMPORTED_OBJECT_COUNTER ++; + // Return the constructed object + $IMPORTED_DATA[] = $handled; + return true; - - return false; - } - - /** - * This function attempts to retrieve a previously imported entity via its UUID. - * - * @param $uuid - */ - function get_entity_from_uuid($uuid) - { - $uuid = sanitise_string($uuid); - - $entities = get_entities_from_metadata("import_uuid", $uuid); - - if ($entities) - return $entities[0]; - - return false; + } } - - /** - * Tag a previously created guid with the uuid it was imported on. - * - * @param int $guid - * @param string $uuid - */ - function add_uuid_to_guid($guid, $uuid) - { - $guid = (int)$guid; - $uuid = sanitise_string($uuid); - - return create_metadata($guid, "import_uuid", $uuid); + + return false; +} + +/** + * Exports an entity as an array + * + * @param int $guid Entity GUID + * + * @return array + * @throws ExportException + * @access private + */ +function exportAsArray($guid) { + $guid = (int)$guid; + + // Trigger a hook to + $to_be_serialised = elgg_trigger_plugin_hook("export", "all", array("guid" => $guid), array()); + + // Sanity check + if ((!is_array($to_be_serialised)) || (count($to_be_serialised) == 0)) { + throw new ExportException(elgg_echo('ExportException:NoSuchEntity', array($guid))); } - - + + return $to_be_serialised; +} + +/** + * Export a GUID. + * + * This function exports a GUID and all information related to it in an XML format. + * + * This function makes use of the "serialise" plugin hook, which is passed an array to which plugins + * should add data to be serialised to. + * + * @param int $guid The GUID. + * + * @return string XML + * @see ElggEntity for an example of its usage. + * @access private + */ +function export($guid) { + $odd = new ODDDocument(exportAsArray($guid)); + + return ODD_Export($odd); +} + +/** + * Import an XML serialisation of an object. + * This will make a best attempt at importing a given xml doc. + * + * @param string $xml XML string + * + * @return bool + * @throws ImportException if there was a problem importing the data. + * @access private + */ +function import($xml) { + global $IMPORTED_DATA, $IMPORTED_OBJECT_COUNTER; + $IMPORTED_DATA = array(); $IMPORTED_OBJECT_COUNTER = 0; - - /** - * This function processes an element, passing elements to the plugin stack to see if someone will - * process it. - * - * If nobody processes the top level element, the sub level elements are processed. - * - * @param array $element The dom tree. - */ - function __process_element($element) - { - global $IMPORTED_DATA, $IMPORTED_OBJECT_COUNTER; - - // See if we can convert the element into an ODD element - $odd = ODD_factory($element); - - // See if anyone handles this element, return true if it is. - if ($odd) - $handled = trigger_plugin_hook("import", "all", array("element" => $odd), $to_be_serialised); - - // If not, then see if any of its sub elements are handled - if (!$handled) - { - // Issue a warning - trigger_error("'<{$element->name}>' had no registered handler.", E_USER_WARNING); - - if (isset($element->children)) - foreach ($element->children as $c) - __process_element($c); - } - else - { - $IMPORTED_OBJECT_COUNTER ++; // Increment validation counter - $IMPORTED_DATA[] = $handled; // Return the constructed object - return true; - } + $document = ODD_Import($xml); + if (!$document) { + throw new ImportException(elgg_echo('ImportException:NoODDElements')); } - - /** - * Export a GUID. - * - * This function exports a GUID and all information related to it in an XML format. - * - * This function makes use of the "serialise" plugin hook, which is passed an array to which plugins - * should add data to be serialised to. - * - * @see ElggEntity for an example of its usage. - * @param int $guid The GUID. - * @return xml - */ - function export($guid) - { - $guid = (int)$guid; - - // Initialise the array - $to_be_serialised = array(); - - // Trigger a hook to - $to_be_serialised = trigger_plugin_hook("export", "all", array("guid" => $guid), $to_be_serialised); - - // 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"; - - return $output; + + foreach ($document as $element) { + _process_element($element); } - - /** - * Import an XML serialisation of an object. - * This will make a best attempt at importing a given xml doc. - * - * @param string $xml - * @return bool - * @throws Exception if there was a problem importing the data. - */ - function import($xml) - { - global $IMPORTED_DATA, $IMPORTED_OBJECT_COUNTER; - - $IMPORTED_DATA = array(); - $IMPORTED_OBJECT_COUNTER = 0; - - __process_element(xml_2_object($xml)); - - if ($IMPORTED_OBJECT_COUNTER!= count($IMPORTED_DATA)) - throw new ImportException("Not all elements were imported."); - - return true; + + if ($IMPORTED_OBJECT_COUNTER != count($IMPORTED_DATA)) { + throw new ImportException(elgg_echo('ImportException:NotAllImported')); } - -?>
\ No newline at end of file + + return true; +} + + +/** + * Register the OpenDD import action + * + * @return void + * @access private + */ +function export_init() { + global $CONFIG; + + elgg_register_action("import/opendd"); +} + +// Register a startup event +elgg_register_event_handler('init', 'system', 'export_init', 100); |
