Packages

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • None
  • PHP

Classes

  • NFileTemplate
  • NTemplate
  • NTemplateHelpers

Interfaces

  • IFileTemplate
  • ITemplate

Exceptions

  • NTemplateException
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  *
  6:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  * @package Nette\Templating
 11:  */
 12: 
 13: 
 14: 
 15: /**
 16:  * Template.
 17:  *
 18:  * @author     David Grudl
 19:  * @package Nette\Templating
 20:  */
 21: class NTemplate extends NObject implements ITemplate
 22: {
 23:     /** @var array of function(Template $sender); Occurs before a template is compiled - implement to customize the filters */
 24:     public $onPrepareFilters = array();
 25: 
 26:     /** @var string */
 27:     private $source;
 28: 
 29:     /** @var array */
 30:     private $params = array();
 31: 
 32:     /** @var array compile-time filters */
 33:     private $filters = array();
 34: 
 35:     /** @var array run-time helpers */
 36:     private $helpers = array();
 37: 
 38:     /** @var array */
 39:     private $helperLoaders = array();
 40: 
 41:     /** @var ICacheStorage */
 42:     private $cacheStorage;
 43: 
 44: 
 45: 
 46:     /**
 47:      * Sets template source code.
 48:      * @param  string
 49:      * @return NTemplate  provides a fluent interface
 50:      */
 51:     public function setSource($source)
 52:     {
 53:         $this->source = $source;
 54:         return $this;
 55:     }
 56: 
 57: 
 58: 
 59:     /**
 60:      * Returns template source code.
 61:      * @return source
 62:      */
 63:     public function getSource()
 64:     {
 65:         return $this->source;
 66:     }
 67: 
 68: 
 69: 
 70:     /********************* rendering ****************d*g**/
 71: 
 72: 
 73: 
 74:     /**
 75:      * Renders template to output.
 76:      * @return void
 77:      */
 78:     public function render()
 79:     {
 80:         $cache = new NCache($storage = $this->getCacheStorage(), 'Nette.Template');
 81:         $cached = $compiled = $cache->load($this->source);
 82: 
 83:         if ($compiled === NULL) {
 84:             $compiled = $this->compile();
 85:             $cache->save($this->source, $compiled, array(NCache::CONSTS => 'NFramework::REVISION'));
 86:             $cached = $cache->load($this->source);
 87:         }
 88: 
 89:         if ($cached !== NULL && $storage instanceof NPhpFileStorage) {
 90:             NLimitedScope::load($cached['file'], $this->getParameters());
 91:         } else {
 92:             NLimitedScope::evaluate($compiled, $this->getParameters());
 93:         }
 94:     }
 95: 
 96: 
 97: 
 98:     /**
 99:      * Renders template to file.
100:      * @param  string
101:      * @return void
102:      */
103:     public function save($file)
104:     {
105:         if (file_put_contents($file, $this->__toString(TRUE)) === FALSE) {
106:             throw new IOException("Unable to save file '$file'.");
107:         }
108:     }
109: 
110: 
111: 
112:     /**
113:      * Renders template to string.
114:      * @param  bool  can throw exceptions? (hidden parameter)
115:      * @return string
116:      */
117:     public function __toString()
118:     {
119:         $args = func_get_args();
120:         ob_start();
121:         try {
122:             $this->render();
123:             return ob_get_clean();
124: 
125:         } catch (Exception $e) {
126:             ob_end_clean();
127:             if ($args && $args[0]) {
128:                 throw $e;
129:             } else {
130:                 trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
131:             }
132:         }
133:     }
134: 
135: 
136: 
137:     /**
138:      * Applies filters on template content.
139:      * @return string
140:      */
141:     public function compile()
142:     {
143:         if (!$this->filters) {
144:             $this->onPrepareFilters($this);
145:         }
146: 
147:         $code = $this->getSource();
148:         foreach ($this->filters as $filter) {
149:             $code = self::extractPhp($code, $blocks);
150:             $code = $filter->invoke($code);
151:             $code = strtr($code, $blocks); // put PHP code back
152:         }
153: 
154:         return NTemplateHelpers::optimizePhp($code);
155:     }
156: 
157: 
158: 
159:     /********************* template filters & helpers ****************d*g**/
160: 
161: 
162: 
163:     /**
164:      * Registers callback as template compile-time filter.
165:      * @param  callable
166:      * @return NTemplate  provides a fluent interface
167:      */
168:     public function registerFilter($callback)
169:     {
170:         $callback = new NCallback($callback);
171:         if (in_array($callback, $this->filters)) {
172:             throw new InvalidStateException("Filter '$callback' was registered twice.");
173:         }
174:         $this->filters[] = $callback;
175:         return $this;
176:     }
177: 
178: 
179: 
180:     /**
181:      * Returns all registered compile-time filters.
182:      * @return array
183:      */
184:     final public function getFilters()
185:     {
186:         return $this->filters;
187:     }
188: 
189: 
190: 
191:     /**
192:      * Registers callback as template run-time helper.
193:      * @param  string
194:      * @param  callable
195:      * @return NTemplate  provides a fluent interface
196:      */
197:     public function registerHelper($name, $callback)
198:     {
199:         $this->helpers[strtolower($name)] = new NCallback($callback);
200:         return $this;
201:     }
202: 
203: 
204: 
205:     /**
206:      * Registers callback as template run-time helpers loader.
207:      * @param  callable
208:      * @return NTemplate  provides a fluent interface
209:      */
210:     public function registerHelperLoader($callback)
211:     {
212:         $this->helperLoaders[] = new NCallback($callback);
213:         return $this;
214:     }
215: 
216: 
217: 
218:     /**
219:      * Returns all registered run-time helpers.
220:      * @return array
221:      */
222:     final public function getHelpers()
223:     {
224:         return $this->helpers;
225:     }
226: 
227: 
228: 
229:     /**
230:      * Returns all registered template run-time helper loaders.
231:      * @return array
232:      */
233:     final public function getHelperLoaders()
234:     {
235:         return $this->helperLoaders;
236:     }
237: 
238: 
239: 
240:     /**
241:      * Call a template run-time helper. Do not call directly.
242:      * @param  string  helper name
243:      * @param  array   arguments
244:      * @return mixed
245:      */
246:     public function __call($name, $args)
247:     {
248:         $lname = strtolower($name);
249:         if (!isset($this->helpers[$lname])) {
250:             foreach ($this->helperLoaders as $loader) {
251:                 $helper = $loader->invoke($lname);
252:                 if ($helper) {
253:                     $this->registerHelper($lname, $helper);
254:                     return $this->helpers[$lname]->invokeArgs($args);
255:                 }
256:             }
257:             return parent::__call($name, $args);
258:         }
259: 
260:         return $this->helpers[$lname]->invokeArgs($args);
261:     }
262: 
263: 
264: 
265:     /**
266:      * Sets translate adapter.
267:      * @return NTemplate  provides a fluent interface
268:      */
269:     public function setTranslator(ITranslator $translator = NULL)
270:     {
271:         $this->registerHelper('translate', $translator === NULL ? NULL : array($translator, 'translate'));
272:         return $this;
273:     }
274: 
275: 
276: 
277:     /********************* template parameters ****************d*g**/
278: 
279: 
280: 
281:     /**
282:      * Adds new template parameter.
283:      * @param  string  name
284:      * @param  mixed   value
285:      * @return NTemplate  provides a fluent interface
286:      */
287:     public function add($name, $value)
288:     {
289:         if (array_key_exists($name, $this->params)) {
290:             throw new InvalidStateException("The variable '$name' already exists.");
291:         }
292: 
293:         $this->params[$name] = $value;
294:         return $this;
295:     }
296: 
297: 
298: 
299:     /**
300:      * Sets all parameters.
301:      * @param  array
302:      * @return NTemplate  provides a fluent interface
303:      */
304:     public function setParameters(array $params)
305:     {
306:         $this->params = $params + $this->params;
307:         return $this;
308:     }
309: 
310: 
311: 
312:     /**
313:      * Returns array of all parameters.
314:      * @return array
315:      */
316:     public function getParameters()
317:     {
318:         $this->params['template'] = $this;
319:         return $this->params;
320:     }
321: 
322: 
323: 
324:     /** @deprecated */
325:     function setParams(array $params)
326:     {
327:         trigger_error(__METHOD__ . '() is deprecated; use setParameters() instead.', E_USER_WARNING);
328:         return $this->setParameters($params);
329:     }
330: 
331: 
332: 
333:     /** @deprecated */
334:     function getParams()
335:     {
336:         trigger_error(__METHOD__ . '() is deprecated; use getParameters() instead.', E_USER_WARNING);
337:         return $this->getParameters();
338:     }
339: 
340: 
341: 
342:     /**
343:      * Sets a template parameter. Do not call directly.
344:      * @param  string  name
345:      * @param  mixed   value
346:      * @return void
347:      */
348:     public function __set($name, $value)
349:     {
350:         $this->params[$name] = $value;
351:     }
352: 
353: 
354: 
355:     /**
356:      * Returns a template parameter. Do not call directly.
357:      * @param  string  name
358:      * @return mixed  value
359:      */
360:     public function &__get($name)
361:     {
362:         if (!array_key_exists($name, $this->params)) {
363:             trigger_error("The variable '$name' does not exist in template.", E_USER_NOTICE);
364:         }
365: 
366:         return $this->params[$name];
367:     }
368: 
369: 
370: 
371:     /**
372:      * Determines whether parameter is defined. Do not call directly.
373:      * @param  string    name
374:      * @return bool
375:      */
376:     public function __isset($name)
377:     {
378:         return isset($this->params[$name]);
379:     }
380: 
381: 
382: 
383:     /**
384:      * Removes a template parameter. Do not call directly.
385:      * @param  string    name
386:      * @return void
387:      */
388:     public function __unset($name)
389:     {
390:         unset($this->params[$name]);
391:     }
392: 
393: 
394: 
395:     /********************* caching ****************d*g**/
396: 
397: 
398: 
399:     /**
400:      * Set cache storage.
401:      * @return NTemplate  provides a fluent interface
402:      */
403:     public function setCacheStorage(ICacheStorage $storage)
404:     {
405:         $this->cacheStorage = $storage;
406:         return $this;
407:     }
408: 
409: 
410: 
411:     /**
412:      * @return ICacheStorage
413:      */
414:     public function getCacheStorage()
415:     {
416:         if ($this->cacheStorage === NULL) {
417:             return new NDevNullStorage;
418:         }
419:         return $this->cacheStorage;
420:     }
421: 
422: 
423: 
424:     /********************* tools ****************d*g**/
425: 
426: 
427: 
428:     /**
429:      * Extracts all blocks of PHP code.
430:      * @param  string
431:      * @param  array
432:      * @return string
433:      */
434:     private static function extractPhp($source, & $blocks)
435:     {
436:         $res = '';
437:         $blocks = array();
438:         $tokens = token_get_all($source);
439:         foreach ($tokens as $n => $token) {
440:             if (is_array($token)) {
441:                 if ($token[0] === T_INLINE_HTML) {
442:                     $res .= $token[1];
443:                     continue;
444: 
445:                 } elseif ($token[0] === T_CLOSE_TAG) {
446:                     if ($php !== $res) { // not <?xml
447:                         $res .= str_repeat("\n", substr_count($php, "\n"));
448:                     }
449:                     $res .= $token[1];
450:                     continue;
451: 
452:                 } elseif ($token[0] === T_OPEN_TAG && $token[1] === '<?' && isset($tokens[$n+1][1]) && $tokens[$n+1][1] === 'xml') {
453:                     $php = & $res;
454:                     $token[1] = '<<?php ?>?';
455: 
456:                 } elseif ($token[0] === T_OPEN_TAG || $token[0] === T_OPEN_TAG_WITH_ECHO) {
457:                     $res .= $id = "<?php \x01@php:p" . count($blocks) . "@\x02";
458:                     $php = & $blocks[$id];
459:                 }
460:                 $php .= $token[1];
461: 
462:             } else {
463:                 $php .= $token;
464:             }
465:         }
466:         return $res;
467:     }
468: 
469: }
470: 
Nette Framework 2.0.7 (for PHP 5.2, prefixed) API API documentation generated by ApiGen 2.8.0