diff --git a/.env.example b/.env.example
index ac4eb2f..e181b10 100644
--- a/.env.example
+++ b/.env.example
@@ -1,6 +1,6 @@
BASE_PATH=./
BUILD_ROOT_PATH=/app/
-PROJECT_NAME=me_library
+PROJECT_NAME=dhii_twig-template
PHP_BUILD_VERSION=7.2
PHP_TEST_VERSION=7.2
diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index a5e5aaf..26fc44d 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -5,7 +5,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- php-versions: ['7.2', '7.3', '7.4']
+ php-versions: ['7.2', '7.3', '7.4', '8.0']
steps:
- uses: actions/checkout@v2
diff --git a/.idea/php-project.iml b/.idea/php-project.iml
index 995493d..4886a25 100644
--- a/.idea/php-project.iml
+++ b/.idea/php-project.iml
@@ -5,6 +5,7 @@
+
@@ -60,6 +61,9 @@
+
+
+
diff --git a/.idea/php.xml b/.idea/php.xml
index f881867..72688c0 100644
--- a/.idea/php.xml
+++ b/.idea/php.xml
@@ -57,6 +57,9 @@
+
+
+
@@ -187,7 +190,7 @@
-
+
diff --git a/composer.json b/composer.json
index 80dc3a9..cbfd466 100644
--- a/composer.json
+++ b/composer.json
@@ -11,8 +11,9 @@
}
],
"require": {
- "php": "^7.2",
- "dhii/output-renderer-interface": "^0.4"
+ "php": "^7.2 | ^8.0",
+ "dhii/output-renderer-interface": "^0.4",
+ "twig/twig": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "^8.0 | ^9.0",
diff --git a/composer.lock b/composer.lock
index 8d9d833..338bb2f 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "1dfd20fa40210db6f4e0e33c6d18f040",
+ "content-hash": "dde9acfce478521545be4538c8900a02",
"packages": [
{
"name": "dhii/output-renderer-interface",
@@ -107,6 +107,244 @@
"source": "https://github.com/Dhii/stringable-interface/tree/master"
},
"time": "2017-01-23T15:08:20+00:00"
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "dev-main",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "fade6deebd931cfd7a544f68479405a6a08979a3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/fade6deebd931cfd7a544f68479405a6a08979a3",
+ "reference": "fade6deebd931cfd7a544f68479405a6a08979a3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "default-branch": true,
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.21-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-ctype/tree/main"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-10-26T13:35:45+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "dev-main",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "401c9d9d3400c53a8f1a39425f0543406c137a43"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/401c9d9d3400c53a8f1a39425f0543406c137a43",
+ "reference": "401c9d9d3400c53a8f1a39425f0543406c137a43",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "default-branch": true,
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.21-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/main"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-10-26T13:35:45+00:00"
+ },
+ {
+ "name": "twig/twig",
+ "version": "3.x-dev",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/twigphp/Twig.git",
+ "reference": "e3bca056f1331cf017893c2248d1d4951c165162"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/e3bca056f1331cf017893c2248d1d4951c165162",
+ "reference": "e3bca056f1331cf017893c2248d1d4951c165162",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/polyfill-ctype": "^1.8",
+ "symfony/polyfill-mbstring": "^1.3"
+ },
+ "require-dev": {
+ "psr/container": "^1.0",
+ "symfony/phpunit-bridge": "^4.4.9|^5.0.9"
+ },
+ "default-branch": true,
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Twig\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Twig Team",
+ "role": "Contributors"
+ },
+ {
+ "name": "Armin Ronacher",
+ "email": "armin.ronacher@active-4.com",
+ "role": "Project Founder"
+ }
+ ],
+ "description": "Twig, the flexible, fast, and secure template language for PHP",
+ "homepage": "https://twig.symfony.com",
+ "keywords": [
+ "templating"
+ ],
+ "support": {
+ "issues": "https://github.com/twigphp/Twig/issues",
+ "source": "https://github.com/twigphp/Twig/tree/3.x"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/twig/twig",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-11-30T12:06:55+00:00"
}
],
"packages-dev": [
@@ -1687,12 +1925,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "51f5d93eedecd6f512562cb26d0f4d3abb52eb41"
+ "reference": "29f420d0b3844451a03d1d6e5e641bac88f27b07"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/51f5d93eedecd6f512562cb26d0f4d3abb52eb41",
- "reference": "51f5d93eedecd6f512562cb26d0f4d3abb52eb41",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/29f420d0b3844451a03d1d6e5e641bac88f27b07",
+ "reference": "29f420d0b3844451a03d1d6e5e641bac88f27b07",
"shasum": ""
},
"require": {
@@ -1776,7 +2014,7 @@
"type": "github"
}
],
- "time": "2020-12-23T06:00:38+00:00"
+ "time": "2020-12-24T12:25:02+00:00"
},
{
"name": "psr/container",
@@ -2829,86 +3067,6 @@
],
"time": "2020-12-18T08:03:24+00:00"
},
- {
- "name": "symfony/polyfill-ctype",
- "version": "dev-main",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "fade6deebd931cfd7a544f68479405a6a08979a3"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/fade6deebd931cfd7a544f68479405a6a08979a3",
- "reference": "fade6deebd931cfd7a544f68479405a6a08979a3",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "suggest": {
- "ext-ctype": "For best performance"
- },
- "default-branch": true,
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "1.21-dev"
- },
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Polyfill\\Ctype\\": ""
- },
- "files": [
- "bootstrap.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Gert de Pagter",
- "email": "BackEndTea@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for ctype functions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "ctype",
- "polyfill",
- "portable"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/main"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "time": "2020-10-26T13:35:45+00:00"
- },
{
"name": "symfony/polyfill-intl-grapheme",
"version": "dev-main",
@@ -3076,87 +3234,6 @@
],
"time": "2020-10-26T13:35:45+00:00"
},
- {
- "name": "symfony/polyfill-mbstring",
- "version": "dev-main",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "401c9d9d3400c53a8f1a39425f0543406c137a43"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/401c9d9d3400c53a8f1a39425f0543406c137a43",
- "reference": "401c9d9d3400c53a8f1a39425f0543406c137a43",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "suggest": {
- "ext-mbstring": "For best performance"
- },
- "default-branch": true,
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "1.21-dev"
- },
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Polyfill\\Mbstring\\": ""
- },
- "files": [
- "bootstrap.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for the Mbstring extension",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "mbstring",
- "polyfill",
- "portable",
- "shim"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/main"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "time": "2020-10-26T13:35:45+00:00"
- },
{
"name": "symfony/polyfill-php73",
"version": "dev-main",
@@ -3803,7 +3880,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": "^7.2"
+ "php": "^7.2 | ^8.0"
},
"platform-dev": [],
"plugin-api-version": "2.0.0"
diff --git a/src/Exception/TemplateRenderException.php b/src/Exception/TemplateRenderException.php
new file mode 100644
index 0000000..9903901
--- /dev/null
+++ b/src/Exception/TemplateRenderException.php
@@ -0,0 +1,56 @@
+renderer = $renderer;
+ $this->context = $context;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getContext()
+ {
+ return $this->context;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getRenderer()
+ {
+ return $this->renderer;
+ }
+}
diff --git a/src/FileTemplate.php b/src/FileTemplate.php
new file mode 100644
index 0000000..2b589df
--- /dev/null
+++ b/src/FileTemplate.php
@@ -0,0 +1,74 @@
+twigTemplate = $twigTemplate;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function render($context = null)
+ {
+ $context = $this->normalizeContext($context);
+
+ try {
+ return $this->twigTemplate->render($context);
+ } catch (Exception $e) {
+ throw new TemplateRenderException($this, $context, $this->__('Could not render template'), 0, $e);
+ }
+ }
+
+ /**
+ * Normalizes context to a canonical representation.
+ *
+ * @param array|iterable|object $context The context to normalize.
+ * @return array The canonical representation of the context.
+ * @throws InvalidArgumentException If context cannot be normalized.
+ */
+ protected function normalizeContext($context): array
+ {
+ if ($context instanceof Traversable) {
+ $context = iterator_to_array($context);
+ }
+
+ if (!is_array($context)) {
+ throw new InvalidArgumentException($this->__('Context must be an array; %1$s given', [gettype($context)]));
+ }
+
+ return $context;
+ }
+
+ /**
+ * Translates a string and interpolates values.
+ *
+ * The values in the string may be specified using the {@see sprintf()} style.
+ *
+ * @param string $string The string to translate.
+ * @param array $placeholders Numeric array. The values to replace placeholders in the string with.
+ *
+ * @throws Exception If problem translating.
+ *
+ * @return string The translated string, with placeholders replaced.
+ */
+ protected function __(string $string, $placeholders = []): string
+ {
+ return vsprintf($string, $placeholders);
+ }
+}
diff --git a/src/FileTemplateFactory.php b/src/FileTemplateFactory.php
new file mode 100644
index 0000000..b8fa96a
--- /dev/null
+++ b/src/FileTemplateFactory.php
@@ -0,0 +1,36 @@
+environment = $environment;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function fromPath(string $templatePath): TemplateInterface
+ {
+ $twigTemplate = $this->environment->load($templatePath);
+ $template = new FileTemplate($twigTemplate);
+
+ return $template;
+ }
+}
diff --git a/tests/functional/FileTemplateFactoryTest.php b/tests/functional/FileTemplateFactoryTest.php
new file mode 100644
index 0000000..4645799
--- /dev/null
+++ b/tests/functional/FileTemplateFactoryTest.php
@@ -0,0 +1,73 @@
+getMockBuilder(Subject::class)
+ ->enableProxyingToOriginalMethods()
+ ->setConstructorArgs([$environment])
+ ->getMock();
+
+ return $mock;
+ }
+
+ public function testTemplate()
+ {
+ {
+ $env = $this->getEnvironment();
+ $templatePath = self::TEMPLATE_PATH_SIMPLE;
+ $message = uniqid('message');
+ $data = [
+ 'message' => $message,
+ ];
+ $subject = $this->createSubject($env);
+ }
+
+ {
+ $template = $subject->fromPath($templatePath);
+ $result = $template->render($data);
+ $this->assertEquals($this->renderTemplate($templatePath, $data), $result);
+ }
+ }
+
+ protected function renderTemplate(string $filePath, array $context): string
+ {
+ $env = $this->getEnvironment();
+ $template = $env->load($filePath);
+ $output = $template->render($context);
+
+ return $output;
+ }
+
+ protected function getEnvironment(): Environment
+ {
+ if (!($this->environment instanceof Environment)) {
+ $loader = new FilesystemLoader(
+ [
+ '__main__' => '//',
+ ], '//'
+ );
+ $this->environment = new Environment($loader, []);
+ }
+
+ return $this->environment;
+ }
+}
diff --git a/tests/stub/simple.twig b/tests/stub/simple.twig
new file mode 100644
index 0000000..d0edeb9
--- /dev/null
+++ b/tests/stub/simple.twig
@@ -0,0 +1 @@
+{{ message }}