1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Bridges\ApplicationLatte;
9:
10: use Latte;
11: use Nette;
12: use Nette\Application\UI;
13:
14:
15: 16: 17:
18: class TemplateFactory implements UI\ITemplateFactory
19: {
20: use Nette\SmartObject;
21:
22:
23: public $onCreate;
24:
25:
26: private $latteFactory;
27:
28:
29: private $httpRequest;
30:
31:
32: private $user;
33:
34:
35: private $cacheStorage;
36:
37:
38: private $templateClass;
39:
40:
41: public function __construct(ILatteFactory $latteFactory, Nette\Http\IRequest $httpRequest = null,
42: Nette\Security\User $user = null, Nette\Caching\IStorage $cacheStorage = null, $templateClass = null)
43: {
44: $this->latteFactory = $latteFactory;
45: $this->httpRequest = $httpRequest;
46: $this->user = $user;
47: $this->cacheStorage = $cacheStorage;
48: if ($templateClass && (!class_exists($templateClass) || !is_a($templateClass, Template::class, true))) {
49: throw new Nette\InvalidArgumentException("Class $templateClass does not extend " . Template::class . ' or it does not exist.');
50: }
51: $this->templateClass = $templateClass ?: Template::class;
52: }
53:
54:
55: 56: 57:
58: public function createTemplate(UI\Control $control = null)
59: {
60: $latte = $this->latteFactory->create();
61: $template = new $this->templateClass($latte);
62: $presenter = $control ? $control->getPresenter(false) : null;
63:
64: if ($control instanceof UI\Presenter) {
65: $latte->setLoader(new Loader($control));
66: }
67:
68: if ($latte->onCompile instanceof \Traversable) {
69: $latte->onCompile = iterator_to_array($latte->onCompile);
70: }
71:
72: array_unshift($latte->onCompile, function ($latte) use ($control, $template) {
73: if ($this->cacheStorage) {
74: $latte->getCompiler()->addMacro('cache', new Nette\Bridges\CacheLatte\CacheMacro);
75: }
76: UIMacros::install($latte->getCompiler());
77: if (class_exists(Nette\Bridges\FormsLatte\FormMacros::class)) {
78: Nette\Bridges\FormsLatte\FormMacros::install($latte->getCompiler());
79: }
80: if ($control) {
81: $control->templatePrepareFilters($template);
82: }
83: });
84:
85: $latte->addFilter('url', 'rawurlencode');
86: foreach (['normalize', 'toAscii', 'webalize', 'reverse'] as $name) {
87: $latte->addFilter($name, 'Nette\Utils\Strings::' . $name);
88: }
89: $latte->addFilter('null', function () {});
90: $latte->addFilter('modifyDate', function ($time, $delta, $unit = null) {
91: return $time == null ? null : Nette\Utils\DateTime::from($time)->modify($delta . $unit);
92: });
93:
94: if (!isset($latte->getFilters()['translate'])) {
95: $latte->addFilter('translate', function (Latte\Runtime\FilterInfo $fi) {
96: throw new Nette\InvalidStateException('Translator has not been set. Set translator using $template->setTranslator().');
97: });
98: }
99:
100:
101: $template->user = $this->user;
102: $template->baseUri = $template->baseUrl = $this->httpRequest ? rtrim($this->httpRequest->getUrl()->getBaseUrl(), '/') : null;
103: $template->basePath = preg_replace('#https?://[^/]+#A', '', $template->baseUrl);
104: $template->flashes = [];
105: if ($control) {
106: $template->control = $control;
107: $template->presenter = $presenter;
108: $latte->addProvider('uiControl', $control);
109: $latte->addProvider('uiPresenter', $presenter);
110: $latte->addProvider('snippetBridge', new Nette\Bridges\ApplicationLatte\SnippetBridge($control));
111: if ($presenter) {
112: $header = $presenter->getHttpResponse()->getHeader('Content-Security-Policy')
113: ?: $presenter->getHttpResponse()->getHeader('Content-Security-Policy-Report-Only');
114: }
115: $nonce = $presenter && preg_match('#\s\'nonce-([\w+/]+=*)\'#', (string) $header, $m) ? $m[1] : null;
116: $latte->addProvider('uiNonce', $nonce);
117: }
118: $latte->addProvider('cacheStorage', $this->cacheStorage);
119:
120:
121: $template->_control = $control;
122: $template->_presenter = $presenter;
123: $template->netteCacheStorage = $this->cacheStorage;
124:
125: if ($presenter instanceof UI\Presenter && $presenter->hasFlashSession()) {
126: $id = $control->getParameterId('flash');
127: $template->flashes = (array) $presenter->getFlashSession()->$id;
128: }
129:
130: $this->onCreate($template);
131:
132: return $template;
133: }
134: }
135: