Skip to content
This repository has been archived by the owner on Oct 12, 2024. It is now read-only.

Commit

Permalink
Inital
Browse files Browse the repository at this point in the history
  • Loading branch information
dantleech committed Nov 25, 2015
0 parents commit 1758c78
Show file tree
Hide file tree
Showing 12 changed files with 588 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
composer.lock
vendor
docs/build
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
DOM
===

This library provides a wrapper for the PHP DOM library which makes your life
easier.

It wraps the `\DOMDocument`, `\DOMElement` and `\DOMXpath` classes.`

Example:

```php
$dom = new Document();
$element = $dom->createRoot('example');
$element->appendChild('boo', 'hello');
$element->appendChild('baz', 'world');

echo $dom->saveXml();
// <?xml version="1.0"?>
// <example>
// <boo>hello</boo>
// <baz>world</baz>
// </example>

$element->appendChild('number', 5);
$element->appendChild('number', 10);

echo $element->evaluate('sum(./number)'); // 15

$nodeList = $element->query('./number');

echo $nodeList->length; // 2
```

Document
--------

The `PhpBench\Dom\Document` class wraps the `\DOMDocument` class and replaces the
`\DOMElement` class with the `PhpBench\Dom\Element` class.

It implements the `XPathAware` interface.

- `createRoot($name, $value = null)`: Create and return a new root node with `$name` and optional
`$value`.
- `query($query, $context = null)`: Execute a given XPath query on the
document.
- `queryOne($query, $context = null)`: Execute a given XPath query on the
document and return the first element or `NULL`.
- `evaluate($query, $context = null)`: Evaluate the given XPath expression.

Element
-------

- `appendElement($name $value)`: Create and return an element with name
`$name` and value `$value`.
- `query`, `queryOne` and `evalauate`: As with Document but will use the context of this element by
default.
33 changes: 33 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "phpbench/dom",
"description": "DOM wrapper to simplify working with the PHP DOM implementation",
"license": "MIT",
"authors": [
{
"name": "Daniel Leech",
"email": "daniel@dantleech.com"
}
],
"require": {
"php": "^5.0",
"ext-dom": "*"
},
"require-dev": {
"phpunit/phpunit": "^4.6"
},
"autoload": {
"psr-4": {
"PhpBench\\Dom\\": "lib/"
}
},
"autoload-dev": {
"psr-4": {
"PhpBench\\Dom\\Tests\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}
88 changes: 88 additions & 0 deletions lib/Document.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

/*
* This file is part of the PHPBench package
*
* (c) Daniel Leech <daniel@dantleech.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace PhpBench\Dom;

use PhpBench\Dom\Element;
use PhpBench\Dom\XPath;
use PhpBench\Dom\XPathAware;

/**
* Wrapper for the \DOMDocument class.
*/
class Document extends \DOMDocument implements XPathAware
{
/**
* @var XPath
*/
private $xpath;

/**
* @param string $version
* @param mixed $encoding
*/
public function __construct($version = '1.0', $encoding = null)
{
parent::__construct($version, $encoding);
$this->registerNodeClass('DOMElement', 'PhpBench\Dom\Element');
}

/**
* Create and return a root DOM element
*
* @param string $name
* @return Element
*/
public function createRoot($name)
{
return $this->appendChild(new Element($name));
}

/**
* Return the XPath object bound to this document.
*
* @return XPath
*/
public function xpath()
{
if ($this->xpath) {
return $this->xpath;
}

$this->xpath = new XPath($this);

return $this->xpath;
}

/**
* {@inheritdoc}
*/
public function query($query, \DOMNode $context = null)
{
return $this->xpath()->query($query, $context);
}

/**
* {@inheritdoc}
*/
public function queryOne($query, \DOMNode $context = null)
{
return $this->xpath()->queryOne($query, $context);
}

/**
* {@inheritdoc}
*/
public function evaluate($expression, \DOMNode $context = null)
{
return $this->xpath()->evaluate($expression, $context);
}
}
53 changes: 53 additions & 0 deletions lib/Element.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of the PHPBench package
*
* (c) Daniel Leech <daniel@dantleech.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace PhpBench\Dom;

use PhpBench\Dom\XPathAware;

/**
* Wrapper for the \DOMElement class.
*/
class Element extends \DOMElement implements XPathAware
{
/**
* Create and append an element with the given name and optionally given value.
*
* @param string $name
* @param mixed $value
* @return Element
*/
public function appendElement($name, $value = null)
{
return $this->appendChild(new self($name, $value));
}

/**
* {@inheritdoc}
*/
public function query($xpath, \DOMNode $context = null)
{
return $this->ownerDocument->xpath()->query($xpath, $context ?: $this);
}

public function queryOne($xpath, \DOMNode $context = null)
{
return $this->ownerDocument->xpath()->queryOne($xpath, $context ?: $this);
}

/**
* {@inheritdoc}
*/
public function evaluate($expression, \DOMNode $context = null)
{
return $this->ownerDocument->xpath()->evaluate($expression, $context ?: $this);
}
}
7 changes: 7 additions & 0 deletions lib/Exception/InvalidQueryException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace PhpBench\Dom\Exception;

class InvalidQueryException extends \InvalidArgumentException
{
}
76 changes: 76 additions & 0 deletions lib/XPath.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

/*
* This file is part of the Tabular package
*
* (c) Daniel Leech <daniel@dantleech.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace PhpBench\Dom;

/**
* Wrapper for the \DOMXPath class.
*/
class XPath extends \DOMXPath
{
/**
* {@inheritdoc}
*/
public function evaluate($expr, \DOMNode $contextEl = null, $registerNodeNs = null)
{
$result = $this->execute('evaluate', 'expression', $expr, $contextEl, $registerNodeNs);
return $result;
}

/**
* {@inheritdoc}
*/
public function query($expr, \DOMNode $contextEl = null, $registerNodeNs = null)
{
return $this->execute('query', 'query', $expr, $contextEl, $registerNodeNs);
}

/**
* Query for one node
*/
public function queryOne($expr, \DOMNode $contextEl = null, $registerNodeNs = null)
{
$nodeList = $this->query($expr, $contextEl, $registerNodeNs);

if (0 === $nodeList->length) {
return null;
}

return $nodeList->item(0);
}

/**
* Execute the given xpath method and cactch any errors.
*/
private function execute($method, $context, $query, \DOMNode $contextEl = null, $registerNodeNs)
{
libxml_use_internal_errors(true);

$value = @parent::$method($query, $contextEl, $registerNodeNs);

if (false === $value) {
$xmlErrors = libxml_get_errors();
$errors = array();
foreach ($xmlErrors as $xmlError) {
$errors[] = sprintf('[%s] %s', $xmlError->code, $xmlError->message);
}

throw new Exception\InvalidQueryException(sprintf(
'Errors encountered when evaluating XPath %s "%s": %s%s',
$context, $query, PHP_EOL, implode(PHP_EOL, $errors)
));
}

libxml_use_internal_errors(false);

return $value;
}
}
41 changes: 41 additions & 0 deletions lib/XPathAware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace PhpBench\Dom;

interface XPathAware
{
/**
* Perform an xpath query on this document, optionally with
* the given context node.
*
* If this interface is applied to an Element, then the element
* should be used as the context if no context is given.
*
* @param string $query
* @param \DOMNode $context
* @return \DOMNodeList
*/
public function query($query, \DOMNode $context = null);

/**
* As with XPathAware::query but return a single node or NULL if no node was found.
*
* @param string $query
* @param \DOMNode $context
* @return Element|null
*/
public function queryOne($query, \DOMNode $context = null);

/**
* Evaluate an XPath expression on this document, optionally
* with the given context node.
*
* If this interface is applied to an Element, then the element
* should be used as the context if no context is given.
*
* @param string $expression
* @param \DOMNode $context
* @return mixed
*/
public function evaluate($expression, \DOMNode $context = null);
}
24 changes: 24 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>

<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit
colors="true"
bootstrap="vendor/autoload.php"
>

<testsuites>
<testsuite name="PhpBench DOM Test Suite">
<directory>./tests</directory>
</testsuite>
</testsuites>

<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<directory>.</directory>
<exclude>
<directory>vendor/</directory>
</exclude>
</whitelist>
</filter>

</phpunit>
Loading

0 comments on commit 1758c78

Please sign in to comment.