1*04fd306cSNickeau<?php 2*04fd306cSNickeau/** 3*04fd306cSNickeau * Handlebars 4*04fd306cSNickeau * 5*04fd306cSNickeau * @category Xamin 6*04fd306cSNickeau * @package Handlebars 7*04fd306cSNickeau * @author fzerorubigd <fzerorubigd@gmail.com> 8*04fd306cSNickeau * @author Behrooz Shabani <everplays@gmail.com> 9*04fd306cSNickeau * @author Mardix <https://github.com/mardix> 10*04fd306cSNickeau * @copyright 2012 (c) ParsPooyesh Co 11*04fd306cSNickeau * @copyright 2013 (c) Behrooz Shabani 12*04fd306cSNickeau * @copyright 2014 (c) Mardix 13*04fd306cSNickeau * @license MIT 14*04fd306cSNickeau * @link http://voodoophp.org/docs/handlebars 15*04fd306cSNickeau */ 16*04fd306cSNickeau 17*04fd306cSNickeaunamespace Handlebars; 18*04fd306cSNickeauuse Handlebars\Loader\StringLoader; 19*04fd306cSNickeauuse Handlebars\Cache\Dummy; 20*04fd306cSNickeauuse InvalidArgumentException; 21*04fd306cSNickeau 22*04fd306cSNickeau 23*04fd306cSNickeauclass Handlebars 24*04fd306cSNickeau{ 25*04fd306cSNickeau private static $instance = null; 26*04fd306cSNickeau const VERSION = '2.2'; 27*04fd306cSNickeau 28*04fd306cSNickeau const OPTION_ENABLE_DATA_VARIABLES = 'enableDataVariables'; 29*04fd306cSNickeau 30*04fd306cSNickeau /** 31*04fd306cSNickeau * factory method 32*04fd306cSNickeau * 33*04fd306cSNickeau * @param array $options see __construct's options parameter 34*04fd306cSNickeau * 35*04fd306cSNickeau * @return Handlebars 36*04fd306cSNickeau */ 37*04fd306cSNickeau public static function factory($options = array()) 38*04fd306cSNickeau { 39*04fd306cSNickeau if (! self::$instance) { 40*04fd306cSNickeau self::$instance = new self($options); 41*04fd306cSNickeau } 42*04fd306cSNickeau 43*04fd306cSNickeau return self::$instance; 44*04fd306cSNickeau } 45*04fd306cSNickeau 46*04fd306cSNickeau /** 47*04fd306cSNickeau * @var Tokenizer 48*04fd306cSNickeau */ 49*04fd306cSNickeau private $tokenizer; 50*04fd306cSNickeau 51*04fd306cSNickeau /** 52*04fd306cSNickeau * @var Parser 53*04fd306cSNickeau */ 54*04fd306cSNickeau private $parser; 55*04fd306cSNickeau 56*04fd306cSNickeau /** 57*04fd306cSNickeau * @var Helpers 58*04fd306cSNickeau */ 59*04fd306cSNickeau private $helpers; 60*04fd306cSNickeau 61*04fd306cSNickeau /** 62*04fd306cSNickeau * @var Loader 63*04fd306cSNickeau */ 64*04fd306cSNickeau private $loader; 65*04fd306cSNickeau 66*04fd306cSNickeau /** 67*04fd306cSNickeau * @var Loader 68*04fd306cSNickeau */ 69*04fd306cSNickeau private $partialsLoader; 70*04fd306cSNickeau 71*04fd306cSNickeau /** 72*04fd306cSNickeau * @var Cache 73*04fd306cSNickeau */ 74*04fd306cSNickeau private $cache; 75*04fd306cSNickeau 76*04fd306cSNickeau /** 77*04fd306cSNickeau * @var callable escape function to use 78*04fd306cSNickeau */ 79*04fd306cSNickeau private $escape = 'htmlspecialchars'; 80*04fd306cSNickeau 81*04fd306cSNickeau /** 82*04fd306cSNickeau * @var array parametes to pass to escape function 83*04fd306cSNickeau */ 84*04fd306cSNickeau private $escapeArgs = array( 85*04fd306cSNickeau ENT_COMPAT, 86*04fd306cSNickeau 'UTF-8' 87*04fd306cSNickeau ); 88*04fd306cSNickeau 89*04fd306cSNickeau private $aliases = array(); 90*04fd306cSNickeau 91*04fd306cSNickeau /** 92*04fd306cSNickeau * @var bool Enable @data variables 93*04fd306cSNickeau */ 94*04fd306cSNickeau private $enableDataVariables = false; 95*04fd306cSNickeau 96*04fd306cSNickeau /** 97*04fd306cSNickeau * Handlebars engine constructor 98*04fd306cSNickeau * $options array can contain : 99*04fd306cSNickeau * helpers => Helpers object 100*04fd306cSNickeau * escape => a callable function to escape values 101*04fd306cSNickeau * escapeArgs => array to pass as extra parameter to escape function 102*04fd306cSNickeau * loader => Loader object 103*04fd306cSNickeau * partials_loader => Loader object 104*04fd306cSNickeau * cache => Cache object 105*04fd306cSNickeau * enableDataVariables => boolean. Enables @data variables (default: false) 106*04fd306cSNickeau * 107*04fd306cSNickeau * @param array $options array of options to set 108*04fd306cSNickeau * 109*04fd306cSNickeau * @throws \InvalidArgumentException 110*04fd306cSNickeau */ 111*04fd306cSNickeau public function __construct(Array $options = []) 112*04fd306cSNickeau { 113*04fd306cSNickeau if (isset($options['helpers'])) { 114*04fd306cSNickeau $this->setHelpers($options['helpers']); 115*04fd306cSNickeau } 116*04fd306cSNickeau 117*04fd306cSNickeau if (isset($options['loader'])) { 118*04fd306cSNickeau $this->setLoader($options['loader']); 119*04fd306cSNickeau } 120*04fd306cSNickeau 121*04fd306cSNickeau if (isset($options['partials_loader'])) { 122*04fd306cSNickeau $this->setPartialsLoader($options['partials_loader']); 123*04fd306cSNickeau } 124*04fd306cSNickeau 125*04fd306cSNickeau if (isset($options['cache'])) { 126*04fd306cSNickeau $this->setCache($options['cache']); 127*04fd306cSNickeau } 128*04fd306cSNickeau 129*04fd306cSNickeau if (isset($options['escape'])) { 130*04fd306cSNickeau if (!is_callable($options['escape'])) { 131*04fd306cSNickeau throw new InvalidArgumentException( 132*04fd306cSNickeau 'Handlebars Constructor "escape" option must be callable' 133*04fd306cSNickeau ); 134*04fd306cSNickeau } 135*04fd306cSNickeau $this->escape = $options['escape']; 136*04fd306cSNickeau } 137*04fd306cSNickeau 138*04fd306cSNickeau if (isset($options['escapeArgs'])) { 139*04fd306cSNickeau if (!is_array($options['escapeArgs'])) { 140*04fd306cSNickeau $options['escapeArgs'] = array($options['escapeArgs']); 141*04fd306cSNickeau } 142*04fd306cSNickeau $this->escapeArgs = $options['escapeArgs']; 143*04fd306cSNickeau } 144*04fd306cSNickeau 145*04fd306cSNickeau if (isset($options['partials_alias']) 146*04fd306cSNickeau && is_array($options['partials_alias']) 147*04fd306cSNickeau ) { 148*04fd306cSNickeau $this->aliases = $options['partials_alias']; 149*04fd306cSNickeau } 150*04fd306cSNickeau 151*04fd306cSNickeau if (isset($options[self::OPTION_ENABLE_DATA_VARIABLES])) { 152*04fd306cSNickeau if (!is_bool($options[self::OPTION_ENABLE_DATA_VARIABLES])) { 153*04fd306cSNickeau throw new InvalidArgumentException( 154*04fd306cSNickeau 'Handlebars Constructor "' . self::OPTION_ENABLE_DATA_VARIABLES . '" option must be a boolean' 155*04fd306cSNickeau ); 156*04fd306cSNickeau } 157*04fd306cSNickeau $this->enableDataVariables = $options[self::OPTION_ENABLE_DATA_VARIABLES]; 158*04fd306cSNickeau } 159*04fd306cSNickeau } 160*04fd306cSNickeau 161*04fd306cSNickeau 162*04fd306cSNickeau 163*04fd306cSNickeau /** 164*04fd306cSNickeau * Shortcut 'render' invocation. 165*04fd306cSNickeau * 166*04fd306cSNickeau * Equivalent to calling `$handlebars->loadTemplate($template)->render($data);` 167*04fd306cSNickeau * 168*04fd306cSNickeau * @param string $template template name 169*04fd306cSNickeau * @param mixed $data data to use as context 170*04fd306cSNickeau * @return string Rendered template 171*04fd306cSNickeau */ 172*04fd306cSNickeau public function render($template, $data) 173*04fd306cSNickeau { 174*04fd306cSNickeau return $this->loadTemplate($template)->render($data); 175*04fd306cSNickeau } 176*04fd306cSNickeau /** 177*04fd306cSNickeau * To invoke when this object is called as a function 178*04fd306cSNickeau * 179*04fd306cSNickeau * @param string $template template name 180*04fd306cSNickeau * @param mixed $data data to use as context 181*04fd306cSNickeau * @return string Rendered template 182*04fd306cSNickeau */ 183*04fd306cSNickeau public function __invoke($template, $data) 184*04fd306cSNickeau { 185*04fd306cSNickeau return $this->render($template, $data); 186*04fd306cSNickeau } 187*04fd306cSNickeau 188*04fd306cSNickeau /** 189*04fd306cSNickeau * Set helpers for current enfine 190*04fd306cSNickeau * 191*04fd306cSNickeau * @param Helpers $helpers handlebars helper 192*04fd306cSNickeau * 193*04fd306cSNickeau * @return void 194*04fd306cSNickeau */ 195*04fd306cSNickeau public function setHelpers(Helpers $helpers) 196*04fd306cSNickeau { 197*04fd306cSNickeau $this->helpers = $helpers; 198*04fd306cSNickeau } 199*04fd306cSNickeau 200*04fd306cSNickeau /** 201*04fd306cSNickeau * Get helpers, or create new one if ther is no helper 202*04fd306cSNickeau * 203*04fd306cSNickeau * @return Helpers 204*04fd306cSNickeau */ 205*04fd306cSNickeau public function getHelpers() 206*04fd306cSNickeau { 207*04fd306cSNickeau if (!isset($this->helpers)) { 208*04fd306cSNickeau $this->helpers = new Helpers(); 209*04fd306cSNickeau } 210*04fd306cSNickeau return $this->helpers; 211*04fd306cSNickeau } 212*04fd306cSNickeau 213*04fd306cSNickeau /** 214*04fd306cSNickeau * Add a new helper. 215*04fd306cSNickeau * 216*04fd306cSNickeau * @param string $name helper name 217*04fd306cSNickeau * @param mixed $helper helper callable 218*04fd306cSNickeau * 219*04fd306cSNickeau * @return void 220*04fd306cSNickeau */ 221*04fd306cSNickeau public function addHelper($name, $helper) 222*04fd306cSNickeau { 223*04fd306cSNickeau $this->getHelpers()->add($name, $helper); 224*04fd306cSNickeau } 225*04fd306cSNickeau 226*04fd306cSNickeau /** 227*04fd306cSNickeau * Get a helper by name. 228*04fd306cSNickeau * 229*04fd306cSNickeau * @param string $name helper name 230*04fd306cSNickeau * @return callable Helper 231*04fd306cSNickeau */ 232*04fd306cSNickeau public function getHelper($name) 233*04fd306cSNickeau { 234*04fd306cSNickeau return $this->getHelpers()->__get($name); 235*04fd306cSNickeau } 236*04fd306cSNickeau 237*04fd306cSNickeau /** 238*04fd306cSNickeau * Check whether this instance has a helper. 239*04fd306cSNickeau * 240*04fd306cSNickeau * @param string $name helper name 241*04fd306cSNickeau * @return boolean True if the helper is present 242*04fd306cSNickeau */ 243*04fd306cSNickeau public function hasHelper($name) 244*04fd306cSNickeau { 245*04fd306cSNickeau return $this->getHelpers()->has($name); 246*04fd306cSNickeau } 247*04fd306cSNickeau 248*04fd306cSNickeau /** 249*04fd306cSNickeau * Remove a helper by name. 250*04fd306cSNickeau * 251*04fd306cSNickeau * @param string $name helper name 252*04fd306cSNickeau * @return void 253*04fd306cSNickeau */ 254*04fd306cSNickeau public function removeHelper($name) 255*04fd306cSNickeau { 256*04fd306cSNickeau $this->getHelpers()->remove($name); 257*04fd306cSNickeau } 258*04fd306cSNickeau 259*04fd306cSNickeau /** 260*04fd306cSNickeau * Set current loader 261*04fd306cSNickeau * 262*04fd306cSNickeau * @param Loader $loader handlebars loader 263*04fd306cSNickeau * @return void 264*04fd306cSNickeau */ 265*04fd306cSNickeau public function setLoader(Loader $loader) 266*04fd306cSNickeau { 267*04fd306cSNickeau $this->loader = $loader; 268*04fd306cSNickeau } 269*04fd306cSNickeau 270*04fd306cSNickeau /** 271*04fd306cSNickeau * get current loader 272*04fd306cSNickeau * 273*04fd306cSNickeau * @return Loader 274*04fd306cSNickeau */ 275*04fd306cSNickeau public function getLoader() 276*04fd306cSNickeau { 277*04fd306cSNickeau if (! isset($this->loader)) { 278*04fd306cSNickeau $this->loader = new StringLoader(); 279*04fd306cSNickeau } 280*04fd306cSNickeau return $this->loader; 281*04fd306cSNickeau } 282*04fd306cSNickeau 283*04fd306cSNickeau /** 284*04fd306cSNickeau * Set current partials loader 285*04fd306cSNickeau * 286*04fd306cSNickeau * @param Loader $loader handlebars loader 287*04fd306cSNickeau * @return void 288*04fd306cSNickeau */ 289*04fd306cSNickeau public function setPartialsLoader(Loader $loader) 290*04fd306cSNickeau { 291*04fd306cSNickeau $this->partialsLoader = $loader; 292*04fd306cSNickeau } 293*04fd306cSNickeau 294*04fd306cSNickeau /** 295*04fd306cSNickeau * get current partials loader 296*04fd306cSNickeau * 297*04fd306cSNickeau * @return Loader 298*04fd306cSNickeau */ 299*04fd306cSNickeau public function getPartialsLoader() 300*04fd306cSNickeau { 301*04fd306cSNickeau if (!isset($this->partialsLoader)) { 302*04fd306cSNickeau $this->partialsLoader = new StringLoader(); 303*04fd306cSNickeau } 304*04fd306cSNickeau return $this->partialsLoader; 305*04fd306cSNickeau } 306*04fd306cSNickeau 307*04fd306cSNickeau /** 308*04fd306cSNickeau * Set cache for current engine 309*04fd306cSNickeau * 310*04fd306cSNickeau * @param Cache $cache handlebars cache 311*04fd306cSNickeau * @return void 312*04fd306cSNickeau */ 313*04fd306cSNickeau public function setCache(Cache $cache) 314*04fd306cSNickeau { 315*04fd306cSNickeau $this->cache = $cache; 316*04fd306cSNickeau } 317*04fd306cSNickeau 318*04fd306cSNickeau /** 319*04fd306cSNickeau * Get cache 320*04fd306cSNickeau * 321*04fd306cSNickeau * @return Cache 322*04fd306cSNickeau */ 323*04fd306cSNickeau public function getCache() 324*04fd306cSNickeau { 325*04fd306cSNickeau if (!isset($this->cache)) { 326*04fd306cSNickeau $this->cache = new Dummy(); 327*04fd306cSNickeau } 328*04fd306cSNickeau return $this->cache; 329*04fd306cSNickeau } 330*04fd306cSNickeau 331*04fd306cSNickeau /** 332*04fd306cSNickeau * Get current escape function 333*04fd306cSNickeau * 334*04fd306cSNickeau * @return callable 335*04fd306cSNickeau */ 336*04fd306cSNickeau public function getEscape() 337*04fd306cSNickeau { 338*04fd306cSNickeau return $this->escape; 339*04fd306cSNickeau } 340*04fd306cSNickeau 341*04fd306cSNickeau /** 342*04fd306cSNickeau * Set current escape function 343*04fd306cSNickeau * 344*04fd306cSNickeau * @param callable $escape function 345*04fd306cSNickeau * @throws \InvalidArgumentException 346*04fd306cSNickeau * @return void 347*04fd306cSNickeau */ 348*04fd306cSNickeau public function setEscape($escape) 349*04fd306cSNickeau { 350*04fd306cSNickeau if (!is_callable($escape)) { 351*04fd306cSNickeau throw new InvalidArgumentException( 352*04fd306cSNickeau 'Escape function must be a callable' 353*04fd306cSNickeau ); 354*04fd306cSNickeau } 355*04fd306cSNickeau $this->escape = $escape; 356*04fd306cSNickeau } 357*04fd306cSNickeau 358*04fd306cSNickeau /** 359*04fd306cSNickeau * Get current escape function 360*04fd306cSNickeau * 361*04fd306cSNickeau * @return array 362*04fd306cSNickeau */ 363*04fd306cSNickeau public function getEscapeArgs() 364*04fd306cSNickeau { 365*04fd306cSNickeau return $this->escapeArgs; 366*04fd306cSNickeau } 367*04fd306cSNickeau 368*04fd306cSNickeau /** 369*04fd306cSNickeau * Set current escape function 370*04fd306cSNickeau * 371*04fd306cSNickeau * @param array $escapeArgs arguments to pass as extra arg to function 372*04fd306cSNickeau * @return void 373*04fd306cSNickeau */ 374*04fd306cSNickeau public function setEscapeArgs($escapeArgs) 375*04fd306cSNickeau { 376*04fd306cSNickeau if (! is_array($escapeArgs)) { 377*04fd306cSNickeau $escapeArgs = array($escapeArgs); 378*04fd306cSNickeau } 379*04fd306cSNickeau $this->escapeArgs = $escapeArgs; 380*04fd306cSNickeau } 381*04fd306cSNickeau 382*04fd306cSNickeau 383*04fd306cSNickeau /** 384*04fd306cSNickeau * Set the Handlebars Tokenizer instance. 385*04fd306cSNickeau * 386*04fd306cSNickeau * @param Tokenizer $tokenizer tokenizer 387*04fd306cSNickeau * @return void 388*04fd306cSNickeau */ 389*04fd306cSNickeau public function setTokenizer(Tokenizer $tokenizer) 390*04fd306cSNickeau { 391*04fd306cSNickeau $this->tokenizer = $tokenizer; 392*04fd306cSNickeau } 393*04fd306cSNickeau 394*04fd306cSNickeau /** 395*04fd306cSNickeau * Get the current Handlebars Tokenizer instance. 396*04fd306cSNickeau * 397*04fd306cSNickeau * If no Tokenizer instance has been explicitly specified, this method will 398*04fd306cSNickeau * instantiate and return a new one. 399*04fd306cSNickeau * 400*04fd306cSNickeau * @return Tokenizer 401*04fd306cSNickeau */ 402*04fd306cSNickeau public function getTokenizer() 403*04fd306cSNickeau { 404*04fd306cSNickeau if (! isset($this->tokenizer)) { 405*04fd306cSNickeau $this->tokenizer = new Tokenizer(); 406*04fd306cSNickeau } 407*04fd306cSNickeau 408*04fd306cSNickeau return $this->tokenizer; 409*04fd306cSNickeau } 410*04fd306cSNickeau 411*04fd306cSNickeau /** 412*04fd306cSNickeau * Set the Handlebars Parser instance. 413*04fd306cSNickeau * 414*04fd306cSNickeau * @param Parser $parser parser object 415*04fd306cSNickeau * @return void 416*04fd306cSNickeau */ 417*04fd306cSNickeau public function setParser(Parser $parser) 418*04fd306cSNickeau { 419*04fd306cSNickeau $this->parser = $parser; 420*04fd306cSNickeau } 421*04fd306cSNickeau 422*04fd306cSNickeau /** 423*04fd306cSNickeau * Get the current Handlebars Parser instance. 424*04fd306cSNickeau * 425*04fd306cSNickeau * If no Parser instance has been explicitly specified, this method will 426*04fd306cSNickeau * instantiate and return a new one. 427*04fd306cSNickeau * 428*04fd306cSNickeau * @return Parser 429*04fd306cSNickeau */ 430*04fd306cSNickeau public function getParser() 431*04fd306cSNickeau { 432*04fd306cSNickeau if (! isset($this->parser)) { 433*04fd306cSNickeau $this->parser = new Parser(); 434*04fd306cSNickeau } 435*04fd306cSNickeau return $this->parser; 436*04fd306cSNickeau } 437*04fd306cSNickeau 438*04fd306cSNickeau /** 439*04fd306cSNickeau * Determines if the @data variables are enabled. 440*04fd306cSNickeau * @return bool 441*04fd306cSNickeau */ 442*04fd306cSNickeau public function isDataVariablesEnabled() 443*04fd306cSNickeau { 444*04fd306cSNickeau return $this->enableDataVariables; 445*04fd306cSNickeau } 446*04fd306cSNickeau 447*04fd306cSNickeau /** 448*04fd306cSNickeau * Load a template by name with current template loader 449*04fd306cSNickeau * 450*04fd306cSNickeau * @param string $name template name 451*04fd306cSNickeau * 452*04fd306cSNickeau * @return Template 453*04fd306cSNickeau */ 454*04fd306cSNickeau public function loadTemplate($name) 455*04fd306cSNickeau { 456*04fd306cSNickeau $source = $this->getLoader()->load($name); 457*04fd306cSNickeau $tree = $this->tokenize($source); 458*04fd306cSNickeau return new Template($this, $tree, $source); 459*04fd306cSNickeau } 460*04fd306cSNickeau 461*04fd306cSNickeau /** 462*04fd306cSNickeau * Load a partial by name with current partial loader 463*04fd306cSNickeau * 464*04fd306cSNickeau * @param string $name partial name 465*04fd306cSNickeau * 466*04fd306cSNickeau * @return Template 467*04fd306cSNickeau */ 468*04fd306cSNickeau public function loadPartial($name) 469*04fd306cSNickeau { 470*04fd306cSNickeau if (isset($this->aliases[$name])) { 471*04fd306cSNickeau $name = $this->aliases[$name]; 472*04fd306cSNickeau } 473*04fd306cSNickeau $source = $this->getPartialsLoader()->load($name); 474*04fd306cSNickeau $tree = $this->tokenize($source); 475*04fd306cSNickeau return new Template($this, $tree, $source); 476*04fd306cSNickeau } 477*04fd306cSNickeau 478*04fd306cSNickeau /** 479*04fd306cSNickeau * Register partial alias 480*04fd306cSNickeau * 481*04fd306cSNickeau * @param string $alias Partial alias 482*04fd306cSNickeau * @param string $content The real value 483*04fd306cSNickeau * @return void 484*04fd306cSNickeau */ 485*04fd306cSNickeau public function registerPartial($alias, $content) 486*04fd306cSNickeau { 487*04fd306cSNickeau $this->aliases[$alias] = $content; 488*04fd306cSNickeau } 489*04fd306cSNickeau 490*04fd306cSNickeau /** 491*04fd306cSNickeau * Un-register partial alias 492*04fd306cSNickeau * 493*04fd306cSNickeau * @param string $alias Partial alias 494*04fd306cSNickeau * @return void 495*04fd306cSNickeau */ 496*04fd306cSNickeau public function unRegisterPartial($alias) 497*04fd306cSNickeau { 498*04fd306cSNickeau if (isset($this->aliases[$alias])) { 499*04fd306cSNickeau unset($this->aliases[$alias]); 500*04fd306cSNickeau } 501*04fd306cSNickeau } 502*04fd306cSNickeau 503*04fd306cSNickeau /** 504*04fd306cSNickeau * Load string into a template object 505*04fd306cSNickeau * 506*04fd306cSNickeau * @param string $source string to load 507*04fd306cSNickeau * @return Template 508*04fd306cSNickeau */ 509*04fd306cSNickeau public function loadString($source) 510*04fd306cSNickeau { 511*04fd306cSNickeau $tree = $this->tokenize($source); 512*04fd306cSNickeau return new Template($this, $tree, $source); 513*04fd306cSNickeau } 514*04fd306cSNickeau 515*04fd306cSNickeau /** 516*04fd306cSNickeau * try to tokenize source, or get them from cache if available 517*04fd306cSNickeau * 518*04fd306cSNickeau * @param string $source handlebars source code 519*04fd306cSNickeau * @return array handlebars parsed data into array 520*04fd306cSNickeau */ 521*04fd306cSNickeau private function tokenize($source) 522*04fd306cSNickeau { 523*04fd306cSNickeau $hash = md5(sprintf('version: %s, data : %s', self::VERSION, $source)); 524*04fd306cSNickeau $tree = $this->getCache()->get($hash); 525*04fd306cSNickeau if ($tree === false) { 526*04fd306cSNickeau $tokens = $this->getTokenizer()->scan($source); 527*04fd306cSNickeau $tree = $this->getParser()->parse($tokens); 528*04fd306cSNickeau $this->getCache()->set($hash, $tree); 529*04fd306cSNickeau } 530*04fd306cSNickeau return $tree; 531*04fd306cSNickeau } 532*04fd306cSNickeau 533*04fd306cSNickeau}