| <?php |
| |
| /** |
| * Zend Framework |
| * |
| * LICENSE |
| * |
| * This source file is subject to the new BSD license that is bundled |
| * with this package in the file LICENSE.txt. |
| * It is also available through the world-wide-web at this URL: |
| * http://framework.zend.com/license/new-bsd |
| * If you did not receive a copy of the license and are unable to |
| * obtain it through the world-wide-web, please send an email |
| * to license@zend.com so we can send you a copy immediately. |
| * |
| * @category Zend |
| * @package Zend_Feed |
| * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) |
| * @license http://framework.zend.com/license/new-bsd New BSD License |
| * @version $Id: Element.php 8064 2008-02-16 10:58:39Z thomas $ |
| */ |
| |
| /** |
| * Wraps a DOMElement allowing for SimpleXML-like access to attributes. |
| * |
| * @category Zend |
| * @package Zend_Feed |
| * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) |
| * @license http://framework.zend.com/license/new-bsd New BSD License |
| */ |
| class Zend_Feed_Element implements ArrayAccess { |
| |
| /** |
| * @var DOMElement |
| */ |
| protected $_element; |
| |
| /** |
| * @var Zend_Feed_Element |
| */ |
| protected $_parentElement; |
| |
| /** |
| * @var boolean |
| */ |
| protected $_appended = true; |
| |
| /** |
| * Zend_Feed_Element constructor. |
| * |
| * @param DOMElement $element The DOM element we're encapsulating. |
| * @return void |
| */ |
| public function __construct($element = null) { |
| $this->_element = $element; |
| } |
| |
| /** |
| * Get a DOM representation of the element |
| * |
| * Returns the underlying DOM object, which can then be |
| * manipulated with full DOM methods. |
| * |
| * @return DOMDocument |
| */ |
| public function getDOM() { |
| return $this->_element; |
| } |
| |
| /** |
| * Update the object from a DOM element |
| * |
| * Take a DOMElement object, which may be originally from a call |
| * to getDOM() or may be custom created, and use it as the |
| * DOM tree for this Zend_Feed_Element. |
| * |
| * @param DOMElement $element |
| * @return void |
| */ |
| public function setDOM(DOMElement $element) { |
| $this->_element = $this->_element->ownerDocument->importNode($element, true); |
| } |
| |
| /** |
| * Set the parent element of this object to another |
| * Zend_Feed_Element. |
| * |
| * @param Zend_Feed_Element $element |
| * @return void |
| */ |
| public function setParent(Zend_Feed_Element $element) { |
| $this->_parentElement = $element; |
| $this->_appended = false; |
| } |
| |
| /** |
| * Appends this element to its parent if necessary. |
| * |
| * @return void |
| */ |
| protected function ensureAppended() { |
| if (! $this->_appended) { |
| $this->_parentElement->getDOM()->appendChild($this->_element); |
| $this->_appended = true; |
| $this->_parentElement->ensureAppended(); |
| } |
| } |
| |
| /** |
| * Get an XML string representation of this element |
| * |
| * Returns a string of this element's XML, including the XML |
| * prologue. |
| * |
| * @return string |
| */ |
| public function saveXml() { |
| // Return a complete document including XML prologue. |
| $doc = new DOMDocument($this->_element->ownerDocument->version, $this->_element->ownerDocument->actualEncoding); |
| $doc->appendChild($doc->importNode($this->_element, true)); |
| return $doc->saveXML(); |
| } |
| |
| /** |
| * Get the XML for only this element |
| * |
| * Returns a string of this element's XML without prologue. |
| * |
| * @return string |
| */ |
| public function saveXmlFragment() { |
| return $this->_element->ownerDocument->saveXML($this->_element); |
| } |
| |
| /** |
| * Map variable access onto the underlying entry representation. |
| * |
| * Get-style access returns a Zend_Feed_Element representing the |
| * child element accessed. To get string values, use method syntax |
| * with the __call() overriding. |
| * |
| * @param string $var The property to access. |
| * @return mixed |
| */ |
| public function __get($var) { |
| $nodes = $this->_children($var); |
| $length = count($nodes); |
| |
| if ($length == 1) { |
| return new Zend_Feed_Element($nodes[0]); |
| } elseif ($length > 1) { |
| return array_map(create_function('$e', 'return new Zend_Feed_Element($e);'), $nodes); |
| } else { |
| // When creating anonymous nodes for __set chaining, don't |
| // call appendChild() on them. Instead we pass the current |
| // element to them as an extra reference; the child is |
| // then responsible for appending itself when it is |
| // actually set. This way "if ($foo->bar)" doesn't create |
| // a phantom "bar" element in our tree. |
| if (strpos($var, ':') !== false) { |
| list($ns, $elt) = explode(':', $var, 2); |
| $node = $this->_element->ownerDocument->createElementNS(Zend_Feed::lookupNamespace($ns), $elt); |
| } else { |
| $node = $this->_element->ownerDocument->createElement($var); |
| } |
| $node = new self($node); |
| $node->setParent($this); |
| return $node; |
| } |
| } |
| |
| /** |
| * Map variable sets onto the underlying entry representation. |
| * |
| * @param string $var The property to change. |
| * @param string $val The property's new value. |
| * @return void |
| * @throws Zend_Feed_Exception |
| */ |
| public function __set($var, $val) { |
| $this->ensureAppended(); |
| |
| $nodes = $this->_children($var); |
| if (! $nodes) { |
| if (strpos($var, ':') !== false) { |
| list($ns, $elt) = explode(':', $var, 2); |
| $node = $this->_element->ownerDocument->createElementNS(Zend_Feed::lookupNamespace($ns), $var, $val); |
| $this->_element->appendChild($node); |
| } else { |
| $node = $this->_element->ownerDocument->createElement($var, $val); |
| $this->_element->appendChild($node); |
| } |
| } elseif (count($nodes) > 1) { |
| /** |
| * @see Zend_Feed_Exception |
| */ |
| require_once 'external/Zend/Feed/Exception.php'; |
| throw new Zend_Feed_Exception('Cannot set the value of multiple tags simultaneously.'); |
| } else { |
| $nodes[0]->nodeValue = $val; |
| } |
| } |
| |
| /** |
| * Map isset calls onto the underlying entry representation. |
| * |
| * @param string $var |
| * @return boolean |
| */ |
| public function __isset($var) { |
| // Look for access of the form {ns:var}. We don't use |
| // _children() here because we can break out of the loop |
| // immediately once we find something. |
| if (strpos($var, ':') !== false) { |
| list($ns, $elt) = explode(':', $var, 2); |
| foreach ($this->_element->childNodes as $child) { |
| if ($child->localName == $elt && $child->prefix == $ns) { |
| return true; |
| } |
| } |
| } else { |
| foreach ($this->_element->childNodes as $child) { |
| if ($child->localName == $var) { |
| return true; |
| } |
| } |
| } |
| } |
| |
| /** |
| * Get the value of an element with method syntax. |
| * |
| * Map method calls to get the string value of the requested |
| * element. If there are multiple elements that match, this will |
| * return an array of those objects. |
| * |
| * @param string $var The element to get the string value of. |
| * @param mixed $unused This parameter is not used. |
| * @return mixed The node's value, null, or an array of nodes. |
| */ |
| public function __call($var, $unused) { |
| $nodes = $this->_children($var); |
| |
| if (! $nodes) { |
| return null; |
| } elseif (count($nodes) > 1) { |
| return $nodes; |
| } else { |
| return $nodes[0]->nodeValue; |
| } |
| } |
| |
| /** |
| * Remove all children matching $var. |
| * |
| * @param string $var |
| * @return void |
| */ |
| public function __unset($var) { |
| $nodes = $this->_children($var); |
| foreach ($nodes as $node) { |
| $parent = $node->parentNode; |
| $parent->removeChild($node); |
| } |
| } |
| |
| /** |
| * Returns the nodeValue of this element when this object is used |
| * in a string context. |
| * |
| * @return string |
| */ |
| public function __toString() { |
| return $this->_element->nodeValue; |
| } |
| |
| /** |
| * Finds children with tagnames matching $var |
| * |
| * Similar to SimpleXML's children() method. |
| * |
| * @param string $var Tagname to match, can be either namespace:tagName or just tagName. |
| * @return array |
| */ |
| protected function _children($var) { |
| $found = array(); |
| |
| // Look for access of the form {ns:var}. |
| if (strpos($var, ':') !== false) { |
| list($ns, $elt) = explode(':', $var, 2); |
| foreach ($this->_element->childNodes as $child) { |
| if ($child->localName == $elt && $child->prefix == $ns) { |
| $found[] = $child; |
| } |
| } |
| } else { |
| foreach ($this->_element->childNodes as $child) { |
| if ($child->localName == $var) { |
| $found[] = $child; |
| } |
| } |
| } |
| |
| return $found; |
| } |
| |
| /** |
| * Required by the ArrayAccess interface. |
| * |
| * @param string $offset |
| * @return boolean |
| */ |
| public function offsetExists($offset) { |
| if (strpos($offset, ':') !== false) { |
| list($ns, $attr) = explode(':', $offset, 2); |
| return $this->_element->hasAttributeNS(Zend_Feed::lookupNamespace($ns), $attr); |
| } else { |
| return $this->_element->hasAttribute($offset); |
| } |
| } |
| |
| /** |
| * Required by the ArrayAccess interface. |
| * |
| * @param string $offset |
| * @return string |
| */ |
| public function offsetGet($offset) { |
| if (strpos($offset, ':') !== false) { |
| list($ns, $attr) = explode(':', $offset, 2); |
| return $this->_element->getAttributeNS(Zend_Feed::lookupNamespace($ns), $attr); |
| } else { |
| return $this->_element->getAttribute($offset); |
| } |
| } |
| |
| /** |
| * Required by the ArrayAccess interface. |
| * |
| * @param string $offset |
| * @param string $value |
| * @return string |
| */ |
| public function offsetSet($offset, $value) { |
| $this->ensureAppended(); |
| |
| if (strpos($offset, ':') !== false) { |
| list($ns, $attr) = explode(':', $offset, 2); |
| return $this->_element->setAttributeNS(Zend_Feed::lookupNamespace($ns), $attr, $value); |
| } else { |
| return $this->_element->setAttribute($offset, $value); |
| } |
| } |
| |
| /** |
| * Required by the ArrayAccess interface. |
| * |
| * @param string $offset |
| * @return boolean |
| */ |
| public function offsetUnset($offset) { |
| if (strpos($offset, ':') !== false) { |
| list($ns, $attr) = explode(':', $offset, 2); |
| return $this->_element->removeAttributeNS(Zend_Feed::lookupNamespace($ns), $attr); |
| } else { |
| return $this->_element->removeAttribute($offset); |
| } |
| } |
| |
| } |