Compare commits
8 Commits
master
...
api-revamp
Author | SHA1 | Date | |
---|---|---|---|
|
c3746713f0 | ||
|
c38fbeca48 | ||
|
900839a01a | ||
|
006f1ca951 | ||
|
73899ce987 | ||
|
d8eaf093da | ||
|
9b723a4c42 | ||
|
7bbf744a76 |
@ -1,58 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace YusufKandemir\MicrodataParser;
|
|
||||||
|
|
||||||
abstract class Microdata
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a MicrodataParser from HTML string
|
|
||||||
*
|
|
||||||
* @param string $html HTML string to be parsed
|
|
||||||
* @param string $documentURI DocumentURI to be used in absolutizing URIs
|
|
||||||
*
|
|
||||||
* @return MicrodataParser
|
|
||||||
*/
|
|
||||||
public static function fromHTML(string $html, string $documentURI = '') : MicrodataParser
|
|
||||||
{
|
|
||||||
$dom = new MicrodataDOMDocument;
|
|
||||||
$dom->loadHTML($html, LIBXML_NOERROR);
|
|
||||||
$dom->documentURI = $documentURI;
|
|
||||||
|
|
||||||
return new MicrodataParser($dom);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a MicrodataParser from a HTML file
|
|
||||||
*
|
|
||||||
* @param string $filename Path to the file to be parsed
|
|
||||||
* @param string $documentURI DocumentURI to be used in absolutizing URIs
|
|
||||||
*
|
|
||||||
* @return MicrodataParser
|
|
||||||
*/
|
|
||||||
public static function fromHTMLFile(string $filename, string $documentURI = '') : MicrodataParser
|
|
||||||
{
|
|
||||||
$dom = new MicrodataDOMDocument;
|
|
||||||
$dom->loadHTMLFile($filename, LIBXML_NOERROR);
|
|
||||||
$dom->documentURI = $documentURI;
|
|
||||||
|
|
||||||
return new MicrodataParser($dom);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a MicrodataParser from a DOMDocument instance.
|
|
||||||
* If you have MicrodataDOMDocument then instantiate MicrodataParser class directly to avoid conversion.
|
|
||||||
*
|
|
||||||
* @param \DOMDocument $domDocument DOMDocument to be parsed.
|
|
||||||
* Needs to have documentURI property to be used in absolutizing URIs if wanted.
|
|
||||||
*
|
|
||||||
* @return MicrodataParser
|
|
||||||
*/
|
|
||||||
public static function fromDOMDocument(\DOMDocument $domDocument) : MicrodataParser
|
|
||||||
{
|
|
||||||
$dom = new MicrodataDOMDocument;
|
|
||||||
$importedNode = $dom->importNode($domDocument->documentElement, true);
|
|
||||||
$dom->appendChild($importedNode);
|
|
||||||
|
|
||||||
return new MicrodataParser($dom);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace YusufKandemir\MicrodataParser;
|
|
||||||
|
|
||||||
class MicrodataDOMDocument extends \DOMDocument
|
|
||||||
{
|
|
||||||
/** @var \DOMXPath */
|
|
||||||
public $xpath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get top-level items of the document
|
|
||||||
*
|
|
||||||
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-top-level-microdata-item
|
|
||||||
*
|
|
||||||
* @return \DOMNodeList List of top level items as elements
|
|
||||||
*/
|
|
||||||
public function getItems() : \DOMNodeList
|
|
||||||
{
|
|
||||||
return $this->xpath->query('//*[@itemscope and not(@itemprop)]');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
* Also assigns $xpath with DOMXPath of freshly loaded DOMDocument
|
|
||||||
*/
|
|
||||||
public function loadHTML($source, $options = 0)
|
|
||||||
{
|
|
||||||
$return = parent::loadHTML($source, $options);
|
|
||||||
|
|
||||||
$this->xpath = new \DOMXPath($this);
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
* Also assigns $xpath with DOMXPath of freshly loaded DOMDocument
|
|
||||||
*/
|
|
||||||
public function loadHTMLFile($filename, $options = 0)
|
|
||||||
{
|
|
||||||
$return = parent::loadHTMLFile($filename, $options);
|
|
||||||
|
|
||||||
$this->xpath = new \DOMXPath($this);
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,217 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace YusufKandemir\MicrodataParser;
|
|
||||||
|
|
||||||
class MicrodataDOMElement extends \DOMElement
|
|
||||||
{
|
|
||||||
/** @var array "tag name" to "attribute name" mapping */
|
|
||||||
private static $tagNameLookup = [
|
|
||||||
'audio' => 'src',
|
|
||||||
'embed' => 'src',
|
|
||||||
'iframe' => 'src',
|
|
||||||
'img' => 'src',
|
|
||||||
'source' => 'src',
|
|
||||||
'track' => 'src',
|
|
||||||
'video' => 'src',
|
|
||||||
'a' => 'href',
|
|
||||||
'area' => 'href',
|
|
||||||
'link' => 'href',
|
|
||||||
'object' => 'data',
|
|
||||||
'data' => 'value',
|
|
||||||
'meter' => 'value',
|
|
||||||
'time' => 'datetime',
|
|
||||||
];
|
|
||||||
|
|
||||||
/** @var array Attributes that have absolute values */
|
|
||||||
private static $absoluteAttributes = ['src', 'href', 'data',];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-item-properties for details of algorithm
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getProperties() : array
|
|
||||||
{
|
|
||||||
$results = [];
|
|
||||||
$memory = [$this];
|
|
||||||
$pending = $this->getChildElementNodes();
|
|
||||||
|
|
||||||
$pending = array_merge($pending, $this->getReferenceNodes());
|
|
||||||
|
|
||||||
while ($pending) {
|
|
||||||
$current = array_pop($pending);
|
|
||||||
|
|
||||||
foreach ($memory as $memory_item) {
|
|
||||||
if ($current->isSameNode($memory_item)) {
|
|
||||||
continue 2; // Skip next part and continue while loop if memory contains $current
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$memory[] = $current;
|
|
||||||
|
|
||||||
if (! $current->hasAttribute('itemscope')) {
|
|
||||||
$pending = array_merge($pending, $current->getChildElementNodes());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($current->hasAttribute('itemprop') && $current->hasPropertyNames()) {
|
|
||||||
$results[] = $current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_reverse($results);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasPropertyNames() : bool
|
|
||||||
{
|
|
||||||
return !empty($this->tokenizeAttribute('itemprop'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-property-name
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getPropertyNames() : array
|
|
||||||
{
|
|
||||||
$tokens = $this->tokenizeAttribute('itemprop');
|
|
||||||
|
|
||||||
$properties = [];
|
|
||||||
|
|
||||||
foreach ($tokens as $token) {
|
|
||||||
if (!$this->isAbsoluteUri($token) && $this->tokenizeAttribute('itemtype')) {
|
|
||||||
$token = /*$vocabularyIdentifier . */ $token;
|
|
||||||
}
|
|
||||||
|
|
||||||
$properties[] = $token;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_unique($properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-property-value for details of algorithm
|
|
||||||
*
|
|
||||||
* @param callable $absoluteUriHandler
|
|
||||||
*
|
|
||||||
* @return $this|string
|
|
||||||
*/
|
|
||||||
public function getPropertyValue(callable $absoluteUriHandler = null)
|
|
||||||
{
|
|
||||||
if ($this->hasAttribute('itemscope')) {
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->hasAttribute('content')) {
|
|
||||||
return $this->getAttribute('content');
|
|
||||||
}
|
|
||||||
|
|
||||||
$value = '';
|
|
||||||
|
|
||||||
if (\array_key_exists($this->tagName, self::$tagNameLookup)) {
|
|
||||||
$attribute = self::$tagNameLookup[$this->tagName];
|
|
||||||
$value = $this->getAttribute($attribute);
|
|
||||||
|
|
||||||
if (!empty($value) && \in_array($attribute, self::$absoluteAttributes) && !$this->isAbsoluteUri($value)) {
|
|
||||||
$value = $absoluteUriHandler($value, $this->ownerDocument->documentURI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $value ?: $this->textContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks a string to see if its absolute uri or not
|
|
||||||
* Note: As it uses a simple regex to check, it is not that reliable
|
|
||||||
*
|
|
||||||
* @see \preg_match() for return values
|
|
||||||
*
|
|
||||||
* @param string $uri
|
|
||||||
*
|
|
||||||
* @return false|int
|
|
||||||
*/
|
|
||||||
protected function isAbsoluteUri(string $uri)
|
|
||||||
{
|
|
||||||
return preg_match("/^\w+:/", trim($uri));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filters out TextNodes etc. and returns child ElementNodes as array
|
|
||||||
*
|
|
||||||
* @return array Result array which contains child ElementNodes
|
|
||||||
*/
|
|
||||||
protected function getChildElementNodes()
|
|
||||||
{
|
|
||||||
$childNodes = [];
|
|
||||||
|
|
||||||
foreach ($this->childNodes as $childNode) {
|
|
||||||
if ($childNode->nodeType == XML_ELEMENT_NODE) {
|
|
||||||
$childNodes[] = $childNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $childNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tokenizes value of given attribute
|
|
||||||
*
|
|
||||||
* @param string $attributeName Name of the attribute
|
|
||||||
*
|
|
||||||
* @return array|array[]|false|string[]
|
|
||||||
*/
|
|
||||||
public function tokenizeAttribute(string $attributeName)
|
|
||||||
{
|
|
||||||
$attribute = [];
|
|
||||||
|
|
||||||
if ($this->hasAttribute($attributeName)) {
|
|
||||||
$attribute = $this->tokenize($this->getAttribute($attributeName));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $attribute;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits given attribute value in space characters to array
|
|
||||||
*
|
|
||||||
* @see \preg_split() for possible return values and behaviour
|
|
||||||
*
|
|
||||||
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-split-a-string-on-spaces for definition of tokens
|
|
||||||
*
|
|
||||||
* @param string $attribute
|
|
||||||
*
|
|
||||||
* @return array[]|false|string[]
|
|
||||||
*/
|
|
||||||
protected function tokenize(string $attribute)
|
|
||||||
{
|
|
||||||
return preg_split('/\s+/', trim($attribute));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the nodes that this node references through the document
|
|
||||||
*
|
|
||||||
* @see https://www.w3.org/TR/microdata/#dfn-item-properties 4th step
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getReferenceNodes(): array
|
|
||||||
{
|
|
||||||
$referenceNodes = [];
|
|
||||||
|
|
||||||
if ($this->hasAttribute('itemref')) {
|
|
||||||
$tokens = $this->tokenizeAttribute('itemref');
|
|
||||||
|
|
||||||
foreach ($tokens as $token) {
|
|
||||||
$references = $this->ownerDocument->xpath->query('//*[@id="' . $token . '"]');
|
|
||||||
|
|
||||||
if ($first = $references->item(0)) {
|
|
||||||
$referenceNodes[] = $first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $referenceNodes;
|
|
||||||
}
|
|
||||||
}
|
|
59
src/MicrodataDocumentParser.php
Normal file
59
src/MicrodataDocumentParser.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace YusufKandemir\MicrodataParser;
|
||||||
|
|
||||||
|
class MicrodataDocumentParser
|
||||||
|
{
|
||||||
|
/** @var \DOMDocument */
|
||||||
|
protected $dom;
|
||||||
|
|
||||||
|
/** @var \DOMXPath */
|
||||||
|
protected $xpath;
|
||||||
|
|
||||||
|
/** @var MicrodataElementParser */
|
||||||
|
protected $elementParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MicrodataParser constructor.
|
||||||
|
*
|
||||||
|
* @param \DOMDocument $dom DOMDocument to be parsed
|
||||||
|
* @param MicrodataElementParser|null $elementParser
|
||||||
|
*/
|
||||||
|
public function __construct(\DOMDocument $dom, MicrodataElementParser $elementParser = null)
|
||||||
|
{
|
||||||
|
$this->dom = $dom;
|
||||||
|
$this->xpath = new \DOMXPath($this->dom);
|
||||||
|
|
||||||
|
$this->elementParser = $elementParser ?? new MicrodataElementParser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses microdata and returns result as object
|
||||||
|
*
|
||||||
|
* @return \stdClass
|
||||||
|
*/
|
||||||
|
public function parse() : \stdClass
|
||||||
|
{
|
||||||
|
$result = new \stdClass;
|
||||||
|
|
||||||
|
$result->items = [];
|
||||||
|
|
||||||
|
foreach ($this->getTopLevelItems() as $item) {
|
||||||
|
$result->items[] = $this->elementParser->parse($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds top level items in document
|
||||||
|
*
|
||||||
|
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-top-level-microdata-item
|
||||||
|
*
|
||||||
|
* @return \DOMNodeList
|
||||||
|
*/
|
||||||
|
protected function getTopLevelItems() : \DOMNodeList
|
||||||
|
{
|
||||||
|
return $this->xpath->query('//*[@itemscope and not(@itemprop)]');
|
||||||
|
}
|
||||||
|
}
|
320
src/MicrodataElementParser.php
Normal file
320
src/MicrodataElementParser.php
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace YusufKandemir\MicrodataParser;
|
||||||
|
|
||||||
|
class MicrodataElementParser
|
||||||
|
{
|
||||||
|
/** @var array "tag name" to "attribute name" mapping */
|
||||||
|
private static $tagNameLookup = [
|
||||||
|
'audio' => 'src',
|
||||||
|
'embed' => 'src',
|
||||||
|
'iframe' => 'src',
|
||||||
|
'img' => 'src',
|
||||||
|
'source' => 'src',
|
||||||
|
'track' => 'src',
|
||||||
|
'video' => 'src',
|
||||||
|
'a' => 'href',
|
||||||
|
'area' => 'href',
|
||||||
|
'link' => 'href',
|
||||||
|
'object' => 'data',
|
||||||
|
'data' => 'value',
|
||||||
|
'meter' => 'value',
|
||||||
|
'time' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @var array Attributes that have absolute values */
|
||||||
|
private static $absoluteAttributes = ['src', 'href', 'data',];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler will be called with $value(non-absolute uri string) and $base(base uri) parameters
|
||||||
|
*
|
||||||
|
* Should return the processed uri (string)
|
||||||
|
*
|
||||||
|
* @var callable|null
|
||||||
|
*/
|
||||||
|
private $absoluteUriHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param callable|null $absoluteUriHandler Can be set later with setAbsoluteUriHandler()
|
||||||
|
*/
|
||||||
|
public function __construct(callable $absoluteUriHandler = null)
|
||||||
|
{
|
||||||
|
$this->absoluteUriHandler = $absoluteUriHandler ?: function ($value, $base) {
|
||||||
|
return $base . $value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set absolute uri handler
|
||||||
|
*
|
||||||
|
* @param callable $handler
|
||||||
|
*/
|
||||||
|
public function setAbsoluteUriHandler(callable $handler)
|
||||||
|
{
|
||||||
|
$this->absoluteUriHandler = $handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-get-the-object
|
||||||
|
*
|
||||||
|
* @param \DOMElement $item
|
||||||
|
* @param array $memory
|
||||||
|
*
|
||||||
|
* @return \stdClass
|
||||||
|
*/
|
||||||
|
public function parse(\DOMElement $item, $memory = []) : \stdClass
|
||||||
|
{
|
||||||
|
$result = new \stdClass;
|
||||||
|
|
||||||
|
$memory[] = $item;
|
||||||
|
|
||||||
|
$result->type = $this->tokenizeAttribute($item, 'itemtype');
|
||||||
|
// @todo Check if types are valid absolute urls
|
||||||
|
|
||||||
|
if ($item->hasAttribute('itemid')) {
|
||||||
|
$result->id = $item->getAttribute('itemid');
|
||||||
|
}
|
||||||
|
// @todo Check if item ids are valid absolute urls or like isbn:xxx
|
||||||
|
|
||||||
|
$properties = new \stdClass;
|
||||||
|
|
||||||
|
foreach ($this->getProperties($item) as $element) {
|
||||||
|
$value = $this->getPropertyValue($element, $this->absoluteUriHandler);
|
||||||
|
|
||||||
|
if ($this->isItem($value)) {
|
||||||
|
foreach ($memory as $memory_item) {
|
||||||
|
if ($element->isSameNode($memory_item)) {
|
||||||
|
$value = 'ERROR';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($value != 'ERROR') {
|
||||||
|
$value = $this->parse($value, $memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->getPropertyNames($element) as $name) {
|
||||||
|
$properties->{$name}[] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result->properties = $properties;
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-item-properties for details of algorithm
|
||||||
|
*
|
||||||
|
* @param \DOMElement $element
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getProperties(\DOMElement $element) : array
|
||||||
|
{
|
||||||
|
$results = [];
|
||||||
|
$memory = [$element];
|
||||||
|
$pending = $this->getChildElementNodes($element);
|
||||||
|
|
||||||
|
$pending = array_merge($pending, $this->getReferenceElements($element));
|
||||||
|
|
||||||
|
while ($pending) {
|
||||||
|
$current = array_pop($pending);
|
||||||
|
|
||||||
|
foreach ($memory as $memory_item) {
|
||||||
|
if ($current->isSameNode($memory_item)) {
|
||||||
|
continue 2; // Skip next part and continue while loop if memory contains $current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$memory[] = $current;
|
||||||
|
|
||||||
|
if (! $current->hasAttribute('itemscope')) {
|
||||||
|
$pending = array_merge($pending, $this->getChildElementNodes($current));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($current->hasAttribute('itemprop') && $this->hasPropertyNames($current)) {
|
||||||
|
$results[] = $current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_reverse($results);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \DOMElement $element
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasPropertyNames(\DOMElement $element) : bool
|
||||||
|
{
|
||||||
|
return !empty($this->tokenizeAttribute($element, 'itemprop'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-property-name
|
||||||
|
*
|
||||||
|
* @param \DOMElement $element
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getPropertyNames(\DOMElement $element) : array
|
||||||
|
{
|
||||||
|
$tokens = $this->tokenizeAttribute($element, 'itemprop');
|
||||||
|
|
||||||
|
$properties = [];
|
||||||
|
|
||||||
|
foreach ($tokens as $token) {
|
||||||
|
if (!$this->isAbsoluteUri($token) && $this->tokenizeAttribute($element, 'itemtype')) {
|
||||||
|
$token = /*$vocabularyIdentifier . */ $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
$properties[] = $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \array_unique($properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-property-value for details of algorithm
|
||||||
|
*
|
||||||
|
* @param \DOMElement $element
|
||||||
|
* @param callable $absoluteUriHandler
|
||||||
|
*
|
||||||
|
* @return \DOMElement|string
|
||||||
|
*/
|
||||||
|
public function getPropertyValue(\DOMElement $element, callable $absoluteUriHandler = null)
|
||||||
|
{
|
||||||
|
if ($element->hasAttribute('itemscope')) {
|
||||||
|
return $element;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($element->hasAttribute('content')) {
|
||||||
|
return $element->getAttribute('content');
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = '';
|
||||||
|
|
||||||
|
if (\array_key_exists($element->tagName, self::$tagNameLookup)) {
|
||||||
|
$attribute = self::$tagNameLookup[$element->tagName];
|
||||||
|
$value = $element->getAttribute($attribute);
|
||||||
|
|
||||||
|
if (!empty($value) && \in_array($attribute, self::$absoluteAttributes) && !$this->isAbsoluteUri($value)) {
|
||||||
|
$value = $absoluteUriHandler($value, $element->ownerDocument->documentURI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value ?: $element->textContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the elements that given element references through the document
|
||||||
|
*
|
||||||
|
* @see https://www.w3.org/TR/microdata/#dfn-item-properties 4th step
|
||||||
|
*
|
||||||
|
* @param \DOMElement $element
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getReferenceElements(\DOMElement $element): array
|
||||||
|
{
|
||||||
|
$referenceElements = [];
|
||||||
|
|
||||||
|
if ($element->hasAttribute('itemref')) {
|
||||||
|
$tokens = $this->tokenizeAttribute($element, 'itemref');
|
||||||
|
|
||||||
|
foreach ($tokens as $token) {
|
||||||
|
$referenceElement = $element->ownerDocument->getElementById($token);
|
||||||
|
|
||||||
|
if ($referenceElement instanceof \DOMElement) {
|
||||||
|
$referenceElements[] = $referenceElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $referenceElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters out TextNodes etc. and returns child ElementNodes as array
|
||||||
|
*
|
||||||
|
* @param \DOMElement $element
|
||||||
|
*
|
||||||
|
* @return array Result array which contains child ElementNodes
|
||||||
|
*/
|
||||||
|
protected function getChildElementNodes(\DOMElement $element)
|
||||||
|
{
|
||||||
|
$childNodes = [];
|
||||||
|
|
||||||
|
foreach ($element->childNodes as $childNode) {
|
||||||
|
if ($childNode->nodeType == XML_ELEMENT_NODE) {
|
||||||
|
$childNodes[] = $childNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $childNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tokenizes value of given attribute
|
||||||
|
*
|
||||||
|
* @param \DOMElement $element
|
||||||
|
* @param string $attributeName Name of the attribute
|
||||||
|
*
|
||||||
|
* @return array|array[]|false|string[]
|
||||||
|
*/
|
||||||
|
public function tokenizeAttribute(\DOMElement $element, string $attributeName)
|
||||||
|
{
|
||||||
|
$attribute = [];
|
||||||
|
|
||||||
|
if ($element->hasAttribute($attributeName)) {
|
||||||
|
$attribute = $this->tokenize($element->getAttribute($attributeName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits given attribute value in space characters to array
|
||||||
|
*
|
||||||
|
* @see \preg_split() for possible return values and behaviour
|
||||||
|
*
|
||||||
|
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-split-a-string-on-spaces for definition of tokens
|
||||||
|
*
|
||||||
|
* @param string $attribute
|
||||||
|
*
|
||||||
|
* @return array[]|false|string[]
|
||||||
|
*/
|
||||||
|
protected function tokenize(string $attribute)
|
||||||
|
{
|
||||||
|
return preg_split('/\s+/', trim($attribute));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks a string to see if its absolute uri or not
|
||||||
|
* Note: As it uses a simple regex to check, it is not that reliable
|
||||||
|
*
|
||||||
|
* @see \preg_match() for return values
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
*
|
||||||
|
* @return false|int
|
||||||
|
*/
|
||||||
|
protected function isAbsoluteUri(string $uri)
|
||||||
|
{
|
||||||
|
return preg_match("/^\w+:/", trim($uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given parameter is a DOMElement and has itemscope attribute
|
||||||
|
*
|
||||||
|
* @param $element
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isItem($element) : bool
|
||||||
|
{
|
||||||
|
return $element instanceof \DOMElement && $element->hasAttribute('itemscope');
|
||||||
|
}
|
||||||
|
}
|
@ -4,157 +4,98 @@ namespace YusufKandemir\MicrodataParser;
|
|||||||
|
|
||||||
class MicrodataParser
|
class MicrodataParser
|
||||||
{
|
{
|
||||||
/** @var MicrodataDOMDocument */
|
/** @var callable|null */
|
||||||
protected $dom;
|
protected $absoluteUriHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler will be called with $value(non-absolute uri string) and $base(base uri) parameters
|
* @param callable|null $absoluteUriHandler
|
||||||
*
|
*
|
||||||
* Should return a string value
|
* @see MicrodataElementParser::$absoluteUriHandler
|
||||||
*
|
|
||||||
* @var callable|null
|
|
||||||
*/
|
*/
|
||||||
private $absoluteUriHandler;
|
public function __construct(callable $absoluteUriHandler = null)
|
||||||
|
|
||||||
/**
|
|
||||||
* MicrodataParser constructor.
|
|
||||||
*
|
|
||||||
* @param MicrodataDOMDocument $dom
|
|
||||||
* @param callable|null $absoluteUriHandler Can be set later with MicrodataParser::setAbsoluteUriHandler()
|
|
||||||
*
|
|
||||||
* @see MicrodataParser::$absoluteUriHandler
|
|
||||||
*/
|
|
||||||
public function __construct(MicrodataDOMDocument $dom, callable $absoluteUriHandler = null)
|
|
||||||
{
|
{
|
||||||
$dom->registerNodeClass(\DOMElement::class, MicrodataDOMElement::class);
|
$this->absoluteUriHandler = $absoluteUriHandler;
|
||||||
|
|
||||||
$this->dom = $dom;
|
|
||||||
$this->absoluteUriHandler = $absoluteUriHandler ?: function ($value, $base) {
|
|
||||||
return $base . $value;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts and converts microdata to associative array
|
* Parses HTML string, extracts microdata from it
|
||||||
*
|
*
|
||||||
* @return array
|
* @param string $html HTML string to be parsed
|
||||||
*/
|
* @param string $documentURI DocumentURI to be used in absolutizing URIs
|
||||||
public function toArray() : array
|
|
||||||
{
|
|
||||||
// Somewhat hacky way to convert deep objects
|
|
||||||
return json_decode(json_encode($this->extractMicrodata()), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts and converts microdata to object
|
|
||||||
*
|
*
|
||||||
* @return \stdClass
|
* @return \stdClass
|
||||||
*/
|
*/
|
||||||
public function toObject() : \stdClass
|
public function parseHTML(string $html, string $documentURI = '') : \stdClass
|
||||||
{
|
{
|
||||||
return $this->extractMicrodata();
|
$dom = new \DOMDocument;
|
||||||
|
$dom->loadHTML($html, \LIBXML_NOERROR);
|
||||||
|
$dom->documentURI = $documentURI;
|
||||||
|
|
||||||
|
return $this->parse($dom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts and converts microdata to json using \json_encode()
|
* Parses HTML file, extracts microdata from it
|
||||||
*
|
*
|
||||||
* @see \json_encode() to description of parameters and return values
|
* @param string $path Path to the file to be parsed
|
||||||
*
|
* @param string $documentURI DocumentURI to be used in absolutizing URIs
|
||||||
* @param int $options
|
|
||||||
* @param int $depth
|
|
||||||
*
|
|
||||||
* @return false|string
|
|
||||||
*/
|
|
||||||
public function toJSON($options = 0, $depth = 512)
|
|
||||||
{
|
|
||||||
return json_encode($this->extractMicrodata(), $options, $depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \stdClass
|
|
||||||
*/
|
|
||||||
protected function extractMicrodata() : \stdClass
|
|
||||||
{
|
|
||||||
$result = new \stdClass;
|
|
||||||
|
|
||||||
$result->items = [];
|
|
||||||
|
|
||||||
foreach ($this->dom->getItems() as $item) {
|
|
||||||
$result->items[] = $this->getObject($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-get-the-object
|
|
||||||
*
|
|
||||||
* @param MicrodataDOMElement $item
|
|
||||||
* @param array $memory
|
|
||||||
*
|
*
|
||||||
* @return \stdClass
|
* @return \stdClass
|
||||||
*/
|
*/
|
||||||
protected function getObject(MicrodataDOMElement $item, $memory = []) : \stdClass
|
public function parseHTMLFile(string $path, string $documentURI = '') : \stdClass
|
||||||
{
|
{
|
||||||
$result = new \stdClass;
|
$dom = new \DOMDocument;
|
||||||
|
$dom->loadHTMLFile($path, \LIBXML_NOERROR);
|
||||||
|
$dom->documentURI = $documentURI;
|
||||||
|
|
||||||
$memory[] = $item;
|
return $this->parse($dom);
|
||||||
|
|
||||||
$result->type = $item->tokenizeAttribute('itemtype');
|
|
||||||
// @todo Check if types are valid absolute urls
|
|
||||||
|
|
||||||
if ($item->hasAttribute('itemid')) {
|
|
||||||
$result->id = $item->getAttribute('itemid');
|
|
||||||
}
|
|
||||||
// @todo Check if item ids are valid absolute urls or like isbn:xxx
|
|
||||||
|
|
||||||
$properties = new \stdClass;
|
|
||||||
|
|
||||||
foreach ($item->getProperties() as $element) {
|
|
||||||
$value = $element->getPropertyValue($this->absoluteUriHandler);
|
|
||||||
|
|
||||||
if ($this->isItem($value)) {
|
|
||||||
foreach ($memory as $memory_item) {
|
|
||||||
if ($element->isSameNode($memory_item)) {
|
|
||||||
$value = 'ERROR';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($value != 'ERROR') {
|
|
||||||
$value = $this->getObject($value, $memory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($element->getPropertyNames() as $name) {
|
|
||||||
$properties->{$name}[] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result->properties = $properties;
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set absolute uri handler
|
* Creates a MicrodataParser from a DOMDocument instance.
|
||||||
|
* If you have MicrodataDOMDocument then instantiate MicrodataParser class directly to avoid conversion.
|
||||||
*
|
*
|
||||||
* @param callable $handler
|
* @param \DOMDocument $domDocument DOMDocument to be parsed.
|
||||||
|
* @param string $documentURI If non-empty value is provided,
|
||||||
|
* it will be new value of documentURI property of $domDocument.
|
||||||
|
*
|
||||||
|
* @return \stdClass
|
||||||
*/
|
*/
|
||||||
public function setAbsoluteUriHandler(callable $handler)
|
public function parseDOMDocument(\DOMDocument $domDocument, string $documentURI = '') : \stdClass
|
||||||
{
|
{
|
||||||
$this->absoluteUriHandler = $handler;
|
if (!empty($documentURI)) {
|
||||||
|
$domDocument->documentURI = $documentURI;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->parse($domDocument);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given parameter is a MicrodataDOMElement and has itemscope attribute
|
* @param \DOMDocument $dom
|
||||||
*
|
*
|
||||||
* @param $element
|
* @see MicrodataElementParser::$absoluteUriHandler
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return \stdClass
|
||||||
*/
|
*/
|
||||||
protected function isItem($element) : bool
|
protected function parse(\DOMDocument $dom) : \stdClass
|
||||||
{
|
{
|
||||||
return $element instanceof MicrodataDOMElement && $element->hasAttribute('itemscope');
|
$elementParser = new MicrodataElementParser($this->absoluteUriHandler);
|
||||||
|
$documentParser = new MicrodataDocumentParser($dom, $elementParser);
|
||||||
|
|
||||||
|
return $documentParser->parse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param callable|null $absoluteUriHandler
|
||||||
|
*
|
||||||
|
* @see MicrodataElementParser::$absoluteUriHandler
|
||||||
|
*
|
||||||
|
* @return MicrodataParser
|
||||||
|
*/
|
||||||
|
public function setAbsoluteUriHandler(callable $absoluteUriHandler = null) : self
|
||||||
|
{
|
||||||
|
$this->absoluteUriHandler = $absoluteUriHandler;
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
51
tests/DataDrivenTestCase.php
Normal file
51
tests/DataDrivenTestCase.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace YusufKandemir\MicrodataParser\Tests;
|
||||||
|
|
||||||
|
class DataDrivenTestCase extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
libxml_use_internal_errors(true); // Ignore warnings of DOMDocument::loadHTML check
|
||||||
|
}
|
||||||
|
|
||||||
|
public function data()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
// https://www.w3.org/TR/microdata/#ex-jsonconv
|
||||||
|
'W3C Example' => [
|
||||||
|
$this->getTestData('W3C', 'source.html', 'result.json')
|
||||||
|
],
|
||||||
|
'Itemref & src based tags' => [
|
||||||
|
$this->getTestData('Itemref', 'source.html', 'result.json')
|
||||||
|
],
|
||||||
|
'Object & Data tags' => [
|
||||||
|
$this->getTestData('Object & Data', 'source.html', 'result.json')
|
||||||
|
],
|
||||||
|
'Itemid & Content attributes' => [
|
||||||
|
$this->getTestData('Itemid & Content', 'source.html', 'result.json')
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getTestData($folderName, $sourceName, $resultName)
|
||||||
|
{
|
||||||
|
$folderPath = __DIR__.'/data/'.$folderName.'/';
|
||||||
|
|
||||||
|
$source = file_get_contents($folderPath . $sourceName);
|
||||||
|
$result = file_get_contents($folderPath . $resultName);
|
||||||
|
|
||||||
|
$uri = '';
|
||||||
|
// Set $uri if URI specified in test data
|
||||||
|
if (preg_match('/<!-- URI: (.*) -->/', $source, $matches)) {
|
||||||
|
$uri = $matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'path' => $folderPath . $sourceName,
|
||||||
|
'uri' => $uri,
|
||||||
|
'source' => $source, // HTML String
|
||||||
|
'result' => $result, // JSON String
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -2,123 +2,77 @@
|
|||||||
|
|
||||||
namespace YusufKandemir\MicrodataParser\Tests;
|
namespace YusufKandemir\MicrodataParser\Tests;
|
||||||
|
|
||||||
use YusufKandemir\MicrodataParser\MicrodataDOMDocument;
|
|
||||||
use YusufKandemir\MicrodataParser\MicrodataParser;
|
use YusufKandemir\MicrodataParser\MicrodataParser;
|
||||||
|
use YusufKandemir\MicrodataParser\MicrodataDocumentParser;
|
||||||
|
|
||||||
class MicrodataParserTest extends \PHPUnit\Framework\TestCase
|
class MicrodataParserTest extends DataDrivenTestCase
|
||||||
{
|
{
|
||||||
protected function setUp()
|
/**
|
||||||
|
* @param array $data
|
||||||
|
* @dataProvider data
|
||||||
|
*/
|
||||||
|
public function testItParsesHtml(array $data)
|
||||||
{
|
{
|
||||||
libxml_use_internal_errors(true); // Ignore warnings of DOMDocument::loadHTML check
|
$parser = new MicrodataParser();
|
||||||
|
$result = $parser->parseHTML($data['source'], $data['uri']);
|
||||||
|
|
||||||
|
$expected = \json_decode($data['result']);
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getParser($data)
|
/**
|
||||||
|
* @param array $data
|
||||||
|
* @dataProvider data
|
||||||
|
*/
|
||||||
|
public function testItParsesHtmlFile(array $data)
|
||||||
{
|
{
|
||||||
$dom = new MicrodataDOMDocument;
|
$parser = new MicrodataParser();
|
||||||
|
$result = $parser->parseHTMLFile($data['path'], $data['uri']);
|
||||||
|
|
||||||
|
$expected = \json_decode($data['result']);
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $data
|
||||||
|
* @dataProvider data
|
||||||
|
*/
|
||||||
|
public function testItParsesDomDocument(array $data)
|
||||||
|
{
|
||||||
|
$dom = new \DOMDocument;
|
||||||
$dom->loadHTML($data['source']);
|
$dom->loadHTML($data['source']);
|
||||||
$dom->documentURI = $data['uri'];
|
$dom->documentURI = $data['uri'];
|
||||||
|
|
||||||
return new MicrodataParser($dom);
|
$parser = new MicrodataParser();
|
||||||
}
|
$result = $parser->parseDOMDocument($dom);
|
||||||
|
|
||||||
/**
|
$expected = \json_decode($data['result']);
|
||||||
* @dataProvider data
|
|
||||||
*/
|
|
||||||
public function testItConvertsMicrodataToObjectFormat($data)
|
|
||||||
{
|
|
||||||
$parser = $this->getParser($data);
|
|
||||||
|
|
||||||
$result = $parser->toObject();
|
$this->assertEquals($expected, $result);
|
||||||
|
|
||||||
$this->assertEquals(json_decode($data['result']), $result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider data
|
|
||||||
*/
|
|
||||||
public function testItConvertsMicrodataToArrayFormat($data)
|
|
||||||
{
|
|
||||||
$parser = $this->getParser($data);
|
|
||||||
|
|
||||||
$result = $parser->toArray();
|
|
||||||
|
|
||||||
$this->assertEquals(json_decode($data['result'], true), $result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider data
|
|
||||||
*/
|
|
||||||
public function testItConvertsMicrodataToJsonFormat($data)
|
|
||||||
{
|
|
||||||
$parser = $this->getParser($data);
|
|
||||||
|
|
||||||
$result = $parser->toJSON();
|
|
||||||
|
|
||||||
$this->assertJsonStringEqualsJsonString($data['result'], $result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItUsesAbsoluteUriHandlerWhenHandlingAbsoluteUris()
|
public function testItUsesAbsoluteUriHandlerWhenHandlingAbsoluteUris()
|
||||||
{
|
{
|
||||||
$baseUri = 'https://absolute.uri.handler/';
|
$baseUri = 'https://absolute.uri.handler/';
|
||||||
$data = $this->data()['Itemref & src based tags'][0];
|
$data = $this->data()['Itemref & src based tags'][0];
|
||||||
$parser = $this->getParser($data);
|
$parser = new MicrodataParser();
|
||||||
|
|
||||||
$resultBefore = $parser->toObject();
|
$resultBefore = $parser->parseHTML($data['source'], $data['uri']);
|
||||||
$resultBeforeUri = $resultBefore->items[0]->properties->work[0];
|
$resultBeforeUri = $resultBefore->items[0]->properties->work[0];
|
||||||
|
|
||||||
$this->assertNotContains($baseUri, $resultBeforeUri);
|
$this->assertNotContains($baseUri, $resultBeforeUri);
|
||||||
|
|
||||||
$parser->setAbsoluteUriHandler(
|
$absoluteUriHandler = function (string $value, string $base) use ($baseUri) : string {
|
||||||
function (string $value, string $base) use ($baseUri) : string {
|
return $baseUri . $value;
|
||||||
return $baseUri . $value;
|
};
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$resultAfter = $parser->toObject();
|
$resultAfter = $parser
|
||||||
|
->setAbsoluteUriHandler($absoluteUriHandler)
|
||||||
|
->parseHTML($data['source'], $data['uri']);
|
||||||
$resultAfterUri = $resultAfter->items[0]->properties->work[0];
|
$resultAfterUri = $resultAfter->items[0]->properties->work[0];
|
||||||
|
|
||||||
$this->assertContains($baseUri, $resultAfterUri);
|
$this->assertContains($baseUri, $resultAfterUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo Provide more test data
|
|
||||||
*/
|
|
||||||
public function data()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
// https://www.w3.org/TR/microdata/#ex-jsonconv
|
|
||||||
'W3C Example' => [
|
|
||||||
$this->getTestData('W3C', 'source.html', 'result.json')
|
|
||||||
],
|
|
||||||
'Itemref & src based tags' => [
|
|
||||||
$this->getTestData('Itemref', 'source.html', 'result.json')
|
|
||||||
],
|
|
||||||
'Object & Data tags' => [
|
|
||||||
$this->getTestData('Object & Data', 'source.html', 'result.json')
|
|
||||||
],
|
|
||||||
'Itemid & Content attributes' => [
|
|
||||||
$this->getTestData('Itemid & Content', 'source.html', 'result.json')
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getTestData($folderName, $sourceName, $resultName)
|
|
||||||
{
|
|
||||||
$folderPath = __DIR__.'/data/'.$folderName.'/';
|
|
||||||
|
|
||||||
$source = file_get_contents($folderPath . $sourceName);
|
|
||||||
$result = file_get_contents($folderPath . $resultName);
|
|
||||||
|
|
||||||
$uri = '';
|
|
||||||
// Set $uri if URI specified in test data
|
|
||||||
if (preg_match('/<!-- URI: (.*) -->/', $source, $matches)) {
|
|
||||||
$uri = $matches[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'uri' => $uri,
|
|
||||||
'source' => $source, // HTML String
|
|
||||||
'result' => $result, // JSON String
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace YusufKandemir\MicrodataParser\Tests;
|
|
||||||
|
|
||||||
use YusufKandemir\MicrodataParser\Microdata;
|
|
||||||
use YusufKandemir\MicrodataParser\MicrodataParser;
|
|
||||||
|
|
||||||
class MicrodataTest extends \PHPUnit\Framework\TestCase
|
|
||||||
{
|
|
||||||
protected $htmlFileName = __DIR__ . '/data/W3C/source.html';
|
|
||||||
|
|
||||||
public function testItCreatesMicrodataParserFromHtml()
|
|
||||||
{
|
|
||||||
$html = file_get_contents($this->htmlFileName);
|
|
||||||
$microdata = Microdata::fromHTML($html);
|
|
||||||
|
|
||||||
$this->assertInstanceOf(MicrodataParser::class, $microdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItCreatesMicrodataParserFromHtmlFile()
|
|
||||||
{
|
|
||||||
$microdata = Microdata::fromHTMLFile($this->htmlFileName);
|
|
||||||
|
|
||||||
$this->assertInstanceOf(MicrodataParser::class, $microdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItCreatesMicrodataParserFromDomDocument()
|
|
||||||
{
|
|
||||||
$dom = new \DOMDocument;
|
|
||||||
$dom->loadHTMLFile($this->htmlFileName);
|
|
||||||
|
|
||||||
$microdata = Microdata::fromDOMDocument($dom);
|
|
||||||
|
|
||||||
$this->assertInstanceOf(MicrodataParser::class, $microdata);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user