Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationLatte
      • ApplicationTracy
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsLatte
      • Framework
      • HttpTracy
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Templating
    • Utils
  • NetteModule
  • none
  • Tracy

Classes

  • FileTemplate
  • Helpers
  • Template

Interfaces

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