8000 Merge branch '3.1' into 3.2 · symfony/symfony@ec858ce · GitHub
[go: up one dir, main page]

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 ec858ce

Browse files
Merge branch '3.1' into 3.2
* 3.1: Fix getMock usage Remove dead code [Form] DateTimeToLocalizedStringTransformer does not use TZ when using only date [Validator] Fix caching of constraints derived from non-serializable parents [TwigBundle] Fix bug where namespaced paths don't take parent bundles in account [FrameworkBundle] Fix relative paths used as cache keys respect groups when merging constraints fix IPv6 address handling in server commands
2 parents 2e4d87f + 473fd3b commit ec858ce

File tree

16 files changed

+234
-45
lines changed

16 files changed

+234
-45
lines changed

src/Symfony/Bundle/FrameworkBundle/Command/ServerCommand.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ protected function isOtherServerProcessRunning($address)
5454
return true;
5555
}
5656

57-
list($hostname, $port) = explode(':', $address);
57+
$pos = strrpos($address, ':');
58+
$hostname = substr($address, 0, $pos);
59+
$port = substr($address, $pos + 1);
5860

5961
$fp = @fsockopen($hostname, $port, $errno, $errstr, 5);
6062

src/Symfony/Bundle/FrameworkBundle/Templating/Loader/TemplateLocator.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class TemplateLocator implements FileLocatorInterface
2424
protected $locator;
2525
protected $cache;
2626

