Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ $factory = \Keepsuit\Liquid\EnvironmentFactory::new()
// enable strict variables mode
->setStrictVariables()
// rethrow exceptions instead of rendering them
->setRethrowExceptions()
->setRethrowErrors()
// set filesystem used to load templates
->setFilesystem(new \Keepsuit\Liquid\FileSystems\LocalFileSystem(__DIR__ . '/views'));
```
Expand Down
14 changes: 14 additions & 0 deletions src/Contracts/LiquidErrorHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Keepsuit\Liquid\Contracts;

use Keepsuit\Liquid\Exceptions\LiquidException;

interface LiquidErrorHandler
{
/**
* Handle the given error.
* The returned string will be printed to the output.
*/
public function handle(LiquidException $error): string;
}
6 changes: 6 additions & 0 deletions src/Environment.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace Keepsuit\Liquid;

use Keepsuit\Liquid\Contracts\LiquidErrorHandler;
use Keepsuit\Liquid\Contracts\LiquidFileSystem;
use Keepsuit\Liquid\ErrorHandlers\DefaultErrorHandler;
use Keepsuit\Liquid\Exceptions\LiquidException;
use Keepsuit\Liquid\FileSystems\BlankFileSystem;
use Keepsuit\Liquid\Parse\ParseContext;
Expand All @@ -22,6 +24,8 @@ class Environment

public readonly LiquidFileSystem $fileSystem;

public readonly LiquidErrorHandler $errorHandler;

public readonly ResourceLimits $defaultResourceLimits;

public readonly RenderContextOptions $defaultRenderContextOptions;
Expand All @@ -30,13 +34,15 @@ public function __construct(
?TagRegistry $tagRegistry = null,
?FilterRegistry $filterRegistry = null,
?LiquidFileSystem $fileSystem = null,
?LiquidErrorHandler $errorHandler = null,
?ResourceLimits $defaultResourceLimits = null,
?RenderContextOptions $defaultRenderContextOptions = null,
public readonly bool $profile = false,
) {
$this->tagRegistry = $tagRegistry ?? TagRegistry::default();
$this->filterRegistry = $filterRegistry ?? FilterRegistry::default();
$this->fileSystem = $fileSystem ?? new BlankFileSystem;
$this->errorHandler = $errorHandler ?? new DefaultErrorHandler;
$this->defaultResourceLimits = $defaultResourceLimits ?? new ResourceLimits;
$this->defaultRenderContextOptions = $defaultRenderContextOptions ?? new RenderContextOptions;
}
Expand Down
20 changes: 16 additions & 4 deletions src/EnvironmentFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace Keepsuit\Liquid;

use Keepsuit\Liquid\Contracts\LiquidErrorHandler;
use Keepsuit\Liquid\Contracts\LiquidFileSystem;
use Keepsuit\Liquid\ErrorHandlers\DefaultErrorHandler;
use Keepsuit\Liquid\FileSystems\BlankFileSystem;
use Keepsuit\Liquid\Filters\FiltersProvider;
use Keepsuit\Liquid\Render\RenderContextOptions;
Expand All @@ -18,6 +20,8 @@ final class EnvironmentFactory

protected LiquidFileSystem $fileSystem;

protected LiquidErrorHandler $errorHandler;

protected ResourceLimits $resourceLimits;

protected RenderContextOptions $defaultRenderContextOptions;
Expand All @@ -29,6 +33,7 @@ public function __construct()
$this->tagRegistry = TagRegistry::default();
$this->filterRegistry = FilterRegistry::default();
$this->fileSystem = new BlankFileSystem;
$this->errorHandler = new DefaultErrorHandler;
$this->resourceLimits = new ResourceLimits;
$this->defaultRenderContextOptions = new RenderContextOptions;
}
Expand Down Expand Up @@ -59,6 +64,13 @@ public function setFilesystem(LiquidFileSystem $fileSystem): EnvironmentFactory
return $this;
}

public function setErrorHandler(LiquidErrorHandler $errorHandler): EnvironmentFactory
{
$this->errorHandler = $errorHandler;

return $this;
}

public function setResourceLimits(ResourceLimits $resourceLimits): EnvironmentFactory
{
$this->resourceLimits = $resourceLimits;
Expand All @@ -73,12 +85,12 @@ public function setProfile(bool $profile = true): EnvironmentFactory
return $this;
}

public function setRethrowExceptions(bool $rethrowExceptions = true): EnvironmentFactory
public function setRethrowErrors(bool $rethrowErrors = true): EnvironmentFactory
{
$this->defaultRenderContextOptions = new RenderContextOptions(
strictVariables: $this->defaultRenderContextOptions->strictVariables,
strictFilters: $this->defaultRenderContextOptions->strictFilters,
rethrowExceptions: $rethrowExceptions,
rethrowErrors: $rethrowErrors,
);

return $this;
Expand All @@ -89,7 +101,7 @@ public function setStrictVariables(bool $strictVariables = true): EnvironmentFac
$this->defaultRenderContextOptions = new RenderContextOptions(
strictVariables: $strictVariables,
strictFilters: $this->defaultRenderContextOptions->strictFilters,
rethrowExceptions: $this->defaultRenderContextOptions->rethrowExceptions,
rethrowErrors: $this->defaultRenderContextOptions->rethrowErrors,
);

return $this;
Expand All @@ -100,7 +112,7 @@ public function setStrictFilters(bool $strictFilters = true): EnvironmentFactory
$this->defaultRenderContextOptions = new RenderContextOptions(
strictVariables: $this->defaultRenderContextOptions->strictVariables,
strictFilters: $strictFilters,
rethrowExceptions: $this->defaultRenderContextOptions->rethrowExceptions,
rethrowErrors: $this->defaultRenderContextOptions->rethrowErrors,
);

return $this;
Expand Down
14 changes: 14 additions & 0 deletions src/ErrorHandlers/DefaultErrorHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Keepsuit\Liquid\ErrorHandlers;

use Keepsuit\Liquid\Contracts\LiquidErrorHandler;
use Keepsuit\Liquid\Exceptions\LiquidException;

class DefaultErrorHandler implements LiquidErrorHandler
{
public function handle(LiquidException $error): string
{
return $error->toLiquidErrorMessage();
}
}
14 changes: 14 additions & 0 deletions src/ErrorHandlers/RethrowErrorHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Keepsuit\Liquid\ErrorHandlers;

use Keepsuit\Liquid\Contracts\LiquidErrorHandler;
use Keepsuit\Liquid\Exceptions\LiquidException;

class RethrowErrorHandler implements LiquidErrorHandler
{
public function handle(LiquidException $error): string
{
throw $error;
}
}
11 changes: 6 additions & 5 deletions src/Render/RenderContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
use Closure;
use Keepsuit\Liquid\Contracts\CanBeEvaluated;
use Keepsuit\Liquid\Contracts\IsContextAware;
use Keepsuit\Liquid\Contracts\LiquidErrorHandler;
use Keepsuit\Liquid\Contracts\MapsToLiquid;
use Keepsuit\Liquid\Drop;
use Keepsuit\Liquid\Environment;
use Keepsuit\Liquid\ErrorHandlers\RethrowErrorHandler;
use Keepsuit\Liquid\Exceptions\ArithmeticException;
use Keepsuit\Liquid\Exceptions\InternalException;
use Keepsuit\Liquid\Exceptions\LiquidException;
Expand All @@ -33,6 +35,8 @@ final class RenderContext

public readonly ResourceLimits $resourceLimits;

protected LiquidErrorHandler $errorHandler;

protected int $baseScopeDepth = 0;

protected ?string $templateName = null;
Expand Down Expand Up @@ -86,6 +90,7 @@ public function __construct(
) {
$this->environment = $environment ?? Environment::default();
$this->resourceLimits = $resourceLimits ?? ResourceLimits::clone($this->environment->defaultResourceLimits);
$this->errorHandler = $this->options->rethrowErrors ? new RethrowErrorHandler : $this->environment->errorHandler;

$this->scopes = [[]];

Expand Down Expand Up @@ -299,11 +304,7 @@ public function handleError(Throwable $error, ?int $lineNumber = null): string

$this->sharedState->errors[] = $error;

if ($this->options->rethrowExceptions) {
throw $error;
}

return $error->toLiquidErrorMessage();
return $this->errorHandler->handle($error);
}

public function getErrors(): array
Expand Down
2 changes: 1 addition & 1 deletion src/Render/RenderContextOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function __construct(
/**
* Rethrow exceptions that occur during rendering instead of rendering the error message.
*/
public readonly bool $rethrowExceptions = false,
public readonly bool $rethrowErrors = false,
) {}
}
8 changes: 4 additions & 4 deletions tests/Integration/Tags/AssignTagTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@
test('assign score exceeding resource limit', function () {
$template = parseTemplate('{% assign foo = 42 %}{% assign bar = 23 %}');

$context = new RenderContext(options: new RenderContextOptions(rethrowExceptions: true), resourceLimits: new ResourceLimits(assignScoreLimit: 1));
$context = new RenderContext(options: new RenderContextOptions(rethrowErrors: true), resourceLimits: new ResourceLimits(assignScoreLimit: 1));
expect(fn () => $template->render($context))->toThrow(ResourceLimitException::class);
expect($context->resourceLimits->reached())->toBeTrue();

$context = new RenderContext(options: new RenderContextOptions(rethrowExceptions: true), resourceLimits: new ResourceLimits(assignScoreLimit: 2));
$context = new RenderContext(options: new RenderContextOptions(rethrowErrors: true), resourceLimits: new ResourceLimits(assignScoreLimit: 2));
expect($template->render($context))->toBe('');
expect($context->resourceLimits->reached())->toBeFalse();
expect($context->resourceLimits->getAssignScore())->toBe(2);
});

test('assign score exceeding resource limit from composite object', function () {
$environment = EnvironmentFactory::new()
->setRethrowExceptions()
->setRethrowErrors()
->build();

$template = $environment->parseString("{% assign foo = 'aaaa' | split: '' %}");
Expand Down Expand Up @@ -104,7 +104,7 @@

function assignScoreOf(mixed $value): int
{
$context = new RenderContext(staticData: ['value' => $value], options: new RenderContextOptions(rethrowExceptions: true));
$context = new RenderContext(staticData: ['value' => $value], options: new RenderContextOptions(rethrowErrors: true));
parseTemplate('{% assign obj = value %}')->render($context);

return $context->resourceLimits->getAssignScore();
Expand Down
2 changes: 1 addition & 1 deletion tests/Integration/Tags/ForTagTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@
});

test('for cleans up registers', function () {
$context = new RenderContext(staticData: ['drop' => new ErrorDrop], options: new RenderContextOptions(rethrowExceptions: true));
$context = new RenderContext(staticData: ['drop' => new ErrorDrop], options: new RenderContextOptions(rethrowErrors: true));

expect(fn () => parseTemplate('{% for i in (1..2) %}{{ drop.standard_error }}{% endfor %}')->render($context))->toThrow(\Keepsuit\Liquid\Exceptions\StandardException::class);

Expand Down
14 changes: 7 additions & 7 deletions tests/Integration/TemplateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
test('resource limits abort rendering after first error', function () {
$template = parseTemplate('{% for a in (1..100) %} foo1 {% endfor %} bar {% for a in (1..100) %} foo2 {% endfor %}');
$context = new RenderContext(
options: new RenderContextOptions(rethrowExceptions: false),
options: new RenderContextOptions(rethrowErrors: false),
resourceLimits: new ResourceLimits(renderScoreLimit: 50)
);
expect(fn () => $template->render($context))->toThrow(ResourceLimitException::class);
Expand Down Expand Up @@ -130,7 +130,7 @@

test('undefined variables', function (bool $strict) {
$environment = EnvironmentFactory::new()
->setRethrowExceptions(false)
->setRethrowErrors(false)
->setStrictVariables($strict)
->build();

Expand Down Expand Up @@ -169,7 +169,7 @@
],
options: new RenderContextOptions(
strictVariables: $strict,
rethrowExceptions: false,
rethrowErrors: false,
)
);

Expand All @@ -184,7 +184,7 @@

test('undefined drop method', function (bool $strict) {
$environment = EnvironmentFactory::new()
->setRethrowExceptions(false)
->setRethrowErrors(false)
->setStrictVariables($strict)
->build();

Expand All @@ -211,7 +211,7 @@

test('undefined drop method throw exception', function (bool $strict) {
$environment = EnvironmentFactory::new()
->setRethrowExceptions()
->setRethrowErrors()
->setStrictVariables($strict)
->build();

Expand All @@ -234,7 +234,7 @@

test('undefined filter', function (bool $strict) {
$environment = EnvironmentFactory::new()
->setRethrowExceptions(false)
->setRethrowErrors(false)
->setStrictFilters($strict)
->build();

Expand Down Expand Up @@ -264,7 +264,7 @@

test('undefined filter throw exception', function (bool $strict) {
$environment = EnvironmentFactory::new()
->setRethrowExceptions()
->setRethrowErrors()
->setStrictFilters($strict)
->build();

Expand Down
4 changes: 2 additions & 2 deletions tests/Pest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function renderTemplate(
$environment = $factory
->setFilesystem(new StubFileSystem(partials: $partials))
->setStrictVariables($strictVariables)
->setRethrowExceptions(! $renderErrors)
->setRethrowErrors(! $renderErrors)
->build();

$template = $environment->parseString($template);
Expand Down Expand Up @@ -86,7 +86,7 @@ function streamTemplate(
$environment = $factory
->setFilesystem(new StubFileSystem(partials: $partials))
->setStrictVariables($strictVariables)
->setRethrowExceptions(! $renderErrors)
->setRethrowErrors(! $renderErrors)
->build();

$template = $environment->parseString($template);
Expand Down
4 changes: 2 additions & 2 deletions tests/Unit/EnvironmentFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@

test('default render options settings', function () {
$environment = EnvironmentFactory::new()
->setRethrowExceptions()
->setRethrowErrors()
->setStrictVariables()
->setStrictFilters()
->build();

expect($environment)
->defaultRenderContextOptions->rethrowExceptions->toBeTrue()
->defaultRenderContextOptions->rethrowErrors->toBeTrue()
->defaultRenderContextOptions->strictVariables->toBeTrue()
->defaultRenderContextOptions->strictFilters->toBeTrue();
});
Loading