Skip to content

Commit

Permalink
Custom Twig Extensions (#49)
Browse files Browse the repository at this point in the history
* Adding the ability to load custom Twig Extensions

* Adding Twig Extension docs and example
  • Loading branch information
EvanLovely authored Feb 5, 2018
1 parent f402a2f commit b6f6297
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 0 deletions.
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,52 @@ This tag would be used like this in a pattern:
{{ name }}
```

### Adding a custom Twig Extension

A [Twig Extension](https://twig.symfony.com/doc/1.x/advanced.html#creating-an-extension) is a collection of Twig functions, filters, tags, globals, and tests all as a single bundle. This approach is more advanced than adding a single function or filter using the above method, but allows greater flexibility as the whole Twig Extension can be installed in multiple environments.

To add a Twig Extension using the PHP class `\MyProject\MyCustomTwigExtension`, add this to `config.yml`:

```yml
twigExtensions:
- '\MyProject\MyCustomTwigExtension'
```
What happens under the hood is basically this:
```php
$twig = new Twig_Environment($loader);

foreach ($twigExtensions as $twigExtension) {
$twig->addExtension(new $twigExtension());
}
```

If two Twig Extensions declare a function, filter, etc; the later ones override earlier ones. Any ones declared in Pattern Lab's `_twig-components` folder will override any declared using this method of custom Twig Extensions.

For an example of how this works, see `ExampleTwigExtension.php` in this repo. You can enable it by adding this to your `config.yml`:

```yml
twigExtensions:
- '\PatternLab\PatternEngine\Twig\ExampleTwigExtension'
```
Then place this in any Twig file:
```twig
<p>Testing: {{ testPlFunction('testing...') }}</p>
```
That function declaration looks like this in `ExampleTwigExtension.php`:

```php
new Twig_SimpleFunction('testPlFunction', function($arg) {
return 'Thanks for testing out the Pattern Lab Example Twig Extension with this arg: ' . $arg;
}),
```

An incredible amount of exciting possibilities are enabled with this; have fun!

### Enable `dump()`

To use `dump()` set `twigDebug` in `config/config.yml` to `true`.
Expand Down
93 changes: 93 additions & 0 deletions src/PatternLab/PatternEngine/Twig/ExampleTwigExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace PatternLab\PatternEngine\Twig;

use Twig_Extension;
use Twig_ExtensionInterface;
use Twig_SimpleFilter;
use Twig_SimpleFunction;

class ExampleTwigExtension extends Twig_Extension implements Twig_ExtensionInterface {

/**
* Returns the name of the extension.
*
* @return string The extension name
*
* @deprecated since 1.26 (to be removed in 2.0), not used anymore internally
*/
function getName() {
return 'Pattern Lab Twig ExampleTwigExtension';
}

/**
* Returns a list of filters to add to the existing list.
*
* @return Twig_SimpleFilter[]
*/
function getFilters() {
return [];
}

/**
* Returns a list of functions to add to the existing list.
*
* @return Twig_SimpleFunction[]
*/
function getFunctions() {
return [
new Twig_SimpleFunction('testPlFunction', function($arg) {
return 'Thanks for testing out the Pattern Lab Example Twig Extension with this arg: ' . $arg;
}),
];
}

/**
* Returns a list of operators to add to the existing list.
*
* @return array<array> First array of unary operators, second array of binary operators
*/
function getOperators() {
return [];
}

/**
* Returns a list of global variables to add to the existing list.
*
* @return array An array of global variables
*
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_GlobalsInterface instead
*/
function getGlobals() {
return [
'pl' => 'is awesome',
];
}

/**
* Returns a list of tests to add to the existing list.
*
* @return Twig_SimpleTest[]
*/
function getTests() {
return [];
}
/**
* Returns the token parser instances to add to the existing list.
*
* @return (Twig_TokenParserInterface|Twig_TokenParserBrokerInterface)[]
*/
function getTokenParsers() {
return [];
}

/**
* Returns the node visitor instances to add to the existing list.
*
* @return Twig_NodeVisitorInterface[]
*/
function getNodeVisitors() {
return [];
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function __construct($options = array()) {

// customize Twig
TwigUtil::setInstance($instance);
TwigUtil::loadCustomExtensions();
TwigUtil::loadFilters();
TwigUtil::loadFunctions();
TwigUtil::loadTags();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public function __construct($options = array()) {

// customize Twig
TwigUtil::setInstance($instance);
TwigUtil::loadCustomExtensions();
TwigUtil::loadFilters();
TwigUtil::loadFunctions();
TwigUtil::loadTags();
Expand Down
1 change: 1 addition & 0 deletions src/PatternLab/PatternEngine/Twig/Loaders/StringLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public function __construct($options = array()) {

// customize Twig
TwigUtil::setInstance($instance);
TwigUtil::loadCustomExtensions();
TwigUtil::loadFilters();
TwigUtil::loadFunctions();
TwigUtil::loadTags();
Expand Down
21 changes: 21 additions & 0 deletions src/PatternLab/PatternEngine/Twig/TwigUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,27 @@ public static function setInstance($instance = "") {

}

/**
* Load Custom Twig Extensions
* Looks in config for an array of strings that are classes that can be called and implements the interface `Twig_ExtensionInterface`
* Config example:
* twigExtensions:
* - '\MyProject\MyCustomTwigExtension'
* @link https://twig.symfony.com/doc/1.x/advanced.html#creating-an-extension
*/
public static function loadCustomExtensions() {
$twigExtensions = Config::getOption("twigExtensions");
if ($twigExtensions) {
foreach ($twigExtensions as $twigExtension) {
if (class_exists($twigExtension)) {
self::$instance->addExtension(new $twigExtension());
} else {
Console::writeError("Your custom Twig Extension setting isn't a PHP class that exists: `" . $twigExtension . "`");
}
}
}
}

/**
* Get an instance of the Twig loaders
*
Expand Down

0 comments on commit b6f6297

Please sign in to comment.