diff --git a/src/Renderer/Twig/Extensions/Develop.php b/src/Renderer/Twig/Extensions/Develop.php new file mode 100644 index 00000000..a0de3df5 --- /dev/null +++ b/src/Renderer/Twig/Extensions/Develop.php @@ -0,0 +1,94 @@ +config = $config; + } + + /** + * @return TwigFunction[] + */ + public function getFunctions(): array + { + if ($this->config->get('environment') != 'development') { + return []; + } + + return [ + new TwigFunction('dump', [$this, 'dump'], ['is_safe' => ['html']]), + new TwigFunction('dd', [$this, 'dd']), + ]; + } + + /** + * @param mixed $vars + * @return string + */ + public function dump(...$vars): string + { + ob_start(); + + foreach ($vars as $v) { + $this->dumper ? $this->dumper->dump($v) : var_dump($v); + } + + return ob_get_clean(); + } + + /** + * @param mixed $vars + * @return string + */ + public function dd(...$vars): string + { + $this->flushBuffers(); + + echo call_user_func_array([$this, 'dump'], $vars); + + $this->exit(); + + return ''; + } + + /** + * @param VarDumper $dumper + */ + public function setDumper($dumper) + { + $this->dumper = $dumper; + } + + /** + * @codeCoverageIgnore + */ + protected function exit() + { + exit(1); + } + + /** + * @codeCoverageIgnore + */ + protected function flushBuffers() + { + ob_end_flush(); + } +} diff --git a/src/Renderer/TwigServiceProvider.php b/src/Renderer/TwigServiceProvider.php index d4e4a939..41009eb5 100644 --- a/src/Renderer/TwigServiceProvider.php +++ b/src/Renderer/TwigServiceProvider.php @@ -8,12 +8,14 @@ use Engelsystem\Renderer\Twig\Extensions\Assets; use Engelsystem\Renderer\Twig\Extensions\Authentication; use Engelsystem\Renderer\Twig\Extensions\Config; use Engelsystem\Renderer\Twig\Extensions\Csrf; +use Engelsystem\Renderer\Twig\Extensions\Develop; use Engelsystem\Renderer\Twig\Extensions\Globals; use Engelsystem\Renderer\Twig\Extensions\Legacy; use Engelsystem\Renderer\Twig\Extensions\Markdown; use Engelsystem\Renderer\Twig\Extensions\Session; use Engelsystem\Renderer\Twig\Extensions\Translation; use Engelsystem\Renderer\Twig\Extensions\Url; +use Symfony\Component\VarDumper\VarDumper; use Twig\Environment as Twig; use Twig\Extension\CoreExtension as TwigCore; use Twig\Loader\LoaderInterface as TwigLoaderInterface; @@ -26,6 +28,7 @@ class TwigServiceProvider extends ServiceProvider 'authentication' => Authentication::class, 'config' => Config::class, 'csrf' => Csrf::class, + 'develop' => Develop::class, 'globals' => Globals::class, 'session' => Session::class, 'legacy' => Legacy::class, @@ -51,6 +54,12 @@ class TwigServiceProvider extends ServiceProvider foreach ($this->app->tagged('twig.extension') as $extension) { $renderer->addExtension($extension); } + + if (class_exists(VarDumper::class)) { + /** @var Develop $dev */ + $dev = $this->app->get('twig.extension.develop'); + $dev->setDumper($this->app->make(VarDumper::class)); + } } protected function registerTwigEngine() diff --git a/tests/Unit/Renderer/Twig/Extensions/DevelopTest.php b/tests/Unit/Renderer/Twig/Extensions/DevelopTest.php new file mode 100644 index 00000000..0e225a23 --- /dev/null +++ b/tests/Unit/Renderer/Twig/Extensions/DevelopTest.php @@ -0,0 +1,70 @@ +getFunctions(); + $this->assertEquals($functions, []); + + $config->set('environment', 'development'); + $functions = $extension->getFunctions(); + $this->assertExtensionExists('dump', [$extension, 'dump'], $functions); + $this->assertExtensionExists('dd', [$extension, 'dd'], $functions); + } + + /** + * @covers \Engelsystem\Renderer\Twig\Extensions\Develop::dump + * @covers \Engelsystem\Renderer\Twig\Extensions\Develop::setDumper + */ + public function testDump() + { + $config = new Config(); + $varDumper = new VarDumper(); + $varDumper->setHandler(function ($var) { + echo $var; + }); + + $extension = new Develop($config); + $extension->setDumper($varDumper); + + $return = $extension->dump('Foo', 1234); + $this->assertEquals('Foo1234', $return); + } + + /** + * @covers \Engelsystem\Renderer\Twig\Extensions\Develop::dd + */ + public function testDD() + { + /** @var Develop|MockObject $extension */ + $extension = $this->getMockBuilder(Develop::class) + ->onlyMethods(['exit', 'flushBuffers', 'dump']) + ->disableOriginalConstructor() + ->getMock(); + $extension->expects($this->once()) + ->method('exit'); + $extension->expects($this->once()) + ->method('flushBuffers'); + $extension->expects($this->once()) + ->method('dump') + ->with(123, 'Abc'); + + $return = $extension->dd(123, 'Abc'); + $this->assertEquals('', $return); + } +} diff --git a/tests/Unit/Renderer/TwigServiceProviderTest.php b/tests/Unit/Renderer/TwigServiceProviderTest.php index 3336e015..618f7101 100644 --- a/tests/Unit/Renderer/TwigServiceProviderTest.php +++ b/tests/Unit/Renderer/TwigServiceProviderTest.php @@ -3,6 +3,7 @@ namespace Engelsystem\Test\Unit\Renderer; use Engelsystem\Config\Config; +use Engelsystem\Renderer\Twig\Extensions\Develop; use Engelsystem\Renderer\TwigEngine; use Engelsystem\Renderer\TwigLoader; use Engelsystem\Renderer\TwigServiceProvider; @@ -11,6 +12,7 @@ use PHPUnit\Framework\MockObject\MockObject; use ReflectionClass as Reflection; use ReflectionException; use stdClass; +use Symfony\Component\VarDumper\VarDumper; use Twig\Environment as Twig; use Twig\Extension\AbstractExtension; use Twig\Extension\CoreExtension as TwigCore; @@ -70,22 +72,34 @@ class TwigServiceProviderTest extends ServiceProviderTest $firsExtension = $this->getMockForAbstractClass(ExtensionInterface::class); /** @var ExtensionInterface|MockObject $secondExtension */ $secondExtension = $this->getMockForAbstractClass(ExtensionInterface::class); + /** @var Develop|MockObject $devExtension */ + $devExtension = $this->createMock(Develop::class); + /** @var VarDumper|MockObject $dumper */ + $dumper = $this->createMock(VarDumper::class); - $app = $this->getApp(['get', 'tagged']); + $app = $this->getApp(['get', 'tagged', 'make']); - $app->expects($this->once()) + $app->expects($this->exactly(2)) ->method('get') - ->with('twig.environment') - ->willReturn($twig); + ->withConsecutive(['twig.environment'], ['twig.extension.develop']) + ->willReturnOnConsecutiveCalls($twig, $devExtension); $app->expects($this->once()) ->method('tagged') ->with('twig.extension') ->willReturn([$firsExtension, $secondExtension]); + $app->expects($this->once()) + ->method('make') + ->with(VarDumper::class) + ->willReturn($dumper); $twig->expects($this->exactly(2)) ->method('addExtension') ->withConsecutive([$firsExtension], [$secondExtension]); + $devExtension->expects($this->once()) + ->method('setDumper') + ->with($dumper); + $serviceProvider = new TwigServiceProvider($app); $serviceProvider->boot(); }