Skip to content

Commit

Permalink
Merge pull request #4 from sanderdlm/revert-2-context-extension
Browse files Browse the repository at this point in the history
Revert "Parse the page context using a Twig extension instead of a parse step"
  • Loading branch information
sanderdlm authored Dec 29, 2023
2 parents 2ae5215 + c77891b commit 72b3112
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 74 deletions.
5 changes: 4 additions & 1 deletion src/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
use Jug\Domain\File;
use Jug\Domain\Page;
use Jug\Domain\Site;
use Jug\Twig\Parser;
use Symfony\Component\Finder\Finder;

final class Builder
{
public function __construct(
private readonly Config $config
private readonly Config $config,
private readonly Parser $parser
) {
}

Expand All @@ -39,6 +41,7 @@ private function collectPages(): array
$pages[] = new Page(
new File($file->getRelativePathname()),
new File($this->buildOutputPath($file->getRelativePathname())),
$this->parser->parse($file->getRelativePathname())
);
}

Expand Down
10 changes: 1 addition & 9 deletions src/Domain/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,7 @@ class Page
public function __construct(
public readonly File $source,
public readonly File $output,
public array $context = []
public readonly array $context = []
) {
}

/**
* @param array<string, mixed> $context
*/
public function addContext(array $context): void
{
$this->context = $context;
}
}
7 changes: 4 additions & 3 deletions src/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use Jug\Twig\DynamicFilesystemLoader;
use Jug\Twig\HighlightExtension;
use Jug\Twig\MarkdownExtension;
use Jug\Twig\ContextExtension;
use Jug\Twig\Parser;
use Jug\Twig\SqliteExtension;
use ParsedownExtra;
use Symfony\Bridge\Twig\Extension\TranslationExtension;
Expand Down Expand Up @@ -92,7 +92,6 @@ public function buildGenerator(): Generator
$twig->addExtension(new MarkdownExtension(new ParsedownExtra()));
$twig->addExtension(new HighlightExtension());
$twig->addExtension(new SqliteExtension());
$twig->addExtension(new ContextExtension());

$dispatcher = new EventDispatcher();

Expand All @@ -101,8 +100,10 @@ public function buildGenerator(): Generator
$eventFactory($dispatcher);
}

$parser = new Parser($twig);

// Create the site data object
$siteBuilder = new Builder($config);
$siteBuilder = new Builder($config, $parser);

// Create the site generator object
return new Generator($siteBuilder, $twig, $this->filesystem, $dispatcher);
Expand Down
39 changes: 0 additions & 39 deletions src/Twig/ContextExtension.php

This file was deleted.

106 changes: 106 additions & 0 deletions src/Twig/Parser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

namespace Jug\Twig;

use Twig\Environment;
use Twig\Node\Expression\ArrayExpression;
use Twig\Node\Expression\AssignNameExpression;
use Twig\Node\Expression\Binary\AbstractBinary;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Node;
use Twig\Node\SetNode;

class Parser
{
public function __construct(
private readonly Environment $twig
) {
}

/**
* @return array<string, string>
*/
public function parse(string $twigTemplateName): array
{
$source = $this->twig->getLoader()->getSourceContext($twigTemplateName);
$node = $this->twig->parse($this->twig->tokenize($source));

$variables = [];

$this->process($node, $variables);

return $variables;
}

/**
* @param array<string, string> $variables
*/
private function process(Node $node, array &$variables): void
{
if ($node instanceof SetNode) {
$variableNameNodes = $this->getNodes(
$node->getNode('names'),
AssignNameExpression::class
);

$variableValueNodes = $this->getNodes(
$node->getNode('values'),
ConstantExpression::class
);

foreach ($variableNameNodes as $index => $variableNameNode) {
$definedVariableName = $variableNameNode->getAttribute('name');
$correspondingValue = $variableValueNodes[$index];

if (is_array($correspondingValue)) {
foreach ($correspondingValue as $nestedIndex => $nestedValue) {
/*
* Twig returns all ArrayExpressions with both the keys and
* the values in the same list. To get the correct end result
* for both objects and arrays, we have to loop over the array
* and match all the key/value pairs. We assume that the first
* element is the first key, and from the on, each uneven element
* contains the value for the key that comes right before it.
*/
if ($nestedIndex !== 0 && $nestedIndex % 2 !== 0) {
$key = $correspondingValue[$nestedIndex - 1]->getAttribute('value');
$value = $nestedValue->getAttribute('value');
$variables[$definedVariableName][$key] = $value;
}
}
} else {
$variables[$definedVariableName] = $correspondingValue->getAttribute('value');
}
}
}

foreach ($node as $child) {
if ($child instanceof Node) {
$this->process($child, $variables);
}
}
}

/** @phpstan-ignore-next-line */
private function getNodes(Node $parent, string $nodeClass): array
{
$matches = [];

foreach ($parent as $child) {
if ($child instanceof ArrayExpression) {
$matches[] = $this->getNodes($child, ConstantExpression::class);
} elseif ($child instanceof AbstractBinary) {
$matches[] = $this->getNodes($child, ConstantExpression::class);
} else {
if (
$child instanceof $nodeClass &&
is_subclass_of($child, Node::class)
) {
$matches[] = $child;
}
}
}

return $matches;
}
}
7 changes: 4 additions & 3 deletions tests/BaseFunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Jug\Twig\DynamicFilesystemLoader;
use Jug\Twig\HighlightExtension;
use Jug\Twig\MarkdownExtension;
use Jug\Twig\ContextExtension;
use Jug\Twig\Parser;
use Jug\Twig\SqliteExtension;
use ParsedownExtra;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -78,10 +78,11 @@ protected function setUp(): void
$twig->addExtension(new MarkdownExtension(new ParsedownExtra()));
$twig->addExtension(new HighlightExtension());
$twig->addExtension(new SqliteExtension());
$twig->addExtension(new ContextExtension());

