AbstractWidgetTestCase.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <?php
  2. /*
  3. * This file is part of the Sonata Project package.
  4. *
  5. * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Sonata\CoreBundle\Test;
  11. use Symfony\Bridge\Twig\Extension\FormExtension;
  12. use Symfony\Bridge\Twig\Extension\TranslationExtension;
  13. use Symfony\Bridge\Twig\Form\TwigRenderer;
  14. use Symfony\Bridge\Twig\Form\TwigRendererEngine;
  15. use Symfony\Bridge\Twig\Form\TwigRendererEngineInterface;
  16. use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader;
  17. use Symfony\Bundle\FrameworkBundle\Tests\Templating\Helper\Fixtures\StubTranslator;
  18. use Symfony\Component\Form\FormExtensionInterface;
  19. use Symfony\Component\Form\FormView;
  20. use Symfony\Component\Form\Test\TypeTestCase;
  21. /**
  22. * Base class for tests checking rendering of form widgets.
  23. *
  24. * @author Christian Gripp <mail@core23.de>
  25. */
  26. abstract class AbstractWidgetTestCase extends TypeTestCase
  27. {
  28. /**
  29. * @var FormExtensionInterface
  30. */
  31. private $extension;
  32. /**
  33. * @var TwigRenderer
  34. */
  35. private $renderer;
  36. /**
  37. * {@inheritdoc}
  38. */
  39. protected function setUp()
  40. {
  41. // NEXT_MAJOR: remove this block when dropping symfony < 2.7 support
  42. if (!class_exists('Symfony\Bridge\Twig\Extension\AssetExtension')) {
  43. $this->markTestSkipped();
  44. }
  45. parent::setUp();
  46. // NEXT_MAJOR: Remove BC hack when dropping symfony 2.4 support
  47. $csrfProviderClasses = array_filter(array(
  48. // symfony <=2.4
  49. 'Symfony\Component\Security\Csrf\CsrfTokenManagerInterface',
  50. // symfony >=2.4
  51. 'Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface',
  52. ), 'interface_exists');
  53. // TODO: remove the condition when dropping symfony/twig-bundle < 3.2
  54. if (method_exists('Symfony\Bridge\Twig\AppVariable', 'getToken')) {
  55. $this->extension = new FormExtension();
  56. $environment = $this->getEnvironment();
  57. $this->renderer = new TwigRenderer(
  58. $this->getRenderingEngine($environment),
  59. $this->createMock(current($csrfProviderClasses))
  60. );
  61. $runtimeLoader = $this
  62. ->getMockBuilder('Twig_RuntimeLoaderInterface')
  63. ->getMock();
  64. $runtimeLoader->expects($this->any())
  65. ->method('load')
  66. ->with($this->equalTo('Symfony\Bridge\Twig\Form\TwigRenderer'))
  67. ->will($this->returnValue($this->renderer));
  68. $environment->addRuntimeLoader($runtimeLoader);
  69. } else {
  70. $this->renderer = new TwigRenderer(
  71. $this->getRenderingEngine(),
  72. $this->createMock(current($csrfProviderClasses))
  73. );
  74. $this->extension = new FormExtension($this->renderer);
  75. $environment = $this->getEnvironment();
  76. }
  77. $this->extension->initRuntime($environment);
  78. }
  79. /**
  80. * @return \Twig_Environment
  81. */
  82. protected function getEnvironment()
  83. {
  84. $loader = new StubFilesystemLoader($this->getTemplatePaths());
  85. $environment = new \Twig_Environment($loader, array(
  86. 'strict_variables' => true,
  87. ));
  88. $environment->addExtension(new TranslationExtension(new StubTranslator()));
  89. $environment->addExtension($this->extension);
  90. return $environment;
  91. }
  92. /**
  93. * Returns a list of template paths.
  94. *
  95. * @return string[]
  96. */
  97. protected function getTemplatePaths()
  98. {
  99. // this is an workaround for different composer requirements and different TwigBridge installation directories
  100. $twigPaths = array_filter(array(
  101. // symfony/twig-bridge (running from this bundle)
  102. __DIR__.'/../vendor/symfony/twig-bridge/Resources/views/Form',
  103. // symfony/twig-bridge (running from other bundles)
  104. __DIR__.'/../../../symfony/twig-bridge/Resources/views/Form',
  105. // NEXT_MAJOR: Remove BC hacks when dropping symfony 2.3 support
  106. // symfony/twig-bridge 2.3 (running from this bundle)
  107. __DIR__.'/../vendor/symfony/twig-bridge/Symfony/Bridge/Twig/Resources/views/Form',
  108. // symfony/twig-bridge 2.3 (running from other bundles)
  109. __DIR__.'/../../../symfony/twig-bridge/Symfony/Bridge/Twig/Resources/views/Form',
  110. // symfony/symfony (running from this bundle)
  111. __DIR__.'/../vendor/symfony/symfony/src/Symfony/Bridge/Twig/Resources/views/Form',
  112. // symfony/symfony (running from other bundles)
  113. __DIR__.'/../../../symfony/symfony/src/Symfony/Bridge/Twig/Resources/views/Form',
  114. ), 'is_dir');
  115. $twigPaths[] = __DIR__.'/../Resources/views/Form';
  116. return $twigPaths;
  117. }
  118. /**
  119. * NEXT_MAJOR: uncomment and use the $environment argument.
  120. *
  121. * @return TwigRendererEngineInterface
  122. */
  123. protected function getRenderingEngine(/* \Twig_Environment $environment = null */)
  124. {
  125. $environment = current(func_get_args());
  126. if (is_null($environment) && method_exists('Symfony\Bridge\Twig\AppVariable', 'getToken')) {
  127. @trigger_error(
  128. 'Not passing a \Twig_Environment instance to '.__METHOD__.
  129. ' is deprecated since 3.3 and will not be possible in 4.0',
  130. E_USER_DEPRECATED
  131. );
  132. }
  133. return new TwigRendererEngine(array('form_div_layout.html.twig'), $environment);
  134. }
  135. /**
  136. * Renders widget from FormView, in SonataAdmin context, with optional view variables $vars. Returns plain HTML.
  137. *
  138. * @param FormView $view
  139. * @param array $vars
  140. *
  141. * @return string
  142. */
  143. final protected function renderWidget(FormView $view, array $vars = array())
  144. {
  145. return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
  146. }
  147. /**
  148. * Helper method to strip newline and space characters from html string to make comparing easier.
  149. *
  150. * @param string $html
  151. *
  152. * @return string
  153. */
  154. final protected function cleanHtmlWhitespace($html)
  155. {
  156. return preg_replace_callback('/\s*>([^<]+)</', function ($value) {
  157. return '>'.trim($value[1]).'<';
  158. }, $html);
  159. }
  160. /**
  161. * @param string $html
  162. *
  163. * @return string
  164. */
  165. final protected function cleanHtmlAttributeWhitespace($html)
  166. {
  167. return preg_replace_callback('~<([A-Z0-9]+) \K(.*?)>~i', function ($m) {
  168. return preg_replace('~\s*~', '', $m[0]);
  169. }, $html);
  170. }
  171. /**
  172. * NEXT_MAJOR: Remove this method when dropping support for < PHPUnit 5.4.
  173. *
  174. * @param string $class
  175. *
  176. * @return \PHPUnit_Framework_MockObject_MockObject
  177. */
  178. protected function createMock($class)
  179. {
  180. if (is_callable('parent::createMock')) {
  181. return parent::createMock($class);
  182. }
  183. return $this->getMock($class);
  184. }
  185. }