diff --git a/README.md b/README.md index 486659f..8a575dd 100644 --- a/README.md +++ b/README.md @@ -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 +

Testing: {{ testPlFunction('testing...') }}

+``` + +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`. diff --git a/src/PatternLab/PatternEngine/Twig/ExampleTwigExtension.php b/src/PatternLab/PatternEngine/Twig/ExampleTwigExtension.php new file mode 100644 index 0000000..09806fb --- /dev/null +++ b/src/PatternLab/PatternEngine/Twig/ExampleTwigExtension.php @@ -0,0 +1,93 @@ + 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 []; + } + +} diff --git a/src/PatternLab/PatternEngine/Twig/Loaders/FilesystemLoader.php b/src/PatternLab/PatternEngine/Twig/Loaders/FilesystemLoader.php index 38f99bd..d21577e 100644 --- a/src/PatternLab/PatternEngine/Twig/Loaders/FilesystemLoader.php +++ b/src/PatternLab/PatternEngine/Twig/Loaders/FilesystemLoader.php @@ -50,6 +50,7 @@ public function __construct($options = array()) { // customize Twig TwigUtil::setInstance($instance); + TwigUtil::loadCustomExtensions(); TwigUtil::loadFilters(); TwigUtil::loadFunctions(); TwigUtil::loadTags(); diff --git a/src/PatternLab/PatternEngine/Twig/Loaders/PatternLoader.php b/src/PatternLab/PatternEngine/Twig/Loaders/PatternLoader.php index fa2ce2f..456ca16 100644 --- a/src/PatternLab/PatternEngine/Twig/Loaders/PatternLoader.php +++ b/src/PatternLab/PatternEngine/Twig/Loaders/PatternLoader.php @@ -92,6 +92,7 @@ public function __construct($options = array()) { // customize Twig TwigUtil::setInstance($instance); + TwigUtil::loadCustomExtensions(); TwigUtil::loadFilters(); TwigUtil::loadFunctions(); TwigUtil::loadTags(); diff --git a/src/PatternLab/PatternEngine/Twig/Loaders/StringLoader.php b/src/PatternLab/PatternEngine/Twig/Loaders/StringLoader.php index e81c9b7..ff95698 100644 --- a/src/PatternLab/PatternEngine/Twig/Loaders/StringLoader.php +++ b/src/PatternLab/PatternEngine/Twig/Loaders/StringLoader.php @@ -56,6 +56,7 @@ public function __construct($options = array()) { // customize Twig TwigUtil::setInstance($instance); + TwigUtil::loadCustomExtensions(); TwigUtil::loadFilters(); TwigUtil::loadFunctions(); TwigUtil::loadTags(); diff --git a/src/PatternLab/PatternEngine/Twig/TwigUtil.php b/src/PatternLab/PatternEngine/Twig/TwigUtil.php index 64f97da..8d3995f 100644 --- a/src/PatternLab/PatternEngine/Twig/TwigUtil.php +++ b/src/PatternLab/PatternEngine/Twig/TwigUtil.php @@ -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 *