diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 000000000..74e660ba7 --- /dev/null +++ b/lib/.gitignore @@ -0,0 +1,28 @@ +# TCPDF +/combodo/tcpdf/examples +/combodo/tcpdf/tools +/combodo/tcpdf/fonts +!/combodo/tcpdf/fonts/courier* +!/combodo/tcpdf/fonts/dejavusans* +!/combodo/tcpdf/fonts/droidsansfallback* +!/combodo/tcpdf/fonts/helvetica* +!/combodo/tcpdf/fonts/symbol.php +!/combodo/tcpdf/fonts/times* +!/combodo/tcpdf/fonts/zapfdingbats.php + +# Emogrifier +/pelago/emogrifier/.github +/pelago/emogrifier/tests + +# SCSSPHP +/scssphp/scssphp/example + +# SwiftMailer +/swiftmailer/swiftmailer/.github +/swiftmailer/swiftmailer/doc +/swiftmailer/swiftmailer/tests + +# TWIG +/twig/twig/doc +/twig/twig/test +/twig/twig/drupal_test.sh \ No newline at end of file diff --git a/lib/pelago/emogrifier/.github/CONTRIBUTING.md b/lib/pelago/emogrifier/.github/CONTRIBUTING.md deleted file mode 100644 index 6287d6549..000000000 --- a/lib/pelago/emogrifier/.github/CONTRIBUTING.md +++ /dev/null @@ -1,129 +0,0 @@ -# Contributing to Emogrifier - -Those that wish to contribute bug fixes, new features, refactorings and -clean-up to Emogrifier are more than welcome. - -When you contribute, please take the following things into account: - - -## Contributor Code of Conduct - -Please note that this project is released with a -[Contributor Code of Conduct](../CODE_OF_CONDUCT.md). By participating in this -project, you agree to abide by its terms. - - -## General workflow - -This is the workflow for contributing changes to Emogrifier: - -1. [Fork the Emogrifier Git repository](https://guides.github.com/activities/forking/). -2. Clone your forked repository and - [install the development dependencies](#install-the-development-dependencies). -3. Add a local remote "upstream" so you will be able to - [synchronize your fork with the original Emogrifier repository](https://help.github.com/articles/syncing-a-fork/). -4. Create a local branch for your changes. -5. [Add unit tests for your changes](#unit-test-your-changes). - These tests should fail without your changes. -6. Add your changes. Your added unit tests now should pass, and no other tests - should be broken. Check that your changes follow the same - [coding style](#coding-style) as the rest of the project. -7. Add a changelog entry. -8. [Commit](#git-commits) and push your changes. -9. [Create a pull request](https://help.github.com/articles/about-pull-requests/) - for your changes. Check that the Travis build is green. (If it is not, fix the - problems listed by Travis.) -10. [Request a review](https://help.github.com/articles/about-pull-request-reviews/) - from @oliverklee. -11. Together with him, polish your changes until they are ready to be merged. - - -## About code reviews - -After you have submitted a pull request, the Emogrifier team will review your -changes. This will probably result in quite a few comments on ways to improve -your pull request. The Emogrifier project receives contributions from -developers around the world, so we need the code to be the most consistent, -readable, and maintainable that it can be. - -Please do not feel frustrated by this - instead please view this both as our -contribution to your pull request as well as a way to learn more about -improving code quality. - -If you would like to know whether an idea would fit in the general strategy of -the Emogrifier project or would like to get feedback on the best architecture -for your ideas, we propose you open a ticket first and discuss your ideas there -first before investing a lot of time in writing code. - - -## Install the development dependencies - -To install the development dependencies (PHPUnit and PHP_CodeSniffer), please -run the following commands: - -```shell -composer install -composer require --dev slevomat/coding-standard:^4.0 -``` - -Note that the development dependencies (in particular, for PHP_CodeSniffer) -require PHP 7.0 or later. The second command installs the PHP_CodeSniffer -dependencies and should be omitted if specifically testing against an earlier -version of PHP, however you will not be able to run the static code analysis. - - -## Unit-test your changes - -Please cover all changes with unit tests and make sure that your code does not -break any existing tests. We will only merge pull requests that include full -code coverage of the fixed bugs and the new features. - -To run the existing PHPUnit tests, run this command: - -```shell -composer ci:tests:unit -``` - - -## Coding Style - -Please use the same coding style (PSR-2) as the rest of the code. Indentation -is four spaces. - -We will only merge pull requests that follow the project's coding style. - -Please check your code with the provided static code analysis tools: - -```shell -composer ci:static -``` - -Please make your code clean, well-readable and easy to understand. - -If you add new methods or fields, please add proper PHPDoc for the new -methods/fields. Please use grammatically correct, complete sentences in the -code documentation. - -You can autoformat your code using the following command: - -```shell -composer php:fix -``` - - -## Git commits - -Commit message should have a <= 50 character summary, optionally followed by a -blank line and a more in depth description of 79 characters per line. - -Please use grammatically correct, complete sentences in the commit messages. - -Also, please prefix the subject line of the commit message with either -[FEATURE], [TASK], [BUGFIX] OR [CLEANUP]. This makes it faster to see what -a commit is about. - - -## Creating pull requests (PRs) - -When you create a pull request, please -[make your PR editable](https://github.com/blog/2247-improving-collaboration-with-forks). diff --git a/lib/pelago/emogrifier/tests/Support/Traits/AssertCss.php b/lib/pelago/emogrifier/tests/Support/Traits/AssertCss.php deleted file mode 100644 index 959ee6411..000000000 --- a/lib/pelago/emogrifier/tests/Support/Traits/AssertCss.php +++ /dev/null @@ -1,100 +0,0 @@ - - */ -trait AssertCss -{ - /** - * Processing of @media rules may involve removal of some unnecessary whitespace from the CSS placed in the

target

' - ); - - $result = $subject->emogrify(); - - static::assertContains('

target

', $result); - } - - /** - * @test - */ - public function emogrifyRemovesStyleNodes() - { - $subject = $this->buildDebugSubject(''); - - $result = $subject->emogrify(); - - static::assertNotContains('' - ); - $subject->setDebug(true); - - $subject->emogrify(); - } - - /** - * @test - */ - public function emogrifyNotInDebugModeIgnoresInvalidCssSelectors() - { - $html = ' ' . - '

'; - $subject = new CssInliner($html); - $subject->setDebug(false); - - $html = $subject->emogrify(); - - static::assertContains('color: red', $html); - static::assertContains('background-color: blue', $html); - } - - /** - * @test - */ - public function emogrifyByDefaultIgnoresInvalidCssSelectors() - { - $html = ' ' . - '