$parser = new Parser($twig);

// Create the site data object
$this->builder = new Builder($config);
$this->builder = new Builder($config, $parser);

// Create the site generator object
$this->generator = new Generator($this->builder, $twig, $filesystem, $dispatcher);
Expand Down
7 changes: 5 additions & 2 deletions tests/EventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

class EventTest extends BaseFunctionalTest
{
public function testDynamicConfigValueFromEventEvent(): void
public function testDynamicConfigValueFromBeforeEvent(): void
{
$this->assertTrue($this->site->config->get('a_dynamic_setting'));
$fixtureTags = ['he', 'is', 'a', 'smooth', 'operator'];

$this->assertIsArray($this->site->config->getarray('tags'));
$this->assertEquals($fixtureTags, $this->site->config->getArray('tags'));
}
}
19 changes: 17 additions & 2 deletions tests/Fixture/events.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,27 @@
$dispatcher->addListener(BeforeBuild::NAME, function (Event $event) {
/** @var BeforeBuild $beforeBuild */
$beforeBuild = $event;

/*
* An example of what you can build with the before event would be a tag cloud.
*/
$tags = [];
foreach ($beforeBuild->site->select('tags') as $page) {
if (
array_key_exists('tags', $page->context) &&
is_array($page->context['tags'])
) {
foreach ($page->context['tags'] as $tag) {
$tags[] = $tag;
}
}
}

$beforeBuild->site->config->add('tags', $tags);
});

$dispatcher->addListener(AfterBuild::NAME, function (Event $event) {
/** @var AfterBuild $afterBuild */
$afterBuild = $event;

$afterBuild->site->config->add('a_dynamic_setting', true);
});
};
1 change: 0 additions & 1 deletion tests/Fixture/source/_templates/header.twig
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{{ parseContext() }}
<!DOCTYPE html>
<html lang="en">
<head>
Expand Down
6 changes: 2 additions & 4 deletions tests/Fixture/source/index.twig
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
<h1>Jug</h1>
<p>This is a testing template</p>
<ul>
{% for page in site.select('tags') %}
{% for tag in page.context['tags'] %}
<li>{{ tag }}</li>
{% endfor %}
{% for tag in site.config.get('tags') %}
<li>{{ tag }}</li>
{% endfor %}
</ul>
{% endblock %}
1 change: 0 additions & 1 deletion tests/Fixture/source/set.twig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
{% set foo = [1, 2] %}
{% set bar = {'foo': 'bar'} %}
{% set til, bil = 'til', 'bil' %}
{% set lop = 'foo' ~ 'barz' %}

{% block main %}
<h1>{{ title }}</h1>
Expand Down
9 changes: 0 additions & 9 deletions tests/SiteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,6 @@ public function testSiteSelect(): void
}
}

public function testTags(): void
{
$pagesWithTags = $this->site->select('tags');

foreach ($pagesWithTags as $page) {
$this->assertIsArray($page->context['tags']);
}
}

public function testSiteDir(): void
{
$newsFolderContent = $this->site->dir('news');
Expand Down

0 comments on commit 72b3112

Please sign in to comment.