Skip to content

Commit

Permalink
Merge branch '3.1'
Browse files Browse the repository at this point in the history
* 3.1:
  [TwigBridge] removed deprecations added in Twig 1.27
  PHP CS Fixer: use php_unit_dedicate_assert
  3.0 Upgrade Guide: Added details describing how to pass data to a form through the options resolver
  fixed Filesystem:makePathRelative and added 2 more testcases
  no 304 response if method is not cacheable
  move tags from decorated to decorating service
  • Loading branch information
fabpot committed Oct 18, 2016
2 parents 9fc7306 + f07bf03 commit de4a650
Show file tree
Hide file tree
Showing 27 changed files with 126 additions and 44 deletions.
1 change: 1 addition & 0 deletions .php_cs
Expand Up @@ -6,6 +6,7 @@ return Symfony\CS\Config\Config::create()
->fixers(array(
'long_array_syntax',
'php_unit_construct',
'php_unit_dedicate_assert',
))
->finder(
Symfony\CS\Finder\DefaultFinder::create()
Expand Down
52 changes: 52 additions & 0 deletions UPGRADE-3.0.md
Expand Up @@ -410,6 +410,58 @@ UPGRADE FROM 2.x to 3.0
$form = $this->createForm(MyType::class);
```

* Passing custom data to forms now needs to be done
through the options resolver.

In the controller:

Before:
```php
$form = $this->createForm(new MyType($variable), $entity, array(
'action' => $this->generateUrl('action_route'),
'method' => 'PUT',
));
```
After:
```php
$form = $this->createForm(MyType::class, $entity, array(
'action' => $this->generateUrl('action_route'),
'method' => 'PUT',
'custom_value' => $variable,
));
```
In the form type:

Before:
```php
class MyType extends AbstractType
{
private $value;

public function __construct($variableValue)
{
$this->value = $value;
}
// ...
}
```

After:
```php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$value = $options['custom_value'];
// ...
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'custom_value' => null,
));
}
```

* The alias option of the `form.type_extension` tag was removed in favor of
the `extended_type`/`extended-type` option.

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -18,7 +18,7 @@
"require": {
"php": ">=5.5.9",
"doctrine/common": "~2.4",
"twig/twig": "~1.26|~2.0",
"twig/twig": "~1.27|~2.0",
"psr/cache": "~1.0",
"psr/log": "~1.0",
"symfony/polyfill-intl-icu": "~1.0",
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bridge/Twig/Command/LintCommand.php
Expand Up @@ -142,7 +142,7 @@ private function validate(\Twig_Environment $twig, $template, $file)
try {
$temporaryLoader = new \Twig_Loader_Array(array((string) $file => $template));
$twig->setLoader($temporaryLoader);
$nodeTree = $twig->parse($twig->tokenize($template, (string) $file));
$nodeTree = $twig->parse($twig->tokenize(new \Twig_Source($template, (string) $file)));
$twig->compile($nodeTree);
$twig->setLoader($realLoader);
} catch (\Twig_Error $e) {
Expand Down
Expand Up @@ -23,7 +23,7 @@ public function testEscaping($template, $mustBeEscaped)
$twig = new \Twig_Environment($this->getMock('Twig_LoaderInterface'), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0));
$twig->addExtension(new RoutingExtension($this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface')));

$nodes = $twig->parse($twig->tokenize($template));
$nodes = $twig->parse($twig->tokenize(new \Twig_Source($template)));

$this->assertSame($mustBeEscaped, $nodes->getNode('body')->getNode(0)->getNode('expr') instanceof \Twig_Node_Expression_Filter);
}
Expand Down
Expand Up @@ -36,7 +36,7 @@ public function testTrans($template, $expected, array $variables = array())
$twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
$twig->addExtension(new TranslationExtension(new Translator('en', new MessageSelector())));

echo $twig->compile($twig->parse($twig->tokenize($twig->getLoader()->getSource('index'), 'index')))."\n\n";
echo $twig->compile($twig->parse($twig->tokenize(new \Twig_Source($twig->getLoader()->getSource('index'), 'index'))))."\n\n";
$this->assertEquals($expected, $this->getTemplate($template)->render($variables));
}

Expand Down
Expand Up @@ -25,7 +25,7 @@ public static function getModule($content)
new \Twig_Node_Expression_Array(array(), 0),
new \Twig_Node_Expression_Array(array(), 0),
null,
null
new \Twig_Source('')
);
}

Expand Down
Expand Up @@ -23,7 +23,7 @@ public function testCompile($source, $expected)
{
$env = new \Twig_Environment($this->getMock('Twig_LoaderInterface'), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
$env->addTokenParser(new FormThemeTokenParser());
$stream = $env->tokenize($source);
$stream = $env->tokenize(new \Twig_Source($source));
$parser = new \Twig_Parser($env);

$this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0));
Expand Down
Expand Up @@ -64,7 +64,7 @@ public function parse(\Twig_Token $token)
$body = $this->parser->subparse(array($this, 'decideTransChoiceFork'), true);

if (!$body instanceof \Twig_Node_Text && !$body instanceof \Twig_Node_Expression) {
throw new \Twig_Error_Syntax('A message inside a transchoice tag must be a simple text.', $body->getLine(), $stream->getFilename());
throw new \Twig_Error_Syntax('A message inside a transchoice tag must be a simple text.', $body->getLine(), $stream->getSourceContext()->getName());
}

$stream->expect(\Twig_Token::BLOCK_END_TYPE);
Expand Down
4 changes: 2 additions & 2 deletions src/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php
Expand Up @@ -55,7 +55,7 @@ public function parse(\Twig_Token $token)
$stream->next();
$locale = $this->parser->getExpressionParser()->parseExpression();
} elseif (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) {
throw new \Twig_Error_Syntax('Unexpected token. Twig was looking for the "with", "from", or "into" keyword.', $stream->getCurrent()->getLine(), $stream->getFilename());
throw new \Twig_Error_Syntax('Unexpected token. Twig was looking for the "with", "from", or "into" keyword.', $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName());
}
}

Expand All @@ -64,7 +64,7 @@ public function parse(\Twig_Token $token)
$body = $this->parser->subparse(array($this, 'decideTransFork'), true);

if (!$body instanceof \Twig_Node_Text && !$body instanceof \Twig_Node_Expression) {
throw new \Twig_Error_Syntax('A message inside a trans tag must be a simple text.', $body->getLine(), $stream->getFilename());
throw new \Twig_Error_Syntax('A message inside a trans tag must be a simple text.', $body->getLine(), $stream->getSourceContext()->getName());
}

$stream->expect(\Twig_Token::BLOCK_END_TYPE);
Expand Down
6 changes: 3 additions & 3 deletions src/Symfony/Bridge/Twig/Translation/TwigExtractor.php
Expand Up @@ -62,9 +62,9 @@ public function extract($resource, MessageCatalogue $catalogue)
$this->extractTemplate(file_get_contents($file->getPathname()), $catalogue);
} catch (\Twig_Error $e) {
if ($file instanceof SplFileInfo) {
$e->setTemplateFile($file->getRelativePathname());
$e->setTemplateName($file->getRelativePathname());
} elseif ($file instanceof \SplFileInfo) {
$e->setTemplateFile($file->getRealPath());
$e->setTemplateName($file->getRealPath());
}

throw $e;
Expand All @@ -85,7 +85,7 @@ protected function extractTemplate($template, MessageCatalogue $catalogue)
$visitor = $this->twig->getExtension('Symfony\Bridge\Twig\Extension\TranslationExtension')->getTranslationNodeVisitor();
$visitor->enable();

$this->twig->parse($this->twig->tokenize($template));
$this->twig->parse($this->twig->tokenize(new \Twig_Source($template)));

foreach ($visitor->getMessages() as $message) {
$catalogue->set(trim($message[0]), $this->prefix.trim($message[0]), $message[1] ?: $this->defaultDomain);
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bridge/Twig/composer.json
Expand Up @@ -17,7 +17,7 @@
],
"require": {
"php": ">=5.5.9",
"twig/twig": "~1.26|~2.0"
"twig/twig": "~1.27|~2.0"
},
"require-dev": {
"symfony/asset": "~2.8|~3.0",
Expand Down
Expand Up @@ -30,7 +30,7 @@ public function testProfilerIsDisabled($insulate)
$client->enableProfiler();
$crawler = $client->request('GET', '/profiler');
$profile = $client->getProfile();
$this->assertTrue(is_object($profile));
$this->assertInternalType('object', $profile);

$client->request('GET', '/profiler');
$this->assertFalse($client->getProfile());
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bundle/SecurityBundle/composer.json
Expand Up @@ -40,7 +40,7 @@
"symfony/yaml": "~2.8|~3.0",
"symfony/expression-language": "~2.8|~3.0",
"doctrine/doctrine-bundle": "~1.4",
"twig/twig": "~1.26|~2.0"
"twig/twig": "~1.27|~2.0"
},
"suggest": {
"symfony/security-acl": "For using the ACL functionality of this bundle"
Expand Down
Expand Up @@ -120,7 +120,7 @@ private function addTwigOptions(ArrayNodeDefinition $rootNode)
$rootNode
->fixXmlConfig('path')
->children()
->variableNode('autoescape')->defaultValue('filename')->end()
->variableNode('autoescape')->defaultValue('name')->end()
->scalarNode('autoescape_service')->defaultNull()->end()
->scalarNode('autoescape_service_method')->defaultNull()->end()
->scalarNode('base_template_class')->example('Twig_Template')->cannotBeEmpty()->end()
Expand Down
Expand Up @@ -113,7 +113,7 @@ public function testLoadDefaultTemplateEscapingGuesserConfiguration($format)
$this->compileContainer($container);

$options = $container->getDefinition('twig')->getArgument(1);
$this->assertEquals('filename', $options['autoescape']);
$this->assertEquals('name', $options['autoescape']);
}

public function testGlobalsWithDifferentTypesAndValues()
Expand Down
Expand Up @@ -28,7 +28,7 @@ public function testCacheIsProperlyWarmedWhenTemplatingIsAvailable()
$warmer->enableOptionalWarmers();
$warmer->warmUp($kernel->getCacheDir());

$this->assertTrue(file_exists($kernel->getCacheDir().'/twig'));
$this->assertFileExists($kernel->getCacheDir().'/twig');
}

public function testCacheIsProperlyWarmedWhenTemplatingIsDisabled()
Expand All @@ -40,7 +40,7 @@ public function testCacheIsProperlyWarmedWhenTemplatingIsDisabled()
$warmer->enableOptionalWarmers();
$warmer->warmUp($kernel->getCacheDir());

$this->assertTrue(file_exists($kernel->getCacheDir().'/twig'));
$this->assertFileExists($kernel->getCacheDir().'/twig');
}

protected function setUp()
Expand Down
4 changes: 2 additions & 2 deletions src/Symfony/Bundle/TwigBundle/TwigEngine.php
Expand Up @@ -51,8 +51,8 @@ public function render($name, array $parameters = array())
} catch (\Twig_Error $e) {
if ($name instanceof TemplateReference) {
try {
// try to get the real file name of the template where the error occurred
$e->setTemplateFile(sprintf('%s', $this->locator->locate($this->parser->parse($e->getTemplateFile()))));
// try to get the real name of the template where the error occurred
$e->setTemplateName(sprintf('%s', $this->locator->locate($this->parser->parse($e->getTemplateName()))));
} catch (\Exception $e2) {
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bundle/TwigBundle/composer.json
Expand Up @@ -20,7 +20,7 @@
"symfony/twig-bridge": "~3.2",
"symfony/http-foundation": "~2.8|~3.0",
"symfony/http-kernel": "~2.8|~3.0",
"twig/twig": "~1.26|~2.0"
"twig/twig": "~1.27|~2.0"
},
"require-dev": {
"symfony/asset": "~2.8|~3.0",
Expand Down
Expand Up @@ -51,10 +51,12 @@ public function process(ContainerBuilder $container)
$public = $alias->isPublic();
$container->setAlias($renamedId, new Alias((string) $alias, false));
} else {
$definition = $container->getDefinition($inner);
$public = $definition->isPublic();
$definition->setPublic(false);
$container->setDefinition($renamedId, $definition);
$decoratedDefinition = $container->getDefinition($inner);
$definition->setTags($decoratedDefinition->getTags(), $definition->getTags());
$public = $decoratedDefinition->isPublic();
$decoratedDefinition->setPublic(false);
$decoratedDefinition->setTags(array());
$container->setDefinition($renamedId, $decoratedDefinition);
}

$container->setAlias($inner, new Alias($id, $public));
Expand Down
Expand Up @@ -124,6 +124,24 @@ public function testProcessWithPriority()
$this->assertNull($quxDefinition->getDecoratedService());
}

public function testProcessMovesTagsFromDecoratedDefinitionToDecoratingDefinition()
{
$container = new ContainerBuilder();
$container
->register('foo')
->setTags(array('name' => 'bar'))
;
$container
->register('baz')
->setDecoratedService('foo')
;

$this->process($container);

$this->assertEmpty($container->getDefinition('baz.inner')->getTags());
$this->assertEquals(array('name' => 'bar'), $container->getDefinition('baz')->getTags());
}

protected function process(ContainerBuilder $container)
{
$repeatedPass = new DecoratorServicePass();
Expand Down
8 changes: 6 additions & 2 deletions src/Symfony/Component/Filesystem/Filesystem.php
Expand Up @@ -453,10 +453,14 @@ public function makePathRelative($endPath, $startPath)
}

// Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
$depth = count($startPathArr) - $index;
if (count($startPathArr) === 1 && $startPathArr[0] === '') {
$depth = 0;
} else {
$depth = count($startPathArr) - $index;
}

// When we need to traverse from the start, and we are starting from a root path, don't add '../'
if ('/' === $startPath[0] && 0 === $index && 1 === $depth) {
if ('/' === $startPath[0] && 0 === $index && 0 === $depth) {
$traverser = '';
} else {
// Repeated "../" for each level need to reach the common path
Expand Down
2 changes: 2 additions & 0 deletions src/Symfony/Component/Filesystem/Tests/FilesystemTest.php
Expand Up @@ -1089,6 +1089,8 @@ public function providePathsForMakePathRelative()
array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
array('/a/aab/bb/', '/', 'a/aab/bb/'),
array('/a/aab/bb/', '/b/aab', '../../a/aab/bb/'),
array('/aab/bb', '/aa', '../aab/bb/'),
array('/aab', '/aa', '../aab/'),
);

if ('\\' === DIRECTORY_SEPARATOR) {
Expand Down
Expand Up @@ -58,7 +58,7 @@ public function testValidationGroupsCanBeSetToCallback()
'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'),
));

$this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups')));
$this->assertInternalType('callable', $form->getConfig()->getOption('validation_groups'));
}

public function testValidationGroupsCanBeSetToClosure()
Expand All @@ -67,7 +67,7 @@ public function testValidationGroupsCanBeSetToClosure()
'validation_groups' => function (FormInterface $form) { },
));

$this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups')));
$this->assertInternalType('callable', $form->getConfig()->getOption('validation_groups'));
}

abstract protected function createForm(array $options = array());
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/HttpFoundation/Response.php
Expand Up @@ -1049,7 +1049,7 @@ public function setVary($headers, $replace = true)
*/
public function isNotModified(Request $request)
{
if (!$request->isMethodSafe()) {
if (!$request->isMethodCacheable()) {
return false;
}

Expand Down
Expand Up @@ -97,21 +97,24 @@ public function dump(Data $data)

break;
} elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof \Twig_Template) {
$info = $trace[$i]['object'];
$name = $info->getTemplateName();
$src = method_exists($info, 'getSource') ? $info->getSource() : $info->getEnvironment()->getLoader()->getSource($name);
$info = $info->getDebugInfo();
$template = $trace[$i]['object'];
$name = $template->getTemplateName();
$file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : false;
$src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false);
$info = $template->getDebugInfo();
if (null !== $src && isset($info[$trace[$i - 1]['line']])) {
$file = false;
$line = $info[$trace[$i - 1]['line']];
$src = explode("\n", $src);
$fileExcerpt = array();

for ($i = max($line - 3, 1), $max = min($line + 3, count($src)); $i <= $max; ++$i) {
$fileExcerpt[] = '<li'.($i === $line ? ' class="selected"' : '').'><code>'.$this->htmlEncode($src[$i - 1]).'</code></li>';
}
if ($src) {
$src = explode("\n", $src);
$fileExcerpt = array();

for ($i = max($line - 3, 1), $max = min($line + 3, count($src)); $i <= $max; ++$i) {
$fileExcerpt[] = '<li'.($i === $line ? ' class="selected"' : '').'><code>'.$this->htmlEncode($src[$i - 1]).'</code></li>';
}

$fileExcerpt = '<ol start="'.max($line - 3, 1).'">'.implode("\n", $fileExcerpt).'</ol>';
$fileExcerpt = '<ol start="'.max($line - 3, 1).'">'.implode("\n", $fileExcerpt).'</ol>';
}
}
break;
}
Expand Down

0 comments on commit de4a650

Please sign in to comment.