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