Skip to content

Commit

Permalink
Merge pull request #2 from keepsuit/refactoring
Browse files Browse the repository at this point in the history
Added TemplateFactory
  • Loading branch information
cappuc authored Aug 31, 2023
2 parents 8de56dc + b2af578 commit f143352
Show file tree
Hide file tree
Showing 47 changed files with 719 additions and 613 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"symfony/yaml": "^6.0"
},
"require-dev": {
"illuminate/support": "^10.21",
"laravel/pint": "^1.2",
"pestphp/pest": "^2.6",
"pestphp/pest-plugin-arch": "^2.0",
Expand All @@ -46,7 +45,8 @@
"test": "vendor/bin/pest",
"test-coverage": "vendor/bin/pest --coverage",
"format": "vendor/bin/pint",
"lint": "vendor/bin/phpstan analyse"
"lint": "vendor/bin/phpstan analyse",
"benchmark": "@php performance/benchmark.php"
},
"config": {
"sort-packages": true,
Expand Down
6 changes: 3 additions & 3 deletions performance/BenchmarkRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

class BenchmarkRunner
{
public function run(int $seconds, \Closure $callback)
public function run(int $seconds, \Closure $callback): BenchmarkResult
{
$durationNs = $seconds * 1e9;
$start = hrtime(true);

gc_collect_cycles();

$runs = [];
do {
gc_collect_cycles();

$runs[] = $this->measure($callback);
$end = hrtime(true);
} while (($end - $start) < $durationNs);
Expand Down
14 changes: 6 additions & 8 deletions performance/CompiledThemeTestTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

namespace Keepsuit\Liquid\Performance;

use Keepsuit\Liquid\Performance\Shopify\CustomFilters;
use Keepsuit\Liquid\Render\Context;
use Keepsuit\Liquid\Template;
use Keepsuit\Liquid\TemplateFactory;

class CompiledThemeTestTemplate
{
public function __construct(
protected TemplateFactory $factory,
public string $templateName,
public Template $template,
public ?Template $layout,
Expand All @@ -22,23 +23,20 @@ public function pageTemplate(): string

public function render(array $assigns = []): void
{
$content = $this->template->render($this->buildContext($assigns));

if ($this->layout) {
$this->layout->render($this->buildContext([
...$assigns,
'content_for_layout' => $this->template->render($this->buildContext($assigns)),
'content_for_layout' => $content,
]));
} else {
$this->template->render($this->buildContext($assigns));
}
}

protected function buildContext(array $assigns = []): Context
{
return new Context(
return $this->factory->newRenderContext(
staticEnvironment: $assigns,
filters: [
CustomFilters::class,
],
);
}
}
5 changes: 3 additions & 2 deletions performance/Shopify/CommentFormTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function parse(Tokenizer $tokenizer): static
public function render(Context $context): string
{
$article = $context->get($this->variableName);
assert(is_array($article));

$context->stack(function (Context $context) {
$context->set('form', [
Expand All @@ -52,10 +53,10 @@ public function render(Context $context): string
return $this->wrapInForm($article, parent::render($context));
}

protected function wrapInForm(mixed $article, string $input): string
protected function wrapInForm(array $article, string $input): string
{
return <<<HTML
<form id="article-{$article->id}-comment-form" class="comment-form" method="post" action="">
<form id="article-{$article['id']}-comment-form" class="comment-form" method="post" action="">
$input
</form>
HTML;
Expand Down
9 changes: 2 additions & 7 deletions performance/Shopify/CustomFilters.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@
namespace Keepsuit\Liquid\Performance\Shopify;

use Keepsuit\Liquid\Exceptions\InvalidArgumentException;
use Keepsuit\Liquid\Render\Context;
use Keepsuit\Liquid\Filters\FiltersProvider;

class CustomFilters
class CustomFilters extends FiltersProvider
{
public function __construct(
protected Context $context
) {
}

public function json(mixed $value): string
{
if (is_array($value) && array_key_exists('collections', $value)) {
Expand Down
2 changes: 1 addition & 1 deletion performance/Shopify/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Database

protected static ?array $tables = null;

public static function tables()
public static function tables(): array
{
if (static::$tables !== null) {
return static::$tables;
Expand Down
22 changes: 13 additions & 9 deletions performance/Shopify/PaginateTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Keepsuit\Liquid\Exceptions\InvalidArgumentException;
use Keepsuit\Liquid\Exceptions\SyntaxException;
use Keepsuit\Liquid\Nodes\Range;
use Keepsuit\Liquid\Parse\Regex;
use Keepsuit\Liquid\Parse\Tokenizer;
use Keepsuit\Liquid\Render\Context;
Expand Down Expand Up @@ -50,8 +51,11 @@ public function render(Context $context): string
$currentPage = $context->get('current_page');

$collection = $context->get($this->collectionName);
$collection = is_iterable($collection) ? iterator_to_array($collection) : $collection;

$collection = match (true) {
$collection instanceof Range => $collection->toArray(),
$collection instanceof \Iterator => iterator_to_array($collection),
default => $collection,
};
if (! is_array($collection)) {
throw new InvalidArgumentException(sprintf('Cannot paginate array %s. Not found.', $this->collectionName));
}
Expand All @@ -71,14 +75,14 @@ public function render(Context $context): string
];

if ($pageCount > 2) {
foreach (range(1, $pageCount - 1) as $page) {
foreach (range(1, (int) $pageCount - 1) as $page) {
$pagination['parts'][] = match (true) {
$currentPage === $page => $this->noLink($page),
$page === 1 => $this->link($page, $page),
$page === $pageCount - 1 => $this->link($page, $page),
$page <= $currentPage - $this->attributes['window_size'] => $this->link('...', $page),
$page >= $currentPage + $this->attributes['window_size'] => $this->link('...', $page),
default => $this->link($page, $page),
$currentPage === $page => $this->noLink((string) $page),
$page === 1 => $this->link((string) $page, $page),
$page === $pageCount - 1 => $this->link((string) $page, $page),
$page <= ($currentPage - (int) $this->attributes['window_size']) => $this->link('...', $page),
$page >= ($currentPage + (int) $this->attributes['window_size']) => $this->link('...', $page),
default => $this->link((string) $page, $page),
};
}
}
Expand Down
18 changes: 10 additions & 8 deletions performance/ThemeRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Keepsuit\Liquid\Performance\Shopify\Database;
use Keepsuit\Liquid\Support\Arr;
use Keepsuit\Liquid\Template;
use Keepsuit\Liquid\TemplateFactory;

class ThemeRunner
{
Expand All @@ -18,9 +18,10 @@ class ThemeRunner
*/
protected array $compiledTemplates;

public function __construct()
{
$files = glob(__DIR__.'/tests/**/*.liquid');
public function __construct(
protected TemplateFactory $templateFactory
) {
$files = glob(__DIR__.'/tests/**/*.liquid') ?: [];

$this->tests = Arr::compact(Arr::map($files, function (string $path) {
if (basename($path) === 'theme.liquid') {
Expand All @@ -30,9 +31,10 @@ public function __construct()
$themePath = dirname($path).'/theme.liquid';

return new ThemeTestTemplate(
factory: $this->templateFactory,
templateName: $path,
liquid: file_get_contents($path),
layoutLiquid: file_exists($themePath) ? file_get_contents($themePath) : null,
liquid: file_get_contents($path) ?: '',
layoutLiquid: file_exists($themePath) ? (file_get_contents($themePath) ?: '') : null,
);
}));

Expand All @@ -42,9 +44,9 @@ public function __construct()
public function compile(): void
{
foreach ($this->tests as $test) {
Template::parse($test->liquid);
$this->templateFactory->parse($test->liquid);
if ($test->layoutLiquid !== null) {
Template::parse($test->layoutLiquid);
$this->templateFactory->parse($test->layoutLiquid);
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions performance/ThemeTestTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

namespace Keepsuit\Liquid\Performance;

use Keepsuit\Liquid\Template;
use Keepsuit\Liquid\TemplateFactory;

class ThemeTestTemplate
{
public function __construct(
protected TemplateFactory $factory,
public string $templateName,
public string $liquid,
public ?string $layoutLiquid,
Expand All @@ -20,10 +21,11 @@ public function pageTemplate(): string

public function compile(): CompiledThemeTestTemplate
{
$template = Template::parse($this->liquid);
$layout = $this->layoutLiquid !== null ? Template::parse($this->layoutLiquid) : null;
$template = $this->factory->parse($this->liquid);
$layout = $this->layoutLiquid !== null ? $this->factory->parse($this->layoutLiquid) : null;

return new CompiledThemeTestTemplate(
factory: $this->factory,
templateName: $this->templateName,
template: $template,
layout: $layout,
Expand Down
25 changes: 17 additions & 8 deletions performance/benchmark.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
use Keepsuit\Liquid\Performance\BenchmarkResult;
use Keepsuit\Liquid\Performance\BenchmarkRunner;
use Keepsuit\Liquid\Performance\Shopify\CommentFormTag;
use Keepsuit\Liquid\Performance\Shopify\CustomFilters;
use Keepsuit\Liquid\Performance\Shopify\PaginateTag;
use Keepsuit\Liquid\Performance\ThemeRunner;
use Keepsuit\Liquid\Template;
use Keepsuit\Liquid\TemplateFactory;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand All @@ -15,28 +16,33 @@

require __DIR__.'/../vendor/autoload.php';

Template::registerTag(CommentFormTag::class);
Template::registerTag(PaginateTag::class);
$templateFactory = TemplateFactory::new()
->registerTag(CommentFormTag::class)
->registerTag(PaginateTag::class)
->registerFilter(CustomFilters::class);

(new SingleCommandApplication())
->setName('Benchmark')
->setCode(function (InputInterface $input, OutputInterface $output) {
->setCode(function (InputInterface $input, OutputInterface $output) use ($templateFactory) {
$style = new SymfonyStyle($input, $output);

$times = 10;
$warmup = 5;
$warmup = 0;

$output->writeln(sprintf('Running benchmark for %s seconds (with %s seconds warmup).', $times, $warmup));
if ($warmup > 0) {
$output->writeln(sprintf('Running benchmark for %s seconds (with %s seconds warmup).', $times, $warmup));
} else {
$output->writeln(sprintf('Running benchmark for %s seconds.', $times));
}

$benchmark = new BenchmarkRunner();
$profiler = new ThemeRunner();
$profiler = new ThemeRunner($templateFactory);

if ($warmup > 0) {
$output->writeln('Warming up...');
$benchmark->run($warmup, fn () => $profiler->compile());
}

$output->writeln('Benchmarking...');
$computeTable = $style->createTable();
$computeTable->setHeaders([
'test',
Expand All @@ -45,8 +51,11 @@
'runs',
'duration',
]);
$output->writeln('Running parse benchmark...');
outputBenchmarkResult($computeTable, 'parse', $benchmark->run($times, fn () => $profiler->compile()));
$output->writeln('Running render benchmark...');
outputBenchmarkResult($computeTable, 'render', $benchmark->run($times, fn () => $profiler->render()));
$output->writeln('Running parse & render benchmark...');
outputBenchmarkResult($computeTable, 'parse & render', $benchmark->run($times, fn () => $profiler->run()));
$computeTable->render();
})
Expand Down
15 changes: 15 additions & 0 deletions src/Concerns/ContextAware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Keepsuit\Liquid\Concerns;

use Keepsuit\Liquid\Render\Context;

trait ContextAware
{
protected Context $context;

public function setContext(Context $context): void
{
$this->context = $context;
}
}
11 changes: 3 additions & 8 deletions src/Drop.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,22 @@

namespace Keepsuit\Liquid;

use Keepsuit\Liquid\Concerns\ContextAware;
use Keepsuit\Liquid\Contracts\IsContextAware;
use Keepsuit\Liquid\Contracts\MapsToLiquid;
use Keepsuit\Liquid\Drops\DropMethodPrivate;
use Keepsuit\Liquid\Exceptions\UndefinedDropMethodException;
use Keepsuit\Liquid\Render\Context;
use Keepsuit\Liquid\Support\Str;

class Drop implements IsContextAware, MapsToLiquid
{
protected ?Context $context = null;
use ContextAware;

/**
* @var string[]
*/
private ?array $invokableMethods = null;

public function setContext(Context $context): void
{
$this->context = $context;
}

public function toLiquid(): mixed
{
return $this;
Expand All @@ -35,7 +30,7 @@ public function toLiquidValue(): mixed

protected function liquidMethodMissing(string $name): mixed
{
if ($this->context?->strictVariables) {
if ($this->context->strictVariables) {
throw new UndefinedDropMethodException($name);
}

Expand Down
11 changes: 11 additions & 0 deletions src/Filters/FiltersProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Keepsuit\Liquid\Filters;

use Keepsuit\Liquid\Concerns\ContextAware;
use Keepsuit\Liquid\Contracts\IsContextAware;

abstract class FiltersProvider implements IsContextAware
{
use ContextAware;
}
8 changes: 1 addition & 7 deletions src/Filters/StandardFilters.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,11 @@
use Keepsuit\Liquid\Contracts\MapsToLiquid;
use Keepsuit\Liquid\Drop;
use Keepsuit\Liquid\Exceptions\InvalidArgumentException;
use Keepsuit\Liquid\Render\Context;
use Keepsuit\Liquid\Support\Arr;
use Keepsuit\Liquid\Support\Str;

class StandardFilters
class StandardFilters extends FiltersProvider
{
public function __construct(
protected Context $context
) {
}

/**
* Returns the absolute value of a number.
*/
Expand Down
Loading

0 comments on commit f143352

Please sign in to comment.