friendship ended with social-app. php is my new best friend
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
12namespace Symfony\Component\CssSelector\XPath\Extension;
13
14use Symfony\Component\CssSelector\XPath\Translator;
15use 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 */
27class AttributeMatchingExtension extends AbstractExtension
28{
29 public function getAttributeMatchingTranslators(): array
30 {
31 return [
32 'exists' => $this->translateExists(...),
33 '=' => $this->translateEquals(...),
34 '~=' => $this->translateIncludes(...),
35 '|=' => $this->translateDashMatch(...),
36 '^=' => $this->translatePrefixMatch(...),
37 '$=' => $this->translateSuffixMatch(...),
38 '*=' => $this->translateSubstringMatch(...),
39 '!=' => $this->translateDifferent(...),
40 ];
41 }
42
43 public function translateExists(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
44 {
45 return $xpath->addCondition($attribute);
46 }
47
48 public function translateEquals(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
49 {
50 return $xpath->addCondition(\sprintf('%s = %s', $attribute, Translator::getXpathLiteral($value)));
51 }
52
53 public function translateIncludes(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
54 {
55 return $xpath->addCondition($value ? \sprintf(
56 '%1$s and contains(concat(\' \', normalize-space(%1$s), \' \'), %2$s)',
57 $attribute,
58 Translator::getXpathLiteral(' '.$value.' ')
59 ) : '0');
60 }
61
62 public function translateDashMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
63 {
64 return $xpath->addCondition(\sprintf(
65 '%1$s and (%1$s = %2$s or starts-with(%1$s, %3$s))',
66 $attribute,
67 Translator::getXpathLiteral($value),
68 Translator::getXpathLiteral($value.'-')
69 ));
70 }
71
72 public function translatePrefixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
73 {
74 return $xpath->addCondition($value ? \sprintf(
75 '%1$s and starts-with(%1$s, %2$s)',
76 $attribute,
77 Translator::getXpathLiteral($value)
78 ) : '0');
79 }
80
81 public function translateSuffixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
82 {
83 return $xpath->addCondition($value ? \sprintf(
84 '%1$s and substring(%1$s, string-length(%1$s)-%2$s) = %3$s',
85 $attribute,
86 \strlen($value) - 1,
87 Translator::getXpathLiteral($value)
88 ) : '0');
89 }
90
91 public function translateSubstringMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
92 {
93 return $xpath->addCondition($value ? \sprintf(
94 '%1$s and contains(%1$s, %2$s)',
95 $attribute,
96 Translator::getXpathLiteral($value)
97 ) : '0');
98 }
99
100 public function translateDifferent(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr
101 {
102 return $xpath->addCondition(\sprintf(
103 $value ? 'not(%1$s) or %1$s != %2$s' : '%s != %s',
104 $attribute,
105 Translator::getXpathLiteral($value)
106 ));
107 }
108
109 public function getName(): string
110 {
111 return 'attribute-matching';
112 }
113}