8000 Deprecate some interface in Twig Bridge by fabpot · Pull Request #16333 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Deprecate some interface in Twig Bridge #16333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Bumped Twig version to 1.24 and get rid of initRuntime
  • Loading branch information
fabpot committed Sep 29, 2016
commit aa0f3a3e1722ce2f8f938d39cf1baeb54b503c13
41 changes: 41 additions & 0 deletions src/Symfony/Bridge/Twig/Extension/ContainerAwareRuntimeLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Loads Twig extension runtimes.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class ContainerAwareRuntimeLoader implements \Twig_RuntimeLoaderInterface
{
private $container;

public function __construct(ContainerInterface $container)
{
$this->container = $container;
}

/**
* {@inheritdoc}
*/
public function load($name)
{
$id = 'twig.extension.runtime.'.$name;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please don't force this convention: it forbids third-party bundles to use this behavior while following best practices for shared bundles. The id of the runtime should be provided as an optional attribute in the twig.extension tag IMO, to build a mapping between extension names and runtimes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this is just a quick POC to prove that it works.


if ($this->container->has($id)) {
return $this->container->get($id);
}
}
}
66 changes: 0 additions & 66 deletions src/Symfony/Bridge/Twig/Extension/FormExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
namespace Symfony\Bridge\Twig\Extension;

use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser;
use Symfony\Bridge\Twig\Form\TwigRenderer;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;

/**
Expand All @@ -23,19 +22,6 @@
*/
class FormExtension extends \Twig_Extension
{
/**
* This property is public so that it can be accessed directly from compiled
* templates without having to call a getter, which slightly decreases performance.
*
* @var TwigRenderer
*/
public $renderer;

public function __construct(TwigRenderer $renderer)
{
$this->renderer = $renderer;
}

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -85,58 +71,6 @@ public function getTests()
);
}

/**
* {@inheritdoc}
*/
public function renderCsrfToken($tokenId)
{
return $this->renderer->renderCsrfToken($tokenId);
}

/**
* Makes a technical name human readable.
*
* @param string $text The text to humanize
*
* @return string The humanized text
*/
public function humanize($text)
{
return $this->renderer->humanize($text);
}

/**
* Returns whether a choice is selected for a given form value.
*
* Unfortunately Twig does not support an efficient way to execute the
* "is_selected" closure passed to the template by ChoiceType. It is faster
* to implement the logic here (around 65ms for a specific form).
*
* Directly implementing the logic here is also faster than doing so in
* ChoiceView (around 30ms).
*
* The worst option tested so far is to implement the logic in ChoiceView
* and access the ChoiceView method directly in the template. Doing so is
* around 220ms slower than doing the method call here in the filter. Twig
* seems to be much more efficient at executing filters than at executing
* methods of an object.
*
* @param ChoiceView $choice The choice to check
* @param string|array $selectedValue The selected value to compare
*
* @return bool Whether the choice is selected
*
* @see ChoiceView::isSelected()
*/
public function isSelectedChoice(ChoiceView $choice, $selectedValue)
{
if (is_array($selectedValue)) {
return in_array($choice->value, $selectedValue, true);
}

return $choice->value === $selectedValue;
}

/**
* {@inheritdoc}
*/
Expand Down
92 changes: 92 additions & 0 deletions src/Symfony/Bridge/Twig/Extension/FormExtensionRuntime.php
< 8000 td class="blob-num blob-num-addition empty-cell">
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Bridge\Twig\Form\TwigRenderer;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;

/**
* FormExtension extends Twig with form capabilities.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class FormExtensionRuntime
{
/**
* This property is public so that it can be accessed directly from compiled
* templates without having to call a getter, which slightly decreases performance.
*
* @var TwigRenderer
*/
public $renderer;

public function __construct(TwigRenderer $renderer)
{
$this->renderer = $renderer;
}

/**
* Renders a CSRF token.
*
* @param string $intention The intention of the protected action.
*
* @return string A CSRF token.
*/
public function renderCsrfToken($intention)
{
return $this->renderer->renderCsrfToken($intention);
}

/**
* Makes a technical name human readable.
*
* @param string $text The text to humanize.
*
* @return string The humanized text.
*/
public function humanize($text)
{
return $this->renderer->humanize($text);
}