27+
private $cacheHits = array();
28+
2729
/**
2830
* Constructor.
2931
*
@@ -71,12 +73,15 @@ public function locate($template, $currentPath = null, $first = true)
7173

7274
$key = $this->getCacheKey($template);
7375

76+
if (isset($this->cacheHits[$key])) {
77+
return $this->cacheHits[$key];
78+
}
7479
if (isset($this->cache[$key])) {
75-
return $this->cache[$key];
80+
return $this->cacheHits[$key] = realpath($this->cache[$key]) ?: $this->cache[$key];
7681
}
7782

7883
try {
79-
return $this->cache[$key] = $this->locator->locate($template->getPath(), $currentPath);
84+
return $this->cacheHits[$key] = $this->locator->locate($template->getPath(), $currentPath);
8085
} catch (\InvalidArgumentException $e) {
8186
throw new \InvalidArgumentException(sprintf('Unable to find template "%s" : "%s".', $template, $e->getMessage()), 0, $e);
8287
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
return array(
4+
'bundle:controller:name.format.engine' => __DIR__.'/../Fixtures/Resources/views/this.is.a.template.format.engine',
5+
);

src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Loader/TemplateLocatorTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ public function testLocateATemplate()
3838
$this->assertEquals('/path/to/template', $locator->locate($template));
3939
}
4040

41+
public function testLocateATemplateFromCacheDir()
42+
{
43+
$template = new TemplateReference('bundle', 'controller', 'name', 'format', 'engine');
44+
45+
$fileLocator = $this->getFileLocator();
46+
47+
$locator = new TemplateLocator($fileLocator, __DIR__.'/../../Fixtures');
48+
49+
$this->assertEquals(realpath(__DIR__.'/../../Fixtures/Resources/views/this.is.a.template.format.engine'), $locator->locate($template));
50+
}
51+
4152
public function testThrowsExceptionWhenTemplateNotFound()
4253
{
4354
$template = new TemplateReference('bundle', 'controller', 'name', 'format', 'engine');

src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -92,23 +92,23 @@ public function load(array $configs, ContainerBuilder $container)
9292
$container->getDefinition('twig.cache_warmer')->replaceArgument(2, $config['paths']);
9393
$container->getDefinition('twig.template_iterator')->replaceArgument(2, $config['paths']);
9494

95-
// register bundles as Twig namespaces
96-
foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
97-
$dir = $container->getParameter('kernel.root_dir').'/Resources/'.$name.'/views';
98-
if (is_dir($dir)) {
99-
$this->addTwigPath($twigFilesystemLoaderDefinition, $dir, $name);
95+
$bundleHierarchy = $this->getBundleHierarchy($container);
96+
97+
foreach ($bundleHierarchy as $name => $bundle) {
98+
$namespace = $this->normalizeBundleName($name);
99+
100+
foreach ($bundle['children'] as $child) {
101+
foreach ($bundleHierarchy[$child]['paths'] as $path) {
102+
$twigFilesystemLoaderDefinition->addMethodCall('addPath', array($path, $namespace));
103+
}
100104
}
101-
$container->addResource(new FileExistenceResource($dir));
102105

103-
$dir = $bundle['path'].'/Resources/views';
104-
if (is_dir($dir)) {
105-
$this->addTwigPath($twigFilesystemLoaderDefinition, $dir, $name);
106+
foreach ($bundle['paths'] as $path) {
107+
$twigFilesystemLoaderDefinition->addMethodCall('addPath', array($path, $namespace));
106108
}
107-
$container->addResource(new FileExistenceResource($dir));
108109
}
109110

110-
$dir = $container->getParameter('kernel.root_dir').'/Resources/views';
111-
if (is_dir($dir)) {
111+
if (is_dir($dir = $container->getParameter('kernel.root_dir').'/Resources/views')) {
112112
$twigFilesystemLoaderDefinition->addMethodCall('addPath', array($dir));
113113
}
114114
$container->addResource(new FileExistenceResource($dir));
@@ -149,13 +149,65 @@ public function load(array $configs, ContainerBuilder $container)
149149
));
150150
}
151151

152-
private function addTwigPath($twigFilesystemLoaderDefinition, $dir, $bundle)
152+
private function getBundleHierarchy(ContainerBuilder $container)
153+
{
154+
$bundleHierarchy = array();
155+
156+
foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
157+
if (!array_key_exists($name, $bundleHierarchy)) {
158+
$bundleHierarchy[$name] = array(
159+
'paths' => array(),
160+
'parents' => array(),
161+
'children' => array(),
162+
);
163+
}
164+
165+
if (is_dir($dir = $container->getParameter('kernel.root_dir').'/Resources/'.$name.'/views')) {
166+
$bundleHierarchy[$name]['paths'][] = $dir;
167+
}
168+
$container->addResource(new FileExistenceResource($dir));
169+
170+
if (is_dir($dir = $bundle['path'].'/Resources/views')) {
171+
$bundleHierarchy[$name]['paths'][] = $dir;
172+
}
173+
$container->addResource(new FileExistenceResource($dir));
174+
175+
if (null === $bundle['parent']) {
176+
continue;
177+
}
178+
179+
$bundleHierarchy[$name]['parents'][] = $bundle['parent'];
180+
181+
if (!array_key_exists($bundle['parent'], $bundleHierarchy)) {
182+
$bundleHierarchy[$bundle['parent']] = array(
183+
'paths' => array(),
184+
'parents' => array(),
185+
'children' => array(),
186+
);
187+
}
188+
189+
$bundleHierarchy[$bundle['parent']]['children'] = array_merge($bundleHierarchy[$name]['children'], array($name), $bundleHierarchy[$bundle['parent']]['children']);
190+
191+
foreach ($bundleHierarchy[$bundle['parent']]['parents'] as $parent) {
192+
$bundleHierarchy[$name]['parents'][] = $parent;
193+
$bundleHierarchy[$parent]['children'] = array_merge($bundleHierarchy[$name]['children'], array($name), $bundleHierarchy[$parent]['children']);
194+
}
195+
196+
foreach ($bundleHierarchy[$name]['children'] as $child) {
197+
$bundleHierarchy[$child]['parents'] = array_merge($bundleHierarchy[$child]['parents'], $bundleHierarchy[$name]['parents']);
198+
}
199+
}
200+
201+
return $bundleHierarchy;
202+
}
203+
204+
private function normalizeBundleName($name)
153205
{
154-
$name = $bundle;
155206
if ('Bundle' === substr($name, -6)) {
156207
$name = substr($name, 0, -6);
157208
}
158-
$twigFilesystemLoaderDefinition->addMethodCall('addPath', array($dir, $name));
209+
210+
return $name;
159211
}
160212

161213
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a layout
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a layout
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a layout
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a layout

src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,22 @@ public function testTwigLoaderPaths($format)
167167
array('namespaced_path1', 'namespace1'),
168168
array('namespaced_path2', 'namespace2'),
169169
array('namespaced_path3', 'namespace3'),
170+
array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildChildChildChildTwig'),
171+
array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildChildChildTwig'),
172+
array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildChildChildTwig'),
173+
array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'Twig'),
174+
array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'Twig'),
175+
array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'Twig'),
176+
array(__DIR__.'/Fixtures/Bundle/ChildTwigBundle/Resources/views', 'Twig'),
170177
array(__DIR__.'/Fixtures/Resources/TwigBundle/views', 'Twig'),
171178
array(realpath(__DIR__.'/../..').'/Resources/views', 'Twig'),
179+
array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildTwig'),
180+
array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildTwig'),
181+
array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'ChildTwig'),
182+
array(__DIR__.'/Fixtures/Bundle/ChildTwigBundle/Resources/views', 'ChildTwig'),
183+
array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildChildTwig'),
184+
array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildChildTwig'),
185+
array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'ChildChildTwig'),
172186
array(__DIR__.'/Fixtures/Resources/views'),
173187
), $paths);
174188
}
@@ -244,8 +258,40 @@ private function createContainer()
244258
'kernel.root_dir' => __DIR__.'/Fixtures',
245259
'kernel.charset' => 'UTF-8',
246260
'kernel.debug' => false,
247-
'kernel.bundles' => array('TwigBundle' => 'Symfony\\Bundle\\TwigBundle\\TwigBundle'),
248-
'kernel.bundles_metadata' => array('TwigBundle' => array('namespace' => 'Symfony\\Bundle\\TwigBundle', 'parent' => null, 'path' => realpath(__DIR__.'/../..'))),
261+
'kernel.bundles' => array(
262+
'TwigBundle' => 'Symfony\\Bundle\\TwigBundle\\TwigBundle',
263+
'ChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildTwigBundle\\ChildTwigBundle',
264+
'ChildChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildTwigBundle\\ChildChildTwigBundle',
265+
'ChildChildChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildTwigBundle\\ChildChildChildTwigBundle',
266+
'ChildChildChildChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildChildTwigBundle\\ChildChildChildChildTwigBundle',
267+
),
268+
'kernel.bundles_metadata' => array(
269+
'ChildChildChildChildTwigBundle' => array(
270+
'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildChildTwigBundle\\ChildChildChildChildTwigBundle',
271+
'parent' => 'ChildChildChildTwigBundle',
272+
'path' => __DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle',
273+
),
274+
'TwigBundle' => array(
275+
'namespace' => 'Symfony\\Bundle\\TwigBundle',
276+
'parent' => null,
277+
'path' => realpath(__DIR__.'/../..'),
278+
),
279+
'ChildTwigBundle' => array(
280+
'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildTwigBundle\\ChildTwigBundle',
281+
'parent' => 'TwigBundle',
282+
'path' => __DIR__.'/Fixtures/Bundle/ChildTwigBundle',
283+
),
284+
'ChildChildChildTwigBundle' => array(
285+
'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildTwigBundle\\ChildChildChildTwigBundle',
286+
'parent' => 'ChildChildTwigBundle',
287+
'path' => __DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle',
288+
),
289+
'ChildChildTwigBundle' => array(
290+
'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildTwigBundle\\ChildChildTwigBundle',
291+
'parent' => 'ChildTwigBundle',
292+
'path' => __DIR__.'/Fixtures/Bundle/ChildChildTwigBundle',
293+
),
294+
),
249295
)));
250296

251297
return $container;

src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,11 @@ public function reverseTransform($value)
129129
try {
130130
if ($dateOnly) {
131131
// we only care about year-month-date, which has been delivered as a timestamp pointing to UTC midnight
132-
return new \DateTime(gmdate('Y-m-d', $timestamp), new \DateTimeZone($this->inputTimezone));
132+
$dateTime = new \DateTime(gmdate('Y-m-d', $timestamp), new \DateTimeZone($this->outputTimezone));
133+
} else {
134+
// read timestamp into DateTime object - the formatter delivers a timestamp
135+
$dateTime = new \DateTime(sprintf('@%s', $timestamp));
133136
}
134-
135-
// read timestamp into DateTime object - the formatter delivers a timestamp
136-
$dateTime = new \DateTime(sprintf('@%s', $timestamp));
137137
// set timezone separately, as it would be ignored if set via the constructor,
138138
// see http://php.net/manual/en/datetime.construct.php
139139
$dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));

src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,15 @@ public function testReverseTransformWithDifferentTimezones()
237237
$this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('03.02.2010, 04:05'));
238238
}
239239

240+
public function testReverseTransformOnlyDateWithDifferentTimezones()
241+
{
242+
$transformer = new DateTimeToLocalizedStringTransformer('Europe/Berlin', 'Pacific/Tahiti', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'yyyy-MM-dd');
243+
244+
$dateTime = new \DateTime('2017-01-10 11:00', new \DateTimeZone('Europe/Berlin'));
245+
246+
$this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('2017-01-10'));
247+
}
248+
240249
public function testReverseTransformWithDifferentPatterns()
241250
{
242251
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss');

src/Symfony/Component/Validator/Mapping/ClassMetadata.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,10 @@ public function mergeConstraints(ClassMetadata $source)
312312
$member = clone $member;
313313

314314
foreach ($member->getConstraints() as $constraint) {
315-
$member->constraintsByGroup[$this->getDefaultGroup()][] = $constraint;
315+
if (in_array($constraint::DEFAULT_GROUP, $constraint->groups, true)) {
316+
$member->constraintsByGroup[$this->getDefaultGroup()][] = $constraint;
317+
}
318+
316319
$constraint->addImplicitGroupName($this->getDefaultGroup());
317320
}
318321

src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,11 @@ public function getMetadataFor($value)
9999
return $this->loadedClasses[$class];
100100
}
101101

102-
if (null !== $this->cache && false !== ($this->loadedClasses[$class] = $this->cache->read($class))) {
103-
return $this->loadedClasses[$class];
102+
if (null !== $this->cache && false !== ($metadata = $this->cache->read($class))) {
103+
// Include constraints from the parent class
104+
$this->mergeConstraints($metadata);
105+
106+
return $this->loadedClasses[$class] = $metadata;
104107
}
105108

106109
if (!class_exists($class) && !interface_exists($class)) {
@@ -109,6 +112,22 @@ public function getMetadataFor($value)
109112

110113
$metadata = new ClassMetadata($class);
111114

115+
if (null !== $this->loader) {
116+
$this->loader->loadClassMetadata($metadata);
117+
}
118+
119+
if (null !== $this->cache) {
120+
$this->cache->write($metadata);
121+
}
122+
123+
// Include constraints from the parent class
124+
$this->mergeConstraints($metadata);
125+
126+
return $this->loadedClasses[$class] = $metadata;
127+
}
128+
129+
private function mergeConstraints(ClassMetadata $metadata)
130+
{
112131
// Include constraints from the parent class
113132
if ($parent = $metadata->getReflectionClass()->getParentClass()) {
114133
$metadata->mergeConstraints($this->getMetadataFor($parent->name));
@@ -139,16 +158,6 @@ public function getMetadataFor($value)
139158
}
140159
$metadata->mergeConstraints($this->getMetadataFor($interface->name));
141160
}
142-
143-
if (null !== $this->loader) {
144-
$this->loader->loadClassMetadata($metadata);
145-
}
146-
147-
if (null !== $this->cache) {
148-
$this->cache->write($metadata);
149-
}
150-
151-
return $this->loadedClasses[$class] = $metadata;
152161
}
153162

154163
/**

src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ public function testMergeConstraintsMergesMemberConstraints()
135135
{
136136
$parent = new ClassMetadata(self::PARENTCLASS);
137137
$parent->addPropertyConstraint('firstName', new ConstraintA());
138+
$parent->addPropertyConstraint('firstName', new ConstraintB(array('groups' => 'foo')));
138139

139140
$this->metadata->mergeConstraints($parent);
140141
$this->metadata->addPropertyConstraint('firstName', new ConstraintA());
@@ -148,9 +149,13 @@ public function testMergeConstraintsMergesMemberConstraints()
148149
'Default',
149150
'Entity',
150151
)));
152+
$constraintB = new ConstraintB(array(
153+
'groups' => array('foo'),
154+
));
151155

152156
$constraints = array(
153157
$constraintA1,
158+
$constraintB,
154159
$constraintA2,
155160
);
156161

@@ -166,6 +171,9 @@ public function testMergeConstraintsMergesMemberConstraints()
166171
$constraintA1,
167172
$constraintA2,
168173
),
174+
'foo' => array(
175+
$constraintB,
176+
),
169177
);
170178

171179
$members = $this->metadata->getPropertyMetadata('firstName');

0 commit comments

Comments
 (0)
0