View file vendor/symfony/css-selector/XPath/Extension/AttributeMatchingExtension.php

File size: 3.73Kb
  1. <?php
  2.  
  3. /*
  4. * This file is part of the Symfony package.
  5. *
  6. * (c) Fabien Potencier <fabien@symfony.com>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11.  
  12. namespace Symfony\Component\CssSelector\XPath\Extension;
  13.  
  14. use Symfony\Component\CssSelector\XPath\Translator;
  15. use Symfony\Component\CssSelector\XPath\XPathExpr;
  16.  
  17. /**
  18. * XPath expression translator attribute extension.
  19. *
  20. * This component is a port of the Python cssselect library,
  21. * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
  22. *
  23. * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
  24. *
  25. * @internal
  26. */
  27. class AttributeMatchingExtension extends AbstractExtension
  28. {
  29. /**
  30. * {@inheritdoc}
  31. */
  32. public function getAttributeMatchingTranslators(): array
  33. {
  34. return [
  35. 'exists' => [$this, 'translateExists'],
  36. '=' => [$this, 'translateEquals'],
  37. '~=' => [$this, 'translateIncludes'],
  38. '|=' => [$this, 'translateDashMatch'],
  39. '^=' => [$this, 'translatePrefixMatch'],
  40. '$=' => [$this, 'translateSuffixMatch'],
  41. '*=' => [$this, 'translateSubstringMatch'],
  42. '!=' => [$this, 'translateDifferent'],
  43. ];
  44. }
  45.  
  46. public function translateExists(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
  47. {
  48. return $xpath->addCondition($attribute);
  49. }
  50.  
  51. public function translateEquals(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
  52. {
  53. return $xpath->addCondition(sprintf('%s = %s', $attribute, Translator::getXpathLiteral($value)));
  54. }
  55.  
  56. public function translateIncludes(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
  57. {
  58. return $xpath->addCondition($value ? sprintf(
  59. '%1$s and contains(concat(\' \', normalize-space(%1$s), \' \'), %2$s)',
  60. $attribute,
  61. Translator::getXpathLiteral(' '.$value.' ')
  62. ) : '0');
  63. }
  64.  
  65. public function translateDashMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
  66. {
  67. return $xpath->addCondition(sprintf(
  68. '%1$s and (%1$s = %2$s or starts-with(%1$s, %3$s))',
  69. $attribute,
  70. Translator::getXpathLiteral($value),
  71. Translator::getXpathLiteral($value.'-')
  72. ));
  73. }
  74.  
  75. public function translatePrefixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
  76. {
  77. return $xpath->addCondition($value ? sprintf(
  78. '%1$s and starts-with(%1$s, %2$s)',
  79. $attribute,
  80. Translator::getXpathLiteral($value)
  81. ) : '0');
  82. }
  83.  
  84. public function translateSuffixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
  85. {
  86. return $xpath->addCondition($value ? sprintf(
  87. '%1$s and substring(%1$s, string-length(%1$s)-%2$s) = %3$s',
  88. $attribute,
  89. \strlen($value) - 1,
  90. Translator::getXpathLiteral($value)
  91. ) : '0');
  92. }
  93.  
  94. public function translateSubstringMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
  95. {
  96. return $xpath->addCondition($value ? sprintf(
  97. '%1$s and contains(%1$s, %2$s)',
  98. $attribute,
  99. Translator::getXpathLiteral($value)
  100. ) : '0');
  101. }
  102.  
  103. public function translateDifferent(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
  104. {
  105. return $xpath->addCondition(sprintf(
  106. $value ? 'not(%1$s) or %1$s != %2$s' : '%s != %s',
  107. $attribute,
  108. Translator::getXpathLiteral($value)
  109. ));
  110. }
  111.  
  112. /**
  113. * {@inheritdoc}
  114. */
  115. public function getName(): string
  116. {
  117. return 'attribute-matching';
  118. }
  119. }