Skip to content

Commit

Permalink
Overhauled the template engine.
Browse files Browse the repository at this point in the history
  • Loading branch information
danbettles committed Sep 28, 2022
1 parent ca220db commit 9fcd6fe
Show file tree
Hide file tree
Showing 77 changed files with 1,080 additions and 493 deletions.
5 changes: 0 additions & 5 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@
<file>src/</file>
<file>tests/</file>

<!-- Ignore fixtures. -->
<exclude-pattern>\/FileInfoTest\/.*?$</exclude-pattern>
<exclude-pattern>\/TemplateFileTest\/.*?$</exclude-pattern>
<exclude-pattern>\/TemplateEngineTest\/.*?$</exclude-pattern>

<arg name="extensions" value="php"/>
<arg value="p"/>
<arg name="colors"/>
Expand Down
12 changes: 5 additions & 7 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ parameters:
- src
- tests
ignoreErrors:
-
message: '#^Variable \$\w+ might not be defined.$#'
paths:
- tests/src/TemplateEngineTest/*
-
message: '#^Call to an undefined method DanBettles\\Marigold\\OutputHelper\\Html5OutputHelper::create[A-Z]#'
path: tests/src/OutputHelper/Html5OutputHelperTest.php
Expand All @@ -17,6 +13,8 @@ parameters:
path: tests/src/OutputHelper/Html5OutputHelperTest.php
count: 1
-
message: "#^Anonymous function has an unused use \\$__layout\\.$#"
count: 1
path: src/TemplateEngine.php
message: '#^Variable \$\w+ might not be defined.$#'
path: tests/src/PhpTest/*
-
message: '#^Variable \$\w+ might not be defined.$#'
path: tests/src/TemplateEngine/EngineTest/*
1 change: 1 addition & 0 deletions src/Exception/FileTypeNotSupportedException.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use const null;

// @todo Remove this?
class FileTypeNotSupportedException extends RuntimeException
{
/**
Expand Down
2 changes: 1 addition & 1 deletion src/File/FileInfo.php → src/FileInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace DanBettles\Marigold\File;
namespace DanBettles\Marigold;

use SplFileInfo;

Expand Down
1 change: 1 addition & 0 deletions src/OutputHelper/OutputHelperInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace DanBettles\Marigold\OutputHelper;

// @todo Remove this.
interface OutputHelperInterface
{
}
54 changes: 54 additions & 0 deletions src/Php.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace DanBettles\Marigold;

use DanBettles\Marigold\Exception\FileNotFoundException;

use function extract;
use function is_file;
use function ob_end_clean;
use function ob_get_contents;
use function ob_start;

use const null;

class Php
{
/**
* @param array<string, mixed> $context
* @return mixed
* @throws FileNotFoundException If the PHP file does not exist.
*/
public function executeFile(
string $pathname,
array $context = [],
?string &$output = null
) {
if (!is_file($pathname)) {
throw new FileNotFoundException($pathname);
}

return (static function (
string $__FILE__,
array $context,
&$__OUTPUT__
) {
ob_start();

try {
extract($context);
unset($context);

$__RESPONSE__ = require $__FILE__;

$__OUTPUT__ = ob_get_contents();

return $__RESPONSE__;
} finally {
ob_end_clean();
}
})($pathname, $context, $output);
}
}
8 changes: 4 additions & 4 deletions src/ServiceFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
class ServiceFactory
{
/**
* @var array<string, class-string|Closure>
* @phpstan-var array<string, class-string|Closure>
*/
private array $config;

Expand All @@ -28,7 +28,7 @@ class ServiceFactory
private array $services = [];

/**
* @param array<string, class-string|Closure> $config
* @phpstan-param array<string, class-string|Closure> $config
*/
public function __construct(array $config)
{
Expand Down Expand Up @@ -87,7 +87,7 @@ public function get(string $id): object
}

/**
* @param array<string, class-string|Closure> $config
* @phpstan-param array<string, class-string|Closure> $config
*/
private function setConfig(array $config): self
{
Expand All @@ -96,7 +96,7 @@ private function setConfig(array $config): self
}

/**
* @return array<string, class-string|Closure> $config
* @phpstan-return array<string, class-string|Closure> $config
*/
public function getConfig(): array
{
Expand Down
122 changes: 0 additions & 122 deletions src/TemplateEngine.php

This file was deleted.

116 changes: 116 additions & 0 deletions src/TemplateEngine/Engine.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

declare(strict_types=1);

namespace DanBettles\Marigold\TemplateEngine;

use DanBettles\Marigold\Exception\FileNotFoundException;
use DanBettles\Marigold\Php;
use SplFileInfo;

use function array_replace;

use const null;

class Engine
{
private Php $php;

private TemplateFileLoader $templateFileLoader;

public function __construct(
Php $php,
TemplateFileLoader $templateFileLoader
) {
$this
->setPhp($php)
->setTemplateFileLoader($templateFileLoader)
;
}

/**
* Inside the template being rendered, variables can be found in the `$input` collection. The value of a variable
* called "foo" could be accessed with `$input['foo']`, for example.
*
* The `$output` object provides:
* - `include()`, which allows to include other files;
* - and `insertInto()`/`wrapWith()`, which causes the output of the template to be inserted into another template.
*
* @param string|SplFileInfo $pathnameOrFileInfo
* @param array<string, mixed> $variables
* @throws FileNotFoundException If the template file could not be found.
*/
public function render(
$pathnameOrFileInfo,
array $variables = []
): string {
$templateFile = $this->getTemplateFileLoader()->findTemplate($pathnameOrFileInfo);

if (null === $templateFile) {
throw new FileNotFoundException((string) $pathnameOrFileInfo);
}

$output = new OutputFacade($this);

$renderedOutput = null;

$this->getPhp()->executeFile(
$templateFile->getPathname(),
[
'input' => $variables,
'output' => $output,
],
$renderedOutput
);

if ($output->getWrapperArgs()) {
// @phpstan-ignore-next-line
list(
$wrapperPathnameOrTemplateFile,
$wrapperTargetVarName,
$wrapperVariables
) = $output->getWrapperArgs();

/** @var array<string, mixed> */
$wrapperVariables = array_replace($wrapperVariables, [
($wrapperTargetVarName) => $renderedOutput,
]);

return (new self($this->getPhp(), $this->getTemplateFileLoader()))
->render($wrapperPathnameOrTemplateFile, $wrapperVariables)
;
}

return $renderedOutput;
}

private function setPhp(Php $php): self
{
$this->php = $php;
return $this;
}

public function getPhp(): Php
{
return $this->php;
}

private function setTemplateFileLoader(TemplateFileLoader $loader): self
{
$this->templateFileLoader = $loader;
return $this;
}

public function getTemplateFileLoader(): TemplateFileLoader
{
return $this->templateFileLoader;
}

/**
* Factory method, for convenience.
*/
public static function create(TemplateFileLoader $loader): self
{
return new self(new Php(), $loader);
}
}
Loading

0 comments on commit 9fcd6fe

Please sign in to comment.