Skip to content

Custom Twig Extensions #49

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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