1<?php 2 3/* 4 * This file is part of the Assetic package, an OpenSky project. 5 * 6 * (c) 2010-2014 OpenSky Project Inc 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Assetic\Extension\Twig; 13 14use Assetic\Factory\Loader\FormulaLoaderInterface; 15use Assetic\Factory\Resource\ResourceInterface; 16use Psr\Log\LoggerInterface; 17 18/** 19 * Loads asset formulae from Twig templates. 20 * 21 * @author Kris Wallsmith <kris.wallsmith@gmail.com> 22 */ 23class TwigFormulaLoader implements FormulaLoaderInterface 24{ 25 private $twig; 26 private $logger; 27 28 public function __construct(\Twig_Environment $twig, LoggerInterface $logger = null) 29 { 30 $this->twig = $twig; 31 $this->logger = $logger; 32 } 33 34 public function load(ResourceInterface $resource) 35 { 36 try { 37 $tokens = $this->twig->tokenize(new \Twig_Source($resource->getContent(), (string) $resource)); 38 $nodes = $this->twig->parse($tokens); 39 } catch (\Exception $e) { 40 if ($this->logger) { 41 $this->logger->error(sprintf('The template "%s" contains an error: %s', $resource, $e->getMessage())); 42 } 43 44 return array(); 45 } 46 47 return $this->loadNode($nodes); 48 } 49 50 /** 51 * Loads assets from the supplied node. 52 * 53 * @param \Twig_Node $node 54 * 55 * @return array An array of asset formulae indexed by name 56 */ 57 private function loadNode(\Twig_Node $node) 58 { 59 $formulae = array(); 60 61 if ($node instanceof AsseticNode) { 62 $formulae[$node->getAttribute('name')] = array( 63 $node->getAttribute('inputs'), 64 $node->getAttribute('filters'), 65 array( 66 'output' => $node->getAttribute('asset')->getTargetPath(), 67 'name' => $node->getAttribute('name'), 68 'debug' => $node->getAttribute('debug'), 69 'combine' => $node->getAttribute('combine'), 70 'vars' => $node->getAttribute('vars'), 71 ), 72 ); 73 } elseif ($node instanceof AsseticFilterNode) { 74 $name = $node->getAttribute('name'); 75 76 $arguments = array(); 77 foreach ($node->getNode('arguments') as $argument) { 78 $arguments[] = eval('return '.$this->twig->compile($argument).';'); 79 } 80 81 $invoker = $this->twig->getExtension('Assetic\Extension\Twig\AsseticExtension')->getFilterInvoker($name); 82 83 $inputs = isset($arguments[0]) ? (array) $arguments[0] : array(); 84 $filters = $invoker->getFilters(); 85 $options = array_replace($invoker->getOptions(), isset($arguments[1]) ? $arguments[1] : array()); 86 87 if (!isset($options['name'])) { 88 $options['name'] = $invoker->getFactory()->generateAssetName($inputs, $filters, $options); 89 } 90 91 $formulae[$options['name']] = array($inputs, $filters, $options); 92 } 93 94 foreach ($node as $child) { 95 if ($child instanceof \Twig_Node) { 96 $formulae += $this->loadNode($child); 97 } 98 } 99 100 if ($node->hasAttribute('embedded_templates')) { 101 foreach ($node->getAttribute('embedded_templates') as $child) { 102 $formulae += $this->loadNode($child); 103 } 104 } 105 106 return $formulae; 107 } 108} 109