Namespaces

  • 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
  • Helpers
  • Template

Interfaces

  • IFileTemplate
  • ITemplate

Exceptions

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