bug #33777 Fix the :only-of-type pseudo class selector (jakzal)

This PR was squashed before being merged into the 3.4 branch (closes #33777).

Discussion
----------

Fix the :only-of-type pseudo class selector

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #33773
| License       | MIT
| Doc PR        | -

Commits
-------

c2a9bf08f1 Fix the :only-of-type pseudo class selector
This commit is contained in:
Fabien Potencier 2019-10-01 13:57:42 +02:00
commit d2b66ff592
2 changed files with 34 additions and 5 deletions

View File

@ -98,7 +98,7 @@ class TranslatorTest extends TestCase
$elements = $document->xpath($translator->cssToXPath($css));
$this->assertCount(\count($elementsId), $elements);
foreach ($elements as $element) {
$this->assertTrue(\in_array($element->attributes()->id, $elementsId));
$this->assertContains((string) $element->attributes()->id, $elementsId);
}
}
@ -116,7 +116,7 @@ class TranslatorTest extends TestCase
$this->assertCount(\count($elementsId), $elementsId);
foreach ($elements as $element) {
if (null !== $element->attributes()->id) {
$this->assertTrue(\in_array($element->attributes()->id, $elementsId));
$this->assertContains((string) $element->attributes()->id, $elementsId);
}
}
libxml_clear_errors();
@ -137,6 +137,33 @@ class TranslatorTest extends TestCase
$this->assertCount($count, $elements);
}
public function testOnlyOfTypeFindsSingleChildrenOfGivenType()
{
$translator = new Translator();
$translator->registerExtension(new HtmlExtension($translator));
$document = new \DOMDocument();
$document->loadHTML(<<<'HTML'
<html>
<body>
<p>
<span>A</span>
</p>
<p>
<span>B</span>
<span>C</span>
</p>
</body>
</html>
HTML
);
$xpath = new \DOMXPath($document);
$nodeList = $xpath->query($translator->cssToXPath('span:only-of-type'));
$this->assertSame(1, $nodeList->length);
$this->assertSame('A', $nodeList->item(0)->textContent);
}
public function getXpathLiteralTestData()
{
return [
@ -175,7 +202,7 @@ class TranslatorTest extends TestCase
['e:first-of-type', '*/e[position() = 1]'],
['e:last-of-type', '*/e[position() = last()]'],
['e:only-child', "*/*[(name() = 'e') and (last() = 1)]"],
['e:only-of-type', 'e[last() = 1]'],
['e:only-of-type', 'e[count(preceding-sibling::e)=0 and count(following-sibling::e)=0]'],
['e:empty', 'e[not(*) and not(string-length())]'],
['e:EmPTY', 'e[not(*) and not(string-length())]'],
['e:root', 'e[not(parent::*)]'],

View File

@ -123,11 +123,13 @@ class PseudoClassExtension extends AbstractExtension
*/
public function translateOnlyOfType(XPathExpr $xpath)
{
if ('*' === $xpath->getElement()) {
$element = $xpath->getElement();
if ('*' === $element) {
throw new ExpressionErrorException('"*:only-of-type" is not implemented.');
}
return $xpath->addCondition('last() = 1');
return $xpath->addCondition(sprintf('count(preceding-sibling::%s)=0 and count(following-sibling::%s)=0', $element, $element));
}
/**