/**
* Returns whether a choice is selected for a given form value.
*
* Unfortunately Twig does not support an efficient way to execute the
* "is_selected" closure passed to the template by ChoiceType. It is faster
* to implement the logic here (around 65ms for a specific form).
*
* Directly implementing the logic here is also faster than doing so in
* ChoiceView (around 30ms).
*
* The worst option tested so far is to implement the logic in ChoiceView
* and access the ChoiceView method directly in the template. Doing so is
* around 220ms slower than doing the method call here in the filter. Twig
* seems to be much more efficient at executing filters than at executing
* methods of an object.
*
* @param ChoiceView $choice The choice to check.
* @param string|array $selectedValue The selected value to compare.
*
* @return bool Whether the choice is selected.
*
* @see ChoiceView::isSelected()
*/
public function isSelectedChoice(ChoiceView $choice, $selectedValue)
{
if (is_array($selectedValue)) {
return in_array($choice->value, $selectedValue, true);
}

return $choice->value === $selectedValue;
}
}
2 changes: 1 addition & 1 deletion src/Symfony/Bridge/Twig/Node/FormThemeNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function compile(\Twig_Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write('$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->setTheme(')
->write('$this->env->getRuntime(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->setTheme(')
->subcompile($this->getNode('form'))
->raw(', ')
->subcompile($this->getNode('resources'))
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bridge/Twig/Node/RenderBlockNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function compile(\Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$arguments = iterator_to_array($this->getNode('arguments'));
$compiler->write('$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->renderBlock(');
$compiler->write('$this->env->getRuntime(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->renderBlock(');

if (isset($arguments[0])) {
$compiler->subcompile($arguments[0]);
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class SearchAndRenderBlockNode extends \Twig_Node_Expression_Function
public function compile(\Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$compiler->raw('$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(');
$compiler->raw('$this->env->getRuntime(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(');

preg_match('/_([^_]+)$/', $this->getAttribute('name'), $matches);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Bridge\Twig\Tests\Extension;

use Symfony\Bridge\Twig\Extension\FormExtension;
use Symfony\Bridge\Twig\Extension\FormExtensionRuntime;
use Symfony\Bridge\Twig\Form\TwigRenderer;
use Symfony\Bridge\Twig\Form\TwigRendererEngine;
use Symfony\Bridge\Twig\Extension\TranslationExtension;
Expand All @@ -22,10 +23,11 @@

class FormExtensionBootstrap3LayoutTest extends AbstractBootstrap3LayoutTest
{
/**
* @var FormExtension
*/
protected $extension;
protected $testableFeatures = array(
'choice_attr',
);

private $environment;

protected function setUp()
{
Expand All @@ -36,27 +38,23 @@ protected function setUp()
__DIR__.'/Fixtures/templates/form',
));

$environment = new \Twig_Environment($loader, array('strict_variables' => true));
$environment->addExtension(new TranslationExtension(new StubTranslator()));
$this->environment = new \Twig_Environment($loader, array('strict_variables' => true));
$this->environment->addExtension(new TranslationExtension(new StubTranslator()));
$this->environment->addExtension(new FormExtension());

$rendererEngine = new TwigRendererEngine(array(
'bootstrap_3_layout.html.twig',
'custom_widgets.html.twig',
), $environment);
), $this->environment);
$renderer = new TwigRenderer($rendererEngine, $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'));

$this->extension = new FormExtension($renderer);

$environment->addExtension($this->extension);

$this->extension->initRuntime($environment);
}

protected function tearDown()
{
parent::tearDown();
$loader = $this->getMock('Twig_RuntimeLoaderInterface');
$loader->expects($this->any())->method('load')->will($this->returnValueMap(array(
array('form', new FormExtensionRuntime($renderer)),
array('translator', null),
)));

$this->extension = null;
$this->environment->registerRuntimeLoader($loader);
}

public function testStartTagHasNoActionAttributeWhenActionIsEmpty()
Expand Down Expand Up @@ -85,7 +83,7 @@ public function testStartTagHasActionAttributeWhenActionIsZero()

protected function renderForm(FormView $view, array $vars = array())
{
return (string) $this->extension->renderer->renderBlock($view, 'form', $vars);
return (string) $this->environment->getRuntime('form')->renderer->renderBlock($view, 'form', $vars);
}

protected function renderLabel(FormView $view, $label = null, array $vars = array())
Expand All @@ -94,41 +92,41 @@ protected function renderLabel(FormView $view, $label = null, array $vars = arra
$vars += array('label' => $label);
}

return (string) $this->extension->renderer->searchAndRenderBlock($view, 'label', $vars);
return (string) $this->environment->getRuntime('form')->renderer->searchAndRenderBlock($view, 'label', $vars);
}

protected function renderErrors(FormView $view)
{
return (string) $this->extension->renderer->searchAndRenderBlock($view, 'errors');
return (string) $this->environment->getRuntime('form')->renderer->searchAndRenderBlock($view, 'errors');
}

protected function renderWidget(FormView $view, array $vars = array())
{
return (string) $this->extension->renderer->searchAndRenderBlock($view, 'widget', $vars);
return (string) $this->environment->getRuntime('form')->renderer->searchAndRenderBlock($view, 'widget', $vars);
}

protected function renderRow(FormView $view, array $vars = array())
{
return (string) $this->extension->renderer->searchAndRenderBlock($view, 'row', $vars);
return (string) $this->environment->getRuntime('form')->renderer->searchAndRenderBlock($view, 'row', $vars);
}

protected function renderRest(FormView $view, array $vars = array())
{
return (string) $this->extension->renderer->searchAndRenderBlock($view, 'rest', $vars);
return (string) $this->environment->getRuntime('form')->renderer->searchAndRenderBlock($view, 'rest', $vars);
}

protected function renderStart(FormView $view, array $vars = array())
{
return (string) $this->extension->renderer->renderBlock($view, 'form_start', $vars);
return (string) $this->environment->getRuntime('form')->renderer->renderBlock($view, 'form_start', $vars);
}

protected function renderEnd(FormView $view, array $vars = array())
{
return (string) $this->extension->renderer->renderBlock($view, 'form_end', $vars);
return (string) $this->environment->getRuntime('form')->renderer->renderBlock($view, 'form_end', $vars);
}

protected function setTheme(FormView $view, array $themes)
{
$this->extension->renderer->setTheme($view, $themes);
$this->environment->getRuntime('form')->renderer->setTheme($view, $themes);
}
}
Loading
0