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

  • FileTemplate
  • Template
  • TemplateHelpers

Interfaces

  • IFileTemplate
  • ITemplate

Exceptions

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