'; - $subject = new CssInliner($html); - - $html = $subject->emogrify(); - static::assertContains('color: red', $html); - static::assertContains('background-color: blue', $html); - } - - /** - * Data provider for things that should be left out when applying the CSS. - * - * @return string[][] - */ - public function unneededCssThingsDataProvider() - { - return [ - 'CSS comments with one asterisk' => ['p {color: #000;/* black */}', 'black'], - 'CSS comments with two asterisks' => ['p {color: #000;/** black */}', 'black'], - '@import directive' => ['@import "foo.css";', '@import'], - 'two @import directives, minified' => ['@import "foo.css";@import "bar.css";', '@import'], - '@charset directive' => ['@charset "UTF-8";', '@charset'], - 'style in "aural" media type rule' => ['@media aural {p {color: #000;}}', '#000'], - 'style in "braille" media type rule' => ['@media braille {p {color: #000;}}', '#000'], - 'style in "embossed" media type rule' => ['@media embossed {p {color: #000;}}', '#000'], - 'style in "handheld" media type rule' => ['@media handheld {p {color: #000;}}', '#000'], - 'style in "projection" media type rule' => ['@media projection {p {color: #000;}}', '#000'], - 'style in "speech" media type rule' => ['@media speech {p {color: #000;}}', '#000'], - 'style in "tty" media type rule' => ['@media tty {p {color: #000;}}', '#000'], - 'style in "tv" media type rule' => ['@media tv {p {color: #000;}}', '#000'], - 'style in "tv" media type rule with extra spaces' => [ - ' @media tv { p { color : #000 ; } } ', - '#000', - ], - 'style in "tv" media type rule with linefeeds' => [ - "\n@media\ntv\n{\np\n{\ncolor\n:\n#000\n;\n}\n}\n", - '#000', - ], - 'style in "tv" media type rule with Windows line endings' => [ - "\r\n@media\r\ntv\r\n{\r\np\r\n{\r\ncolor\r\n:\r\n#000\r\n;\r\n}\r\n}\r\n", - '#000', - ], - 'style in "only tv" media type rule' => ['@media only tv {p {color: #000;}}', '#000'], - 'style in "only tv" media type rule with extra spaces' => [ - ' @media only tv { p { color : #000 ; } } ', - '#000', - ], - 'style in "only tv" media type rule with linefeeds' => [ - "\n@media\nonly\ntv\n{\np\n{\ncolor\n:\n#000\n;\n}\n}\n", - '#000', - ], - 'style in "only tv" media type rule with Windows line endings' => [ - "\r\n@media\r\nonly\r\ntv\r\n{\r\np\r\n{\r\ncolor\r\n:\r\n#000\r\n;\r\n}\r\n}\r\n", - '#000', - ], - ]; - } - - /** - * @test - * - * @param string $unneededCss - * @param string $markerNotExpectedInHtml - * - * @dataProvider unneededCssThingsDataProvider - */ - public function emogrifyFiltersUnneededCssThings($unneededCss, $markerNotExpectedInHtml) - { - $subject = $this->buildDebugSubject('

foo

'); - $subject->setCss($unneededCss); - - $result = $subject->emogrify(); - - static::assertNotContains($markerNotExpectedInHtml, $result); - } - - /** - * @test - * - * @param string $unneededCss - * - * @dataProvider unneededCssThingsDataProvider - */ - public function emogrifyMatchesRuleAfterUnneededCssThing($unneededCss) - { - $subject = $this->buildDebugSubject(''); - $subject->setCss($unneededCss . ' body { color: green; }'); - - $result = $subject->emogrify(); - - static::assertContains('', $result); - } - - /** - * Data provider for media rules. - * - * @return string[][] - */ - public function mediaRulesDataProvider() - { - return [ - 'style in "only all" media type rule' => ['@media only all {p {color: #000;}}'], - 'style in "only screen" media type rule' => ['@media only screen {p {color: #000;}}'], - 'style in "only screen" media type rule with extra spaces' - => [' @media only screen { p { color : #000; } } '], - 'style in "only screen" media type rule with linefeeds' - => ["\n@media\nonly\nscreen\n{\np\n{\ncolor\n:\n#000;\n}\n}\n"], - 'style in "only screen" media type rule with Windows line endings' - => ["\r\n@media\r\nonly\r\nscreen\r\n{\r\np\r\n{\r\ncolor\r\n:\r\n#000;\r\n}\r\n}\r\n"], - 'style in media type rule' => ['@media {p {color: #000;}}'], - 'style in media type rule with extra spaces' => [' @media { p { color : #000; } } '], - 'style in media type rule with linefeeds' => ["\n@media\n{\np\n{\ncolor\n:\n#000;\n}\n}\n"], - 'style in media type rule with Windows line endings' - => ["\r\n@media\r\n{\r\np\r\n{\r\ncolor\r\n:\r\n#000;\r\n}\r\n}\r\n"], - 'style in "screen" media type rule' => ['@media screen {p {color: #000;}}'], - 'style in "screen" media type rule with extra spaces' - => [' @media screen { p { color : #000; } } '], - 'style in "screen" media type rule with linefeeds' - => ["\n@media\nscreen\n{\np\n{\ncolor\n:\n#000;\n}\n}\n"], - 'style in "screen" media type rule with Windows line endings' - => ["\r\n@media\r\nscreen\r\n{\r\np\r\n{\r\ncolor\r\n:\r\n#000;\r\n}\r\n}\r\n"], - 'style in "print" media type rule' => ['@media print {p {color: #000;}}'], - 'style in "all" media type rule' => ['@media all {p {color: #000;}}'], - ]; - } - - /** - * @test - * - * @param string $css - * - * @dataProvider mediaRulesDataProvider - */ - public function emogrifyKeepsMediaRules($css) - { - $subject = $this->buildDebugSubject('

foo

'); - $subject->setCss($css); - - $result = $subject->emogrify(); - - static::assertContainsCss($css, $result); - } - - /** - * @return string[][] - */ - public function orderedRulesAndSurroundingCssDataProvider() - { - $possibleSurroundingCss = [ - 'nothing' => '', - 'space' => ' ', - 'linefeed' => "\n", - 'Windows line ending' => "\r\n", - 'comment' => '/* hello */', - 'other non-matching CSS' => 'h6 { color: #f00; }', - 'other matching CSS' => 'p { color: #f00; }', - 'disallowed media rule' => '@media tv { p { color: #f00; } }', - 'allowed but non-matching media rule' => '@media screen { h6 { color: #f00; } }', - 'non-matching CSS with pseudo-component' => 'h6:hover { color: #f00; }', - ]; - $possibleCssBefore = $possibleSurroundingCss + [ - '@import' => '@import "foo.css";', - '@charset' => '@charset "UTF-8";', - ]; - - $datasetsSurroundingCss = []; - foreach ($possibleCssBefore as $descriptionBefore => $cssBefore) { - foreach ($possibleSurroundingCss as $descriptionBetween => $cssBetween) { - foreach ($possibleSurroundingCss as $descriptionAfter => $cssAfter) { - // every combination would be a ridiculous c.1000 datasets - choose a select few - // test all possible CSS before once - if (($cssBetween === '' && $cssAfter === '') - // test all possible CSS between once - || ($cssBefore === '' && $cssAfter === '') - // test all possible CSS after once - || ($cssBefore === '' && $cssBetween === '') - // test with each possible CSS in all three positions - || ($cssBefore === $cssBetween && $cssBetween === $cssAfter) - ) { - $description = ' with ' . $descriptionBefore . ' before, ' - . $descriptionBetween . ' between, ' - . $descriptionAfter . ' after'; - $datasetsSurroundingCss[$description] = [$cssBefore, $cssBetween, $cssAfter]; - } - } - } - } - - $datasets = []; - foreach ($datasetsSurroundingCss as $description => $datasetSurroundingCss) { - $datasets += [ - 'two media rules' . $description => \array_merge( - ['@media all { p { color: #333; } }', '@media print { p { color: #000; } }'], - $datasetSurroundingCss - ), - 'two rules involving pseudo-components' . $description => \array_merge( - ['a:hover { color: blue; }', 'a:active { color: green; }'], - $datasetSurroundingCss - ), - 'media rule followed by rule involving pseudo-components' . $description => \array_merge( - ['@media screen { p { color: #000; } }', 'a:hover { color: green; }'], - $datasetSurroundingCss - ), - 'rule involving pseudo-components followed by media rule' . $description => \array_merge( - ['a:hover { color: green; }', '@media screen { p { color: #000; } }'], - $datasetSurroundingCss - ), - ]; - } - return $datasets; - } - - /** - * @test - * - * @param string $rule1 - * @param string $rule2 - * @param string $cssBefore CSS to insert before the first rule - * @param string $cssBetween CSS to insert between the rules - * @param string $cssAfter CSS to insert after the second rule - * - * @dataProvider orderedRulesAndSurroundingCssDataProvider - */ - public function emogrifyKeepsRulesCopiedToStyleElementInSpecifiedOrder( - $rule1, - $rule2, - $cssBefore, - $cssBetween, - $cssAfter - ) { - $subject = $this->buildDebugSubject('

foo

'); - $subject->setCss($cssBefore . $rule1 . $cssBetween . $rule2 . $cssAfter); - - $result = $subject->emogrify(); - - static::assertContainsCss($rule1 . $rule2, $result); - } - - /** - * @test - */ - public function removeAllowedMediaTypeRemovesStylesForTheGivenMediaType() - { - $css = '@media screen { html { some-property: value; } }'; - $subject = $this->buildDebugSubject(''); - $subject->setCss($css); - $subject->removeAllowedMediaType('screen'); - - $result = $subject->emogrify(); - - static::assertNotContains('@media', $result); - } - - /** - * @test - */ - public function addAllowedMediaTypeKeepsStylesForTheGivenMediaType() - { - $css = '@media braille { html { some-property: value; } }'; - $subject = $this->buildDebugSubject(''); - $subject->setCss($css); - $subject->addAllowedMediaType('braille'); - - $result = $subject->emogrify(); - - static::assertContainsCss($css, $result); - } - - /** - * @test - */ - public function emogrifyKeepsExistingHeadElementContent() - { - $subject = $this->buildDebugSubject(''); - $subject->setCss('@media all { html { some-property: value; } }'); - - $result = $subject->emogrify(); - - static::assertContains('', $result); - } - - /** - * @test - */ - public function emogrifyAddsStyleElementToBody() - { - $html = $this->html5DocumentType . ''; - $subject = $this->buildDebugSubject($html); - $subject->setCss('@media all { html { some-property: value; } }'); - - $result = $subject->emogrify(); - - static::assertContains('', $result); - } - - /** - * @test - * - * @param string $css - * - * @dataProvider validMediaPreserveDataProvider - */ - public function emogrifyWithValidMinifiedMediaQueryContainsInnerCss($css) - { - // Minify CSS by removing unnecessary whitespace. - $css = \preg_replace('/\\s*{\\s*/', '{', $css); - $css = \preg_replace('/;?\\s*}\\s*/', '}', $css); - $css = \preg_replace('/@media{/', '@media {', $css); - - $subject = $this->buildDebugSubject('

'); - $subject->setCss($css); - - $result = $subject->emogrify(); - - static::assertContains('', $result); - } - - /** - * @test - * - * @param string $css - * - * @dataProvider validMediaPreserveDataProvider - */ - public function emogrifyForHtmlWithValidMediaQueryContainsInnerCss($css) - { - $subject = $this->buildDebugSubject('

'); - - $result = $subject->emogrify(); - - static::assertContainsCss('', $result); - } - - /** - * @test - * - * @param string $css - * - * @dataProvider validMediaPreserveDataProvider - */ - public function emogrifyWithValidMediaQueryNotContainsInlineCss($css) - { - $subject = $this->buildDebugSubject('

'); - $subject->setCss($css); - - $result = $subject->emogrify(); - - static::assertNotContains('style=', $result); - } - - /** - * Invalid media query which need to be strip - * - * @return string[][] - */ - public function invalidMediaPreserveDataProvider() - { - return [ - 'style in "braille" type rule' => ['@media braille { h1 { color:red; } }'], - 'style in "embossed" type rule' => ['@media embossed { h1 { color:red; } }'], - 'style in "handheld" type rule' => ['@media handheld { h1 { color:red; } }'], - 'style in "projection" type rule' => ['@media projection { h1 { color:red; } }'], - 'style in "speech" type rule' => ['@media speech { h1 { color:red; } }'], - 'style in "tty" type rule' => ['@media tty { h1 { color:red; } }'], - 'style in "tv" type rule' => ['@media tv { h1 { color:red; } }'], - ]; - } - - /** - * @test - * - * @param string $css - * - * @dataProvider invalidMediaPreserveDataProvider - */ - public function emogrifyWithInvalidMediaQueryNotContainsInnerCss($css) - { - $subject = $this->buildDebugSubject('

'); - $subject->setCss($css); - - $result = $subject->emogrify(); - - static::assertNotContainsCss($css, $result); - } - - /** - * @test - * - * @param string $css - * - * @dataProvider invalidMediaPreserveDataProvider - */ - public function emogrifyWithInvalidMediaQueryNotContainsInlineCss($css) - { - $subject = $this->buildDebugSubject('

'); - $subject->setCss($css); - - $result = $subject->emogrify(); - - static::assertNotContains('style=', $result); - } - - /** - * @test - * - * @param string $css - * - * @dataProvider invalidMediaPreserveDataProvider - */ - public function emogrifyFromHtmlWithInvalidMediaQueryNotContainsInnerCss($css) - { - $subject = $this->buildDebugSubject('

'); - - $result = $subject->emogrify(); - - static::assertNotContainsCss($css, $result); - } - - /** - * @test - * - * @param string $css - * - * @dataProvider invalidMediaPreserveDataProvider - */ - public function emogrifyFromHtmlWithInvalidMediaQueryNotContainsInlineCss($css) - { - $subject = $this->buildDebugSubject('

'); - - $result = $subject->emogrify(); - - static::assertNotContains('style=', $result); - } - - /** - * @test - */ - public function emogrifyIgnoresEmptyMediaQuery() - { - $subject = $this->buildDebugSubject('

'); - $subject->setCss('@media screen {} @media tv { h1 { color: red; } }'); - - $result = $subject->emogrify(); - - static::assertNotContains('style=', $result); - static::assertNotContains('@media screen', $result); - } - - /** - * @test - */ - public function emogrifyIgnoresMediaQueryWithWhitespaceOnly() - { - $subject = $this->buildDebugSubject('

'); - $subject->setCss('@media screen { } @media tv { h1 { color: red; } }'); - - $result = $subject->emogrify(); - - static::assertNotContains('style=', $result); - static::assertNotContains('@media screen', $result); - } - - /** - * @return string[][] - */ - public function mediaTypeDataProvider() - { - return [ - 'disallowed type' => ['tv'], - 'allowed type' => ['screen'], - ]; - } - - /** - * @test - * - * @param string $emptyRuleMediaType - * - * @dataProvider mediaTypeDataProvider - */ - public function emogrifyKeepsMediaRuleAfterEmptyMediaRule($emptyRuleMediaType) - { - $subject = $this->buildDebugSubject('

'); - $subject->setCss('@media ' . $emptyRuleMediaType . ' {} @media all { h1 { color: red; } }'); - - $result = $subject->emogrify(); - - static::assertContainsCss('@media all { h1 { color: red; } }', $result); - } - - /** - * @test - * - * @param string $emptyRuleMediaType - * - * @dataProvider mediaTypeDataProvider - */ - public function emogrifyNotKeepsUnneededMediaRuleAfterEmptyMediaRule($emptyRuleMediaType) - { - $subject = $this->buildDebugSubject('

'); - $subject->setCss('@media ' . $emptyRuleMediaType . ' {} @media speech { h1 { color: red; } }'); - - $result = $subject->emogrify(); - - static::assertNotContains('@media', $result); - } - - /** - * @param string[] $precedingSelectorComponents Array of selectors to which each type of pseudo-component is - * appended to create a selector for a CSS rule. - * Keys are human-readable descriptions. - * - * @return string[][] - */ - private function getCssRuleDatasetsWithSelectorPseudoComponents(array $precedingSelectorComponents) - { - $rulesComponents = [ - 'pseudo-element' => [ - 'selectorPseudoComponent' => '::after', - 'declarationsBlock' => 'content: "bar";', - ], - 'CSS2 pseudo-element' => [ - 'selectorPseudoComponent' => ':after', - 'declarationsBlock' => 'content: "bar";', - ], - 'hyphenated pseudo-element' => [ - 'selectorPseudoComponent' => '::first-letter', - 'declarationsBlock' => 'color: green;', - ], - 'pseudo-class' => [ - 'selectorPseudoComponent' => ':hover', - 'declarationsBlock' => 'color: green;', - ], - 'hyphenated pseudo-class' => [ - 'selectorPseudoComponent' => ':read-only', - 'declarationsBlock' => 'color: green;', - ], - 'pseudo-class with parameter' => [ - 'selectorPseudoComponent' => ':lang(en)', - 'declarationsBlock' => 'color: green;', - ], - ]; - - $datasets = []; - foreach ($precedingSelectorComponents as $precedingComponentDescription => $precedingSelectorComponent) { - foreach ($rulesComponents as $pseudoComponentDescription => $ruleComponents) { - $datasets[$precedingComponentDescription . ' ' . $pseudoComponentDescription] = [ - $precedingSelectorComponent . $ruleComponents['selectorPseudoComponent'] - . ' { ' . $ruleComponents['declarationsBlock'] . ' }', - ]; - } - } - return $datasets; - } - - /** - * @return string[][] - */ - public function matchingSelectorWithPseudoComponentCssRuleDataProvider() - { - $datasetsWithSelectorPseudoComponents = $this->getCssRuleDatasetsWithSelectorPseudoComponents( - [ - 'lone' => '', - 'type &' => 'a', - 'class &' => '.a', - 'ID &' => '#a', - 'attribute &' => 'a[href="a"]', - 'static pseudo-class &' => 'a:first-child', - 'ancestor &' => 'p ', - 'ancestor & type &' => 'p a', - ] - ); - $datasetsWithCombinedPseudoSelectors = [ - 'pseudo-class & descendant' => ['p:hover a { color: green; }'], - 'pseudo-class & pseudo-element' => ['a:hover::after { content: "bar"; }'], - 'pseudo-element & pseudo-class' => ['a::after:hover { content: "bar"; }'], - 'two pseudo-classes' => ['a:focus:hover { color: green; }'], - ]; - - return \array_merge($datasetsWithSelectorPseudoComponents, $datasetsWithCombinedPseudoSelectors); - } - - /** - * @test - * - * @param string $css - * - * @dataProvider matchingSelectorWithPseudoComponentCssRuleDataProvider - */ - public function emogrifyKeepsRuleWithPseudoComponentInMatchingSelector($css) - { - $subject = $this->buildDebugSubject('

foo

'); - $subject->setCss($css); - - $result = $subject->emogrify(); - - self::assertContainsCss($css, $result); - } - - /** - * @return string[][] - */ - public function nonMatchingSelectorWithPseudoComponentCssRuleDataProvider() - { - $datasetsWithSelectorPseudoComponents = $this->getCssRuleDatasetsWithSelectorPseudoComponents( - [ - 'type &' => 'b', - 'class &' => '.b', - 'ID &' => '#b', - 'attribute &' => 'a[href="b"]', - 'static pseudo-class &' => 'a:not(.a)', - 'ancestor &' => 'ul ', - 'ancestor & type &' => 'p b', - ] - ); - $datasetsWithCombinedPseudoSelectors = [ - 'pseudo-class & descendant' => ['ul:hover a { color: green; }'], - 'pseudo-class & pseudo-element' => ['b:hover::after { content: "bar"; }'], - 'pseudo-element & pseudo-class' => ['b::after:hover { content: "bar"; }'], - 'two pseudo-classes' => ['input:focus:hover { color: green; }'], - ]; - - return \array_merge($datasetsWithSelectorPseudoComponents, $datasetsWithCombinedPseudoSelectors); - } - - /** - * @test - * - * @param string $css - * - * @dataProvider nonMatchingSelectorWithPseudoComponentCssRuleDataProvider - */ - public function emogrifyNotKeepsRuleWithPseudoComponentInNonMatchingSelector($css) - { - $subject = $this->buildDebugSubject('

foo

'); - $subject->setCss($css); - - $result = $subject->emogrify(); - - self::assertNotContainsCss($css, $result); - } - - /** - * @test - */ - public function emogrifyKeepsRuleInMediaQueryWithPseudoComponentInMatchingSelector() - { - $subject = $this->buildDebugSubject('foo'); - $css = '@media screen { a:hover { color: green; } }'; - $subject->setCss($css); - - $result = $subject->emogrify(); - - self::assertContainsCss($css, $result); - } - - /** - * @test - */ - public function emogrifyNotKeepsRuleInMediaQueryWithPseudoComponentInNonMatchingSelector() - { - $subject = $this->buildDebugSubject('foo'); - $css = '@media screen { b:hover { color: green; } }'; - $subject->setCss($css); - - $result = $subject->emogrify(); - - self::assertNotContainsCss($css, $result); - } - - /** - * @test - */ - public function emogrifyKeepsRuleWithPseudoComponentInMultipleMatchingSelectorsFromSingleRule() - { - $subject = $this->buildDebugSubject('

foo

bar'); - $css = 'p:hover, a:hover { color: green; }'; - $subject->setCss($css); - - $result = $subject->emogrify(); - - static::assertContainsCss($css, $result); - } - - /** - * @test - */ - public function emogrifyKeepsOnlyMatchingSelectorsWithPseudoComponentFromSingleRule() - { - $subject = $this->buildDebugSubject('foo'); - $subject->setCss('p:hover, a:hover { color: green; }'); - - $result = $subject->emogrify(); - - static::assertContainsCss('', $result); - } - - /** - * @test - */ - public function emogrifyAppliesCssToMatchingElementsAndKeepsRuleWithPseudoComponentFromSingleRule() - { - $subject = $this->buildDebugSubject('

foo

bar'); - $subject->setCss('p, a:hover { color: green; }'); - - $result = $subject->emogrify(); - - static::assertContains('

', $result); - static::assertContainsCss('', $result); - } - - /** - * @return string[][] - */ - public function mediaTypesDataProvider() - { - return [ - 'disallowed type after disallowed type' => ['tv', 'speech'], - 'allowed type after disallowed type' => ['tv', 'all'], - 'disallowed type after allowed type' => ['screen', 'tv'], - 'allowed type after allowed type' => ['screen', 'all'], - ]; - } - - /** - * @test - * - * @param string $emptyRuleMediaType - * @param string $mediaType - * - * @dataProvider mediaTypesDataProvider - */ - public function emogrifyAppliesCssBetweenEmptyMediaRuleAndMediaRule($emptyRuleMediaType, $mediaType) - { - $subject = $this->buildDebugSubject('

'); - $subject->setCss( - '@media ' . $emptyRuleMediaType . ' {} h1 { color: green; } @media ' . $mediaType - . ' { h1 { color: red; } }' - ); - - $result = $subject->emogrify(); - - static::assertContains('

', $result); - } - - /** - * @test - * - * @param string $emptyRuleMediaType - * @param string $mediaType - * - * @dataProvider mediaTypesDataProvider - */ - public function emogrifyAppliesCssBetweenEmptyMediaRuleAndMediaRuleWithCssAfter($emptyRuleMediaType, $mediaType) - { - $subject = $this->buildDebugSubject('

'); - $subject->setCss( - '@media ' . $emptyRuleMediaType . ' {} h1 { color: green; } @media ' . $mediaType - . ' { h1 { color: red; } } h1 { font-size: 24px; }' - ); - - $result = $subject->emogrify(); - - static::assertContains('

', $result); - } - - /** - * @test - */ - public function emogrifyAppliesCssFromStyleNodes() - { - $styleAttributeValue = 'color: #ccc;'; - $subject = $this->buildDebugSubject( - '' - ); - - $result = $subject->emogrify(); - - static::assertContains('', $result); - } - - /** - * @test - */ - public function emogrifyWhenDisabledNotAppliesCssFromStyleBlocks() - { - $styleAttributeValue = 'color: #ccc;'; - $subject = $this->buildDebugSubject( - '' - ); - $subject->disableStyleBlocksParsing(); - - $result = $subject->emogrify(); - - static::assertNotContains('style=', $result); - } - - /** - * @test - */ - public function emogrifyWhenStyleBlocksParsingDisabledKeepInlineStyles() - { - $styleAttributeValue = 'text-align: center;'; - $subject = $this->buildDebugSubject( - '' . - '

paragraph

' - ); - $subject->disableStyleBlocksParsing(); - - $result = $subject->emogrify(); - - static::assertContains('

', $result); - } - - /** - * @test - */ - public function emogrifyWhenDisabledNotAppliesCssFromInlineStyles() - { - $subject = $this->buildDebugSubject(''); - $subject->disableInlineStyleAttributesParsing(); - - $result = $subject->emogrify(); - - static::assertNotContains('buildDebugSubject( - '' . - '

paragraph

' - ); - $subject->disableInlineStyleAttributesParsing(); - - $result = $subject->emogrify(); - - static::assertContains('

', $result); - } - - /** - * Emogrify was handling case differently for passed-in CSS vs. CSS parsed from style blocks. - * - * @test - */ - public function emogrifyAppliesCssWithMixedCaseAttributesInStyleBlock() - { - $subject = $this->buildDebugSubject( - '' . - '

some content

' - ); - - $result = $subject->emogrify(); - - static::assertContains('

', $result); - } - - /** - * Style block CSS overrides values. - * - * @test - */ - public function emogrifyMergesCssWithMixedCaseAttribute() - { - $subject = $this->buildDebugSubject( - '' . - '

some content

' - ); - $subject->setCss('p { margin: 0; padding-TOP: 0; PADDING-bottom: 1PX;}'); - - $result = $subject->emogrify(); - - static::assertContains( - '

', - $result - ); - } - - /** - * @test - */ - public function emogrifyMergesCssWithMixedUnits() - { - $subject = $this->buildDebugSubject( - '' . - '

some content

' - ); - $subject->setCss('p { margin: 1px; padding-bottom:0;}'); - - $result = $subject->emogrify(); - - static::assertContains('

', $result); - } - - /** - * @test - */ - public function emogrifyByDefaultRemovesElementsWithDisplayNoneFromExternalCss() - { - $subject = $this->buildDebugSubject('

'); - $subject->setCss('div.foo { display: none; }'); - - $result = $subject->emogrify(); - - static::assertNotContains('
', $result); - } - - /** - * @test - */ - public function emogrifyByDefaultRemovesElementsWithDisplayNoneInStyleAttribute() - { - $subject = $this->buildDebugSubject( - '' . - '' - ); - - $result = $subject->emogrify(); - - static::assertNotContains('buildDebugSubject('
'); - $subject->setCss('div.foo { display: none; }'); - - $subject->disableInvisibleNodeRemoval(); - $result = $subject->emogrify(); - - static::assertContains('"; -echo trim(preg_replace('/>\s+<', ob_get_clean())); -EOF - ], - ]; - } -} diff --git a/lib/twig/twig/test/Twig/Tests/Node/TextTest.php b/lib/twig/twig/test/Twig/Tests/Node/TextTest.php deleted file mode 100644 index 6735083ce..000000000 --- a/lib/twig/twig/test/Twig/Tests/Node/TextTest.php +++ /dev/null @@ -1,31 +0,0 @@ -assertEquals('foo', $node->getAttribute('data')); - } - - public function getTests() - { - $tests = []; - $tests[] = [new TextNode('foo', 1), "// line 1\necho \"foo\";"]; - - return $tests; - } -} diff --git a/lib/twig/twig/test/Twig/Tests/NodeTraverserTest.php b/lib/twig/twig/test/Twig/Tests/NodeTraverserTest.php deleted file mode 100644 index 2e08aac36..000000000 --- a/lib/twig/twig/test/Twig/Tests/NodeTraverserTest.php +++ /dev/null @@ -1,47 +0,0 @@ -getMockBuilder('\Twig\Loader\LoaderInterface')->getMock()); - $traverser = new NodeTraverser($env, [new IdentityVisitor()]); - $n = new Node([new Node([]), null, new Node([])]); - $this->assertCount(3, $traverser->traverse($n)); - } -} - -class IdentityVisitor implements NodeVisitorInterface -{ - public function enterNode(\Twig_NodeInterface $node, Environment $env) - { - return $node; - } - - public function leaveNode(\Twig_NodeInterface $node, Environment $env) - { - return $node; - } - - public function getPriority() - { - return 0; - } -} diff --git a/lib/twig/twig/test/Twig/Tests/NodeVisitor/OptimizerTest.php b/lib/twig/twig/test/Twig/Tests/NodeVisitor/OptimizerTest.php deleted file mode 100644 index 9afdbc603..000000000 --- a/lib/twig/twig/test/Twig/Tests/NodeVisitor/OptimizerTest.php +++ /dev/null @@ -1,129 +0,0 @@ -getMockBuilder('\Twig\Loader\LoaderInterface')->getMock(), ['cache' => false, 'autoescape' => false]); - - $stream = $env->parse($env->tokenize(new Source('{{ block("foo") }}', 'index'))); - - $node = $stream->getNode('body')->getNode(0); - - $this->assertInstanceOf('\Twig\Node\Expression\BlockReferenceExpression', $node); - $this->assertTrue($node->getAttribute('output')); - } - - public function testRenderParentBlockOptimizer() - { - $env = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock(), ['cache' => false, 'autoescape' => false]); - - $stream = $env->parse($env->tokenize(new Source('{% extends "foo" %}{% block content %}{{ parent() }}{% endblock %}', 'index'))); - - $node = $stream->getNode('blocks')->getNode('content')->getNode(0)->getNode('body'); - - $this->assertInstanceOf('\Twig\Node\Expression\ParentExpression', $node); - $this->assertTrue($node->getAttribute('output')); - } - - public function testRenderVariableBlockOptimizer() - { - if (PHP_VERSION_ID >= 50400) { - $this->markTestSkipped('not needed on PHP >= 5.4'); - } - - $env = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock(), ['cache' => false, 'autoescape' => false]); - $stream = $env->parse($env->tokenize(new Source('{{ block(name|lower) }}', 'index'))); - - $node = $stream->getNode('body')->getNode(0)->getNode(1); - - $this->assertInstanceOf('\Twig\Node\Expression\BlockReferenceExpression', $node); - $this->assertTrue($node->getAttribute('output')); - } - - /** - * @dataProvider getTestsForForOptimizer - */ - public function testForOptimizer($template, $expected) - { - $env = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock(), ['cache' => false]); - - $stream = $env->parse($env->tokenize(new Source($template, 'index'))); - - foreach ($expected as $target => $withLoop) { - $this->assertTrue($this->checkForConfiguration($stream, $target, $withLoop), sprintf('variable %s is %soptimized', $target, $withLoop ? 'not ' : '')); - } - } - - public function getTestsForForOptimizer() - { - return [ - ['{% for i in foo %}{% endfor %}', ['i' => false]], - - ['{% for i in foo %}{{ loop.index }}{% endfor %}', ['i' => true]], - - ['{% for i in foo %}{% for j in foo %}{% endfor %}{% endfor %}', ['i' => false, 'j' => false]], - - ['{% for i in foo %}{% include "foo" %}{% endfor %}', ['i' => true]], - - ['{% for i in foo %}{% include "foo" only %}{% endfor %}', ['i' => false]], - - ['{% for i in foo %}{% include "foo" with { "foo": "bar" } only %}{% endfor %}', ['i' => false]], - - ['{% for i in foo %}{% include "foo" with { "foo": loop.index } only %}{% endfor %}', ['i' => true]], - - ['{% for i in foo %}{% for j in foo %}{{ loop.index }}{% endfor %}{% endfor %}', ['i' => false, 'j' => true]], - - ['{% for i in foo %}{% for j in foo %}{{ loop.parent.loop.index }}{% endfor %}{% endfor %}', ['i' => true, 'j' => true]], - - ['{% for i in foo %}{% set l = loop %}{% for j in foo %}{{ l.index }}{% endfor %}{% endfor %}', ['i' => true, 'j' => false]], - - ['{% for i in foo %}{% for j in foo %}{{ foo.parent.loop.index }}{% endfor %}{% endfor %}', ['i' => false, 'j' => false]], - - ['{% for i in foo %}{% for j in foo %}{{ loop["parent"].loop.index }}{% endfor %}{% endfor %}', ['i' => true, 'j' => true]], - - ['{% for i in foo %}{{ include("foo") }}{% endfor %}', ['i' => true]], - - ['{% for i in foo %}{{ include("foo", with_context = false) }}{% endfor %}', ['i' => false]], - - ['{% for i in foo %}{{ include("foo", with_context = true) }}{% endfor %}', ['i' => true]], - - ['{% for i in foo %}{{ include("foo", { "foo": "bar" }, with_context = false) }}{% endfor %}', ['i' => false]], - - ['{% for i in foo %}{{ include("foo", { "foo": loop.index }, with_context = false) }}{% endfor %}', ['i' => true]], - ]; - } - - public function checkForConfiguration(Twig_NodeInterface $node = null, $target, $withLoop) - { - if (null === $node) { - return; - } - - foreach ($node as $n) { - if ($n instanceof ForNode) { - if ($target === $n->getNode('value_target')->getAttribute('name')) { - return $withLoop == $n->getAttribute('with_loop'); - } - } - - $ret = $this->checkForConfiguration($n, $target, $withLoop); - if (null !== $ret) { - return $ret; - } - } - } -} diff --git a/lib/twig/twig/test/Twig/Tests/ParserTest.php b/lib/twig/twig/test/Twig/Tests/ParserTest.php deleted file mode 100644 index bb39dc9b9..000000000 --- a/lib/twig/twig/test/Twig/Tests/ParserTest.php +++ /dev/null @@ -1,217 +0,0 @@ -getParser(); - $parser->setMacro('parent', $this->getMockBuilder('\Twig\Node\MacroNode')->disableOriginalConstructor()->getMock()); - } - - /** - * @expectedException \Twig\Error\SyntaxError - * @expectedExceptionMessage Unknown "foo" tag. Did you mean "for" at line 1? - */ - public function testUnknownTag() - { - $stream = new TokenStream([ - new Token(Token::BLOCK_START_TYPE, '', 1), - new Token(Token::NAME_TYPE, 'foo', 1), - new Token(Token::BLOCK_END_TYPE, '', 1), - new Token(Token::EOF_TYPE, '', 1), - ]); - $parser = new Parser(new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock())); - $parser->parse($stream); - } - - /** - * @expectedException \Twig\Error\SyntaxError - * @expectedExceptionMessage Unknown "foobar" tag at line 1. - */ - public function testUnknownTagWithoutSuggestions() - { - $stream = new TokenStream([ - new Token(Token::BLOCK_START_TYPE, '', 1), - new Token(Token::NAME_TYPE, 'foobar', 1), - new Token(Token::BLOCK_END_TYPE, '', 1), - new Token(Token::EOF_TYPE, '', 1), - ]); - $parser = new Parser(new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock())); - $parser->parse($stream); - } - - /** - * @dataProvider getFilterBodyNodesData - */ - public function testFilterBodyNodes($input, $expected) - { - $parser = $this->getParser(); - - $this->assertEquals($expected, $parser->filterBodyNodes($input)); - } - - public function getFilterBodyNodesData() - { - return [ - [ - new Node([new TextNode(' ', 1)]), - new Node([]), - ], - [ - $input = new Node([new SetNode(false, new Node(), new Node(), 1)]), - $input, - ], - [ - $input = new Node([new SetNode(true, new Node(), new Node([new Node([new TextNode('foo', 1)])]), 1)]), - $input, - ], - ]; - } - - /** - * @dataProvider getFilterBodyNodesDataThrowsException - * @expectedException \Twig\Error\SyntaxError - */ - public function testFilterBodyNodesThrowsException($input) - { - $parser = $this->getParser(); - - $parser->filterBodyNodes($input); - } - - public function getFilterBodyNodesDataThrowsException() - { - return [ - [new TextNode('foo', 1)], - [new Node([new Node([new TextNode('foo', 1)])])], - ]; - } - - /** - * @dataProvider getFilterBodyNodesWithBOMData - */ - public function testFilterBodyNodesWithBOM($emptyNode) - { - $this->assertNull($this->getParser()->filterBodyNodes(new TextNode(\chr(0xEF).\chr(0xBB).\chr(0xBF).$emptyNode, 1))); - } - - public function getFilterBodyNodesWithBOMData() - { - return [ - [' '], - ["\t"], - ["\n"], - ["\n\t\n "], - ]; - } - - public function testParseIsReentrant() - { - $twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock(), [ - 'autoescape' => false, - 'optimizations' => 0, - ]); - $twig->addTokenParser(new TestTokenParser()); - - $parser = new Parser($twig); - - $parser->parse(new TokenStream([ - new Token(Token::BLOCK_START_TYPE, '', 1), - new Token(Token::NAME_TYPE, 'test', 1), - new Token(Token::BLOCK_END_TYPE, '', 1), - new Token(Token::VAR_START_TYPE, '', 1), - new Token(Token::NAME_TYPE, 'foo', 1), - new Token(Token::VAR_END_TYPE, '', 1), - new Token(Token::EOF_TYPE, '', 1), - ])); - - $this->assertNull($parser->getParent()); - } - - public function testGetVarName() - { - $twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock(), [ - 'autoescape' => false, - 'optimizations' => 0, - ]); - - $twig->parse($twig->tokenize(new Source(<<addToAssertionCount(1); - } - - protected function getParser() - { - $parser = new TestParser(new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock())); - $parser->setParent(new Node()); - $parser->stream = new TokenStream([]); - - return $parser; - } -} - -class TestParser extends Parser -{ - public $stream; - - public function filterBodyNodes(Twig_NodeInterface $node) - { - return parent::filterBodyNodes($node); - } -} - -class TestTokenParser extends AbstractTokenParser -{ - public function parse(Token $token) - { - // simulate the parsing of another template right in the middle of the parsing of the current template - $this->parser->parse(new TokenStream([ - new Token(Token::BLOCK_START_TYPE, '', 1), - new Token(Token::NAME_TYPE, 'extends', 1), - new Token(Token::STRING_TYPE, 'base', 1), - new Token(Token::BLOCK_END_TYPE, '', 1), - new Token(Token::EOF_TYPE, '', 1), - ])); - - $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); - - return new Node([]); - } - - public function getTag() - { - return 'test'; - } -} diff --git a/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/AbstractTest.php b/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/AbstractTest.php deleted file mode 100644 index 508f79ca5..000000000 --- a/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/AbstractTest.php +++ /dev/null @@ -1,105 +0,0 @@ -getIndexProfile( - [ - $this->getEmbeddedBlockProfile(), - $this->getEmbeddedTemplateProfile( - [ - $this->getIncludedTemplateProfile(), - ] - ), - $this->getMacroProfile(), - $this->getEmbeddedTemplateProfile( - [ - $this->getIncludedTemplateProfile(), - ] - ), - ] - ), - ]; - - $p = new \ReflectionProperty($profile, 'profiles'); - $p->setAccessible(true); - $p->setValue($profile, $subProfiles); - - return $profile; - } - - private function getIndexProfile(array $subProfiles = []) - { - return $this->generateProfile('main', 1, 'template', 'index.twig', $subProfiles); - } - - private function getEmbeddedBlockProfile(array $subProfiles = []) - { - return $this->generateProfile('body', 0.0001, 'block', 'embedded.twig', $subProfiles); - } - - private function getEmbeddedTemplateProfile(array $subProfiles = []) - { - return $this->generateProfile('main', 0.0001, 'template', 'embedded.twig', $subProfiles); - } - - private function getIncludedTemplateProfile(array $subProfiles = []) - { - return $this->generateProfile('main', 0.0001, 'template', 'included.twig', $subProfiles); - } - - private function getMacroProfile(array $subProfiles = []) - { - return $this->generateProfile('foo', 0.0001, 'macro', 'index.twig', $subProfiles); - } - - /** - * @param string $name - * @param float $duration - * @param bool $isTemplate - * @param string $type - * @param string $templateName - * @param array $subProfiles - * - * @return Profile - */ - private function generateProfile($name, $duration, $type, $templateName, array $subProfiles = []) - { - $profile = new Profile($templateName, $type, $name); - - $p = new \ReflectionProperty($profile, 'profiles'); - $p->setAccessible(true); - $p->setValue($profile, $subProfiles); - - $starts = new \ReflectionProperty($profile, 'starts'); - $starts->setAccessible(true); - $starts->setValue($profile, [ - 'wt' => 0, - 'mu' => 0, - 'pmu' => 0, - ]); - $ends = new \ReflectionProperty($profile, 'ends'); - $ends->setAccessible(true); - $ends->setValue($profile, [ - 'wt' => $duration, - 'mu' => 0, - 'pmu' => 0, - ]); - - return $profile; - } -} diff --git a/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/BlackfireTest.php b/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/BlackfireTest.php deleted file mode 100644 index 26ef2dad2..000000000 --- a/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/BlackfireTest.php +++ /dev/null @@ -1,34 +0,0 @@ -assertStringMatchesFormat(<<index.twig//1 %d %d %d -index.twig==>embedded.twig::block(body)//1 %d %d 0 -index.twig==>embedded.twig//2 %d %d %d -embedded.twig==>included.twig//2 %d %d %d -index.twig==>index.twig::macro(foo)//1 %d %d %d -EOF - , $dumper->dump($this->getProfile())); - } -} diff --git a/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/HtmlTest.php b/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/HtmlTest.php deleted file mode 100644 index e04bbcf2b..000000000 --- a/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/HtmlTest.php +++ /dev/null @@ -1,32 +0,0 @@ -assertStringMatchesFormat(<<main %d.%dms/%d% -└ index.twig %d.%dms/%d% - └ embedded.twig::block(body) - └ embedded.twig - │ └ included.twig - └ index.twig::macro(foo) - └ embedded.twig - └ included.twig - -EOF - , $dumper->dump($this->getProfile())); - } -} diff --git a/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/TextTest.php b/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/TextTest.php deleted file mode 100644 index e36d0ad60..000000000 --- a/lib/twig/twig/test/Twig/Tests/Profiler/Dumper/TextTest.php +++ /dev/null @@ -1,32 +0,0 @@ -assertStringMatchesFormat(<<dump($this->getProfile())); - } -} diff --git a/lib/twig/twig/test/Twig/Tests/Profiler/ProfileTest.php b/lib/twig/twig/test/Twig/Tests/Profiler/ProfileTest.php deleted file mode 100644 index 18e2a5b56..000000000 --- a/lib/twig/twig/test/Twig/Tests/Profiler/ProfileTest.php +++ /dev/null @@ -1,112 +0,0 @@ -assertEquals('template', $profile->getTemplate()); - $this->assertEquals('type', $profile->getType()); - $this->assertEquals('name', $profile->getName()); - } - - public function testIsRoot() - { - $profile = new Profile('template', Profile::ROOT); - $this->assertTrue($profile->isRoot()); - - $profile = new Profile('template', Profile::TEMPLATE); - $this->assertFalse($profile->isRoot()); - } - - public function testIsTemplate() - { - $profile = new Profile('template', Profile::TEMPLATE); - $this->assertTrue($profile->isTemplate()); - - $profile = new Profile('template', Profile::ROOT); - $this->assertFalse($profile->isTemplate()); - } - - public function testIsBlock() - { - $profile = new Profile('template', Profile::BLOCK); - $this->assertTrue($profile->isBlock()); - - $profile = new Profile('template', Profile::ROOT); - $this->assertFalse($profile->isBlock()); - } - - public function testIsMacro() - { - $profile = new Profile('template', Profile::MACRO); - $this->assertTrue($profile->isMacro()); - - $profile = new Profile('template', Profile::ROOT); - $this->assertFalse($profile->isMacro()); - } - - public function testGetAddProfile() - { - $profile = new Profile(); - $profile->addProfile($a = new Profile()); - $profile->addProfile($b = new Profile()); - - $this->assertSame([$a, $b], $profile->getProfiles()); - $this->assertSame([$a, $b], iterator_to_array($profile)); - } - - public function testGetDuration() - { - $profile = new Profile(); - usleep(1); - $profile->leave(); - - $this->assertTrue($profile->getDuration() > 0, sprintf('Expected duration > 0, got: %f', $profile->getDuration())); - } - - public function testSerialize() - { - $profile = new Profile('template', 'type', 'name'); - $profile1 = new Profile('template1', 'type1', 'name1'); - $profile->addProfile($profile1); - $profile->leave(); - $profile1->leave(); - - $profile2 = unserialize(serialize($profile)); - $profiles = $profile->getProfiles(); - $this->assertCount(1, $profiles); - $profile3 = $profiles[0]; - - $this->assertEquals($profile->getTemplate(), $profile2->getTemplate()); - $this->assertEquals($profile->getType(), $profile2->getType()); - $this->assertEquals($profile->getName(), $profile2->getName()); - $this->assertEquals($profile->getDuration(), $profile2->getDuration()); - - $this->assertEquals($profile1->getTemplate(), $profile3->getTemplate()); - $this->assertEquals($profile1->getType(), $profile3->getType()); - $this->assertEquals($profile1->getName(), $profile3->getName()); - } - - public function testReset() - { - $profile = new Profile(); - usleep(1); - $profile->leave(); - $profile->reset(); - - $this->assertEquals(0, $profile->getDuration()); - } -} diff --git a/lib/twig/twig/test/Twig/Tests/TemplateTest.php b/lib/twig/twig/test/Twig/Tests/TemplateTest.php deleted file mode 100644 index 1b42b93e1..000000000 --- a/lib/twig/twig/test/Twig/Tests/TemplateTest.php +++ /dev/null @@ -1,812 +0,0 @@ -getMockForAbstractClass('\Twig\Template', [], '', false); - $template->displayBlock('foo', [], ['foo' => [new \stdClass(), 'foo']]); - } - - /** - * @dataProvider getAttributeExceptions - */ - public function testGetAttributeExceptions($template, $message) - { - $templates = ['index' => $template]; - $env = new Environment(new ArrayLoader($templates), ['strict_variables' => true]); - $template = $env->load('index'); - - $context = [ - 'string' => 'foo', - 'null' => null, - 'empty_array' => [], - 'array' => ['foo' => 'foo'], - 'array_access' => new Twig_TemplateArrayAccessObject(), - 'magic_exception' => new Twig_TemplateMagicPropertyObjectWithException(), - 'object' => new \stdClass(), - ]; - - try { - $template->render($context); - $this->fail('Accessing an invalid attribute should throw an exception.'); - } catch (RuntimeError $e) { - $this->assertSame(sprintf($message, 'index'), $e->getMessage()); - } - } - - public function getAttributeExceptions() - { - return [ - ['{{ string["a"] }}', 'Impossible to access a key ("a") on a string variable ("foo") in "%s" at line 1.'], - ['{{ null["a"] }}', 'Impossible to access a key ("a") on a null variable in "%s" at line 1.'], - ['{{ empty_array["a"] }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.'], - ['{{ array["a"] }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.'], - ['{{ array_access["a"] }}', 'Key "a" in object with ArrayAccess of class "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1.'], - ['{{ string.a }}', 'Impossible to access an attribute ("a") on a string variable ("foo") in "%s" at line 1.'], - ['{{ string.a() }}', 'Impossible to invoke a method ("a") on a string variable ("foo") in "%s" at line 1.'], - ['{{ null.a }}', 'Impossible to access an attribute ("a") on a null variable in "%s" at line 1.'], - ['{{ null.a() }}', 'Impossible to invoke a method ("a") on a null variable in "%s" at line 1.'], - ['{{ array.a() }}', 'Impossible to invoke a method ("a") on an array in "%s" at line 1.'], - ['{{ empty_array.a }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.'], - ['{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.'], - ['{{ attribute(array, -10) }}', 'Key "-10" for array with keys "foo" does not exist in "%s" at line 1.'], - ['{{ array_access.a }}', 'Neither the property "a" nor one of the methods "a()", "geta()"/"isa()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.'], - ['{% from _self import foo %}{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ foo(array_access) }}', 'Neither the property "missing_method" nor one of the methods "missing_method()", "getmissing_method()"/"ismissing_method()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.'], - ['{{ magic_exception.test }}', 'An exception has been thrown during the rendering of a template ("Hey! Don\'t try to isset me!") in "%s" at line 1.'], - ['{{ object["a"] }}', 'Impossible to access a key "a" on an object of class "stdClass" that does not implement ArrayAccess interface in "%s" at line 1.'], - ]; - } - - /** - * @dataProvider getGetAttributeWithSandbox - */ - public function testGetAttributeWithSandbox($object, $item, $allowed) - { - $twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock()); - $policy = new SecurityPolicy([], [], [/*method*/], [/*prop*/], []); - $twig->addExtension(new SandboxExtension($policy, !$allowed)); - $template = new Twig_TemplateTest($twig); - - try { - $template->getAttribute($object, $item, [], 'any'); - - if (!$allowed) { - $this->fail(); - } else { - $this->addToAssertionCount(1); - } - } catch (SecurityError $e) { - if ($allowed) { - $this->fail(); - } else { - $this->addToAssertionCount(1); - } - - $this->assertContains('is not allowed', $e->getMessage()); - } - } - - public function getGetAttributeWithSandbox() - { - return [ - [new Twig_TemplatePropertyObject(), 'defined', false], - [new Twig_TemplatePropertyObject(), 'defined', true], - [new Twig_TemplateMethodObject(), 'defined', false], - [new Twig_TemplateMethodObject(), 'defined', true], - ]; - } - - /** - * @group legacy - */ - public function testGetAttributeWithTemplateAsObject() - { - // to be removed in 2.0 - $twig = new Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock()); - //$twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface', '\Twig\Loader\SourceContextLoaderInterface')->getMock()); - - $template = new Twig_TemplateTest($twig, 'index.twig'); - $template1 = new Twig_TemplateTest($twig, 'index1.twig'); - - $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'string')); - $this->assertEquals('some_string', $template->getAttribute($template1, 'string')); - - $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'true')); - $this->assertEquals('1', $template->getAttribute($template1, 'true')); - - $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'zero')); - $this->assertEquals('0', $template->getAttribute($template1, 'zero')); - - $this->assertNotInstanceof('\Twig\Markup', $template->getAttribute($template1, 'empty')); - $this->assertSame('', $template->getAttribute($template1, 'empty')); - - $this->assertFalse($template->getAttribute($template1, 'env', [], Template::ANY_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'environment', [], Template::ANY_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'getEnvironment', [], Template::METHOD_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'displayWithErrorHandling', [], Template::METHOD_CALL, true)); - } - - /** - * @group legacy - * @expectedDeprecation Calling "string" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. - * @expectedDeprecation Calling "string" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. - * @expectedDeprecation Calling "true" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. - * @expectedDeprecation Calling "true" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. - * @expectedDeprecation Calling "zero" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. - * @expectedDeprecation Calling "zero" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. - * @expectedDeprecation Calling "empty" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. - * @expectedDeprecation Calling "empty" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. - * @expectedDeprecation Calling "renderBlock" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name") instead). - * @expectedDeprecation Calling "displayBlock" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name") instead). - * @expectedDeprecation Calling "hasBlock" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use "block("name") is defined" instead). - * @expectedDeprecation Calling "render" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index.twig") instead). - * @expectedDeprecation Calling "display" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index.twig") instead). - * @expectedDeprecation Calling "renderBlock" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name", template) instead). - * @expectedDeprecation Calling "displayBlock" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name", template) instead). - * @expectedDeprecation Calling "hasBlock" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use "block("name", template) is defined" instead). - * @expectedDeprecation Calling "render" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index1.twig") instead). - * @expectedDeprecation Calling "display" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index1.twig") instead). - */ - public function testGetAttributeWithTemplateAsObjectForDeprecations() - { - // to be removed in 2.0 - $twig = new Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock()); - //$twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface', '\Twig\Loader\SourceContextLoaderInterface')->getMock()); - - $template = new Twig_TemplateTest($twig, 'index.twig'); - $template1 = new Twig_TemplateTest($twig, 'index1.twig'); - - $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'string')); - $this->assertEquals('some_string', $template->getAttribute($template1, 'string')); - - $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'true')); - $this->assertEquals('1', $template->getAttribute($template1, 'true')); - - $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'zero')); - $this->assertEquals('0', $template->getAttribute($template1, 'zero')); - - $this->assertNotInstanceof('\Twig\Markup', $template->getAttribute($template1, 'empty')); - $this->assertSame('', $template->getAttribute($template1, 'empty')); - - $blocks = ['name' => [$template1, 'block_name']]; - - // trigger some deprecation notice messages to check them with @expectedDeprecation - $template->getAttribute($template, 'renderBlock', ['name', [], $blocks]); - $template->getAttribute($template, 'displayBlock', ['name', [], $blocks]); - $template->getAttribute($template, 'hasBlock', ['name', []]); - $template->getAttribute($template, 'render', [[]]); - $template->getAttribute($template, 'display', [[]]); - - $template->getAttribute($template1, 'renderBlock', ['name', [], $blocks]); - $template->getAttribute($template1, 'displayBlock', ['name', [], $blocks]); - $template->getAttribute($template1, 'hasBlock', ['name', []]); - $template->getAttribute($template1, 'render', [[]]); - $template->getAttribute($template1, 'display', [[]]); - - $this->assertFalse($template->getAttribute($template1, 'env', [], Template::ANY_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'environment', [], Template::ANY_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'getEnvironment', [], Template::METHOD_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'displayWithErrorHandling', [], Template::METHOD_CALL, true)); - } - - /** - * @group legacy - * @expectedDeprecation Silent display of undefined block "unknown" in template "index.twig" is deprecated since version 1.29 and will throw an exception in 2.0. Use the "block('unknown') is defined" expression to test for block existence. - * @expectedDeprecation Silent display of undefined block "unknown" in template "index.twig" is deprecated since version 1.29 and will throw an exception in 2.0. Use the "block('unknown') is defined" expression to test for block existence. - */ - public function testRenderBlockWithUndefinedBlock() - { - $twig = new Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock()); - - $template = new Twig_TemplateTest($twig, 'index.twig'); - $template->renderBlock('unknown', []); - $template->displayBlock('unknown', []); - } - - public function testGetAttributeOnArrayWithConfusableKey() - { - $template = new Twig_TemplateTest(new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock())); - - $array = ['Zero', 'One', -1 => 'MinusOne', '' => 'EmptyString', '1.5' => 'FloatButString', '01' => 'IntegerButStringWithLeadingZeros']; - - $this->assertSame('Zero', $array[false]); - $this->assertSame('One', $array[true]); - $this->assertSame('One', $array[1.5]); - $this->assertSame('One', $array['1']); - $this->assertSame('MinusOne', $array[-1.5]); - $this->assertSame('FloatButString', $array['1.5']); - $this->assertSame('IntegerButStringWithLeadingZeros', $array['01']); - $this->assertSame('EmptyString', $array[null]); - - $this->assertSame('Zero', $template->getAttribute($array, false), 'false is treated as 0 when accessing an array (equals PHP behavior)'); - $this->assertSame('One', $template->getAttribute($array, true), 'true is treated as 1 when accessing an array (equals PHP behavior)'); - $this->assertSame('One', $template->getAttribute($array, 1.5), 'float is casted to int when accessing an array (equals PHP behavior)'); - $this->assertSame('One', $template->getAttribute($array, '1'), '"1" is treated as integer 1 when accessing an array (equals PHP behavior)'); - $this->assertSame('MinusOne', $template->getAttribute($array, -1.5), 'negative float is casted to int when accessing an array (equals PHP behavior)'); - $this->assertSame('FloatButString', $template->getAttribute($array, '1.5'), '"1.5" is treated as-is when accessing an array (equals PHP behavior)'); - $this->assertSame('IntegerButStringWithLeadingZeros', $template->getAttribute($array, '01'), '"01" is treated as-is when accessing an array (equals PHP behavior)'); - $this->assertSame('EmptyString', $template->getAttribute($array, null), 'null is treated as "" when accessing an array (equals PHP behavior)'); - } - - /** - * @dataProvider getGetAttributeTests - */ - public function testGetAttribute($defined, $value, $object, $item, $arguments, $type) - { - $template = new Twig_TemplateTest(new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock())); - - $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type)); - } - - /** - * @dataProvider getGetAttributeTests - */ - public function testGetAttributeStrict($defined, $value, $object, $item, $arguments, $type, $exceptionMessage = null) - { - $template = new Twig_TemplateTest(new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock(), ['strict_variables' => true])); - - if ($defined) { - $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type)); - } else { - if (method_exists($this, 'expectException')) { - $this->expectException('\Twig\Error\RuntimeError'); - if (null !== $exceptionMessage) { - $this->expectExceptionMessage($exceptionMessage); - } - } else { - $this->setExpectedException('\Twig\Error\RuntimeError', $exceptionMessage); - } - $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type)); - } - } - - /** - * @dataProvider getGetAttributeTests - */ - public function testGetAttributeDefined($defined, $value, $object, $item, $arguments, $type) - { - $template = new Twig_TemplateTest(new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock())); - - $this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true)); - } - - /** - * @dataProvider getGetAttributeTests - */ - public function testGetAttributeDefinedStrict($defined, $value, $object, $item, $arguments, $type) - { - $template = new Twig_TemplateTest(new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock(), ['strict_variables' => true])); - - $this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true)); - } - - public function testGetAttributeCallExceptions() - { - $template = new Twig_TemplateTest(new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock())); - - $object = new Twig_TemplateMagicMethodExceptionObject(); - - $this->assertNull($template->getAttribute($object, 'foo')); - } - - public function getGetAttributeTests() - { - $array = [ - 'defined' => 'defined', - 'zero' => 0, - 'null' => null, - '1' => 1, - 'bar' => true, - 'baz' => 'baz', - '09' => '09', - '+4' => '+4', - ]; - - $objectArray = new Twig_TemplateArrayAccessObject(); - $arrayObject = new \ArrayObject($array); - $stdObject = (object) $array; - $magicPropertyObject = new Twig_TemplateMagicPropertyObject(); - $propertyObject = new Twig_TemplatePropertyObject(); - $propertyObject1 = new Twig_TemplatePropertyObjectAndIterator(); - $propertyObject2 = new Twig_TemplatePropertyObjectAndArrayAccess(); - $propertyObject3 = new Twig_TemplatePropertyObjectDefinedWithUndefinedValue(); - $methodObject = new Twig_TemplateMethodObject(); - $magicMethodObject = new Twig_TemplateMagicMethodObject(); - - $anyType = Template::ANY_CALL; - $methodType = Template::METHOD_CALL; - $arrayType = Template::ARRAY_CALL; - - $basicTests = [ - // array(defined, value, property to fetch) - [true, 'defined', 'defined'], - [false, null, 'undefined'], - [false, null, 'protected'], - [true, 0, 'zero'], - [true, 1, 1], - [true, 1, 1.0], - [true, null, 'null'], - [true, true, 'bar'], - [true, 'baz', 'baz'], - [true, '09', '09'], - [true, '+4', '+4'], - ]; - $testObjects = [ - // array(object, type of fetch) - [$array, $arrayType], - [$objectArray, $arrayType], - [$arrayObject, $anyType], - [$stdObject, $anyType], - [$magicPropertyObject, $anyType], - [$methodObject, $methodType], - [$methodObject, $anyType], - [$propertyObject, $anyType], - [$propertyObject1, $anyType], - [$propertyObject2, $anyType], - ]; - - $tests = []; - foreach ($testObjects as $testObject) { - foreach ($basicTests as $test) { - // properties cannot be numbers - if (($testObject[0] instanceof \stdClass || $testObject[0] instanceof Twig_TemplatePropertyObject) && is_numeric($test[2])) { - continue; - } - - if ('+4' === $test[2] && $methodObject === $testObject[0]) { - continue; - } - - $tests[] = [$test[0], $test[1], $testObject[0], $test[2], [], $testObject[1]]; - } - } - - // additional properties tests - $tests = array_merge($tests, [ - [true, null, $propertyObject3, 'foo', [], $anyType], - ]); - - // additional method tests - $tests = array_merge($tests, [ - [true, 'defined', $methodObject, 'defined', [], $methodType], - [true, 'defined', $methodObject, 'DEFINED', [], $methodType], - [true, 'defined', $methodObject, 'getDefined', [], $methodType], - [true, 'defined', $methodObject, 'GETDEFINED', [], $methodType], - [true, 'static', $methodObject, 'static', [], $methodType], - [true, 'static', $methodObject, 'getStatic', [], $methodType], - - [true, '__call_undefined', $magicMethodObject, 'undefined', [], $methodType], - [true, '__call_UNDEFINED', $magicMethodObject, 'UNDEFINED', [], $methodType], - ]); - - // add the same tests for the any type - foreach ($tests as $test) { - if ($anyType !== $test[5]) { - $test[5] = $anyType; - $tests[] = $test; - } - } - - $methodAndPropObject = new Twig_TemplateMethodAndPropObject(); - - // additional method tests - $tests = array_merge($tests, [ - [true, 'a', $methodAndPropObject, 'a', [], $anyType], - [true, 'a', $methodAndPropObject, 'a', [], $methodType], - [false, null, $methodAndPropObject, 'a', [], $arrayType], - - [true, 'b_prop', $methodAndPropObject, 'b', [], $anyType], - [true, 'b', $methodAndPropObject, 'B', [], $anyType], - [true, 'b', $methodAndPropObject, 'b', [], $methodType], - [true, 'b', $methodAndPropObject, 'B', [], $methodType], - [false, null, $methodAndPropObject, 'b', [], $arrayType], - - [false, null, $methodAndPropObject, 'c', [], $anyType], - [false, null, $methodAndPropObject, 'c', [], $methodType], - [false, null, $methodAndPropObject, 'c', [], $arrayType], - ]); - - $arrayAccess = new Twig_TemplateArrayAccess(); - $tests = array_merge($tests, [ - [true, ['foo' => 'bar'], $arrayAccess, 'vars', [], $anyType], - ]); - - // tests when input is not an array or object - $tests = array_merge($tests, [ - [false, null, 42, 'a', [], $anyType, 'Impossible to access an attribute ("a") on a integer variable ("42") in "index.twig".'], - [false, null, 'string', 'a', [], $anyType, 'Impossible to access an attribute ("a") on a string variable ("string") in "index.twig".'], - [false, null, [], 'a', [], $anyType, 'Key "a" does not exist as the array is empty in "index.twig".'], - ]); - - return $tests; - } - - /** - * @expectedException \Twig\Error\RuntimeError - */ - public function testGetIsMethods() - { - $getIsObject = new Twig_TemplateGetIsMethods(); - $template = new Twig_TemplateTest(new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock(), ['strict_variables' => true])); - // first time should not create a cache for "get" - $this->assertNull($template->getAttribute($getIsObject, 'get')); - // 0 should be in the method cache now, so this should fail - $this->assertNull($template->getAttribute($getIsObject, 0)); - } -} - -class Twig_TemplateTest extends Template -{ - private $name; - - public function __construct(Environment $env, $name = 'index.twig') - { - parent::__construct($env); - self::$cache = []; - $this->name = $name; - } - - public function getZero() - { - return 0; - } - - public function getEmpty() - { - return ''; - } - - public function getString() - { - return 'some_string'; - } - - public function getTrue() - { - return true; - } - - public function getTemplateName() - { - return $this->name; - } - - public function getDebugInfo() - { - return []; - } - - protected function doGetParent(array $context) - { - return false; - } - - protected function doDisplay(array $context, array $blocks = []) - { - } - - public function getAttribute($object, $item, array $arguments = [], $type = Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false) - { - if (\function_exists('twig_template_get_attributes')) { - return twig_template_get_attributes($this, $object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck); - } else { - return parent::getAttribute($object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck); - } - } - - public function block_name($context, array $blocks = []) - { - } -} - -class Twig_TemplateArrayAccessObject implements \ArrayAccess -{ - protected $protected = 'protected'; - - public $attributes = [ - 'defined' => 'defined', - 'zero' => 0, - 'null' => null, - '1' => 1, - 'bar' => true, - 'baz' => 'baz', - '09' => '09', - '+4' => '+4', - ]; - - public function offsetExists($name) - { - return \array_key_exists($name, $this->attributes); - } - - public function offsetGet($name) - { - return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null; - } - - public function offsetSet($name, $value) - { - } - - public function offsetUnset($name) - { - } -} - -class Twig_TemplateMagicPropertyObject -{ - public $defined = 'defined'; - - public $attributes = [ - 'zero' => 0, - 'null' => null, - '1' => 1, - 'bar' => true, - 'baz' => 'baz', - '09' => '09', - '+4' => '+4', - ]; - - protected $protected = 'protected'; - - public function __isset($name) - { - return \array_key_exists($name, $this->attributes); - } - - public function __get($name) - { - return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null; - } -} - -class Twig_TemplateMagicPropertyObjectWithException -{ - public function __isset($key) - { - throw new \Exception('Hey! Don\'t try to isset me!'); - } -} - -class Twig_TemplatePropertyObject -{ - public $defined = 'defined'; - public $zero = 0; - public $null = null; - public $bar = true; - public $baz = 'baz'; - - protected $protected = 'protected'; -} - -class Twig_TemplatePropertyObjectAndIterator extends Twig_TemplatePropertyObject implements \IteratorAggregate -{ - public function getIterator() - { - return new \ArrayIterator(['foo', 'bar']); - } -} - -class Twig_TemplatePropertyObjectAndArrayAccess extends Twig_TemplatePropertyObject implements \ArrayAccess -{ - private $data = [ - 'defined' => 'defined', - 'zero' => 0, - 'null' => null, - 'bar' => true, - 'foo' => true, - 'baz' => 'baz', - 'baf' => 'baf', - ]; - - public function offsetExists($offset) - { - return \array_key_exists($offset, $this->data); - } - - public function offsetGet($offset) - { - return $this->offsetExists($offset) ? $this->data[$offset] : 'n/a'; - } - - public function offsetSet($offset, $value) - { - } - - public function offsetUnset($offset) - { - } -} - -class Twig_TemplatePropertyObjectDefinedWithUndefinedValue -{ - public $foo; - - public function __construct() - { - $this->foo = @$notExist; - } -} - -class Twig_TemplateMethodObject -{ - public function getDefined() - { - return 'defined'; - } - - public function get1() - { - return 1; - } - - public function get09() - { - return '09'; - } - - public function getZero() - { - return 0; - } - - public function getNull() - { - } - - public function isBar() - { - return true; - } - - public function isBaz() - { - return 'should never be returned'; - } - - public function getBaz() - { - return 'baz'; - } - - protected function getProtected() - { - return 'protected'; - } - - public static function getStatic() - { - return 'static'; - } -} - -class Twig_TemplateGetIsMethods -{ - public function get() - { - } - - public function is() - { - } -} - -class Twig_TemplateMethodAndPropObject -{ - private $a = 'a_prop'; - - public function getA() - { - return 'a'; - } - - public $b = 'b_prop'; - - public function getB() - { - return 'b'; - } - - private $c = 'c_prop'; - - private function getC() - { - return 'c'; - } -} - -class Twig_TemplateArrayAccess implements \ArrayAccess -{ - public $vars = [ - 'foo' => 'bar', - ]; - private $children = []; - - public function offsetExists($offset) - { - return \array_key_exists($offset, $this->children); - } - - public function offsetGet($offset) - { - return $this->children[$offset]; - } - - public function offsetSet($offset, $value) - { - $this->children[$offset] = $value; - } - - public function offsetUnset($offset) - { - unset($this->children[$offset]); - } -} - -class Twig_TemplateMagicMethodObject -{ - public function __call($method, $arguments) - { - return '__call_'.$method; - } -} - -class Twig_TemplateMagicMethodExceptionObject -{ - public function __call($method, $arguments) - { - throw new \BadMethodCallException(sprintf('Unknown method "%s".', $method)); - } -} - -class CExtDisablingNodeVisitor implements NodeVisitorInterface -{ - public function enterNode(Twig_NodeInterface $node, Environment $env) - { - if ($node instanceof GetAttrExpression) { - $node->setAttribute('disable_c_ext', true); - } - - return $node; - } - - public function leaveNode(Twig_NodeInterface $node, Environment $env) - { - return $node; - } - - public function getPriority() - { - return 0; - } -} - -// to be removed in 2.0 -interface Twig_TemplateTestLoaderInterface extends LoaderInterface, SourceContextLoaderInterface -{ -} diff --git a/lib/twig/twig/test/Twig/Tests/TemplateWrapperTest.php b/lib/twig/twig/test/Twig/Tests/TemplateWrapperTest.php deleted file mode 100644 index 74618406c..000000000 --- a/lib/twig/twig/test/Twig/Tests/TemplateWrapperTest.php +++ /dev/null @@ -1,68 +0,0 @@ - '{% block foo %}{% endblock %}', - 'index_with_use' => '{% use "imported" %}{% block foo %}{% endblock %}', - 'index_with_extends' => '{% extends "extended" %}{% block foo %}{% endblock %}', - 'imported' => '{% block imported %}{% endblock %}', - 'extended' => '{% block extended %}{% endblock %}', - ])); - - $wrapper = $twig->load('index'); - $this->assertTrue($wrapper->hasBlock('foo')); - $this->assertFalse($wrapper->hasBlock('bar')); - $this->assertEquals(['foo'], $wrapper->getBlockNames()); - - $wrapper = $twig->load('index_with_use'); - $this->assertTrue($wrapper->hasBlock('foo')); - $this->assertTrue($wrapper->hasBlock('imported')); - $this->assertEquals(['imported', 'foo'], $wrapper->getBlockNames()); - - $wrapper = $twig->load('index_with_extends'); - $this->assertTrue($wrapper->hasBlock('foo')); - $this->assertTrue($wrapper->hasBlock('extended')); - $this->assertEquals(['foo', 'extended'], $wrapper->getBlockNames()); - } - - public function testRenderBlock() - { - $twig = new Environment(new ArrayLoader([ - 'index' => '{% block foo %}{{ foo }}{{ bar }}{% endblock %}', - ])); - $twig->addGlobal('bar', 'BAR'); - - $wrapper = $twig->load('index'); - $this->assertEquals('FOOBAR', $wrapper->renderBlock('foo', ['foo' => 'FOO'])); - } - - public function testDisplayBlock() - { - $twig = new Environment(new ArrayLoader([ - 'index' => '{% block foo %}{{ foo }}{{ bar }}{% endblock %}', - ])); - $twig->addGlobal('bar', 'BAR'); - - $wrapper = $twig->load('index'); - - ob_start(); - $wrapper->displayBlock('foo', ['foo' => 'FOO']); - - $this->assertEquals('FOOBAR', ob_get_clean()); - } -} diff --git a/lib/twig/twig/test/Twig/Tests/TokenStreamTest.php b/lib/twig/twig/test/Twig/Tests/TokenStreamTest.php deleted file mode 100644 index e5cd568b0..000000000 --- a/lib/twig/twig/test/Twig/Tests/TokenStreamTest.php +++ /dev/null @@ -1,85 +0,0 @@ -assertEquals('foo', $stream->getFilename()); - $this->assertEquals('{{ foo }}', $stream->getSource()); - $this->assertEquals('foo', $stream->getSourceContext()->getName()); - $this->assertEquals('{{ foo }}', $stream->getSourceContext()->getCode()); - } - - public function testNext() - { - $stream = new TokenStream(self::$tokens); - $repr = []; - while (!$stream->isEOF()) { - $token = $stream->next(); - - $repr[] = $token->getValue(); - } - $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->next() advances the pointer and returns the current token'); - } - - /** - * @expectedException \Twig\Error\SyntaxError - * @expectedExceptionMessage Unexpected end of template - */ - public function testEndOfTemplateNext() - { - $stream = new TokenStream([ - new Token(Token::BLOCK_START_TYPE, 1, 1), - ]); - while (!$stream->isEOF()) { - $stream->next(); - } - } - - /** - * @expectedException \Twig\Error\SyntaxError - * @expectedExceptionMessage Unexpected end of template - */ - public function testEndOfTemplateLook() - { - $stream = new TokenStream([ - new Token(Token::BLOCK_START_TYPE, 1, 1), - ]); - while (!$stream->isEOF()) { - $stream->look(); - $stream->next(); - } - } -} diff --git a/lib/twig/twig/test/Twig/Tests/Util/DeprecationCollectorTest.php b/lib/twig/twig/test/Twig/Tests/Util/DeprecationCollectorTest.php deleted file mode 100644 index 0f577c60f..000000000 --- a/lib/twig/twig/test/Twig/Tests/Util/DeprecationCollectorTest.php +++ /dev/null @@ -1,46 +0,0 @@ -getMockBuilder('\Twig\Loader\LoaderInterface')->getMock()); - $twig->addFunction(new TwigFunction('deprec', [$this, 'deprec'], ['deprecated' => true])); - - $collector = new DeprecationCollector($twig); - $deprecations = $collector->collect(new Twig_Tests_Util_Iterator()); - - $this->assertEquals(['Twig Function "deprec" is deprecated in deprec.twig at line 1.'], $deprecations); - } - - public function deprec() - { - } -} - -class Twig_Tests_Util_Iterator implements \IteratorAggregate -{ - public function getIterator() - { - return new \ArrayIterator([ - 'ok.twig' => '{{ foo }}', - 'deprec.twig' => '{{ deprec("foo") }}', - ]); - } -} diff --git a/lib/twig/twig/test/Twig/Tests/escapingTest.php b/lib/twig/twig/test/Twig/Tests/escapingTest.php deleted file mode 100644 index 6de31a935..000000000 --- a/lib/twig/twig/test/Twig/Tests/escapingTest.php +++ /dev/null @@ -1,325 +0,0 @@ - ''', - '"' => '"', - '<' => '<', - '>' => '>', - '&' => '&', - ]; - - protected $htmlAttrSpecialChars = [ - '\'' => ''', - /* Characters beyond ASCII value 255 to unicode escape */ - 'Ā' => 'Ā', - '😀' => '😀', - /* Immune chars excluded */ - ',' => ',', - '.' => '.', - '-' => '-', - '_' => '_', - /* Basic alnums excluded */ - 'a' => 'a', - 'A' => 'A', - 'z' => 'z', - 'Z' => 'Z', - '0' => '0', - '9' => '9', - /* Basic control characters and null */ - "\r" => ' ', - "\n" => ' ', - "\t" => ' ', - "\0" => '�', // should use Unicode replacement char - /* Encode chars as named entities where possible */ - '<' => '<', - '>' => '>', - '&' => '&', - '"' => '"', - /* Encode spaces for quoteless attribute protection */ - ' ' => ' ', - ]; - - protected $jsSpecialChars = [ - /* HTML special chars - escape without exception to hex */ - '<' => '\\u003C', - '>' => '\\u003E', - '\'' => '\\u0027', - '"' => '\\u0022', - '&' => '\\u0026', - '/' => '\\/', - /* Characters beyond ASCII value 255 to unicode escape */ - 'Ā' => '\\u0100', - '😀' => '\\uD83D\\uDE00', - /* Immune chars excluded */ - ',' => ',', - '.' => '.', - '_' => '_', - /* Basic alnums excluded */ - 'a' => 'a', - 'A' => 'A', - 'z' => 'z', - 'Z' => 'Z', - '0' => '0', - '9' => '9', - /* Basic control characters and null */ - "\r" => '\r', - "\n" => '\n', - "\x08" => '\b', - "\t" => '\t', - "\x0C" => '\f', - "\0" => '\\u0000', - /* Encode spaces for quoteless attribute protection */ - ' ' => '\\u0020', - ]; - - protected $urlSpecialChars = [ - /* HTML special chars - escape without exception to percent encoding */ - '<' => '%3C', - '>' => '%3E', - '\'' => '%27', - '"' => '%22', - '&' => '%26', - /* Characters beyond ASCII value 255 to hex sequence */ - 'Ā' => '%C4%80', - /* Punctuation and unreserved check */ - ',' => '%2C', - '.' => '.', - '_' => '_', - '-' => '-', - ':' => '%3A', - ';' => '%3B', - '!' => '%21', - /* Basic alnums excluded */ - 'a' => 'a', - 'A' => 'A', - 'z' => 'z', - 'Z' => 'Z', - '0' => '0', - '9' => '9', - /* Basic control characters and null */ - "\r" => '%0D', - "\n" => '%0A', - "\t" => '%09', - "\0" => '%00', - /* PHP quirks from the past */ - ' ' => '%20', - '~' => '~', - '+' => '%2B', - ]; - - protected $cssSpecialChars = [ - /* HTML special chars - escape without exception to hex */ - '<' => '\\3C ', - '>' => '\\3E ', - '\'' => '\\27 ', - '"' => '\\22 ', - '&' => '\\26 ', - /* Characters beyond ASCII value 255 to unicode escape */ - 'Ā' => '\\100 ', - /* Immune chars excluded */ - ',' => '\\2C ', - '.' => '\\2E ', - '_' => '\\5F ', - /* Basic alnums excluded */ - 'a' => 'a', - 'A' => 'A', - 'z' => 'z', - 'Z' => 'Z', - '0' => '0', - '9' => '9', - /* Basic control characters and null */ - "\r" => '\\D ', - "\n" => '\\A ', - "\t" => '\\9 ', - "\0" => '\\0 ', - /* Encode spaces for quoteless attribute protection */ - ' ' => '\\20 ', - ]; - - protected $env; - - protected function setUp() - { - $this->env = new \Twig\Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock()); - } - - public function testHtmlEscapingConvertsSpecialChars() - { - foreach ($this->htmlSpecialChars as $key => $value) { - $this->assertEquals($value, twig_escape_filter($this->env, $key, 'html'), 'Failed to escape: '.$key); - } - } - - public function testHtmlAttributeEscapingConvertsSpecialChars() - { - foreach ($this->htmlAttrSpecialChars as $key => $value) { - $this->assertEquals($value, twig_escape_filter($this->env, $key, 'html_attr'), 'Failed to escape: '.$key); - } - } - - public function testJavascriptEscapingConvertsSpecialChars() - { - foreach ($this->jsSpecialChars as $key => $value) { - $this->assertEquals($value, twig_escape_filter($this->env, $key, 'js'), 'Failed to escape: '.$key); - } - } - - public function testJavascriptEscapingReturnsStringIfZeroLength() - { - $this->assertEquals('', twig_escape_filter($this->env, '', 'js')); - } - - public function testJavascriptEscapingReturnsStringIfContainsOnlyDigits() - { - $this->assertEquals('123', twig_escape_filter($this->env, '123', 'js')); - } - - public function testCssEscapingConvertsSpecialChars() - { - foreach ($this->cssSpecialChars as $key => $value) { - $this->assertEquals($value, twig_escape_filter($this->env, $key, 'css'), 'Failed to escape: '.$key); - } - } - - public function testCssEscapingReturnsStringIfZeroLength() - { - $this->assertEquals('', twig_escape_filter($this->env, '', 'css')); - } - - public function testCssEscapingReturnsStringIfContainsOnlyDigits() - { - $this->assertEquals('123', twig_escape_filter($this->env, '123', 'css')); - } - - public function testUrlEscapingConvertsSpecialChars() - { - foreach ($this->urlSpecialChars as $key => $value) { - $this->assertEquals($value, twig_escape_filter($this->env, $key, 'url'), 'Failed to escape: '.$key); - } - } - - /** - * Range tests to confirm escaped range of characters is within OWASP recommendation. - */ - - /** - * Only testing the first few 2 ranges on this prot. function as that's all these - * other range tests require. - */ - public function testUnicodeCodepointConversionToUtf8() - { - $expected = ' ~ޙ'; - $codepoints = [0x20, 0x7e, 0x799]; - $result = ''; - foreach ($codepoints as $value) { - $result .= $this->codepointToUtf8($value); - } - $this->assertEquals($expected, $result); - } - - /** - * Convert a Unicode Codepoint to a literal UTF-8 character. - * - * @param int $codepoint Unicode codepoint in hex notation - * - * @return string UTF-8 literal string - */ - protected function codepointToUtf8($codepoint) - { - if ($codepoint < 0x80) { - return \chr($codepoint); - } - if ($codepoint < 0x800) { - return \chr($codepoint >> 6 & 0x3f | 0xc0) - .\chr($codepoint & 0x3f | 0x80); - } - if ($codepoint < 0x10000) { - return \chr($codepoint >> 12 & 0x0f | 0xe0) - .\chr($codepoint >> 6 & 0x3f | 0x80) - .\chr($codepoint & 0x3f | 0x80); - } - if ($codepoint < 0x110000) { - return \chr($codepoint >> 18 & 0x07 | 0xf0) - .\chr($codepoint >> 12 & 0x3f | 0x80) - .\chr($codepoint >> 6 & 0x3f | 0x80) - .\chr($codepoint & 0x3f | 0x80); - } - throw new \Exception('Codepoint requested outside of Unicode range.'); - } - - public function testJavascriptEscapingEscapesOwaspRecommendedRanges() - { - $immune = [',', '.', '_']; // Exceptions to escaping ranges - for ($chr = 0; $chr < 0xFF; ++$chr) { - if ($chr >= 0x30 && $chr <= 0x39 - || $chr >= 0x41 && $chr <= 0x5A - || $chr >= 0x61 && $chr <= 0x7A) { - $literal = $this->codepointToUtf8($chr); - $this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'js')); - } else { - $literal = $this->codepointToUtf8($chr); - if (\in_array($literal, $immune)) { - $this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'js')); - } else { - $this->assertNotEquals( - $literal, - twig_escape_filter($this->env, $literal, 'js'), - "$literal should be escaped!"); - } - } - } - } - - public function testHtmlAttributeEscapingEscapesOwaspRecommendedRanges() - { - $immune = [',', '.', '-', '_']; // Exceptions to escaping ranges - for ($chr = 0; $chr < 0xFF; ++$chr) { - if ($chr >= 0x30 && $chr <= 0x39 - || $chr >= 0x41 && $chr <= 0x5A - || $chr >= 0x61 && $chr <= 0x7A) { - $literal = $this->codepointToUtf8($chr); - $this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'html_attr')); - } else { - $literal = $this->codepointToUtf8($chr); - if (\in_array($literal, $immune)) { - $this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'html_attr')); - } else { - $this->assertNotEquals( - $literal, - twig_escape_filter($this->env, $literal, 'html_attr'), - "$literal should be escaped!"); - } - } - } - } - - public function testCssEscapingEscapesOwaspRecommendedRanges() - { - // CSS has no exceptions to escaping ranges - for ($chr = 0; $chr < 0xFF; ++$chr) { - if ($chr >= 0x30 && $chr <= 0x39 - || $chr >= 0x41 && $chr <= 0x5A - || $chr >= 0x61 && $chr <= 0x7A) { - $literal = $this->codepointToUtf8($chr); - $this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'css')); - } else { - $literal = $this->codepointToUtf8($chr); - $this->assertNotEquals( - $literal, - twig_escape_filter($this->env, $literal, 'css'), - "$literal should be escaped!"); - } - } - } -}