From 489c667f53e4886bc0cfd90055aa43bc0f5ba5f8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 12 Nov 2025 08:23:43 +0000 Subject: [PATCH 1/9] Initial plan From de5c380befb6530d91b3ae8512198c5b454a3cfb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 12 Nov 2025 08:30:29 +0000 Subject: [PATCH 2/9] Initial exploration and understanding of the repository Co-authored-by: mustafauysal <1421387+mustafauysal@users.noreply.github.com> --- .phpunit.result.cache | 1 + .../Tests/CssSelectorConverterTest.php | 83 ++++ .../Tests/Node/AbstractNodeTestCase.php | 34 ++ .../Tests/Node/AttributeNodeTest.php | 37 ++ .../CssSelector/Tests/Node/ClassNodeTest.php | 33 ++ .../Tests/Node/CombinedSelectorNodeTest.php | 35 ++ .../Tests/Node/ElementNodeTest.php | 35 ++ .../Tests/Node/FunctionNodeTest.php | 47 ++ .../CssSelector/Tests/Node/HashNodeTest.php | 33 ++ .../Tests/Node/NegationNodeTest.php | 33 ++ .../CssSelector/Tests/Node/PseudoNodeTest.php | 32 ++ .../Tests/Node/SelectorNodeTest.php | 34 ++ .../Tests/Node/SpecificityTest.php | 63 +++ .../Handler/AbstractHandlerTestCase.php | 70 +++ .../Parser/Handler/CommentHandlerTest.php | 55 +++ .../Tests/Parser/Handler/HashHandlerTest.php | 49 +++ .../Parser/Handler/IdentifierHandlerTest.php | 49 +++ .../Parser/Handler/NumberHandlerTest.php | 50 +++ .../Parser/Handler/StringHandlerTest.php | 50 +++ .../Parser/Handler/WhitespaceHandlerTest.php | 44 ++ .../CssSelector/Tests/Parser/ParserTest.php | 263 +++++++++++ .../CssSelector/Tests/Parser/ReaderTest.php | 102 +++++ .../Tests/Parser/Shortcut/ClassParserTest.php | 45 ++ .../Parser/Shortcut/ElementParserTest.php | 44 ++ .../Parser/Shortcut/EmptyStringParserTest.php | 36 ++ .../Tests/Parser/Shortcut/HashParserTest.php | 45 ++ .../Tests/Parser/TokenStreamTest.php | 97 ++++ .../CssSelector/Tests/XPath/Fixtures/ids.html | 52 +++ .../CssSelector/Tests/XPath/Fixtures/lang.xml | 11 + .../Tests/XPath/Fixtures/shakespear.html | 308 +++++++++++++ .../Tests/XPath/TranslatorTest.php | 416 ++++++++++++++++++ .../Component/CssSelector/phpunit.xml.dist | 31 ++ 32 files changed, 2317 insertions(+) create mode 100644 .phpunit.result.cache create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTestCase.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTestCase.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ParserTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php create mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/phpunit.xml.dist diff --git a/.phpunit.result.cache b/.phpunit.result.cache new file mode 100644 index 0000000..fe33bcf --- /dev/null +++ b/.phpunit.result.cache @@ -0,0 +1 @@ +{"version":1,"defects":[],"times":{"PoweredCache\\Core\\Core_Tests::test_setup":0.187,"PoweredCache\\Core\\Core_Tests::test_i18n":0.024,"PoweredCache\\Core\\Core_Tests::test_init":0,"Encryption_Test::testEncrypt":0.013,"Encryption_Test::testDecrypt":0,"PoweredCache\\Utils\\Util_Tests::testIsDirEmpty":0.004,"PoweredCache\\Utils\\Util_Tests::testIsIpInRange with data set #0":0.002,"PoweredCache\\Utils\\Util_Tests::testIsIpInRange with data set #1":0.002,"PoweredCache\\Utils\\Util_Tests::testIsIpInRange with data set #2":0.002,"PoweredCache\\Utils\\Util_Tests::testIsIpInRange with data set #3":0.002,"PoweredCache\\Utils\\Util_Tests::testMaskString with data set #0":0.002,"PoweredCache\\Utils\\Util_Tests::testMaskString with data set #1":0.002,"PoweredCache\\Utils\\Util_Tests::testMaskString with data set #2":0.002,"PoweredCache\\Utils\\Util_Tests::testMaskString with data set #3":0.002,"PoweredCache\\Utils\\Util_Tests::testGetClientIp":0.002,"PoweredCache\\Utils\\Util_Tests::testBypassRequest":0.002,"PoweredCache\\Utils\\Util_Tests::testIsLocalSiteWithLocalhost":0.003,"PoweredCache\\Utils\\Util_Tests::testIsLocalSiteWithEnvironmentTypeLocal":0.002,"PoweredCache\\Utils\\Util_Tests::testIsLocalSiteWithEnvironmentTypeProduction":0.01,"PoweredCache\\Utils\\Util_Tests::testPoweredCacheIsMobileWithMobileUserAgent":0.003,"PoweredCache\\Utils\\Util_Tests::testPoweredCacheIsMobileWithNonMobileUserAgent":0.002,"PoweredCache\\Utils\\Util_Tests::testGetExpiredFiles":0.002,"PoweredCache\\Utils\\Util_Tests::testGetUrlDir":0.003}} \ No newline at end of file diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php new file mode 100644 index 0000000..d42ce90 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\CssSelectorConverter; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\ParseException; + +class CssSelectorConverterTest extends TestCase +{ + public function testCssToXPath() + { + $converter = new CssSelectorConverter(); + + $this->assertEquals('descendant-or-self::*', $converter->toXPath('')); + $this->assertEquals('descendant-or-self::h1', $converter->toXPath('h1')); + $this->assertEquals("descendant-or-self::h1[@id = 'foo']", $converter->toXPath('h1#foo')); + $this->assertEquals("descendant-or-self::h1[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]", $converter->toXPath('h1.foo')); + $this->assertEquals('descendant-or-self::foo:h1', $converter->toXPath('foo|h1')); + $this->assertEquals('descendant-or-self::h1', $converter->toXPath('H1')); + + // Test the cache layer + $converter = new CssSelectorConverter(); + $this->assertEquals('descendant-or-self::h1', $converter->toXPath('H1')); + } + + public function testCssToXPathXml() + { + $converter = new CssSelectorConverter(false); + + $this->assertEquals('descendant-or-self::H1', $converter->toXPath('H1')); + + $converter = new CssSelectorConverter(false); + // Test the cache layer + $this->assertEquals('descendant-or-self::H1', $converter->toXPath('H1')); + } + + public function testParseExceptions() + { + $this->expectException(ParseException::class); + $this->expectExceptionMessage('Expected identifier, but found.'); + $converter = new CssSelectorConverter(); + $converter->toXPath('h1:'); + } + + /** @dataProvider getCssToXPathWithoutPrefixTestData */ + public function testCssToXPathWithoutPrefix($css, $xpath) + { + $converter = new CssSelectorConverter(); + + $this->assertEquals($xpath, $converter->toXPath($css, ''), '->parse() parses an input string and returns a node'); + } + + public static function getCssToXPathWithoutPrefixTestData() + { + return [ + ['h1', 'h1'], + ['foo|h1', 'foo:h1'], + ['h1, h2, h3', 'h1 | h2 | h3'], + ['h1:nth-child(3n+1)', "*/*[(name() = 'h1') and (position() - 1 >= 0 and (position() - 1) mod 3 = 0)]"], + ['h1 > p', 'h1/p'], + ['h1#foo', "h1[@id = 'foo']"], + ['h1.foo', "h1[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"], + ['h1[class*="foo bar"]', "h1[@class and contains(@class, 'foo bar')]"], + ['h1[foo|class*="foo bar"]', "h1[@foo:class and contains(@foo:class, 'foo bar')]"], + ['h1[class]', 'h1[@class]'], + ['h1 .foo', "h1/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"], + ['h1 #foo', "h1/descendant-or-self::*/*[@id = 'foo']"], + ['h1 [class*=foo]', "h1/descendant-or-self::*/*[@class and contains(@class, 'foo')]"], + ['div>.foo', "div/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"], + ['div > .foo', "div/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTestCase.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTestCase.php new file mode 100644 index 0000000..99460ae --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTestCase.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\NodeInterface; + +abstract class AbstractNodeTestCase extends TestCase +{ + /** @dataProvider getToStringConversionTestData */ + public function testToStringConversion(NodeInterface $node, $representation) + { + $this->assertEquals($representation, (string) $node); + } + + /** @dataProvider getSpecificityValueTestData */ + public function testSpecificityValue(NodeInterface $node, $value) + { + $this->assertEquals($value, $node->getSpecificity()->getValue()); + } + + abstract public static function getToStringConversionTestData(); + + abstract public static function getSpecificityValueTestData(); +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php new file mode 100644 index 0000000..5115605 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\AttributeNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; + +class AttributeNodeTest extends AbstractNodeTestCase +{ + public static function getToStringConversionTestData() + { + return [ + [new AttributeNode(new ElementNode(), null, 'attribute', 'exists', null), 'Powered_Cache_Attribute[Element[*][attribute]]'], + [new AttributeNode(new ElementNode(), null, 'attribute', '$=', 'value'), "Powered_Cache_Attribute[Element[*][attribute $= 'value']]"], + [new AttributeNode(new ElementNode(), 'namespace', 'attribute', '$=', 'value'), "Powered_Cache_Attribute[Element[*][namespace|attribute $= 'value']]"], + ]; + } + + public static function getSpecificityValueTestData() + { + return [ + [new AttributeNode(new ElementNode(), null, 'attribute', 'exists', null), 10], + [new AttributeNode(new ElementNode(null, 'element'), null, 'attribute', 'exists', null), 11], + [new AttributeNode(new ElementNode(), null, 'attribute', '$=', 'value'), 10], + [new AttributeNode(new ElementNode(), 'namespace', 'attribute', '$=', 'value'), 10], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php new file mode 100644 index 0000000..ae43a62 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ClassNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; + +class ClassNodeTest extends AbstractNodeTestCase +{ + public static function getToStringConversionTestData() + { + return [ + [new ClassNode(new ElementNode(), 'class'), 'Class[Element[*].class]'], + ]; + } + + public static function getSpecificityValueTestData() + { + return [ + [new ClassNode(new ElementNode(), 'class'), 10], + [new ClassNode(new ElementNode(null, 'element'), 'class'), 11], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php new file mode 100644 index 0000000..d9b2a38 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\CombinedSelectorNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; + +class CombinedSelectorNodeTest extends AbstractNodeTestCase +{ + public static function getToStringConversionTestData() + { + return [ + [new CombinedSelectorNode(new ElementNode(), '>', new ElementNode()), 'CombinedSelector[Element[*] > Element[*]]'], + [new CombinedSelectorNode(new ElementNode(), ' ', new ElementNode()), 'CombinedSelector[Element[*] Element[*]]'], + ]; + } + + public static function getSpecificityValueTestData() + { + return [ + [new CombinedSelectorNode(new ElementNode(), '>', new ElementNode()), 0], + [new CombinedSelectorNode(new ElementNode(null, 'element'), '>', new ElementNode()), 1], + [new CombinedSelectorNode(new ElementNode(null, 'element'), '>', new ElementNode(null, 'element')), 2], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php new file mode 100644 index 0000000..b3ef2b2 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; + +class ElementNodeTest extends AbstractNodeTestCase +{ + public static function getToStringConversionTestData() + { + return [ + [new ElementNode(), 'Element[*]'], + [new ElementNode(null, 'element'), 'Element[element]'], + [new ElementNode('namespace', 'element'), 'Element[namespace|element]'], + ]; + } + + public static function getSpecificityValueTestData() + { + return [ + [new ElementNode(), 0], + [new ElementNode(null, 'element'), 1], + [new ElementNode('namespace', 'element'), 1], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php new file mode 100644 index 0000000..f99a66b --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\FunctionNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; + +class FunctionNodeTest extends AbstractNodeTestCase +{ + public static function getToStringConversionTestData() + { + return [ + [new FunctionNode(new ElementNode(), 'function'), 'Function[Element[*]:function()]'], + [new FunctionNode(new ElementNode(), 'function', [ + new Token(Token::TYPE_IDENTIFIER, 'value', 0), + ]), "Function[Element[*]:function(['value'])]"], + [new FunctionNode(new ElementNode(), 'function', [ + new Token(Token::TYPE_STRING, 'value1', 0), + new Token(Token::TYPE_NUMBER, 'value2', 0), + ]), "Function[Element[*]:function(['value1', 'value2'])]"], + ]; + } + + public static function getSpecificityValueTestData() + { + return [ + [new FunctionNode(new ElementNode(), 'function'), 10], + [new FunctionNode(new ElementNode(), 'function', [ + new Token(Token::TYPE_IDENTIFIER, 'value', 0), + ]), 10], + [new FunctionNode(new ElementNode(), 'function', [ + new Token(Token::TYPE_STRING, 'value1', 0), + new Token(Token::TYPE_NUMBER, 'value2', 0), + ]), 10], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php new file mode 100644 index 0000000..d43aac1 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\HashNode; + +class HashNodeTest extends AbstractNodeTestCase +{ + public static function getToStringConversionTestData() + { + return [ + [new HashNode(new ElementNode(), 'id'), 'Hash[Element[*]#id]'], + ]; + } + + public static function getSpecificityValueTestData() + { + return [ + [new HashNode(new ElementNode(), 'id'), 100], + [new HashNode(new ElementNode(null, 'id'), 'class'), 101], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php new file mode 100644 index 0000000..9aafe8f --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ClassNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\NegationNode; + +class NegationNodeTest extends AbstractNodeTestCase +{ + public static function getToStringConversionTestData() + { + return [ + [new NegationNode(new ElementNode(), new ClassNode(new ElementNode(), 'class')), 'Negation[Element[*]:not(Class[Element[*].class])]'], + ]; + } + + public static function getSpecificityValueTestData() + { + return [ + [new NegationNode(new ElementNode(), new ClassNode(new ElementNode(), 'class')), 10], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php new file mode 100644 index 0000000..cf13881 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\PseudoNode; + +class PseudoNodeTest extends AbstractNodeTestCase +{ + public static function getToStringConversionTestData() + { + return [ + [new PseudoNode(new ElementNode(), 'pseudo'), 'Pseudo[Element[*]:pseudo]'], + ]; + } + + public static function getSpecificityValueTestData() + { + return [ + [new PseudoNode(new ElementNode(), 'pseudo'), 10], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php new file mode 100644 index 0000000..142b104 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; + +class SelectorNodeTest extends AbstractNodeTestCase +{ + public static function getToStringConversionTestData() + { + return [ + [new SelectorNode(new ElementNode()), 'Selector[Element[*]]'], + [new SelectorNode(new ElementNode(), 'pseudo'), 'Selector[Element[*]::pseudo]'], + ]; + } + + public static function getSpecificityValueTestData() + { + return [ + [new SelectorNode(new ElementNode()), 0], + [new SelectorNode(new ElementNode(), 'pseudo'), 1], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php new file mode 100644 index 0000000..790f8c1 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\Specificity; + +class SpecificityTest extends TestCase +{ + /** @dataProvider getValueTestData */ + public function testValue(Specificity $specificity, $value) + { + $this->assertEquals($value, $specificity->getValue()); + } + + /** @dataProvider getValueTestData */ + public function testPlusValue(Specificity $specificity, $value) + { + $this->assertEquals($value + 123, $specificity->plus(new Specificity(1, 2, 3))->getValue()); + } + + public static function getValueTestData() + { + return [ + [new Specificity(0, 0, 0), 0], + [new Specificity(0, 0, 2), 2], + [new Specificity(0, 3, 0), 30], + [new Specificity(4, 0, 0), 400], + [new Specificity(4, 3, 2), 432], + ]; + } + + /** @dataProvider getCompareTestData */ + public function testCompareTo(Specificity $a, Specificity $b, $result) + { + $this->assertEquals($result, $a->compareTo($b)); + } + + public static function getCompareTestData() + { + return [ + [new Specificity(0, 0, 0), new Specificity(0, 0, 0), 0], + [new Specificity(0, 0, 1), new Specificity(0, 0, 1), 0], + [new Specificity(0, 0, 2), new Specificity(0, 0, 1), 1], + [new Specificity(0, 0, 2), new Specificity(0, 0, 3), -1], + [new Specificity(0, 4, 0), new Specificity(0, 4, 0), 0], + [new Specificity(0, 6, 0), new Specificity(0, 5, 11), 1], + [new Specificity(0, 7, 0), new Specificity(0, 8, 0), -1], + [new Specificity(9, 0, 0), new Specificity(9, 0, 0), 0], + [new Specificity(11, 0, 0), new Specificity(10, 11, 0), 1], + [new Specificity(12, 11, 0), new Specificity(13, 0, 0), -1], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTestCase.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTestCase.php new file mode 100644 index 0000000..b46f2f7 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTestCase.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; + +/** + * @author Jean-François Simon + */ +abstract class AbstractHandlerTestCase extends TestCase +{ + /** @dataProvider getHandleValueTestData */ + public function testHandleValue($value, Token $expectedToken, $remainingContent) + { + $reader = new Reader($value); + $stream = new TokenStream(); + + $this->assertTrue($this->generateHandler()->handle($reader, $stream)); + $this->assertEquals($expectedToken, $stream->getNext()); + $this->assertRemainingContent($reader, $remainingContent); + } + + /** @dataProvider getDontHandleValueTestData */ + public function testDontHandleValue($value) + { + $reader = new Reader($value); + $stream = new TokenStream(); + + $this->assertFalse($this->generateHandler()->handle($reader, $stream)); + $this->assertStreamEmpty($stream); + $this->assertRemainingContent($reader, $value); + } + + abstract public static function getHandleValueTestData(); + + abstract public static function getDontHandleValueTestData(); + + abstract protected function generateHandler(); + + protected function assertStreamEmpty(TokenStream $stream) + { + $property = new \ReflectionProperty($stream, 'tokens'); + $property->setAccessible(true); + + $this->assertEquals([], $property->getValue($stream)); + } + + protected function assertRemainingContent(Reader $reader, $remainingContent) + { + if ('' === $remainingContent) { + $this->assertEquals(0, $reader->getRemainingLength()); + $this->assertTrue($reader->isEOF()); + } else { + $this->assertEquals(\strlen($remainingContent), $reader->getRemainingLength()); + $this->assertEquals(0, $reader->getOffset($remainingContent)); + } + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php new file mode 100644 index 0000000..459d8de --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\CommentHandler; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; + +class CommentHandlerTest extends AbstractHandlerTestCase +{ + /** @dataProvider getHandleValueTestData */ + public function testHandleValue($value, Token $unusedArgument, $remainingContent) + { + $reader = new Reader($value); + $stream = new TokenStream(); + + $this->assertTrue($this->generateHandler()->handle($reader, $stream)); + // comments are ignored (not pushed as token in stream) + $this->assertStreamEmpty($stream); + $this->assertRemainingContent($reader, $remainingContent); + } + + public static function getHandleValueTestData() + { + return [ + // 2nd argument only exists for inherited method compatibility + ['/* comment */', new Token(null, null, null), ''], + ['/* comment */foo', new Token(null, null, null), 'foo'], + ]; + } + + public static function getDontHandleValueTestData() + { + return [ + ['>'], + ['+'], + [' '], + ]; + } + + protected function generateHandler() + { + return new CommentHandler(); + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php new file mode 100644 index 0000000..a96c861 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\HashHandler; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; + +class HashHandlerTest extends AbstractHandlerTestCase +{ + public static function getHandleValueTestData() + { + return [ + ['#id', new Token(Token::TYPE_HASH, 'id', 0), ''], + ['#123', new Token(Token::TYPE_HASH, '123', 0), ''], + + ['#id.class', new Token(Token::TYPE_HASH, 'id', 0), '.class'], + ['#id element', new Token(Token::TYPE_HASH, 'id', 0), ' element'], + ]; + } + + public static function getDontHandleValueTestData() + { + return [ + ['id'], + ['123'], + ['<'], + ['<'], + ['#'], + ]; + } + + protected function generateHandler() + { + $patterns = new TokenizerPatterns(); + + return new HashHandler($patterns, new TokenizerEscaping($patterns)); + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php new file mode 100644 index 0000000..1cb9ffe --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\IdentifierHandler; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; + +class IdentifierHandlerTest extends AbstractHandlerTestCase +{ + public static function getHandleValueTestData() + { + return [ + ['foo', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), ''], + ['foo|bar', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '|bar'], + ['foo.class', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '.class'], + ['foo[attr]', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '[attr]'], + ['foo bar', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), ' bar'], + ]; + } + + public static function getDontHandleValueTestData() + { + return [ + ['>'], + ['+'], + [' '], + ['*|foo'], + ['/* comment */'], + ]; + } + + protected function generateHandler() + { + $patterns = new TokenizerPatterns(); + + return new IdentifierHandler($patterns, new TokenizerEscaping($patterns)); + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php new file mode 100644 index 0000000..e40b86f --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\NumberHandler; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; + +class NumberHandlerTest extends AbstractHandlerTestCase +{ + public static function getHandleValueTestData() + { + return [ + ['12', new Token(Token::TYPE_NUMBER, '12', 0), ''], + ['12.34', new Token(Token::TYPE_NUMBER, '12.34', 0), ''], + ['+12.34', new Token(Token::TYPE_NUMBER, '+12.34', 0), ''], + ['-12.34', new Token(Token::TYPE_NUMBER, '-12.34', 0), ''], + + ['12 arg', new Token(Token::TYPE_NUMBER, '12', 0), ' arg'], + ['12]', new Token(Token::TYPE_NUMBER, '12', 0), ']'], + ]; + } + + public static function getDontHandleValueTestData() + { + return [ + ['hello'], + ['>'], + ['+'], + [' '], + ['/* comment */'], + ]; + } + + protected function generateHandler() + { + $patterns = new TokenizerPatterns(); + + return new NumberHandler($patterns); + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php new file mode 100644 index 0000000..d00233c --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\StringHandler; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; + +class StringHandlerTest extends AbstractHandlerTestCase +{ + public static function getHandleValueTestData() + { + return [ + ['"hello"', new Token(Token::TYPE_STRING, 'hello', 1), ''], + ['"1"', new Token(Token::TYPE_STRING, '1', 1), ''], + ['" "', new Token(Token::TYPE_STRING, ' ', 1), ''], + ['""', new Token(Token::TYPE_STRING, '', 1), ''], + ["'hello'", new Token(Token::TYPE_STRING, 'hello', 1), ''], + + ["'foo'bar", new Token(Token::TYPE_STRING, 'foo', 1), 'bar'], + ]; + } + + public static function getDontHandleValueTestData() + { + return [ + ['hello'], + ['>'], + ['1'], + [' '], + ]; + } + + protected function generateHandler() + { + $patterns = new TokenizerPatterns(); + + return new StringHandler($patterns, new TokenizerEscaping($patterns)); + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php new file mode 100644 index 0000000..1cd3e9d --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; + +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\WhitespaceHandler; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; + +class WhitespaceHandlerTest extends AbstractHandlerTestCase +{ + public static function getHandleValueTestData() + { + return [ + [' ', new Token(Token::TYPE_WHITESPACE, ' ', 0), ''], + ["\n", new Token(Token::TYPE_WHITESPACE, "\n", 0), ''], + ["\t", new Token(Token::TYPE_WHITESPACE, "\t", 0), ''], + + [' foo', new Token(Token::TYPE_WHITESPACE, ' ', 0), 'foo'], + [' .foo', new Token(Token::TYPE_WHITESPACE, ' ', 0), '.foo'], + ]; + } + + public static function getDontHandleValueTestData() + { + return [ + ['>'], + ['1'], + ['a'], + ]; + } + + protected function generateHandler() + { + return new WhitespaceHandler(); + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ParserTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ParserTest.php new file mode 100644 index 0000000..a9ef9d6 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ParserTest.php @@ -0,0 +1,263 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\SyntaxErrorException; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\FunctionNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Parser; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; + +class ParserTest extends TestCase +{ + /** @dataProvider getParserTestData */ + public function testParser($source, $representation) + { + $parser = new Parser(); + + $this->assertEquals($representation, array_map(function (SelectorNode $node) { + return (string) $node->getTree(); + }, $parser->parse($source))); + } + + /** @dataProvider getParserExceptionTestData */ + public function testParserException($source, $message) + { + $parser = new Parser(); + + try { + $parser->parse($source); + $this->fail('Parser should throw a SyntaxErrorException.'); + } catch (SyntaxErrorException $e) { + $this->assertEquals($message, $e->getMessage()); + } + } + + /** @dataProvider getPseudoElementsTestData */ + public function testPseudoElements($source, $element, $pseudo) + { + $parser = new Parser(); + $selectors = $parser->parse($source); + $this->assertCount(1, $selectors); + + /** @var SelectorNode $selector */ + $selector = $selectors[0]; + $this->assertEquals($element, (string) $selector->getTree()); + $this->assertEquals($pseudo, (string) $selector->getPseudoElement()); + } + + /** @dataProvider getSpecificityTestData */ + public function testSpecificity($source, $value) + { + $parser = new Parser(); + $selectors = $parser->parse($source); + $this->assertCount(1, $selectors); + + /** @var SelectorNode $selector */ + $selector = $selectors[0]; + $this->assertEquals($value, $selector->getSpecificity()->getValue()); + } + + /** @dataProvider getParseSeriesTestData */ + public function testParseSeries($series, $a, $b) + { + $parser = new Parser(); + $selectors = $parser->parse(sprintf(':nth-child(%s)', $series)); + $this->assertCount(1, $selectors); + + /** @var FunctionNode $function */ + $function = $selectors[0]->getTree(); + $this->assertEquals([$a, $b], Parser::parseSeries($function->getArguments())); + } + + /** @dataProvider getParseSeriesExceptionTestData */ + public function testParseSeriesException($series) + { + $parser = new Parser(); + $selectors = $parser->parse(sprintf(':nth-child(%s)', $series)); + $this->assertCount(1, $selectors); + + /** @var FunctionNode $function */ + $function = $selectors[0]->getTree(); + $this->expectException(SyntaxErrorException::class); + Parser::parseSeries($function->getArguments()); + } + + public static function getParserTestData() + { + return [ + ['*', ['Element[*]']], + ['*|*', ['Element[*]']], + ['*|foo', ['Element[foo]']], + ['foo|*', ['Element[foo|*]']], + ['foo|bar', ['Element[foo|bar]']], + ['#foo#bar', ['Hash[Hash[Element[*]#foo]#bar]']], + ['div>.foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']], + ['div> .foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']], + ['div >.foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']], + ['div > .foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']], + ["div \n> \t \t .foo", ['CombinedSelector[Element[div] > Class[Element[*].foo]]']], + ['td.foo,.bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']], + ['td.foo, .bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']], + ["td.foo\t\r\n\f ,\t\r\n\f .bar", ['Class[Element[td].foo]', 'Class[Element[*].bar]']], + ['td.foo,.bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']], + ['td.foo, .bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']], + ["td.foo\t\r\n\f ,\t\r\n\f .bar", ['Class[Element[td].foo]', 'Class[Element[*].bar]']], + ['div, td.foo, div.bar span', ['Element[div]', 'Class[Element[td].foo]', 'CombinedSelector[Class[Element[div].bar] Element[span]]']], + ['div > p', ['CombinedSelector[Element[div] > Element[p]]']], + ['td:first', ['Pseudo[Element[td]:first]']], + ['td :first', ['CombinedSelector[Element[td] Pseudo[Element[*]:first]]']], + ['a[name]', ['Powered_Cache_Attribute[Element[a][name]]']], + ["a[ name\t]", ['Powered_Cache_Attribute[Element[a][name]]']], + ['a [name]', ['CombinedSelector[Element[a] Powered_Cache_Attribute[Element[*][name]]]']], + ['[name="foo"]', ["Powered_Cache_Attribute[Element[*][name = 'foo']]"]], + ["[name='foo[1]']", ["Powered_Cache_Attribute[Element[*][name = 'foo[1]']]"]], + ["[name='foo[0][bar]']", ["Powered_Cache_Attribute[Element[*][name = 'foo[0][bar]']]"]], + ['a[rel="include"]', ["Attribute[Element[a][rel = 'include']]"]], + ['a[rel = include]', ["Attribute[Element[a][rel = 'include']]"]], + ["a[hreflang |= 'en']", ["Powered_Cache_Attribute[Element[a][hreflang |= 'en']]"]], + ['a[hreflang|=en]', ["Powered_Cache_Attribute[Element[a][hreflang |= 'en']]"]], + ['div:nth-child(10)', ["Function[Element[div]:nth-child(['10'])]"]], + [':nth-child(2n+2)', ["Function[Element[*]:nth-child(['2', 'n', '+2'])]"]], + ['div:nth-of-type(10)', ["Function[Element[div]:nth-of-type(['10'])]"]], + ['div div:nth-of-type(10) .aclass', ["CombinedSelector[CombinedSelector[Element[div] Function[Element[div]:nth-of-type(['10'])]] Class[Element[*].aclass]]"]], + ['label:only', ['Pseudo[Element[label]:only]']], + ['a:lang(fr)', ["Function[Element[a]:lang(['fr'])]"]], + ['div:contains("foo")', ["Function[Element[div]:contains(['foo'])]"]], + ['div#foobar', ['Hash[Element[div]#foobar]']], + ['div:not(div.foo)', ['Negation[Element[div]:not(Class[Element[div].foo])]']], + ['td ~ th', ['CombinedSelector[Element[td] ~ Element[th]]']], + ['.foo[data-bar][data-baz=0]', ["Powered_Cache_Attribute[Attribute[Class[Element[*].foo][data-bar]][data-baz = '0']]"]], + ['div#foo\.bar', ['Hash[Element[div]#foo.bar]']], + ['div.w-1\/3', ['Class[Element[div].w-1/3]']], + ['#test\:colon', ['Hash[Element[*]#test:colon]']], + [".a\xc1b", ["Class[Element[*].a\xc1b]"]], + // unicode escape: \22 == " + ['*[aval="\'\22\'"]', ['Powered_Cache_Attribute[Element[*][aval = \'\'"\'\']]']], + ['*[aval="\'\22 2\'"]', ['Powered_Cache_Attribute[Element[*][aval = \'\'"2\'\']]']], + // unicode escape: \20 == (space) + ['*[aval="\'\20 \'"]', ['Powered_Cache_Attribute[Element[*][aval = \'\' \'\']]']], + ["*[aval=\"'\\20\r\n '\"]", ['Powered_Cache_Attribute[Element[*][aval = \'\' \'\']]']], + ]; + } + + public static function getParserExceptionTestData() + { + return [ + ['attributes(href)/html/body/a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '(', 10))->getMessage()], + ['attributes(href)', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '(', 10))->getMessage()], + ['html/body/a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '/', 4))->getMessage()], + [' ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 1))->getMessage()], + ['div, ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 5))->getMessage()], + [' , div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, ',', 1))->getMessage()], + ['p, , div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, ',', 3))->getMessage()], + ['div > ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 6))->getMessage()], + [' > div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '>', 2))->getMessage()], + ['foo|#bar', SyntaxErrorException::unexpectedToken('identifier or "*"', new Token(Token::TYPE_HASH, 'bar', 4))->getMessage()], + ['#.foo', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '#', 0))->getMessage()], + ['.#foo', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_HASH, 'foo', 1))->getMessage()], + [':#foo', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_HASH, 'foo', 1))->getMessage()], + ['[*]', SyntaxErrorException::unexpectedToken('"|"', new Token(Token::TYPE_DELIMITER, ']', 2))->getMessage()], + ['[foo|]', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_DELIMITER, ']', 5))->getMessage()], + ['[#]', SyntaxErrorException::unexpectedToken('identifier or "*"', new Token(Token::TYPE_DELIMITER, '#', 1))->getMessage()], + ['[foo=#]', SyntaxErrorException::unexpectedToken('string or identifier', new Token(Token::TYPE_DELIMITER, '#', 5))->getMessage()], + [':nth-child()', SyntaxErrorException::unexpectedToken('at least one argument', new Token(Token::TYPE_DELIMITER, ')', 11))->getMessage()], + ['[href]a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_IDENTIFIER, 'a', 6))->getMessage()], + ['[rel:stylesheet]', SyntaxErrorException::unexpectedToken('operator', new Token(Token::TYPE_DELIMITER, ':', 4))->getMessage()], + ['[rel=stylesheet', SyntaxErrorException::unexpectedToken('"]"', new Token(Token::TYPE_FILE_END, '', 15))->getMessage()], + [':lang(fr', SyntaxErrorException::unexpectedToken('an argument', new Token(Token::TYPE_FILE_END, '', 8))->getMessage()], + [':contains("foo', SyntaxErrorException::unclosedString(10)->getMessage()], + ['foo!', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '!', 3))->getMessage()], + ]; + } + + public static function getPseudoElementsTestData() + { + return [ + ['foo', 'Element[foo]', ''], + ['*', 'Element[*]', ''], + [':empty', 'Pseudo[Element[*]:empty]', ''], + [':BEfore', 'Element[*]', 'before'], + [':aftER', 'Element[*]', 'after'], + [':First-Line', 'Element[*]', 'first-line'], + [':First-Letter', 'Element[*]', 'first-letter'], + ['::befoRE', 'Element[*]', 'before'], + ['::AFter', 'Element[*]', 'after'], + ['::firsT-linE', 'Element[*]', 'first-line'], + ['::firsT-letteR', 'Element[*]', 'first-letter'], + ['::Selection', 'Element[*]', 'selection'], + ['foo:after', 'Element[foo]', 'after'], + ['foo::selection', 'Element[foo]', 'selection'], + ['lorem#ipsum ~ a#b.c[href]:empty::selection', 'CombinedSelector[Hash[Element[lorem]#ipsum] ~ Pseudo[Powered_Cache_Attribute[Class[Hash[Element[a]#b].c][href]]:empty]]', 'selection'], + ['video::-webkit-media-controls', 'Element[video]', '-webkit-media-controls'], + ]; + } + + public static function getSpecificityTestData() + { + return [ + ['*', 0], + [' foo', 1], + [':empty ', 10], + [':before', 1], + ['*:before', 1], + [':nth-child(2)', 10], + ['.bar', 10], + ['[baz]', 10], + ['[baz="4"]', 10], + ['[baz^="4"]', 10], + ['#lipsum', 100], + [':not(*)', 0], + [':not(foo)', 1], + [':not(.foo)', 10], + [':not([foo])', 10], + [':not(:empty)', 10], + [':not(#foo)', 100], + ['foo:empty', 11], + ['foo:before', 2], + ['foo::before', 2], + ['foo:empty::before', 12], + ['#lorem + foo#ipsum:first-child > bar:first-line', 213], + ]; + } + + public static function getParseSeriesTestData() + { + return [ + ['1n+3', 1, 3], + ['1n +3', 1, 3], + ['1n + 3', 1, 3], + ['1n+ 3', 1, 3], + ['1n-3', 1, -3], + ['1n -3', 1, -3], + ['1n - 3', 1, -3], + ['1n- 3', 1, -3], + ['n-5', 1, -5], + ['odd', 2, 1], + ['even', 2, 0], + ['3n', 3, 0], + ['n', 1, 0], + ['+n', 1, 0], + ['-n', -1, 0], + ['5', 0, 5], + ]; + } + + public static function getParseSeriesExceptionTestData() + { + return [ + ['foo'], + ['n+'], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php new file mode 100644 index 0000000..b160113 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; + +class ReaderTest extends TestCase +{ + public function testIsEOF() + { + $reader = new Reader(''); + $this->assertTrue($reader->isEOF()); + + $reader = new Reader('hello'); + $this->assertFalse($reader->isEOF()); + + $this->assignPosition($reader, 2); + $this->assertFalse($reader->isEOF()); + + $this->assignPosition($reader, 5); + $this->assertTrue($reader->isEOF()); + } + + public function testGetRemainingLength() + { + $reader = new Reader('hello'); + $this->assertEquals(5, $reader->getRemainingLength()); + + $this->assignPosition($reader, 2); + $this->assertEquals(3, $reader->getRemainingLength()); + + $this->assignPosition($reader, 5); + $this->assertEquals(0, $reader->getRemainingLength()); + } + + public function testGetSubstring() + { + $reader = new Reader('hello'); + $this->assertEquals('he', $reader->getSubstring(2)); + $this->assertEquals('el', $reader->getSubstring(2, 1)); + + $this->assignPosition($reader, 2); + $this->assertEquals('ll', $reader->getSubstring(2)); + $this->assertEquals('lo', $reader->getSubstring(2, 1)); + } + + public function testGetOffset() + { + $reader = new Reader('hello'); + $this->assertEquals(2, $reader->getOffset('ll')); + $this->assertFalse($reader->getOffset('w')); + + $this->assignPosition($reader, 2); + $this->assertEquals(0, $reader->getOffset('ll')); + $this->assertFalse($reader->getOffset('he')); + } + + public function testFindPattern() + { + $reader = new Reader('hello'); + + $this->assertFalse($reader->findPattern('/world/')); + $this->assertEquals(['hello', 'h'], $reader->findPattern('/^([a-z]).*/')); + + $this->assignPosition($reader, 2); + $this->assertFalse($reader->findPattern('/^h.*/')); + $this->assertEquals(['llo'], $reader->findPattern('/^llo$/')); + } + + public function testMoveForward() + { + $reader = new Reader('hello'); + $this->assertEquals(0, $reader->getPosition()); + + $reader->moveForward(2); + $this->assertEquals(2, $reader->getPosition()); + } + + public function testToEnd() + { + $reader = new Reader('hello'); + $reader->moveToEnd(); + $this->assertTrue($reader->isEOF()); + } + + private function assignPosition(Reader $reader, int $value) + { + $position = new \ReflectionProperty($reader, 'position'); + $position->setAccessible(true); + $position->setValue($reader, $value); + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php new file mode 100644 index 0000000..188d29f --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Shortcut; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\ClassParser; + +/** + * @author Jean-François Simon + */ +class ClassParserTest extends TestCase +{ + /** @dataProvider getParseTestData */ + public function testParse($source, $representation) + { + $parser = new ClassParser(); + $selectors = $parser->parse($source); + $this->assertCount(1, $selectors); + + /** @var SelectorNode $selector */ + $selector = $selectors[0]; + $this->assertEquals($representation, (string) $selector->getTree()); + } + + public static function getParseTestData() + { + return [ + ['.testclass', 'Class[Element[*].testclass]'], + ['testel.testclass', 'Class[Element[testel].testclass]'], + ['testns|.testclass', 'Class[Element[testns|*].testclass]'], + ['testns|*.testclass', 'Class[Element[testns|*].testclass]'], + ['testns|testel.testclass', 'Class[Element[testns|testel].testclass]'], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php new file mode 100644 index 0000000..58540ea --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Shortcut; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\ElementParser; + +/** + * @author Jean-François Simon + */ +class ElementParserTest extends TestCase +{ + /** @dataProvider getParseTestData */ + public function testParse($source, $representation) + { + $parser = new ElementParser(); + $selectors = $parser->parse($source); + $this->assertCount(1, $selectors); + + /** @var SelectorNode $selector */ + $selector = $selectors[0]; + $this->assertEquals($representation, (string) $selector->getTree()); + } + + public static function getParseTestData() + { + return [ + ['*', 'Element[*]'], + ['testel', 'Element[testel]'], + ['testns|*', 'Element[testns|*]'], + ['testns|testel', 'Element[testns|testel]'], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php new file mode 100644 index 0000000..b6540ff --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Shortcut; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser; + +/** + * @author Jean-François Simon + */ +class EmptyStringParserTest extends TestCase +{ + public function testParse() + { + $parser = new EmptyStringParser(); + $selectors = $parser->parse(''); + $this->assertCount(1, $selectors); + + /** @var SelectorNode $selector */ + $selector = $selectors[0]; + $this->assertEquals('Element[*]', (string) $selector->getTree()); + + $selectors = $parser->parse('this will produce an empty array'); + $this->assertCount(0, $selectors); + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php new file mode 100644 index 0000000..9a92ca4 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Shortcut; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\HashParser; + +/** + * @author Jean-François Simon + */ +class HashParserTest extends TestCase +{ + /** @dataProvider getParseTestData */ + public function testParse($source, $representation) + { + $parser = new HashParser(); + $selectors = $parser->parse($source); + $this->assertCount(1, $selectors); + + /** @var SelectorNode $selector */ + $selector = $selectors[0]; + $this->assertEquals($representation, (string) $selector->getTree()); + } + + public static function getParseTestData() + { + return [ + ['#testid', 'Hash[Element[*]#testid]'], + ['testel#testid', 'Hash[Element[testel]#testid]'], + ['testns|#testid', 'Hash[Element[testns|*]#testid]'], + ['testns|*#testid', 'Hash[Element[testns|*]#testid]'], + ['testns|testel#testid', 'Hash[Element[testns|testel]#testid]'], + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php new file mode 100644 index 0000000..ec7f7f5 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\SyntaxErrorException; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; + +class TokenStreamTest extends TestCase +{ + public function testGetNext() + { + $stream = new TokenStream(); + $stream->push($t1 = new Token(Token::TYPE_IDENTIFIER, 'h1', 0)); + $stream->push($t2 = new Token(Token::TYPE_DELIMITER, '.', 2)); + $stream->push($t3 = new Token(Token::TYPE_IDENTIFIER, 'title', 3)); + + $this->assertSame($t1, $stream->getNext()); + $this->assertSame($t2, $stream->getNext()); + $this->assertSame($t3, $stream->getNext()); + } + + public function testGetPeek() + { + $stream = new TokenStream(); + $stream->push($t1 = new Token(Token::TYPE_IDENTIFIER, 'h1', 0)); + $stream->push($t2 = new Token(Token::TYPE_DELIMITER, '.', 2)); + $stream->push($t3 = new Token(Token::TYPE_IDENTIFIER, 'title', 3)); + + $this->assertSame($t1, $stream->getPeek()); + $this->assertSame($t1, $stream->getNext()); + $this->assertSame($t2, $stream->getPeek()); + $this->assertSame($t2, $stream->getPeek()); + $this->assertSame($t2, $stream->getNext()); + } + + public function testGetNextIdentifier() + { + $stream = new TokenStream(); + $stream->push(new Token(Token::TYPE_IDENTIFIER, 'h1', 0)); + + $this->assertEquals('h1', $stream->getNextIdentifier()); + } + + public function testFailToGetNextIdentifier() + { + $this->expectException(SyntaxErrorException::class); + + $stream = new TokenStream(); + $stream->push(new Token(Token::TYPE_DELIMITER, '.', 2)); + $stream->getNextIdentifier(); + } + + public function testGetNextIdentifierOrStar() + { + $stream = new TokenStream(); + + $stream->push(new Token(Token::TYPE_IDENTIFIER, 'h1', 0)); + $this->assertEquals('h1', $stream->getNextIdentifierOrStar()); + + $stream->push(new Token(Token::TYPE_DELIMITER, '*', 0)); + $this->assertNull($stream->getNextIdentifierOrStar()); + } + + public function testFailToGetNextIdentifierOrStar() + { + $this->expectException(SyntaxErrorException::class); + + $stream = new TokenStream(); + $stream->push(new Token(Token::TYPE_DELIMITER, '.', 2)); + $stream->getNextIdentifierOrStar(); + } + + public function testSkipWhitespace() + { + $stream = new TokenStream(); + $stream->push($t1 = new Token(Token::TYPE_IDENTIFIER, 'h1', 0)); + $stream->push($t2 = new Token(Token::TYPE_WHITESPACE, ' ', 2)); + $stream->push($t3 = new Token(Token::TYPE_IDENTIFIER, 'h1', 3)); + + $stream->skipWhitespace(); + $this->assertSame($t1, $stream->getNext()); + + $stream->skipWhitespace(); + $this->assertSame($t3, $stream->getNext()); + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html new file mode 100644 index 0000000..1147bf3 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html @@ -0,0 +1,52 @@ + + + + +
+ + + + link +
    +
  1. content
  2. +
  3. +
    +
    +
  4. +
  5. +
  6. +
  7. +
  8. +
  9. +
+

+ hi there + guy + + + + + + + +

+ + +
+

+
    +
+ + + + +
+
+
+ +
+ + diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml new file mode 100644 index 0000000..14f8dbe --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml @@ -0,0 +1,11 @@ + + a + b + c + d + e + f + + + + diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html new file mode 100644 index 0000000..15d1ad3 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html @@ -0,0 +1,308 @@ + + + + + + +
+
+

As You Like It

+
+ by William Shakespeare +
+
+

ACT I, SCENE III. A room in the palace.

+
+
Enter CELIA and ROSALIND
+
+
CELIA
+
+
Why, cousin! why, Rosalind! Cupid have mercy! not a word?
+
+
ROSALIND
+
+
Not one to throw at a dog.
+
+
CELIA
+
+
No, thy words are too precious to be cast away upon
+
curs; throw some of them at me; come, lame me with reasons.
+
+
ROSALIND
+
CELIA
+
+
But is all this for your father?
+
+
+
Then there were two cousins laid up; when the one
+
should be lamed with reasons and the other mad
+
without any.
+
+
ROSALIND
+
+
No, some of it is for my child's father. O, how
+
full of briers is this working-day world!
+
+
CELIA
+
+
They are but burs, cousin, thrown upon thee in
+
holiday foolery: if we walk not in the trodden
+
paths our very petticoats will catch them.
+
+
ROSALIND
+
+
I could shake them off my coat: these burs are in my heart.
+
+
CELIA
+
+
Hem them away.
+
+
ROSALIND
+
+
I would try, if I could cry 'hem' and have him.
+
+
CELIA
+
+
Come, come, wrestle with thy affections.
+
+
ROSALIND
+
+
O, they take the part of a better wrestler than myself!
+
+
CELIA
+
+
O, a good wish upon you! you will try in time, in
+
despite of a fall. But, turning these jests out of
+
service, let us talk in good earnest: is it
+
possible, on such a sudden, you should fall into so
+
strong a liking with old Sir Rowland's youngest son?
+
+
ROSALIND
+
+
The duke my father loved his father dearly.
+
+
CELIA
+
+
Doth it therefore ensue that you should love his son
+
dearly? By this kind of chase, I should hate him,
+
for my father hated his father dearly; yet I hate
+
not Orlando.
+
+
ROSALIND
+
+
No, faith, hate him not, for my sake.
+
+
CELIA
+
+
Why should I not? doth he not deserve well?
+
+
ROSALIND
+
+
Let me love him for that, and do you love him
+
because I do. Look, here comes the duke.
+
+
CELIA
+
+
With his eyes full of anger.
+
Enter DUKE FREDERICK, with Lords
+
+
DUKE FREDERICK
+
+
Mistress, dispatch you with your safest haste
+
And get you from our court.
+
+
ROSALIND
+
+
Me, uncle?
+
+
DUKE FREDERICK
+
+
You, cousin
+
Within these ten days if that thou be'st found
+
So near our public court as twenty miles,
+
Thou diest for it.
+
+
ROSALIND
+
+
I do beseech your grace,
+
Let me the knowledge of my fault bear with me:
+
If with myself I hold intelligence
+
Or have acquaintance with mine own desires,
+
If that I do not dream or be not frantic,--
+
As I do trust I am not--then, dear uncle,
+
Never so much as in a thought unborn
+
Did I offend your highness.
+
+
DUKE FREDERICK
+
+
Thus do all traitors:
+
If their purgation did consist in words,
+
They are as innocent as grace itself:
+
Let it suffice thee that I trust thee not.
+
+
ROSALIND
+
+
Yet your mistrust cannot make me a traitor:
+
Tell me whereon the likelihood depends.
+
+
DUKE FREDERICK
+
+
Thou art thy father's daughter; there's enough.
+
+
ROSALIND
+
+
So was I when your highness took his dukedom;
+
So was I when your highness banish'd him:
+
Treason is not inherited, my lord;
+
Or, if we did derive it from our friends,
+
What's that to me? my father was no traitor:
+
Then, good my liege, mistake me not so much
+
To think my poverty is treacherous.
+
+
CELIA
+
+
Dear sovereign, hear me speak.
+
+
DUKE FREDERICK
+
+
Ay, Celia; we stay'd her for your sake,
+
Else had she with her father ranged along.
+
+
CELIA
+
+
I did not then entreat to have her stay;
+
It was your pleasure and your own remorse:
+
I was too young that time to value her;
+
But now I know her: if she be a traitor,
+
Why so am I; we still have slept together,
+
Rose at an instant, learn'd, play'd, eat together,
+
And wheresoever we went, like Juno's swans,
+
Still we went coupled and inseparable.
+
+
DUKE FREDERICK
+
+
She is too subtle for thee; and her smoothness,
+
Her very silence and her patience
+
Speak to the people, and they pity her.
+
Thou art a fool: she robs thee of thy name;
+
And thou wilt show more bright and seem more virtuous
+
When she is gone. Then open not thy lips:
+
Firm and irrevocable is my doom
+
Which I have pass'd upon her; she is banish'd.
+
+
CELIA
+
+
Pronounce that sentence then on me, my liege:
+
I cannot live out of her company.
+
+
DUKE FREDERICK
+
+
You are a fool. You, niece, provide yourself:
+
If you outstay the time, upon mine honour,
+
And in the greatness of my word, you die.
+
Exeunt DUKE FREDERICK and Lords
+
+
CELIA
+
+
O my poor Rosalind, whither wilt thou go?
+
Wilt thou change fathers? I will give thee mine.
+
I charge thee, be not thou more grieved than I am.
+
+
ROSALIND
+
+
I have more cause.
+
+
CELIA
+
+
Thou hast not, cousin;
+
Prithee be cheerful: know'st thou not, the duke
+
Hath banish'd me, his daughter?
+
+
ROSALIND
+
+
That he hath not.
+
+
CELIA
+
+
No, hath not? Rosalind lacks then the love
+
Which teacheth thee that thou and I am one:
+
Shall we be sunder'd? shall we part, sweet girl?
+
No: let my father seek another heir.
+
Therefore devise with me how we may fly,
+
Whither to go and what to bear with us;
+
And do not seek to take your change upon you,
+
To bear your griefs yourself and leave me out;
+
For, by this heaven, now at our sorrows pale,
+
Say what thou canst, I'll go along with thee.
+
+
ROSALIND
+
+
Why, whither shall we go?
+
+
CELIA
+
+
To seek my uncle in the forest of Arden.
+
+
ROSALIND
+
+
Alas, what danger will it be to us,
+
Maids as we are, to travel forth so far!
+
Beauty provoketh thieves sooner than gold.
+
+
CELIA
+
+
I'll put myself in poor and mean attire
+
And with a kind of umber smirch my face;
+
The like do you: so shall we pass along
+
And never stir assailants.
+
+
ROSALIND
+
+
Were it not better,
+
Because that I am more than common tall,
+
That I did suit me all points like a man?
+
A gallant curtle-axe upon my thigh,
+
A boar-spear in my hand; and--in my heart
+
Lie there what hidden woman's fear there will--
+
We'll have a swashing and a martial outside,
+
As many other mannish cowards have
+
That do outface it with their semblances.
+
+
CELIA
+
+
What shall I call thee when thou art a man?
+
+
ROSALIND
+
+
I'll have no worse a name than Jove's own page;
+
And therefore look you call me Ganymede.
+
But what will you be call'd?
+
+
CELIA
+
+
Something that hath a reference to my state
+
No longer Celia, but Aliena.
+
+
ROSALIND
+
+
But, cousin, what if we assay'd to steal
+
The clownish fool out of your father's court?
+
Would he not be a comfort to our travel?
+
+
CELIA
+
+
He'll go along o'er the wide world with me;
+
Leave me alone to woo him. Let's away,
+
And get our jewels and our wealth together,
+
Devise the fittest time and safest way
+
To hide us from pursuit that will be made
+
After my flight. Now go we in content
+
To liberty and not to banishment.
+
Exeunt
+
+
+
+
+ + diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php new file mode 100644 index 0000000..fad6105 --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php @@ -0,0 +1,416 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\XPath; + +use PHPUnit\Framework\TestCase; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\ExpressionErrorException; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\FunctionNode; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Parser; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Extension\HtmlExtension; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Translator; +use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\XPathExpr; + +class TranslatorTest extends TestCase +{ + /** @dataProvider getXpathLiteralTestData */ + public function testXpathLiteral($value, $literal) + { + $this->assertEquals($literal, Translator::getXpathLiteral($value)); + } + + /** @dataProvider getCssToXPathTestData */ + public function testCssToXPath($css, $xpath) + { + $translator = new Translator(); + $translator->registerExtension(new HtmlExtension($translator)); + $this->assertEquals($xpath, $translator->cssToXPath($css, '')); + } + + public function testCssToXPathPseudoElement() + { + $this->expectException(ExpressionErrorException::class); + $translator = new Translator(); + $translator->registerExtension(new HtmlExtension($translator)); + $translator->cssToXPath('e::first-line'); + } + + public function testGetExtensionNotExistsExtension() + { + $this->expectException(ExpressionErrorException::class); + $translator = new Translator(); + $translator->registerExtension(new HtmlExtension($translator)); + $translator->getExtension('fake'); + } + + public function testAddCombinationNotExistsExtension() + { + $this->expectException(ExpressionErrorException::class); + $translator = new Translator(); + $translator->registerExtension(new HtmlExtension($translator)); + $parser = new Parser(); + $xpath = $parser->parse('*')[0]; + $combinedXpath = $parser->parse('*')[0]; + $translator->addCombination('fake', $xpath, $combinedXpath); + } + + public function testAddFunctionNotExistsFunction() + { + $this->expectException(ExpressionErrorException::class); + $translator = new Translator(); + $translator->registerExtension(new HtmlExtension($translator)); + $xpath = new XPathExpr(); + $function = new FunctionNode(new ElementNode(), 'fake'); + $translator->addFunction($xpath, $function); + } + + public function testAddPseudoClassNotExistsClass() + { + $this->expectException(ExpressionErrorException::class); + $translator = new Translator(); + $translator->registerExtension(new HtmlExtension($translator)); + $xpath = new XPathExpr(); + $translator->addPseudoClass($xpath, 'fake'); + } + + public function testAddAttributeMatchingClassNotExistsClass() + { + $this->expectException(ExpressionErrorException::class); + $translator = new Translator(); + $translator->registerExtension(new HtmlExtension($translator)); + $xpath = new XPathExpr(); + $translator->addAttributeMatching($xpath, '', '', ''); + } + + /** @dataProvider getXmlLangTestData */ + public function testXmlLang($css, array $elementsId) + { + $translator = new Translator(); + $document = new \SimpleXMLElement(file_get_contents(__DIR__.'/Fixtures/lang.xml')); + $elements = $document->xpath($translator->cssToXPath($css)); + $this->assertCount(\count($elementsId), $elements); + foreach ($elements as $element) { + $this->assertContains((string) $element->attributes()->id, $elementsId); + } + } + + /** @dataProvider getHtmlIdsTestData */ + public function testHtmlIds($css, array $elementsId) + { + $translator = new Translator(); + $translator->registerExtension(new HtmlExtension($translator)); + $document = new \DOMDocument(); + $document->strictErrorChecking = false; + $internalErrors = libxml_use_internal_errors(true); + $document->loadHTMLFile(__DIR__.'/Fixtures/ids.html'); + $document = simplexml_import_dom($document); + $elements = $document->xpath($translator->cssToXPath($css)); + $this->assertCount(\count($elementsId), $elements); + foreach ($elements as $element) { + if (null !== $element->attributes()->id) { + $this->assertContains((string) $element->attributes()->id, $elementsId); + } + } + libxml_clear_errors(); + libxml_use_internal_errors($internalErrors); + } + + /** @dataProvider getHtmlShakespearTestData */ + public function testHtmlShakespear($css, $count) + { + $translator = new Translator(); + $translator->registerExtension(new HtmlExtension($translator)); + $document = new \DOMDocument(); + $document->strictErrorChecking = false; + $document->loadHTMLFile(__DIR__.'/Fixtures/shakespear.html'); + $document = simplexml_import_dom($document); + $bodies = $document->xpath('//body'); + $elements = $bodies[0]->xpath($translator->cssToXPath($css)); + $this->assertCount($count, $elements); + } + + public function testOnlyOfTypeFindsSingleChildrenOfGivenType() + { + $translator = new Translator(); + $translator->registerExtension(new HtmlExtension($translator)); + $document = new \DOMDocument(); + $document->loadHTML(<<<'HTML' + + +

+ A +

+

+ B + C +

+ + +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 static function getXpathLiteralTestData() + { + return [ + ['foo', "'foo'"], + ["foo's bar", '"foo\'s bar"'], + ["foo's \"middle\" bar", 'concat(\'foo\', "\'", \'s "middle" bar\')'], + ["foo's 'middle' \"bar\"", 'concat(\'foo\', "\'", \'s \', "\'", \'middle\', "\'", \' "bar"\')'], + ]; + } + + public static function getCssToXPathTestData() + { + return [ + ['*', '*'], + ['e', 'e'], + ['*|e', 'e'], + ['e|f', 'e:f'], + ['e[foo]', 'e[@foo]'], + ['e[foo|bar]', 'e[@foo:bar]'], + ['e[foo="bar"]', "e[@foo = 'bar']"], + ['e[foo~="bar"]', "e[@foo and contains(concat(' ', normalize-space(@foo), ' '), ' bar ')]"], + ['e[foo^="bar"]', "e[@foo and starts-with(@foo, 'bar')]"], + ['e[foo$="bar"]', "e[@foo and substring(@foo, string-length(@foo)-2) = 'bar']"], + ['e[foo*="bar"]', "e[@foo and contains(@foo, 'bar')]"], + ['e[foo!="bar"]', "e[not(@foo) or @foo != 'bar']"], + ['e[foo!="bar"][foo!="baz"]', "e[(not(@foo) or @foo != 'bar') and (not(@foo) or @foo != 'baz')]"], + ['e[hreflang|="en"]', "e[@hreflang and (@hreflang = 'en' or starts-with(@hreflang, 'en-'))]"], + ['e:nth-child(1)', "*/*[(name() = 'e') and (position() = 1)]"], + ['e:nth-last-child(1)', "*/*[(name() = 'e') and (position() = last() - 0)]"], + ['e:nth-last-child(2n+2)', "*/*[(name() = 'e') and (last() - position() - 1 >= 0 and (last() - position() - 1) mod 2 = 0)]"], + ['e:nth-of-type(1)', '*/e[position() = 1]'], + ['e:nth-last-of-type(1)', '*/e[position() = last() - 0]'], + ['div e:nth-last-of-type(1) .aclass', "div/descendant-or-self::*/e[position() = last() - 0]/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' aclass ')]"], + ['e:first-child', "*/*[(name() = 'e') and (position() = 1)]"], + ['e:last-child', "*/*[(name() = 'e') and (position() = last())]"], + ['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[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::*)]'], + ['e:hover', 'e[0]'], + ['e:contains("foo")', "e[contains(string(.), 'foo')]"], + ['e:ConTains(foo)', "e[contains(string(.), 'foo')]"], + ['e.warning', "e[@class and contains(concat(' ', normalize-space(@class), ' '), ' warning ')]"], + ['e#myid', "e[@id = 'myid']"], + ['e:not(:nth-child(odd))', 'e[not(position() - 1 >= 0 and (position() - 1) mod 2 = 0)]'], + ['e:nOT(*)', 'e[0]'], + ['e f', 'e/descendant-or-self::*/f'], + ['e > f', 'e/f'], + ['e + f', "e/following-sibling::*[(name() = 'f') and (position() = 1)]"], + ['e ~ f', 'e/following-sibling::f'], + ['div#container p', "div[@id = 'container']/descendant-or-self::*/p"], + ]; + } + + public static function getXmlLangTestData() + { + return [ + [':lang("EN")', ['first', 'second', 'third', 'fourth']], + [':lang("en-us")', ['second', 'fourth']], + [':lang(en-nz)', ['third']], + [':lang(fr)', ['fifth']], + [':lang(ru)', ['sixth']], + [":lang('ZH')", ['eighth']], + [':lang(de) :lang(zh)', ['eighth']], + [':lang(en), :lang(zh)', ['first', 'second', 'third', 'fourth', 'eighth']], + [':lang(es)', []], + ]; + } + + public static function getHtmlIdsTestData() + { + return [ + ['div', ['outer-div', 'li-div', 'foobar-div']], + ['DIV', ['outer-div', 'li-div', 'foobar-div']], // case-insensitive in HTML + ['div div', ['li-div']], + ['div, div div', ['outer-div', 'li-div', 'foobar-div']], + ['a[name]', ['name-anchor']], + ['a[NAme]', ['name-anchor']], // case-insensitive in HTML: + ['a[rel]', ['tag-anchor', 'nofollow-anchor']], + ['a[rel="tag"]', ['tag-anchor']], + ['a[href*="localhost"]', ['tag-anchor']], + ['a[href*=""]', []], + ['a[href^="http"]', ['tag-anchor', 'nofollow-anchor']], + ['a[href^="http:"]', ['tag-anchor']], + ['a[href^=""]', []], + ['a[href$="org"]', ['nofollow-anchor']], + ['a[href$=""]', []], + ['div[foobar~="bc"]', ['foobar-div']], + ['div[foobar~="cde"]', ['foobar-div']], + ['[foobar~="ab bc"]', ['foobar-div']], + ['[foobar~=""]', []], + ['[foobar~=" \t"]', []], + ['div[foobar~="cd"]', []], + ['*[lang|="En"]', ['second-li']], + ['[lang|="En-us"]', ['second-li']], + // Powered_Cache_Attribute values are case sensitive + ['*[lang|="en"]', []], + ['[lang|="en-US"]', []], + ['*[lang|="e"]', []], + // ... :lang() is not. + [':lang("EN")', ['second-li', 'li-div']], + ['*:lang(en-US)', ['second-li', 'li-div']], + [':lang("e")', []], + ['li:nth-child(3)', ['third-li']], + ['li:nth-child(10)', []], + ['li:nth-child(2n)', ['second-li', 'fourth-li', 'sixth-li']], + ['li:nth-child(even)', ['second-li', 'fourth-li', 'sixth-li']], + ['li:nth-child(2n+0)', ['second-li', 'fourth-li', 'sixth-li']], + ['li:nth-child(+2n+1)', ['first-li', 'third-li', 'fifth-li', 'seventh-li']], + ['li:nth-child(odd)', ['first-li', 'third-li', 'fifth-li', 'seventh-li']], + ['li:nth-child(2n+4)', ['fourth-li', 'sixth-li']], + ['li:nth-child(3n+1)', ['first-li', 'fourth-li', 'seventh-li']], + ['li:nth-child(n)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], + ['li:nth-child(n-1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], + ['li:nth-child(n+1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], + ['li:nth-child(n+3)', ['third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], + ['li:nth-child(-n)', []], + ['li:nth-child(-n-1)', []], + ['li:nth-child(-n+1)', ['first-li']], + ['li:nth-child(-n+3)', ['first-li', 'second-li', 'third-li']], + ['li:nth-last-child(0)', []], + ['li:nth-last-child(2n)', ['second-li', 'fourth-li', 'sixth-li']], + ['li:nth-last-child(even)', ['second-li', 'fourth-li', 'sixth-li']], + ['li:nth-last-child(2n+2)', ['second-li', 'fourth-li', 'sixth-li']], + ['li:nth-last-child(n)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], + ['li:nth-last-child(n-1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], + ['li:nth-last-child(n-3)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], + ['li:nth-last-child(n+1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], + ['li:nth-last-child(n+3)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li']], + ['li:nth-last-child(-n)', []], + ['li:nth-last-child(-n-1)', []], + ['li:nth-last-child(-n+1)', ['seventh-li']], + ['li:nth-last-child(-n+3)', ['fifth-li', 'sixth-li', 'seventh-li']], + ['ol:first-of-type', ['first-ol']], + ['ol:nth-child(4)', ['first-ol']], + ['ol:nth-of-type(2)', ['second-ol']], + ['ol:nth-last-of-type(1)', ['second-ol']], + ['span:only-child', ['foobar-span', 'no-siblings-of-any-type']], + ['li div:only-child', ['li-div']], + ['div *:only-child', ['li-div', 'foobar-span']], + ['p:only-of-type', ['paragraph']], + [':only-of-type', ['html', 'li-div', 'foobar-span', 'no-siblings-of-any-type']], + ['div#foobar-div :only-of-type', ['foobar-span']], + ['a:empty', ['name-anchor']], + ['a:EMpty', ['name-anchor']], + ['li:empty', ['third-li', 'fourth-li', 'fifth-li', 'sixth-li']], + [':root', ['html']], + ['html:root', ['html']], + ['li:root', []], + ['* :root', []], + ['*:contains("link")', ['html', 'nil', 'outer-div', 'tag-anchor', 'nofollow-anchor']], + [':CONtains("link")', ['html', 'nil', 'outer-div', 'tag-anchor', 'nofollow-anchor']], + ['*:contains("LInk")', []], // case sensitive + ['*:contains("e")', ['html', 'nil', 'outer-div', 'first-ol', 'first-li', 'paragraph', 'p-em']], + ['*:contains("E")', []], // case-sensitive + ['.a', ['first-ol']], + ['.b', ['first-ol']], + ['*.a', ['first-ol']], + ['ol.a', ['first-ol']], + ['.c', ['first-ol', 'third-li', 'fourth-li']], + ['*.c', ['first-ol', 'third-li', 'fourth-li']], + ['ol *.c', ['third-li', 'fourth-li']], + ['ol li.c', ['third-li', 'fourth-li']], + ['li ~ li.c', ['third-li', 'fourth-li']], + ['ol > li.c', ['third-li', 'fourth-li']], + ['#first-li', ['first-li']], + ['li#first-li', ['first-li']], + ['*#first-li', ['first-li']], + ['li div', ['li-div']], + ['li > div', ['li-div']], + ['div div', ['li-div']], + ['div > div', []], + ['div>.c', ['first-ol']], + ['div > .c', ['first-ol']], + ['div + div', ['foobar-div']], + ['a ~ a', ['tag-anchor', 'nofollow-anchor']], + ['a[rel="tag"] ~ a', ['nofollow-anchor']], + ['ol#first-ol li:last-child', ['seventh-li']], + ['ol#first-ol *:last-child', ['li-div', 'seventh-li']], + ['#outer-div:first-child', ['outer-div']], + ['#outer-div :first-child', ['name-anchor', 'first-li', 'li-div', 'p-b', 'checkbox-fieldset-disabled', 'area-href']], + ['a[href]', ['tag-anchor', 'nofollow-anchor']], + [':not(*)', []], + ['a:not([href])', ['name-anchor']], + ['ol :Not(li[class])', ['first-li', 'second-li', 'li-div', 'fifth-li', 'sixth-li', 'seventh-li']], + // HTML-specific + [':link', ['link-href', 'tag-anchor', 'nofollow-anchor', 'area-href']], + [':visited', []], + [':enabled', ['link-href', 'tag-anchor', 'nofollow-anchor', 'checkbox-unchecked', 'text-checked', 'checkbox-checked', 'area-href']], + [':disabled', ['checkbox-disabled', 'checkbox-disabled-checked', 'fieldset', 'checkbox-fieldset-disabled']], + [':checked', ['checkbox-checked', 'checkbox-disabled-checked']], + ]; + } + + public static function getHtmlShakespearTestData() + { + return [ + ['*', 246], + ['div:contains(CELIA)', 26], + ['div:only-child', 22], // ? + ['div:nth-child(even)', 106], + ['div:nth-child(2n)', 106], + ['div:nth-child(odd)', 137], + ['div:nth-child(2n+1)', 137], + ['div:nth-child(n)', 243], + ['div:last-child', 53], + ['div:first-child', 51], + ['div > div', 242], + ['div + div', 190], + ['div ~ div', 190], + ['body', 1], + ['body div', 243], + ['div', 243], + ['div div', 242], + ['div div div', 241], + ['div, div, div', 243], + ['div, a, span', 243], + ['.dialog', 51], + ['div.dialog', 51], + ['div .dialog', 51], + ['div.character, div.dialog', 99], + ['div.direction.dialog', 0], + ['div.dialog.direction', 0], + ['div.dialog.scene', 1], + ['div.scene.scene', 1], + ['div.scene .scene', 0], + ['div.direction .dialog ', 0], + ['div .dialog .direction', 4], + ['div.dialog .dialog .direction', 4], + ['#speech5', 1], + ['div#speech5', 1], + ['div #speech5', 1], + ['div.scene div.dialog', 49], + ['div#scene1 div.dialog div', 142], + ['#scene1 #speech1', 1], + ['div[class]', 103], + ['div[class=dialog]', 50], + ['div[class^=dia]', 51], + ['div[class$=log]', 50], + ['div[class*=sce]', 1], + ['div[class|=dialog]', 50], // ? Seems right + ['div[class!=madeup]', 243], // ? Seems right + ['div[class~=dialog]', 51], // ? Seems right + ]; + } +} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/phpunit.xml.dist b/includes/classes/Dependencies/Symfony/Component/CssSelector/phpunit.xml.dist new file mode 100644 index 0000000..a8e537e --- /dev/null +++ b/includes/classes/Dependencies/Symfony/Component/CssSelector/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + + From fd056142a54a6707becf71053685180a7976764d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 12 Nov 2025 08:31:19 +0000 Subject: [PATCH 3/9] Add CI workflow for automated testing and code coverage Co-authored-by: mustafauysal <1421387+mustafauysal@users.noreply.github.com> --- .github/workflows/ci.yml | 99 ++++++++++++++++++++++++++++++++++++++++ .gitignore | 3 ++ .phpunit.result.cache | 1 - 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .phpunit.result.cache diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..67ee61d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,99 @@ +name: CI + +on: + push: + branches: + - master + - develop + pull_request: + branches: + - master + - develop + +jobs: + test: + name: Test (PHP ${{ matrix.php }}) + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + php: ['7.4', '8.0', '8.1', '8.2'] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: xdebug + tools: composer + + - name: Get Composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache Composer dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install PHP dependencies + run: composer install --no-interaction --prefer-dist + + - name: Run PHPUnit tests + run: vendor/bin/phpunit --colors=always + + - name: Run PHPUnit tests with coverage + if: matrix.php == '8.1' + run: vendor/bin/phpunit --coverage-clover=coverage.xml --colors=always + + - name: Upload coverage to Codecov + if: matrix.php == '8.1' + uses: codecov/codecov-action@v4 + with: + files: ./coverage.xml + flags: unittests + name: codecov-php-${{ matrix.php }} + fail_ci_if_error: false + token: ${{ secrets.CODECOV_TOKEN }} + + lint: + name: Lint (PHP ${{ matrix.php }}) + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + php: ['7.4', '8.0', '8.1', '8.2'] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + tools: composer, cs2pr + + - name: Get Composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache Composer dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install PHP dependencies + run: composer install --no-interaction --prefer-dist + + - name: Run PHPCS + run: composer run-script lint diff --git a/.gitignore b/.gitignore index 4821b74..7bd7ce4 100755 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ Thumbs.db Desktop.ini *.js.map *.css.map + +# PHPUnit +.phpunit.result.cache diff --git a/.phpunit.result.cache b/.phpunit.result.cache deleted file mode 100644 index fe33bcf..0000000 --- a/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -{"version":1,"defects":[],"times":{"PoweredCache\\Core\\Core_Tests::test_setup":0.187,"PoweredCache\\Core\\Core_Tests::test_i18n":0.024,"PoweredCache\\Core\\Core_Tests::test_init":0,"Encryption_Test::testEncrypt":0.013,"Encryption_Test::testDecrypt":0,"PoweredCache\\Utils\\Util_Tests::testIsDirEmpty":0.004,"PoweredCache\\Utils\\Util_Tests::testIsIpInRange with data set #0":0.002,"PoweredCache\\Utils\\Util_Tests::testIsIpInRange with data set #1":0.002,"PoweredCache\\Utils\\Util_Tests::testIsIpInRange with data set #2":0.002,"PoweredCache\\Utils\\Util_Tests::testIsIpInRange with data set #3":0.002,"PoweredCache\\Utils\\Util_Tests::testMaskString with data set #0":0.002,"PoweredCache\\Utils\\Util_Tests::testMaskString with data set #1":0.002,"PoweredCache\\Utils\\Util_Tests::testMaskString with data set #2":0.002,"PoweredCache\\Utils\\Util_Tests::testMaskString with data set #3":0.002,"PoweredCache\\Utils\\Util_Tests::testGetClientIp":0.002,"PoweredCache\\Utils\\Util_Tests::testBypassRequest":0.002,"PoweredCache\\Utils\\Util_Tests::testIsLocalSiteWithLocalhost":0.003,"PoweredCache\\Utils\\Util_Tests::testIsLocalSiteWithEnvironmentTypeLocal":0.002,"PoweredCache\\Utils\\Util_Tests::testIsLocalSiteWithEnvironmentTypeProduction":0.01,"PoweredCache\\Utils\\Util_Tests::testPoweredCacheIsMobileWithMobileUserAgent":0.003,"PoweredCache\\Utils\\Util_Tests::testPoweredCacheIsMobileWithNonMobileUserAgent":0.002,"PoweredCache\\Utils\\Util_Tests::testGetExpiredFiles":0.002,"PoweredCache\\Utils\\Util_Tests::testGetUrlDir":0.003}} \ No newline at end of file From fb27c29da0ea863053c59cd1166235517acfc488 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 12 Nov 2025 08:34:26 +0000 Subject: [PATCH 4/9] Add CI and coverage badges to README, update gitignore Co-authored-by: mustafauysal <1421387+mustafauysal@users.noreply.github.com> --- .gitignore | 2 ++ README.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7bd7ce4..d88c5c0 100755 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ node_modules bower_components release vendor +includes/classes/Dependencies/**/Tests .idea *.log @@ -32,3 +33,4 @@ Desktop.ini # PHPUnit .phpunit.result.cache +coverage.xml diff --git a/README.md b/README.md index aeef787..ed6f92d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Powered Cache ============= -![Support Level](https://img.shields.io/badge/support-active-green.svg) [![Release Version](https://img.shields.io/wordpress/plugin/v/powered-cache?label=Release%20Version)](https://github.com/poweredcache/powered-cache/releases) ![WordPress tested up to version](https://img.shields.io/wordpress/plugin/tested/powered-cache?label=WordPress) ![Required PHP Version](https://img.shields.io/wordpress/plugin/required-php/powered-cache?label=PHP) +![Support Level](https://img.shields.io/badge/support-active-green.svg) [![Release Version](https://img.shields.io/wordpress/plugin/v/powered-cache?label=Release%20Version)](https://github.com/poweredcache/powered-cache/releases) ![WordPress tested up to version](https://img.shields.io/wordpress/plugin/tested/powered-cache?label=WordPress) ![Required PHP Version](https://img.shields.io/wordpress/plugin/required-php/powered-cache?label=PHP) [![CI](https://github.com/poweredcache/powered-cache/actions/workflows/ci.yml/badge.svg)](https://github.com/poweredcache/powered-cache/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/poweredcache/powered-cache/branch/master/graph/badge.svg)](https://codecov.io/gh/poweredcache/powered-cache) The most powerful caching and performance suite for WordPress. Easily Improve PageSpeed & Web Vitals Score. From e136d5054af2b6d3e9a938aa9652c9031954ae37 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 12 Nov 2025 08:37:30 +0000 Subject: [PATCH 5/9] Add explicit permissions to CI workflow for security Co-authored-by: mustafauysal <1421387+mustafauysal@users.noreply.github.com> --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67ee61d..64b6b10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,9 @@ on: - master - develop +permissions: + contents: read + jobs: test: name: Test (PHP ${{ matrix.php }}) From 12f5cc87347b98cf80ac36234d18d9782a1fd57f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 12 Nov 2025 08:43:07 +0000 Subject: [PATCH 6/9] Remove vendor test directory pattern from gitignore Co-authored-by: mustafauysal <1421387+mustafauysal@users.noreply.github.com> --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index d88c5c0..4c7d8f9 100755 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ node_modules bower_components release vendor -includes/classes/Dependencies/**/Tests .idea *.log From 90cc4f28bc40f73676625e5e93d8876595574a85 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 12 Nov 2025 08:50:45 +0000 Subject: [PATCH 7/9] Remove Dependencies directory from repo and add to gitignore Co-authored-by: mustafauysal <1421387+mustafauysal@users.noreply.github.com> --- .gitignore | 1 + .../MatthiasMullie/Minify/CSS.php | 870 -------- .../MatthiasMullie/Minify/Exception.php | 22 - .../Minify/Exceptions/BasicException.php | 24 - .../Minify/Exceptions/FileImportException.php | 22 - .../Minify/Exceptions/IOException.php | 22 - .../Dependencies/MatthiasMullie/Minify/JS.php | 618 ----- .../MatthiasMullie/Minify/Minify.php | 560 ----- .../PathConverter/Converter.php | 204 -- .../PathConverter/ConverterInterface.php | 24 - .../PathConverter/NoConverter.php | 23 - .../MatthiasMullie/data/js/keywords_after.txt | 7 - .../data/js/keywords_before.txt | 26 - .../data/js/keywords_reserved.txt | 63 - .../MatthiasMullie/data/js/operators.txt | 46 - .../data/js/operators_after.txt | 43 - .../data/js/operators_before.txt | 43 - .../Component/CssSelector/CHANGELOG.md | 18 - .../CssSelector/CssSelectorConverter.php | 69 - .../Exception/ExceptionInterface.php | 24 - .../Exception/ExpressionErrorException.php | 24 - .../Exception/InternalErrorException.php | 24 - .../CssSelector/Exception/ParseException.php | 24 - .../Exception/SyntaxErrorException.php | 65 - .../Symfony/Component/CssSelector/LICENSE | 19 - .../CssSelector/Node/AbstractNode.php | 39 - .../CssSelector/Node/AttributeNode.php | 82 - .../Component/CssSelector/Node/ClassNode.php | 57 - .../CssSelector/Node/CombinedSelectorNode.php | 66 - .../CssSelector/Node/ElementNode.php | 59 - .../CssSelector/Node/FunctionNode.php | 76 - .../Component/CssSelector/Node/HashNode.php | 57 - .../CssSelector/Node/NegationNode.php | 57 - .../CssSelector/Node/NodeInterface.php | 31 - .../Component/CssSelector/Node/PseudoNode.php | 57 - .../CssSelector/Node/SelectorNode.php | 57 - .../CssSelector/Node/Specificity.php | 73 - .../Parser/Handler/CommentHandler.php | 48 - .../Parser/Handler/HandlerInterface.php | 30 - .../Parser/Handler/HashHandler.php | 58 - .../Parser/Handler/IdentifierHandler.php | 58 - .../Parser/Handler/NumberHandler.php | 54 - .../Parser/Handler/StringHandler.php | 77 - .../Parser/Handler/WhitespaceHandler.php | 46 - .../Component/CssSelector/Parser/Parser.php | 353 --- .../CssSelector/Parser/ParserInterface.php | 34 - .../Component/CssSelector/Parser/Reader.php | 86 - .../Parser/Shortcut/ClassParser.php | 51 - .../Parser/Shortcut/ElementParser.php | 47 - .../Parser/Shortcut/EmptyStringParser.php | 46 - .../Parser/Shortcut/HashParser.php | 51 - .../Component/CssSelector/Parser/Token.php | 111 - .../CssSelector/Parser/TokenStream.php | 167 -- .../Parser/Tokenizer/Tokenizer.php | 73 - .../Parser/Tokenizer/TokenizerEscaping.php | 65 - .../Parser/Tokenizer/TokenizerPatterns.php | 89 - .../Symfony/Component/CssSelector/README.md | 20 - .../Tests/CssSelectorConverterTest.php | 83 - .../Tests/Node/AbstractNodeTestCase.php | 34 - .../Tests/Node/AttributeNodeTest.php | 37 - .../CssSelector/Tests/Node/ClassNodeTest.php | 33 - .../Tests/Node/CombinedSelectorNodeTest.php | 35 - .../Tests/Node/ElementNodeTest.php | 35 - .../Tests/Node/FunctionNodeTest.php | 47 - .../CssSelector/Tests/Node/HashNodeTest.php | 33 - .../Tests/Node/NegationNodeTest.php | 33 - .../CssSelector/Tests/Node/PseudoNodeTest.php | 32 - .../Tests/Node/SelectorNodeTest.php | 34 - .../Tests/Node/SpecificityTest.php | 63 - .../Handler/AbstractHandlerTestCase.php | 70 - .../Parser/Handler/CommentHandlerTest.php | 55 - .../Tests/Parser/Handler/HashHandlerTest.php | 49 - .../Parser/Handler/IdentifierHandlerTest.php | 49 - .../Parser/Handler/NumberHandlerTest.php | 50 - .../Parser/Handler/StringHandlerTest.php | 50 - .../Parser/Handler/WhitespaceHandlerTest.php | 44 - .../CssSelector/Tests/Parser/ParserTest.php | 263 --- .../CssSelector/Tests/Parser/ReaderTest.php | 102 - .../Tests/Parser/Shortcut/ClassParserTest.php | 45 - .../Parser/Shortcut/ElementParserTest.php | 44 - .../Parser/Shortcut/EmptyStringParserTest.php | 36 - .../Tests/Parser/Shortcut/HashParserTest.php | 45 - .../Tests/Parser/TokenStreamTest.php | 97 - .../CssSelector/Tests/XPath/Fixtures/ids.html | 52 - .../CssSelector/Tests/XPath/Fixtures/lang.xml | 11 - .../Tests/XPath/Fixtures/shakespear.html | 308 --- .../Tests/XPath/TranslatorTest.php | 416 ---- .../XPath/Extension/AbstractExtension.php | 65 - .../Extension/AttributeMatchingExtension.php | 119 - .../XPath/Extension/CombinationExtension.php | 71 - .../XPath/Extension/ExtensionInterface.php | 67 - .../XPath/Extension/FunctionExtension.php | 171 -- .../XPath/Extension/HtmlExtension.php | 187 -- .../XPath/Extension/NodeExtension.php | 197 -- .../XPath/Extension/PseudoClassExtension.php | 122 - .../CssSelector/XPath/Translator.php | 230 -- .../CssSelector/XPath/TranslatorInterface.php | 37 - .../Component/CssSelector/XPath/XPathExpr.php | 111 - .../Component/CssSelector/composer.json | 33 - .../Component/CssSelector/phpunit.xml.dist | 31 - .../Symfony/Polyfill/Php80/LICENSE | 19 - .../Symfony/Polyfill/Php80/Php80.php | 115 - .../Symfony/Polyfill/Php80/PhpToken.php | 106 - .../Symfony/Polyfill/Php80/README.md | 25 - .../Php80/Resources/stubs/Attribute.php | 31 - .../Php80/Resources/stubs/PhpToken.php | 16 - .../Php80/Resources/stubs/Stringable.php | 20 - .../Resources/stubs/UnhandledMatchError.php | 16 - .../Php80/Resources/stubs/ValueError.php | 16 - .../Symfony/Polyfill/Php80/bootstrap.php | 42 - .../Symfony/Polyfill/Php80/composer.json | 37 - .../voku/helper/AbstractDomParser.php | 527 ----- .../voku/helper/AbstractSimpleHtmlDom.php | 255 --- .../voku/helper/AbstractSimpleHtmlDomNode.php | 80 - .../voku/helper/AbstractSimpleXmlDom.php | 217 -- .../voku/helper/AbstractSimpleXmlDomNode.php | 80 - .../voku/helper/DomParserInterface.php | 201 -- .../voku/helper/HtmlDomHelper.php | 72 - .../voku/helper/HtmlDomParser.php | 1228 ---------- .../Dependencies/voku/helper/HtmlMin.php | 1981 ----------------- .../helper/HtmlMinDomObserverInterface.php | 28 - .../HtmlMinDomObserverOptimizeAttributes.php | 381 ---- .../voku/helper/HtmlMinInterface.php | 154 -- .../voku/helper/SelectorConverter.php | 75 - .../voku/helper/SimpleHtmlAttributes.php | 269 --- .../helper/SimpleHtmlAttributesInterface.php | 82 - .../voku/helper/SimpleHtmlDom.php | 1011 --------- .../voku/helper/SimpleHtmlDomBlank.php | 472 ---- .../voku/helper/SimpleHtmlDomInterface.php | 391 ---- .../voku/helper/SimpleHtmlDomNode.php | 161 -- .../voku/helper/SimpleHtmlDomNodeBlank.php | 106 - .../helper/SimpleHtmlDomNodeInterface.php | 117 - .../Dependencies/voku/helper/SimpleXmlDom.php | 843 ------- .../voku/helper/SimpleXmlDomBlank.php | 447 ---- .../voku/helper/SimpleXmlDomInterface.php | 367 --- .../voku/helper/SimpleXmlDomNode.php | 161 -- .../voku/helper/SimpleXmlDomNodeBlank.php | 104 - .../voku/helper/SimpleXmlDomNodeInterface.php | 117 - .../Dependencies/voku/helper/XmlDomParser.php | 733 ------ 139 files changed, 1 insertion(+), 19988 deletions(-) delete mode 100644 includes/classes/Dependencies/MatthiasMullie/Minify/CSS.php delete mode 100644 includes/classes/Dependencies/MatthiasMullie/Minify/Exception.php delete mode 100644 includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/BasicException.php delete mode 100644 includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/FileImportException.php delete mode 100644 includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/IOException.php delete mode 100644 includes/classes/Dependencies/MatthiasMullie/Minify/JS.php delete mode 100644 includes/classes/Dependencies/MatthiasMullie/Minify/Minify.php delete mode 100644 includes/classes/Dependencies/MatthiasMullie/PathConverter/Converter.php delete mode 100644 includes/classes/Dependencies/MatthiasMullie/PathConverter/ConverterInterface.php delete mode 100644 includes/classes/Dependencies/MatthiasMullie/PathConverter/NoConverter.php delete mode 100644 includes/classes/Dependencies/MatthiasMullie/data/js/keywords_after.txt delete mode 100644 includes/classes/Dependencies/MatthiasMullie/data/js/keywords_before.txt delete mode 100644 includes/classes/Dependencies/MatthiasMullie/data/js/keywords_reserved.txt delete mode 100644 includes/classes/Dependencies/MatthiasMullie/data/js/operators.txt delete mode 100644 includes/classes/Dependencies/MatthiasMullie/data/js/operators_after.txt delete mode 100644 includes/classes/Dependencies/MatthiasMullie/data/js/operators_before.txt delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/CHANGELOG.md delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/CssSelectorConverter.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ExceptionInterface.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ExpressionErrorException.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/InternalErrorException.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ParseException.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/SyntaxErrorException.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/LICENSE delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/AbstractNode.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/AttributeNode.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/ClassNode.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/CombinedSelectorNode.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/ElementNode.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/FunctionNode.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/HashNode.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/NegationNode.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/NodeInterface.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/PseudoNode.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/SelectorNode.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Node/Specificity.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/HashHandler.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/StringHandler.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Parser.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/ParserInterface.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Reader.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Token.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/TokenStream.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/README.md delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTestCase.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTestCase.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ParserTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/AbstractExtension.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/ExtensionInterface.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Translator.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/TranslatorInterface.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/XPathExpr.php delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/composer.json delete mode 100644 includes/classes/Dependencies/Symfony/Component/CssSelector/phpunit.xml.dist delete mode 100644 includes/classes/Dependencies/Symfony/Polyfill/Php80/LICENSE delete mode 100644 includes/classes/Dependencies/Symfony/Polyfill/Php80/Php80.php delete mode 100644 includes/classes/Dependencies/Symfony/Polyfill/Php80/PhpToken.php delete mode 100644 includes/classes/Dependencies/Symfony/Polyfill/Php80/README.md delete mode 100644 includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/Attribute.php delete mode 100644 includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/PhpToken.php delete mode 100644 includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/Stringable.php delete mode 100644 includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/UnhandledMatchError.php delete mode 100644 includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/ValueError.php delete mode 100644 includes/classes/Dependencies/Symfony/Polyfill/Php80/bootstrap.php delete mode 100644 includes/classes/Dependencies/Symfony/Polyfill/Php80/composer.json delete mode 100644 includes/classes/Dependencies/voku/helper/AbstractDomParser.php delete mode 100644 includes/classes/Dependencies/voku/helper/AbstractSimpleHtmlDom.php delete mode 100644 includes/classes/Dependencies/voku/helper/AbstractSimpleHtmlDomNode.php delete mode 100644 includes/classes/Dependencies/voku/helper/AbstractSimpleXmlDom.php delete mode 100644 includes/classes/Dependencies/voku/helper/AbstractSimpleXmlDomNode.php delete mode 100644 includes/classes/Dependencies/voku/helper/DomParserInterface.php delete mode 100644 includes/classes/Dependencies/voku/helper/HtmlDomHelper.php delete mode 100644 includes/classes/Dependencies/voku/helper/HtmlDomParser.php delete mode 100644 includes/classes/Dependencies/voku/helper/HtmlMin.php delete mode 100644 includes/classes/Dependencies/voku/helper/HtmlMinDomObserverInterface.php delete mode 100644 includes/classes/Dependencies/voku/helper/HtmlMinDomObserverOptimizeAttributes.php delete mode 100644 includes/classes/Dependencies/voku/helper/HtmlMinInterface.php delete mode 100644 includes/classes/Dependencies/voku/helper/SelectorConverter.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleHtmlAttributes.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleHtmlAttributesInterface.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleHtmlDom.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleHtmlDomBlank.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleHtmlDomInterface.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleHtmlDomNode.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleHtmlDomNodeBlank.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleHtmlDomNodeInterface.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleXmlDom.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleXmlDomBlank.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleXmlDomInterface.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleXmlDomNode.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleXmlDomNodeBlank.php delete mode 100644 includes/classes/Dependencies/voku/helper/SimpleXmlDomNodeInterface.php delete mode 100644 includes/classes/Dependencies/voku/helper/XmlDomParser.php diff --git a/.gitignore b/.gitignore index 4c7d8f9..554862e 100755 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ node_modules bower_components release vendor +includes/classes/Dependencies .idea *.log diff --git a/includes/classes/Dependencies/MatthiasMullie/Minify/CSS.php b/includes/classes/Dependencies/MatthiasMullie/Minify/CSS.php deleted file mode 100644 index 6b13213..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/Minify/CSS.php +++ /dev/null @@ -1,870 +0,0 @@ - - * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved - * @license MIT License - */ - -namespace PoweredCache\Dependencies\MatthiasMullie\Minify; - -use PoweredCache\Dependencies\MatthiasMullie\Minify\Exceptions\FileImportException; -use PoweredCache\Dependencies\MatthiasMullie\PathConverter\Converter; -use PoweredCache\Dependencies\MatthiasMullie\PathConverter\ConverterInterface; - -/** - * CSS minifier. - * - * Please report bugs on https://github.com/matthiasmullie/minify/issues - * - * @author Matthias Mullie - * @author Tijs Verkoyen - * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved - * @license MIT License - */ -class CSS extends Minify -{ - /** - * @var int maximum inport size in kB - */ - protected $maxImportSize = 5; - - /** - * @var string[] valid import extensions - */ - protected $importExtensions = array( - 'gif' => 'data:image/gif', - 'png' => 'data:image/png', - 'jpe' => 'data:image/jpeg', - 'jpg' => 'data:image/jpeg', - 'jpeg' => 'data:image/jpeg', - 'svg' => 'data:image/svg+xml', - 'woff' => 'data:application/x-font-woff', - 'woff2' => 'data:application/x-font-woff2', - 'avif' => 'data:image/avif', - 'apng' => 'data:image/apng', - 'webp' => 'data:image/webp', - 'tif' => 'image/tiff', - 'tiff' => 'image/tiff', - 'xbm' => 'image/x-xbitmap', - ); - - /** - * Set the maximum size if files to be imported. - * - * Files larger than this size (in kB) will not be imported into the CSS. - * Importing files into the CSS as data-uri will save you some connections, - * but we should only import relatively small decorative images so that our - * CSS file doesn't get too bulky. - * - * @param int $size Size in kB - */ - public function setMaxImportSize($size) - { - $this->maxImportSize = $size; - } - - /** - * Set the type of extensions to be imported into the CSS (to save network - * connections). - * Keys of the array should be the file extensions & respective values - * should be the data type. - * - * @param string[] $extensions Array of file extensions - */ - public function setImportExtensions(array $extensions) - { - $this->importExtensions = $extensions; - } - - /** - * Move any import statements to the top. - * - * @param string $content Nearly finished CSS content - * - * @return string - */ - protected function moveImportsToTop($content) - { - if (preg_match_all('/(;?)(@import (?url\()?(?P["\']?).+?(?P=quotes)(?(url)\)));?/', $content, $matches)) { - // remove from content - foreach ($matches[0] as $import) { - $content = str_replace($import, '', $content); - } - - // add to top - $content = implode(';', $matches[2]) . ';' . trim($content, ';'); - } - - return $content; - } - - /** - * Combine CSS from import statements. - * - * \@import's will be loaded and their content merged into the original file, - * to save HTTP requests. - * - * @param string $source The file to combine imports for - * @param string $content The CSS content to combine imports for - * @param string[] $parents Parent paths, for circular reference checks - * - * @return string - * - * @throws FileImportException - */ - protected function combineImports($source, $content, $parents) - { - $importRegexes = array( - // @import url(xxx) - '/ - # import statement - @import - - # whitespace - \s+ - - # open url() - url\( - - # (optional) open path enclosure - (?P["\']?) - - # fetch path - (?P.+?) - - # (optional) close path enclosure - (?P=quotes) - - # close url() - \) - - # (optional) trailing whitespace - \s* - - # (optional) media statement(s) - (?P[^;]*) - - # (optional) trailing whitespace - \s* - - # (optional) closing semi-colon - ;? - - /ix', - - // @import 'xxx' - '/ - - # import statement - @import - - # whitespace - \s+ - - # open path enclosure - (?P["\']) - - # fetch path - (?P.+?) - - # close path enclosure - (?P=quotes) - - # (optional) trailing whitespace - \s* - - # (optional) media statement(s) - (?P[^;]*) - - # (optional) trailing whitespace - \s* - - # (optional) closing semi-colon - ;? - - /ix', - ); - - // find all relative imports in css - $matches = array(); - foreach ($importRegexes as $importRegex) { - if (preg_match_all($importRegex, $content, $regexMatches, PREG_SET_ORDER)) { - $matches = array_merge($matches, $regexMatches); - } - } - - $search = array(); - $replace = array(); - - // loop the matches - foreach ($matches as $match) { - // get the path for the file that will be imported - $importPath = dirname($source) . '/' . $match['path']; - - // only replace the import with the content if we can grab the - // content of the file - if (!$this->canImportByPath($match['path']) || !$this->canImportFile($importPath)) { - continue; - } - - // check if current file was not imported previously in the same - // import chain. - if (in_array($importPath, $parents)) { - throw new FileImportException('Failed to import file "' . $importPath . '": circular reference detected.'); - } - - // grab referenced file & minify it (which may include importing - // yet other @import statements recursively) - $minifier = new self($importPath); - $minifier->setMaxImportSize($this->maxImportSize); - $minifier->setImportExtensions($this->importExtensions); - $importContent = $minifier->execute($source, $parents); - - // check if this is only valid for certain media - if (!empty($match['media'])) { - $importContent = '@media ' . $match['media'] . '{' . $importContent . '}'; - } - - // add to replacement array - $search[] = $match[0]; - $replace[] = $importContent; - } - - // replace the import statements - return str_replace($search, $replace, $content); - } - - /** - * Import files into the CSS, base64-ized. - * - * @url(image.jpg) images will be loaded and their content merged into the - * original file, to save HTTP requests. - * - * @param string $source The file to import files for - * @param string $content The CSS content to import files for - * - * @return string - */ - protected function importFiles($source, $content) - { - $regex = '/url\((["\']?)(.+?)\\1\)/i'; - if ($this->importExtensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) { - $search = array(); - $replace = array(); - - // loop the matches - foreach ($matches as $match) { - $extension = substr(strrchr($match[2], '.'), 1); - if ($extension && !array_key_exists($extension, $this->importExtensions)) { - continue; - } - - // get the path for the file that will be imported - $path = $match[2]; - $path = dirname($source) . '/' . $path; - - // only replace the import with the content if we're able to get - // the content of the file, and it's relatively small - if ($this->canImportFile($path) && $this->canImportBySize($path)) { - // grab content && base64-ize - $importContent = $this->load($path); - $importContent = base64_encode($importContent); - - // build replacement - $search[] = $match[0]; - $replace[] = 'url(' . $this->importExtensions[$extension] . ';base64,' . $importContent . ')'; - } - } - - // replace the import statements - $content = str_replace($search, $replace, $content); - } - - return $content; - } - - /** - * Minify the data. - * Perform CSS optimizations. - * - * @param string[optional] $path Path to write the data to - * @param string[] $parents Parent paths, for circular reference checks - * - * @return string The minified data - */ - public function execute($path = null, $parents = array()) - { - $content = ''; - - // loop CSS data (raw data and files) - foreach ($this->data as $source => $css) { - /* - * Let's first take out strings & comments, since we can't just - * remove whitespace anywhere. If whitespace occurs inside a string, - * we should leave it alone. E.g.: - * p { content: "a test" } - */ - $this->extractStrings(); - $this->stripComments(); - $this->extractMath(); - $this->extractCustomProperties(); - $css = $this->replace($css); - - $css = $this->stripWhitespace($css); - $css = $this->convertLegacyColors($css); - $css = $this->cleanupModernColors($css); - $css = $this->shortenHEXColors($css); - $css = $this->shortenZeroes($css); - $css = $this->shortenFontWeights($css); - $css = $this->stripEmptyTags($css); - - // restore the string we've extracted earlier - $css = $this->restoreExtractedData($css); - - $source = is_int($source) ? '' : $source; - $parents = $source ? array_merge($parents, array($source)) : $parents; - $css = $this->combineImports($source, $css, $parents); - $css = $this->importFiles($source, $css); - - /* - * If we'll save to a new path, we'll have to fix the relative paths - * to be relative no longer to the source file, but to the new path. - * If we don't write to a file, fall back to same path so no - * conversion happens (because we still want it to go through most - * of the move code, which also addresses url() & @import syntax...) - */ - $converter = $this->getPathConverter($source, $path ?: $source); - $css = $this->move($converter, $css); - - // combine css - $content .= $css; - } - - $content = $this->moveImportsToTop($content); - - return $content; - } - - /** - * Moving a css file should update all relative urls. - * Relative references (e.g. ../images/image.gif) in a certain css file, - * will have to be updated when a file is being saved at another location - * (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper). - * - * @param ConverterInterface $converter Relative path converter - * @param string $content The CSS content to update relative urls for - * - * @return string - */ - protected function move(ConverterInterface $converter, $content) - { - /* - * Relative path references will usually be enclosed by url(). @import - * is an exception, where url() is not necessary around the path (but is - * allowed). - * This *could* be 1 regular expression, where both regular expressions - * in this array are on different sides of a |. But we're using named - * patterns in both regexes, the same name on both regexes. This is only - * possible with a (?J) modifier, but that only works after a fairly - * recent PCRE version. That's why I'm doing 2 separate regular - * expressions & combining the matches after executing of both. - */ - $relativeRegexes = array( - // url(xxx) - '/ - # open url() - url\( - - \s* - - # open path enclosure - (?P["\'])? - - # fetch path - (?P.+?) - - # close path enclosure - (?(quotes)(?P=quotes)) - - \s* - - # close url() - \) - - /ix', - - // @import "xxx" - '/ - # import statement - @import - - # whitespace - \s+ - - # we don\'t have to check for @import url(), because the - # condition above will already catch these - - # open path enclosure - (?P["\']) - - # fetch path - (?P.+?) - - # close path enclosure - (?P=quotes) - - /ix', - ); - - // find all relative urls in css - $matches = array(); - foreach ($relativeRegexes as $relativeRegex) { - if (preg_match_all($relativeRegex, $content, $regexMatches, PREG_SET_ORDER)) { - $matches = array_merge($matches, $regexMatches); - } - } - - $search = array(); - $replace = array(); - - // loop all urls - foreach ($matches as $match) { - // determine if it's a url() or an @import match - $type = (strpos($match[0], '@import') === 0 ? 'import' : 'url'); - - $url = $match['path']; - if ($this->canImportByPath($url)) { - // attempting to interpret GET-params makes no sense, so let's discard them for awhile - $params = strrchr($url, '?'); - $url = $params ? substr($url, 0, -strlen($params)) : $url; - - // fix relative url - $url = $converter->convert($url); - - // now that the path has been converted, re-apply GET-params - $url .= $params; - } - - /* - * Urls with control characters above 0x7e should be quoted. - * According to Mozilla's parser, whitespace is only allowed at the - * end of unquoted urls. - * Urls with `)` (as could happen with data: uris) should also be - * quoted to avoid being confused for the url() closing parentheses. - * And urls with a # have also been reported to cause issues. - * Urls with quotes inside should also remain escaped. - * - * @see https://developer.mozilla.org/nl/docs/Web/CSS/url#The_url()_functional_notation - * @see https://hg.mozilla.org/mozilla-central/rev/14abca4e7378 - * @see https://github.com/matthiasmullie/minify/issues/193 - */ - $url = trim($url); - if (preg_match('/[\s\)\'"#\x{7f}-\x{9f}]/u', $url)) { - $url = $match['quotes'] . $url . $match['quotes']; - } - - // build replacement - $search[] = $match[0]; - if ($type === 'url') { - $replace[] = 'url(' . $url . ')'; - } elseif ($type === 'import') { - $replace[] = '@import "' . $url . '"'; - } - } - - // replace urls - return str_replace($search, $replace, $content); - } - - /** - * Shorthand HEX color codes. - * #FF0000FF -> #f00 -> red - * #FF00FF00 -> transparent. - * - * @param string $content The CSS content to shorten the HEX color codes for - * - * @return string - */ - protected function shortenHexColors($content) - { - // shorten repeating patterns within HEX .. - $content = preg_replace('/(?<=[: ])#([0-9a-f])\\1([0-9a-f])\\2([0-9a-f])\\3(?:([0-9a-f])\\4)?(?=[; }])/i', '#$1$2$3$4', $content); - - // remove alpha channel if it's pointless .. - $content = preg_replace('/(?<=[: ])#([0-9a-f]{6})ff(?=[; }])/i', '#$1', $content); - $content = preg_replace('/(?<=[: ])#([0-9a-f]{3})f(?=[; }])/i', '#$1', $content); - - // replace `transparent` with shortcut .. - $content = preg_replace('/(?<=[: ])#[0-9a-f]{6}00(?=[; }])/i', '#fff0', $content); - - $colors = array( - // make these more readable - '#00f' => 'blue', - '#dc143c' => 'crimson', - '#0ff' => 'cyan', - '#8b0000' => 'darkred', - '#696969' => 'dimgray', - '#ff69b4' => 'hotpink', - '#0f0' => 'lime', - '#fdf5e6' => 'oldlace', - '#87ceeb' => 'skyblue', - '#d8bfd8' => 'thistle', - // we can shorten some even more by replacing them with their color name - '#f0ffff' => 'azure', - '#f5f5dc' => 'beige', - '#ffe4c4' => 'bisque', - '#a52a2a' => 'brown', - '#ff7f50' => 'coral', - '#ffd700' => 'gold', - '#808080' => 'gray', - '#008000' => 'green', - '#4b0082' => 'indigo', - '#fffff0' => 'ivory', - '#f0e68c' => 'khaki', - '#faf0e6' => 'linen', - '#800000' => 'maroon', - '#000080' => 'navy', - '#808000' => 'olive', - '#ffa500' => 'orange', - '#da70d6' => 'orchid', - '#cd853f' => 'peru', - '#ffc0cb' => 'pink', - '#dda0dd' => 'plum', - '#800080' => 'purple', - '#f00' => 'red', - '#fa8072' => 'salmon', - '#a0522d' => 'sienna', - '#c0c0c0' => 'silver', - '#fffafa' => 'snow', - '#d2b48c' => 'tan', - '#008080' => 'teal', - '#ff6347' => 'tomato', - '#ee82ee' => 'violet', - '#f5deb3' => 'wheat', - // or the other way around - 'black' => '#000', - 'fuchsia' => '#f0f', - 'magenta' => '#f0f', - 'white' => '#fff', - 'yellow' => '#ff0', - // and also `transparent` - 'transparent' => '#fff0', - ); - - return preg_replace_callback( - '/(?<=[: ])(' . implode('|', array_keys($colors)) . ')(?=[; }])/i', - function ($match) use ($colors) { - return $colors[strtolower($match[0])]; - }, - $content - ); - } - - /** - * Convert RGB|HSL color codes. - * rgb(255,0,0,.5) -> rgb(255 0 0 / .5). - * rgb(255,0,0) -> #f00. - * - * @param string $content The CSS content to shorten the RGB color codes for - * - * @return string - */ - protected function convertLegacyColors($content) - { - /* - https://drafts.csswg.org/css-color/#color-syntax-legacy - https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb - https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl - */ - - // convert legacy color syntax - $content = preg_replace('/(rgb)a?\(\s*([0-9]{1,3}%?)\s*,\s*([0-9]{1,3}%?)\s*,\s*([0-9]{1,3}%?)\s*,\s*([0,1]?(?:\.[0-9]*)?)\s*\)/i', '$1($2 $3 $4 / $5)', $content); - $content = preg_replace('/(rgb)a?\(\s*([0-9]{1,3}%?)\s*,\s*([0-9]{1,3}%?)\s*,\s*([0-9]{1,3}%?)\s*\)/i', '$1($2 $3 $4)', $content); - $content = preg_replace('/(hsl)a?\(\s*([0-9]+(?:deg|grad|rad|turn)?)\s*,\s*([0-9]{1,3}%)\s*,\s*([0-9]{1,3}%)\s*,\s*([0,1]?(?:\.[0-9]*)?)\s*\)/i', '$1($2 $3 $4 / $5)', $content); - $content = preg_replace('/(hsl)a?\(\s*([0-9]+(?:deg|grad|rad|turn)?)\s*,\s*([0-9]{1,3}%)\s*,\s*([0-9]{1,3}%)\s*\)/i', '$1($2 $3 $4)', $content); - - // convert `rgb` to `hex` - $dec = '([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])'; - return preg_replace_callback( - "/rgb\($dec $dec $dec\)/i", - function ($match) { - return sprintf('#%02x%02x%02x', $match[1], $match[2], $match[3]); - }, - $content - ); - } - - /** - * Cleanup RGB|HSL|HWB|LCH|LAB - * rgb(255 0 0 / 1) -> rgb(255 0 0). - * rgb(255 0 0 / 0) -> transparent. - * - * @param string $content The CSS content to cleanup HSL|HWB|LCH|LAB - * - * @return string - */ - protected function cleanupModernColors($content) - { - /* - https://drafts.csswg.org/css-color/#color-syntax-modern - https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hwb - https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/lch - https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/lab - https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch - https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklab - */ - $tag = '(rgb|hsl|hwb|(?:(?:ok)?(?:lch|lab)))'; - - // remove alpha channel if it's pointless .. - $content = preg_replace('/' . $tag . '\(\s*([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+\/\s+1(?:(?:\.\d?)*|00%)?\s*\)/i', '$1($2 $3 $4)', $content); - - // replace `transparent` with shortcut .. - $content = preg_replace('/' . $tag . '\(\s*[^\s]+\s+[^\s]+\s+[^\s]+\s+\/\s+0(?:[\.0%]*)?\s*\)/i', '#fff0', $content); - - return $content; - } - - /** - * Shorten CSS font weights. - * - * @param string $content The CSS content to shorten the font weights for - * - * @return string - */ - protected function shortenFontWeights($content) - { - $weights = array( - 'normal' => 400, - 'bold' => 700, - ); - - $callback = function ($match) use ($weights) { - return $match[1] . $weights[$match[2]]; - }; - - return preg_replace_callback('/(font-weight\s*:\s*)(' . implode('|', array_keys($weights)) . ')(?=[;}])/', $callback, $content); - } - - /** - * Shorthand 0 values to plain 0, instead of e.g. -0em. - * - * @param string $content The CSS content to shorten the zero values for - * - * @return string - */ - protected function shortenZeroes($content) - { - // we don't want to strip units in `calc()` expressions: - // `5px - 0px` is valid, but `5px - 0` is not - // `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but - // `10 * 0` is invalid - // we've extracted calcs earlier, so we don't need to worry about this - - // reusable bits of code throughout these regexes: - // before & after are used to make sure we don't match lose unintended - // 0-like values (e.g. in #000, or in http://url/1.0) - // units can be stripped from 0 values, or used to recognize non 0 - // values (where wa may be able to strip a .0 suffix) - $before = '(?<=[:(, ])'; - $after = '(?=[ ,);}])'; - $units = '(em|ex|%|px|cm|mm|in|pt|pc|ch|rem|vh|vw|vmin|vmax|vm)'; - - // strip units after zeroes (0px -> 0) - // NOTE: it should be safe to remove all units for a 0 value, but in - // practice, Webkit (especially Safari) seems to stumble over at least - // 0%, potentially other units as well. Only stripping 'px' for now. - // @see https://github.com/matthiasmullie/minify/issues/60 - $content = preg_replace('/' . $before . '(-?0*(\.0+)?)(?<=0)px' . $after . '/', '\\1', $content); - - // strip 0-digits (.0 -> 0) - $content = preg_replace('/' . $before . '\.0+' . $units . '?' . $after . '/', '0\\1', $content); - // strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px - $content = preg_replace('/' . $before . '(-?[0-9]+\.[0-9]+)0+' . $units . '?' . $after . '/', '\\1\\2', $content); - // strip trailing 0: 50.00 -> 50, 50.00px -> 50px - $content = preg_replace('/' . $before . '(-?[0-9]+)\.0+' . $units . '?' . $after . '/', '\\1\\2', $content); - // strip leading 0: 0.1 -> .1, 01.1 -> 1.1 - $content = preg_replace('/' . $before . '(-?)0+([0-9]*\.[0-9]+)' . $units . '?' . $after . '/', '\\1\\2\\3', $content); - - // strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0) - $content = preg_replace('/' . $before . '-?0+' . $units . '?' . $after . '/', '0\\1', $content); - - // IE doesn't seem to understand a unitless flex-basis value (correct - - // it goes against the spec), so let's add it in again (make it `%`, - // which is only 1 char: 0%, 0px, 0 anything, it's all just the same) - // @see https://developer.mozilla.org/nl/docs/Web/CSS/flex - $content = preg_replace('/flex:([0-9]+\s[0-9]+\s)0([;\}])/', 'flex:${1}0%${2}', $content); - $content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content); - - return $content; - } - - /** - * Strip empty tags from source code. - * - * @param string $content - * - * @return string - */ - protected function stripEmptyTags($content) - { - $content = preg_replace('/(?<=^)[^\{\};]+\{\s*\}/', '', $content); - $content = preg_replace('/(?<=(\}|;))[^\{\};]+\{\s*\}/', '', $content); - - return $content; - } - - /** - * Strip comments from source code. - */ - protected function stripComments() - { - $this->stripMultilineComments(); - } - - /** - * Strip whitespace. - * - * @param string $content The CSS content to strip the whitespace for - * - * @return string - */ - protected function stripWhitespace($content) - { - // remove leading & trailing whitespace - $content = preg_replace('/^\s*/m', '', $content); - $content = preg_replace('/\s*$/m', '', $content); - - // replace newlines with a single space - $content = preg_replace('/\s+/', ' ', $content); - - // remove whitespace around meta characters - // inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex - $content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content); - $content = preg_replace('/([\[(:>\+])\s+/', '$1', $content); - $content = preg_replace('/\s+([\]\)>\+])/', '$1', $content); - $content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content); - - // whitespace around + and - can only be stripped inside some pseudo- - // classes, like `:nth-child(3+2n)` - // not in things like `calc(3px + 2px)`, shorthands like `3px -2px`, or - // selectors like `div.weird- p` - $pseudos = array('nth-child', 'nth-last-child', 'nth-last-of-type', 'nth-of-type'); - $content = preg_replace('/:(' . implode('|', $pseudos) . ')\(\s*([+-]?)\s*(.+?)\s*([+-]?)\s*(.*?)\s*\)/', ':$1($2$3$4$5)', $content); - - // remove semicolon/whitespace followed by closing bracket - $content = str_replace(';}', '}', $content); - - return trim($content); - } - - /** - * Replace all occurrences of functions that may contain math, where - * whitespace around operators needs to be preserved (e.g. calc, clamp). - */ - protected function extractMath() - { - $functions = array('calc', 'clamp', 'min', 'max'); - $pattern = '/\b(' . implode('|', $functions) . ')(\(.+?)(?=$|;|})/m'; - - // PHP only supports $this inside anonymous functions since 5.4 - $minifier = $this; - $callback = function ($match) use ($minifier, $pattern, &$callback) { - $function = $match[1]; - $length = strlen($match[2]); - $expr = ''; - $opened = 0; - - // the regular expression for extracting math has 1 significant problem: - // it can't determine the correct closing parenthesis... - // instead, it'll match a larger portion of code to where it's certain that - // the calc() musts have ended, and we'll figure out which is the correct - // closing parenthesis here, by counting how many have opened - for ($i = 0; $i < $length; ++$i) { - $char = $match[2][$i]; - $expr .= $char; - if ($char === '(') { - ++$opened; - } elseif ($char === ')' && --$opened === 0) { - break; - } - } - - // now that we've figured out where the calc() starts and ends, extract it - $count = count($minifier->extracted); - $placeholder = 'math(' . $count . ')'; - $minifier->extracted[$placeholder] = $function . '(' . trim(substr($expr, 1, -1)) . ')'; - - // and since we've captured more code than required, we may have some leftover - // calc() in here too - go recursive on the remaining but of code to go figure - // that out and extract what is needed - $rest = $minifier->str_replace_first($function . $expr, '', $match[0]); - $rest = preg_replace_callback($pattern, $callback, $rest); - - return $placeholder . $rest; - }; - - $this->registerPattern($pattern, $callback); - } - - /** - * Replace custom properties, whose values may be used in scenarios where - * we wouldn't want them to be minified (e.g. inside calc). - */ - protected function extractCustomProperties() - { - // PHP only supports $this inside anonymous functions since 5.4 - $minifier = $this; - $this->registerPattern( - '/(?<=^|[;}{])\s*(--[^:;{}"\'\s]+)\s*:([^;{}]+)/m', - function ($match) use ($minifier) { - $placeholder = '--custom-' . count($minifier->extracted) . ':0'; - $minifier->extracted[$placeholder] = $match[1] . ':' . trim($match[2]); - - return $placeholder; - } - ); - } - - /** - * Check if file is small enough to be imported. - * - * @param string $path The path to the file - * - * @return bool - */ - protected function canImportBySize($path) - { - return ($size = @filesize($path)) && $size <= $this->maxImportSize * 1024; - } - - /** - * Check if file a file can be imported, going by the path. - * - * @param string $path - * - * @return bool - */ - protected function canImportByPath($path) - { - return preg_match('/^(data:|https?:|\\/)/', $path) === 0; - } - - /** - * Return a converter to update relative paths to be relative to the new - * destination. - * - * @param string $source - * @param string $target - * - * @return ConverterInterface - */ - protected function getPathConverter($source, $target) - { - return new Converter($source, $target); - } -} diff --git a/includes/classes/Dependencies/MatthiasMullie/Minify/Exception.php b/includes/classes/Dependencies/MatthiasMullie/Minify/Exception.php deleted file mode 100644 index 300e43c..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/Minify/Exception.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ - -namespace PoweredCache\Dependencies\MatthiasMullie\Minify; - -/** - * Base Exception Class. - * - * @deprecated Use Exceptions\BasicException instead - * - * @author Matthias Mullie - */ -abstract class Exception extends \Exception -{ -} diff --git a/includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/BasicException.php b/includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/BasicException.php deleted file mode 100644 index 6b095e7..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/BasicException.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved - * @license MIT License - */ - -namespace PoweredCache\Dependencies\MatthiasMullie\Minify\Exceptions; - -use PoweredCache\Dependencies\MatthiasMullie\Minify\Exception; - -/** - * Basic Exception Class. - * - * @author Matthias Mullie - */ -abstract class BasicException extends Exception -{ -} diff --git a/includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/FileImportException.php b/includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/FileImportException.php deleted file mode 100644 index 312d6ec..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/FileImportException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved - * @license MIT License - */ - -namespace PoweredCache\Dependencies\MatthiasMullie\Minify\Exceptions; - -/** - * File Import Exception Class. - * - * @author Matthias Mullie - */ -class FileImportException extends BasicException -{ -} diff --git a/includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/IOException.php b/includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/IOException.php deleted file mode 100644 index 174d738..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/Minify/Exceptions/IOException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved - * @license MIT License - */ - -namespace PoweredCache\Dependencies\MatthiasMullie\Minify\Exceptions; - -/** - * IO Exception Class. - * - * @author Matthias Mullie - */ -class IOException extends BasicException -{ -} diff --git a/includes/classes/Dependencies/MatthiasMullie/Minify/JS.php b/includes/classes/Dependencies/MatthiasMullie/Minify/JS.php deleted file mode 100644 index f934969..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/Minify/JS.php +++ /dev/null @@ -1,618 +0,0 @@ - - * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved - * @license MIT License - */ - -namespace PoweredCache\Dependencies\MatthiasMullie\Minify; - -/** - * JavaScript Minifier Class. - * - * Please report bugs on https://github.com/matthiasmullie/minify/issues - * - * @author Matthias Mullie - * @author Tijs Verkoyen - * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved - * @license MIT License - */ -class JS extends Minify -{ - /** - * Var-matching regex based on http://stackoverflow.com/a/9337047/802993. - * - * Note that regular expressions using that bit must have the PCRE_UTF8 - * pattern modifier (/u) set. - * - * @internal - * - * @var string - */ - const REGEX_VARIABLE = '\b[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}0-9\x{0300}-\x{036f}\x{0483}-\x{0487}\x{0591}-\x{05bd}\x{05bf}\x{05c1}\x{05c2}\x{05c4}\x{05c5}\x{05c7}\x{0610}-\x{061a}\x{064b}-\x{0669}\x{0670}\x{06d6}-\x{06dc}\x{06df}-\x{06e4}\x{06e7}\x{06e8}\x{06ea}-\x{06ed}\x{06f0}-\x{06f9}\x{0711}\x{0730}-\x{074a}\x{07a6}-\x{07b0}\x{07c0}-\x{07c9}\x{07eb}-\x{07f3}\x{0816}-\x{0819}\x{081b}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082d}\x{0859}-\x{085b}\x{08e4}-\x{08fe}\x{0900}-\x{0903}\x{093a}-\x{093c}\x{093e}-\x{094f}\x{0951}-\x{0957}\x{0962}\x{0963}\x{0966}-\x{096f}\x{0981}-\x{0983}\x{09bc}\x{09be}-\x{09c4}\x{09c7}\x{09c8}\x{09cb}-\x{09cd}\x{09d7}\x{09e2}\x{09e3}\x{09e6}-\x{09ef}\x{0a01}-\x{0a03}\x{0a3c}\x{0a3e}-\x{0a42}\x{0a47}\x{0a48}\x{0a4b}-\x{0a4d}\x{0a51}\x{0a66}-\x{0a71}\x{0a75}\x{0a81}-\x{0a83}\x{0abc}\x{0abe}-\x{0ac5}\x{0ac7}-\x{0ac9}\x{0acb}-\x{0acd}\x{0ae2}\x{0ae3}\x{0ae6}-\x{0aef}\x{0b01}-\x{0b03}\x{0b3c}\x{0b3e}-\x{0b44}\x{0b47}\x{0b48}\x{0b4b}-\x{0b4d}\x{0b56}\x{0b57}\x{0b62}\x{0b63}\x{0b66}-\x{0b6f}\x{0b82}\x{0bbe}-\x{0bc2}\x{0bc6}-\x{0bc8}\x{0bca}-\x{0bcd}\x{0bd7}\x{0be6}-\x{0bef}\x{0c01}-\x{0c03}\x{0c3e}-\x{0c44}\x{0c46}-\x{0c48}\x{0c4a}-\x{0c4d}\x{0c55}\x{0c56}\x{0c62}\x{0c63}\x{0c66}-\x{0c6f}\x{0c82}\x{0c83}\x{0cbc}\x{0cbe}-\x{0cc4}\x{0cc6}-\x{0cc8}\x{0cca}-\x{0ccd}\x{0cd5}\x{0cd6}\x{0ce2}\x{0ce3}\x{0ce6}-\x{0cef}\x{0d02}\x{0d03}\x{0d3e}-\x{0d44}\x{0d46}-\x{0d48}\x{0d4a}-\x{0d4d}\x{0d57}\x{0d62}\x{0d63}\x{0d66}-\x{0d6f}\x{0d82}\x{0d83}\x{0dca}\x{0dcf}-\x{0dd4}\x{0dd6}\x{0dd8}-\x{0ddf}\x{0df2}\x{0df3}\x{0e31}\x{0e34}-\x{0e3a}\x{0e47}-\x{0e4e}\x{0e50}-\x{0e59}\x{0eb1}\x{0eb4}-\x{0eb9}\x{0ebb}\x{0ebc}\x{0ec8}-\x{0ecd}\x{0ed0}-\x{0ed9}\x{0f18}\x{0f19}\x{0f20}-\x{0f29}\x{0f35}\x{0f37}\x{0f39}\x{0f3e}\x{0f3f}\x{0f71}-\x{0f84}\x{0f86}\x{0f87}\x{0f8d}-\x{0f97}\x{0f99}-\x{0fbc}\x{0fc6}\x{102b}-\x{103e}\x{1040}-\x{1049}\x{1056}-\x{1059}\x{105e}-\x{1060}\x{1062}-\x{1064}\x{1067}-\x{106d}\x{1071}-\x{1074}\x{1082}-\x{108d}\x{108f}-\x{109d}\x{135d}-\x{135f}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}\x{1753}\x{1772}\x{1773}\x{17b4}-\x{17d3}\x{17dd}\x{17e0}-\x{17e9}\x{180b}-\x{180d}\x{1810}-\x{1819}\x{18a9}\x{1920}-\x{192b}\x{1930}-\x{193b}\x{1946}-\x{194f}\x{19b0}-\x{19c0}\x{19c8}\x{19c9}\x{19d0}-\x{19d9}\x{1a17}-\x{1a1b}\x{1a55}-\x{1a5e}\x{1a60}-\x{1a7c}\x{1a7f}-\x{1a89}\x{1a90}-\x{1a99}\x{1b00}-\x{1b04}\x{1b34}-\x{1b44}\x{1b50}-\x{1b59}\x{1b6b}-\x{1b73}\x{1b80}-\x{1b82}\x{1ba1}-\x{1bad}\x{1bb0}-\x{1bb9}\x{1be6}-\x{1bf3}\x{1c24}-\x{1c37}\x{1c40}-\x{1c49}\x{1c50}-\x{1c59}\x{1cd0}-\x{1cd2}\x{1cd4}-\x{1ce8}\x{1ced}\x{1cf2}-\x{1cf4}\x{1dc0}-\x{1de6}\x{1dfc}-\x{1dff}\x{200c}\x{200d}\x{203f}\x{2040}\x{2054}\x{20d0}-\x{20dc}\x{20e1}\x{20e5}-\x{20f0}\x{2cef}-\x{2cf1}\x{2d7f}\x{2de0}-\x{2dff}\x{302a}-\x{302f}\x{3099}\x{309a}\x{a620}-\x{a629}\x{a66f}\x{a674}-\x{a67d}\x{a69f}\x{a6f0}\x{a6f1}\x{a802}\x{a806}\x{a80b}\x{a823}-\x{a827}\x{a880}\x{a881}\x{a8b4}-\x{a8c4}\x{a8d0}-\x{a8d9}\x{a8e0}-\x{a8f1}\x{a900}-\x{a909}\x{a926}-\x{a92d}\x{a947}-\x{a953}\x{a980}-\x{a983}\x{a9b3}-\x{a9c0}\x{a9d0}-\x{a9d9}\x{aa29}-\x{aa36}\x{aa43}\x{aa4c}\x{aa4d}\x{aa50}-\x{aa59}\x{aa7b}\x{aab0}\x{aab2}-\x{aab4}\x{aab7}\x{aab8}\x{aabe}\x{aabf}\x{aac1}\x{aaeb}-\x{aaef}\x{aaf5}\x{aaf6}\x{abe3}-\x{abea}\x{abec}\x{abed}\x{abf0}-\x{abf9}\x{fb1e}\x{fe00}-\x{fe0f}\x{fe20}-\x{fe26}\x{fe33}\x{fe34}\x{fe4d}-\x{fe4f}\x{ff10}-\x{ff19}\x{ff3f}]*\b'; - - /** - * Full list of JavaScript reserved words. - * Will be loaded from /data/js/keywords_reserved.txt. - * - * @see https://mathiasbynens.be/notes/reserved-keywords - * - * @var string[] - */ - protected $keywordsReserved = array(); - - /** - * List of JavaScript reserved words that accept a - * after them. Some end of lines are not the end of a statement, like with - * these keywords. - * - * E.g.: we shouldn't insert a ; after this else - * else - * console.log('this is quite fine') - * - * Will be loaded from /data/js/keywords_before.txt - * - * @var string[] - */ - protected $keywordsBefore = array(); - - /** - * List of JavaScript reserved words that accept a - * before them. Some end of lines are not the end of a statement, like when - * continued by one of these keywords on the newline. - * - * E.g.: we shouldn't insert a ; before this instanceof - * variable - * instanceof String - * - * Will be loaded from /data/js/keywords_after.txt - * - * @var string[] - */ - protected $keywordsAfter = array(); - - /** - * List of all JavaScript operators. - * - * Will be loaded from /data/js/operators.txt - * - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators - * - * @var string[] - */ - protected $operators = array(); - - /** - * List of JavaScript operators that accept a after - * them. Some end of lines are not the end of a statement, like with these - * operators. - * - * Note: Most operators are fine, we've only removed ++ and --. - * ++ & -- have to be joined with the value they're in-/decrementing. - * - * Will be loaded from /data/js/operators_before.txt - * - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators - * - * @var string[] - */ - protected $operatorsBefore = array(); - - /** - * List of JavaScript operators that accept a before - * them. Some end of lines are not the end of a statement, like when - * continued by one of these operators on the newline. - * - * Note: Most operators are fine, we've only removed ), ], ++, --, ! and ~. - * There can't be a newline separating ! or ~ and whatever it is negating. - * ++ & -- have to be joined with the value they're in-/decrementing. - * ) & ] are "special" in that they have lots or usecases. () for example - * is used for function calls, for grouping, in if () and for (), ... - * - * Will be loaded from /data/js/operators_after.txt - * - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators - * - * @var string[] - */ - protected $operatorsAfter = array(); - - public function __construct() - { - call_user_func_array(array('\\PoweredCache\Dependencies\MatthiasMullie\Minify\\Minify', '__construct'), func_get_args()); - - $dataDir = __DIR__ . '/../data/js/'; - $options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES; - $this->keywordsReserved = file($dataDir . 'keywords_reserved.txt', $options); - $this->keywordsBefore = file($dataDir . 'keywords_before.txt', $options); - $this->keywordsAfter = file($dataDir . 'keywords_after.txt', $options); - $this->operators = file($dataDir . 'operators.txt', $options); - $this->operatorsBefore = file($dataDir . 'operators_before.txt', $options); - $this->operatorsAfter = file($dataDir . 'operators_after.txt', $options); - } - - /** - * Minify the data. - * Perform JS optimizations. - * - * @param string[optional] $path Path to write the data to - * - * @return string The minified data - */ - public function execute($path = null) - { - $content = ''; - - /* - * Let's first take out strings, comments and regular expressions. - * All of these can contain JS code-like characters, and we should make - * sure any further magic ignores anything inside of these. - * - * Consider this example, where we should not strip any whitespace: - * var str = "a test"; - * - * Comments will be removed altogether, strings and regular expressions - * will be replaced by placeholder text, which we'll restore later. - */ - $this->extractStrings('\'"`'); - $this->stripComments(); - $this->extractRegex(); - - // loop files - foreach ($this->data as $source => $js) { - // take out strings, comments & regex (for which we've registered - // the regexes just a few lines earlier) - $js = $this->replace($js); - - $js = $this->propertyNotation($js); - $js = $this->shortenBools($js); - $js = $this->stripWhitespace($js); - - // combine js: separating the scripts by a ; - $content .= $js . ';'; - } - - // clean up leftover `;`s from the combination of multiple scripts - $content = ltrim($content, ';'); - $content = (string) substr($content, 0, -1); - - /* - * Earlier, we extracted strings & regular expressions and replaced them - * with placeholder text. This will restore them. - */ - $content = $this->restoreExtractedData($content); - - return $content; - } - - /** - * Strip comments from source code. - */ - protected function stripComments() - { - $this->stripMultilineComments(); - - // single-line comments - $this->registerPattern('/\/\/.*$/m', ''); - } - - /** - * JS can have /-delimited regular expressions, like: /ab+c/.match(string). - * - * The content inside the regex can contain characters that may be confused - * for JS code: e.g. it could contain whitespace it needs to match & we - * don't want to strip whitespace in there. - * - * The regex can be pretty simple: we don't have to care about comments, - * (which also use slashes) because stripComments() will have stripped those - * already. - * - * This method will replace all string content with simple REGEX# - * placeholder text, so we've rid all regular expressions from characters - * that may be misinterpreted. Original regex content will be saved in - * $this->extracted and after doing all other minifying, we can restore the - * original content via restoreRegex() - */ - protected function extractRegex() - { - // PHP only supports $this inside anonymous functions since 5.4 - $minifier = $this; - $callback = function ($match) use ($minifier) { - $count = count($minifier->extracted); - $placeholder = '"' . $count . '"'; - $minifier->extracted[$placeholder] = $match[0]; - - return $placeholder; - }; - - // match all chars except `/` and `\` - // `\` is allowed though, along with whatever char follows (which is the - // one being escaped) - // this should allow all chars, except for an unescaped `/` (= the one - // closing the regex) - // then also ignore bare `/` inside `[]`, where they don't need to be - // escaped: anything inside `[]` can be ignored safely - $pattern = '\\/(?!\*)(?:[^\\[\\/\\\\\n\r]++|(?:\\\\.)++|(?:\\[(?:[^\\]\\\\\n\r]++|(?:\\\\.)++)++\\])++)++\\/[gimuy]*'; - - // a regular expression can only be followed by a few operators or some - // of the RegExp methods (a `\` followed by a variable or value is - // likely part of a division, not a regex) - $keywords = array('do', 'in', 'new', 'else', 'throw', 'yield', 'delete', 'return', 'typeof'); - $before = '(^|[=:,;\+\-\*\?\/\}\(\{\[&\|!]|' . implode('|', $keywords) . ')\s*'; - $propertiesAndMethods = array( - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Properties_2 - 'constructor', - 'flags', - 'global', - 'ignoreCase', - 'multiline', - 'source', - 'sticky', - 'unicode', - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Methods_2 - 'compile(', - 'exec(', - 'test(', - 'toSource(', - 'toString(', - ); - $delimiters = array_fill(0, count($propertiesAndMethods), '/'); - $propertiesAndMethods = array_map('preg_quote', $propertiesAndMethods, $delimiters); - $after = '(?=\s*([\.,;:\)\}&\|+]|\/\/|$|\.(' . implode('|', $propertiesAndMethods) . ')))'; - $this->registerPattern('/' . $before . '\K' . $pattern . $after . '/', $callback); - - // regular expressions following a `)` are rather annoying to detect... - // quite often, `/` after `)` is a division operator & if it happens to - // be followed by another one (or a comment), it is likely to be - // confused for a regular expression - // however, it's perfectly possible for a regex to follow a `)`: after - // a single-line `if()`, `while()`, ... statement, for example - // since, when they occur like that, they're always the start of a - // statement, there's only a limited amount of ways they can be useful: - // by calling the regex methods directly - // if a regex following `)` is not followed by `.`, - // it's quite likely not a regex - $before = '\)\s*'; - $after = '(?=\s*\.(' . implode('|', $propertiesAndMethods) . '))'; - $this->registerPattern('/' . $before . '\K' . $pattern . $after . '/', $callback); - - // 1 more edge case: a regex can be followed by a lot more operators or - // keywords if there's a newline (ASI) in between, where the operator - // actually starts a new statement - // (https://github.com/matthiasmullie/minify/issues/56) - $operators = $this->getOperatorsForRegex($this->operatorsBefore, '/'); - $operators += $this->getOperatorsForRegex($this->keywordsReserved, '/'); - $after = '(?=\s*\n\s*(' . implode('|', $operators) . '))'; - $this->registerPattern('/' . $pattern . $after . '/', $callback); - } - - /** - * Strip whitespace. - * - * We won't strip *all* whitespace, but as much as possible. The thing that - * we'll preserve are newlines we're unsure about. - * JavaScript doesn't require statements to be terminated with a semicolon. - * It will automatically fix missing semicolons with ASI (automatic semi- - * colon insertion) at the end of line causing errors (without semicolon.) - * - * Because it's sometimes hard to tell if a newline is part of a statement - * that should be terminated or not, we'll just leave some of them alone. - * - * @param string $content The content to strip the whitespace for - * - * @return string - */ - protected function stripWhitespace($content) - { - // uniform line endings, make them all line feed - $content = str_replace(array("\r\n", "\r"), "\n", $content); - - // collapse all non-line feed whitespace into a single space - $content = preg_replace('/[^\S\n]+/', ' ', $content); - - // strip leading & trailing whitespace - $content = str_replace(array(" \n", "\n "), "\n", $content); - - // collapse consecutive line feeds into just 1 - $content = preg_replace('/\n+/', "\n", $content); - - $operatorsBefore = $this->getOperatorsForRegex($this->operatorsBefore, '/'); - $operatorsAfter = $this->getOperatorsForRegex($this->operatorsAfter, '/'); - $operators = $this->getOperatorsForRegex($this->operators, '/'); - $keywordsBefore = $this->getKeywordsForRegex($this->keywordsBefore, '/'); - $keywordsAfter = $this->getKeywordsForRegex($this->keywordsAfter, '/'); - - // strip whitespace that ends in (or next line begin with) an operator - // that allows statements to be broken up over multiple lines - unset($operatorsBefore['+'], $operatorsBefore['-'], $operatorsAfter['+'], $operatorsAfter['-']); - $content = preg_replace( - array( - '/(' . implode('|', $operatorsBefore) . ')\s+/', - '/\s+(' . implode('|', $operatorsAfter) . ')/', - ), - '\\1', - $content - ); - - // make sure + and - can't be mistaken for, or joined into ++ and -- - $content = preg_replace( - array( - '/(?%&|', $delimiter); - $operators['='] = '(?keywordsReserved; - $callback = function ($match) use ($minifier, $keywords) { - $property = trim($minifier->extracted[$match[1]], '\'"'); - - /* - * Check if the property is a reserved keyword. In this context (as - * property of an object literal/array) it shouldn't matter, but IE8 - * freaks out with "Expected identifier". - */ - if (in_array($property, $keywords)) { - return $match[0]; - } - - /* - * See if the property is in a variable-like format (e.g. - * array['key-here'] can't be replaced by array.key-here since '-' - * is not a valid character there. - */ - if (!preg_match('/^' . $minifier::REGEX_VARIABLE . '$/u', $property)) { - return $match[0]; - } - - return '.' . $property; - }; - - /* - * Figure out if previous character is a variable name (of the array - * we want to use property notation on) - this is to make sure - * standalone ['value'] arrays aren't confused for keys-of-an-array. - * We can (and only have to) check the last character, because PHP's - * regex implementation doesn't allow unfixed-length look-behind - * assertions. - */ - preg_match('/(\[[^\]]+\])[^\]]*$/', static::REGEX_VARIABLE, $previousChar); - $previousChar = $previousChar[1]; - - /* - * Make sure word preceding the ['value'] is not a keyword, e.g. - * return['x']. Because -again- PHP's regex implementation doesn't allow - * unfixed-length look-behind assertions, I'm just going to do a lot of - * separate look-behind assertions, one for each keyword. - */ - $keywords = $this->getKeywordsForRegex($keywords); - $keywords = '(? - * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved - * @license MIT License - */ - -namespace PoweredCache\Dependencies\MatthiasMullie\Minify; - -use PoweredCache\Dependencies\MatthiasMullie\Minify\Exceptions\IOException; -use Psr\Cache\CacheItemInterface; - -/** - * Abstract minifier class. - * - * Please report bugs on https://github.com/matthiasmullie/minify/issues - * - * @author Matthias Mullie - * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved - * @license MIT License - */ -abstract class Minify -{ - /** - * The data to be minified. - * - * @var string[] - */ - protected $data = array(); - - /** - * Array of patterns to match. - * - * @var string[] - */ - protected $patterns = array(); - - /** - * This array will hold content of strings and regular expressions that have - * been extracted from the JS source code, so we can reliably match "code", - * without having to worry about potential "code-like" characters inside. - * - * @internal - * - * @var string[] - */ - public $extracted = array(); - - /** - * Init the minify class - optionally, code may be passed along already. - */ - public function __construct(/* $data = null, ... */) - { - // it's possible to add the source through the constructor as well ;) - if (func_num_args()) { - call_user_func_array(array($this, 'add'), func_get_args()); - } - } - - /** - * Add a file or straight-up code to be minified. - * - * @param string|string[] $data - * - * @return static - */ - public function add($data /* $data = null, ... */) - { - // bogus "usage" of parameter $data: scrutinizer warns this variable is - // not used (we're using func_get_args instead to support overloading), - // but it still needs to be defined because it makes no sense to have - // this function without argument :) - $args = array($data) + func_get_args(); - - // this method can be overloaded - foreach ($args as $data) { - if (is_array($data)) { - call_user_func_array(array($this, 'add'), $data); - continue; - } - - // redefine var - $data = (string) $data; - - // load data - $value = $this->load($data); - $key = ($data != $value) ? $data : count($this->data); - - // replace CR linefeeds etc. - // @see https://github.com/matthiasmullie/minify/pull/139 - $value = str_replace(array("\r\n", "\r"), "\n", $value); - - // store data - $this->data[$key] = $value; - } - - return $this; - } - - /** - * Add a file to be minified. - * - * @param string|string[] $data - * - * @return static - * - * @throws IOException - */ - public function addFile($data /* $data = null, ... */) - { - // bogus "usage" of parameter $data: scrutinizer warns this variable is - // not used (we're using func_get_args instead to support overloading), - // but it still needs to be defined because it makes no sense to have - // this function without argument :) - $args = array($data) + func_get_args(); - - // this method can be overloaded - foreach ($args as $path) { - if (is_array($path)) { - call_user_func_array(array($this, 'addFile'), $path); - continue; - } - - // redefine var - $path = (string) $path; - - // check if we can read the file - if (!$this->canImportFile($path)) { - throw new IOException('The file "' . $path . '" could not be opened for reading. Check if PHP has enough permissions.'); - } - - $this->add($path); - } - - return $this; - } - - /** - * Minify the data & (optionally) saves it to a file. - * - * @param string[optional] $path Path to write the data to - * - * @return string The minified data - */ - public function minify($path = null) - { - $content = $this->execute($path); - - // save to path - if ($path !== null) { - $this->save($content, $path); - } - - return $content; - } - - /** - * Minify & gzip the data & (optionally) saves it to a file. - * - * @param string[optional] $path Path to write the data to - * @param int[optional] $level Compression level, from 0 to 9 - * - * @return string The minified & gzipped data - */ - public function gzip($path = null, $level = 9) - { - $content = $this->execute($path); - $content = gzencode($content, $level, FORCE_GZIP); - - // save to path - if ($path !== null) { - $this->save($content, $path); - } - - return $content; - } - - /** - * Minify the data & write it to a CacheItemInterface object. - * - * @param CacheItemInterface $item Cache item to write the data to - * - * @return CacheItemInterface Cache item with the minifier data - */ - public function cache(CacheItemInterface $item) - { - $content = $this->execute(); - $item->set($content); - - return $item; - } - - /** - * Minify the data. - * - * @param string[optional] $path Path to write the data to - * - * @return string The minified data - */ - abstract public function execute($path = null); - - /** - * Load data. - * - * @param string $data Either a path to a file or the content itself - * - * @return string - */ - protected function load($data) - { - // check if the data is a file - if ($this->canImportFile($data)) { - $data = file_get_contents($data); - - // strip BOM, if any - if (substr($data, 0, 3) == "\xef\xbb\xbf") { - $data = substr($data, 3); - } - } - - return $data; - } - - /** - * Save to file. - * - * @param string $content The minified data - * @param string $path The path to save the minified data to - * - * @throws IOException - */ - protected function save($content, $path) - { - $handler = $this->openFileForWriting($path); - - $this->writeToFile($handler, $content); - - @fclose($handler); - } - - /** - * Register a pattern to execute against the source content. - * - * If $replacement is a string, it must be plain text. Placeholders like $1 or \2 don't work. - * If you need that functionality, use a callback instead. - * - * @param string $pattern PCRE pattern - * @param string|callable $replacement Replacement value for matched pattern - */ - protected function registerPattern($pattern, $replacement = '') - { - // study the pattern, we'll execute it more than once - $pattern .= 'S'; - - $this->patterns[] = array($pattern, $replacement); - } - - /** - * Both JS and CSS use the same form of multi-line comment, so putting the common code here. - */ - protected function stripMultilineComments() - { - // First extract comments we want to keep, so they can be restored later - // PHP only supports $this inside anonymous functions since 5.4 - $minifier = $this; - $callback = function ($match) use ($minifier) { - $count = count($minifier->extracted); - $placeholder = '/*' . $count . '*/'; - $minifier->extracted[$placeholder] = $match[0]; - - return $placeholder; - }; - $this->registerPattern('/ - # optional newline - \n? - - # start comment - \/\* - - # comment content - (?: - # either starts with an ! - ! - | - # or, after some number of characters which do not end the comment - (?:(?!\*\/).)*? - - # there is either a @license or @preserve tag - @(?:license|preserve) - ) - - # then match to the end of the comment - .*?\*\/\n? - - /ixs', $callback); - - // Then strip all other comments - $this->registerPattern('/\/\*.*?\*\//s', ''); - } - - /** - * We can't "just" run some regular expressions against JavaScript: it's a - * complex language. E.g. having an occurrence of // xyz would be a comment, - * unless it's used within a string. Of you could have something that looks - * like a 'string', but inside a comment. - * The only way to accurately replace these pieces is to traverse the JS one - * character at a time and try to find whatever starts first. - * - * @param string $content The content to replace patterns in - * - * @return string The (manipulated) content - */ - protected function replace($content) - { - $contentLength = strlen($content); - $output = ''; - $processedOffset = 0; - $positions = array_fill(0, count($this->patterns), -1); - $matches = array(); - - while ($processedOffset < $contentLength) { - // find first match for all patterns - foreach ($this->patterns as $i => $pattern) { - list($pattern, $replacement) = $pattern; - - // we can safely ignore patterns for positions we've unset earlier, - // because we know these won't show up anymore - if (array_key_exists($i, $positions) == false) { - continue; - } - - // no need to re-run matches that are still in the part of the - // content that hasn't been processed - if ($positions[$i] >= $processedOffset) { - continue; - } - - $match = null; - if (preg_match($pattern, $content, $match, PREG_OFFSET_CAPTURE, $processedOffset)) { - $matches[$i] = $match; - - // we'll store the match position as well; that way, we - // don't have to redo all preg_matches after changing only - // the first (we'll still know where those others are) - $positions[$i] = $match[0][1]; - } else { - // if the pattern couldn't be matched, there's no point in - // executing it again in later runs on this same content; - // ignore this one until we reach end of content - unset($matches[$i], $positions[$i]); - } - } - - // no more matches to find: everything's been processed, break out - if (!$matches) { - // output the remaining content - $output .= substr($content, $processedOffset); - break; - } - - // see which of the patterns actually found the first thing (we'll - // only want to execute that one, since we're unsure if what the - // other found was not inside what the first found) - $matchOffset = min($positions); - $firstPattern = array_search($matchOffset, $positions); - $match = $matches[$firstPattern]; - - // execute the pattern that matches earliest in the content string - list(, $replacement) = $this->patterns[$firstPattern]; - - // add the part of the input between $processedOffset and the first match; - // that content wasn't matched by anything - $output .= substr($content, $processedOffset, $matchOffset - $processedOffset); - // add the replacement for the match - $output .= $this->executeReplacement($replacement, $match); - // advance $processedOffset past the match - $processedOffset = $matchOffset + strlen($match[0][0]); - } - - return $output; - } - - /** - * If $replacement is a callback, execute it, passing in the match data. - * If it's a string, just pass it through. - * - * @param string|callable $replacement Replacement value - * @param array $match Match data, in PREG_OFFSET_CAPTURE form - * - * @return string - */ - protected function executeReplacement($replacement, $match) - { - if (!is_callable($replacement)) { - return $replacement; - } - // convert $match from the PREG_OFFSET_CAPTURE form to the form the callback expects - foreach ($match as &$matchItem) { - $matchItem = $matchItem[0]; - } - - return $replacement($match); - } - - /** - * Strings are a pattern we need to match, in order to ignore potential - * code-like content inside them, but we just want all of the string - * content to remain untouched. - * - * This method will replace all string content with simple STRING# - * placeholder text, so we've rid all strings from characters that may be - * misinterpreted. Original string content will be saved in $this->extracted - * and after doing all other minifying, we can restore the original content - * via restoreStrings(). - * - * @param string[optional] $chars - * @param string[optional] $placeholderPrefix - */ - protected function extractStrings($chars = '\'"', $placeholderPrefix = '') - { - // PHP only supports $this inside anonymous functions since 5.4 - $minifier = $this; - $callback = function ($match) use ($minifier, $placeholderPrefix) { - // check the second index here, because the first always contains a quote - if ($match[2] === '') { - /* - * Empty strings need no placeholder; they can't be confused for - * anything else anyway. - * But we still needed to match them, for the extraction routine - * to skip over this particular string. - */ - return $match[0]; - } - - $count = count($minifier->extracted); - $placeholder = $match[1] . $placeholderPrefix . $count . $match[1]; - $minifier->extracted[$placeholder] = $match[1] . $match[2] . $match[1]; - - return $placeholder; - }; - - /* - * The \\ messiness explained: - * * Don't count ' or " as end-of-string if it's escaped (has backslash - * in front of it) - * * Unless... that backslash itself is escaped (another leading slash), - * in which case it's no longer escaping the ' or " - * * So there can be either no backslash, or an even number - * * multiply all of that times 4, to account for the escaping that has - * to be done to pass the backslash into the PHP string without it being - * considered as escape-char (times 2) and to get it in the regex, - * escaped (times 2) - */ - $this->registerPattern('/([' . $chars . '])(.*?(?extracted. - * - * @param string $content - * - * @return string - */ - protected function restoreExtractedData($content) - { - if (!$this->extracted) { - // nothing was extracted, nothing to restore - return $content; - } - - $content = strtr($content, $this->extracted); - - $this->extracted = array(); - - return $content; - } - - /** - * Check if the path is a regular file and can be read. - * - * @param string $path - * - * @return bool - */ - protected function canImportFile($path) - { - $parsed = parse_url($path); - if ( - // file is elsewhere - isset($parsed['host']) - // file responds to queries (may change, or need to bypass cache) - || isset($parsed['query']) - ) { - return false; - } - - try { - return strlen($path) < PHP_MAXPATHLEN && @is_file($path) && is_readable($path); - } - // catch openbasedir exceptions which are not caught by @ on is_file() - catch (\Exception $e) { - return false; - } - } - - /** - * Attempts to open file specified by $path for writing. - * - * @param string $path The path to the file - * - * @return resource Specifier for the target file - * - * @throws IOException - */ - protected function openFileForWriting($path) - { - if ($path === '' || ($handler = @fopen($path, 'w')) === false) { - throw new IOException('The file "' . $path . '" could not be opened for writing. Check if PHP has enough permissions.'); - } - - return $handler; - } - - /** - * Attempts to write $content to the file specified by $handler. $path is used for printing exceptions. - * - * @param resource $handler The resource to write to - * @param string $content The content to write - * @param string $path The path to the file (for exception printing only) - * - * @throws IOException - */ - protected function writeToFile($handler, $content, $path = '') - { - if ( - !is_resource($handler) - || ($result = @fwrite($handler, $content)) === false - || ($result < strlen($content)) - ) { - throw new IOException('The file "' . $path . '" could not be written to. Check your disk space and file permissions.'); - } - } - - protected static function str_replace_first($search, $replace, $subject) - { - $pos = strpos($subject, $search); - if ($pos !== false) { - return substr_replace($subject, $replace, $pos, strlen($search)); - } - - return $subject; - } -} diff --git a/includes/classes/Dependencies/MatthiasMullie/PathConverter/Converter.php b/includes/classes/Dependencies/MatthiasMullie/PathConverter/Converter.php deleted file mode 100644 index d1aedbd..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/PathConverter/Converter.php +++ /dev/null @@ -1,204 +0,0 @@ - - * @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved - * @license MIT License - */ -class Converter implements ConverterInterface -{ - /** - * @var string - */ - protected $from; - - /** - * @var string - */ - protected $to; - - /** - * @param string $from The original base path (directory, not file!) - * @param string $to The new base path (directory, not file!) - * @param string $root Root directory (defaults to `getcwd`) - */ - public function __construct($from, $to, $root = '') - { - $shared = $this->shared($from, $to); - if ($shared === '') { - // when both paths have nothing in common, one of them is probably - // absolute while the other is relative - $root = $root ?: getcwd(); - $from = strpos($from, $root) === 0 ? $from : preg_replace('/\/+/', '/', $root.'/'.$from); - $to = strpos($to, $root) === 0 ? $to : preg_replace('/\/+/', '/', $root.'/'.$to); - - // or traveling the tree via `..` - // attempt to resolve path, or assume it's fine if it doesn't exist - $from = @realpath($from) ?: $from; - $to = @realpath($to) ?: $to; - } - - $from = $this->dirname($from); - $to = $this->dirname($to); - - $from = $this->normalize($from); - $to = $this->normalize($to); - - $this->from = $from; - $this->to = $to; - } - - /** - * Normalize path. - * - * @param string $path - * - * @return string - */ - protected function normalize($path) - { - // deal with different operating systems' directory structure - $path = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '/'); - - // remove leading current directory. - if (substr($path, 0, 2) === './') { - $path = substr($path, 2); - } - - // remove references to current directory in the path. - $path = str_replace('/./', '/', $path); - - /* - * Example: - * /home/forkcms/frontend/cache/compiled_templates/../../core/layout/css/../images/img.gif - * to - * /home/forkcms/frontend/core/layout/images/img.gif - */ - do { - $path = preg_replace('/[^\/]+(? $chunk) { - if (isset($path2[$i]) && $path1[$i] == $path2[$i]) { - $shared[] = $chunk; - } else { - break; - } - } - - return implode('/', $shared); - } - - /** - * Convert paths relative from 1 file to another. - * - * E.g. - * ../images/img.gif relative to /home/forkcms/frontend/core/layout/css - * should become: - * ../../core/layout/images/img.gif relative to - * /home/forkcms/frontend/cache/minified_css - * - * @param string $path The relative path that needs to be converted - * - * @return string The new relative path - */ - public function convert($path) - { - // quit early if conversion makes no sense - if ($this->from === $this->to) { - return $path; - } - - $path = $this->normalize($path); - // if we're not dealing with a relative path, just return absolute - if (strpos($path, '/') === 0) { - return $path; - } - - // normalize paths - $path = $this->normalize($this->from.'/'.$path); - - // strip shared ancestor paths - $shared = $this->shared($path, $this->to); - $path = mb_substr($path, mb_strlen($shared)); - $to = mb_substr($this->to, mb_strlen($shared)); - - // add .. for every directory that needs to be traversed to new path - $to = str_repeat('../', count(array_filter(explode('/', $to)))); - - return $to.ltrim($path, '/'); - } - - /** - * Attempt to get the directory name from a path. - * - * @param string $path - * - * @return string - */ - protected function dirname($path) - { - if (@is_file($path)) { - return dirname($path); - } - - if (@is_dir($path)) { - return rtrim($path, '/'); - } - - // no known file/dir, start making assumptions - - // ends in / = dir - if (mb_substr($path, -1) === '/') { - return rtrim($path, '/'); - } - - // has a dot in the name, likely a file - if (preg_match('/.*\..*$/', basename($path)) !== 0) { - return dirname($path); - } - - // you're on your own here! - return $path; - } -} diff --git a/includes/classes/Dependencies/MatthiasMullie/PathConverter/ConverterInterface.php b/includes/classes/Dependencies/MatthiasMullie/PathConverter/ConverterInterface.php deleted file mode 100644 index 729ecbd..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/PathConverter/ConverterInterface.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved - * @license MIT License - */ -interface ConverterInterface -{ - /** - * Convert file paths. - * - * @param string $path The path to be converted - * - * @return string The new path - */ - public function convert($path); -} diff --git a/includes/classes/Dependencies/MatthiasMullie/PathConverter/NoConverter.php b/includes/classes/Dependencies/MatthiasMullie/PathConverter/NoConverter.php deleted file mode 100644 index f004bd0..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/PathConverter/NoConverter.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved - * @license MIT License - */ -class NoConverter implements ConverterInterface -{ - /** - * {@inheritdoc} - */ - public function convert($path) - { - return $path; - } -} diff --git a/includes/classes/Dependencies/MatthiasMullie/data/js/keywords_after.txt b/includes/classes/Dependencies/MatthiasMullie/data/js/keywords_after.txt deleted file mode 100644 index 5c8cba7..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/data/js/keywords_after.txt +++ /dev/null @@ -1,7 +0,0 @@ -in -public -extends -private -protected -implements -instanceof \ No newline at end of file diff --git a/includes/classes/Dependencies/MatthiasMullie/data/js/keywords_before.txt b/includes/classes/Dependencies/MatthiasMullie/data/js/keywords_before.txt deleted file mode 100644 index 5abf357..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/data/js/keywords_before.txt +++ /dev/null @@ -1,26 +0,0 @@ -do -in -let -new -var -case -else -enum -void -with -class -const -yield -delete -export -import -public -static -typeof -extends -package -private -function -protected -implements -instanceof \ No newline at end of file diff --git a/includes/classes/Dependencies/MatthiasMullie/data/js/keywords_reserved.txt b/includes/classes/Dependencies/MatthiasMullie/data/js/keywords_reserved.txt deleted file mode 100644 index 2a3ad3c..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/data/js/keywords_reserved.txt +++ /dev/null @@ -1,63 +0,0 @@ -do -if -in -for -let -new -try -var -case -else -enum -eval -null -this -true -void -with -break -catch -class -const -false -super -throw -while -yield -delete -export -import -public -return -static -switch -typeof -default -extends -finally -package -private -continue -debugger -function -arguments -interface -protected -implements -instanceof -abstract -boolean -byte -char -double -final -float -goto -int -long -native -short -synchronized -throws -transient -volatile \ No newline at end of file diff --git a/includes/classes/Dependencies/MatthiasMullie/data/js/operators.txt b/includes/classes/Dependencies/MatthiasMullie/data/js/operators.txt deleted file mode 100644 index e66229a..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/data/js/operators.txt +++ /dev/null @@ -1,46 +0,0 @@ -+ -- -* -/ -% -= -+= --= -*= -/= -%= -<<= ->>= ->>>= -&= -^= -|= -& -| -^ -~ -<< ->> ->>> -== -=== -!= -!== -> -< ->= -<= -&& -|| -! -. -[ -] -? -: -, -; -( -) -{ -} \ No newline at end of file diff --git a/includes/classes/Dependencies/MatthiasMullie/data/js/operators_after.txt b/includes/classes/Dependencies/MatthiasMullie/data/js/operators_after.txt deleted file mode 100644 index 71a9b70..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/data/js/operators_after.txt +++ /dev/null @@ -1,43 +0,0 @@ -+ -- -* -/ -% -= -+= --= -*= -/= -%= -<<= ->>= ->>>= -&= -^= -|= -& -| -^ -<< ->> ->>> -== -=== -!= -!== -> -< ->= -<= -&& -|| -. -[ -] -? -: -, -; -( -) -} \ No newline at end of file diff --git a/includes/classes/Dependencies/MatthiasMullie/data/js/operators_before.txt b/includes/classes/Dependencies/MatthiasMullie/data/js/operators_before.txt deleted file mode 100644 index ff50d87..0000000 --- a/includes/classes/Dependencies/MatthiasMullie/data/js/operators_before.txt +++ /dev/null @@ -1,43 +0,0 @@ -+ -- -* -/ -% -= -+= --= -*= -/= -%= -<<= ->>= ->>>= -&= -^= -|= -& -| -^ -~ -<< ->> ->>> -== -=== -!= -!== -> -< ->= -<= -&& -|| -! -. -[ -? -: -, -; -( -{ diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/CHANGELOG.md b/includes/classes/Dependencies/Symfony/Component/CssSelector/CHANGELOG.md deleted file mode 100644 index de81fa2..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/CHANGELOG.md +++ /dev/null @@ -1,18 +0,0 @@ -CHANGELOG -========= - -4.4.0 ------ - - * Added support for `*:only-of-type` - -2.8.0 ------ - - * Added the `CssSelectorConverter` class as a non-static API for the component. - * Deprecated the `CssSelector` static API of the component. - -2.1.0 ------ - - * none diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/CssSelectorConverter.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/CssSelectorConverter.php deleted file mode 100644 index 8336bfe..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/CssSelectorConverter.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\ClassParser; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\ElementParser; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\HashParser; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Extension\HtmlExtension; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Translator; - -/** - * CssSelectorConverter is the main entry point of the component and can convert CSS - * selectors to XPath expressions. - * - * @author Christophe Coevoet - */ -class CssSelectorConverter -{ - private $translator; - private $cache; - - private static $xmlCache = []; - private static $htmlCache = []; - - /** - * @param bool $html Whether HTML support should be enabled. Disable it for XML documents - */ - public function __construct(bool $html = true) - { - $this->translator = new Translator(); - - if ($html) { - $this->translator->registerExtension(new HtmlExtension($this->translator)); - $this->cache = &self::$htmlCache; - } else { - $this->cache = &self::$xmlCache; - } - - $this->translator - ->registerParserShortcut(new EmptyStringParser()) - ->registerParserShortcut(new ElementParser()) - ->registerParserShortcut(new ClassParser()) - ->registerParserShortcut(new HashParser()) - ; - } - - /** - * Translates a CSS expression to its XPath equivalent. - * - * Optionally, a prefix can be added to the resulting XPath - * expression with the $prefix parameter. - * - * @return string - */ - public function toXPath(string $cssExpr, string $prefix = 'descendant-or-self::') - { - return $this->cache[$prefix][$cssExpr] ?? $this->cache[$prefix][$cssExpr] = $this->translator->cssToXPath($cssExpr, $prefix); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ExceptionInterface.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ExceptionInterface.php deleted file mode 100644 index 311463d..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ExceptionInterface.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception; - -/** - * Interface for exceptions. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ExpressionErrorException.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ExpressionErrorException.php deleted file mode 100644 index 63e7ede..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ExpressionErrorException.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception; - -/** - * ParseException is thrown when a CSS selector syntax is not valid. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - */ -class ExpressionErrorException extends ParseException -{ -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/InternalErrorException.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/InternalErrorException.php deleted file mode 100644 index 0e23f8b..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/InternalErrorException.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception; - -/** - * ParseException is thrown when a CSS selector syntax is not valid. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - */ -class InternalErrorException extends ParseException -{ -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ParseException.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ParseException.php deleted file mode 100644 index b3f0b1a..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/ParseException.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception; - -/** - * ParseException is thrown when a CSS selector syntax is not valid. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Fabien Potencier - */ -class ParseException extends \Exception implements ExceptionInterface -{ -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/SyntaxErrorException.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/SyntaxErrorException.php deleted file mode 100644 index 55d000d..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Exception/SyntaxErrorException.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; - -/** - * ParseException is thrown when a CSS selector syntax is not valid. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - */ -class SyntaxErrorException extends ParseException -{ - /** - * @return self - */ - public static function unexpectedToken(string $expectedValue, Token $foundToken) - { - return new self(sprintf('Expected %s, but %s found.', $expectedValue, $foundToken)); - } - - /** - * @return self - */ - public static function pseudoElementFound(string $pseudoElement, string $unexpectedLocation) - { - return new self(sprintf('Unexpected pseudo-element "::%s" found %s.', $pseudoElement, $unexpectedLocation)); - } - - /** - * @return self - */ - public static function unclosedString(int $position) - { - return new self(sprintf('Unclosed/invalid string at %s.', $position)); - } - - /** - * @return self - */ - public static function nestedNot() - { - return new self('Got nested ::not().'); - } - - /** - * @return self - */ - public static function stringAsFunctionArgument() - { - return new self('String not allowed as function argument.'); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/LICENSE b/includes/classes/Dependencies/Symfony/Component/CssSelector/LICENSE deleted file mode 100644 index 0138f8f..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-present Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/AbstractNode.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/AbstractNode.php deleted file mode 100644 index c643366..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/AbstractNode.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -/** - * Abstract base node class. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -abstract class AbstractNode implements NodeInterface -{ - /** - * @var string - */ - private $nodeName; - - public function getNodeName(): string - { - if (null === $this->nodeName) { - $this->nodeName = preg_replace('~.*\\\\([^\\\\]+)Node$~', '$1', static::class); - } - - return $this->nodeName; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/AttributeNode.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/AttributeNode.php deleted file mode 100644 index e624a46..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/AttributeNode.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -/** - * Represents a "[| ]" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class AttributeNode extends AbstractNode -{ - private $selector; - private $namespace; - private $attribute; - private $operator; - private $value; - - public function __construct(NodeInterface $selector, ?string $namespace, string $attribute, string $operator, ?string $value) - { - $this->selector = $selector; - $this->namespace = $namespace; - $this->attribute = $attribute; - $this->operator = $operator; - $this->value = $value; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getNamespace(): ?string - { - return $this->namespace; - } - - public function getAttribute(): string - { - return $this->attribute; - } - - public function getOperator(): string - { - return $this->operator; - } - - public function getValue(): ?string - { - return $this->value; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); - } - - public function __toString(): string - { - $attribute = $this->namespace ? $this->namespace.'|'.$this->attribute : $this->attribute; - - return 'exists' === $this->operator - ? sprintf('%s[%s[%s]]', $this->getNodeName(), $this->selector, $attribute) - : sprintf("%s[%s[%s %s '%s']]", $this->getNodeName(), $this->selector, $attribute, $this->operator, $this->value); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/ClassNode.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/ClassNode.php deleted file mode 100644 index 1efb467..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/ClassNode.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -/** - * Represents a "." node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class ClassNode extends AbstractNode -{ - private $selector; - private $name; - - public function __construct(NodeInterface $selector, string $name) - { - $this->selector = $selector; - $this->name = $name; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getName(): string - { - return $this->name; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); - } - - public function __toString(): string - { - return sprintf('%s[%s.%s]', $this->getNodeName(), $this->selector, $this->name); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/CombinedSelectorNode.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/CombinedSelectorNode.php deleted file mode 100644 index 468b02a..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/CombinedSelectorNode.php +++ /dev/null @@ -1,66 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -/** - * Represents a combined node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class CombinedSelectorNode extends AbstractNode -{ - private $selector; - private $combinator; - private $subSelector; - - public function __construct(NodeInterface $selector, string $combinator, NodeInterface $subSelector) - { - $this->selector = $selector; - $this->combinator = $combinator; - $this->subSelector = $subSelector; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getCombinator(): string - { - return $this->combinator; - } - - public function getSubSelector(): NodeInterface - { - return $this->subSelector; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); - } - - public function __toString(): string - { - $combinator = ' ' === $this->combinator ? '' : $this->combinator; - - return sprintf('%s[%s %s %s]', $this->getNodeName(), $this->selector, $combinator, $this->subSelector); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/ElementNode.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/ElementNode.php deleted file mode 100644 index 72851c0..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/ElementNode.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -/** - * Represents a "|" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class ElementNode extends AbstractNode -{ - private $namespace; - private $element; - - public function __construct(?string $namespace = null, ?string $element = null) - { - $this->namespace = $namespace; - $this->element = $element; - } - - public function getNamespace(): ?string - { - return $this->namespace; - } - - public function getElement(): ?string - { - return $this->element; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return new Specificity(0, 0, $this->element ? 1 : 0); - } - - public function __toString(): string - { - $element = $this->element ?: '*'; - - return sprintf('%s[%s]', $this->getNodeName(), $this->namespace ? $this->namespace.'|'.$element : $element); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/FunctionNode.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/FunctionNode.php deleted file mode 100644 index 66626c8..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/FunctionNode.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; - -/** - * Represents a ":()" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class FunctionNode extends AbstractNode -{ - private $selector; - private $name; - private $arguments; - - /** - * @param Token[] $arguments - */ - public function __construct(NodeInterface $selector, string $name, array $arguments = []) - { - $this->selector = $selector; - $this->name = strtolower($name); - $this->arguments = $arguments; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getName(): string - { - return $this->name; - } - - /** - * @return Token[] - */ - public function getArguments(): array - { - return $this->arguments; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); - } - - public function __toString(): string - { - $arguments = implode(', ', array_map(function (Token $token) { - return "'".$token->getValue()."'"; - }, $this->arguments)); - - return sprintf('%s[%s:%s(%s)]', $this->getNodeName(), $this->selector, $this->name, $arguments ? '['.$arguments.']' : ''); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/HashNode.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/HashNode.php deleted file mode 100644 index 366bc54..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/HashNode.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -/** - * Represents a "#" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class HashNode extends AbstractNode -{ - private $selector; - private $id; - - public function __construct(NodeInterface $selector, string $id) - { - $this->selector = $selector; - $this->id = $id; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getId(): string - { - return $this->id; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus(new Specificity(1, 0, 0)); - } - - public function __toString(): string - { - return sprintf('%s[%s#%s]', $this->getNodeName(), $this->selector, $this->id); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/NegationNode.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/NegationNode.php deleted file mode 100644 index abead95..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/NegationNode.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -/** - * Represents a ":not()" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class NegationNode extends AbstractNode -{ - private $selector; - private $subSelector; - - public function __construct(NodeInterface $selector, NodeInterface $subSelector) - { - $this->selector = $selector; - $this->subSelector = $subSelector; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getSubSelector(): NodeInterface - { - return $this->subSelector; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); - } - - public function __toString(): string - { - return sprintf('%s[%s:not(%s)]', $this->getNodeName(), $this->selector, $this->subSelector); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/NodeInterface.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/NodeInterface.php deleted file mode 100644 index 41d22b5..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/NodeInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -/** - * Interface for nodes. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -interface NodeInterface -{ - public function getNodeName(): string; - - public function getSpecificity(): Specificity; - - public function __toString(): string; -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/PseudoNode.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/PseudoNode.php deleted file mode 100644 index 0f4c835..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/PseudoNode.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -/** - * Represents a ":" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class PseudoNode extends AbstractNode -{ - private $selector; - private $identifier; - - public function __construct(NodeInterface $selector, string $identifier) - { - $this->selector = $selector; - $this->identifier = strtolower($identifier); - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getIdentifier(): string - { - return $this->identifier; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); - } - - public function __toString(): string - { - return sprintf('%s[%s:%s]', $this->getNodeName(), $this->selector, $this->identifier); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/SelectorNode.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/SelectorNode.php deleted file mode 100644 index d0988d8..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/SelectorNode.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -/** - * Represents a "(::|:)" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class SelectorNode extends AbstractNode -{ - private $tree; - private $pseudoElement; - - public function __construct(NodeInterface $tree, ?string $pseudoElement = null) - { - $this->tree = $tree; - $this->pseudoElement = $pseudoElement ? strtolower($pseudoElement) : null; - } - - public function getTree(): NodeInterface - { - return $this->tree; - } - - public function getPseudoElement(): ?string - { - return $this->pseudoElement; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->tree->getSpecificity()->plus(new Specificity(0, 0, $this->pseudoElement ? 1 : 0)); - } - - public function __toString(): string - { - return sprintf('%s[%s%s]', $this->getNodeName(), $this->tree, $this->pseudoElement ? '::'.$this->pseudoElement : ''); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/Specificity.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/Specificity.php deleted file mode 100644 index fdfdb67..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Node/Specificity.php +++ /dev/null @@ -1,73 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; - -/** - * Represents a node specificity. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @see http://www.w3.org/TR/selectors/#specificity - * - * @author Jean-François Simon - * - * @internal - */ -class Specificity -{ - public const A_FACTOR = 100; - public const B_FACTOR = 10; - public const C_FACTOR = 1; - - private $a; - private $b; - private $c; - - public function __construct(int $a, int $b, int $c) - { - $this->a = $a; - $this->b = $b; - $this->c = $c; - } - - public function plus(self $specificity): self - { - return new self($this->a + $specificity->a, $this->b + $specificity->b, $this->c + $specificity->c); - } - - public function getValue(): int - { - return $this->a * self::A_FACTOR + $this->b * self::B_FACTOR + $this->c * self::C_FACTOR; - } - - /** - * Returns -1 if the object specificity is lower than the argument, - * 0 if they are equal, and 1 if the argument is lower. - */ - public function compareTo(self $specificity): int - { - if ($this->a !== $specificity->a) { - return $this->a > $specificity->a ? 1 : -1; - } - - if ($this->b !== $specificity->b) { - return $this->b > $specificity->b ? 1 : -1; - } - - if ($this->c !== $specificity->c) { - return $this->c > $specificity->c ? 1 : -1; - } - - return 0; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php deleted file mode 100644 index 1164047..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector comment handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class CommentHandler implements HandlerInterface -{ - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - if ('/*' !== $reader->getSubstring(2)) { - return false; - } - - $offset = $reader->getOffset('*/'); - - if (false === $offset) { - $reader->moveToEnd(); - } else { - $reader->moveForward($offset + 2); - } - - return true; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php deleted file mode 100644 index 8f59a56..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector handler interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -interface HandlerInterface -{ - public function handle(Reader $reader, TokenStream $stream): bool; -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/HashHandler.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/HashHandler.php deleted file mode 100644 index a739fc7..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/HashHandler.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector comment handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class HashHandler implements HandlerInterface -{ - private $patterns; - private $escaping; - - public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) - { - $this->patterns = $patterns; - $this->escaping = $escaping; - } - - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - $match = $reader->findPattern($this->patterns->getHashPattern()); - - if (!$match) { - return false; - } - - $value = $this->escaping->escapeUnicode($match[1]); - $stream->push(new Token(Token::TYPE_HASH, $value, $reader->getPosition())); - $reader->moveForward(\strlen($match[0])); - - return true; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php deleted file mode 100644 index 56e4e23..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector comment handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class IdentifierHandler implements HandlerInterface -{ - private $patterns; - private $escaping; - - public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) - { - $this->patterns = $patterns; - $this->escaping = $escaping; - } - - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - $match = $reader->findPattern($this->patterns->getIdentifierPattern()); - - if (!$match) { - return false; - } - - $value = $this->escaping->escapeUnicode($match[0]); - $stream->push(new Token(Token::TYPE_IDENTIFIER, $value, $reader->getPosition())); - $reader->moveForward(\strlen($match[0])); - - return true; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php deleted file mode 100644 index 435f44c..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector comment handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class NumberHandler implements HandlerInterface -{ - private $patterns; - - public function __construct(TokenizerPatterns $patterns) - { - $this->patterns = $patterns; - } - - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - $match = $reader->findPattern($this->patterns->getNumberPattern()); - - if (!$match) { - return false; - } - - $stream->push(new Token(Token::TYPE_NUMBER, $match[0], $reader->getPosition())); - $reader->moveForward(\strlen($match[0])); - - return true; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/StringHandler.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/StringHandler.php deleted file mode 100644 index caf70c4..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/StringHandler.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\InternalErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\SyntaxErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector comment handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class StringHandler implements HandlerInterface -{ - private $patterns; - private $escaping; - - public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) - { - $this->patterns = $patterns; - $this->escaping = $escaping; - } - - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - $quote = $reader->getSubstring(1); - - if (!\in_array($quote, ["'", '"'])) { - return false; - } - - $reader->moveForward(1); - $match = $reader->findPattern($this->patterns->getQuotedStringPattern($quote)); - - if (!$match) { - throw new InternalErrorException(sprintf('Should have found at least an empty match at %d.', $reader->getPosition())); - } - - // check unclosed strings - if (\strlen($match[0]) === $reader->getRemainingLength()) { - throw SyntaxErrorException::unclosedString($reader->getPosition() - 1); - } - - // check quotes pairs validity - if ($quote !== $reader->getSubstring(1, \strlen($match[0]))) { - throw SyntaxErrorException::unclosedString($reader->getPosition() - 1); - } - - $string = $this->escaping->escapeUnicodeAndNewLine($match[0]); - $stream->push(new Token(Token::TYPE_STRING, $string, $reader->getPosition())); - $reader->moveForward(\strlen($match[0]) + 1); - - return true; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php deleted file mode 100644 index ad93cca..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector whitespace handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class WhitespaceHandler implements HandlerInterface -{ - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - $match = $reader->findPattern('~^[ \t\r\n\f]+~'); - - if (false === $match) { - return false; - } - - $stream->push(new Token(Token::TYPE_WHITESPACE, $match[0], $reader->getPosition())); - $reader->moveForward(\strlen($match[0])); - - return true; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Parser.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Parser.php deleted file mode 100644 index 09d44c5..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Parser.php +++ /dev/null @@ -1,353 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\SyntaxErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\Tokenizer; - -/** - * CSS selector parser. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class Parser implements ParserInterface -{ - private $tokenizer; - - public function __construct(?Tokenizer $tokenizer = null) - { - $this->tokenizer = $tokenizer ?? new Tokenizer(); - } - - /** - * {@inheritdoc} - */ - public function parse(string $source): array - { - $reader = new Reader($source); - $stream = $this->tokenizer->tokenize($reader); - - return $this->parseSelectorList($stream); - } - - /** - * Parses the arguments for ":nth-child()" and friends. - * - * @param Token[] $tokens - * - * @throws SyntaxErrorException - */ - public static function parseSeries(array $tokens): array - { - foreach ($tokens as $token) { - if ($token->isString()) { - throw SyntaxErrorException::stringAsFunctionArgument(); - } - } - - $joined = trim(implode('', array_map(function (Token $token) { - return $token->getValue(); - }, $tokens))); - - $int = function ($string) { - if (!is_numeric($string)) { - throw SyntaxErrorException::stringAsFunctionArgument(); - } - - return (int) $string; - }; - - switch (true) { - case 'odd' === $joined: - return [2, 1]; - case 'even' === $joined: - return [2, 0]; - case 'n' === $joined: - return [1, 0]; - case !str_contains($joined, 'n'): - return [0, $int($joined)]; - } - - $split = explode('n', $joined); - $first = $split[0] ?? null; - - return [ - $first ? ('-' === $first || '+' === $first ? $int($first.'1') : $int($first)) : 1, - isset($split[1]) && $split[1] ? $int($split[1]) : 0, - ]; - } - - private function parseSelectorList(TokenStream $stream): array - { - $stream->skipWhitespace(); - $selectors = []; - - while (true) { - $selectors[] = $this->parserSelectorNode($stream); - - if ($stream->getPeek()->isDelimiter([','])) { - $stream->getNext(); - $stream->skipWhitespace(); - } else { - break; - } - } - - return $selectors; - } - - private function parserSelectorNode(TokenStream $stream): Node\SelectorNode - { - [$result, $pseudoElement] = $this->parseSimpleSelector($stream); - - while (true) { - $stream->skipWhitespace(); - $peek = $stream->getPeek(); - - if ($peek->isFileEnd() || $peek->isDelimiter([','])) { - break; - } - - if (null !== $pseudoElement) { - throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector'); - } - - if ($peek->isDelimiter(['+', '>', '~'])) { - $combinator = $stream->getNext()->getValue(); - $stream->skipWhitespace(); - } else { - $combinator = ' '; - } - - [$nextSelector, $pseudoElement] = $this->parseSimpleSelector($stream); - $result = new Node\CombinedSelectorNode($result, $combinator, $nextSelector); - } - - return new Node\SelectorNode($result, $pseudoElement); - } - - /** - * Parses next simple node (hash, class, pseudo, negation). - * - * @throws SyntaxErrorException - */ - private function parseSimpleSelector(TokenStream $stream, bool $insideNegation = false): array - { - $stream->skipWhitespace(); - - $selectorStart = \count($stream->getUsed()); - $result = $this->parseElementNode($stream); - $pseudoElement = null; - - while (true) { - $peek = $stream->getPeek(); - if ($peek->isWhitespace() - || $peek->isFileEnd() - || $peek->isDelimiter([',', '+', '>', '~']) - || ($insideNegation && $peek->isDelimiter([')'])) - ) { - break; - } - - if (null !== $pseudoElement) { - throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector'); - } - - if ($peek->isHash()) { - $result = new Node\HashNode($result, $stream->getNext()->getValue()); - } elseif ($peek->isDelimiter(['.'])) { - $stream->getNext(); - $result = new Node\ClassNode($result, $stream->getNextIdentifier()); - } elseif ($peek->isDelimiter(['['])) { - $stream->getNext(); - $result = $this->parseAttributeNode($result, $stream); - } elseif ($peek->isDelimiter([':'])) { - $stream->getNext(); - - if ($stream->getPeek()->isDelimiter([':'])) { - $stream->getNext(); - $pseudoElement = $stream->getNextIdentifier(); - - continue; - } - - $identifier = $stream->getNextIdentifier(); - if (\in_array(strtolower($identifier), ['first-line', 'first-letter', 'before', 'after'])) { - // Special case: CSS 2.1 pseudo-elements can have a single ':'. - // Any new pseudo-element must have two. - $pseudoElement = $identifier; - - continue; - } - - if (!$stream->getPeek()->isDelimiter(['('])) { - $result = new Node\PseudoNode($result, $identifier); - - continue; - } - - $stream->getNext(); - $stream->skipWhitespace(); - - if ('not' === strtolower($identifier)) { - if ($insideNegation) { - throw SyntaxErrorException::nestedNot(); - } - - [$argument, $argumentPseudoElement] = $this->parseSimpleSelector($stream, true); - $next = $stream->getNext(); - - if (null !== $argumentPseudoElement) { - throw SyntaxErrorException::pseudoElementFound($argumentPseudoElement, 'inside ::not()'); - } - - if (!$next->isDelimiter([')'])) { - throw SyntaxErrorException::unexpectedToken('")"', $next); - } - - $result = new Node\NegationNode($result, $argument); - } else { - $arguments = []; - $next = null; - - while (true) { - $stream->skipWhitespace(); - $next = $stream->getNext(); - - if ($next->isIdentifier() - || $next->isString() - || $next->isNumber() - || $next->isDelimiter(['+', '-']) - ) { - $arguments[] = $next; - } elseif ($next->isDelimiter([')'])) { - break; - } else { - throw SyntaxErrorException::unexpectedToken('an argument', $next); - } - } - - if (empty($arguments)) { - throw SyntaxErrorException::unexpectedToken('at least one argument', $next); - } - - $result = new Node\FunctionNode($result, $identifier, $arguments); - } - } else { - throw SyntaxErrorException::unexpectedToken('selector', $peek); - } - } - - if (\count($stream->getUsed()) === $selectorStart) { - throw SyntaxErrorException::unexpectedToken('selector', $stream->getPeek()); - } - - return [$result, $pseudoElement]; - } - - private function parseElementNode(TokenStream $stream): Node\ElementNode - { - $peek = $stream->getPeek(); - - if ($peek->isIdentifier() || $peek->isDelimiter(['*'])) { - if ($peek->isIdentifier()) { - $namespace = $stream->getNext()->getValue(); - } else { - $stream->getNext(); - $namespace = null; - } - - if ($stream->getPeek()->isDelimiter(['|'])) { - $stream->getNext(); - $element = $stream->getNextIdentifierOrStar(); - } else { - $element = $namespace; - $namespace = null; - } - } else { - $element = $namespace = null; - } - - return new Node\ElementNode($namespace, $element); - } - - private function parseAttributeNode(Node\NodeInterface $selector, TokenStream $stream): Node\AttributeNode - { - $stream->skipWhitespace(); - $attribute = $stream->getNextIdentifierOrStar(); - - if (null === $attribute && !$stream->getPeek()->isDelimiter(['|'])) { - throw SyntaxErrorException::unexpectedToken('"|"', $stream->getPeek()); - } - - if ($stream->getPeek()->isDelimiter(['|'])) { - $stream->getNext(); - - if ($stream->getPeek()->isDelimiter(['='])) { - $namespace = null; - $stream->getNext(); - $operator = '|='; - } else { - $namespace = $attribute; - $attribute = $stream->getNextIdentifier(); - $operator = null; - } - } else { - $namespace = $operator = null; - } - - if (null === $operator) { - $stream->skipWhitespace(); - $next = $stream->getNext(); - - if ($next->isDelimiter([']'])) { - return new Node\AttributeNode($selector, $namespace, $attribute, 'exists', null); - } elseif ($next->isDelimiter(['='])) { - $operator = '='; - } elseif ($next->isDelimiter(['^', '$', '*', '~', '|', '!']) - && $stream->getPeek()->isDelimiter(['=']) - ) { - $operator = $next->getValue().'='; - $stream->getNext(); - } else { - throw SyntaxErrorException::unexpectedToken('operator', $next); - } - } - - $stream->skipWhitespace(); - $value = $stream->getNext(); - - if ($value->isNumber()) { - // if the value is a number, it's casted into a string - $value = new Token(Token::TYPE_STRING, (string) $value->getValue(), $value->getPosition()); - } - - if (!($value->isIdentifier() || $value->isString())) { - throw SyntaxErrorException::unexpectedToken('string or identifier', $value); - } - - $stream->skipWhitespace(); - $next = $stream->getNext(); - - if (!$next->isDelimiter([']'])) { - throw SyntaxErrorException::unexpectedToken('"]"', $next); - } - - return new Node\AttributeNode($selector, $namespace, $attribute, $operator, $value->getValue()); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/ParserInterface.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/ParserInterface.php deleted file mode 100644 index df808e2..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/ParserInterface.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; - -/** - * CSS selector parser interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -interface ParserInterface -{ - /** - * Parses given selector source into an array of tokens. - * - * @return SelectorNode[] - */ - public function parse(string $source): array; -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Reader.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Reader.php deleted file mode 100644 index 2bef8ae..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Reader.php +++ /dev/null @@ -1,86 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser; - -/** - * CSS selector reader. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class Reader -{ - private $source; - private $length; - private $position = 0; - - public function __construct(string $source) - { - $this->source = $source; - $this->length = \strlen($source); - } - - public function isEOF(): bool - { - return $this->position >= $this->length; - } - - public function getPosition(): int - { - return $this->position; - } - - public function getRemainingLength(): int - { - return $this->length - $this->position; - } - - public function getSubstring(int $length, int $offset = 0): string - { - return substr($this->source, $this->position + $offset, $length); - } - - public function getOffset(string $string) - { - $position = strpos($this->source, $string, $this->position); - - return false === $position ? false : $position - $this->position; - } - - /** - * @return array|false - */ - public function findPattern(string $pattern) - { - $source = substr($this->source, $this->position); - - if (preg_match($pattern, $source, $matches)) { - return $matches; - } - - return false; - } - - public function moveForward(int $length) - { - $this->position += $length; - } - - public function moveToEnd() - { - $this->position = $this->length; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php deleted file mode 100644 index a34a122..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ClassNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\ParserInterface; - -/** - * CSS selector class parser shortcut. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class ClassParser implements ParserInterface -{ - /** - * {@inheritdoc} - */ - public function parse(string $source): array - { - // Matches an optional namespace, optional element, and required class - // $source = 'test|input.ab6bd_field'; - // $matches = array (size=4) - // 0 => string 'test|input.ab6bd_field' (length=22) - // 1 => string 'test' (length=4) - // 2 => string 'input' (length=5) - // 3 => string 'ab6bd_field' (length=11) - if (preg_match('/^(?:([a-z]++)\|)?+([\w-]++|\*)?+\.([\w-]++)$/i', trim($source), $matches)) { - return [ - new SelectorNode(new ClassNode(new ElementNode($matches[1] ?: null, $matches[2] ?: null), $matches[3])), - ]; - } - - return []; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php deleted file mode 100644 index 2d07857..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\ParserInterface; - -/** - * CSS selector element parser shortcut. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class ElementParser implements ParserInterface -{ - /** - * {@inheritdoc} - */ - public function parse(string $source): array - { - // Matches an optional namespace, required element or `*` - // $source = 'testns|testel'; - // $matches = array (size=3) - // 0 => string 'testns|testel' (length=13) - // 1 => string 'testns' (length=6) - // 2 => string 'testel' (length=6) - if (preg_match('/^(?:([a-z]++)\|)?([\w-]++|\*)$/i', trim($source), $matches)) { - return [new SelectorNode(new ElementNode($matches[1] ?: null, $matches[2]))]; - } - - return []; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php deleted file mode 100644 index 68f8a87..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\ParserInterface; - -/** - * CSS selector class parser shortcut. - * - * This shortcut ensure compatibility with previous version. - * - The parser fails to parse an empty string. - * - In the previous version, an empty string matches each tags. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class EmptyStringParser implements ParserInterface -{ - /** - * {@inheritdoc} - */ - public function parse(string $source): array - { - // Matches an empty string - if ('' == $source) { - return [new SelectorNode(new ElementNode(null, '*'))]; - } - - return []; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php deleted file mode 100644 index 6f08f5f..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\HashNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\ParserInterface; - -/** - * CSS selector hash parser shortcut. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class HashParser implements ParserInterface -{ - /** - * {@inheritdoc} - */ - public function parse(string $source): array - { - // Matches an optional namespace, optional element, and required id - // $source = 'test|input#ab6bd_field'; - // $matches = array (size=4) - // 0 => string 'test|input#ab6bd_field' (length=22) - // 1 => string 'test' (length=4) - // 2 => string 'input' (length=5) - // 3 => string 'ab6bd_field' (length=11) - if (preg_match('/^(?:([a-z]++)\|)?+([\w-]++|\*)?+#([\w-]++)$/i', trim($source), $matches)) { - return [ - new SelectorNode(new HashNode(new ElementNode($matches[1] ?: null, $matches[2] ?: null), $matches[3])), - ]; - } - - return []; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Token.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Token.php deleted file mode 100644 index ed43632..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Token.php +++ /dev/null @@ -1,111 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser; - -/** - * CSS selector token. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class Token -{ - public const TYPE_FILE_END = 'eof'; - public const TYPE_DELIMITER = 'delimiter'; - public const TYPE_WHITESPACE = 'whitespace'; - public const TYPE_IDENTIFIER = 'identifier'; - public const TYPE_HASH = 'hash'; - public const TYPE_NUMBER = 'number'; - public const TYPE_STRING = 'string'; - - private $type; - private $value; - private $position; - - public function __construct(?string $type, ?string $value, ?int $position) - { - $this->type = $type; - $this->value = $value; - $this->position = $position; - } - - public function getType(): ?int - { - return $this->type; - } - - public function getValue(): ?string - { - return $this->value; - } - - public function getPosition(): ?int - { - return $this->position; - } - - public function isFileEnd(): bool - { - return self::TYPE_FILE_END === $this->type; - } - - public function isDelimiter(array $values = []): bool - { - if (self::TYPE_DELIMITER !== $this->type) { - return false; - } - - if (empty($values)) { - return true; - } - - return \in_array($this->value, $values); - } - - public function isWhitespace(): bool - { - return self::TYPE_WHITESPACE === $this->type; - } - - public function isIdentifier(): bool - { - return self::TYPE_IDENTIFIER === $this->type; - } - - public function isHash(): bool - { - return self::TYPE_HASH === $this->type; - } - - public function isNumber(): bool - { - return self::TYPE_NUMBER === $this->type; - } - - public function isString(): bool - { - return self::TYPE_STRING === $this->type; - } - - public function __toString(): string - { - if ($this->value) { - return sprintf('<%s "%s" at %s>', $this->type, $this->value, $this->position); - } - - return sprintf('<%s at %s>', $this->type, $this->position); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/TokenStream.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/TokenStream.php deleted file mode 100644 index 56c5f55..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/TokenStream.php +++ /dev/null @@ -1,167 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\InternalErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\SyntaxErrorException; - -/** - * CSS selector token stream. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class TokenStream -{ - /** - * @var Token[] - */ - private $tokens = []; - - /** - * @var Token[] - */ - private $used = []; - - /** - * @var int - */ - private $cursor = 0; - - /** - * @var Token|null - */ - private $peeked; - - /** - * @var bool - */ - private $peeking = false; - - /** - * Pushes a token. - * - * @return $this - */ - public function push(Token $token): self - { - $this->tokens[] = $token; - - return $this; - } - - /** - * Freezes stream. - * - * @return $this - */ - public function freeze(): self - { - return $this; - } - - /** - * Returns next token. - * - * @throws InternalErrorException If there is no more token - */ - public function getNext(): Token - { - if ($this->peeking) { - $this->peeking = false; - $this->used[] = $this->peeked; - - return $this->peeked; - } - - if (!isset($this->tokens[$this->cursor])) { - throw new InternalErrorException('Unexpected token stream end.'); - } - - return $this->tokens[$this->cursor++]; - } - - /** - * Returns peeked token. - */ - public function getPeek(): Token - { - if (!$this->peeking) { - $this->peeked = $this->getNext(); - $this->peeking = true; - } - - return $this->peeked; - } - - /** - * Returns used tokens. - * - * @return Token[] - */ - public function getUsed(): array - { - return $this->used; - } - - /** - * Returns next identifier token. - * - * @throws SyntaxErrorException If next token is not an identifier - */ - public function getNextIdentifier(): string - { - $next = $this->getNext(); - - if (!$next->isIdentifier()) { - throw SyntaxErrorException::unexpectedToken('identifier', $next); - } - - return $next->getValue(); - } - - /** - * Returns next identifier or null if star delimiter token is found. - * - * @throws SyntaxErrorException If next token is not an identifier or a star delimiter - */ - public function getNextIdentifierOrStar(): ?string - { - $next = $this->getNext(); - - if ($next->isIdentifier()) { - return $next->getValue(); - } - - if ($next->isDelimiter(['*'])) { - return null; - } - - throw SyntaxErrorException::unexpectedToken('identifier or "*"', $next); - } - - /** - * Skips next whitespace if any. - */ - public function skipWhitespace() - { - $peek = $this->getPeek(); - - if ($peek->isWhitespace()) { - $this->getNext(); - } - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php deleted file mode 100644 index aa5cb8a..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php +++ /dev/null @@ -1,73 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector tokenizer. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class Tokenizer -{ - /** - * @var Handler\HandlerInterface[] - */ - private $handlers; - - public function __construct() - { - $patterns = new TokenizerPatterns(); - $escaping = new TokenizerEscaping($patterns); - - $this->handlers = [ - new Handler\WhitespaceHandler(), - new Handler\IdentifierHandler($patterns, $escaping), - new Handler\HashHandler($patterns, $escaping), - new Handler\StringHandler($patterns, $escaping), - new Handler\NumberHandler($patterns), - new Handler\CommentHandler(), - ]; - } - - /** - * Tokenize selector source code. - */ - public function tokenize(Reader $reader): TokenStream - { - $stream = new TokenStream(); - - while (!$reader->isEOF()) { - foreach ($this->handlers as $handler) { - if ($handler->handle($reader, $stream)) { - continue 2; - } - } - - $stream->push(new Token(Token::TYPE_DELIMITER, $reader->getSubstring(1), $reader->getPosition())); - $reader->moveForward(1); - } - - return $stream - ->push(new Token(Token::TYPE_FILE_END, null, $reader->getPosition())) - ->freeze(); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php deleted file mode 100644 index fa319c5..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer; - -/** - * CSS selector tokenizer escaping applier. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class TokenizerEscaping -{ - private $patterns; - - public function __construct(TokenizerPatterns $patterns) - { - $this->patterns = $patterns; - } - - public function escapeUnicode(string $value): string - { - $value = $this->replaceUnicodeSequences($value); - - return preg_replace($this->patterns->getSimpleEscapePattern(), '$1', $value); - } - - public function escapeUnicodeAndNewLine(string $value): string - { - $value = preg_replace($this->patterns->getNewLineEscapePattern(), '', $value); - - return $this->escapeUnicode($value); - } - - private function replaceUnicodeSequences(string $value): string - { - return preg_replace_callback($this->patterns->getUnicodeEscapePattern(), function ($match) { - $c = hexdec($match[1]); - - if (0x80 > $c %= 0x200000) { - return \chr($c); - } - if (0x800 > $c) { - return \chr(0xC0 | $c >> 6).\chr(0x80 | $c & 0x3F); - } - if (0x10000 > $c) { - return \chr(0xE0 | $c >> 12).\chr(0x80 | $c >> 6 & 0x3F).\chr(0x80 | $c & 0x3F); - } - - return ''; - }, $value); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php deleted file mode 100644 index e714a8e..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php +++ /dev/null @@ -1,89 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer; - -/** - * CSS selector tokenizer patterns builder. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class TokenizerPatterns -{ - private $unicodeEscapePattern; - private $simpleEscapePattern; - private $newLineEscapePattern; - private $escapePattern; - private $stringEscapePattern; - private $nonAsciiPattern; - private $nmCharPattern; - private $nmStartPattern; - private $identifierPattern; - private $hashPattern; - private $numberPattern; - private $quotedStringPattern; - - public function __construct() - { - $this->unicodeEscapePattern = '\\\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?'; - $this->simpleEscapePattern = '\\\\(.)'; - $this->newLineEscapePattern = '\\\\(?:\n|\r\n|\r|\f)'; - $this->escapePattern = $this->unicodeEscapePattern.'|\\\\[^\n\r\f0-9a-f]'; - $this->stringEscapePattern = $this->newLineEscapePattern.'|'.$this->escapePattern; - $this->nonAsciiPattern = '[^\x00-\x7F]'; - $this->nmCharPattern = '[_a-z0-9-]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; - $this->nmStartPattern = '[_a-z]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; - $this->identifierPattern = '-?(?:'.$this->nmStartPattern.')(?:'.$this->nmCharPattern.')*'; - $this->hashPattern = '#((?:'.$this->nmCharPattern.')+)'; - $this->numberPattern = '[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)'; - $this->quotedStringPattern = '([^\n\r\f\\\\%s]|'.$this->stringEscapePattern.')*'; - } - - public function getNewLineEscapePattern(): string - { - return '~'.$this->newLineEscapePattern.'~'; - } - - public function getSimpleEscapePattern(): string - { - return '~'.$this->simpleEscapePattern.'~'; - } - - public function getUnicodeEscapePattern(): string - { - return '~'.$this->unicodeEscapePattern.'~i'; - } - - public function getIdentifierPattern(): string - { - return '~^'.$this->identifierPattern.'~i'; - } - - public function getHashPattern(): string - { - return '~^'.$this->hashPattern.'~i'; - } - - public function getNumberPattern(): string - { - return '~^'.$this->numberPattern.'~'; - } - - public function getQuotedStringPattern(string $quote): string - { - return '~^'.sprintf($this->quotedStringPattern, $quote).'~i'; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/README.md b/includes/classes/Dependencies/Symfony/Component/CssSelector/README.md deleted file mode 100644 index ede4a3a..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/README.md +++ /dev/null @@ -1,20 +0,0 @@ -CssSelector Component -===================== - -The CssSelector component converts CSS selectors to XPath expressions. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/css_selector.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) - -Credits -------- - -This component is a port of the Python cssselect library -[v0.7.1](https://github.com/SimonSapin/cssselect/releases/tag/v0.7.1), -which is distributed under the BSD license. diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php deleted file mode 100644 index d42ce90..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php +++ /dev/null @@ -1,83 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\CssSelectorConverter; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\ParseException; - -class CssSelectorConverterTest extends TestCase -{ - public function testCssToXPath() - { - $converter = new CssSelectorConverter(); - - $this->assertEquals('descendant-or-self::*', $converter->toXPath('')); - $this->assertEquals('descendant-or-self::h1', $converter->toXPath('h1')); - $this->assertEquals("descendant-or-self::h1[@id = 'foo']", $converter->toXPath('h1#foo')); - $this->assertEquals("descendant-or-self::h1[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]", $converter->toXPath('h1.foo')); - $this->assertEquals('descendant-or-self::foo:h1', $converter->toXPath('foo|h1')); - $this->assertEquals('descendant-or-self::h1', $converter->toXPath('H1')); - - // Test the cache layer - $converter = new CssSelectorConverter(); - $this->assertEquals('descendant-or-self::h1', $converter->toXPath('H1')); - } - - public function testCssToXPathXml() - { - $converter = new CssSelectorConverter(false); - - $this->assertEquals('descendant-or-self::H1', $converter->toXPath('H1')); - - $converter = new CssSelectorConverter(false); - // Test the cache layer - $this->assertEquals('descendant-or-self::H1', $converter->toXPath('H1')); - } - - public function testParseExceptions() - { - $this->expectException(ParseException::class); - $this->expectExceptionMessage('Expected identifier, but found.'); - $converter = new CssSelectorConverter(); - $converter->toXPath('h1:'); - } - - /** @dataProvider getCssToXPathWithoutPrefixTestData */ - public function testCssToXPathWithoutPrefix($css, $xpath) - { - $converter = new CssSelectorConverter(); - - $this->assertEquals($xpath, $converter->toXPath($css, ''), '->parse() parses an input string and returns a node'); - } - - public static function getCssToXPathWithoutPrefixTestData() - { - return [ - ['h1', 'h1'], - ['foo|h1', 'foo:h1'], - ['h1, h2, h3', 'h1 | h2 | h3'], - ['h1:nth-child(3n+1)', "*/*[(name() = 'h1') and (position() - 1 >= 0 and (position() - 1) mod 3 = 0)]"], - ['h1 > p', 'h1/p'], - ['h1#foo', "h1[@id = 'foo']"], - ['h1.foo', "h1[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"], - ['h1[class*="foo bar"]', "h1[@class and contains(@class, 'foo bar')]"], - ['h1[foo|class*="foo bar"]', "h1[@foo:class and contains(@foo:class, 'foo bar')]"], - ['h1[class]', 'h1[@class]'], - ['h1 .foo', "h1/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"], - ['h1 #foo', "h1/descendant-or-self::*/*[@id = 'foo']"], - ['h1 [class*=foo]', "h1/descendant-or-self::*/*[@class and contains(@class, 'foo')]"], - ['div>.foo', "div/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"], - ['div > .foo', "div/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTestCase.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTestCase.php deleted file mode 100644 index 99460ae..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTestCase.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\NodeInterface; - -abstract class AbstractNodeTestCase extends TestCase -{ - /** @dataProvider getToStringConversionTestData */ - public function testToStringConversion(NodeInterface $node, $representation) - { - $this->assertEquals($representation, (string) $node); - } - - /** @dataProvider getSpecificityValueTestData */ - public function testSpecificityValue(NodeInterface $node, $value) - { - $this->assertEquals($value, $node->getSpecificity()->getValue()); - } - - abstract public static function getToStringConversionTestData(); - - abstract public static function getSpecificityValueTestData(); -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php deleted file mode 100644 index 5115605..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\AttributeNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; - -class AttributeNodeTest extends AbstractNodeTestCase -{ - public static function getToStringConversionTestData() - { - return [ - [new AttributeNode(new ElementNode(), null, 'attribute', 'exists', null), 'Powered_Cache_Attribute[Element[*][attribute]]'], - [new AttributeNode(new ElementNode(), null, 'attribute', '$=', 'value'), "Powered_Cache_Attribute[Element[*][attribute $= 'value']]"], - [new AttributeNode(new ElementNode(), 'namespace', 'attribute', '$=', 'value'), "Powered_Cache_Attribute[Element[*][namespace|attribute $= 'value']]"], - ]; - } - - public static function getSpecificityValueTestData() - { - return [ - [new AttributeNode(new ElementNode(), null, 'attribute', 'exists', null), 10], - [new AttributeNode(new ElementNode(null, 'element'), null, 'attribute', 'exists', null), 11], - [new AttributeNode(new ElementNode(), null, 'attribute', '$=', 'value'), 10], - [new AttributeNode(new ElementNode(), 'namespace', 'attribute', '$=', 'value'), 10], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php deleted file mode 100644 index ae43a62..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ClassNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; - -class ClassNodeTest extends AbstractNodeTestCase -{ - public static function getToStringConversionTestData() - { - return [ - [new ClassNode(new ElementNode(), 'class'), 'Class[Element[*].class]'], - ]; - } - - public static function getSpecificityValueTestData() - { - return [ - [new ClassNode(new ElementNode(), 'class'), 10], - [new ClassNode(new ElementNode(null, 'element'), 'class'), 11], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php deleted file mode 100644 index d9b2a38..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\CombinedSelectorNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; - -class CombinedSelectorNodeTest extends AbstractNodeTestCase -{ - public static function getToStringConversionTestData() - { - return [ - [new CombinedSelectorNode(new ElementNode(), '>', new ElementNode()), 'CombinedSelector[Element[*] > Element[*]]'], - [new CombinedSelectorNode(new ElementNode(), ' ', new ElementNode()), 'CombinedSelector[Element[*] Element[*]]'], - ]; - } - - public static function getSpecificityValueTestData() - { - return [ - [new CombinedSelectorNode(new ElementNode(), '>', new ElementNode()), 0], - [new CombinedSelectorNode(new ElementNode(null, 'element'), '>', new ElementNode()), 1], - [new CombinedSelectorNode(new ElementNode(null, 'element'), '>', new ElementNode(null, 'element')), 2], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php deleted file mode 100644 index b3ef2b2..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; - -class ElementNodeTest extends AbstractNodeTestCase -{ - public static function getToStringConversionTestData() - { - return [ - [new ElementNode(), 'Element[*]'], - [new ElementNode(null, 'element'), 'Element[element]'], - [new ElementNode('namespace', 'element'), 'Element[namespace|element]'], - ]; - } - - public static function getSpecificityValueTestData() - { - return [ - [new ElementNode(), 0], - [new ElementNode(null, 'element'), 1], - [new ElementNode('namespace', 'element'), 1], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php deleted file mode 100644 index f99a66b..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\FunctionNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; - -class FunctionNodeTest extends AbstractNodeTestCase -{ - public static function getToStringConversionTestData() - { - return [ - [new FunctionNode(new ElementNode(), 'function'), 'Function[Element[*]:function()]'], - [new FunctionNode(new ElementNode(), 'function', [ - new Token(Token::TYPE_IDENTIFIER, 'value', 0), - ]), "Function[Element[*]:function(['value'])]"], - [new FunctionNode(new ElementNode(), 'function', [ - new Token(Token::TYPE_STRING, 'value1', 0), - new Token(Token::TYPE_NUMBER, 'value2', 0), - ]), "Function[Element[*]:function(['value1', 'value2'])]"], - ]; - } - - public static function getSpecificityValueTestData() - { - return [ - [new FunctionNode(new ElementNode(), 'function'), 10], - [new FunctionNode(new ElementNode(), 'function', [ - new Token(Token::TYPE_IDENTIFIER, 'value', 0), - ]), 10], - [new FunctionNode(new ElementNode(), 'function', [ - new Token(Token::TYPE_STRING, 'value1', 0), - new Token(Token::TYPE_NUMBER, 'value2', 0), - ]), 10], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php deleted file mode 100644 index d43aac1..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\HashNode; - -class HashNodeTest extends AbstractNodeTestCase -{ - public static function getToStringConversionTestData() - { - return [ - [new HashNode(new ElementNode(), 'id'), 'Hash[Element[*]#id]'], - ]; - } - - public static function getSpecificityValueTestData() - { - return [ - [new HashNode(new ElementNode(), 'id'), 100], - [new HashNode(new ElementNode(null, 'id'), 'class'), 101], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php deleted file mode 100644 index 9aafe8f..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ClassNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\NegationNode; - -class NegationNodeTest extends AbstractNodeTestCase -{ - public static function getToStringConversionTestData() - { - return [ - [new NegationNode(new ElementNode(), new ClassNode(new ElementNode(), 'class')), 'Negation[Element[*]:not(Class[Element[*].class])]'], - ]; - } - - public static function getSpecificityValueTestData() - { - return [ - [new NegationNode(new ElementNode(), new ClassNode(new ElementNode(), 'class')), 10], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php deleted file mode 100644 index cf13881..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\PseudoNode; - -class PseudoNodeTest extends AbstractNodeTestCase -{ - public static function getToStringConversionTestData() - { - return [ - [new PseudoNode(new ElementNode(), 'pseudo'), 'Pseudo[Element[*]:pseudo]'], - ]; - } - - public static function getSpecificityValueTestData() - { - return [ - [new PseudoNode(new ElementNode(), 'pseudo'), 10], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php deleted file mode 100644 index 142b104..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; - -class SelectorNodeTest extends AbstractNodeTestCase -{ - public static function getToStringConversionTestData() - { - return [ - [new SelectorNode(new ElementNode()), 'Selector[Element[*]]'], - [new SelectorNode(new ElementNode(), 'pseudo'), 'Selector[Element[*]::pseudo]'], - ]; - } - - public static function getSpecificityValueTestData() - { - return [ - [new SelectorNode(new ElementNode()), 0], - [new SelectorNode(new ElementNode(), 'pseudo'), 1], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php deleted file mode 100644 index 790f8c1..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Node; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\Specificity; - -class SpecificityTest extends TestCase -{ - /** @dataProvider getValueTestData */ - public function testValue(Specificity $specificity, $value) - { - $this->assertEquals($value, $specificity->getValue()); - } - - /** @dataProvider getValueTestData */ - public function testPlusValue(Specificity $specificity, $value) - { - $this->assertEquals($value + 123, $specificity->plus(new Specificity(1, 2, 3))->getValue()); - } - - public static function getValueTestData() - { - return [ - [new Specificity(0, 0, 0), 0], - [new Specificity(0, 0, 2), 2], - [new Specificity(0, 3, 0), 30], - [new Specificity(4, 0, 0), 400], - [new Specificity(4, 3, 2), 432], - ]; - } - - /** @dataProvider getCompareTestData */ - public function testCompareTo(Specificity $a, Specificity $b, $result) - { - $this->assertEquals($result, $a->compareTo($b)); - } - - public static function getCompareTestData() - { - return [ - [new Specificity(0, 0, 0), new Specificity(0, 0, 0), 0], - [new Specificity(0, 0, 1), new Specificity(0, 0, 1), 0], - [new Specificity(0, 0, 2), new Specificity(0, 0, 1), 1], - [new Specificity(0, 0, 2), new Specificity(0, 0, 3), -1], - [new Specificity(0, 4, 0), new Specificity(0, 4, 0), 0], - [new Specificity(0, 6, 0), new Specificity(0, 5, 11), 1], - [new Specificity(0, 7, 0), new Specificity(0, 8, 0), -1], - [new Specificity(9, 0, 0), new Specificity(9, 0, 0), 0], - [new Specificity(11, 0, 0), new Specificity(10, 11, 0), 1], - [new Specificity(12, 11, 0), new Specificity(13, 0, 0), -1], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTestCase.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTestCase.php deleted file mode 100644 index b46f2f7..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTestCase.php +++ /dev/null @@ -1,70 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * @author Jean-François Simon - */ -abstract class AbstractHandlerTestCase extends TestCase -{ - /** @dataProvider getHandleValueTestData */ - public function testHandleValue($value, Token $expectedToken, $remainingContent) - { - $reader = new Reader($value); - $stream = new TokenStream(); - - $this->assertTrue($this->generateHandler()->handle($reader, $stream)); - $this->assertEquals($expectedToken, $stream->getNext()); - $this->assertRemainingContent($reader, $remainingContent); - } - - /** @dataProvider getDontHandleValueTestData */ - public function testDontHandleValue($value) - { - $reader = new Reader($value); - $stream = new TokenStream(); - - $this->assertFalse($this->generateHandler()->handle($reader, $stream)); - $this->assertStreamEmpty($stream); - $this->assertRemainingContent($reader, $value); - } - - abstract public static function getHandleValueTestData(); - - abstract public static function getDontHandleValueTestData(); - - abstract protected function generateHandler(); - - protected function assertStreamEmpty(TokenStream $stream) - { - $property = new \ReflectionProperty($stream, 'tokens'); - $property->setAccessible(true); - - $this->assertEquals([], $property->getValue($stream)); - } - - protected function assertRemainingContent(Reader $reader, $remainingContent) - { - if ('' === $remainingContent) { - $this->assertEquals(0, $reader->getRemainingLength()); - $this->assertTrue($reader->isEOF()); - } else { - $this->assertEquals(\strlen($remainingContent), $reader->getRemainingLength()); - $this->assertEquals(0, $reader->getOffset($remainingContent)); - } - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php deleted file mode 100644 index 459d8de..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\CommentHandler; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; - -class CommentHandlerTest extends AbstractHandlerTestCase -{ - /** @dataProvider getHandleValueTestData */ - public function testHandleValue($value, Token $unusedArgument, $remainingContent) - { - $reader = new Reader($value); - $stream = new TokenStream(); - - $this->assertTrue($this->generateHandler()->handle($reader, $stream)); - // comments are ignored (not pushed as token in stream) - $this->assertStreamEmpty($stream); - $this->assertRemainingContent($reader, $remainingContent); - } - - public static function getHandleValueTestData() - { - return [ - // 2nd argument only exists for inherited method compatibility - ['/* comment */', new Token(null, null, null), ''], - ['/* comment */foo', new Token(null, null, null), 'foo'], - ]; - } - - public static function getDontHandleValueTestData() - { - return [ - ['>'], - ['+'], - [' '], - ]; - } - - protected function generateHandler() - { - return new CommentHandler(); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php deleted file mode 100644 index a96c861..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\HashHandler; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; - -class HashHandlerTest extends AbstractHandlerTestCase -{ - public static function getHandleValueTestData() - { - return [ - ['#id', new Token(Token::TYPE_HASH, 'id', 0), ''], - ['#123', new Token(Token::TYPE_HASH, '123', 0), ''], - - ['#id.class', new Token(Token::TYPE_HASH, 'id', 0), '.class'], - ['#id element', new Token(Token::TYPE_HASH, 'id', 0), ' element'], - ]; - } - - public static function getDontHandleValueTestData() - { - return [ - ['id'], - ['123'], - ['<'], - ['<'], - ['#'], - ]; - } - - protected function generateHandler() - { - $patterns = new TokenizerPatterns(); - - return new HashHandler($patterns, new TokenizerEscaping($patterns)); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php deleted file mode 100644 index 1cb9ffe..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\IdentifierHandler; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; - -class IdentifierHandlerTest extends AbstractHandlerTestCase -{ - public static function getHandleValueTestData() - { - return [ - ['foo', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), ''], - ['foo|bar', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '|bar'], - ['foo.class', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '.class'], - ['foo[attr]', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '[attr]'], - ['foo bar', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), ' bar'], - ]; - } - - public static function getDontHandleValueTestData() - { - return [ - ['>'], - ['+'], - [' '], - ['*|foo'], - ['/* comment */'], - ]; - } - - protected function generateHandler() - { - $patterns = new TokenizerPatterns(); - - return new IdentifierHandler($patterns, new TokenizerEscaping($patterns)); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php deleted file mode 100644 index e40b86f..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\NumberHandler; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; - -class NumberHandlerTest extends AbstractHandlerTestCase -{ - public static function getHandleValueTestData() - { - return [ - ['12', new Token(Token::TYPE_NUMBER, '12', 0), ''], - ['12.34', new Token(Token::TYPE_NUMBER, '12.34', 0), ''], - ['+12.34', new Token(Token::TYPE_NUMBER, '+12.34', 0), ''], - ['-12.34', new Token(Token::TYPE_NUMBER, '-12.34', 0), ''], - - ['12 arg', new Token(Token::TYPE_NUMBER, '12', 0), ' arg'], - ['12]', new Token(Token::TYPE_NUMBER, '12', 0), ']'], - ]; - } - - public static function getDontHandleValueTestData() - { - return [ - ['hello'], - ['>'], - ['+'], - [' '], - ['/* comment */'], - ]; - } - - protected function generateHandler() - { - $patterns = new TokenizerPatterns(); - - return new NumberHandler($patterns); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php deleted file mode 100644 index d00233c..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\StringHandler; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; - -class StringHandlerTest extends AbstractHandlerTestCase -{ - public static function getHandleValueTestData() - { - return [ - ['"hello"', new Token(Token::TYPE_STRING, 'hello', 1), ''], - ['"1"', new Token(Token::TYPE_STRING, '1', 1), ''], - ['" "', new Token(Token::TYPE_STRING, ' ', 1), ''], - ['""', new Token(Token::TYPE_STRING, '', 1), ''], - ["'hello'", new Token(Token::TYPE_STRING, 'hello', 1), ''], - - ["'foo'bar", new Token(Token::TYPE_STRING, 'foo', 1), 'bar'], - ]; - } - - public static function getDontHandleValueTestData() - { - return [ - ['hello'], - ['>'], - ['1'], - [' '], - ]; - } - - protected function generateHandler() - { - $patterns = new TokenizerPatterns(); - - return new StringHandler($patterns, new TokenizerEscaping($patterns)); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php deleted file mode 100644 index 1cd3e9d..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Handler; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Handler\WhitespaceHandler; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; - -class WhitespaceHandlerTest extends AbstractHandlerTestCase -{ - public static function getHandleValueTestData() - { - return [ - [' ', new Token(Token::TYPE_WHITESPACE, ' ', 0), ''], - ["\n", new Token(Token::TYPE_WHITESPACE, "\n", 0), ''], - ["\t", new Token(Token::TYPE_WHITESPACE, "\t", 0), ''], - - [' foo', new Token(Token::TYPE_WHITESPACE, ' ', 0), 'foo'], - [' .foo', new Token(Token::TYPE_WHITESPACE, ' ', 0), '.foo'], - ]; - } - - public static function getDontHandleValueTestData() - { - return [ - ['>'], - ['1'], - ['a'], - ]; - } - - protected function generateHandler() - { - return new WhitespaceHandler(); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ParserTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ParserTest.php deleted file mode 100644 index a9ef9d6..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ParserTest.php +++ /dev/null @@ -1,263 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\SyntaxErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\FunctionNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Parser; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; - -class ParserTest extends TestCase -{ - /** @dataProvider getParserTestData */ - public function testParser($source, $representation) - { - $parser = new Parser(); - - $this->assertEquals($representation, array_map(function (SelectorNode $node) { - return (string) $node->getTree(); - }, $parser->parse($source))); - } - - /** @dataProvider getParserExceptionTestData */ - public function testParserException($source, $message) - { - $parser = new Parser(); - - try { - $parser->parse($source); - $this->fail('Parser should throw a SyntaxErrorException.'); - } catch (SyntaxErrorException $e) { - $this->assertEquals($message, $e->getMessage()); - } - } - - /** @dataProvider getPseudoElementsTestData */ - public function testPseudoElements($source, $element, $pseudo) - { - $parser = new Parser(); - $selectors = $parser->parse($source); - $this->assertCount(1, $selectors); - - /** @var SelectorNode $selector */ - $selector = $selectors[0]; - $this->assertEquals($element, (string) $selector->getTree()); - $this->assertEquals($pseudo, (string) $selector->getPseudoElement()); - } - - /** @dataProvider getSpecificityTestData */ - public function testSpecificity($source, $value) - { - $parser = new Parser(); - $selectors = $parser->parse($source); - $this->assertCount(1, $selectors); - - /** @var SelectorNode $selector */ - $selector = $selectors[0]; - $this->assertEquals($value, $selector->getSpecificity()->getValue()); - } - - /** @dataProvider getParseSeriesTestData */ - public function testParseSeries($series, $a, $b) - { - $parser = new Parser(); - $selectors = $parser->parse(sprintf(':nth-child(%s)', $series)); - $this->assertCount(1, $selectors); - - /** @var FunctionNode $function */ - $function = $selectors[0]->getTree(); - $this->assertEquals([$a, $b], Parser::parseSeries($function->getArguments())); - } - - /** @dataProvider getParseSeriesExceptionTestData */ - public function testParseSeriesException($series) - { - $parser = new Parser(); - $selectors = $parser->parse(sprintf(':nth-child(%s)', $series)); - $this->assertCount(1, $selectors); - - /** @var FunctionNode $function */ - $function = $selectors[0]->getTree(); - $this->expectException(SyntaxErrorException::class); - Parser::parseSeries($function->getArguments()); - } - - public static function getParserTestData() - { - return [ - ['*', ['Element[*]']], - ['*|*', ['Element[*]']], - ['*|foo', ['Element[foo]']], - ['foo|*', ['Element[foo|*]']], - ['foo|bar', ['Element[foo|bar]']], - ['#foo#bar', ['Hash[Hash[Element[*]#foo]#bar]']], - ['div>.foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']], - ['div> .foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']], - ['div >.foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']], - ['div > .foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']], - ["div \n> \t \t .foo", ['CombinedSelector[Element[div] > Class[Element[*].foo]]']], - ['td.foo,.bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']], - ['td.foo, .bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']], - ["td.foo\t\r\n\f ,\t\r\n\f .bar", ['Class[Element[td].foo]', 'Class[Element[*].bar]']], - ['td.foo,.bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']], - ['td.foo, .bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']], - ["td.foo\t\r\n\f ,\t\r\n\f .bar", ['Class[Element[td].foo]', 'Class[Element[*].bar]']], - ['div, td.foo, div.bar span', ['Element[div]', 'Class[Element[td].foo]', 'CombinedSelector[Class[Element[div].bar] Element[span]]']], - ['div > p', ['CombinedSelector[Element[div] > Element[p]]']], - ['td:first', ['Pseudo[Element[td]:first]']], - ['td :first', ['CombinedSelector[Element[td] Pseudo[Element[*]:first]]']], - ['a[name]', ['Powered_Cache_Attribute[Element[a][name]]']], - ["a[ name\t]", ['Powered_Cache_Attribute[Element[a][name]]']], - ['a [name]', ['CombinedSelector[Element[a] Powered_Cache_Attribute[Element[*][name]]]']], - ['[name="foo"]', ["Powered_Cache_Attribute[Element[*][name = 'foo']]"]], - ["[name='foo[1]']", ["Powered_Cache_Attribute[Element[*][name = 'foo[1]']]"]], - ["[name='foo[0][bar]']", ["Powered_Cache_Attribute[Element[*][name = 'foo[0][bar]']]"]], - ['a[rel="include"]', ["Attribute[Element[a][rel = 'include']]"]], - ['a[rel = include]', ["Attribute[Element[a][rel = 'include']]"]], - ["a[hreflang |= 'en']", ["Powered_Cache_Attribute[Element[a][hreflang |= 'en']]"]], - ['a[hreflang|=en]', ["Powered_Cache_Attribute[Element[a][hreflang |= 'en']]"]], - ['div:nth-child(10)', ["Function[Element[div]:nth-child(['10'])]"]], - [':nth-child(2n+2)', ["Function[Element[*]:nth-child(['2', 'n', '+2'])]"]], - ['div:nth-of-type(10)', ["Function[Element[div]:nth-of-type(['10'])]"]], - ['div div:nth-of-type(10) .aclass', ["CombinedSelector[CombinedSelector[Element[div] Function[Element[div]:nth-of-type(['10'])]] Class[Element[*].aclass]]"]], - ['label:only', ['Pseudo[Element[label]:only]']], - ['a:lang(fr)', ["Function[Element[a]:lang(['fr'])]"]], - ['div:contains("foo")', ["Function[Element[div]:contains(['foo'])]"]], - ['div#foobar', ['Hash[Element[div]#foobar]']], - ['div:not(div.foo)', ['Negation[Element[div]:not(Class[Element[div].foo])]']], - ['td ~ th', ['CombinedSelector[Element[td] ~ Element[th]]']], - ['.foo[data-bar][data-baz=0]', ["Powered_Cache_Attribute[Attribute[Class[Element[*].foo][data-bar]][data-baz = '0']]"]], - ['div#foo\.bar', ['Hash[Element[div]#foo.bar]']], - ['div.w-1\/3', ['Class[Element[div].w-1/3]']], - ['#test\:colon', ['Hash[Element[*]#test:colon]']], - [".a\xc1b", ["Class[Element[*].a\xc1b]"]], - // unicode escape: \22 == " - ['*[aval="\'\22\'"]', ['Powered_Cache_Attribute[Element[*][aval = \'\'"\'\']]']], - ['*[aval="\'\22 2\'"]', ['Powered_Cache_Attribute[Element[*][aval = \'\'"2\'\']]']], - // unicode escape: \20 == (space) - ['*[aval="\'\20 \'"]', ['Powered_Cache_Attribute[Element[*][aval = \'\' \'\']]']], - ["*[aval=\"'\\20\r\n '\"]", ['Powered_Cache_Attribute[Element[*][aval = \'\' \'\']]']], - ]; - } - - public static function getParserExceptionTestData() - { - return [ - ['attributes(href)/html/body/a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '(', 10))->getMessage()], - ['attributes(href)', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '(', 10))->getMessage()], - ['html/body/a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '/', 4))->getMessage()], - [' ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 1))->getMessage()], - ['div, ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 5))->getMessage()], - [' , div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, ',', 1))->getMessage()], - ['p, , div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, ',', 3))->getMessage()], - ['div > ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 6))->getMessage()], - [' > div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '>', 2))->getMessage()], - ['foo|#bar', SyntaxErrorException::unexpectedToken('identifier or "*"', new Token(Token::TYPE_HASH, 'bar', 4))->getMessage()], - ['#.foo', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '#', 0))->getMessage()], - ['.#foo', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_HASH, 'foo', 1))->getMessage()], - [':#foo', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_HASH, 'foo', 1))->getMessage()], - ['[*]', SyntaxErrorException::unexpectedToken('"|"', new Token(Token::TYPE_DELIMITER, ']', 2))->getMessage()], - ['[foo|]', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_DELIMITER, ']', 5))->getMessage()], - ['[#]', SyntaxErrorException::unexpectedToken('identifier or "*"', new Token(Token::TYPE_DELIMITER, '#', 1))->getMessage()], - ['[foo=#]', SyntaxErrorException::unexpectedToken('string or identifier', new Token(Token::TYPE_DELIMITER, '#', 5))->getMessage()], - [':nth-child()', SyntaxErrorException::unexpectedToken('at least one argument', new Token(Token::TYPE_DELIMITER, ')', 11))->getMessage()], - ['[href]a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_IDENTIFIER, 'a', 6))->getMessage()], - ['[rel:stylesheet]', SyntaxErrorException::unexpectedToken('operator', new Token(Token::TYPE_DELIMITER, ':', 4))->getMessage()], - ['[rel=stylesheet', SyntaxErrorException::unexpectedToken('"]"', new Token(Token::TYPE_FILE_END, '', 15))->getMessage()], - [':lang(fr', SyntaxErrorException::unexpectedToken('an argument', new Token(Token::TYPE_FILE_END, '', 8))->getMessage()], - [':contains("foo', SyntaxErrorException::unclosedString(10)->getMessage()], - ['foo!', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '!', 3))->getMessage()], - ]; - } - - public static function getPseudoElementsTestData() - { - return [ - ['foo', 'Element[foo]', ''], - ['*', 'Element[*]', ''], - [':empty', 'Pseudo[Element[*]:empty]', ''], - [':BEfore', 'Element[*]', 'before'], - [':aftER', 'Element[*]', 'after'], - [':First-Line', 'Element[*]', 'first-line'], - [':First-Letter', 'Element[*]', 'first-letter'], - ['::befoRE', 'Element[*]', 'before'], - ['::AFter', 'Element[*]', 'after'], - ['::firsT-linE', 'Element[*]', 'first-line'], - ['::firsT-letteR', 'Element[*]', 'first-letter'], - ['::Selection', 'Element[*]', 'selection'], - ['foo:after', 'Element[foo]', 'after'], - ['foo::selection', 'Element[foo]', 'selection'], - ['lorem#ipsum ~ a#b.c[href]:empty::selection', 'CombinedSelector[Hash[Element[lorem]#ipsum] ~ Pseudo[Powered_Cache_Attribute[Class[Hash[Element[a]#b].c][href]]:empty]]', 'selection'], - ['video::-webkit-media-controls', 'Element[video]', '-webkit-media-controls'], - ]; - } - - public static function getSpecificityTestData() - { - return [ - ['*', 0], - [' foo', 1], - [':empty ', 10], - [':before', 1], - ['*:before', 1], - [':nth-child(2)', 10], - ['.bar', 10], - ['[baz]', 10], - ['[baz="4"]', 10], - ['[baz^="4"]', 10], - ['#lipsum', 100], - [':not(*)', 0], - [':not(foo)', 1], - [':not(.foo)', 10], - [':not([foo])', 10], - [':not(:empty)', 10], - [':not(#foo)', 100], - ['foo:empty', 11], - ['foo:before', 2], - ['foo::before', 2], - ['foo:empty::before', 12], - ['#lorem + foo#ipsum:first-child > bar:first-line', 213], - ]; - } - - public static function getParseSeriesTestData() - { - return [ - ['1n+3', 1, 3], - ['1n +3', 1, 3], - ['1n + 3', 1, 3], - ['1n+ 3', 1, 3], - ['1n-3', 1, -3], - ['1n -3', 1, -3], - ['1n - 3', 1, -3], - ['1n- 3', 1, -3], - ['n-5', 1, -5], - ['odd', 2, 1], - ['even', 2, 0], - ['3n', 3, 0], - ['n', 1, 0], - ['+n', 1, 0], - ['-n', -1, 0], - ['5', 0, 5], - ]; - } - - public static function getParseSeriesExceptionTestData() - { - return [ - ['foo'], - ['n+'], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php deleted file mode 100644 index b160113..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php +++ /dev/null @@ -1,102 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Reader; - -class ReaderTest extends TestCase -{ - public function testIsEOF() - { - $reader = new Reader(''); - $this->assertTrue($reader->isEOF()); - - $reader = new Reader('hello'); - $this->assertFalse($reader->isEOF()); - - $this->assignPosition($reader, 2); - $this->assertFalse($reader->isEOF()); - - $this->assignPosition($reader, 5); - $this->assertTrue($reader->isEOF()); - } - - public function testGetRemainingLength() - { - $reader = new Reader('hello'); - $this->assertEquals(5, $reader->getRemainingLength()); - - $this->assignPosition($reader, 2); - $this->assertEquals(3, $reader->getRemainingLength()); - - $this->assignPosition($reader, 5); - $this->assertEquals(0, $reader->getRemainingLength()); - } - - public function testGetSubstring() - { - $reader = new Reader('hello'); - $this->assertEquals('he', $reader->getSubstring(2)); - $this->assertEquals('el', $reader->getSubstring(2, 1)); - - $this->assignPosition($reader, 2); - $this->assertEquals('ll', $reader->getSubstring(2)); - $this->assertEquals('lo', $reader->getSubstring(2, 1)); - } - - public function testGetOffset() - { - $reader = new Reader('hello'); - $this->assertEquals(2, $reader->getOffset('ll')); - $this->assertFalse($reader->getOffset('w')); - - $this->assignPosition($reader, 2); - $this->assertEquals(0, $reader->getOffset('ll')); - $this->assertFalse($reader->getOffset('he')); - } - - public function testFindPattern() - { - $reader = new Reader('hello'); - - $this->assertFalse($reader->findPattern('/world/')); - $this->assertEquals(['hello', 'h'], $reader->findPattern('/^([a-z]).*/')); - - $this->assignPosition($reader, 2); - $this->assertFalse($reader->findPattern('/^h.*/')); - $this->assertEquals(['llo'], $reader->findPattern('/^llo$/')); - } - - public function testMoveForward() - { - $reader = new Reader('hello'); - $this->assertEquals(0, $reader->getPosition()); - - $reader->moveForward(2); - $this->assertEquals(2, $reader->getPosition()); - } - - public function testToEnd() - { - $reader = new Reader('hello'); - $reader->moveToEnd(); - $this->assertTrue($reader->isEOF()); - } - - private function assignPosition(Reader $reader, int $value) - { - $position = new \ReflectionProperty($reader, 'position'); - $position->setAccessible(true); - $position->setValue($reader, $value); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php deleted file mode 100644 index 188d29f..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Shortcut; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\ClassParser; - -/** - * @author Jean-François Simon - */ -class ClassParserTest extends TestCase -{ - /** @dataProvider getParseTestData */ - public function testParse($source, $representation) - { - $parser = new ClassParser(); - $selectors = $parser->parse($source); - $this->assertCount(1, $selectors); - - /** @var SelectorNode $selector */ - $selector = $selectors[0]; - $this->assertEquals($representation, (string) $selector->getTree()); - } - - public static function getParseTestData() - { - return [ - ['.testclass', 'Class[Element[*].testclass]'], - ['testel.testclass', 'Class[Element[testel].testclass]'], - ['testns|.testclass', 'Class[Element[testns|*].testclass]'], - ['testns|*.testclass', 'Class[Element[testns|*].testclass]'], - ['testns|testel.testclass', 'Class[Element[testns|testel].testclass]'], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php deleted file mode 100644 index 58540ea..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Shortcut; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\ElementParser; - -/** - * @author Jean-François Simon - */ -class ElementParserTest extends TestCase -{ - /** @dataProvider getParseTestData */ - public function testParse($source, $representation) - { - $parser = new ElementParser(); - $selectors = $parser->parse($source); - $this->assertCount(1, $selectors); - - /** @var SelectorNode $selector */ - $selector = $selectors[0]; - $this->assertEquals($representation, (string) $selector->getTree()); - } - - public static function getParseTestData() - { - return [ - ['*', 'Element[*]'], - ['testel', 'Element[testel]'], - ['testns|*', 'Element[testns|*]'], - ['testns|testel', 'Element[testns|testel]'], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php deleted file mode 100644 index b6540ff..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Shortcut; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser; - -/** - * @author Jean-François Simon - */ -class EmptyStringParserTest extends TestCase -{ - public function testParse() - { - $parser = new EmptyStringParser(); - $selectors = $parser->parse(''); - $this->assertCount(1, $selectors); - - /** @var SelectorNode $selector */ - $selector = $selectors[0]; - $this->assertEquals('Element[*]', (string) $selector->getTree()); - - $selectors = $parser->parse('this will produce an empty array'); - $this->assertCount(0, $selectors); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php deleted file mode 100644 index 9a92ca4..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser\Shortcut; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Shortcut\HashParser; - -/** - * @author Jean-François Simon - */ -class HashParserTest extends TestCase -{ - /** @dataProvider getParseTestData */ - public function testParse($source, $representation) - { - $parser = new HashParser(); - $selectors = $parser->parse($source); - $this->assertCount(1, $selectors); - - /** @var SelectorNode $selector */ - $selector = $selectors[0]; - $this->assertEquals($representation, (string) $selector->getTree()); - } - - public static function getParseTestData() - { - return [ - ['#testid', 'Hash[Element[*]#testid]'], - ['testel#testid', 'Hash[Element[testel]#testid]'], - ['testns|#testid', 'Hash[Element[testns|*]#testid]'], - ['testns|*#testid', 'Hash[Element[testns|*]#testid]'], - ['testns|testel#testid', 'Hash[Element[testns|testel]#testid]'], - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php deleted file mode 100644 index ec7f7f5..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\Parser; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\SyntaxErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Token; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\TokenStream; - -class TokenStreamTest extends TestCase -{ - public function testGetNext() - { - $stream = new TokenStream(); - $stream->push($t1 = new Token(Token::TYPE_IDENTIFIER, 'h1', 0)); - $stream->push($t2 = new Token(Token::TYPE_DELIMITER, '.', 2)); - $stream->push($t3 = new Token(Token::TYPE_IDENTIFIER, 'title', 3)); - - $this->assertSame($t1, $stream->getNext()); - $this->assertSame($t2, $stream->getNext()); - $this->assertSame($t3, $stream->getNext()); - } - - public function testGetPeek() - { - $stream = new TokenStream(); - $stream->push($t1 = new Token(Token::TYPE_IDENTIFIER, 'h1', 0)); - $stream->push($t2 = new Token(Token::TYPE_DELIMITER, '.', 2)); - $stream->push($t3 = new Token(Token::TYPE_IDENTIFIER, 'title', 3)); - - $this->assertSame($t1, $stream->getPeek()); - $this->assertSame($t1, $stream->getNext()); - $this->assertSame($t2, $stream->getPeek()); - $this->assertSame($t2, $stream->getPeek()); - $this->assertSame($t2, $stream->getNext()); - } - - public function testGetNextIdentifier() - { - $stream = new TokenStream(); - $stream->push(new Token(Token::TYPE_IDENTIFIER, 'h1', 0)); - - $this->assertEquals('h1', $stream->getNextIdentifier()); - } - - public function testFailToGetNextIdentifier() - { - $this->expectException(SyntaxErrorException::class); - - $stream = new TokenStream(); - $stream->push(new Token(Token::TYPE_DELIMITER, '.', 2)); - $stream->getNextIdentifier(); - } - - public function testGetNextIdentifierOrStar() - { - $stream = new TokenStream(); - - $stream->push(new Token(Token::TYPE_IDENTIFIER, 'h1', 0)); - $this->assertEquals('h1', $stream->getNextIdentifierOrStar()); - - $stream->push(new Token(Token::TYPE_DELIMITER, '*', 0)); - $this->assertNull($stream->getNextIdentifierOrStar()); - } - - public function testFailToGetNextIdentifierOrStar() - { - $this->expectException(SyntaxErrorException::class); - - $stream = new TokenStream(); - $stream->push(new Token(Token::TYPE_DELIMITER, '.', 2)); - $stream->getNextIdentifierOrStar(); - } - - public function testSkipWhitespace() - { - $stream = new TokenStream(); - $stream->push($t1 = new Token(Token::TYPE_IDENTIFIER, 'h1', 0)); - $stream->push($t2 = new Token(Token::TYPE_WHITESPACE, ' ', 2)); - $stream->push($t3 = new Token(Token::TYPE_IDENTIFIER, 'h1', 3)); - - $stream->skipWhitespace(); - $this->assertSame($t1, $stream->getNext()); - - $stream->skipWhitespace(); - $this->assertSame($t3, $stream->getNext()); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html deleted file mode 100644 index 1147bf3..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - -
- - - - link -
    -
  1. content
  2. -
  3. -
    -
    -
  4. -
  5. -
  6. -
  7. -
  8. -
  9. -
-

- hi there - guy - - - - - - - -

- - -
-

-
    -
- - - - -
-
-
- -
- - diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml deleted file mode 100644 index 14f8dbe..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml +++ /dev/null @@ -1,11 +0,0 @@ - - a - b - c - d - e - f - - - - diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html deleted file mode 100644 index 15d1ad3..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html +++ /dev/null @@ -1,308 +0,0 @@ - - - - - - -
-
-

As You Like It

-
- by William Shakespeare -
-
-

ACT I, SCENE III. A room in the palace.

-
-
Enter CELIA and ROSALIND
-
-
CELIA
-
-
Why, cousin! why, Rosalind! Cupid have mercy! not a word?
-
-
ROSALIND
-
-
Not one to throw at a dog.
-
-
CELIA
-
-
No, thy words are too precious to be cast away upon
-
curs; throw some of them at me; come, lame me with reasons.
-
-
ROSALIND
-
CELIA
-
-
But is all this for your father?
-
-
-
Then there were two cousins laid up; when the one
-
should be lamed with reasons and the other mad
-
without any.
-
-
ROSALIND
-
-
No, some of it is for my child's father. O, how
-
full of briers is this working-day world!
-
-
CELIA
-
-
They are but burs, cousin, thrown upon thee in
-
holiday foolery: if we walk not in the trodden
-
paths our very petticoats will catch them.
-
-
ROSALIND
-
-
I could shake them off my coat: these burs are in my heart.
-
-
CELIA
-
-
Hem them away.
-
-
ROSALIND
-
-
I would try, if I could cry 'hem' and have him.
-
-
CELIA
-
-
Come, come, wrestle with thy affections.
-
-
ROSALIND
-
-
O, they take the part of a better wrestler than myself!
-
-
CELIA
-
-
O, a good wish upon you! you will try in time, in
-
despite of a fall. But, turning these jests out of
-
service, let us talk in good earnest: is it
-
possible, on such a sudden, you should fall into so
-
strong a liking with old Sir Rowland's youngest son?
-
-
ROSALIND
-
-
The duke my father loved his father dearly.
-
-
CELIA
-
-
Doth it therefore ensue that you should love his son
-
dearly? By this kind of chase, I should hate him,
-
for my father hated his father dearly; yet I hate
-
not Orlando.
-
-
ROSALIND
-
-
No, faith, hate him not, for my sake.
-
-
CELIA
-
-
Why should I not? doth he not deserve well?
-
-
ROSALIND
-
-
Let me love him for that, and do you love him
-
because I do. Look, here comes the duke.
-
-
CELIA
-
-
With his eyes full of anger.
-
Enter DUKE FREDERICK, with Lords
-
-
DUKE FREDERICK
-
-
Mistress, dispatch you with your safest haste
-
And get you from our court.
-
-
ROSALIND
-
-
Me, uncle?
-
-
DUKE FREDERICK
-
-
You, cousin
-
Within these ten days if that thou be'st found
-
So near our public court as twenty miles,
-
Thou diest for it.
-
-
ROSALIND
-
-
I do beseech your grace,
-
Let me the knowledge of my fault bear with me:
-
If with myself I hold intelligence
-
Or have acquaintance with mine own desires,
-
If that I do not dream or be not frantic,--
-
As I do trust I am not--then, dear uncle,
-
Never so much as in a thought unborn
-
Did I offend your highness.
-
-
DUKE FREDERICK
-
-
Thus do all traitors:
-
If their purgation did consist in words,
-
They are as innocent as grace itself:
-
Let it suffice thee that I trust thee not.
-
-
ROSALIND
-
-
Yet your mistrust cannot make me a traitor:
-
Tell me whereon the likelihood depends.
-
-
DUKE FREDERICK
-
-
Thou art thy father's daughter; there's enough.
-
-
ROSALIND
-
-
So was I when your highness took his dukedom;
-
So was I when your highness banish'd him:
-
Treason is not inherited, my lord;
-
Or, if we did derive it from our friends,
-
What's that to me? my father was no traitor:
-
Then, good my liege, mistake me not so much
-
To think my poverty is treacherous.
-
-
CELIA
-
-
Dear sovereign, hear me speak.
-
-
DUKE FREDERICK
-
-
Ay, Celia; we stay'd her for your sake,
-
Else had she with her father ranged along.
-
-
CELIA
-
-
I did not then entreat to have her stay;
-
It was your pleasure and your own remorse:
-
I was too young that time to value her;
-
But now I know her: if she be a traitor,
-
Why so am I; we still have slept together,
-
Rose at an instant, learn'd, play'd, eat together,
-
And wheresoever we went, like Juno's swans,
-
Still we went coupled and inseparable.
-
-
DUKE FREDERICK
-
-
She is too subtle for thee; and her smoothness,
-
Her very silence and her patience
-
Speak to the people, and they pity her.
-
Thou art a fool: she robs thee of thy name;
-
And thou wilt show more bright and seem more virtuous
-
When she is gone. Then open not thy lips:
-
Firm and irrevocable is my doom
-
Which I have pass'd upon her; she is banish'd.
-
-
CELIA
-
-
Pronounce that sentence then on me, my liege:
-
I cannot live out of her company.
-
-
DUKE FREDERICK
-
-
You are a fool. You, niece, provide yourself:
-
If you outstay the time, upon mine honour,
-
And in the greatness of my word, you die.
-
Exeunt DUKE FREDERICK and Lords
-
-
CELIA
-
-
O my poor Rosalind, whither wilt thou go?
-
Wilt thou change fathers? I will give thee mine.
-
I charge thee, be not thou more grieved than I am.
-
-
ROSALIND
-
-
I have more cause.
-
-
CELIA
-
-
Thou hast not, cousin;
-
Prithee be cheerful: know'st thou not, the duke
-
Hath banish'd me, his daughter?
-
-
ROSALIND
-
-
That he hath not.
-
-
CELIA
-
-
No, hath not? Rosalind lacks then the love
-
Which teacheth thee that thou and I am one:
-
Shall we be sunder'd? shall we part, sweet girl?
-
No: let my father seek another heir.
-
Therefore devise with me how we may fly,
-
Whither to go and what to bear with us;
-
And do not seek to take your change upon you,
-
To bear your griefs yourself and leave me out;
-
For, by this heaven, now at our sorrows pale,
-
Say what thou canst, I'll go along with thee.
-
-
ROSALIND
-
-
Why, whither shall we go?
-
-
CELIA
-
-
To seek my uncle in the forest of Arden.
-
-
ROSALIND
-
-
Alas, what danger will it be to us,
-
Maids as we are, to travel forth so far!
-
Beauty provoketh thieves sooner than gold.
-
-
CELIA
-
-
I'll put myself in poor and mean attire
-
And with a kind of umber smirch my face;
-
The like do you: so shall we pass along
-
And never stir assailants.
-
-
ROSALIND
-
-
Were it not better,
-
Because that I am more than common tall,
-
That I did suit me all points like a man?
-
A gallant curtle-axe upon my thigh,
-
A boar-spear in my hand; and--in my heart
-
Lie there what hidden woman's fear there will--
-
We'll have a swashing and a martial outside,
-
As many other mannish cowards have
-
That do outface it with their semblances.
-
-
CELIA
-
-
What shall I call thee when thou art a man?
-
-
ROSALIND
-
-
I'll have no worse a name than Jove's own page;
-
And therefore look you call me Ganymede.
-
But what will you be call'd?
-
-
CELIA
-
-
Something that hath a reference to my state
-
No longer Celia, but Aliena.
-
-
ROSALIND
-
-
But, cousin, what if we assay'd to steal
-
The clownish fool out of your father's court?
-
Would he not be a comfort to our travel?
-
-
CELIA
-
-
He'll go along o'er the wide world with me;
-
Leave me alone to woo him. Let's away,
-
And get our jewels and our wealth together,
-
Devise the fittest time and safest way
-
To hide us from pursuit that will be made
-
After my flight. Now go we in content
-
To liberty and not to banishment.
-
Exeunt
-
-
-
-
- - diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php deleted file mode 100644 index fad6105..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php +++ /dev/null @@ -1,416 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\Tests\XPath; - -use PHPUnit\Framework\TestCase; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\ExpressionErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\ElementNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\FunctionNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Parser; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Extension\HtmlExtension; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Translator; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\XPathExpr; - -class TranslatorTest extends TestCase -{ - /** @dataProvider getXpathLiteralTestData */ - public function testXpathLiteral($value, $literal) - { - $this->assertEquals($literal, Translator::getXpathLiteral($value)); - } - - /** @dataProvider getCssToXPathTestData */ - public function testCssToXPath($css, $xpath) - { - $translator = new Translator(); - $translator->registerExtension(new HtmlExtension($translator)); - $this->assertEquals($xpath, $translator->cssToXPath($css, '')); - } - - public function testCssToXPathPseudoElement() - { - $this->expectException(ExpressionErrorException::class); - $translator = new Translator(); - $translator->registerExtension(new HtmlExtension($translator)); - $translator->cssToXPath('e::first-line'); - } - - public function testGetExtensionNotExistsExtension() - { - $this->expectException(ExpressionErrorException::class); - $translator = new Translator(); - $translator->registerExtension(new HtmlExtension($translator)); - $translator->getExtension('fake'); - } - - public function testAddCombinationNotExistsExtension() - { - $this->expectException(ExpressionErrorException::class); - $translator = new Translator(); - $translator->registerExtension(new HtmlExtension($translator)); - $parser = new Parser(); - $xpath = $parser->parse('*')[0]; - $combinedXpath = $parser->parse('*')[0]; - $translator->addCombination('fake', $xpath, $combinedXpath); - } - - public function testAddFunctionNotExistsFunction() - { - $this->expectException(ExpressionErrorException::class); - $translator = new Translator(); - $translator->registerExtension(new HtmlExtension($translator)); - $xpath = new XPathExpr(); - $function = new FunctionNode(new ElementNode(), 'fake'); - $translator->addFunction($xpath, $function); - } - - public function testAddPseudoClassNotExistsClass() - { - $this->expectException(ExpressionErrorException::class); - $translator = new Translator(); - $translator->registerExtension(new HtmlExtension($translator)); - $xpath = new XPathExpr(); - $translator->addPseudoClass($xpath, 'fake'); - } - - public function testAddAttributeMatchingClassNotExistsClass() - { - $this->expectException(ExpressionErrorException::class); - $translator = new Translator(); - $translator->registerExtension(new HtmlExtension($translator)); - $xpath = new XPathExpr(); - $translator->addAttributeMatching($xpath, '', '', ''); - } - - /** @dataProvider getXmlLangTestData */ - public function testXmlLang($css, array $elementsId) - { - $translator = new Translator(); - $document = new \SimpleXMLElement(file_get_contents(__DIR__.'/Fixtures/lang.xml')); - $elements = $document->xpath($translator->cssToXPath($css)); - $this->assertCount(\count($elementsId), $elements); - foreach ($elements as $element) { - $this->assertContains((string) $element->attributes()->id, $elementsId); - } - } - - /** @dataProvider getHtmlIdsTestData */ - public function testHtmlIds($css, array $elementsId) - { - $translator = new Translator(); - $translator->registerExtension(new HtmlExtension($translator)); - $document = new \DOMDocument(); - $document->strictErrorChecking = false; - $internalErrors = libxml_use_internal_errors(true); - $document->loadHTMLFile(__DIR__.'/Fixtures/ids.html'); - $document = simplexml_import_dom($document); - $elements = $document->xpath($translator->cssToXPath($css)); - $this->assertCount(\count($elementsId), $elements); - foreach ($elements as $element) { - if (null !== $element->attributes()->id) { - $this->assertContains((string) $element->attributes()->id, $elementsId); - } - } - libxml_clear_errors(); - libxml_use_internal_errors($internalErrors); - } - - /** @dataProvider getHtmlShakespearTestData */ - public function testHtmlShakespear($css, $count) - { - $translator = new Translator(); - $translator->registerExtension(new HtmlExtension($translator)); - $document = new \DOMDocument(); - $document->strictErrorChecking = false; - $document->loadHTMLFile(__DIR__.'/Fixtures/shakespear.html'); - $document = simplexml_import_dom($document); - $bodies = $document->xpath('//body'); - $elements = $bodies[0]->xpath($translator->cssToXPath($css)); - $this->assertCount($count, $elements); - } - - public function testOnlyOfTypeFindsSingleChildrenOfGivenType() - { - $translator = new Translator(); - $translator->registerExtension(new HtmlExtension($translator)); - $document = new \DOMDocument(); - $document->loadHTML(<<<'HTML' - - -

- A -

-

- B - C -

- - -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 static function getXpathLiteralTestData() - { - return [ - ['foo', "'foo'"], - ["foo's bar", '"foo\'s bar"'], - ["foo's \"middle\" bar", 'concat(\'foo\', "\'", \'s "middle" bar\')'], - ["foo's 'middle' \"bar\"", 'concat(\'foo\', "\'", \'s \', "\'", \'middle\', "\'", \' "bar"\')'], - ]; - } - - public static function getCssToXPathTestData() - { - return [ - ['*', '*'], - ['e', 'e'], - ['*|e', 'e'], - ['e|f', 'e:f'], - ['e[foo]', 'e[@foo]'], - ['e[foo|bar]', 'e[@foo:bar]'], - ['e[foo="bar"]', "e[@foo = 'bar']"], - ['e[foo~="bar"]', "e[@foo and contains(concat(' ', normalize-space(@foo), ' '), ' bar ')]"], - ['e[foo^="bar"]', "e[@foo and starts-with(@foo, 'bar')]"], - ['e[foo$="bar"]', "e[@foo and substring(@foo, string-length(@foo)-2) = 'bar']"], - ['e[foo*="bar"]', "e[@foo and contains(@foo, 'bar')]"], - ['e[foo!="bar"]', "e[not(@foo) or @foo != 'bar']"], - ['e[foo!="bar"][foo!="baz"]', "e[(not(@foo) or @foo != 'bar') and (not(@foo) or @foo != 'baz')]"], - ['e[hreflang|="en"]', "e[@hreflang and (@hreflang = 'en' or starts-with(@hreflang, 'en-'))]"], - ['e:nth-child(1)', "*/*[(name() = 'e') and (position() = 1)]"], - ['e:nth-last-child(1)', "*/*[(name() = 'e') and (position() = last() - 0)]"], - ['e:nth-last-child(2n+2)', "*/*[(name() = 'e') and (last() - position() - 1 >= 0 and (last() - position() - 1) mod 2 = 0)]"], - ['e:nth-of-type(1)', '*/e[position() = 1]'], - ['e:nth-last-of-type(1)', '*/e[position() = last() - 0]'], - ['div e:nth-last-of-type(1) .aclass', "div/descendant-or-self::*/e[position() = last() - 0]/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' aclass ')]"], - ['e:first-child', "*/*[(name() = 'e') and (position() = 1)]"], - ['e:last-child', "*/*[(name() = 'e') and (position() = last())]"], - ['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[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::*)]'], - ['e:hover', 'e[0]'], - ['e:contains("foo")', "e[contains(string(.), 'foo')]"], - ['e:ConTains(foo)', "e[contains(string(.), 'foo')]"], - ['e.warning', "e[@class and contains(concat(' ', normalize-space(@class), ' '), ' warning ')]"], - ['e#myid', "e[@id = 'myid']"], - ['e:not(:nth-child(odd))', 'e[not(position() - 1 >= 0 and (position() - 1) mod 2 = 0)]'], - ['e:nOT(*)', 'e[0]'], - ['e f', 'e/descendant-or-self::*/f'], - ['e > f', 'e/f'], - ['e + f', "e/following-sibling::*[(name() = 'f') and (position() = 1)]"], - ['e ~ f', 'e/following-sibling::f'], - ['div#container p', "div[@id = 'container']/descendant-or-self::*/p"], - ]; - } - - public static function getXmlLangTestData() - { - return [ - [':lang("EN")', ['first', 'second', 'third', 'fourth']], - [':lang("en-us")', ['second', 'fourth']], - [':lang(en-nz)', ['third']], - [':lang(fr)', ['fifth']], - [':lang(ru)', ['sixth']], - [":lang('ZH')", ['eighth']], - [':lang(de) :lang(zh)', ['eighth']], - [':lang(en), :lang(zh)', ['first', 'second', 'third', 'fourth', 'eighth']], - [':lang(es)', []], - ]; - } - - public static function getHtmlIdsTestData() - { - return [ - ['div', ['outer-div', 'li-div', 'foobar-div']], - ['DIV', ['outer-div', 'li-div', 'foobar-div']], // case-insensitive in HTML - ['div div', ['li-div']], - ['div, div div', ['outer-div', 'li-div', 'foobar-div']], - ['a[name]', ['name-anchor']], - ['a[NAme]', ['name-anchor']], // case-insensitive in HTML: - ['a[rel]', ['tag-anchor', 'nofollow-anchor']], - ['a[rel="tag"]', ['tag-anchor']], - ['a[href*="localhost"]', ['tag-anchor']], - ['a[href*=""]', []], - ['a[href^="http"]', ['tag-anchor', 'nofollow-anchor']], - ['a[href^="http:"]', ['tag-anchor']], - ['a[href^=""]', []], - ['a[href$="org"]', ['nofollow-anchor']], - ['a[href$=""]', []], - ['div[foobar~="bc"]', ['foobar-div']], - ['div[foobar~="cde"]', ['foobar-div']], - ['[foobar~="ab bc"]', ['foobar-div']], - ['[foobar~=""]', []], - ['[foobar~=" \t"]', []], - ['div[foobar~="cd"]', []], - ['*[lang|="En"]', ['second-li']], - ['[lang|="En-us"]', ['second-li']], - // Powered_Cache_Attribute values are case sensitive - ['*[lang|="en"]', []], - ['[lang|="en-US"]', []], - ['*[lang|="e"]', []], - // ... :lang() is not. - [':lang("EN")', ['second-li', 'li-div']], - ['*:lang(en-US)', ['second-li', 'li-div']], - [':lang("e")', []], - ['li:nth-child(3)', ['third-li']], - ['li:nth-child(10)', []], - ['li:nth-child(2n)', ['second-li', 'fourth-li', 'sixth-li']], - ['li:nth-child(even)', ['second-li', 'fourth-li', 'sixth-li']], - ['li:nth-child(2n+0)', ['second-li', 'fourth-li', 'sixth-li']], - ['li:nth-child(+2n+1)', ['first-li', 'third-li', 'fifth-li', 'seventh-li']], - ['li:nth-child(odd)', ['first-li', 'third-li', 'fifth-li', 'seventh-li']], - ['li:nth-child(2n+4)', ['fourth-li', 'sixth-li']], - ['li:nth-child(3n+1)', ['first-li', 'fourth-li', 'seventh-li']], - ['li:nth-child(n)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], - ['li:nth-child(n-1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], - ['li:nth-child(n+1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], - ['li:nth-child(n+3)', ['third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], - ['li:nth-child(-n)', []], - ['li:nth-child(-n-1)', []], - ['li:nth-child(-n+1)', ['first-li']], - ['li:nth-child(-n+3)', ['first-li', 'second-li', 'third-li']], - ['li:nth-last-child(0)', []], - ['li:nth-last-child(2n)', ['second-li', 'fourth-li', 'sixth-li']], - ['li:nth-last-child(even)', ['second-li', 'fourth-li', 'sixth-li']], - ['li:nth-last-child(2n+2)', ['second-li', 'fourth-li', 'sixth-li']], - ['li:nth-last-child(n)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], - ['li:nth-last-child(n-1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], - ['li:nth-last-child(n-3)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], - ['li:nth-last-child(n+1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']], - ['li:nth-last-child(n+3)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li']], - ['li:nth-last-child(-n)', []], - ['li:nth-last-child(-n-1)', []], - ['li:nth-last-child(-n+1)', ['seventh-li']], - ['li:nth-last-child(-n+3)', ['fifth-li', 'sixth-li', 'seventh-li']], - ['ol:first-of-type', ['first-ol']], - ['ol:nth-child(4)', ['first-ol']], - ['ol:nth-of-type(2)', ['second-ol']], - ['ol:nth-last-of-type(1)', ['second-ol']], - ['span:only-child', ['foobar-span', 'no-siblings-of-any-type']], - ['li div:only-child', ['li-div']], - ['div *:only-child', ['li-div', 'foobar-span']], - ['p:only-of-type', ['paragraph']], - [':only-of-type', ['html', 'li-div', 'foobar-span', 'no-siblings-of-any-type']], - ['div#foobar-div :only-of-type', ['foobar-span']], - ['a:empty', ['name-anchor']], - ['a:EMpty', ['name-anchor']], - ['li:empty', ['third-li', 'fourth-li', 'fifth-li', 'sixth-li']], - [':root', ['html']], - ['html:root', ['html']], - ['li:root', []], - ['* :root', []], - ['*:contains("link")', ['html', 'nil', 'outer-div', 'tag-anchor', 'nofollow-anchor']], - [':CONtains("link")', ['html', 'nil', 'outer-div', 'tag-anchor', 'nofollow-anchor']], - ['*:contains("LInk")', []], // case sensitive - ['*:contains("e")', ['html', 'nil', 'outer-div', 'first-ol', 'first-li', 'paragraph', 'p-em']], - ['*:contains("E")', []], // case-sensitive - ['.a', ['first-ol']], - ['.b', ['first-ol']], - ['*.a', ['first-ol']], - ['ol.a', ['first-ol']], - ['.c', ['first-ol', 'third-li', 'fourth-li']], - ['*.c', ['first-ol', 'third-li', 'fourth-li']], - ['ol *.c', ['third-li', 'fourth-li']], - ['ol li.c', ['third-li', 'fourth-li']], - ['li ~ li.c', ['third-li', 'fourth-li']], - ['ol > li.c', ['third-li', 'fourth-li']], - ['#first-li', ['first-li']], - ['li#first-li', ['first-li']], - ['*#first-li', ['first-li']], - ['li div', ['li-div']], - ['li > div', ['li-div']], - ['div div', ['li-div']], - ['div > div', []], - ['div>.c', ['first-ol']], - ['div > .c', ['first-ol']], - ['div + div', ['foobar-div']], - ['a ~ a', ['tag-anchor', 'nofollow-anchor']], - ['a[rel="tag"] ~ a', ['nofollow-anchor']], - ['ol#first-ol li:last-child', ['seventh-li']], - ['ol#first-ol *:last-child', ['li-div', 'seventh-li']], - ['#outer-div:first-child', ['outer-div']], - ['#outer-div :first-child', ['name-anchor', 'first-li', 'li-div', 'p-b', 'checkbox-fieldset-disabled', 'area-href']], - ['a[href]', ['tag-anchor', 'nofollow-anchor']], - [':not(*)', []], - ['a:not([href])', ['name-anchor']], - ['ol :Not(li[class])', ['first-li', 'second-li', 'li-div', 'fifth-li', 'sixth-li', 'seventh-li']], - // HTML-specific - [':link', ['link-href', 'tag-anchor', 'nofollow-anchor', 'area-href']], - [':visited', []], - [':enabled', ['link-href', 'tag-anchor', 'nofollow-anchor', 'checkbox-unchecked', 'text-checked', 'checkbox-checked', 'area-href']], - [':disabled', ['checkbox-disabled', 'checkbox-disabled-checked', 'fieldset', 'checkbox-fieldset-disabled']], - [':checked', ['checkbox-checked', 'checkbox-disabled-checked']], - ]; - } - - public static function getHtmlShakespearTestData() - { - return [ - ['*', 246], - ['div:contains(CELIA)', 26], - ['div:only-child', 22], // ? - ['div:nth-child(even)', 106], - ['div:nth-child(2n)', 106], - ['div:nth-child(odd)', 137], - ['div:nth-child(2n+1)', 137], - ['div:nth-child(n)', 243], - ['div:last-child', 53], - ['div:first-child', 51], - ['div > div', 242], - ['div + div', 190], - ['div ~ div', 190], - ['body', 1], - ['body div', 243], - ['div', 243], - ['div div', 242], - ['div div div', 241], - ['div, div, div', 243], - ['div, a, span', 243], - ['.dialog', 51], - ['div.dialog', 51], - ['div .dialog', 51], - ['div.character, div.dialog', 99], - ['div.direction.dialog', 0], - ['div.dialog.direction', 0], - ['div.dialog.scene', 1], - ['div.scene.scene', 1], - ['div.scene .scene', 0], - ['div.direction .dialog ', 0], - ['div .dialog .direction', 4], - ['div.dialog .dialog .direction', 4], - ['#speech5', 1], - ['div#speech5', 1], - ['div #speech5', 1], - ['div.scene div.dialog', 49], - ['div#scene1 div.dialog div', 142], - ['#scene1 #speech1', 1], - ['div[class]', 103], - ['div[class=dialog]', 50], - ['div[class^=dia]', 51], - ['div[class$=log]', 50], - ['div[class*=sce]', 1], - ['div[class|=dialog]', 50], // ? Seems right - ['div[class!=madeup]', 243], // ? Seems right - ['div[class~=dialog]', 51], // ? Seems right - ]; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/AbstractExtension.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/AbstractExtension.php deleted file mode 100644 index 8f3dcbb..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/AbstractExtension.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Extension; - -/** - * XPath expression translator abstract extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -abstract class AbstractExtension implements ExtensionInterface -{ - /** - * {@inheritdoc} - */ - public function getNodeTranslators(): array - { - return []; - } - - /** - * {@inheritdoc} - */ - public function getCombinationTranslators(): array - { - return []; - } - - /** - * {@inheritdoc} - */ - public function getFunctionTranslators(): array - { - return []; - } - - /** - * {@inheritdoc} - */ - public function getPseudoClassTranslators(): array - { - return []; - } - - /** - * {@inheritdoc} - */ - public function getAttributeMatchingTranslators(): array - { - return []; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.php deleted file mode 100644 index 5415136..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.php +++ /dev/null @@ -1,119 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Extension; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Translator; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator attribute extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class AttributeMatchingExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getAttributeMatchingTranslators(): array - { - return [ - 'exists' => [$this, 'translateExists'], - '=' => [$this, 'translateEquals'], - '~=' => [$this, 'translateIncludes'], - '|=' => [$this, 'translateDashMatch'], - '^=' => [$this, 'translatePrefixMatch'], - '$=' => [$this, 'translateSuffixMatch'], - '*=' => [$this, 'translateSubstringMatch'], - '!=' => [$this, 'translateDifferent'], - ]; - } - - public function translateExists(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition($attribute); - } - - public function translateEquals(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition(sprintf('%s = %s', $attribute, Translator::getXpathLiteral($value))); - } - - public function translateIncludes(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition($value ? sprintf( - '%1$s and contains(concat(\' \', normalize-space(%1$s), \' \'), %2$s)', - $attribute, - Translator::getXpathLiteral(' '.$value.' ') - ) : '0'); - } - - public function translateDashMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition(sprintf( - '%1$s and (%1$s = %2$s or starts-with(%1$s, %3$s))', - $attribute, - Translator::getXpathLiteral($value), - Translator::getXpathLiteral($value.'-') - )); - } - - public function translatePrefixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition($value ? sprintf( - '%1$s and starts-with(%1$s, %2$s)', - $attribute, - Translator::getXpathLiteral($value) - ) : '0'); - } - - public function translateSuffixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition($value ? sprintf( - '%1$s and substring(%1$s, string-length(%1$s)-%2$s) = %3$s', - $attribute, - \strlen($value) - 1, - Translator::getXpathLiteral($value) - ) : '0'); - } - - public function translateSubstringMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition($value ? sprintf( - '%1$s and contains(%1$s, %2$s)', - $attribute, - Translator::getXpathLiteral($value) - ) : '0'); - } - - public function translateDifferent(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition(sprintf( - $value ? 'not(%1$s) or %1$s != %2$s' : '%s != %s', - $attribute, - Translator::getXpathLiteral($value) - )); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'attribute-matching'; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php deleted file mode 100644 index 9d6e043..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Extension; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator combination extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class CombinationExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getCombinationTranslators(): array - { - return [ - ' ' => [$this, 'translateDescendant'], - '>' => [$this, 'translateChild'], - '+' => [$this, 'translateDirectAdjacent'], - '~' => [$this, 'translateIndirectAdjacent'], - ]; - } - - public function translateDescendant(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr - { - return $xpath->join('/descendant-or-self::*/', $combinedXpath); - } - - public function translateChild(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr - { - return $xpath->join('/', $combinedXpath); - } - - public function translateDirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr - { - return $xpath - ->join('/following-sibling::', $combinedXpath) - ->addNameTest() - ->addCondition('position() = 1'); - } - - public function translateIndirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr - { - return $xpath->join('/following-sibling::', $combinedXpath); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'combination'; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/ExtensionInterface.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/ExtensionInterface.php deleted file mode 100644 index 56fb4a1..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/ExtensionInterface.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Extension; - -/** - * XPath expression translator extension interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -interface ExtensionInterface -{ - /** - * Returns node translators. - * - * These callables will receive the node as first argument and the translator as second argument. - * - * @return callable[] - */ - public function getNodeTranslators(): array; - - /** - * Returns combination translators. - * - * @return callable[] - */ - public function getCombinationTranslators(): array; - - /** - * Returns function translators. - * - * @return callable[] - */ - public function getFunctionTranslators(): array; - - /** - * Returns pseudo-class translators. - * - * @return callable[] - */ - public function getPseudoClassTranslators(): array; - - /** - * Returns attribute operation translators. - * - * @return callable[] - */ - public function getAttributeMatchingTranslators(): array; - - /** - * Returns extension name. - */ - public function getName(): string; -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php deleted file mode 100644 index 811105d..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php +++ /dev/null @@ -1,171 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Extension; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\ExpressionErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\SyntaxErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\FunctionNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Parser; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Translator; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator function extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class FunctionExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getFunctionTranslators(): array - { - return [ - 'nth-child' => [$this, 'translateNthChild'], - 'nth-last-child' => [$this, 'translateNthLastChild'], - 'nth-of-type' => [$this, 'translateNthOfType'], - 'nth-last-of-type' => [$this, 'translateNthLastOfType'], - 'contains' => [$this, 'translateContains'], - 'lang' => [$this, 'translateLang'], - ]; - } - - /** - * @throws ExpressionErrorException - */ - public function translateNthChild(XPathExpr $xpath, FunctionNode $function, bool $last = false, bool $addNameTest = true): XPathExpr - { - try { - [$a, $b] = Parser::parseSeries($function->getArguments()); - } catch (SyntaxErrorException $e) { - throw new ExpressionErrorException(sprintf('Invalid series: "%s".', implode('", "', $function->getArguments())), 0, $e); - } - - $xpath->addStarPrefix(); - if ($addNameTest) { - $xpath->addNameTest(); - } - - if (0 === $a) { - return $xpath->addCondition('position() = '.($last ? 'last() - '.($b - 1) : $b)); - } - - if ($a < 0) { - if ($b < 1) { - return $xpath->addCondition('false()'); - } - - $sign = '<='; - } else { - $sign = '>='; - } - - $expr = 'position()'; - - if ($last) { - $expr = 'last() - '.$expr; - --$b; - } - - if (0 !== $b) { - $expr .= ' - '.$b; - } - - $conditions = [sprintf('%s %s 0', $expr, $sign)]; - - if (1 !== $a && -1 !== $a) { - $conditions[] = sprintf('(%s) mod %d = 0', $expr, $a); - } - - return $xpath->addCondition(implode(' and ', $conditions)); - - // todo: handle an+b, odd, even - // an+b means every-a, plus b, e.g., 2n+1 means odd - // 0n+b means b - // n+0 means a=1, i.e., all elements - // an means every a elements, i.e., 2n means even - // -n means -1n - // -1n+6 means elements 6 and previous - } - - public function translateNthLastChild(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - return $this->translateNthChild($xpath, $function, true); - } - - public function translateNthOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - return $this->translateNthChild($xpath, $function, false, false); - } - - /** - * @throws ExpressionErrorException - */ - public function translateNthLastOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - if ('*' === $xpath->getElement()) { - throw new ExpressionErrorException('"*:nth-of-type()" is not implemented.'); - } - - return $this->translateNthChild($xpath, $function, true, false); - } - - /** - * @throws ExpressionErrorException - */ - public function translateContains(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - $arguments = $function->getArguments(); - foreach ($arguments as $token) { - if (!($token->isString() || $token->isIdentifier())) { - throw new ExpressionErrorException('Expected a single string or identifier for :contains(), got '.implode(', ', $arguments)); - } - } - - return $xpath->addCondition(sprintf( - 'contains(string(.), %s)', - Translator::getXpathLiteral($arguments[0]->getValue()) - )); - } - - /** - * @throws ExpressionErrorException - */ - public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - $arguments = $function->getArguments(); - foreach ($arguments as $token) { - if (!($token->isString() || $token->isIdentifier())) { - throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments)); - } - } - - return $xpath->addCondition(sprintf( - 'lang(%s)', - Translator::getXpathLiteral($arguments[0]->getValue()) - )); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'function'; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php deleted file mode 100644 index 72b9a23..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php +++ /dev/null @@ -1,187 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Extension; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\ExpressionErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\FunctionNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Translator; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator HTML extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class HtmlExtension extends AbstractExtension -{ - public function __construct(Translator $translator) - { - $translator - ->getExtension('node') - ->setFlag(NodeExtension::ELEMENT_NAME_IN_LOWER_CASE, true) - ->setFlag(NodeExtension::ATTRIBUTE_NAME_IN_LOWER_CASE, true); - } - - /** - * {@inheritdoc} - */ - public function getPseudoClassTranslators(): array - { - return [ - 'checked' => [$this, 'translateChecked'], - 'link' => [$this, 'translateLink'], - 'disabled' => [$this, 'translateDisabled'], - 'enabled' => [$this, 'translateEnabled'], - 'selected' => [$this, 'translateSelected'], - 'invalid' => [$this, 'translateInvalid'], - 'hover' => [$this, 'translateHover'], - 'visited' => [$this, 'translateVisited'], - ]; - } - - /** - * {@inheritdoc} - */ - public function getFunctionTranslators(): array - { - return [ - 'lang' => [$this, 'translateLang'], - ]; - } - - public function translateChecked(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition( - '(@checked ' - ."and (name(.) = 'input' or name(.) = 'command')" - ."and (@type = 'checkbox' or @type = 'radio'))" - ); - } - - public function translateLink(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition("@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')"); - } - - public function translateDisabled(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition( - '(' - .'@disabled and' - .'(' - ."(name(.) = 'input' and @type != 'hidden')" - ." or name(.) = 'button'" - ." or name(.) = 'select'" - ." or name(.) = 'textarea'" - ." or name(.) = 'command'" - ." or name(.) = 'fieldset'" - ." or name(.) = 'optgroup'" - ." or name(.) = 'option'" - .')' - .') or (' - ."(name(.) = 'input' and @type != 'hidden')" - ." or name(.) = 'button'" - ." or name(.) = 'select'" - ." or name(.) = 'textarea'" - .')' - .' and ancestor::fieldset[@disabled]' - ); - // todo: in the second half, add "and is not a descendant of that fieldset element's first legend element child, if any." - } - - public function translateEnabled(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition( - '(' - .'@href and (' - ."name(.) = 'a'" - ." or name(.) = 'link'" - ." or name(.) = 'area'" - .')' - .') or (' - .'(' - ."name(.) = 'command'" - ." or name(.) = 'fieldset'" - ." or name(.) = 'optgroup'" - .')' - .' and not(@disabled)' - .') or (' - .'(' - ."(name(.) = 'input' and @type != 'hidden')" - ." or name(.) = 'button'" - ." or name(.) = 'select'" - ." or name(.) = 'textarea'" - ." or name(.) = 'keygen'" - .')' - .' and not (@disabled or ancestor::fieldset[@disabled])' - .') or (' - ."name(.) = 'option' and not(" - .'@disabled or ancestor::optgroup[@disabled]' - .')' - .')' - ); - } - - /** - * @throws ExpressionErrorException - */ - public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - $arguments = $function->getArguments(); - foreach ($arguments as $token) { - if (!($token->isString() || $token->isIdentifier())) { - throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments)); - } - } - - return $xpath->addCondition(sprintf( - 'ancestor-or-self::*[@lang][1][starts-with(concat(' - ."translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-')" - .', %s)]', - 'lang', - Translator::getXpathLiteral(strtolower($arguments[0]->getValue()).'-') - )); - } - - public function translateSelected(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition("(@selected and name(.) = 'option')"); - } - - public function translateInvalid(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition('0'); - } - - public function translateHover(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition('0'); - } - - public function translateVisited(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition('0'); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'html'; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php deleted file mode 100644 index a64f7ee..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php +++ /dev/null @@ -1,197 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Extension; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Translator; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator node extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class NodeExtension extends AbstractExtension -{ - public const ELEMENT_NAME_IN_LOWER_CASE = 1; - public const ATTRIBUTE_NAME_IN_LOWER_CASE = 2; - public const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4; - - private $flags; - - public function __construct(int $flags = 0) - { - $this->flags = $flags; - } - - /** - * @return $this - */ - public function setFlag(int $flag, bool $on): self - { - if ($on && !$this->hasFlag($flag)) { - $this->flags += $flag; - } - - if (!$on && $this->hasFlag($flag)) { - $this->flags -= $flag; - } - - return $this; - } - - public function hasFlag(int $flag): bool - { - return (bool) ($this->flags & $flag); - } - - /** - * {@inheritdoc} - */ - public function getNodeTranslators(): array - { - return [ - 'Selector' => [$this, 'translateSelector'], - 'CombinedSelector' => [$this, 'translateCombinedSelector'], - 'Negation' => [$this, 'translateNegation'], - 'Function' => [$this, 'translateFunction'], - 'Pseudo' => [$this, 'translatePseudo'], - 'Powered_Cache_Attribute' => [$this, 'translateAttribute'], - 'Class' => [$this, 'translateClass'], - 'Hash' => [$this, 'translateHash'], - 'Element' => [$this, 'translateElement'], - ]; - } - - public function translateSelector(Node\SelectorNode $node, Translator $translator): XPathExpr - { - return $translator->nodeToXPath($node->getTree()); - } - - public function translateCombinedSelector(Node\CombinedSelectorNode $node, Translator $translator): XPathExpr - { - return $translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector()); - } - - public function translateNegation(Node\NegationNode $node, Translator $translator): XPathExpr - { - $xpath = $translator->nodeToXPath($node->getSelector()); - $subXpath = $translator->nodeToXPath($node->getSubSelector()); - $subXpath->addNameTest(); - - if ($subXpath->getCondition()) { - return $xpath->addCondition(sprintf('not(%s)', $subXpath->getCondition())); - } - - return $xpath->addCondition('0'); - } - - public function translateFunction(Node\FunctionNode $node, Translator $translator): XPathExpr - { - $xpath = $translator->nodeToXPath($node->getSelector()); - - return $translator->addFunction($xpath, $node); - } - - public function translatePseudo(Node\PseudoNode $node, Translator $translator): XPathExpr - { - $xpath = $translator->nodeToXPath($node->getSelector()); - - return $translator->addPseudoClass($xpath, $node->getIdentifier()); - } - - public function translateAttribute(Node\AttributeNode $node, Translator $translator): XPathExpr - { - $name = $node->getAttribute(); - $safe = $this->isSafeName($name); - - if ($this->hasFlag(self::ATTRIBUTE_NAME_IN_LOWER_CASE)) { - $name = strtolower($name); - } - - if ($node->getNamespace()) { - $name = sprintf('%s:%s', $node->getNamespace(), $name); - $safe = $safe && $this->isSafeName($node->getNamespace()); - } - - $attribute = $safe ? '@'.$name : sprintf('attribute::*[name() = %s]', Translator::getXpathLiteral($name)); - $value = $node->getValue(); - $xpath = $translator->nodeToXPath($node->getSelector()); - - if ($this->hasFlag(self::ATTRIBUTE_VALUE_IN_LOWER_CASE)) { - $value = strtolower($value); - } - - return $translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value); - } - - public function translateClass(Node\ClassNode $node, Translator $translator): XPathExpr - { - $xpath = $translator->nodeToXPath($node->getSelector()); - - return $translator->addAttributeMatching($xpath, '~=', '@class', $node->getName()); - } - - public function translateHash(Node\HashNode $node, Translator $translator): XPathExpr - { - $xpath = $translator->nodeToXPath($node->getSelector()); - - return $translator->addAttributeMatching($xpath, '=', '@id', $node->getId()); - } - - public function translateElement(Node\ElementNode $node): XPathExpr - { - $element = $node->getElement(); - - if ($element && $this->hasFlag(self::ELEMENT_NAME_IN_LOWER_CASE)) { - $element = strtolower($element); - } - - if ($element) { - $safe = $this->isSafeName($element); - } else { - $element = '*'; - $safe = true; - } - - if ($node->getNamespace()) { - $element = sprintf('%s:%s', $node->getNamespace(), $element); - $safe = $safe && $this->isSafeName($node->getNamespace()); - } - - $xpath = new XPathExpr('', $element); - - if (!$safe) { - $xpath->addNameTest(); - } - - return $xpath; - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'node'; - } - - private function isSafeName(string $name): bool - { - return 0 < preg_match('~^[a-zA-Z_][a-zA-Z0-9_.-]*$~', $name); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.php deleted file mode 100644 index b20a597..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\Extension; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\ExpressionErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator pseudo-class extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class PseudoClassExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getPseudoClassTranslators(): array - { - return [ - 'root' => [$this, 'translateRoot'], - 'first-child' => [$this, 'translateFirstChild'], - 'last-child' => [$this, 'translateLastChild'], - 'first-of-type' => [$this, 'translateFirstOfType'], - 'last-of-type' => [$this, 'translateLastOfType'], - 'only-child' => [$this, 'translateOnlyChild'], - 'only-of-type' => [$this, 'translateOnlyOfType'], - 'empty' => [$this, 'translateEmpty'], - ]; - } - - public function translateRoot(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition('not(parent::*)'); - } - - public function translateFirstChild(XPathExpr $xpath): XPathExpr - { - return $xpath - ->addStarPrefix() - ->addNameTest() - ->addCondition('position() = 1'); - } - - public function translateLastChild(XPathExpr $xpath): XPathExpr - { - return $xpath - ->addStarPrefix() - ->addNameTest() - ->addCondition('position() = last()'); - } - - /** - * @throws ExpressionErrorException - */ - public function translateFirstOfType(XPathExpr $xpath): XPathExpr - { - if ('*' === $xpath->getElement()) { - throw new ExpressionErrorException('"*:first-of-type" is not implemented.'); - } - - return $xpath - ->addStarPrefix() - ->addCondition('position() = 1'); - } - - /** - * @throws ExpressionErrorException - */ - public function translateLastOfType(XPathExpr $xpath): XPathExpr - { - if ('*' === $xpath->getElement()) { - throw new ExpressionErrorException('"*:last-of-type" is not implemented.'); - } - - return $xpath - ->addStarPrefix() - ->addCondition('position() = last()'); - } - - public function translateOnlyChild(XPathExpr $xpath): XPathExpr - { - return $xpath - ->addStarPrefix() - ->addNameTest() - ->addCondition('last() = 1'); - } - - public function translateOnlyOfType(XPathExpr $xpath): XPathExpr - { - $element = $xpath->getElement(); - - return $xpath->addCondition(sprintf('count(preceding-sibling::%s)=0 and count(following-sibling::%s)=0', $element, $element)); - } - - public function translateEmpty(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition('not(*) and not(string-length())'); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'pseudo-class'; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Translator.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Translator.php deleted file mode 100644 index 488b40c..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/Translator.php +++ /dev/null @@ -1,230 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Exception\ExpressionErrorException; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\FunctionNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\NodeInterface; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\Parser; -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Parser\ParserInterface; - -/** - * XPath expression translator interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class Translator implements TranslatorInterface -{ - private $mainParser; - - /** - * @var ParserInterface[] - */ - private $shortcutParsers = []; - - /** - * @var Extension\ExtensionInterface[] - */ - private $extensions = []; - - private $nodeTranslators = []; - private $combinationTranslators = []; - private $functionTranslators = []; - private $pseudoClassTranslators = []; - private $attributeMatchingTranslators = []; - - public function __construct(?ParserInterface $parser = null) - { - $this->mainParser = $parser ?? new Parser(); - - $this - ->registerExtension(new Extension\NodeExtension()) - ->registerExtension(new Extension\CombinationExtension()) - ->registerExtension(new Extension\FunctionExtension()) - ->registerExtension(new Extension\PseudoClassExtension()) - ->registerExtension(new Extension\AttributeMatchingExtension()) - ; - } - - public static function getXpathLiteral(string $element): string - { - if (!str_contains($element, "'")) { - return "'".$element."'"; - } - - if (!str_contains($element, '"')) { - return '"'.$element.'"'; - } - - $string = $element; - $parts = []; - while (true) { - if (false !== $pos = strpos($string, "'")) { - $parts[] = sprintf("'%s'", substr($string, 0, $pos)); - $parts[] = "\"'\""; - $string = substr($string, $pos + 1); - } else { - $parts[] = "'$string'"; - break; - } - } - - return sprintf('concat(%s)', implode(', ', $parts)); - } - - /** - * {@inheritdoc} - */ - public function cssToXPath(string $cssExpr, string $prefix = 'descendant-or-self::'): string - { - $selectors = $this->parseSelectors($cssExpr); - - /** @var SelectorNode $selector */ - foreach ($selectors as $index => $selector) { - if (null !== $selector->getPseudoElement()) { - throw new ExpressionErrorException('Pseudo-elements are not supported.'); - } - - $selectors[$index] = $this->selectorToXPath($selector, $prefix); - } - - return implode(' | ', $selectors); - } - - /** - * {@inheritdoc} - */ - public function selectorToXPath(SelectorNode $selector, string $prefix = 'descendant-or-self::'): string - { - return ($prefix ?: '').$this->nodeToXPath($selector); - } - - /** - * @return $this - */ - public function registerExtension(Extension\ExtensionInterface $extension): self - { - $this->extensions[$extension->getName()] = $extension; - - $this->nodeTranslators = array_merge($this->nodeTranslators, $extension->getNodeTranslators()); - $this->combinationTranslators = array_merge($this->combinationTranslators, $extension->getCombinationTranslators()); - $this->functionTranslators = array_merge($this->functionTranslators, $extension->getFunctionTranslators()); - $this->pseudoClassTranslators = array_merge($this->pseudoClassTranslators, $extension->getPseudoClassTranslators()); - $this->attributeMatchingTranslators = array_merge($this->attributeMatchingTranslators, $extension->getAttributeMatchingTranslators()); - - return $this; - } - - /** - * @throws ExpressionErrorException - */ - public function getExtension(string $name): Extension\ExtensionInterface - { - if (!isset($this->extensions[$name])) { - throw new ExpressionErrorException(sprintf('Extension "%s" not registered.', $name)); - } - - return $this->extensions[$name]; - } - - /** - * @return $this - */ - public function registerParserShortcut(ParserInterface $shortcut): self - { - $this->shortcutParsers[] = $shortcut; - - return $this; - } - - /** - * @throws ExpressionErrorException - */ - public function nodeToXPath(NodeInterface $node): XPathExpr - { - if (!isset($this->nodeTranslators[$node->getNodeName()])) { - throw new ExpressionErrorException(sprintf('Node "%s" not supported.', $node->getNodeName())); - } - - return $this->nodeTranslators[$node->getNodeName()]($node, $this); - } - - /** - * @throws ExpressionErrorException - */ - public function addCombination(string $combiner, NodeInterface $xpath, NodeInterface $combinedXpath): XPathExpr - { - if (!isset($this->combinationTranslators[$combiner])) { - throw new ExpressionErrorException(sprintf('Combiner "%s" not supported.', $combiner)); - } - - return $this->combinationTranslators[$combiner]($this->nodeToXPath($xpath), $this->nodeToXPath($combinedXpath)); - } - - /** - * @throws ExpressionErrorException - */ - public function addFunction(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - if (!isset($this->functionTranslators[$function->getName()])) { - throw new ExpressionErrorException(sprintf('Function "%s" not supported.', $function->getName())); - } - - return $this->functionTranslators[$function->getName()]($xpath, $function); - } - - /** - * @throws ExpressionErrorException - */ - public function addPseudoClass(XPathExpr $xpath, string $pseudoClass): XPathExpr - { - if (!isset($this->pseudoClassTranslators[$pseudoClass])) { - throw new ExpressionErrorException(sprintf('Pseudo-class "%s" not supported.', $pseudoClass)); - } - - return $this->pseudoClassTranslators[$pseudoClass]($xpath); - } - - /** - * @throws ExpressionErrorException - */ - public function addAttributeMatching(XPathExpr $xpath, string $operator, string $attribute, ?string $value): XPathExpr - { - if (!isset($this->attributeMatchingTranslators[$operator])) { - throw new ExpressionErrorException(sprintf('Powered_Cache_Attribute matcher operator "%s" not supported.', $operator)); - } - - return $this->attributeMatchingTranslators[$operator]($xpath, $attribute, $value); - } - - /** - * @return SelectorNode[] - */ - private function parseSelectors(string $css): array - { - foreach ($this->shortcutParsers as $shortcut) { - $tokens = $shortcut->parse($css); - - if (!empty($tokens)) { - return $tokens; - } - } - - return $this->mainParser->parse($css); - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/TranslatorInterface.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/TranslatorInterface.php deleted file mode 100644 index 2aae319..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/TranslatorInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath; - -use PoweredCache\Dependencies\Symfony\Component\CssSelector\Node\SelectorNode; - -/** - * XPath expression translator interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -interface TranslatorInterface -{ - /** - * Translates a CSS selector to an XPath expression. - */ - public function cssToXPath(string $cssExpr, string $prefix = 'descendant-or-self::'): string; - - /** - * Translates a parsed selector node to an XPath expression. - */ - public function selectorToXPath(SelectorNode $selector, string $prefix = 'descendant-or-self::'): string; -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/XPathExpr.php b/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/XPathExpr.php deleted file mode 100644 index 8ab83fe..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/XPath/XPathExpr.php +++ /dev/null @@ -1,111 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Component\CssSelector\XPath; - -/** - * XPath expression translator interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon - * - * @internal - */ -class XPathExpr -{ - private $path; - private $element; - private $condition; - - public function __construct(string $path = '', string $element = '*', string $condition = '', bool $starPrefix = false) - { - $this->path = $path; - $this->element = $element; - $this->condition = $condition; - - if ($starPrefix) { - $this->addStarPrefix(); - } - } - - public function getElement(): string - { - return $this->element; - } - - /** - * @return $this - */ - public function addCondition(string $condition): self - { - $this->condition = $this->condition ? sprintf('(%s) and (%s)', $this->condition, $condition) : $condition; - - return $this; - } - - public function getCondition(): string - { - return $this->condition; - } - - /** - * @return $this - */ - public function addNameTest(): self - { - if ('*' !== $this->element) { - $this->addCondition('name() = '.Translator::getXpathLiteral($this->element)); - $this->element = '*'; - } - - return $this; - } - - /** - * @return $this - */ - public function addStarPrefix(): self - { - $this->path .= '*/'; - - return $this; - } - - /** - * Joins another XPathExpr with a combiner. - * - * @return $this - */ - public function join(string $combiner, self $expr): self - { - $path = $this->__toString().$combiner; - - if ('*/' !== $expr->path) { - $path .= $expr->path; - } - - $this->path = $path; - $this->element = $expr->element; - $this->condition = $expr->condition; - - return $this; - } - - public function __toString(): string - { - $path = $this->path.$this->element; - $condition = null === $this->condition || '' === $this->condition ? '' : '['.$this->condition.']'; - - return $path.$condition; - } -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/composer.json b/includes/classes/Dependencies/Symfony/Component/CssSelector/composer.json deleted file mode 100644 index f0b7124..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/composer.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "symfony/css-selector", - "type": "library", - "description": "Converts CSS selectors to XPath expressions", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Jean-François Simon", - "email": "jeanfrancois.simon@sensiolabs.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\CssSelector\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/includes/classes/Dependencies/Symfony/Component/CssSelector/phpunit.xml.dist b/includes/classes/Dependencies/Symfony/Component/CssSelector/phpunit.xml.dist deleted file mode 100644 index a8e537e..0000000 --- a/includes/classes/Dependencies/Symfony/Component/CssSelector/phpunit.xml.dist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - ./Tests/ - - - - - - ./ - - ./Resources - ./Tests - ./vendor - - - - diff --git a/includes/classes/Dependencies/Symfony/Polyfill/Php80/LICENSE b/includes/classes/Dependencies/Symfony/Polyfill/Php80/LICENSE deleted file mode 100644 index 0ed3a24..0000000 --- a/includes/classes/Dependencies/Symfony/Polyfill/Php80/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2020-present Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Php80.php b/includes/classes/Dependencies/Symfony/Polyfill/Php80/Php80.php deleted file mode 100644 index bec0308..0000000 --- a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Php80.php +++ /dev/null @@ -1,115 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Polyfill\Php80; - -/** - * @author Ion Bazan - * @author Nico Oelgart - * @author Nicolas Grekas - * - * @internal - */ -final class Php80 -{ - public static function fdiv(float $dividend, float $divisor): float - { - return @($dividend / $divisor); - } - - public static function get_debug_type($value): string - { - switch (true) { - case null === $value: return 'null'; - case \is_bool($value): return 'bool'; - case \is_string($value): return 'string'; - case \is_array($value): return 'array'; - case \is_int($value): return 'int'; - case \is_float($value): return 'float'; - case \is_object($value): break; - case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class'; - default: - if (null === $type = @get_resource_type($value)) { - return 'unknown'; - } - - if ('Unknown' === $type) { - $type = 'closed'; - } - - return "resource ($type)"; - } - - $class = \get_class($value); - - if (false === strpos($class, '@')) { - return $class; - } - - return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous'; - } - - public static function get_resource_id($res): int - { - if (!\is_resource($res) && null === @get_resource_type($res)) { - throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res))); - } - - return (int) $res; - } - - public static function preg_last_error_msg(): string - { - switch (preg_last_error()) { - case \PREG_INTERNAL_ERROR: - return 'Internal error'; - case \PREG_BAD_UTF8_ERROR: - return 'Malformed UTF-8 characters, possibly incorrectly encoded'; - case \PREG_BAD_UTF8_OFFSET_ERROR: - return 'The offset did not correspond to the beginning of a valid UTF-8 code point'; - case \PREG_BACKTRACK_LIMIT_ERROR: - return 'Backtrack limit exhausted'; - case \PREG_RECURSION_LIMIT_ERROR: - return 'Recursion limit exhausted'; - case \PREG_JIT_STACKLIMIT_ERROR: - return 'JIT stack limit exhausted'; - case \PREG_NO_ERROR: - return 'No error'; - default: - return 'Unknown error'; - } - } - - public static function str_contains(string $haystack, string $needle): bool - { - return '' === $needle || false !== strpos($haystack, $needle); - } - - public static function str_starts_with(string $haystack, string $needle): bool - { - return 0 === strncmp($haystack, $needle, \strlen($needle)); - } - - public static function str_ends_with(string $haystack, string $needle): bool - { - if ('' === $needle || $needle === $haystack) { - return true; - } - - if ('' === $haystack) { - return false; - } - - $needleLength = \strlen($needle); - - return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength); - } -} diff --git a/includes/classes/Dependencies/Symfony/Polyfill/Php80/PhpToken.php b/includes/classes/Dependencies/Symfony/Polyfill/Php80/PhpToken.php deleted file mode 100644 index e5fa75a..0000000 --- a/includes/classes/Dependencies/Symfony/Polyfill/Php80/PhpToken.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace PoweredCache\Dependencies\Symfony\Polyfill\Php80; - -/** - * @author Fedonyuk Anton - * - * @internal - */ -class PhpToken implements \Stringable -{ - /** - * @var int - */ - public $id; - - /** - * @var string - */ - public $text; - - /** - * @var -1|positive-int - */ - public $line; - - /** - * @var int - */ - public $pos; - - /** - * @param -1|positive-int $line - */ - public function __construct(int $id, string $text, int $line = -1, int $position = -1) - { - $this->id = $id; - $this->text = $text; - $this->line = $line; - $this->pos = $position; - } - - public function getTokenName(): ?string - { - if ('UNKNOWN' === $name = token_name($this->id)) { - $name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text; - } - - return $name; - } - - /** - * @param int|string|array $kind - */ - public function is($kind): bool - { - foreach ((array) $kind as $value) { - if (\in_array($value, [$this->id, $this->text], true)) { - return true; - } - } - - return false; - } - - public function isIgnorable(): bool - { - return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true); - } - - public function __toString(): string - { - return (string) $this->text; - } - - /** - * @return list - */ - public static function tokenize(string $code, int $flags = 0): array - { - $line = 1; - $position = 0; - $tokens = token_get_all($code, $flags); - foreach ($tokens as $index => $token) { - if (\is_string($token)) { - $id = \ord($token); - $text = $token; - } else { - [$id, $text, $line] = $token; - } - $tokens[$index] = new static($id, $text, $line, $position); - $position += \strlen($text); - } - - return $tokens; - } -} diff --git a/includes/classes/Dependencies/Symfony/Polyfill/Php80/README.md b/includes/classes/Dependencies/Symfony/Polyfill/Php80/README.md deleted file mode 100644 index 3816c55..0000000 --- a/includes/classes/Dependencies/Symfony/Polyfill/Php80/README.md +++ /dev/null @@ -1,25 +0,0 @@ -Symfony Polyfill / Php80 -======================== - -This component provides features added to PHP 8.0 core: - -- [`Stringable`](https://php.net/stringable) interface -- [`fdiv`](https://php.net/fdiv) -- [`ValueError`](https://php.net/valueerror) class -- [`UnhandledMatchError`](https://php.net/unhandledmatcherror) class -- `FILTER_VALIDATE_BOOL` constant -- [`get_debug_type`](https://php.net/get_debug_type) -- [`PhpToken`](https://php.net/phptoken) class -- [`preg_last_error_msg`](https://php.net/preg_last_error_msg) -- [`str_contains`](https://php.net/str_contains) -- [`str_starts_with`](https://php.net/str_starts_with) -- [`str_ends_with`](https://php.net/str_ends_with) -- [`get_resource_id`](https://php.net/get_resource_id) - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/Attribute.php b/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/Attribute.php deleted file mode 100644 index 2b95542..0000000 --- a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/Attribute.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -#[Attribute(Attribute::TARGET_CLASS)] -final class Attribute -{ - public const TARGET_CLASS = 1; - public const TARGET_FUNCTION = 2; - public const TARGET_METHOD = 4; - public const TARGET_PROPERTY = 8; - public const TARGET_CLASS_CONSTANT = 16; - public const TARGET_PARAMETER = 32; - public const TARGET_ALL = 63; - public const IS_REPEATABLE = 64; - - /** @var int */ - public $flags; - - public function __construct(int $flags = self::TARGET_ALL) - { - $this->flags = $flags; - } -} diff --git a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/PhpToken.php b/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/PhpToken.php deleted file mode 100644 index 903d87e..0000000 --- a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/PhpToken.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID < 80000 && extension_loaded('tokenizer')) { - class PhpToken extends PoweredCache\Dependencies\Symfony\Polyfill\Php80\PhpToken - { - } -} diff --git a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/Stringable.php b/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/Stringable.php deleted file mode 100644 index 7c62d75..0000000 --- a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/Stringable.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID < 80000) { - interface Stringable - { - /** - * @return string - */ - public function __toString(); - } -} diff --git a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/UnhandledMatchError.php b/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/UnhandledMatchError.php deleted file mode 100644 index 01c6c6c..0000000 --- a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/UnhandledMatchError.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID < 80000) { - class UnhandledMatchError extends Error - { - } -} diff --git a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/ValueError.php b/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/ValueError.php deleted file mode 100644 index 783dbc2..0000000 --- a/includes/classes/Dependencies/Symfony/Polyfill/Php80/Resources/stubs/ValueError.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID < 80000) { - class ValueError extends Error - { - } -} diff --git a/includes/classes/Dependencies/Symfony/Polyfill/Php80/bootstrap.php b/includes/classes/Dependencies/Symfony/Polyfill/Php80/bootstrap.php deleted file mode 100644 index 3d6dc26..0000000 --- a/includes/classes/Dependencies/Symfony/Polyfill/Php80/bootstrap.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use PoweredCache\Dependencies\Symfony\Polyfill\Php80 as p; - -if (\PHP_VERSION_ID >= 80000) { - return; -} - -if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) { - define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN); -} - -if (!function_exists('fdiv')) { - function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); } -} -if (!function_exists('preg_last_error_msg')) { - function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); } -} -if (!function_exists('str_contains')) { - function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); } -} -if (!function_exists('str_starts_with')) { - function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); } -} -if (!function_exists('str_ends_with')) { - function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); } -} -if (!function_exists('get_debug_type')) { - function get_debug_type($value): string { return p\Php80::get_debug_type($value); } -} -if (!function_exists('get_resource_id')) { - function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); } -} diff --git a/includes/classes/Dependencies/Symfony/Polyfill/Php80/composer.json b/includes/classes/Dependencies/Symfony/Polyfill/Php80/composer.json deleted file mode 100644 index a503b03..0000000 --- a/includes/classes/Dependencies/Symfony/Polyfill/Php80/composer.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "symfony/polyfill-php80", - "type": "library", - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "keywords": ["polyfill", "shim", "compatibility", "portable"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, - "files": [ "bootstrap.php" ], - "classmap": [ "Resources/stubs" ] - }, - "minimum-stability": "dev", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/includes/classes/Dependencies/voku/helper/AbstractDomParser.php b/includes/classes/Dependencies/voku/helper/AbstractDomParser.php deleted file mode 100644 index 457594d..0000000 --- a/includes/classes/Dependencies/voku/helper/AbstractDomParser.php +++ /dev/null @@ -1,527 +0,0 @@ - ['[', ']', '{', '}'], - 'tmp' => [ - '____SIMPLE_HTML_DOM__VOKU__SQUARE_BRACKET_LEFT____', - '____SIMPLE_HTML_DOM__VOKU__SQUARE_BRACKET_RIGHT____', - '____SIMPLE_HTML_DOM__VOKU__BRACKET_LEFT____', - '____SIMPLE_HTML_DOM__VOKU__BRACKET_RIGHT____', - ], - ]; - - /** - * @var string[][] - */ - protected static $domReplaceHelper = [ - 'orig' => ['&', '|', '+', '%', '@', ' [ - '____SIMPLE_HTML_DOM__VOKU__AMP____', - '____SIMPLE_HTML_DOM__VOKU__PIPE____', - '____SIMPLE_HTML_DOM__VOKU__PLUS____', - '____SIMPLE_HTML_DOM__VOKU__PERCENT____', - '____SIMPLE_HTML_DOM__VOKU__AT____', - 'document = clone $this->document; - } - - /** - * @param string $name - * - * @return string|null - */ - abstract public function __get($name); - - /** - * @return string - */ - abstract public function __toString(); - - /** - * does nothing (only for api-compatibility-reasons) - * - * @return bool - * - * @deprecated - */ - public function clear(): bool - { - return true; - } - - /** - * Create DOMDocument from HTML. - * - * @param string $html - * @param int|null $libXMLExtraOptions - * - * @return \DOMDocument - */ - abstract protected function createDOMDocument(string $html, $libXMLExtraOptions = null): \DOMDocument; - - /** - * @param string $content - * @param bool $multiDecodeNewHtmlEntity - * - * @return string - */ - protected function decodeHtmlEntity(string $content, bool $multiDecodeNewHtmlEntity): string - { - if ($multiDecodeNewHtmlEntity) { - if (\class_exists('\PoweredCache\Dependencies\voku\helper\UTF8')) { - $content = UTF8::rawurldecode($content, true); - } else { - do { - $content_compare = $content; - - $content = \rawurldecode( - \html_entity_decode( - $content, - \ENT_QUOTES | \ENT_HTML5 - ) - ); - } while ($content_compare !== $content); - } - } else { - /** @noinspection NestedPositiveIfStatementsInspection */ - if (\class_exists('\PoweredCache\Dependencies\voku\helper\UTF8')) { - $content = UTF8::rawurldecode($content, false); - } else { - $content = \rawurldecode( - \html_entity_decode( - $content, - \ENT_QUOTES | \ENT_HTML5 - ) - ); - } - } - - return $content; - } - - /** - * Find list of nodes with a CSS selector. - * - * @param string $selector - * @param int|null $idx - * - * @return mixed - */ - abstract public function find(string $selector, $idx = null); - - /** - * Find nodes with a CSS selector. - * - * @param string $selector - * - * @return mixed - */ - abstract public function findMulti(string $selector); - - /** - * Find nodes with a CSS selector or false, if no element is found. - * - * @param string $selector - * - * @return mixed - */ - abstract public function findMultiOrFalse(string $selector); - - /** - * Find one node with a CSS selector. - * - * @param string $selector - * - * @return mixed - */ - abstract public function findOne(string $selector); - - /** - * Find one node with a CSS selector or false, if no element is found. - * - * @param string $selector - * - * @return mixed - */ - abstract public function findOneOrFalse(string $selector); - - /** - * @return \DOMDocument - */ - public function getDocument(): \DOMDocument - { - return $this->document; - } - - /** - * Get dom node's outer html. - * - * @param bool $multiDecodeNewHtmlEntity - * @param bool $putBrokenReplacedBack - * - * @return string - */ - abstract public function html(bool $multiDecodeNewHtmlEntity = false, bool $putBrokenReplacedBack = true): string; - - /** - * Get dom node's inner html. - * - * @param bool $multiDecodeNewHtmlEntity - * @param bool $putBrokenReplacedBack - * - * @return string - */ - public function innerHtml(bool $multiDecodeNewHtmlEntity = false, bool $putBrokenReplacedBack = true): string - { - // init - $text = ''; - - if ($this->document->documentElement) { - foreach ($this->document->documentElement->childNodes as $node) { - $text .= $this->document->saveHTML($node); - } - } - - return $this->fixHtmlOutput($text, $multiDecodeNewHtmlEntity, $putBrokenReplacedBack); - } - - /** - * Get dom node's inner html. - * - * @param bool $multiDecodeNewHtmlEntity - * - * @return string - */ - public function innerXml(bool $multiDecodeNewHtmlEntity = false): string - { - // init - $text = ''; - - if ($this->document->documentElement) { - foreach ($this->document->documentElement->childNodes as $node) { - $text .= $this->document->saveXML($node); - } - } - - return $this->fixHtmlOutput($text, $multiDecodeNewHtmlEntity); - } - - /** - * Load HTML from string. - * - * @param string $html - * @param int|null $libXMLExtraOptions - * - * @return DomParserInterface - */ - abstract public function loadHtml(string $html, $libXMLExtraOptions = null): DomParserInterface; - - /** - * Load HTML from file. - * - * @param string $filePath - * @param int|null $libXMLExtraOptions - * - * @throws \RuntimeException - * - * @return DomParserInterface - */ - abstract public function loadHtmlFile(string $filePath, $libXMLExtraOptions = null): DomParserInterface; - - /** - * Save the html-dom as string. - * - * @param string $filepath - * - * @return string - */ - public function save(string $filepath = ''): string - { - $string = $this->html(); - if ($filepath !== '') { - \file_put_contents($filepath, $string, \LOCK_EX); - } - - return $string; - } - - /** - * @param callable $functionName - * - * @phpstan-param callable(\PoweredCache\Dependencies\voku\helper\XmlDomParser|\PoweredCache\Dependencies\voku\helper\HtmlDomParser): void $functionName - * - * @return void - */ - public function set_callback($functionName) - { - static::$callback = $functionName; - } - - /** - * Get dom node's plain text. - * - * @param bool $multiDecodeNewHtmlEntity - * - * @return string - */ - public function text(bool $multiDecodeNewHtmlEntity = false): string - { - return $this->fixHtmlOutput($this->document->textContent, $multiDecodeNewHtmlEntity); - } - - /** - * Get the HTML as XML or plain XML if needed. - * - * @param bool $multiDecodeNewHtmlEntity - * @param bool $htmlToXml - * @param bool $removeXmlHeader - * @param int $options - * - * @return string - */ - public function xml( - bool $multiDecodeNewHtmlEntity = false, - bool $htmlToXml = true, - bool $removeXmlHeader = true, - int $options = \LIBXML_NOEMPTYTAG - ): string { - $xml = $this->document->saveXML(null, $options); - if ($xml === false) { - return ''; - } - - if ($removeXmlHeader) { - $xml = \ltrim((string) \preg_replace('/<\?xml.*\?>/', '', $xml)); - } - - if ($htmlToXml) { - $return = $this->fixHtmlOutput($xml, $multiDecodeNewHtmlEntity); - } else { - $xml = $this->decodeHtmlEntity($xml, $multiDecodeNewHtmlEntity); - - $return = self::putReplacedBackToPreserveHtmlEntities($xml); - } - - return $return; - } - - /** - * Get the encoding to use. - * - * @return string - */ - protected function getEncoding(): string - { - return $this->encoding; - } - - /** - * workaround for bug: https://bugs.php.net/bug.php?id=74628 - * - * @param string $html - * - * @return void - */ - protected function html5FallbackForScriptTags(string &$html) - { - // regEx for e.g.: ['; - }, - $html - ); - - if ($htmlTmp !== null) { - $html = $htmlTmp; - } - } - - /** - * @param string $html - * - * @return string - */ - public static function putReplacedBackToPreserveHtmlEntities(string $html, bool $putBrokenReplacedBack = true): string - { - static $DOM_REPLACE__HELPER_CACHE = null; - - if ($DOM_REPLACE__HELPER_CACHE === null) { - $DOM_REPLACE__HELPER_CACHE['tmp'] = \array_merge( - self::$domLinkReplaceHelper['tmp'], - self::$domReplaceHelper['tmp'] - ); - $DOM_REPLACE__HELPER_CACHE['orig'] = \array_merge( - self::$domLinkReplaceHelper['orig'], - self::$domReplaceHelper['orig'] - ); - - $DOM_REPLACE__HELPER_CACHE['tmp']['html_wrapper__start'] = '<' . self::$domHtmlWrapperHelper . '>'; - $DOM_REPLACE__HELPER_CACHE['tmp']['html_wrapper__end'] = ''; - - $DOM_REPLACE__HELPER_CACHE['orig']['html_wrapper__start'] = ''; - $DOM_REPLACE__HELPER_CACHE['orig']['html_wrapper__end'] = ''; - - $DOM_REPLACE__HELPER_CACHE['tmp']['html_wrapper__start_broken'] = self::$domHtmlWrapperHelper . '>'; - $DOM_REPLACE__HELPER_CACHE['tmp']['html_wrapper__end_broken'] = ''; - - $DOM_REPLACE__HELPER_CACHE['orig']['html_special_script__start'] = ' 0 - ) { - $html = \str_ireplace(self::$domBrokenReplaceHelper['tmp'], self::$domBrokenReplaceHelper['orig'], $html); - } - - return \str_ireplace($DOM_REPLACE__HELPER_CACHE['tmp'], $DOM_REPLACE__HELPER_CACHE['orig'], $html); - } - - /** - * @param string $html - * - * @return string - */ - public static function replaceToPreserveHtmlEntities(string $html): string - { - // init - $linksNew = []; - $linksOld = []; - - if (\strpos($html, 'http') !== false) { - // regEx for e.g.: [https://www.domain.de/foo.php?foobar=1&email=lars%40moelleken.org&guid=test1233312&{{foo}}#foo] - $regExUrl = '/(\[?\bhttps?:\/\/[^\s<>]+(?:\(\w+\)|[^[:punct:]\s]|\/|}|]))/i'; - \preg_match_all($regExUrl, $html, $linksOld); - - if (!empty($linksOld[1])) { - $linksOld = $linksOld[1]; - foreach ((array) $linksOld as $linkKey => $linkOld) { - $linksNew[$linkKey] = \str_replace( - self::$domLinkReplaceHelper['orig'], - self::$domLinkReplaceHelper['tmp'], - $linkOld - ); - } - } - } - - $linksNewCount = \count($linksNew); - if ($linksNewCount > 0 && \count($linksOld) === $linksNewCount) { - $search = \array_merge($linksOld, self::$domReplaceHelper['orig']); - $replace = \array_merge($linksNew, self::$domReplaceHelper['tmp']); - } else { - $search = self::$domReplaceHelper['orig']; - $replace = self::$domReplaceHelper['tmp']; - } - - return \str_replace($search, $replace, $html); - } -} diff --git a/includes/classes/Dependencies/voku/helper/AbstractSimpleHtmlDom.php b/includes/classes/Dependencies/voku/helper/AbstractSimpleHtmlDom.php deleted file mode 100644 index fdca9af..0000000 --- a/includes/classes/Dependencies/voku/helper/AbstractSimpleHtmlDom.php +++ /dev/null @@ -1,255 +0,0 @@ - 'childNodes', - 'first_child' => 'firstChild', - 'last_child' => 'lastChild', - 'next_sibling' => 'nextSibling', - 'prev_sibling' => 'previousSibling', - 'parent' => 'parentNode', - 'outertext' => 'html', - 'outerhtml' => 'html', - 'innertext' => 'innerHtml', - 'innerhtml' => 'innerHtml', - 'innerhtmlkeep' => 'innerHtmlKeep', - ]; - - /** - * @var string[] - */ - protected static $stringDomNodes = [ - 'id', - 'prefix', - 'content' - ]; - - /** - * @var \DOMElement|\DOMNode|null - */ - protected $node; - - /** - * @var SimpleHtmlAttributes|null - */ - private $classListCache; - - /** - * @param string $name - * @param array $arguments - * - * @throws \BadMethodCallException - * - * @return SimpleHtmlDomInterface|string|null - */ - public function __call($name, $arguments) - { - $name = \strtolower($name); - - if (isset(self::$functionAliases[$name])) { - return \call_user_func_array([$this, self::$functionAliases[$name]], $arguments); - } - - throw new \BadMethodCallException('Method does not exist'); - } - - /** - * @param string $name - * - * @return SimpleHtmlAttributes|string|string[]|null - */ - public function __get($name) - { - $nameOrig = $name; - $name = \strtolower($name); - - switch ($name) { - case 'outerhtml': - case 'outertext': - case 'html': - return $this->html(); - case 'innerhtml': - case 'innertext': - return $this->innerHtml(); - case 'innerhtmlkeep': - return $this->innerHtml(false, false); - case 'text': - case 'plaintext': - return $this->text(); - case 'tag': - return $this->node->nodeName ?? ''; - case 'attr': - return $this->getAllAttributes(); - case 'classlist': - if ($this->classListCache === null) { - $this->classListCache = new SimpleHtmlAttributes($this->node ?? null, 'class'); - } - - return $this->classListCache; - default: - if ($this->node && \property_exists($this->node, $nameOrig)) { - if (\is_string($this->node->{$nameOrig})) { - return HtmlDomParser::putReplacedBackToPreserveHtmlEntities($this->node->{$nameOrig}); - } - - return $this->node->{$nameOrig}; - } - - return $this->getAttribute($name); - } - } - - /** - * @param string $selector - * @param int $idx - * - * @return SimpleHtmlDomInterface|SimpleHtmlDomInterface[]|SimpleHtmlDomNodeInterface - */ - public function __invoke($selector, $idx = null) - { - return $this->find($selector, $idx); - } - - /** - * @param string $name - * - * @return bool - */ - public function __isset($name) - { - $nameOrig = $name; - $name = \strtolower($name); - - switch ($name) { - case 'outertext': - case 'outerhtml': - case 'innertext': - case 'innerhtml': - case 'innerhtmlkeep': - case 'plaintext': - case 'text': - case 'tag': - return true; - default: - if ($this->node && \property_exists($this->node, $nameOrig)) { - return isset($this->node->{$nameOrig}); - } - - return $this->hasAttribute($name); - } - } - - /** - * @param string $name - * @param mixed $value - * - * @return SimpleHtmlDomInterface|null - */ - public function __set($name, $value) - { - $nameOrig = $name; - $name = \strtolower($name); - - switch ($name) { - case 'outerhtml': - case 'outertext': - return $this->replaceNodeWithString($value); - case 'innertext': - case 'innerhtml': - return $this->replaceChildWithString($value); - case 'innerhtmlkeep': - return $this->replaceChildWithString($value, false); - case 'plaintext': - return $this->replaceTextWithString($value); - case 'classlist': - $name = 'class'; - $nameOrig = 'class'; - // no break - default: - if ($this->node && \property_exists($this->node, $nameOrig)) { - // INFO: Cannot assign null to property DOMNode::* of type string - if (in_array($nameOrig, self::$stringDomNodes)) { - $value = (string)$value; - } - - if (!is_null($value)) { - return $this->node->{$nameOrig} = $value; - } - } - - return $this->setAttribute($name, $value); - } - } - - /** - * @return string - */ - public function __toString() - { - return $this->html(); - } - - /** - * @param string $name - * - * @return void - */ - public function __unset($name) - { - /** @noinspection UnusedFunctionResultInspection */ - $this->removeAttribute($name); - } - - /** - * @param string $selector - * @param int|null $idx - * - * @return mixed - */ - abstract public function find(string $selector, $idx = null); - - /** - * @return string[]|null - */ - abstract public function getAllAttributes(); - - abstract public function getAttribute(string $name): string; - - abstract public function hasAttribute(string $name): bool; - - abstract public function html(bool $multiDecodeNewHtmlEntity = false): string; - - abstract public function innerHtml(bool $multiDecodeNewHtmlEntity = false, bool $putBrokenReplacedBack = true): string; - - abstract public function removeAttribute(string $name): SimpleHtmlDomInterface; - - abstract protected function replaceChildWithString(string $string, bool $putBrokenReplacedBack = true): SimpleHtmlDomInterface; - - abstract protected function replaceNodeWithString(string $string): SimpleHtmlDomInterface; - - /** - * @param string $string - * - * @return SimpleHtmlDomInterface - */ - abstract protected function replaceTextWithString($string): SimpleHtmlDomInterface; - - /** - * @param string $name - * @param string|null $value - * @param bool $strictEmptyValueCheck - * - * @return SimpleHtmlDomInterface - */ - abstract public function setAttribute(string $name, $value = null, bool $strictEmptyValueCheck = false): SimpleHtmlDomInterface; - - abstract public function text(): string; -} diff --git a/includes/classes/Dependencies/voku/helper/AbstractSimpleHtmlDomNode.php b/includes/classes/Dependencies/voku/helper/AbstractSimpleHtmlDomNode.php deleted file mode 100644 index 0033ddf..0000000 --- a/includes/classes/Dependencies/voku/helper/AbstractSimpleHtmlDomNode.php +++ /dev/null @@ -1,80 +0,0 @@ -count(); - } - - if ($this->count() > 0) { - $return = []; - - foreach ($this as $node) { - if ($node instanceof SimpleHtmlDomInterface) { - $return[] = $node->{$name}; - } - } - - return $return; - } - - if ($name === 'plaintext' || $name === 'outertext') { - return []; - } - - return null; - } - - /** - * @param string $selector - * @param int|null $idx - * - * @return SimpleHtmlDomNodeInterface|SimpleHtmlDomNodeInterface[]|null - */ - public function __invoke($selector, $idx = null) - { - return $this->find($selector, $idx); - } - - /** - * @return string - */ - public function __toString() - { - // init - $html = ''; - - foreach ($this as $node) { - $html .= $node->outertext; - } - - return $html; - } - - /** - * @param string $selector - * @param int|null $idx - * - * @return SimpleHtmlDomNodeInterface|SimpleHtmlDomNodeInterface[]|null - */ - abstract public function find(string $selector, $idx = null); -} diff --git a/includes/classes/Dependencies/voku/helper/AbstractSimpleXmlDom.php b/includes/classes/Dependencies/voku/helper/AbstractSimpleXmlDom.php deleted file mode 100644 index dae961c..0000000 --- a/includes/classes/Dependencies/voku/helper/AbstractSimpleXmlDom.php +++ /dev/null @@ -1,217 +0,0 @@ - 'childNodes', - 'first_child' => 'firstChild', - 'last_child' => 'lastChild', - 'next_sibling' => 'nextSibling', - 'prev_sibling' => 'previousSibling', - 'parent' => 'parentNode', - ]; - - /** - * @var \DOMElement|\DOMNode|null - */ - protected $node; - - /** - * @param string $name - * @param array $arguments - * - * @throws \BadMethodCallException - * - * @return SimpleXmlDomInterface|string|null - */ - public function __call($name, $arguments) - { - $name = \strtolower($name); - - if (isset(self::$functionAliases[$name])) { - return \call_user_func_array([$this, self::$functionAliases[$name]], $arguments); - } - - throw new \BadMethodCallException('Method does not exist'); - } - - /** - * @param string $name - * - * @return array|string|null - */ - public function __get($name) - { - $nameOrig = $name; - $name = \strtolower($name); - - switch ($name) { - case 'xml': - return $this->xml(); - case 'plaintext': - return $this->text(); - case 'tag': - return $this->node->nodeName ?? ''; - case 'attr': - return $this->getAllAttributes(); - default: - if ($this->node && \property_exists($this->node, $nameOrig)) { - return $this->node->{$nameOrig}; - } - - return $this->getAttribute($name); - } - } - - /** - * @param string $selector - * @param int|null $idx - * - * @return SimpleXmlDomInterface|SimpleXmlDomInterface[]|SimpleXmlDomNodeInterface - */ - public function __invoke($selector, $idx = null) - { - return $this->find($selector, $idx); - } - - /** - * @param string $name - * - * @return bool - */ - public function __isset($name) - { - $nameOrig = $name; - $name = \strtolower($name); - - switch ($name) { - case 'outertext': - case 'outerhtml': - case 'innertext': - case 'innerhtml': - case 'innerhtmlkeep': - case 'plaintext': - case 'text': - case 'tag': - return true; - default: - if ($this->node && \property_exists($this->node, $nameOrig)) { - return isset($this->node->{$nameOrig}); - } - - return $this->hasAttribute($name); - } - } - - /** - * @param string $name - * @param mixed $value - * - * @return SimpleXmlDomInterface|null - */ - public function __set($name, $value) - { - $nameOrig = $name; - $name = \strtolower($name); - - switch ($name) { - case 'outerhtml': - case 'outertext': - return $this->replaceNodeWithString($value); - case 'innertext': - case 'innerhtml': - return $this->replaceChildWithString($value); - case 'innerhtmlkeep': - return $this->replaceChildWithString($value, false); - case 'plaintext': - return $this->replaceTextWithString($value); - default: - if ($this->node && \property_exists($this->node, $nameOrig)) { - return $this->node->{$nameOrig} = $value; - } - - return $this->setAttribute($name, $value); - } - } - - /** - * @return string - */ - public function __toString() - { - return $this->xml(); - } - - /** - * @param string $name - * - * @return void - */ - public function __unset($name) - { - /** @noinspection UnusedFunctionResultInspection */ - $this->removeAttribute($name); - } - - /** - * @param string $selector - * @param int|null $idx - * - * @return SimpleXmlDomInterface|SimpleXmlDomInterface[]|SimpleXmlDomNodeInterface - */ - abstract public function find(string $selector, $idx = null); - - /** - * @return string[]|null - */ - abstract public function getAllAttributes(); - - /** - * @param string $name - * - * @return string - */ - abstract public function getAttribute(string $name): string; - - /** - * @param string $name - * - * @return bool - */ - abstract public function hasAttribute(string $name): bool; - - abstract public function innerXml(bool $multiDecodeNewHtmlEntity = false): string; - - abstract public function removeAttribute(string $name): SimpleXmlDomInterface; - - abstract protected function replaceChildWithString(string $string, bool $putBrokenReplacedBack = true): SimpleXmlDomInterface; - - abstract protected function replaceNodeWithString(string $string): SimpleXmlDomInterface; - - /** - * @param string $string - * - * @return SimpleXmlDomInterface - */ - abstract protected function replaceTextWithString($string): SimpleXmlDomInterface; - - /** - * @param string $name - * @param string|null $value - * @param bool $strictEmptyValueCheck - * - * @return SimpleXmlDomInterface - */ - abstract public function setAttribute(string $name, $value = null, bool $strictEmptyValueCheck = false): SimpleXmlDomInterface; - - abstract public function text(): string; - - abstract public function xml(bool $multiDecodeNewHtmlEntity = false): string; -} diff --git a/includes/classes/Dependencies/voku/helper/AbstractSimpleXmlDomNode.php b/includes/classes/Dependencies/voku/helper/AbstractSimpleXmlDomNode.php deleted file mode 100644 index dd7be0a..0000000 --- a/includes/classes/Dependencies/voku/helper/AbstractSimpleXmlDomNode.php +++ /dev/null @@ -1,80 +0,0 @@ -count(); - } - - if ($this->count() > 0) { - $return = []; - - foreach ($this as $node) { - if ($node instanceof SimpleXmlDomInterface) { - $return[] = $node->{$name}; - } - } - - return $return; - } - - if ($name === 'plaintext' || $name === 'outertext') { - return []; - } - - return null; - } - - /** - * @param string $selector - * @param int|null $idx - * - * @return SimpleXmlDomNodeInterface|SimpleXmlDomNodeInterface[]|null - */ - public function __invoke($selector, $idx = null) - { - return $this->find($selector, $idx); - } - - /** - * @return string - */ - public function __toString() - { - // init - $html = ''; - - foreach ($this as $node) { - $html .= $node->outertext; - } - - return $html; - } - - /** - * @param string $selector - * @param int|null $idx - * - * @return SimpleXmlDomNodeInterface|SimpleXmlDomNodeInterface[]|null - */ - abstract public function find(string $selector, $idx = null); -} diff --git a/includes/classes/Dependencies/voku/helper/DomParserInterface.php b/includes/classes/Dependencies/voku/helper/DomParserInterface.php deleted file mode 100644 index f6e3513..0000000 --- a/includes/classes/Dependencies/voku/helper/DomParserInterface.php +++ /dev/null @@ -1,201 +0,0 @@ -'); - - $domElement = $dom->findOneOrFalse($htmlCssSelector); - if ($domElement === false) { - return $html; - } - $attributes = $domElement->getAllAttributes(); - if (!$attributes) { - return $html; - } - - $domElementNew = $domNew->findOneOrFalse('textarea'); - if ($domElementNew === false) { - return $html; - } - $attributesNew = $domElementNew->getAllAttributes(); - if (!$attributesNew) { - return $html; - } - - foreach ($attributesNew as $attributeNameNew => $attributeValueNew) { - $attributeNameNew = \strtolower($attributeNameNew); - - if ( - $attributeNameNew === 'class' - || - $attributeNameNew === 'style' - || - \strpos($attributeNameNew, 'on') === 0 // e.g. onClick, ... - ) { - if (isset($attributes[$attributeNameNew])) { - $attributes[$attributeNameNew] .= ' ' . $attributeValueNew; - } else { - $attributes[$attributeNameNew] = $attributeValueNew; - } - } else { - $attributes[$attributeNameNew] = $attributeValueNew; - } - } - - foreach ($attributes as $attributeName => $attributeValue) { - $domElement->setAttribute($attributeName, $attributeValue, true); - } - - return $domElement->html(); - } -} diff --git a/includes/classes/Dependencies/voku/helper/HtmlDomParser.php b/includes/classes/Dependencies/voku/helper/HtmlDomParser.php deleted file mode 100644 index 8f87676..0000000 --- a/includes/classes/Dependencies/voku/helper/HtmlDomParser.php +++ /dev/null @@ -1,1228 +0,0 @@ -Get dom node's outer html (alias for "outerHtml").

- * @property-read string $outerHtml - *

Get dom node's outer html.

- * @property-read string $innerText - *

Get dom node's inner html (alias for "innerHtml").

- * @property-read string $innerHtml - *

Get dom node's inner html.

- * @property-read string $plaintext - *

Get dom node's plain text.

- * - * @method string outerText() - *

Get dom node's outer html (alias for "outerHtml()").

- * @method string outerHtml() - *

Get dom node's outer html.

- * @method string innerText() - *

Get dom node's inner html (alias for "innerHtml()").

- * @method HtmlDomParser load(string $html) - *

Load HTML from string.

- * @method HtmlDomParser load_file(string $html) - *

Load HTML from file.

- * @method static HtmlDomParser file_get_html($filePath, $libXMLExtraOptions = null) - *

Load HTML from file.

- * @method static HtmlDomParser str_get_html($html, $libXMLExtraOptions = null) - *

Load HTML from string.

- */ -class HtmlDomParser extends AbstractDomParser -{ - /** - * @var callable|null - * - * @phpstan-var null|callable(string $cssSelectorString, string $xPathString, \DOMXPath, \PoweredCache\Dependencies\voku\helper\HtmlDomParser): string - */ - private $callbackXPathBeforeQuery; - - /** - * @var callable|null - * - * @phpstan-var null|callable(string $htmlString, \PoweredCache\Dependencies\voku\helper\HtmlDomParser): string - */ - private $callbackBeforeCreateDom; - - /** - * @var string[] - */ - protected static $functionAliases = [ - 'outertext' => 'html', - 'outerhtml' => 'html', - 'innertext' => 'innerHtml', - 'innerhtml' => 'innerHtml', - 'load' => 'loadHtml', - 'load_file' => 'loadHtmlFile', - ]; - - /** - * @var string[] - */ - protected $templateLogicSyntaxInSpecialScriptTags = [ - '+', - '<%', - '{%', - '{{', - ]; - - /** - * The properties specified for each special script tag is an array. - * - * ```php - * protected $specialScriptTags = [ - * 'text/html', - * 'text/template', - * 'text/x-custom-template', - * 'text/x-handlebars-template' - * ] - * ``` - * - * @var string[] - */ - protected $specialScriptTags = [ - 'text/html', - 'text/template', - 'text/x-custom-template', - 'text/x-handlebars-template', - ]; - - /** - * @var string[] - */ - protected $selfClosingTags = [ - 'area', - 'base', - 'br', - 'col', - 'command', - 'embed', - 'hr', - 'img', - 'input', - 'keygen', - 'link', - 'meta', - 'param', - 'source', - 'track', - 'wbr', - ]; - - /** - * @var bool - */ - protected $isDOMDocumentCreatedWithoutHtml = false; - - /** - * @var bool - */ - protected $isDOMDocumentCreatedWithoutWrapper = false; - - /** - * @var bool - */ - protected $isDOMDocumentCreatedWithCommentWrapper = false; - - /** - * @var bool - */ - protected $isDOMDocumentCreatedWithoutHeadWrapper = false; - - /** - * @var bool - */ - protected $isDOMDocumentCreatedWithoutPTagWrapper = false; - - /** - * @var bool - */ - protected $isDOMDocumentCreatedWithoutHtmlWrapper = false; - - /** - * @var bool - */ - protected $isDOMDocumentCreatedWithoutBodyWrapper = false; - - /** - * @var bool - */ - protected $isDOMDocumentCreatedWithMultiRoot = false; - - /** - * @var bool - */ - protected $isDOMDocumentCreatedWithFakeEndScript = false; - - /** - * @var bool - */ - protected $keepBrokenHtml = false; - - /** - * @param \DOMNode|SimpleHtmlDomInterface|string $element HTML code or SimpleHtmlDomInterface, \DOMNode - */ - public function __construct($element = null) - { - $this->document = new \DOMDocument('1.0', $this->getEncoding()); - - // DOMDocument settings - $this->document->preserveWhiteSpace = true; - $this->document->formatOutput = true; - - if ($element instanceof SimpleHtmlDomInterface) { - $element = $element->getNode(); - } - - if ($element instanceof \DOMNode) { - $domNode = $this->document->importNode($element, true); - - if ($domNode instanceof \DOMNode) { - $this->document->appendChild($domNode); - } - - return; - } - - if ($element !== null) { - $this->loadHtml($element); - } - } - - /** - * @param string $name - * @param array $arguments - * - * @return bool|mixed - */ - public function __call($name, $arguments) - { - $name = \strtolower($name); - - if (isset(self::$functionAliases[$name])) { - return \call_user_func_array([$this, self::$functionAliases[$name]], $arguments); - } - - throw new \BadMethodCallException('Method does not exist: ' . $name); - } - - /** - * @param string $name - * @param array $arguments - * - * @throws \BadMethodCallException - * @throws \RuntimeException - * - * @return static - */ - public static function __callStatic($name, $arguments) - { - $arguments0 = $arguments[0] ?? ''; - - $arguments1 = $arguments[1] ?? null; - - if ($name === 'str_get_html') { - $parser = new static(); - - return $parser->loadHtml($arguments0, $arguments1); - } - - if ($name === 'file_get_html') { - $parser = new static(); - - return $parser->loadHtmlFile($arguments0, $arguments1); - } - - throw new \BadMethodCallException('Method does not exist'); - } - - /** @noinspection MagicMethodsValidityInspection */ - - /** - * @param string $name - * - * @return string|null - */ - public function __get($name) - { - $name = \strtolower($name); - - switch ($name) { - case 'outerhtml': - case 'outertext': - return $this->html(); - case 'innerhtml': - case 'innertext': - return $this->innerHtml(); - case 'innerhtmlkeep': - return $this->innerHtml(false, false); - case 'text': - case 'plaintext': - return $this->text(); - } - - return null; - } - - /** - * @return string - */ - public function __toString() - { - return $this->html(); - } - - /** - * does nothing (only for api-compatibility-reasons) - * - * @return bool - * - * @deprecated - */ - public function clear(): bool - { - return true; - } - - /** - * Create DOMDocument from HTML. - * - * @param string $html - * @param int|null $libXMLExtraOptions - * @param bool $useDefaultLibXMLOptions - * - * @return \DOMDocument - */ - protected function createDOMDocument(string $html, $libXMLExtraOptions = null, $useDefaultLibXMLOptions = true): \DOMDocument - { - if ($this->callbackBeforeCreateDom) { - $html = \call_user_func($this->callbackBeforeCreateDom, $html, $this); - } - - // Remove content before because otherwise the DOMDocument can not handle the input. - $isDOMDocumentCreatedWithDoctype = false; - if (\stripos($html, ']*)?>/sui', $html, $matches_before_doctype) - && - \trim($matches_before_doctype[1]) - ) { - $html = \str_replace($matches_before_doctype[1], '', $html); - } - } - - if ($this->keepBrokenHtml) { - $html = $this->keepBrokenHtml(\trim($html)); - } - - if (\strpos($html, '<') === false) { - $this->isDOMDocumentCreatedWithoutHtml = true; - } elseif (\strpos(\ltrim($html), '<') !== 0) { - $this->isDOMDocumentCreatedWithoutWrapper = true; - } - - if (\strpos(\ltrim($html), ''; - } - } - - return $html; - } - - /** - * @param \DOMNode $node - * - * @return string - */ - private function getDoctype(\DOMNode $node): string - { - // check the doc-type only if it wasn't generated by DomDocument itself - if (!$this->withDocType) { - return ''; - } - - foreach ($node->childNodes as $child) { - if ( - $child instanceof \DOMDocumentType - && - $child->name - ) { - if (!$child->publicId && $child->systemId) { - $tmpTypeSystem = 'SYSTEM'; - $tmpTypePublic = ''; - } else { - $tmpTypeSystem = ''; - $tmpTypePublic = 'PUBLIC'; - } - - return 'name - . ($child->publicId ? ' ' . $tmpTypePublic . ' "' . $child->publicId . '"' : '') - . ($child->systemId ? ' ' . $tmpTypeSystem . ' "' . $child->systemId . '"' : '') - . '>'; - } - } - - return ''; - } - - /** - * @return array - */ - public function getDomainsToRemoveHttpPrefixFromAttributes(): array - { - return $this->domainsToRemoveHttpPrefixFromAttributes; - } - - /** - * @return bool - */ - public function isDoOptimizeAttributes(): bool - { - return $this->doOptimizeAttributes; - } - - /** - * @return bool - */ - public function isDoOptimizeViaHtmlDomParser(): bool - { - return $this->doOptimizeViaHtmlDomParser; - } - - /** - * @return bool - */ - public function isDoRemoveComments(): bool - { - return $this->doRemoveComments; - } - - /** - * @return bool - */ - public function isDoRemoveDefaultAttributes(): bool - { - return $this->doRemoveDefaultAttributes; - } - - /** - * @return bool - */ - public function isDoRemoveDeprecatedAnchorName(): bool - { - return $this->doRemoveDeprecatedAnchorName; - } - - /** - * @return bool - */ - public function isDoRemoveDeprecatedScriptCharsetAttribute(): bool - { - return $this->doRemoveDeprecatedScriptCharsetAttribute; - } - - /** - * @return bool - */ - public function isDoRemoveDeprecatedTypeFromScriptTag(): bool - { - return $this->doRemoveDeprecatedTypeFromScriptTag; - } - - /** - * @return bool - */ - public function isDoRemoveDeprecatedTypeFromStylesheetLink(): bool - { - return $this->doRemoveDeprecatedTypeFromStylesheetLink; - } - - /** - * @return bool - */ - public function isDoRemoveDeprecatedTypeFromStyleAndLinkTag(): bool - { - return $this->doRemoveDeprecatedTypeFromStyleAndLinkTag; - } - - /** - * @return bool - */ - public function isDoRemoveDefaultMediaTypeFromStyleAndLinkTag(): bool - { - return $this->doRemoveDefaultMediaTypeFromStyleAndLinkTag; - } - - /** - * @return bool - */ - public function isDoRemoveDefaultTypeFromButton(): bool - { - return $this->doRemoveDefaultTypeFromButton; - } - - /** - * @return bool - */ - public function isDoRemoveEmptyAttributes(): bool - { - return $this->doRemoveEmptyAttributes; - } - - /** - * @return bool - */ - public function isDoRemoveHttpPrefixFromAttributes(): bool - { - return $this->doRemoveHttpPrefixFromAttributes; - } - - /** - * @return bool - */ - public function isDoRemoveHttpsPrefixFromAttributes(): bool - { - return $this->doRemoveHttpsPrefixFromAttributes; - } - - /** - * @return bool - */ - public function isdoKeepHttpAndHttpsPrefixOnExternalAttributes(): bool - { - return $this->doKeepHttpAndHttpsPrefixOnExternalAttributes; - } - - /** - * @return bool - */ - public function isDoMakeSameDomainsLinksRelative(): bool - { - return $this->doMakeSameDomainsLinksRelative; - } - - /** - * @return bool - */ - public function isDoRemoveOmittedHtmlTags(): bool - { - return $this->doRemoveOmittedHtmlTags; - } - - /** - * @return bool - */ - public function isDoRemoveOmittedQuotes(): bool - { - return $this->doRemoveOmittedQuotes; - } - - /** - * @return bool - */ - public function isDoRemoveSpacesBetweenTags(): bool - { - return $this->doRemoveSpacesBetweenTags; - } - - /** - * @return bool - */ - public function isDoRemoveValueFromEmptyInput(): bool - { - return $this->doRemoveValueFromEmptyInput; - } - - /** - * @return bool - */ - public function isDoRemoveWhitespaceAroundTags(): bool - { - return $this->doRemoveWhitespaceAroundTags; - } - - /** - * @return bool - */ - public function isDoSortCssClassNames(): bool - { - return $this->doSortCssClassNames; - } - - /** - * @return bool - */ - public function isDoSortHtmlAttributes(): bool - { - return $this->doSortHtmlAttributes; - } - - /** - * @return bool - */ - public function isDoSumUpWhitespace(): bool - { - return $this->doSumUpWhitespace; - } - - /** - * @return bool - */ - public function isHTML4(): bool - { - return $this->isHTML4; - } - - /** - * @return bool - */ - public function isXHTML(): bool - { - return $this->isXHTML; - } - - /** - * @param string $html - * @param bool $multiDecodeNewHtmlEntity - * - * @return string - */ - public function minify($html, $multiDecodeNewHtmlEntity = false): string - { - $html = (string) $html; - if (!isset($html[0])) { - return ''; - } - - $html = \trim($html); - if (!$html) { - return ''; - } - - // reset - $this->protectedChildNodes = []; - - // save old content - $origHtml = $html; - $origHtmlLength = \strlen($html); - - // ------------------------------------------------------------------------- - // Minify the HTML via "HtmlDomParser" - // ------------------------------------------------------------------------- - - if ($this->doOptimizeViaHtmlDomParser) { - $html = $this->minifyHtmlDom($html, $multiDecodeNewHtmlEntity); - } - - // ------------------------------------------------------------------------- - // Trim whitespace from html-string. [protected html is still protected] - // ------------------------------------------------------------------------- - - // Remove extra white-space(s) between HTML attribute(s) - if (\strpos($html, ' ') !== false) { - $htmlCleaned = \preg_replace_callback( - '#<([^/\s<>!]+)(?:\s+([^<>]*?)\s*|\s*)(/?)>#', - static function ($matches) { - return '<' . $matches[1] . \preg_replace('#([^\s=]+)(=([\'"]?)(.*?)\3)?(\s+|$)#su', ' $1$2', $matches[2]) . $matches[3] . '>'; - }, - $html - ); - if ($htmlCleaned !== null) { - $html = (string)$htmlCleaned; - } else { - $htmlCleaned = (string) \preg_replace_callback( - '#<([^/\s<>!]+)(?:\s+([^<>]*)\s*|\s*)(/?)>#', - static function ($matches) { - return '<' . $matches[1] . \preg_replace('#([^\s=]+)(=([\'"]?)(.*?)\3)?(\s+|$)#su', ' $1$2', $matches[2]) . $matches[3] . '>'; - }, - $html - ); - $html = $htmlCleaned; - } - } - - if ($this->doRemoveSpacesBetweenTags) { - /** @noinspection NestedPositiveIfStatementsInspection */ - if (\strpos($html, ' ') !== false) { - // Remove spaces that are between > and < - $html = (string) \preg_replace('#(>)\s(<)#', '>$2', $html); - } - } - - // ------------------------------------------------------------------------- - // Restore protected HTML-code. - // ------------------------------------------------------------------------- - - if (\strpos($html, $this->protectedChildNodesHelper) !== false) { - $html = (string) \preg_replace_callback( - '/<(?' . $this->protectedChildNodesHelper . ')(? [^>]*)?>(?.*?)<\/' . $this->protectedChildNodesHelper . '>/', - [$this, 'restoreProtectedHtml'], - $html - ); - } - - // ------------------------------------------------------------------------- - // Restore protected HTML-entities. - // ------------------------------------------------------------------------- - - if ($this->doOptimizeViaHtmlDomParser) { - $html = HtmlDomParser::putReplacedBackToPreserveHtmlEntities($html); - } - - // ------------------------------------ - // Final clean-up - // ------------------------------------ - - $html = \str_replace( - [ - 'html>' . "\n", - "\n" . '' . "\n", - "\n" . '' . "\n", - "\n" . '' . "\n", - "\n" . '', - '', - '', - '', - ''; - $replacement[] = '<' . $selfClosingTag . '>'; - $replace[] = '<' . $selfClosingTag . ' />'; - $replacement[] = '<' . $selfClosingTag . '>'; - $replace[] = '>'; - $replacement[] = '>'; - } - $html = \str_replace( - $replace, - $replacement, - $html - ); - - // ------------------------------------ - // check if compression worked - // ------------------------------------ - - if ($origHtmlLength < \strlen($html)) { - $html = $origHtml; - } - - return $html; - } - - /** - * @param \DOMNode $node - * - * @return \DOMNode|null - */ - protected function getNextSiblingOfTypeDOMElement(\DOMNode $node) - { - do { - /** @var \DOMElement|\DOMText|null $nodeTmp - false-positive error from phpstan */ - $nodeTmp = $node->nextSibling; - - if ($nodeTmp instanceof \DOMText) { - if ( - \trim($nodeTmp->textContent) !== '' - && - \strpos($nodeTmp->textContent, '<') === false - ) { - $node = $nodeTmp; - } else { - $node = $nodeTmp->nextSibling; - } - } else { - $node = $nodeTmp; - } - } while (!($node === null || $node instanceof \DOMElement || $node instanceof \DOMText)); - - return $node; - } - - /** - * Check if the current string is an conditional comment. - * - * INFO: since IE >= 10 conditional comment are not working anymore - * - * - * HTML - * - * @param string $comment - * - * @return bool - */ - private function isConditionalComment($comment): bool - { - if (\strpos($comment, '[if ') !== false) { - /** @noinspection RegExpRedundantEscape */ - /** @noinspection NestedPositiveIfStatementsInspection */ - if (\preg_match('/^\[if [^\]]+\]/', $comment)) { - return true; - } - } - - if (\strpos($comment, '[endif]') !== false) { - /** @noinspection RegExpRedundantEscape */ - /** @noinspection NestedPositiveIfStatementsInspection */ - if (\preg_match('/\[endif\]$/', $comment)) { - return true; - } - } - - return false; - } - - /** - * Check if the current string is an special comment. - * - * @param string $comment - * - * @return bool - */ - private function isSpecialComment($comment): bool - { - foreach ($this->specialHtmlCommentsStaringWith as $search) { - if (\strpos($comment, $search) === 0) { - return true; - } - } - - foreach ($this->specialHtmlCommentsEndingWith as $search) { - if (\substr($comment, -\strlen($search)) === $search) { - return true; - } - } - - return false; - } - - /** - * @param string $html - * @param bool $multiDecodeNewHtmlEntity - * - * @return string - */ - private function minifyHtmlDom($html, $multiDecodeNewHtmlEntity): string - { - // init dom - $dom = new HtmlDomParser(); - $dom->useKeepBrokenHtml($this->keepBrokenHtml); - - if ($this->templateLogicSyntaxInSpecialScriptTags !== null) { - $dom->overwriteTemplateLogicSyntaxInSpecialScriptTags($this->templateLogicSyntaxInSpecialScriptTags); - } - - if ($this->specialScriptTags !== null) { - $dom->overwriteSpecialScriptTags($this->specialScriptTags); - } - - $dom->getDocument()->preserveWhiteSpace = false; // remove redundant white space - $dom->getDocument()->formatOutput = false; // do not formats output with indentation - - // Remove content before because otherwise the DOMDocument can not handle the input. - if (\stripos($html, ']*)?>/sui', $html, $matches_before_doctype) - && - \trim($matches_before_doctype[1]) - ) { - $html = \str_replace($matches_before_doctype[1], '', $html); - } - } - - // load dom - $dom->loadHtml($html); - - $this->withDocType = (\stripos($html, 'getDoctype($dom->getDocument()); - - if ($doctypeStr) { - $this->isHTML4 = \strpos($doctypeStr, 'html4') !== false; - $this->isXHTML = \strpos($doctypeStr, 'xhtml1') !== false; - } - - // ------------------------------------------------------------------------- - // Protect HTML tags first. - // ------------------------------------------------------------------------- - - $dom = $this->protectTagHelper($dom, 'nocompress'); - - // ------------------------------------------------------------------------- - // Notify the Observer before the minification. - // ------------------------------------------------------------------------- - - foreach ($dom->findMulti('*') as $element) { - $this->notifyObserversAboutDomElementBeforeMinification($element); - } - - // ------------------------------------------------------------------------- - // Protect HTML tags and conditional comments. - // ------------------------------------------------------------------------- - - $dom = $this->protectTags($dom); - - // ------------------------------------------------------------------------- - // Remove default HTML comments. [protected html is still protected] - // ------------------------------------------------------------------------- - - if ($this->doRemoveComments) { - $dom = $this->removeComments($dom); - } - - // ------------------------------------------------------------------------- - // Sum-Up extra whitespace from the Dom. [protected html is still protected] - // ------------------------------------------------------------------------- - - if ($this->doSumUpWhitespace) { - $dom = $this->sumUpWhitespace($dom); - } - - foreach ($dom->findMulti('*') as $element) { - // ------------------------------------------------------------------------- - // Remove whitespace around tags. [protected html is still protected] - // ------------------------------------------------------------------------- - - if ($this->doRemoveWhitespaceAroundTags) { - $this->removeWhitespaceAroundTags($element); - } - - // ------------------------------------------------------------------------- - // Notify the Observer after the minification. - // ------------------------------------------------------------------------- - - $this->notifyObserversAboutDomElementAfterMinification($element); - } - - // ------------------------------------------------------------------------- - // Convert the Dom into a string. - // ------------------------------------------------------------------------- - - return $dom->fixHtmlOutput( - $doctypeStr . $this->domNodeToString($dom->getDocument()), - $multiDecodeNewHtmlEntity - ); - } - - /** - * @param SimpleHtmlDomInterface $domElement - * - * @return void - */ - private function notifyObserversAboutDomElementAfterMinification(SimpleHtmlDomInterface $domElement) - { - foreach ($this->domLoopObservers as $observer) { - $observer->domElementAfterMinification($domElement, $this); - } - } - - /** - * @param SimpleHtmlDomInterface $domElement - * - * @return void - */ - private function notifyObserversAboutDomElementBeforeMinification(SimpleHtmlDomInterface $domElement) - { - foreach ($this->domLoopObservers as $observer) { - $observer->domElementBeforeMinification($domElement, $this); - } - } - - /** - * @param HtmlDomParser $dom - * @param string $selector - * - * @return HtmlDomParser - */ - private function protectTagHelper(HtmlDomParser $dom, string $selector): HtmlDomParser - { - foreach ($dom->findMulti($selector) as $element) { - if ($element->isRemoved()) { - continue; - } - - $parentNode = $element->parentNode(); - if ($parentNode->nodeValue !== null) { - $this->protectedChildNodes[$this->protected_tags_counter] = $parentNode->innerHtml(); - $parentNode->nodeValue = '<' . $this->protectedChildNodesHelper . ' data-' . $this->protectedChildNodesHelper . '="' . $this->protected_tags_counter . '">protectedChildNodesHelper . '>'; - } - - ++$this->protected_tags_counter; - } - - return $dom; - } - - /** - * Prevent changes of inline "styles" and "scripts". - * - * @param HtmlDomParser $dom - * - * @return HtmlDomParser - */ - private function protectTags(HtmlDomParser $dom): HtmlDomParser - { - $this->protectTagHelper($dom, 'code'); - - foreach ($dom->findMulti('script, style') as $element) { - if ($element->isRemoved()) { - continue; - } - - if ($element->tag === 'script' || $element->tag === 'style') { - $attributes = $element->getAllAttributes(); - // skip external links - if (isset($attributes['src'])) { - continue; - } - } - - $this->protectedChildNodes[$this->protected_tags_counter] = $element->innerhtml; - $element->getNode()->nodeValue = '<' . $this->protectedChildNodesHelper . ' data-' . $this->protectedChildNodesHelper . '="' . $this->protected_tags_counter . '">protectedChildNodesHelper . '>'; - - ++$this->protected_tags_counter; - } - - foreach ($dom->findMulti('//comment()') as $element) { - if ($element->isRemoved()) { - continue; - } - - $text = $element->text(); - - if ( - !$this->isConditionalComment($text) - && - !$this->isSpecialComment($text) - ) { - continue; - } - - $this->protectedChildNodes[$this->protected_tags_counter] = ''; - - /* @var $node \DOMComment */ - $node = $element->getNode(); - $child = new \DOMText('<' . $this->protectedChildNodesHelper . ' data-' . $this->protectedChildNodesHelper . '="' . $this->protected_tags_counter . '">protectedChildNodesHelper . '>'); - $parentNode = $element->getNode()->parentNode; - if ($parentNode !== null) { - $parentNode->replaceChild($child, $node); - } - - ++$this->protected_tags_counter; - } - - return $dom; - } - - /** - * Remove comments in the dom. - * - * @param HtmlDomParser $dom - * - * @return HtmlDomParser - */ - private function removeComments(HtmlDomParser $dom): HtmlDomParser - { - foreach ($dom->findMulti('//comment()') as $commentWrapper) { - $comment = $commentWrapper->getNode(); - $val = $comment->nodeValue; - if (\strpos($val, '[') === false) { - $parentNode = $comment->parentNode; - if ($parentNode !== null) { - $parentNode->removeChild($comment); - } - } - } - - $dom->getDocument()->normalizeDocument(); - - return $dom; - } - - /** - * Trim tags in the dom. - * - * @param SimpleHtmlDomInterface $element - * - * @return void - */ - private function removeWhitespaceAroundTags(SimpleHtmlDomInterface $element) - { - if (isset(self::$trimWhitespaceFromTags[$element->tag])) { - $node = $element->getNode(); - - /** @var \DOMNode[] $candidates */ - $candidates = []; - if ($node->childNodes->length > 0) { - $candidates[] = $node->firstChild; - $candidates[] = $node->lastChild; - $candidates[] = $node->previousSibling; - $candidates[] = $node->nextSibling; - } - - /** @var mixed $candidate - false-positive error from phpstan */ - foreach ($candidates as &$candidate) { - if ($candidate === null) { - continue; - } - - if ($candidate->nodeType === \XML_TEXT_NODE) { - $nodeValueTmp = \preg_replace(self::$regExSpace, ' ', $candidate->nodeValue); - if ($nodeValueTmp !== null) { - $candidate->nodeValue = $nodeValueTmp; - } - } - } - } - } - - /** - * Callback function for preg_replace_callback use. - * - * @param array $matches PREG matches - * - * @return string - */ - private function restoreProtectedHtml($matches): string - { - \preg_match('/.*"(?\d*)"/', $matches['attributes'], $matchesInner); - - return $this->protectedChildNodes[$matchesInner['id']] ?? ''; - } - - /** - * @param string[] $domainsToRemoveHttpPrefixFromAttributes - * - * @return $this - */ - public function setDomainsToRemoveHttpPrefixFromAttributes($domainsToRemoveHttpPrefixFromAttributes): self - { - $this->domainsToRemoveHttpPrefixFromAttributes = $domainsToRemoveHttpPrefixFromAttributes; - - return $this; - } - - /** - * @param string[] $startingWith - * @param string[] $endingWith - * - * @return $this - */ - public function setSpecialHtmlComments(array $startingWith, array $endingWith = []): self - { - $this->specialHtmlCommentsStaringWith = $startingWith; - $this->specialHtmlCommentsEndingWith = $endingWith; - - return $this; - } - - /** - * Sum-up extra whitespace from dom-nodes. - * - * @param HtmlDomParser $dom - * - * @return HtmlDomParser - */ - private function sumUpWhitespace(HtmlDomParser $dom): HtmlDomParser - { - foreach ($dom->findMulti('//text()') as $text_node_wrapper) { - /* @var $text_node \DOMNode */ - $text_node = $text_node_wrapper->getNode(); - $xp = $text_node->getNodePath(); - if ($xp === null) { - continue; - } - - $doSkip = false; - foreach (self::$skipTagsForRemoveWhitespace as $pattern) { - if (\strpos($xp, '/' . $pattern) !== false) { - $doSkip = true; - - break; - } - } - if ($doSkip) { - continue; - } - - $nodeValueTmp = \preg_replace(self::$regExSpace, ' ', $text_node->nodeValue); - if ($nodeValueTmp !== null) { - $text_node->nodeValue = $nodeValueTmp; - } - } - - $dom->getDocument()->normalizeDocument(); - - return $dom; - } - - /** - * WARNING: maybe bad for performance ... - * - * @param bool $keepBrokenHtml - * - * @return HtmlMin - */ - public function useKeepBrokenHtml(bool $keepBrokenHtml): self - { - $this->keepBrokenHtml = $keepBrokenHtml; - - return $this; - } - - /** - * @param string[] $templateLogicSyntaxInSpecialScriptTags - * - * @return HtmlMin - */ - public function overwriteTemplateLogicSyntaxInSpecialScriptTags(array $templateLogicSyntaxInSpecialScriptTags): self - { - foreach ($templateLogicSyntaxInSpecialScriptTags as $tmp) { - if (!\is_string($tmp)) { - throw new \InvalidArgumentException('setTemplateLogicSyntaxInSpecialScriptTags only allows string[]'); - } - } - - $this->templateLogicSyntaxInSpecialScriptTags = $templateLogicSyntaxInSpecialScriptTags; - - return $this; - } - - - /** - * @param string[] $specialScriptTags - * - * @return HtmlDomParser - */ - public function overwriteSpecialScriptTags(array $specialScriptTags): self - { - foreach ($specialScriptTags as $tag) { - if (!\is_string($tag)) { - throw new \InvalidArgumentException('SpecialScriptTags only allows string[]'); - } - } - - $this->specialScriptTags = $specialScriptTags; - - return $this; - } -} diff --git a/includes/classes/Dependencies/voku/helper/HtmlMinDomObserverInterface.php b/includes/classes/Dependencies/voku/helper/HtmlMinDomObserverInterface.php deleted file mode 100644 index ead6eea..0000000 --- a/includes/classes/Dependencies/voku/helper/HtmlMinDomObserverInterface.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ - private static $executableScriptsMimeTypes = [ - 'text/javascript' => '', - 'text/ecmascript' => '', - 'text/jscript' => '', - 'application/javascript' => '', - 'application/x-javascript' => '', - 'application/ecmascript' => '', - ]; - - /** - * Receive dom elements before the minification. - * - * @param SimpleHtmlDomInterface $element - * @param HtmlMinInterface $htmlMin - * - * @return void - */ - public function domElementBeforeMinification(SimpleHtmlDomInterface $element, HtmlMinInterface $htmlMin) - { - } - - /** - * Receive dom elements after the minification. - * - * @param SimpleHtmlDomInterface $element - * @param HtmlMinInterface $htmlMin - * - * @return void - */ - public function domElementAfterMinification(SimpleHtmlDomInterface $element, HtmlMinInterface $htmlMin) - { - $attributes = $element->getAllAttributes(); - if ($attributes === null) { - return; - } - - $tagName = $element->getNode()->nodeName; - $attrs = []; - foreach ((array) $attributes as $attrName => $attrValue) { - // ------------------------------------------------------------------------- - // Remove local domains from attributes. - // ------------------------------------------------------------------------- - - if ($htmlMin->isDoMakeSameDomainsLinksRelative()) { - $localDomains = $htmlMin->getLocalDomains(); - foreach ($localDomains as $localDomain) { - /** @noinspection InArrayCanBeUsedInspection */ - if ( - ( - $attrName === 'href' - || - $attrName === 'src' - || - $attrName === 'srcset' - || - $attrName === 'action' - ) - && - !(isset($attributes['rel']) && $attributes['rel'] === 'external') - && - !(isset($attributes['target']) && $attributes['target'] === '_blank') - && - \stripos($attrValue, $localDomain) !== false - ) { - $localDomainEscaped = \preg_quote($localDomain, '/'); - - $attrValue = (string) \preg_replace("/^(?:(?:https?:)?\/\/)?{$localDomainEscaped}(?!\w)(?:\/?)/i", '/', $attrValue); - } - } - } - - // ------------------------------------------------------------------------- - // Remove optional "http:"-prefix from attributes. - // ------------------------------------------------------------------------- - - if ($htmlMin->isDoRemoveHttpPrefixFromAttributes()) { - $attrValue = $this->removeUrlSchemeHelper( - $attrValue, - $attrName, - 'http', - $attributes, - $tagName, - $htmlMin - ); - } - - if ($htmlMin->isDoRemoveHttpsPrefixFromAttributes()) { - $attrValue = $this->removeUrlSchemeHelper( - $attrValue, - $attrName, - 'https', - $attributes, - $tagName, - $htmlMin - ); - } - - // ------------------------------------------------------------------------- - // Remove some special attributes. - // ------------------------------------------------------------------------- - - if ($this->removeAttributeHelper( - $element->tag, - $attrName, - $attrValue, - $attributes, - $htmlMin - )) { - $element->{$attrName} = null; - - continue; - } - - // ------------------------------------------------------------------------- - // Sort css-class-Powered_Cache_names, for better gzip results. - // ------------------------------------------------------------------------- - - if ($htmlMin->isDoSortCssClassNames()) { - $attrValue = $this->sortCssClassNames($attrName, $attrValue); - } - - if ($htmlMin->isDoSortHtmlAttributes()) { - $attrs[$attrName] = $attrValue; - $element->{$attrName} = null; - } - } - - // ------------------------------------------------------------------------- - // Sort html-attributes, for better gzip results. - // ------------------------------------------------------------------------- - - if ($htmlMin->isDoSortHtmlAttributes()) { - \ksort($attrs); - foreach ($attrs as $attrName => $attrValue) { - $attrValue = HtmlDomParser::replaceToPreserveHtmlEntities($attrValue); - $element->setAttribute((string) $attrName, $attrValue, true); - } - } - } - - /** - * Check if the attribute can be removed. - * - * @param string $tag - * @param string $attrName - * @param string $attrValue - * @param array $allAttr - * @param HtmlMinInterface $htmlMin - * - * @return bool - */ - private function removeAttributeHelper($tag, $attrName, $attrValue, $allAttr, HtmlMinInterface $htmlMin): bool - { - // remove defaults - if ($htmlMin->isDoRemoveDefaultAttributes()) { - if ($tag === 'script' && $attrName === 'language' && $attrValue === 'javascript') { - return true; - } - - if ($tag === 'form' && $attrName === 'method' && $attrValue === 'get') { - return true; - } - - if ($tag === 'form' && $attrName === 'autocomplete' && $attrValue === 'on') { - return true; - } - - if ($tag === 'form' && $attrName === 'enctype' && $attrValue === 'application/x-www-form-urlencoded') { - return true; - } - - if ($tag === 'input' && $attrName === 'type' && $attrValue === 'text') { - return true; - } - - if ($tag === 'textarea' && $attrName === 'wrap' && $attrValue === 'soft') { - return true; - } - - if ($tag === 'area' && $attrName === 'shape' && $attrValue === 'rect') { - return true; - } - - if ($tag === 'th' && $attrName === 'scope' && $attrValue === 'auto') { - return true; - } - - if ($tag === 'ol' && $attrName === 'type' && $attrValue === 'decimal') { - return true; - } - - if ($tag === 'ol' && $attrName === 'start' && $attrValue === '1') { - return true; - } - - if ($tag === 'track' && $attrName === 'kind' && $attrValue === 'subtitles') { - return true; - } - - if ($attrName === 'spellcheck' && $attrValue === 'default') { - return true; - } - - if ($attrName === 'draggable' && $attrValue === 'auto') { - return true; - } - } - - // remove deprecated charset-attribute (the browser will use the charset from the HTTP-Header, anyway) - if ($htmlMin->isDoRemoveDeprecatedScriptCharsetAttribute()) { - /** @noinspection NestedPositiveIfStatementsInspection */ - if ($tag === 'script' && $attrName === 'charset' && !isset($allAttr['src'])) { - return true; - } - } - - // remove deprecated anchor-jump - if ($htmlMin->isDoRemoveDeprecatedAnchorName()) { - /** @noinspection NestedPositiveIfStatementsInspection */ - if ($tag === 'a' && $attrName === 'name' && isset($allAttr['id']) && $allAttr['id'] === $attrValue) { - return true; - } - } - - if ($htmlMin->isDoRemoveDefaultMediaTypeFromStyleAndLinkTag()) { - /** @noinspection NestedPositiveIfStatementsInspection */ - if (($tag === 'link' || $tag === 'style') && $attrName === 'media' && $attrValue === 'all') { - return true; - } - } - - // remove "type=text/css" for css "stylesheet"-links - if ($htmlMin->isDoRemoveDeprecatedTypeFromStylesheetLink()) { - /** @noinspection NestedPositiveIfStatementsInspection */ - if ($tag === 'link' && $attrName === 'type' && $attrValue === 'text/css' && isset($allAttr['rel']) && $allAttr['rel'] === 'stylesheet' && $htmlMin->isXHTML() === false && $htmlMin->isHTML4() === false) { - return true; - } - } - // remove deprecated css-mime-types - if ($htmlMin->isDoRemoveDeprecatedTypeFromStyleAndLinkTag()) { - /** @noinspection NestedPositiveIfStatementsInspection */ - if (($tag === 'link' || $tag === 'style') && $attrName === 'type' && $attrValue === 'text/css' && $htmlMin->isXHTML() === false && $htmlMin->isHTML4() === false) { - return true; - } - } - - // remove deprecated script-mime-types - if ($htmlMin->isDoRemoveDeprecatedTypeFromScriptTag()) { - /** @noinspection NestedPositiveIfStatementsInspection */ - if ($tag === 'script' && $attrName === 'type' && isset(self::$executableScriptsMimeTypes[$attrValue]) && $htmlMin->isXHTML() === false && $htmlMin->isHTML4() === false) { - return true; - } - } - - // remove 'type=submit' from