From 3e4701116d9a7a2b93646f2c9aed80b63175d206 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 16 Aug 2019 15:29:24 +0300 Subject: af_readability: add missing file --- .../Readability/Nodes/DOM/DOMNodeList.php | 82 ++++++++++++++++++++++ .../andreskrey/Readability/Nodes/NodeTrait.php | 51 ++++++++++---- .../andreskrey/Readability/Nodes/NodeUtility.php | 20 ++++++ 3 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 plugins/af_readability/vendor/andreskrey/Readability/Nodes/DOM/DOMNodeList.php (limited to 'plugins/af_readability/vendor/andreskrey/Readability/Nodes') diff --git a/plugins/af_readability/vendor/andreskrey/Readability/Nodes/DOM/DOMNodeList.php b/plugins/af_readability/vendor/andreskrey/Readability/Nodes/DOM/DOMNodeList.php new file mode 100644 index 000000000..5149c0b98 --- /dev/null +++ b/plugins/af_readability/vendor/andreskrey/Readability/Nodes/DOM/DOMNodeList.php @@ -0,0 +1,82 @@ +length is hidden + * from the user and cannot be extended, changed, or tweaked. + */ +class DOMNodeList implements \Countable, \IteratorAggregate +{ + /** + * @var array + */ + protected $items = []; + + /** + * @var int + */ + protected $length = 0; + + /** + * To allow access to length in the same way that DOMNodeList allows. + * + * {@inheritdoc} + */ + public function __get($name) + { + switch ($name) { + case 'length': + return $this->length; + default: + trigger_error(sprintf('Undefined property: %s::%s', static::class, $name)); + } + } + + /** + * @param DOMNode|DOMElement|DOMComment $node + * + * @return DOMNodeList + */ + public function add($node) + { + $this->items[] = $node; + $this->length++; + + return $this; + } + + /** + * @param int $offset + * + * @return DOMNode|DOMElement|DOMComment + */ + public function item(int $offset) + { + return $this->items[$offset]; + } + + /** + * @return int|void + */ + public function count(): int + { + return $this->length; + } + + /** + * To make it compatible with iterator_to_array() function. + * + * {@inheritdoc} + */ + public function getIterator(): \ArrayIterator + { + return new \ArrayIterator($this->items); + } +} diff --git a/plugins/af_readability/vendor/andreskrey/Readability/Nodes/NodeTrait.php b/plugins/af_readability/vendor/andreskrey/Readability/Nodes/NodeTrait.php index d7060ccbb..5198bbb5f 100644 --- a/plugins/af_readability/vendor/andreskrey/Readability/Nodes/NodeTrait.php +++ b/plugins/af_readability/vendor/andreskrey/Readability/Nodes/NodeTrait.php @@ -181,11 +181,11 @@ trait NodeTrait /** * Override for native hasAttribute. * - * @see getAttribute - * * @param $attributeName * * @return bool + * + * @see getAttribute */ public function hasAttribute($attributeName) { @@ -317,10 +317,14 @@ trait NodeTrait * * @param bool $filterEmptyDOMText Filter empty DOMText nodes? * + * @deprecated Use NodeUtility::filterTextNodes, function will be removed in version 3.0 + * * @return array */ public function getChildren($filterEmptyDOMText = false) { + @trigger_error('getChildren was replaced with NodeUtility::filterTextNodes and will be removed in version 3.0', E_USER_DEPRECATED); + $ret = iterator_to_array($this->childNodes); if ($filterEmptyDOMText) { // Array values is used to discard the key order. Needs to be 0 to whatever without skipping any number @@ -418,12 +422,12 @@ trait NodeTrait public function hasSingleTagInsideElement($tag) { // There should be exactly 1 element child with given tag - if (count($children = $this->getChildren(true)) !== 1 || $children[0]->nodeName !== $tag) { + if (count($children = NodeUtility::filterTextNodes($this->childNodes)) !== 1 || $children->item(0)->nodeName !== $tag) { return false; } // And there should be no text nodes with real content - return array_reduce($children, function ($carry, $child) { + return array_reduce(iterator_to_array($children), function ($carry, $child) { if (!$carry === false) { return false; } @@ -443,7 +447,7 @@ trait NodeTrait { $result = false; if ($this->hasChildNodes()) { - foreach ($this->getChildren() as $child) { + foreach ($this->childNodes as $child) { if (in_array($child->nodeName, $this->divToPElements)) { $result = true; } else { @@ -500,18 +504,22 @@ trait NodeTrait ); } + /** + * In the original JS project they check if the node has the style display=none, which unfortunately + * in our case we have no way of knowing that. So we just check for the attribute hidden or "display: none". + * + * Might be a good idea to check for classes or other attributes like 'aria-hidden' + * + * @return bool + */ public function isProbablyVisible() { - /* - * In the original JS project they check if the node has the style display=none, which unfortunately - * in our case we have no way of knowing that. So we just check for the attribute hidden or "display: none". - * - * Might be a good idea to check for classes or other attributes like 'aria-hidden' - */ - return !preg_match('/display:( )?none/', $this->getAttribute('style')) && !$this->hasAttribute('hidden'); } + /** + * @return bool + */ public function isWhitespace() { return ($this->nodeType === XML_TEXT_NODE && mb_strlen(trim($this->textContent)) === 0) || @@ -557,4 +565,23 @@ trait NodeTrait $count -= ($count - $nodes->length); } } + + /** + * Mimics JS's firstElementChild property. PHP only has firstChild which could be any type of DOMNode. Use this + * function to get the first one that is an DOMElement node. + * + * @return \DOMElement|null + */ + public function getFirstElementChild() + { + if ($this->childNodes instanceof \Traversable) { + foreach ($this->childNodes as $node) { + if ($node instanceof \DOMElement) { + return $node; + } + } + } + + return null; + } } diff --git a/plugins/af_readability/vendor/andreskrey/Readability/Nodes/NodeUtility.php b/plugins/af_readability/vendor/andreskrey/Readability/Nodes/NodeUtility.php index 7a1f18ee4..cbf78bae0 100644 --- a/plugins/af_readability/vendor/andreskrey/Readability/Nodes/NodeUtility.php +++ b/plugins/af_readability/vendor/andreskrey/Readability/Nodes/NodeUtility.php @@ -5,6 +5,7 @@ namespace andreskrey\Readability\Nodes; use andreskrey\Readability\Nodes\DOM\DOMDocument; use andreskrey\Readability\Nodes\DOM\DOMElement; use andreskrey\Readability\Nodes\DOM\DOMNode; +use andreskrey\Readability\Nodes\DOM\DOMNodeList; /** * Class NodeUtility. @@ -157,4 +158,23 @@ class NodeUtility return ($originalNode) ? $originalNode->nextSibling : $originalNode; } + + /** + * Remove all empty DOMNodes from DOMNodeLists. + * + * @param \DOMNodeList $list + * + * @return DOMNodeList + */ + public static function filterTextNodes(\DOMNodeList $list) + { + $newList = new DOMNodeList(); + foreach ($list as $node) { + if ($node->nodeType !== XML_TEXT_NODE || mb_strlen(trim($node->nodeValue))) { + $newList->add($node); + } + } + + return $newList; + } } -- cgit v1.2.3