From 42c7f296659bc60527dbf7e5d9012e3058ba55d3 Mon Sep 17 00:00:00 2001 From: Deon George Date: Thu, 12 Jul 2012 15:10:39 +1000 Subject: [PATCH] Updated XML module from github --- includes/kohana/modules/xml/LICENSE | 2 +- includes/kohana/modules/xml/README.md | 6 +- .../kohana/modules/xml/classes/xml/core.php | 137 +++++++++--------- .../modules/xml/classes/xml/driver/atom.php | 61 ++++---- .../modules/xml/classes/xml/driver/rss2.php | 23 ++- .../modules/xml/classes/xml/driver/xrds.php | 14 +- .../modules/xml/classes/xml/meta/core.php | 51 ++----- 7 files changed, 137 insertions(+), 157 deletions(-) diff --git a/includes/kohana/modules/xml/LICENSE b/includes/kohana/modules/xml/LICENSE index 215018dc..82b7457f 100644 --- a/includes/kohana/modules/xml/LICENSE +++ b/includes/kohana/modules/xml/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2010 Cédric Cazettes +Copyright (c) 2010 Cédric de Saint Léger Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation diff --git a/includes/kohana/modules/xml/README.md b/includes/kohana/modules/xml/README.md index 6f7ad350..c4b5dcb2 100644 --- a/includes/kohana/modules/xml/README.md +++ b/includes/kohana/modules/xml/README.md @@ -1,11 +1,11 @@ -Kohana_XML is a module used to generate and read XML documents in Kohana. -It is built for KO3, but there are barely one or two lines that makes it KO3 specific, +Kohana_XML is a XML modules to generate and read XML documents in Kohana. +It is build for KO3, but there are barely one or two lines that makes it KO3 specific, so I guess it should work for KO2.x without much trouble. ## Notable Features * **Extendible, configurable drivers** — You can use the XML class to write simple XML, -or use drivers to generate RFC-specific compliant XML (Atom/RSS2...), or write your own driver (extending XML +or use the Atom driver to generate Atom compliant XML, or write your own driver (extending XML or another driver) to generate XML compliant to any specs you want. Driver support initial configuration, which will be used when using native functions, and your own function. Namespaces and prefix, value filters, default attributes, node name abstraction are all part diff --git a/includes/kohana/modules/xml/classes/xml/core.php b/includes/kohana/modules/xml/classes/xml/core.php index a9ac5964..1432e051 100644 --- a/includes/kohana/modules/xml/classes/xml/core.php +++ b/includes/kohana/modules/xml/classes/xml/core.php @@ -99,7 +99,7 @@ // Initialize the document with the given element if (is_string($element)) { - if (is_file($element) OR valid::url($element)) + if (is_file($element) OR Valid::url($element)) { // Generate XML from a file $this->dom_doc->load($element); @@ -124,14 +124,12 @@ elseif ( ! is_null($this->root_node)) { // Create the Root Element from the driver attributes - if ($this->meta()->ns($this->root_node)) + if ($this->meta()->get("namespace", $this->root_node)) { - list($ns, $prefix) = $this->meta()->ns($this->root_node); - - $root_node_name = $prefix ? "$prefix:$this->root_node" : $this->root_node; - + $root_node_name = $this->meta()->get("prefix", $this->root_node) ? $this->meta()->get("prefix", $this->root_node).":$this->root_node" : $this->root_node; + // Create the root node in its prefixed namespace - $root_node = $this->dom_doc->createElementNS($ns, $root_node_name); + $root_node = $this->dom_doc->createElementNS($this->meta()->get("namespace", $this->root_node), $root_node_name); } else { @@ -174,7 +172,7 @@ // Add the value if provided if ($value !== NULL) { - $value = strval($this->filter($name, $value)); + $value = strval($this->filter($name, $value, $node)); if (str_replace(array('<', '>', '&'), "", $value) === $value) { @@ -358,10 +356,33 @@ { // All other nodes shall be parsed normally : attributes then text value and child nodes, running through the XML tree $object_element = array(); - + // Get the desired node name for this node $node_name = $this->meta()->key($dom_node->tagName); - + + // Get children, run through XML tree + if ($dom_node->hasChildNodes()) + { + if (!$dom_node->firstChild->hasChildNodes()) + { + // Get text value + $object_element[$node_name] = trim($dom_node->firstChild->nodeValue); + } + + foreach($dom_node->childNodes as $dom_child) + { + if ($dom_child->nodeType === XML_ELEMENT_NODE) + { + $child = $this->_as_array($dom_child); + + foreach ($child as $key=>$val) + { + $object_element[$node_name][$key][]=$val; + } + } + } + } + // Get attributes if ($dom_node->hasAttributes()) { @@ -370,38 +391,13 @@ { // Get the desired name for this attribute $att_name = $this->meta()->key($att_name); - $object_element[$node_name]['xml_attributes'][$att_name] = $dom_attribute->value; } } - - // Get children, run through XML tree - if ($dom_node->hasChildNodes()) - { - if (!$dom_node->firstChild->hasChildNodes()) - { - // Get text value - $object_element[$node_name] = trim($dom_node->firstChild->nodeValue); - } - - foreach($dom_node->childNodes as $dom_child) - { - if ($dom_child->nodeType === XML_ELEMENT_NODE) - { - $child = $this->_as_array($dom_child); - - foreach ($child as $key=>$val) - { - $object_element[$node_name][$key][]=$val; - } - } - } - } return $object_element; } - /** * Converts an array to XML. Expected structure is given in as_array(). * However, from_array() is essentially more flexible regarding to the input array structure, @@ -418,7 +414,6 @@ } - /** * Array shall be like : array('element_name' => array( 0 => text, 'xml_attributes' => array())); * @param object $mixed @@ -456,6 +451,10 @@ // Create a new element with the key as the element name. // Create the element corresponding to the key $node = $this->create_element($index); + + // Add the driver attributes + $this->add_attributes($node); + // Append it $dom_element->appendChild($node); @@ -464,14 +463,13 @@ } } } - else + elseif ($mixed) { // This is a string value that shall be appended as such - $mixed = $this->filter($dom_element->tagName, $mixed); + $mixed = $this->filter($dom_element->tagName, $mixed, $dom_element); $dom_element->appendChild($this->dom_doc->createTextNode($mixed)); } } - /** @@ -516,24 +514,26 @@ $name = $this->meta()->alias($name); // Let's check if the element name has a namespace, and if this prefix is defined in our driver - if ($this->meta()->ns($name)) + if ($namespace_uri = $this->meta()->get("namespace", $name)) { - list ($ns, $prefix) = $this->meta()->ns($name); - - if ($prefix) + if (stristr($name, ":")) { + // Separate the namespace prefix and the name + list($prefix, $name) = explode(":", $name); + // Register the prefixed namespace in the document root - $this->dom_doc->documentElement->setAttributeNS("http://www.w3.org/2000/xmlns/" ,"xmlns:$prefix", $ns); - + $this->dom_doc->documentElement->setAttributeNS("http://www.w3.org/2000/xmlns/" ,"xmlns:".$prefix, $namespace_uri); + // Create the prefixed element within that namespace - $node = $this->dom_doc->createElementNS($ns, $name); + $node = $this->dom_doc->createElementNS($namespace_uri, $prefix.":".$name); } else { // Create the element normally $node = $this->dom_doc->createElement($name); + // Add the new default namespace as an attribute. - $node->setAttribute("xmlns", $ns); + $node->setAttribute("xmlns", $namespace_uri); } } else @@ -555,26 +555,30 @@ { $node_name = $this->meta()->alias($node->tagName); - if ($this->meta()->attributes($node_name)) + if ($this->meta()->get("attributes", $node_name)) { - $attributes = array_merge($this->meta()->attributes($node_name), $attributes); + $attributes = array_merge($this->meta()->get("attributes", $node_name), $attributes); } foreach ($attributes as $key => $val) { // Trim elements $key = $this->meta()->alias(trim($key)); - $val = $this->filter($key, trim($val)); - + $val = $this->filter($key, trim($val), $node); + // Set the attribute // Let's check if the attribute name has a namespace prefix, and if this prefix is defined in our driver - if ($this->meta()->ns($key)) + if ($namespace_uri = $this->meta()->get("namespace", $key) + AND stristr($name, ":")) { - list ($ns, $prefix) = $this->meta()->ns($key); + // Separate the namespace prefix and the name + list($prefix, $name) = explode(":", $name); + // Register the prefixed namespace - $this->dom_node->setAttributeNS("http://www.w3.org/2000/xmlns/" ,"xmlns:$prefix", $ns); + $this->dom_node->setAttributeNS("http://www.w3.org/2000/xmlns/" ,"xmlns:".$prefix, $namespace_uri); + // Add the prefixed attribute within that namespace - $node->setAttributeNS($ns, $key, $val); + $node->setAttributeNS($namespace_uri, $key, $val); } else { @@ -584,8 +588,7 @@ } return $node; } - - + /** * Applies filter on a value. @@ -593,19 +596,19 @@ * They allow to format dates, links, standard stuff, and play * as you wish with the value before it is added to the document. * - * You could even extend it and modidy the node name. + * You could even extend it and modify the node name. * * @param string $name * @param string $value * @return string $value formatted value */ - protected function filter($name, $value) + protected function filter($name, $value, &$node) { $name = $this->meta()->alias($name); - if ($this->meta()->filter($name)) + if ($this->meta()->get("filter", $name)) { - return call_user_func(array($this, $this->meta()->filter($name)), $value); + return call_user_func(array($this, $this->meta()->get("filter", $name)), $value, $node); } return $value; } @@ -616,10 +619,15 @@ * @param object $value * @return $value */ - public function normalize_uri($value) + public function normalize_uri($value, $node) { if (strpos($value, '://') === FALSE) { + if (strlen(URL::base()) > 1 AND stristr($value, URL::base())) + { + // Make sure the path is not base related + $value = str_replace(URL::base(), '', $value); + } // Convert URIs to URLs $value = URL::site($value, TRUE); } @@ -638,7 +646,6 @@ } - /** * Returns this drivers XML metadata * @return XML_Meta @@ -647,8 +654,7 @@ { return XML::$_metas[strtolower(get_class($this))]; } - - + /** * Outputs nicely formatted XML when converting as string @@ -660,7 +666,6 @@ } - /** * Render the XML. * @param boolean $formatted [optional] Should the output be formatted and indented ? diff --git a/includes/kohana/modules/xml/classes/xml/driver/atom.php b/includes/kohana/modules/xml/classes/xml/driver/atom.php index 45a58916..40989648 100644 --- a/includes/kohana/modules/xml/classes/xml/driver/atom.php +++ b/includes/kohana/modules/xml/classes/xml/driver/atom.php @@ -19,8 +19,9 @@ class XML_Driver_Atom extends XML ->nodes ( array( "feed" => array("namespace" => "http://www.w3.org/2005/Atom"), - "entry" => array("namespace" => "http://www.w3.org/2005/Atom"), + // "entry" => array("namespace" => "http://www.w3.org/2005/Atom"), "href" => array("filter" => "normalize_uri"), + "link" => array("filter" => "normalize_uri"), "logo" => array("filter" => "normalize_uri"), "icon" => array("filter" => "normalize_uri"), "id" => array("filter" => "normalize_uri"), @@ -28,11 +29,15 @@ class XML_Driver_Atom extends XML "published" => array("filter" => "normalize_datetime"), "startDate" => array("filter" => "normalize_date"), 'endDate' => array("filter" => "normalize_date"), + "summary" => array("filter" => "normalize_text"), + "subtitle" => array("filter" => "normalize_text"), + "title" => array("filter" => "normalize_text"), + "content" => array("filter" => "normalize_text") ) ); } - - + + public function add_person($type, $name, $email = NULL, $uri = NULL) { $author = $this->add_node($type); @@ -47,8 +52,8 @@ class XML_Driver_Atom extends XML } return $this; } - - + + public function add_content(XML $xml_document) { $this->add_node("content", NULL, array("type" => $xml_document->meta()->content_type()))->import($xml_document); @@ -56,6 +61,21 @@ class XML_Driver_Atom extends XML } + public function normalize_text($value, $node) + { + if (strpos($value, "<") >= 0 AND strpos($value, ">") > 0) + { + // Assume type = html + $node->setAttribute("type", "html"); + } + else + { + $node->setAttribute("type", "text"); + } + return $value; + } + + public function normalize_datetime($value) { if ( ! is_numeric($value)) @@ -66,7 +86,8 @@ class XML_Driver_Atom extends XML // Convert timestamps to RFC 3339 formatted datetime return date(DATE_RFC3339, $value); } - + + public function normalize_date($value) { if ( ! is_numeric($value)) @@ -77,32 +98,4 @@ class XML_Driver_Atom extends XML // Convert timestamps to RFC 3339 formatted dates return date("Y-m-d", $value); } - - - public function render($formatted = FALSE) - { - if ( ! $this->published) - { - // Add the published node with current date - $this->add_node("published", time()); - } - // Add the link to self - $this->add_node("link", NULL, array("rel" => "self", "href" => $_SERVER['REQUEST_URI'])); - - return parent::render($formatted); - } - - - public function export($file) - { - if ( ! $this->published) - { - // Add the published node with current date - $this->add_node("published", time()); - } - // Add the link to self - $this->add_node("link", NULL, array("rel" => "self", "href" => $_SERVER['REQUEST_URI'])); - - parent::export($file); - } } \ No newline at end of file diff --git a/includes/kohana/modules/xml/classes/xml/driver/rss2.php b/includes/kohana/modules/xml/classes/xml/driver/rss2.php index aa41a46e..b5217631 100644 --- a/includes/kohana/modules/xml/classes/xml/driver/rss2.php +++ b/includes/kohana/modules/xml/classes/xml/driver/rss2.php @@ -18,15 +18,25 @@ class XML_Driver_Rss2 extends XML ->nodes ( array( "rss" => array("attributes" => array("version" => "2.0")), + "title" => array("filter" => "normalize_text"), + "description" => array("filter" => "normalize_text"), "link" => array("filter" => "normalize_uri"), + "atom:link" => array("attributes" => array( + "rel" => "self", + "type" => "application/rss+xml", + // "href" => URL::site(Request::initial()->uri(), TRUE) + ), + "namespace" => "http://www.w3.org/2005/Atom"), + "href" => array("filter" => "normalize_uri"), "docs" => array("filter" => "normalize_uri"), "guid" => array("filter" => "normalize_uri"), "pubDate" => array("filter" => "normalize_date"), - "lastBuildDate" => array("filter" => "normalize_date"), + "lastBuildDate" => array("filter" => "normalize_date") ) ); } + public function normalize_date($value) { if ( ! is_numeric($value)) @@ -34,7 +44,14 @@ class XML_Driver_Rss2 extends XML $value = strtotime($value); } - // Convert timestamps to RFC 822 formatted dates - return date(DATE_RFC822, $value); + // Convert timestamps to RFC 822 formatted dates, with 4 digits year + return date(DATE_RSS, $value); + } + + + public function normalize_text($value) + { + // Strip HTML tags + return strip_tags($value); } } \ No newline at end of file diff --git a/includes/kohana/modules/xml/classes/xml/driver/xrds.php b/includes/kohana/modules/xml/classes/xml/driver/xrds.php index 4b52470f..2f536d2b 100644 --- a/includes/kohana/modules/xml/classes/xml/driver/xrds.php +++ b/includes/kohana/modules/xml/classes/xml/driver/xrds.php @@ -8,19 +8,18 @@ * XRDS driver. For Service Discovery. */ - class XML_Driver_XRDS extends XML - { - public $root_node = 'XRDS'; - - +class XML_Driver_XRDS extends XML +{ + public $root_node = 'xrds:XRDS'; + protected static function initialize(XML_Meta $meta) { $meta ->content_type("application/xrds+xml") ->nodes ( array( - "XRDS" => array("namespace" => 'xri://$xrds', "prefix" => "xrds", "attributes" => array("xmlns" => 'xri://$xrd*($v*2.0)')), + "xrds:XRDS" => array("namespace" => 'xri://$xrds', "attributes" => array("xmlns" => 'xri://$xrd*($v*2.0)')), "LocalID" => array("filter" => "normalize_uri"), - "Delegate" => array("filter" => "normalize_uri", "namespace" => "http://openid.net/xmlns/1.0", "prefix" => "openid"), + "openid:Delegate" => array("filter" => "normalize_uri", "namespace" => "http://openid.net/xmlns/1.0"), "URI" => array("filter" => "normalize_uri"), ) ); @@ -53,5 +52,4 @@ return $service_node; } - } \ No newline at end of file diff --git a/includes/kohana/modules/xml/classes/xml/meta/core.php b/includes/kohana/modules/xml/classes/xml/meta/core.php index ddb555e3..93f699a7 100644 --- a/includes/kohana/modules/xml/classes/xml/meta/core.php +++ b/includes/kohana/modules/xml/classes/xml/meta/core.php @@ -47,7 +47,6 @@ protected $_initialized = FALSE; - /** * Returns the name of a node, sort out aliases * @param string $name @@ -66,53 +65,21 @@ return Arr::get($this->nodes, $name, $name); } - /** - * Return namespace config for a given node - * @param string $name - * @return mixed array(uri, prefix) or NULL + * Returns the value of a meta key for a given node name + * exemple $this->get('attributes', 'feed') will return all the attributes set up in the meta + * for the node feed. + * @param object $key meta key + * @param object $name node name + * @return meta value or NULL if not set */ - public function ns($name) + public function get($key, $name) { $name = $this->alias($name); - if (isset($this->nodes_config[$name]) AND is_array($this->nodes_config[$name]) AND array_key_exists("namespace", $this->nodes_config[$name])) + if (isset($this->nodes_config[$name]) AND is_array($this->nodes_config[$name]) AND array_key_exists($key, $this->nodes_config[$name])) { - return array($this->nodes_config[$name]["namespace"], Arr::get($this->nodes_config[$name], "prefix", NULL)); - } - return NULL; - } - - - /** - * Return default attributes for a given node - * @param string $name - * @return mixed attributes assoc array() or NULL - */ - public function attributes($name) - { - $name = $this->alias($name); - - if (isset($this->nodes_config[$name]) AND is_array($this->nodes_config[$name]) AND array_key_exists("attributes", $this->nodes_config[$name])) - { - return $this->nodes_config[$name]["attributes"]; - } - return NULL; - } - - - /** - * Return user-defined value filter function for a given node - * @param string $name - * @return mixed function name or NULL - */ - public function filter($name) - { - $name = $this->alias($name); - - if (isset($this->nodes_config[$name]) AND is_array($this->nodes_config[$name]) AND array_key_exists("filter", $this->nodes_config[$name])) - { - return $this->nodes_config[$name]["filter"]; + return $this->nodes_config[$name][$key]; } return NULL; }