From dd20ce893012fc620d79eaf787038e35df5f8a2c Mon Sep 17 00:00:00 2001 From: kylekatarnls Date: Thu, 21 Sep 2023 08:28:17 +0200 Subject: [PATCH] Add exception for null cache_dir option --- .../Formatter/Formatter/Format/XmlFormat.php | 6 ++ .../Renderer/Renderer/Adapter/FileAdapter.php | 21 ++++++- tests/Phug/Adapter/FileAdapterTest.php | 62 +++++++++++++++++++ tests/Phug/Element/ExpressionElementTest.php | 12 ++++ tests/Phug/Element/MixinElementTest.php | 33 ++++++++++ tests/Phug/Format/FormatExtendTest.php | 12 ++++ 6 files changed, 144 insertions(+), 2 deletions(-) diff --git a/src/Phug/Formatter/Formatter/Format/XmlFormat.php b/src/Phug/Formatter/Formatter/Format/XmlFormat.php index e7b885df..757ade84 100644 --- a/src/Phug/Formatter/Formatter/Format/XmlFormat.php +++ b/src/Phug/Formatter/Formatter/Format/XmlFormat.php @@ -167,6 +167,7 @@ protected function formatAttributeElement(AttributeElement $element) $value = $element->getValue(); $name = $element->getName(); $nonEmptyAttribute = ($name === 'class' || $name === 'id'); + if ($nonEmptyAttribute && ( !$value || ($value instanceof TextElement && ((string) $value->getValue()) === '') || @@ -174,12 +175,15 @@ protected function formatAttributeElement(AttributeElement $element) )) { return ''; } + if ($value instanceof ExpressionElement) { if ($nonEmptyAttribute && in_array(trim($value->getValue()), ['', '""', "''"], true)) { return ''; } + if (strtolower($value->getValue()) === 'true') { $formattedValue = null; + if ($name instanceof ExpressionElement) { $bufferVariable = $this->pattern('buffer_variable'); $name = $this->pattern( @@ -193,6 +197,7 @@ protected function formatAttributeElement(AttributeElement $element) $value = new ExpressionElement($bufferVariable); $formattedValue = $this->format($value); } + $formattedName = $this->format($name); $formattedValue = $formattedValue || $formattedValue === '0' ? $formattedValue @@ -204,6 +209,7 @@ protected function formatAttributeElement(AttributeElement $element) $formattedValue ); } + if (in_array(strtolower($value->getValue()), ['false', 'null', 'undefined'], true)) { return ''; } diff --git a/src/Phug/Renderer/Renderer/Adapter/FileAdapter.php b/src/Phug/Renderer/Renderer/Adapter/FileAdapter.php index bde9953c..51e9be72 100644 --- a/src/Phug/Renderer/Renderer/Adapter/FileAdapter.php +++ b/src/Phug/Renderer/Renderer/Adapter/FileAdapter.php @@ -389,18 +389,35 @@ private function isCacheUpToDate(&$path, $input = null) return file_exists($path); } - private function getCacheDirectory() + private function readCacheDirectoryFromOptions() { $cacheFolder = $this->hasOption('cache_dir') ? $this->getOption('cache_dir') : null; + if (!$cacheFolder && $cacheFolder !== false) { $cacheFolder = $this->getRenderer()->hasOption('cache_dir') ? $this->getRenderer()->getOption('cache_dir') : null; } + if ($cacheFolder === true) { - $cacheFolder = $this->getOption('tmp_dir'); + return $this->getOption('tmp_dir'); + } + + return $cacheFolder; + } + + private function getCacheDirectory() + { + $cacheFolder = $this->readCacheDirectoryFromOptions(); + + if ($cacheFolder === null) { + throw new RuntimeException( + 'You need to set "cache_dir" option to a writable location in order '. + 'to use cache feature.', + 7 + ); } if (!is_dir($cacheFolder) && !@mkdir($cacheFolder, 0777, true)) { diff --git a/tests/Phug/Adapter/FileAdapterTest.php b/tests/Phug/Adapter/FileAdapterTest.php index c3574232..476e80de 100644 --- a/tests/Phug/Adapter/FileAdapterTest.php +++ b/tests/Phug/Adapter/FileAdapterTest.php @@ -55,6 +55,7 @@ public function testRender() * @covers ::getRawCachePath * @covers ::isCacheUpToDate * @covers ::checkPathExpiration + * @covers ::readCacheDirectoryFromOptions * @covers ::getCacheDirectory * @covers ::getRegistryPath * @covers \Phug\Renderer\Partial\RegistryTrait::findCachePathInRegistryFile @@ -172,12 +173,71 @@ function ($path, $input) { self::assertCount(2, $files); } + /** + * @covers ::readCacheDirectoryFromOptions + * @covers ::getCacheDirectory + * + * @expectedException \RuntimeException + * + * @expectedExceptionMessage You need to set "cache_dir" option to a writable location in order to use cache feature. + */ + public function testNullCacheDir() + { + ExceptionAnnotationReader::read($this, __METHOD__); + + $renderer = new Renderer([ + 'cache_dir' => null, + 'adapter_class_name' => FileAdapter::class, + ]); + + /** @var FileAdapter $adapter */ + $adapter = $renderer->getAdapter(); + + self::assertInstanceOf(FileAdapter::class, $adapter); + + $adapter->cache('foo', 'bar', function () { + return 'abc'; + }); + } + + /** + * @covers ::readCacheDirectoryFromOptions + * @covers ::getCacheDirectory + * + * @expectedException \RuntimeException + * + * @expectedExceptionMessage You need to set "cache_dir" option to a writable location in order to use cache feature. + */ + public function testUnsetCacheDir() + { + ExceptionAnnotationReader::read($this, __METHOD__); + + $renderer = new Renderer([ + 'adapter_class_name' => FileAdapter::class, + ]); + /** @var FileAdapter $adapter */ + $adapter = $renderer->getAdapter(); + + foreach ([$renderer, $adapter] as $handler) { + if ($handler->hasOption('cache_dir')) { + $handler->unsetOption('cache_dir'); + } + } + + self::assertInstanceOf(FileAdapter::class, $adapter); + + $adapter->cache('foo', 'bar', function () { + return 'abc'; + }); + } + /** * @covers :: * @covers ::getCachePath * @covers ::getRawCachePath * @covers ::isCacheUpToDate * @covers ::checkPathExpiration + * @covers ::readCacheDirectoryFromOptions * @covers ::getCacheDirectory * @covers \Phug\Renderer\AbstractAdapter:: * @covers \Phug\Renderer\Partial\AdapterTrait::getAdapter @@ -419,6 +479,7 @@ public function testCacheOnExtendsChange() * @covers ::getRawCachePath * @covers ::isCacheUpToDate * @covers ::checkPathExpiration + * @covers ::readCacheDirectoryFromOptions * @covers ::getCacheDirectory * @covers \Phug\Renderer\AbstractAdapter:: * @covers \Phug\Renderer\Partial\FileSystemTrait::fileMatchExtensions @@ -574,6 +635,7 @@ public function testCacheRenderString() * @covers \Phug\Renderer\Partial\CacheTrait::getCacheAdapter * @covers \Phug\Renderer\Partial\CacheTrait::cacheDirectory * @covers \Phug\Renderer\Adapter\FileAdapter::cacheDirectory + * @covers \Phug\Renderer\Adapter\FileAdapter::readCacheDirectoryFromOptions * @covers \Phug\Renderer\Adapter\FileAdapter::getCacheDirectory * @covers \Phug\Renderer\Partial\Debug\DebuggerTrait::getDebuggedException * diff --git a/tests/Phug/Element/ExpressionElementTest.php b/tests/Phug/Element/ExpressionElementTest.php index 65d1b7e5..a30379a0 100644 --- a/tests/Phug/Element/ExpressionElementTest.php +++ b/tests/Phug/Element/ExpressionElementTest.php @@ -2,6 +2,7 @@ namespace Phug\Test\Element; +use Phug\Ast\Node; use Phug\Formatter; use Phug\Formatter\Element\AttributeElement; use Phug\Formatter\Element\ExpressionElement; @@ -105,4 +106,15 @@ public function testTrueDynamicValue() $actual ); } + + /** + * @covers \Phug\Formatter\AbstractElement::dump + */ + public function testDump() + { + $expression = new ExpressionElement('$foo'); + $expression->appendChild(new Node()); + + self::assertSame("Expression\n ".Node::class, $expression->dump()); + } } diff --git a/tests/Phug/Element/MixinElementTest.php b/tests/Phug/Element/MixinElementTest.php index 572148a0..1eb29303 100644 --- a/tests/Phug/Element/MixinElementTest.php +++ b/tests/Phug/Element/MixinElementTest.php @@ -7,6 +7,7 @@ use Phug\Formatter\Element\AttributeElement; use Phug\Formatter\Element\CodeElement; use Phug\Formatter\Element\DocumentElement; +use Phug\Formatter\Element\ExpressionElement; use Phug\Formatter\Element\MarkupElement; use Phug\Formatter\Element\MixinElement; use Phug\Formatter\Element\TextElement; @@ -127,6 +128,38 @@ public function testRequireAllMixins() self::assertSame('
block
', $html); } + /** + * @covers \Phug\Formatter\AbstractFormat::formatMixinElement + */ + public function testFormatMixinWithDynamicName() + { + $mixin = new MixinElement(); + $name = new ExpressionElement(); + $name->setValue('$var'); + $mixin->setName($name); + $div = new MarkupElement('p'); + $div->appendChild(new AnonymousBlockElement()); + $mixin->appendChild($div); + + $formatter = new Formatter(); + + $php = $formatter->format($mixin); + $formatter->requireAllMixins(); + $php = $formatter->formatDependencies().$php; + $call = ''; + + ob_start(); + $var = 'foo'; + eval('?>'.$php.$call); + $html = ob_get_contents(); + ob_end_clean(); + + self::assertSame('

foo

', $html); + } + /** * @covers \Phug\Formatter::getMixins * @covers \Phug\Formatter::requireMixin diff --git a/tests/Phug/Format/FormatExtendTest.php b/tests/Phug/Format/FormatExtendTest.php index 4e8f808f..6c744075 100644 --- a/tests/Phug/Format/FormatExtendTest.php +++ b/tests/Phug/Format/FormatExtendTest.php @@ -23,6 +23,18 @@ public function testExtendedFormat() $formatter = new Formatter(); $format = new FakeXmlFormat($formatter); + $attribute = new AttributeElement( + 'required', + new ExpressionElement('true') + ); + + ob_start(); + eval('?>'.$format->callFormatAttributeElement($attribute)); + $actual = ob_get_contents(); + ob_end_clean(); + + self::assertSame(' required="required"', $actual); + ob_start(); eval('?>'.$format->callFormatAttributeElement( new AttributeElement(new ExpressionElement('"foo" . "bar"'), 'abc')