PluginProbe
GetResponse Forms by Optin Cat / 1.4.1
GetResponse Forms by Optin Cat v1.4.1
1.3.4 1.3.5 1.3.6 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 2.0.0 All 36 releases
getresponse / includes / classes / Mustache / Engine.php

Engine.php in GetResponse Forms by Optin Cat 1.4.1, at includes/classes/Mustache/Engine.php

748 lines 21.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of Mustache.php.
5 *
6 * (c) 2010-2014 Justin Hileman
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 /**
13 * A Mustache implementation in PHP.
14 *
15 * {@link http://defunkt.github.com/mustache}
16 *
17 * Mustache is a framework-agnostic logic-less templating language. It enforces separation of view
18 * logic from template files. In fact, it is not even possible to embed logic in the template.
19 *
20 * This is very, very rad.
21 *
22 * @author Justin Hileman {@link http://justinhileman.com}
23 */
24 class Mustache_Engine
25 {
26 const VERSION = '2.6.1';
27 const SPEC_VERSION = '1.1.2';
28
29 const PRAGMA_FILTERS = 'FILTERS';
30
31 // Template cache
32 private $templates = array();
33
34 // Environment
35 private $templateClassPrefix = '__Mustache_';
36 private $cache;
37 private $lambdaCache;
38 private $cacheLambdaTemplates = false;
39 private $loader;
40 private $partialsLoader;
41 private $helpers;
42 private $escape;
43 private $entityFlags = ENT_COMPAT;
44 private $charset = 'UTF-8';
45 private $logger;
46 private $strictCallables = false;
47
48 // Services
49 private $tokenizer;
50 private $parser;
51 private $compiler;
52
53 /**
54 * Mustache class constructor.
55 *
56 * Passing an $options array allows overriding certain Mustache options during instantiation:
57 *
58 * $options = array(
59 * // The class prefix for compiled templates. Defaults to '__Mustache_'.
60 * 'template_class_prefix' => '__MyTemplates_',
61 *
62 * // A Mustache cache instance or a cache directory string for compiled templates.
63 * // Mustache will not cache templates unless this is set.
64 * 'cache' => dirname(__FILE__).'/tmp/cache/mustache',
65 *
66 * // Override default permissions for cache files. Defaults to using the system-defined umask. It is
67 * // *strongly* recommended that you configure your umask properly rather than overriding permissions here.
68 * 'cache_file_mode' => 0666,
69 *
70 * // Optionally, enable caching for lambda section templates. This is generally not recommended, as lambda
71 * // sections are often too dynamic to benefit from caching.
72 * 'cache_lambda_templates' => true,
73 *
74 * // A Mustache template loader instance. Uses a StringLoader if not specified.
75 * 'loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views'),
76 *
77 * // A Mustache loader instance for partials.
78 * 'partials_loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views/partials'),
79 *
80 * // An array of Mustache partials. Useful for quick-and-dirty string template loading, but not as
81 * // efficient or lazy as a Filesystem (or database) loader.
82 * 'partials' => array('foo' => file_get_contents(dirname(__FILE__).'/views/partials/foo.mustache')),
83 *
84 * // An array of 'helpers'. Helpers can be global variables or objects, closures (e.g. for higher order
85 * // sections), or any other valid Mustache context value. They will be prepended to the context stack,
86 * // so they will be available in any template loaded by this Mustache instance.
87 * 'helpers' => array('i18n' => function ($text) {
88 * // do something translatey here...
89 * }),
90 *
91 * // An 'escape' callback, responsible for escaping double-mustache variables.
92 * 'escape' => function ($value) {
93 * return htmlspecialchars($buffer, ENT_COMPAT, 'UTF-8');
94 * },
95 *
96 * // Type argument for `htmlspecialchars`. Defaults to ENT_COMPAT. You may prefer ENT_QUOTES.
97 * 'entity_flags' => ENT_QUOTES,
98 *
99 * // Character set for `htmlspecialchars`. Defaults to 'UTF-8'. Use 'UTF-8'.
100 * 'charset' => 'ISO-8859-1',
101 *
102 * // A Mustache Logger instance. No logging will occur unless this is set. Using a PSR-3 compatible
103 * // logging library -- such as Monolog -- is highly recommended. A simple stream logger implementation is
104 * // available as well:
105 * 'logger' => new Mustache_Logger_StreamLogger('php://stderr'),
106 *
107 * // Only treat Closure instances and invokable classes as callable. If true, values like
108 * // `array('ClassName', 'methodName')` and `array($classInstance, 'methodName')`, which are traditionally
109 * // "callable" in PHP, are not called to resolve variables for interpolation or section contexts. This
110 * // helps protect against arbitrary code execution when user input is passed directly into the template.
111 * // This currently defaults to false, but will default to true in v3.0.
112 * 'strict_callables' => true,
113 * );
114 *
115 * @throws Mustache_Exception_InvalidArgumentException If `escape` option is not callable.
116 *
117 * @param array $options (default: array())
118 */
119 public function __construct(array $options = array())
120 {
121 if (isset($options['template_class_prefix'])) {
122 $this->templateClassPrefix = $options['template_class_prefix'];
123 }
124
125 if (isset($options['cache'])) {
126 $cache = $options['cache'];
127
128 if (is_string($cache)) {
129 $mode = isset($options['cache_file_mode']) ? $options['cache_file_mode'] : null;
130 $cache = new Mustache_Cache_FilesystemCache($cache, $mode);
131 }
132
133 $this->setCache($cache);
134 }
135
136 if (isset($options['cache_lambda_templates'])) {
137 $this->cacheLambdaTemplates = (bool) $options['cache_lambda_templates'];
138 }
139
140 if (isset($options['loader'])) {
141 $this->setLoader($options['loader']);
142 }
143
144 if (isset($options['partials_loader'])) {
145 $this->setPartialsLoader($options['partials_loader']);
146 }
147
148 if (isset($options['partials'])) {
149 $this->setPartials($options['partials']);
150 }
151
152 if (isset($options['helpers'])) {
153 $this->setHelpers($options['helpers']);
154 }
155
156 if (isset($options['escape'])) {
157 if (!is_callable($options['escape'])) {
158 throw new Mustache_Exception_InvalidArgumentException('Mustache Constructor "escape" option must be callable');
159 }
160
161 $this->escape = $options['escape'];
162 }
163
164 if (isset($options['entity_flags'])) {
165 $this->entityFlags = $options['entity_flags'];
166 }
167
168 if (isset($options['charset'])) {
169 $this->charset = $options['charset'];
170 }
171
172 if (isset($options['logger'])) {
173 $this->setLogger($options['logger']);
174 }
175
176 if (isset($options['strict_callables'])) {
177 $this->strictCallables = $options['strict_callables'];
178 }
179 }
180
181 /**
182 * Shortcut 'render' invocation.
183 *
184 * Equivalent to calling `$mustache->loadTemplate($template)->render($context);`
185 *
186 * @see Mustache_Engine::loadTemplate
187 * @see Mustache_Template::render
188 *
189 * @param string $template
190 * @param mixed $context (default: array())
191 *
192 * @return string Rendered template
193 */
194 public function render($template, $context = array())
195 {
196 return $this->loadTemplate($template)->render($context);
197 }
198
199 /**
200 * Get the current Mustache escape callback.
201 *
202 * @return callable|null
203 */
204 public function getEscape()
205 {
206 return $this->escape;
207 }
208
209 /**
210 * Get the current Mustache entitity type to escape.
211 *
212 * @return int
213 */
214 public function getEntityFlags()
215 {
216 return $this->entityFlags;
217 }
218
219 /**
220 * Get the current Mustache character set.
221 *
222 * @return string
223 */
224 public function getCharset()
225 {
226 return $this->charset;
227 }
228
229 /**
230 * Set the Mustache template Loader instance.
231 *
232 * @param Mustache_Loader $loader
233 */
234 public function setLoader(Mustache_Loader $loader)
235 {
236 $this->loader = $loader;
237 }
238
239 /**
240 * Get the current Mustache template Loader instance.
241 *
242 * If no Loader instance has been explicitly specified, this method will instantiate and return
243 * a StringLoader instance.
244 *
245 * @return Mustache_Loader
246 */
247 public function getLoader()
248 {
249 if (!isset($this->loader)) {
250 $this->loader = new Mustache_Loader_StringLoader;
251 }
252
253 return $this->loader;
254 }
255
256 /**
257 * Set the Mustache partials Loader instance.
258 *
259 * @param Mustache_Loader $partialsLoader
260 */
261 public function setPartialsLoader(Mustache_Loader $partialsLoader)
262 {
263 $this->partialsLoader = $partialsLoader;
264 }
265
266 /**
267 * Get the current Mustache partials Loader instance.
268 *
269 * If no Loader instance has been explicitly specified, this method will instantiate and return
270 * an ArrayLoader instance.
271 *
272 * @return Mustache_Loader
273 */
274 public function getPartialsLoader()
275 {
276 if (!isset($this->partialsLoader)) {
277 $this->partialsLoader = new Mustache_Loader_ArrayLoader;
278 }
279
280 return $this->partialsLoader;
281 }
282
283 /**
284 * Set partials for the current partials Loader instance.
285 *
286 * @throws Mustache_Exception_RuntimeException If the current Loader instance is immutable
287 *
288 * @param array $partials (default: array())
289 */
290 public function setPartials(array $partials = array())
291 {
292 if (!isset($this->partialsLoader)) {
293 $this->partialsLoader = new Mustache_Loader_ArrayLoader;
294 }
295
296 if (!$this->partialsLoader instanceof Mustache_Loader_MutableLoader) {
297 throw new Mustache_Exception_RuntimeException('Unable to set partials on an immutable Mustache Loader instance');
298 }
299
300 $this->partialsLoader->setTemplates($partials);
301 }
302
303 /**
304 * Set an array of Mustache helpers.
305 *
306 * An array of 'helpers'. Helpers can be global variables or objects, closures (e.g. for higher order sections), or
307 * any other valid Mustache context value. They will be prepended to the context stack, so they will be available in
308 * any template loaded by this Mustache instance.
309 *
310 * @throws Mustache_Exception_InvalidArgumentException if $helpers is not an array or Traversable
311 *
312 * @param array|Traversable $helpers
313 */
314 public function setHelpers($helpers)
315 {
316 if (!is_array($helpers) && !$helpers instanceof Traversable) {
317 throw new Mustache_Exception_InvalidArgumentException('setHelpers expects an array of helpers');
318 }
319
320 $this->getHelpers()->clear();
321
322 foreach ($helpers as $name => $helper) {
323 $this->addHelper($name, $helper);
324 }
325 }
326
327 /**
328 * Get the current set of Mustache helpers.
329 *
330 * @see Mustache_Engine::setHelpers
331 *
332 * @return Mustache_HelperCollection
333 */
334 public function getHelpers()
335 {
336 if (!isset($this->helpers)) {
337 $this->helpers = new Mustache_HelperCollection;
338 }
339
340 return $this->helpers;
341 }
342
343 /**
344 * Add a new Mustache helper.
345 *
346 * @see Mustache_Engine::setHelpers
347 *
348 * @param string $name
349 * @param mixed $helper
350 */
351 public function addHelper($name, $helper)
352 {
353 $this->getHelpers()->add($name, $helper);
354 }
355
356 /**
357 * Get a Mustache helper by name.
358 *
359 * @see Mustache_Engine::setHelpers
360 *
361 * @param string $name
362 *
363 * @return mixed Helper
364 */
365 public function getHelper($name)
366 {
367 return $this->getHelpers()->get($name);
368 }
369
370 /**
371 * Check whether this Mustache instance has a helper.
372 *
373 * @see Mustache_Engine::setHelpers
374 *
375 * @param string $name
376 *
377 * @return boolean True if the helper is present
378 */
379 public function hasHelper($name)
380 {
381 return $this->getHelpers()->has($name);
382 }
383
384 /**
385 * Remove a helper by name.
386 *
387 * @see Mustache_Engine::setHelpers
388 *
389 * @param string $name
390 */
391 public function removeHelper($name)
392 {
393 $this->getHelpers()->remove($name);
394 }
395
396 /**
397 * Set the Mustache Logger instance.
398 *
399 * @throws Mustache_Exception_InvalidArgumentException If logger is not an instance of Mustache_Logger or Psr\Log\LoggerInterface.
400 *
401 * @param Mustache_Logger|Psr\Log\LoggerInterface $logger
402 */
403 public function setLogger($logger = null)
404 {
405 if ($logger !== null && !($logger instanceof Mustache_Logger || is_a($logger, 'Psr\\Log\\LoggerInterface'))) {
406 throw new Mustache_Exception_InvalidArgumentException('Expected an instance of Mustache_Logger or Psr\\Log\\LoggerInterface.');
407 }
408
409 if ($this->getCache()->getLogger() === null) {
410 $this->getCache()->setLogger($logger);
411 }
412
413 $this->logger = $logger;
414 }
415
416 /**
417 * Get the current Mustache Logger instance.
418 *
419 * @return Mustache_Logger|Psr\Log\LoggerInterface
420 */
421 public function getLogger()
422 {
423 return $this->logger;
424 }
425
426 /**
427 * Set the Mustache Tokenizer instance.
428 *
429 * @param Mustache_Tokenizer $tokenizer
430 */
431 public function setTokenizer(Mustache_Tokenizer $tokenizer)
432 {
433 $this->tokenizer = $tokenizer;
434 }
435
436 /**
437 * Get the current Mustache Tokenizer instance.
438 *
439 * If no Tokenizer instance has been explicitly specified, this method will instantiate and return a new one.
440 *
441 * @return Mustache_Tokenizer
442 */
443 public function getTokenizer()
444 {
445 if (!isset($this->tokenizer)) {
446 $this->tokenizer = new Mustache_Tokenizer;
447 }
448
449 return $this->tokenizer;
450 }
451
452 /**
453 * Set the Mustache Parser instance.
454 *
455 * @param Mustache_Parser $parser
456 */
457 public function setParser(Mustache_Parser $parser)
458 {
459 $this->parser = $parser;
460 }
461
462 /**
463 * Get the current Mustache Parser instance.
464 *
465 * If no Parser instance has been explicitly specified, this method will instantiate and return a new one.
466 *
467 * @return Mustache_Parser
468 */
469 public function getParser()
470 {
471 if (!isset($this->parser)) {
472 $this->parser = new Mustache_Parser;
473 }
474
475 return $this->parser;
476 }
477
478 /**
479 * Set the Mustache Compiler instance.
480 *
481 * @param Mustache_Compiler $compiler
482 */
483 public function setCompiler(Mustache_Compiler $compiler)
484 {
485 $this->compiler = $compiler;
486 }
487
488 /**
489 * Get the current Mustache Compiler instance.
490 *
491 * If no Compiler instance has been explicitly specified, this method will instantiate and return a new one.
492 *
493 * @return Mustache_Compiler
494 */
495 public function getCompiler()
496 {
497 if (!isset($this->compiler)) {
498 $this->compiler = new Mustache_Compiler;
499 }
500
501 return $this->compiler;
502 }
503
504 /**
505 * Set the Mustache Cache instance.
506 *
507 * @param Mustache_Cache $cache
508 */
509 public function setCache(Mustache_Cache $cache)
510 {
511 if (isset($this->logger) && $cache->getLogger() === null) {
512 $cache->setLogger($this->getLogger());
513 }
514
515 $this->cache = $cache;
516 }
517
518 /**
519 * Get the current Mustache Cache instance.
520 *
521 * If no Cache instance has been explicitly specified, this method will instantiate and return a new one.
522 *
523 * @return Mustache_Cache
524 */
525 public function getCache()
526 {
527 if (!isset($this->cache)) {
528 $this->setCache(new Mustache_Cache_NoopCache());
529 }
530
531 return $this->cache;
532 }
533
534 /**
535 * Get the current Lambda Cache instance.
536 *
537 * If 'cache_lambda_templates' is enabled, this is the default cache instance. Otherwise, it is a NoopCache.
538 *
539 * @see Mustache_Engine::getCache
540 *
541 * @return Mustache_Cache
542 */
543 protected function getLambdaCache()
544 {
545 if ($this->cacheLambdaTemplates) {
546 return $this->getCache();
547 }
548
549 if (!isset($this->lambdaCache)) {
550 $this->lambdaCache = new Mustache_Cache_NoopCache();
551 }
552
553 return $this->lambdaCache;
554 }
555
556 /**
557 * Helper method to generate a Mustache template class.
558 *
559 * @param string $source
560 *
561 * @return string Mustache Template class name
562 */
563 public function getTemplateClassName($source)
564 {
565 return $this->templateClassPrefix . md5(sprintf(
566 'version:%s,escape:%s,entity_flags:%i,charset:%s,strict_callables:%s,source:%s',
567 self::VERSION,
568 isset($this->escape) ? 'custom' : 'default',
569 $this->entityFlags,
570 $this->charset,
571 $this->strictCallables ? 'true' : 'false',
572 $source
573 ));
574 }
575
576 /**
577 * Load a Mustache Template by name.
578 *
579 * @param string $name
580 *
581 * @return Mustache_Template
582 */
583 public function loadTemplate($name)
584 {
585 return $this->loadSource($this->getLoader()->load($name));
586 }
587
588 /**
589 * Load a Mustache partial Template by name.
590 *
591 * This is a helper method used internally by Template instances for loading partial templates. You can most likely
592 * ignore it completely.
593 *
594 * @param string $name
595 *
596 * @return Mustache_Template
597 */
598 public function loadPartial($name)
599 {
600 try {
601 if (isset($this->partialsLoader)) {
602 $loader = $this->partialsLoader;
603 } elseif (isset($this->loader) && !$this->loader instanceof Mustache_Loader_StringLoader) {
604 $loader = $this->loader;
605 } else {
606 throw new Mustache_Exception_UnknownTemplateException($name);
607 }
608
609 return $this->loadSource($loader->load($name));
610 } catch (Mustache_Exception_UnknownTemplateException $e) {
611 // If the named partial cannot be found, log then return null.
612 $this->log(
613 Mustache_Logger::WARNING,
614 'Partial not found: "{name}"',
615 array('name' => $e->getTemplateName())
616 );
617 }
618 }
619
620 /**
621 * Load a Mustache lambda Template by source.
622 *
623 * This is a helper method used by Template instances to generate subtemplates for Lambda sections. You can most
624 * likely ignore it completely.
625 *
626 * @param string $source
627 * @param string $delims (default: null)
628 *
629 * @return Mustache_Template
630 */
631 public function loadLambda($source, $delims = null)
632 {
633 if ($delims !== null) {
634 $source = $delims . "\n" . $source;
635 }
636
637 return $this->loadSource($source, $this->getLambdaCache());
638 }
639
640 /**
641 * Instantiate and return a Mustache Template instance by source.
642 *
643 * Optionally provide a Mustache_Cache instance. This is used internally by Mustache_Engine::loadLambda to respect
644 * the 'cache_lambda_templates' configuration option.
645 *
646 * @see Mustache_Engine::loadTemplate
647 * @see Mustache_Engine::loadPartial
648 * @see Mustache_Engine::loadLambda
649 *
650 * @param string $source
651 * @param Mustache_Cache $cache (default: null)
652 *
653 * @return Mustache_Template
654 */
655 private function loadSource($source, Mustache_Cache $cache = null)
656 {
657 $className = $this->getTemplateClassName($source);
658
659 if (!isset($this->templates[$className])) {
660 if ($cache === null) {
661 $cache = $this->getCache();
662 }
663
664 if (!class_exists($className, false)) {
665 if (!$cache->load($className)) {
666 $compiled = $this->compile($source);
667 $cache->cache($className, $compiled);
668 }
669 }
670
671 $this->log(
672 Mustache_Logger::DEBUG,
673 'Instantiating template: "{className}"',
674 array('className' => $className)
675 );
676
677 $this->templates[$className] = new $className($this);
678 }
679
680 return $this->templates[$className];
681 }
682
683 /**
684 * Helper method to tokenize a Mustache template.
685 *
686 * @see Mustache_Tokenizer::scan
687 *
688 * @param string $source
689 *
690 * @return array Tokens
691 */
692 private function tokenize($source)
693 {
694 return $this->getTokenizer()->scan($source);
695 }
696
697 /**
698 * Helper method to parse a Mustache template.
699 *
700 * @see Mustache_Parser::parse
701 *
702 * @param string $source
703 *
704 * @return array Token tree
705 */
706 private function parse($source)
707 {
708 return $this->getParser()->parse($this->tokenize($source));
709 }
710
711 /**
712 * Helper method to compile a Mustache template.
713 *
714 * @see Mustache_Compiler::compile
715 *
716 * @param string $source
717 *
718 * @return string generated Mustache template class code
719 */
720 private function compile($source)
721 {
722 $tree = $this->parse($source);
723 $name = $this->getTemplateClassName($source);
724
725 $this->log(
726 Mustache_Logger::INFO,
727 'Compiling template to "{className}" class',
728 array('className' => $name)
729 );
730
731 return $this->getCompiler()->compile($source, $tree, $name, isset($this->escape), $this->charset, $this->strictCallables, $this->entityFlags);
732 }
733
734 /**
735 * Add a log record if logging is enabled.
736 *
737 * @param integer $level The logging level
738 * @param string $message The log message
739 * @param array $context The log context
740 */
741 private function log($level, $message, array $context = array())
742 {
743 if (isset($this->logger)) {
744 $this->logger->log($level, $message, $context);
745 }
746 }
747 }
748