Skip to content

Instantly share code, notes, and snippets.

@M8R-1jmw5r
Created April 13, 2013 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save M8R-1jmw5r/775cd8cc47e22209873d to your computer and use it in GitHub Desktop.
Save M8R-1jmw5r/775cd8cc47e22209873d to your computer and use it in GitHub Desktop.
DOMValueObject and DOMValueCollection
<?php
/*
* DOMValueObject and DOMValueCollection
*
* @author Frank Hilvestede
*/
/**
* Class DOMValueCollection
*
* @author Frank Hilvestede
*/
class DOMValueObject
{
/**
* @var DOMNode
*/
private $contextNode;
/**
* @var array
*/
private $definitions;
public function __construct(DOMNode $contextNode = null) {
$this->contextNode = $contextNode;
}
public function defineProperty($name, $expression, $default = NULL) {
$this->definitions[$name] = array($expression, $default);
}
/**
* @param $name
*
* @throws BadMethodCallException
* @return DOMNode|mixed|null
*/
function __get($name) {
if (!isset($this->definitions[$name])) {
throw new BadMethodCallException(sprintf("Not a property: %s", $name));
}
list($expression, $default) = $this->definitions[$name];
$xpath = new DOMXPath($this->contextNode->ownerDocument);
$result = $xpath->evaluate($expression, $this->contextNode);
if (FALSE === $result) {
return $default;
}
if ($result instanceof DOMNodeList) {
$result = $result->length ? $result->item(0) : $default;
}
return $result;
}
public function setContextNode(DOMNode $contextNode) {
$this->contextNode = $contextNode;
}
public function getPropertyExpression($name) {
return $this->definitions[$name][0];
}
/**
* @return array
*/
public function getObjectProperties() {
$props = array();
foreach ($this->definitions as $name => $def) {
$value = $this->__get($name);
$props[$name] = $this->valuefy($value);
}
return $props;
}
private function valuefy($mixed) {
if ($mixed instanceof DOMNode) {
return $mixed->nodeValue;
}
return $mixed;
}
}
/**
* Class DOMValueCollection
*
* @author Frank Hilvestede
*/
class DOMValueCollection implements Iterator, countable
{
private $doc;
private $xpath;
/**
* @var Iterator|DOMNodeList
*/
private $result;
public function __construct(DOMDocument $doc, $xpath) {
$this->doc = $doc;
$this->xpath = $xpath;
}
public function getArrayCopy() {
$copy = array();
/* @var $this DOMValueObject[] */
foreach ($this as $object) {
$copy[] = $object->getObjectProperties();
}
return $copy;
}
public function count() {
return $this->result ? $this->result->length : 0;
}
public function rewind() {
$xpath = new DOMXPath($this->doc);
$result = $xpath->query($this->xpath);
if (FALSE === $result) {
throw new LogicException(sprintf('Xpath expression failed: %s', $this->xpath));
}
$this->result = new IteratorIterator($result);
$this->result->rewind();
}
public function current() {
$node = $this->result->current();
return new DOMValueObject($node);
}
public function next() {
$this->result->next();
}
public function key() {
return $this->result->key();
}
public function valid() {
return $this->result->valid();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment