Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d4f3b68

Browse filesBrowse files
Merge branch '4.3' into 4.4
* 4.3: Sync Twig templateExists behaviors Fix the :only-of-type pseudo class selector [Serializer] Add CsvEncoder tests for PHP 7.4 Copy phpunit.xsd to a predictable path [Security/Http] fix parsing X509 emailAddress [Serializer] fix denormalization of string-arrays with only one element #33731 [Cache] fix known tag versions ttl check
2 parents 7020f26 + b628210 commit d4f3b68
Copy full SHA for d4f3b68

File tree

17 files changed

+253
-77
lines changed
Filter options

17 files changed

+253
-77
lines changed

‎src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s': 'rm -rf %s', "$PHPUNIT_VERSION_DIR.old"));
117117
}
118118
passthru("$COMPOSER create-project --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi phpunit/phpunit $PHPUNIT_VERSION_DIR \"$PHPUNIT_VERSION.*\"");
119+
@copy("$PHPUNIT_VERSION_DIR/phpunit.xsd", 'phpunit.xsd');
119120
chdir("$PHPUNIT_VERSION_DIR");
120121
if ($SYMFONY_PHPUNIT_REMOVE) {
121122
passthru("$COMPOSER remove --no-update ".$SYMFONY_PHPUNIT_REMOVE);

‎src/Symfony/Bridge/Twig/TwigEngine.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Twig/TwigEngine.php
+15-9Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Twig\Error\Error;
2222
use Twig\Error\LoaderError;
2323
use Twig\Loader\ExistsLoaderInterface;
24+
use Twig\Loader\SourceContextLoaderInterface;
2425
use Twig\Template;
2526

2627
/**
@@ -78,19 +79,24 @@ public function exists($name)
7879

7980
$loader = $this->environment->getLoader();
8081

81-
if ($loader instanceof ExistsLoaderInterface || method_exists($loader, 'exists')) {
82-
return $loader->exists((string) $name);
83-
}
82+
if (1 === Environment::MAJOR_VERSION && !$loader instanceof ExistsLoaderInterface) {
83+
try {
84+
// cast possible TemplateReferenceInterface to string because the
85+
// EngineInterface supports them but LoaderInterface does not
86+
if ($loader instanceof SourceContextLoaderInterface) {
87+
$loader->getSourceContext((string) $name);
88+
} else {
89+
$loader->getSource((string) $name);
90+
}
91+
92+
return true;
93+
} catch (LoaderError $e) {
94+
}
8495

85-
try {
86-
// cast possible TemplateReferenceInterface to string because the
87-
// EngineInterface supports them but LoaderInterface does not
88-
$loader->getSourceContext((string) $name)->getCode();
89-
} catch (LoaderError $e) {
9096
return false;
9197
}
9298

93-
return true;
99+
return $loader->exists((string) $name);
94100
}
95101

96102
/**

‎src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
+15-9Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Twig\Environment;
1919
use Twig\Error\LoaderError;
2020
use Twig\Loader\ExistsLoaderInterface;
21+
use Twig\Loader\SourceContextLoaderInterface;
2122

2223
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ExceptionController::class, \Symfony\Component\HttpKernel\Controller\ErrorController::class), E_USER_DEPRECATED);
2324

@@ -124,23 +125,28 @@ protected function findTemplate(Request $request, $format, $code, $showException
124125
return sprintf('@Twig/Exception/%s.html.twig', $showException ? 'exception_full' : $name);
125126
}
126127

127-
// to be removed when the minimum required version of Twig is >= 3.0
128+
// to be removed when the minimum required version of Twig is >= 2.0
128129
protected function templateExists($template)
129130
{
130131
$template = (string) $template;
131132

132133
$loader = $this->twig->getLoader();
133-
if ($loader instanceof ExistsLoaderInterface || method_exists($loader, 'exists')) {
134-
return $loader->exists($template);
135-
}
136134

137-
try {
138-
$loader->getSourceContext($template)->getCode();
135+
if (1 === Environment::MAJOR_VERSION && !$loader instanceof ExistsLoaderInterface) {
136+
try {
137+
if ($loader instanceof SourceContextLoaderInterface) {
138+
$loader->getSourceContext($template);
139+
} else {
140+
$loader->getSource($template);
141+
}
142+
143+
return true;
144+
} catch (LoaderError $e) {
145+
}
139146

140-
return true;
141-
} catch (LoaderError $e) {
147+
return false;
142148
}
143149

144-
return false;
150+
return $loader->exists($template);
145151
}
146152
}

‎src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionController.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionController.php
+14-8Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Twig\Environment;
2020
use Twig\Error\LoaderError;
2121
use Twig\Loader\ExistsLoaderInterface;
22+
use Twig\Loader\SourceContextLoaderInterface;
2223

2324
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ExceptionController::class, ExceptionPanelController::class), E_USER_DEPRECATED);
2425

@@ -120,17 +121,22 @@ protected function getTemplate()
120121
protected function templateExists($template)
121122
{
122123
$loader = $this->twig->getLoader();
123-
if ($loader instanceof ExistsLoaderInterface) {
124-
return $loader->exists($template);
125-
}
126124

127-
try {
128-
$loader->getSource($template);
125+
if (1 === Environment::MAJOR_VERSION && !$loader instanceof ExistsLoaderInterface) {
126+
try {
127+
if ($loader instanceof SourceContextLoaderInterface) {
128+
$loader->getSourceContext($template);
129+
} else {
130+
$loader->getSource($template);
131+
}
132+
133+
return true;
134+
} catch (LoaderError $e) {
135+
}
129136

130-
return true;
131-
} catch (LoaderError $e) {
137+
return false;
132138
}
133139

134-
return false;
140+
return $loader->exists($template);
135141
}
136142
}

‎src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php
+12-11Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -106,21 +106,22 @@ protected function templateExists($template/*, bool $triggerDeprecation = true *
106106
}
107107

108108
$loader = $this->twig->getLoader();
109-
if ($loader instanceof ExistsLoaderInterface) {
110-
return $loader->exists($template);
111-
}
112109

113-
try {
114-
if ($loader instanceof SourceContextLoaderInterface || method_exists($loader, 'getSourceContext')) {
115-
$loader->getSourceContext($template);
116-
} else {
117-
$loader->getSource($template);
110+
if (1 === Environment::MAJOR_VERSION && !$loader instanceof ExistsLoaderInterface) {
111+
try {
112+
if ($loader instanceof SourceContextLoaderInterface) {
113+
$loader->getSourceContext($template);
114+
} else {
115+
$loader->getSource($template);
116+
}
117+
118+
return true;
119+
} catch (LoaderError $e) {
118120
}
119121

120-
return true;
121-
} catch (LoaderError $e) {
122+
return false;
122123
}
123124

124-
return false;
125+
return $loader->exists($template);
125126
}
126127
}

‎src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ protected function mockTwigEnvironment()
110110
$loader = $this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock();
111111
$loader->method('getSourceContext')->willReturn(new Source('source-code', 'source-name'));
112112
}
113+
113114
$this->twigEnvironment->expects($this->any())->method('getLoader')->willReturn($loader);
114115

115116
return $this->twigEnvironment;

‎src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ private function getTagVersions(array $tagsByKey, array &$invalidatedTags = [])
384384
continue;
385385
}
386386
$version -= $this->knownTagVersions[$tag][1];
387-
if ((0 !== $version && 1 !== $version) || $this->knownTagVersionsTtl > $now - $this->knownTagVersions[$tag][0]) {
387+
if ((0 !== $version && 1 !== $version) || $now - $this->knownTagVersions[$tag][0] >= $this->knownTagVersionsTtl) {
388388
// reuse previously fetched tag versions up to the ttl, unless we are storing items or a potential miss arises
389389
$fetchTagVersions = true;
390390
} else {

‎src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php
+37Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Cache\Tests\Adapter;
1313

1414
use PHPUnit\Framework\MockObject\MockObject;
15+
use Psr\Cache\CacheItemInterface;
1516
use Psr\Cache\CacheItemPoolInterface;
1617
use Symfony\Component\Cache\Adapter\AdapterInterface;
1718
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
@@ -67,6 +68,42 @@ public function testPrune()
6768
$this->assertFalse($cache->prune());
6869
}
6970

71+
public function testKnownTagVersionsTtl()
72+
{
73+
$itemsPool = new FilesystemAdapter('', 10);
74+
$tagsPool = $this
75+
->getMockBuilder(AdapterInterface::class)
76+
->getMock();
77+
78+
$pool = new TagAwareAdapter($itemsPool, $tagsPool, 10);
79+
80+
$item = $pool->getItem('foo');
81+
$item->tag(['baz']);
82+
$item->expiresAfter(100);
83+
84+
$tag = $this->getMockBuilder(CacheItemInterface::class)->getMock();
85+
$tag->expects(self::exactly(2))->method('get')->willReturn(10);
86+
87+
$tagsPool->expects(self::exactly(2))->method('getItems')->willReturn([
88+
'baz'.TagAwareAdapter::TAGS_PREFIX => $tag,
89+
]);
90+
91+
$pool->save($item);
92+
$this->assertTrue($pool->getItem('foo')->isHit());
93+
$this->assertTrue($pool->getItem('foo')->isHit());
94+
95+
sleep(20);
96+
97+
$this->assertTrue($pool->getItem('foo')->isHit());
98+
99+
sleep(5);
100+
101+
$this->assertTrue($pool->getItem('foo')->isHit());
102+
}
103+
104+
/**
105+
* @return MockObject|PruneableCacheInterface
106+
*/
70107
private function getPruneableMock(): AdapterInterface
71108
{
72109
$pruneable = $this->createMock([PruneableInterface::class, AdapterInterface::class]);

‎src/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php
+30-3Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public function testXmlLang($css, array $elementsId)
9898
$elements = $document->xpath($translator->cssToXPath($css));
9999
$this->assertCount(\count($elementsId), $elements);
100100
foreach ($elements as $element) {
101-
$this->assertTrue(\in_array($element->attributes()->id, $elementsId));
101+
$this->assertContains((string) $element->attributes()->id, $elementsId);
102102
}
103103
}
104104

@@ -116,7 +116,7 @@ public function testHtmlIds($css, array $elementsId)
116116
$this->assertCount(\count($elementsId), $elementsId);
117117
foreach ($elements as $element) {
118118
if (null !== $element->attributes()->id) {
119-
$this->assertTrue(\in_array($element->attributes()->id, $elementsId));
119+
$this->assertContains((string) $element->attributes()->id, $elementsId);
120120
}
121121
}
122122
libxml_clear_errors();
@@ -137,6 +137,33 @@ public function testHtmlShakespear($css, $count)
137137
$this->assertCount($count, $elements);
138138
}
139139

140+
public function testOnlyOfTypeFindsSingleChildrenOfGivenType()
141+
{
142+
$translator = new Translator();
143+
$translator->registerExtension(new HtmlExtension($translator));
144+
$document = new \DOMDocument();
145+
$document->loadHTML(<<<'HTML'
146+
<html>
147+
<body>
148+
<p>
149+
<span>A</span>
150+
</p>
151+
<p>
152+
<span>B</span>
153+
<span>C</span>
154+
</p>
155+
</body>
156+
</html>
157+
HTML
158+
);
159+
160+
$xpath = new \DOMXPath($document);
161+
$nodeList = $xpath->query($translator->cssToXPath('span:only-of-type'));
162+
163+
$this->assertSame(1, $nodeList->length);
164+
$this->assertSame('A', $nodeList->item(0)->textContent);
165+
}
166+
140167
public function getXpathLiteralTestData()
141168
{
142169
return [
@@ -175,7 +202,7 @@ public function getCssToXPathTestData()
175202
['e:first-of-type', '*/e[position() = 1]'],
176203
['e:last-of-type', '*/e[position() = last()]'],
177204
['e:only-child', "*/*[(name() = 'e') and (last() = 1)]"],
178-
['e:only-of-type', 'e[last() = 1]'],
205+
['e:only-of-type', 'e[count(preceding-sibling::e)=0 and count(following-sibling::e)=0]'],
179206
['e:empty', 'e[not(*) and not(string-length())]'],
180207
['e:EmPTY', 'e[not(*) and not(string-length())]'],
181208
['e:root', 'e[not(parent::*)]'],

‎src/Symfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.php
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,13 @@ public function translateOnlyChild(XPathExpr $xpath): XPathExpr
105105
*/
106106
public function translateOnlyOfType(XPathExpr $xpath): XPathExpr
107107
{
108-
if ('*' === $xpath->getElement()) {
108+
$element = $xpath->getElement();
109+
110+
if ('*' === $element) {
109111
throw new ExpressionErrorException('"*:only-of-type" is not implemented.');
110112
}
111113

112-
return $xpath->addCondition('last() = 1');
114+
return $xpath->addCondition(sprintf('count(preceding-sibling::%s)=0 and count(following-sibling::%s)=0', $element, $element));
113115
}
114116

115117
public function translateEmpty(XPathExpr $xpath): XPathExpr

‎src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php
+13-11Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Twig\Environment;
2020
use Twig\Error\LoaderError;
2121
use Twig\Loader\ExistsLoaderInterface;
22+
use Twig\Loader\SourceContextLoaderInterface;
2223

2324
/**
2425
* Implements the Hinclude rendering strategy.
@@ -136,22 +137,23 @@ private function templateExists(string $template): bool
136137
}
137138

138139
$loader = $this->templating->getLoader();
139-
if ($loader instanceof ExistsLoaderInterface || method_exists($loader, 'exists')) {
140-
return $loader->exists($template);
141-
}
142140

143-
try {
144-
if (method_exists($loader, 'getSourceContext')) {
145-
$loader->getSourceContext($template);
146-
} else {
147-
$loader->getSource($template);
141+
if (1 === Environment::MAJOR_VERSION && !$loader instanceof ExistsLoaderInterface) {
142+
try {
143+
if ($loader instanceof SourceContextLoaderInterface) {
144+
$loader->getSourceContext($template);
145+
} else {
146+
$loader->getSource($template);
147+
}
148+
149+
return true;
150+
} catch (LoaderError $e) {
148151
}
149152

150-
return true;
151-
} catch (LoaderError $e) {
153+
return false;
152154
}
153155

154-
return false;
156+
return $loader->exists($template);
155157
}
156158

157159
/**

‎src/Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ protected function getPreAuthenticatedData(Request $request)
4646
$user = $request->server->get($this->userKey);
4747
} elseif (
4848
$request->server->has($this->credentialKey)
49-
&& preg_match('#emailAddress=(.+\@.+\.[^,/]+)($|,|/)#', $request->server->get($this->credentialKey), $matches)
49+
&& preg_match('#emailAddress=([^,/@]++@[^,/]++)#', $request->server->get($this->credentialKey), $matches)
5050
) {
5151
$user = $matches[1];
5252
}

‎src/Symfony/Component/Security/Http/Tests/Firewall/X509AuthenticationListenerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Http/Tests/Firewall/X509AuthenticationListenerTest.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public static function dataProviderGetPreAuthenticatedDataNoUser()
8181
yield ['cert+something@example.com', 'CN=Sample certificate DN,emailAddress=cert+something@example.com'];
8282
yield ['cert+something@example.com', 'emailAddress=cert+something@example.com,CN=Sample certificate DN'];
8383
yield ['cert+something@example.com', 'emailAddress=cert+something@example.com'];
84+
yield ['firstname.lastname@mycompany.co.uk', 'emailAddress=firstname.lastname@mycompany.co.uk,CN=Firstname.Lastname,OU=london,OU=company design and engineering,OU=Issuer London,OU=Roaming,OU=Interactive,OU=Users,OU=Standard,OU=Business,DC=england,DC=core,DC=company,DC=co,DC=uk'];
8485
}
8586

8687
public function testGetPreAuthenticatedDataNoData()

‎src/Symfony/Component/Serializer/Encoder/CsvEncoder.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Encoder/CsvEncoder.php
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,12 @@ class CsvEncoder implements EncoderInterface, DecoderInterface
4545
/**
4646
* @param array $defaultContext
4747
*/
48-
public function __construct($defaultContext = [], string $enclosure = '"', string $escapeChar = '\\', string $keySeparator = '.', bool $escapeFormulas = false)
48+
public function __construct($defaultContext = [], string $enclosure = '"', string $escapeChar = '', string $keySeparator = '.', bool $escapeFormulas = false)
4949
{
50+
if ('' === $escapeChar && \PHP_VERSION_ID < 70400) {
51+
$escapeChar = '\\';
52+
}
53+
5054
if (!\is_array($defaultContext)) {
5155
@trigger_error('Passing configuration options directly to the constructor is deprecated since Symfony 4.2, use the default context instead.', E_USER_DEPRECATED);
5256

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.