These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * CakePHP(tm) : Rapid Development Framework (https://cakephp.org) |
||
4 | * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) |
||
5 | * |
||
6 | * Licensed under The MIT License |
||
7 | * For full copyright and license information, please see the LICENSE.txt |
||
8 | * Redistributions of files must retain the above copyright notice. |
||
9 | * |
||
10 | * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) |
||
11 | * @link https://cakephp.org CakePHP(tm) Project |
||
12 | * @since 0.10.0 |
||
13 | * @license https://www.opensource.org/licenses/mit-license.php MIT License |
||
14 | */ |
||
15 | namespace Cake\View; |
||
16 | |||
17 | use Cake\Cache\Cache; |
||
18 | use Cake\Core\App; |
||
19 | use Cake\Core\Plugin; |
||
20 | use Cake\Event\EventDispatcherInterface; |
||
21 | use Cake\Event\EventDispatcherTrait; |
||
22 | use Cake\Event\EventManager; |
||
23 | use Cake\Http\Response; |
||
24 | use Cake\Http\ServerRequest; |
||
25 | use Cake\Log\LogTrait; |
||
26 | use Cake\Routing\RequestActionTrait; |
||
27 | use Cake\Routing\Router; |
||
28 | use Cake\Utility\Inflector; |
||
29 | use Cake\View\Exception\MissingElementException; |
||
30 | use Cake\View\Exception\MissingHelperException; |
||
31 | use Cake\View\Exception\MissingLayoutException; |
||
32 | use Cake\View\Exception\MissingTemplateException; |
||
33 | use InvalidArgumentException; |
||
34 | use LogicException; |
||
35 | use RuntimeException; |
||
36 | |||
37 | /** |
||
38 | * View, the V in the MVC triad. View interacts with Helpers and view variables passed |
||
39 | * in from the controller to render the results of the controller action. Often this is HTML, |
||
40 | * but can also take the form of JSON, XML, PDF's or streaming files. |
||
41 | * |
||
42 | * CakePHP uses a two-step-view pattern. This means that the template content is rendered first, |
||
43 | * and then inserted into the selected layout. This also means you can pass data from the template to the |
||
44 | * layout using `$this->set()` |
||
45 | * |
||
46 | * View class supports using plugins as themes. You can set |
||
47 | * |
||
48 | * ``` |
||
49 | * public function beforeRender(\Cake\Event\Event $event) |
||
50 | * { |
||
51 | * $this->viewBuilder()->setTheme('SuperHot'); |
||
52 | * } |
||
53 | * ``` |
||
54 | * |
||
55 | * in your Controller to use plugin `SuperHot` as a theme. Eg. If current action |
||
56 | * is PostsController::index() then View class will look for template file |
||
57 | * `plugins/SuperHot/Template/Posts/index.ctp`. If a theme template |
||
58 | * is not found for the current action the default app template file is used. |
||
59 | * |
||
60 | * @property \Cake\View\Helper\BreadcrumbsHelper $Breadcrumbs |
||
61 | * @property \Cake\View\Helper\FlashHelper $Flash |
||
62 | * @property \Cake\View\Helper\FormHelper $Form |
||
63 | * @property \Cake\View\Helper\HtmlHelper $Html |
||
64 | * @property \Cake\View\Helper\NumberHelper $Number |
||
65 | * @property \Cake\View\Helper\PaginatorHelper $Paginator |
||
66 | * @property \Cake\View\Helper\RssHelper $Rss |
||
67 | * @property \Cake\View\Helper\SessionHelper $Session |
||
68 | * @property \Cake\View\Helper\TextHelper $Text |
||
69 | * @property \Cake\View\Helper\TimeHelper $Time |
||
70 | * @property \Cake\View\Helper\UrlHelper $Url |
||
71 | * @property \Cake\View\ViewBlock $Blocks |
||
72 | * @property string $view |
||
73 | * @property string $viewPath |
||
74 | */ |
||
75 | class View implements EventDispatcherInterface |
||
76 | { |
||
77 | |||
78 | use CellTrait { |
||
79 | cell as public; |
||
80 | } |
||
81 | use EventDispatcherTrait; |
||
82 | use LogTrait; |
||
83 | use RequestActionTrait; |
||
84 | use ViewVarsTrait; |
||
85 | |||
86 | /** |
||
87 | * Helpers collection |
||
88 | * |
||
89 | * @var \Cake\View\HelperRegistry |
||
90 | */ |
||
91 | protected $_helpers; |
||
92 | |||
93 | /** |
||
94 | * ViewBlock instance. |
||
95 | * |
||
96 | * @var \Cake\View\ViewBlock |
||
97 | */ |
||
98 | protected $Blocks; |
||
99 | |||
100 | /** |
||
101 | * The name of the plugin. |
||
102 | * |
||
103 | * @var string|null |
||
104 | */ |
||
105 | protected $plugin; |
||
106 | |||
107 | /** |
||
108 | * Name of the controller that created the View if any. |
||
109 | * |
||
110 | * @var string |
||
111 | */ |
||
112 | protected $name; |
||
113 | |||
114 | /** |
||
115 | * Current passed params. Passed to View from the creating Controller for convenience. |
||
116 | * |
||
117 | * @var array |
||
118 | * @deprecated 3.1.0 Use `$this->request->getParam('pass')` instead. |
||
119 | */ |
||
120 | public $passedArgs = []; |
||
121 | |||
122 | /** |
||
123 | * An array of names of built-in helpers to include. |
||
124 | * |
||
125 | * @var array |
||
126 | */ |
||
127 | protected $helpers = []; |
||
128 | |||
129 | /** |
||
130 | * The name of the subfolder containing templates for this View. |
||
131 | * |
||
132 | * @var string |
||
133 | */ |
||
134 | protected $templatePath; |
||
135 | |||
136 | /** |
||
137 | * The name of the template file to render. The name specified |
||
138 | * is the filename in /src/Template/<SubFolder> without the .ctp extension. |
||
139 | * |
||
140 | * @var string |
||
141 | */ |
||
142 | protected $template; |
||
143 | |||
144 | /** |
||
145 | * The name of the layout file to render the template inside of. The name specified |
||
146 | * is the filename of the layout in /src/Template/Layout without the .ctp |
||
147 | * extension. |
||
148 | * |
||
149 | * @var string |
||
150 | */ |
||
151 | protected $layout = 'default'; |
||
152 | |||
153 | /** |
||
154 | * The name of the layouts subfolder containing layouts for this View. |
||
155 | * |
||
156 | * @var string |
||
157 | */ |
||
158 | protected $layoutPath; |
||
159 | |||
160 | /** |
||
161 | * Turns on or off CakePHP's conventional mode of applying layout files. On by default. |
||
162 | * Setting to off means that layouts will not be automatically applied to rendered templates. |
||
163 | * |
||
164 | * @var bool |
||
165 | */ |
||
166 | protected $autoLayout = true; |
||
167 | |||
168 | /** |
||
169 | * File extension. Defaults to CakePHP's template ".ctp". |
||
170 | * |
||
171 | * @var string |
||
172 | */ |
||
173 | protected $_ext = '.ctp'; |
||
174 | |||
175 | /** |
||
176 | * Sub-directory for this template file. This is often used for extension based routing. |
||
177 | * Eg. With an `xml` extension, $subDir would be `xml/` |
||
178 | * |
||
179 | * @var string |
||
180 | */ |
||
181 | protected $subDir = ''; |
||
182 | |||
183 | /** |
||
184 | * The view theme to use. |
||
185 | * |
||
186 | * @var string|null |
||
187 | */ |
||
188 | protected $theme; |
||
189 | |||
190 | /** |
||
191 | * True when the view has been rendered. |
||
192 | * |
||
193 | * @var bool |
||
194 | * @deprecated 3.7.0 The property is deprecated and will be removed in 4.0.0. |
||
195 | */ |
||
196 | public $hasRendered = false; |
||
197 | |||
198 | /** |
||
199 | * List of generated DOM UUIDs. |
||
200 | * |
||
201 | * @var array |
||
202 | * @deprecated 3.7.0 The property is deprecated and will be removed in 4.0.0. |
||
203 | */ |
||
204 | public $uuids = []; |
||
205 | |||
206 | /** |
||
207 | * An instance of a \Cake\Http\ServerRequest object that contains information about the current request. |
||
208 | * This object contains all the information about a request and several methods for reading |
||
209 | * additional information about the request. |
||
210 | * |
||
211 | * @var \Cake\Http\ServerRequest |
||
212 | */ |
||
213 | protected $request; |
||
214 | |||
215 | /** |
||
216 | * Reference to the Response object |
||
217 | * |
||
218 | * @var \Cake\Http\Response |
||
219 | */ |
||
220 | protected $response; |
||
221 | |||
222 | /** |
||
223 | * The Cache configuration View will use to store cached elements. Changing this will change |
||
224 | * the default configuration elements are stored under. You can also choose a cache config |
||
225 | * per element. |
||
226 | * |
||
227 | * @var string |
||
228 | * @see \Cake\View\View::element() |
||
229 | */ |
||
230 | protected $elementCache = 'default'; |
||
231 | |||
232 | /** |
||
233 | * List of variables to collect from the associated controller. |
||
234 | * |
||
235 | * @var array |
||
236 | */ |
||
237 | protected $_passedVars = [ |
||
238 | 'viewVars', 'autoLayout', 'helpers', 'template', 'layout', 'name', 'theme', |
||
239 | 'layoutPath', 'templatePath', 'plugin', 'passedArgs' |
||
240 | ]; |
||
241 | |||
242 | /** |
||
243 | * Holds an array of paths. |
||
244 | * |
||
245 | * @var array |
||
246 | */ |
||
247 | protected $_paths = []; |
||
248 | |||
249 | /** |
||
250 | * Holds an array of plugin paths. |
||
251 | * |
||
252 | * @var array |
||
253 | */ |
||
254 | protected $_pathsForPlugin = []; |
||
255 | |||
256 | /** |
||
257 | * The names of views and their parents used with View::extend(); |
||
258 | * |
||
259 | * @var array |
||
260 | */ |
||
261 | protected $_parents = []; |
||
262 | |||
263 | /** |
||
264 | * The currently rendering view file. Used for resolving parent files. |
||
265 | * |
||
266 | * @var string |
||
267 | */ |
||
268 | protected $_current; |
||
269 | |||
270 | /** |
||
271 | * Currently rendering an element. Used for finding parent fragments |
||
272 | * for elements. |
||
273 | * |
||
274 | * @var string |
||
275 | */ |
||
276 | protected $_currentType = ''; |
||
277 | |||
278 | /** |
||
279 | * Content stack, used for nested templates that all use View::extend(); |
||
280 | * |
||
281 | * @var array |
||
282 | */ |
||
283 | protected $_stack = []; |
||
284 | |||
285 | /** |
||
286 | * ViewBlock class. |
||
287 | * |
||
288 | * @var string |
||
289 | */ |
||
290 | protected $_viewBlockClass = ViewBlock::class; |
||
291 | |||
292 | /** |
||
293 | * Constant for view file type 'view' |
||
294 | * |
||
295 | * @var string |
||
296 | * @deprecated 3.1.0 Use TYPE_TEMPLATE instead. |
||
297 | */ |
||
298 | const TYPE_VIEW = 'view'; |
||
299 | |||
300 | /** |
||
301 | * Constant for view file type 'template'. |
||
302 | * |
||
303 | * @var string |
||
304 | */ |
||
305 | const TYPE_TEMPLATE = 'view'; |
||
306 | |||
307 | /** |
||
308 | * Constant for view file type 'element' |
||
309 | * |
||
310 | * @var string |
||
311 | */ |
||
312 | const TYPE_ELEMENT = 'element'; |
||
313 | |||
314 | /** |
||
315 | * Constant for name of view file 'Element' |
||
316 | * |
||
317 | * @var string |
||
318 | */ |
||
319 | const NAME_ELEMENT = 'Element'; |
||
320 | |||
321 | /** |
||
322 | * Constant for view file type 'layout' |
||
323 | * |
||
324 | * @var string |
||
325 | */ |
||
326 | const TYPE_LAYOUT = 'layout'; |
||
327 | |||
328 | /** |
||
329 | * Constant for template folder 'Template' |
||
330 | * |
||
331 | * @var string |
||
332 | */ |
||
333 | const NAME_TEMPLATE = 'Template'; |
||
334 | |||
335 | /** |
||
336 | * Constructor |
||
337 | * |
||
338 | * @param \Cake\Http\ServerRequest|null $request Request instance. |
||
339 | * @param \Cake\Http\Response|null $response Response instance. |
||
340 | * @param \Cake\Event\EventManager|null $eventManager Event manager instance. |
||
341 | * @param array $viewOptions View options. See View::$_passedVars for list of |
||
342 | * options which get set as class properties. |
||
343 | */ |
||
344 | public function __construct( |
||
345 | ServerRequest $request = null, |
||
346 | Response $response = null, |
||
347 | EventManager $eventManager = null, |
||
348 | array $viewOptions = [] |
||
349 | ) { |
||
350 | if (isset($viewOptions['view'])) { |
||
351 | $this->setTemplate($viewOptions['view']); |
||
352 | } |
||
353 | if (isset($viewOptions['viewPath'])) { |
||
354 | $this->setTemplatePath($viewOptions['viewPath']); |
||
355 | } |
||
356 | foreach ($this->_passedVars as $var) { |
||
357 | if (isset($viewOptions[$var])) { |
||
358 | $this->{$var} = $viewOptions[$var]; |
||
359 | } |
||
360 | } |
||
361 | if ($eventManager !== null) { |
||
362 | $this->setEventManager($eventManager); |
||
363 | } |
||
364 | $this->request = $request ?: Router::getRequest(true); |
||
365 | $this->response = $response ?: new Response(); |
||
366 | if (!$this->request) { |
||
367 | $this->request = new ServerRequest([ |
||
368 | 'base' => '', |
||
369 | 'url' => '', |
||
370 | 'webroot' => '/' |
||
371 | ]); |
||
372 | } |
||
373 | $this->Blocks = new $this->_viewBlockClass(); |
||
374 | $this->initialize(); |
||
375 | $this->loadHelpers(); |
||
376 | } |
||
377 | |||
378 | /** |
||
379 | * Initialization hook method. |
||
380 | * |
||
381 | * Properties like $helpers etc. cannot be initialized statically in your custom |
||
382 | * view class as they are overwritten by values from controller in constructor. |
||
383 | * So this method allows you to manipulate them as required after view instance |
||
384 | * is constructed. |
||
385 | * |
||
386 | * @return void |
||
387 | */ |
||
388 | public function initialize() |
||
389 | { |
||
390 | } |
||
391 | |||
392 | /** |
||
393 | * Gets the request instance. |
||
394 | * |
||
395 | * @return \Cake\Http\ServerRequest |
||
396 | * @since 3.7.0 |
||
397 | */ |
||
398 | public function getRequest() |
||
399 | { |
||
400 | return $this->request; |
||
401 | } |
||
402 | |||
403 | /** |
||
404 | * Sets the request objects and configures a number of controller properties |
||
405 | * based on the contents of the request. The properties that get set are: |
||
406 | * |
||
407 | * - $this->request - To the $request parameter |
||
408 | * - $this->plugin - To the value returned by $request->getParam('plugin') |
||
409 | * - $this->passedArgs - Same as $request->params['pass] |
||
410 | * |
||
411 | * @param \Cake\Http\ServerRequest $request Request instance. |
||
412 | * @return $this |
||
413 | * @since 3.7.0 |
||
414 | */ |
||
415 | View Code Duplication | public function setRequest(ServerRequest $request) |
|
416 | { |
||
417 | $this->request = $request; |
||
418 | $this->plugin = $request->getParam('plugin'); |
||
419 | |||
420 | if ($request->getParam('pass')) { |
||
421 | $this->passedArgs = $request->getParam('pass'); |
||
422 | } |
||
423 | |||
424 | return $this; |
||
425 | } |
||
426 | |||
427 | /** |
||
428 | * Gets the response instance. |
||
429 | * |
||
430 | * @return \Cake\Http\Response |
||
431 | * @since 3.7.0 |
||
432 | */ |
||
433 | public function getResponse() |
||
434 | { |
||
435 | return $this->response; |
||
436 | } |
||
437 | |||
438 | /** |
||
439 | * Sets the response instance. |
||
440 | * |
||
441 | * @param \Cake\Http\Response $response Response instance. |
||
442 | * @return $this |
||
443 | * @since 3.7.0 |
||
444 | */ |
||
445 | public function setResponse(Response $response) |
||
446 | { |
||
447 | $this->response = $response; |
||
448 | |||
449 | return $this; |
||
450 | } |
||
451 | |||
452 | /** |
||
453 | * Get path for templates files. |
||
454 | * |
||
455 | * @return string |
||
456 | */ |
||
457 | public function getTemplatePath() |
||
458 | { |
||
459 | return $this->templatePath; |
||
460 | } |
||
461 | |||
462 | /** |
||
463 | * Set path for templates files. |
||
464 | * |
||
465 | * @param string $path Path for template files. |
||
466 | * @return $this |
||
467 | */ |
||
468 | public function setTemplatePath($path) |
||
469 | { |
||
470 | $this->templatePath = $path; |
||
471 | |||
472 | return $this; |
||
473 | } |
||
474 | |||
475 | /** |
||
476 | * Get/set path for templates files. |
||
477 | * |
||
478 | * @deprecated 3.5.0 Use getTemplatePath()/setTemplatePath() instead. |
||
479 | * @param string|null $path Path for template files. If null returns current path. |
||
480 | * @return string|null |
||
481 | */ |
||
482 | public function templatePath($path = null) |
||
483 | { |
||
484 | deprecationWarning( |
||
485 | 'View::templatePath() is deprecated. ' . |
||
486 | 'Use getTemplatePath()/setTemplatePath() instead.' |
||
487 | ); |
||
488 | |||
489 | if ($path === null) { |
||
490 | return $this->templatePath; |
||
491 | } |
||
492 | |||
493 | $this->templatePath = $path; |
||
494 | } |
||
495 | |||
496 | /** |
||
497 | * Get path for layout files. |
||
498 | * |
||
499 | * @return string |
||
500 | */ |
||
501 | public function getLayoutPath() |
||
502 | { |
||
503 | return $this->layoutPath; |
||
504 | } |
||
505 | |||
506 | /** |
||
507 | * Set path for layout files. |
||
508 | * |
||
509 | * @param string $path Path for layout files. |
||
510 | * @return $this |
||
511 | */ |
||
512 | public function setLayoutPath($path) |
||
513 | { |
||
514 | $this->layoutPath = $path; |
||
515 | |||
516 | return $this; |
||
517 | } |
||
518 | |||
519 | /** |
||
520 | * Get/set path for layout files. |
||
521 | * |
||
522 | * @deprecated 3.5.0 Use getLayoutPath()/setLayoutPath() instead. |
||
523 | * @param string|null $path Path for layout files. If null returns current path. |
||
524 | * @return string|null |
||
525 | */ |
||
526 | public function layoutPath($path = null) |
||
527 | { |
||
528 | deprecationWarning( |
||
529 | 'View::layoutPath() is deprecated. ' . |
||
530 | 'Use getLayoutPath()/setLayoutPath() instead.' |
||
531 | ); |
||
532 | |||
533 | if ($path === null) { |
||
534 | return $this->layoutPath; |
||
535 | } |
||
536 | |||
537 | $this->layoutPath = $path; |
||
538 | } |
||
539 | |||
540 | /** |
||
541 | * Returns if CakePHP's conventional mode of applying layout files is enabled. |
||
542 | * Disabled means that layouts will not be automatically applied to rendered views. |
||
543 | * |
||
544 | * @return bool |
||
545 | */ |
||
546 | public function isAutoLayoutEnabled() |
||
547 | { |
||
548 | return $this->autoLayout; |
||
549 | } |
||
550 | |||
551 | /** |
||
552 | * Turns on or off CakePHP's conventional mode of applying layout files. |
||
553 | * On by default. Setting to off means that layouts will not be |
||
554 | * automatically applied to rendered views. |
||
555 | * |
||
556 | * @param bool $enable Boolean to turn on/off. |
||
557 | * @return $this |
||
558 | */ |
||
559 | public function enableAutoLayout($enable = true) |
||
560 | { |
||
561 | $this->autoLayout = (bool)$enable; |
||
562 | |||
563 | return $this; |
||
564 | } |
||
565 | |||
566 | /** |
||
567 | * Turns off CakePHP's conventional mode of applying layout files. |
||
568 | |||
569 | * Layouts will not be automatically applied to rendered views. |
||
570 | * |
||
571 | * @return $this |
||
572 | */ |
||
573 | public function disableAutoLayout() |
||
574 | { |
||
575 | $this->autoLayout = false; |
||
576 | |||
577 | return $this; |
||
578 | } |
||
579 | |||
580 | /** |
||
581 | * Turns on or off CakePHP's conventional mode of applying layout files. |
||
582 | * On by default. Setting to off means that layouts will not be |
||
583 | * automatically applied to rendered templates. |
||
584 | * |
||
585 | * @deprecated 3.5.0 Use isAutoLayoutEnabled()/enableAutoLayout() instead. |
||
586 | * @param bool|null $autoLayout Boolean to turn on/off. If null returns current value. |
||
587 | * @return bool|null |
||
588 | */ |
||
589 | public function autoLayout($autoLayout = null) |
||
590 | { |
||
591 | deprecationWarning( |
||
592 | 'View::autoLayout() is deprecated. ' . |
||
593 | 'Use isAutoLayoutEnabled()/enableAutoLayout() instead.' |
||
594 | ); |
||
595 | |||
596 | if ($autoLayout === null) { |
||
597 | return $this->autoLayout; |
||
598 | } |
||
599 | |||
600 | $this->autoLayout = $autoLayout; |
||
601 | } |
||
602 | |||
603 | /** |
||
604 | * Get the current view theme. |
||
605 | * |
||
606 | * @return string|null |
||
607 | */ |
||
608 | public function getTheme() |
||
609 | { |
||
610 | return $this->theme; |
||
611 | } |
||
612 | |||
613 | /** |
||
614 | * Set the view theme to use. |
||
615 | * |
||
616 | * @param string|null $theme Theme name. |
||
617 | * @return $this |
||
618 | */ |
||
619 | public function setTheme($theme) |
||
620 | { |
||
621 | $this->theme = $theme; |
||
622 | |||
623 | return $this; |
||
624 | } |
||
625 | |||
626 | /** |
||
627 | * The view theme to use. |
||
628 | * |
||
629 | * @deprecated 3.5.0 Use getTheme()/setTheme() instead. |
||
630 | * @param string|null $theme Theme name. If null returns current theme. |
||
631 | * @return string|null |
||
632 | */ |
||
633 | public function theme($theme = null) |
||
634 | { |
||
635 | deprecationWarning( |
||
636 | 'View::theme() is deprecated. ' . |
||
637 | 'Use getTheme()/setTheme() instead.' |
||
638 | ); |
||
639 | |||
640 | if ($theme === null) { |
||
641 | return $this->theme; |
||
642 | } |
||
643 | |||
644 | $this->theme = $theme; |
||
645 | } |
||
646 | |||
647 | /** |
||
648 | * Get the name of the template file to render. The name specified is the |
||
649 | * filename in /src/Template/<SubFolder> without the .ctp extension. |
||
650 | * |
||
651 | * @return string |
||
652 | */ |
||
653 | public function getTemplate() |
||
654 | { |
||
655 | return $this->template; |
||
656 | } |
||
657 | |||
658 | /** |
||
659 | * Set the name of the template file to render. The name specified is the |
||
660 | * filename in /src/Template/<SubFolder> without the .ctp extension. |
||
661 | * |
||
662 | * @param string $name Template file name to set. |
||
663 | * @return $this |
||
664 | */ |
||
665 | public function setTemplate($name) |
||
666 | { |
||
667 | $this->template = $name; |
||
668 | |||
669 | return $this; |
||
670 | } |
||
671 | |||
672 | /** |
||
673 | * Get/set the name of the template file to render. The name specified is the |
||
674 | * filename in /src/Template/<SubFolder> without the .ctp extension. |
||
675 | * |
||
676 | * @deprecated 3.5.0 Use getTemplate()/setTemplate() instead. |
||
677 | * @param string|null $name Template file name to set. If null returns current name. |
||
678 | * @return string|null |
||
679 | */ |
||
680 | public function template($name = null) |
||
681 | { |
||
682 | deprecationWarning( |
||
683 | 'View::template() is deprecated. ' . |
||
684 | 'Use getTemplate()/setTemplate() instead.' |
||
685 | ); |
||
686 | |||
687 | if ($name === null) { |
||
688 | return $this->template; |
||
689 | } |
||
690 | |||
691 | $this->template = $name; |
||
692 | } |
||
693 | |||
694 | /** |
||
695 | * Get the name of the layout file to render the template inside of. |
||
696 | * The name specified is the filename of the layout in /src/Template/Layout |
||
697 | * without the .ctp extension. |
||
698 | * |
||
699 | * @return string |
||
700 | */ |
||
701 | public function getLayout() |
||
702 | { |
||
703 | return $this->layout; |
||
704 | } |
||
705 | |||
706 | /** |
||
707 | * Set the name of the layout file to render the template inside of. |
||
708 | * The name specified is the filename of the layout in /src/Template/Layout |
||
709 | * without the .ctp extension. |
||
710 | * |
||
711 | * @param string $name Layout file name to set. |
||
712 | * @return $this |
||
713 | */ |
||
714 | public function setLayout($name) |
||
715 | { |
||
716 | $this->layout = $name; |
||
717 | |||
718 | return $this; |
||
719 | } |
||
720 | |||
721 | /** |
||
722 | * Get/set the name of the layout file to render the template inside of. |
||
723 | * The name specified is the filename of the layout in /src/Template/Layout |
||
724 | * without the .ctp extension. |
||
725 | * |
||
726 | * @deprecated 3.5.0 Use getLayout()/setLayout() instead. |
||
727 | * @param string|null $name Layout file name to set. If null returns current name. |
||
728 | * @return string|null |
||
729 | */ |
||
730 | public function layout($name = null) |
||
731 | { |
||
732 | deprecationWarning( |
||
733 | 'View::layout() is deprecated. ' . |
||
734 | 'Use getLayout()/setLayout() instead.' |
||
735 | ); |
||
736 | |||
737 | if ($name === null) { |
||
738 | return $this->layout; |
||
739 | } |
||
740 | |||
741 | $this->layout = $name; |
||
742 | } |
||
743 | |||
744 | /** |
||
745 | * Renders a piece of PHP with provided parameters and returns HTML, XML, or any other string. |
||
746 | * |
||
747 | * This realizes the concept of Elements, (or "partial layouts") and the $params array is used to send |
||
748 | * data to be used in the element. Elements can be cached improving performance by using the `cache` option. |
||
749 | * |
||
750 | * @param string $name Name of template file in the /src/Template/Element/ folder, |
||
751 | * or `MyPlugin.template` to use the template element from MyPlugin. If the element |
||
752 | * is not found in the plugin, the normal view path cascade will be searched. |
||
753 | * @param array $data Array of data to be made available to the rendered view (i.e. the Element) |
||
754 | * @param array $options Array of options. Possible keys are: |
||
755 | * - `cache` - Can either be `true`, to enable caching using the config in View::$elementCache. Or an array |
||
756 | * If an array, the following keys can be used: |
||
757 | * - `config` - Used to store the cached element in a custom cache configuration. |
||
758 | * - `key` - Used to define the key used in the Cache::write(). It will be prefixed with `element_` |
||
759 | * - `callbacks` - Set to true to fire beforeRender and afterRender helper callbacks for this element. |
||
760 | * Defaults to false. |
||
761 | * - `ignoreMissing` - Used to allow missing elements. Set to true to not throw exceptions. |
||
762 | * - `plugin` - setting to false will force to use the application's element from plugin templates, when the |
||
763 | * plugin has element with same name. Defaults to true |
||
764 | * @return string Rendered Element |
||
765 | * @throws \Cake\View\Exception\MissingElementException When an element is missing and `ignoreMissing` |
||
766 | * is false. |
||
767 | */ |
||
768 | public function element($name, array $data = [], array $options = []) |
||
769 | { |
||
770 | $options += ['callbacks' => false, 'cache' => null, 'plugin' => null]; |
||
771 | if (isset($options['cache'])) { |
||
772 | $options['cache'] = $this->_elementCache($name, $data, $options); |
||
773 | } |
||
774 | |||
775 | $pluginCheck = $options['plugin'] !== false; |
||
776 | $file = $this->_getElementFileName($name, $pluginCheck); |
||
777 | if ($file && $options['cache']) { |
||
778 | return $this->cache(function () use ($file, $data, $options) { |
||
779 | echo $this->_renderElement($file, $data, $options); |
||
780 | }, $options['cache']); |
||
781 | } |
||
782 | if ($file) { |
||
783 | return $this->_renderElement($file, $data, $options); |
||
784 | } |
||
785 | |||
786 | if (empty($options['ignoreMissing'])) { |
||
787 | list ($plugin, $name) = pluginSplit($name, true); |
||
788 | $name = str_replace('/', DIRECTORY_SEPARATOR, $name); |
||
789 | $file = $plugin . static::NAME_ELEMENT . DIRECTORY_SEPARATOR . $name . $this->_ext; |
||
790 | throw new MissingElementException([$file]); |
||
791 | } |
||
792 | } |
||
793 | |||
794 | /** |
||
795 | * Create a cached block of view logic. |
||
796 | * |
||
797 | * This allows you to cache a block of view output into the cache |
||
798 | * defined in `elementCache`. |
||
799 | * |
||
800 | * This method will attempt to read the cache first. If the cache |
||
801 | * is empty, the $block will be run and the output stored. |
||
802 | * |
||
803 | * @param callable $block The block of code that you want to cache the output of. |
||
804 | * @param array $options The options defining the cache key etc. |
||
805 | * @return string The rendered content. |
||
806 | * @throws \RuntimeException When $options is lacking a 'key' option. |
||
807 | */ |
||
808 | public function cache(callable $block, array $options = []) |
||
809 | { |
||
810 | $options += ['key' => '', 'config' => $this->elementCache]; |
||
811 | if (empty($options['key'])) { |
||
812 | throw new RuntimeException('Cannot cache content with an empty key'); |
||
813 | } |
||
814 | $result = Cache::read($options['key'], $options['config']); |
||
815 | if ($result) { |
||
816 | return $result; |
||
817 | } |
||
818 | ob_start(); |
||
819 | $block(); |
||
820 | $result = ob_get_clean(); |
||
821 | |||
822 | Cache::write($options['key'], $result, $options['config']); |
||
823 | |||
824 | return $result; |
||
825 | } |
||
826 | |||
827 | /** |
||
828 | * Checks if an element exists |
||
829 | * |
||
830 | * @param string $name Name of template file in the /src/Template/Element/ folder, |
||
831 | * or `MyPlugin.template` to check the template element from MyPlugin. If the element |
||
832 | * is not found in the plugin, the normal view path cascade will be searched. |
||
833 | * @return bool Success |
||
834 | */ |
||
835 | public function elementExists($name) |
||
836 | { |
||
837 | return (bool)$this->_getElementFileName($name); |
||
838 | } |
||
839 | |||
840 | /** |
||
841 | * Renders view for given template file and layout. |
||
842 | * |
||
843 | * Render triggers helper callbacks, which are fired before and after the template are rendered, |
||
844 | * as well as before and after the layout. The helper callbacks are called: |
||
845 | * |
||
846 | * - `beforeRender` |
||
847 | * - `afterRender` |
||
848 | * - `beforeLayout` |
||
849 | * - `afterLayout` |
||
850 | * |
||
851 | * If View::$autoRender is false and no `$layout` is provided, the template will be returned bare. |
||
852 | * |
||
853 | * Template and layout names can point to plugin templates/layouts. Using the `Plugin.template` syntax |
||
854 | * a plugin template/layout can be used instead of the app ones. If the chosen plugin is not found |
||
855 | * the template will be located along the regular view path cascade. |
||
856 | * |
||
857 | * @param string|false|null $view Name of view file to use |
||
858 | * @param string|null $layout Layout to use. |
||
859 | * @return string|null Rendered content or null if content already rendered and returned earlier. |
||
860 | * @throws \Cake\Core\Exception\Exception If there is an error in the view. |
||
861 | * @triggers View.beforeRender $this, [$viewFileName] |
||
862 | * @triggers View.afterRender $this, [$viewFileName] |
||
863 | */ |
||
864 | public function render($view = null, $layout = null) |
||
865 | { |
||
866 | if ($this->hasRendered) { |
||
867 | return null; |
||
868 | } |
||
869 | |||
870 | $defaultLayout = null; |
||
871 | if ($layout !== null) { |
||
872 | $defaultLayout = $this->layout; |
||
873 | $this->layout = $layout; |
||
874 | } |
||
875 | |||
876 | $viewFileName = $view !== false ? $this->_getViewFileName($view) : null; |
||
877 | if ($viewFileName) { |
||
878 | $this->_currentType = static::TYPE_TEMPLATE; |
||
879 | $this->dispatchEvent('View.beforeRender', [$viewFileName]); |
||
880 | $this->Blocks->set('content', $this->_render($viewFileName)); |
||
881 | $this->dispatchEvent('View.afterRender', [$viewFileName]); |
||
882 | } |
||
883 | |||
884 | if ($this->layout && $this->autoLayout) { |
||
885 | $this->Blocks->set('content', $this->renderLayout('', $this->layout)); |
||
886 | } |
||
887 | if ($layout !== null) { |
||
888 | $this->layout = $defaultLayout; |
||
889 | } |
||
890 | |||
891 | $this->hasRendered = true; |
||
892 | |||
893 | return $this->Blocks->get('content'); |
||
894 | } |
||
895 | |||
896 | /** |
||
897 | * Renders a layout. Returns output from _render(). Returns false on error. |
||
898 | * Several variables are created for use in layout. |
||
899 | * |
||
900 | * @param string $content Content to render in a template, wrapped by the surrounding layout. |
||
901 | * @param string|null $layout Layout name |
||
902 | * @return mixed Rendered output, or false on error |
||
903 | * @throws \Cake\Core\Exception\Exception if there is an error in the view. |
||
904 | * @triggers View.beforeLayout $this, [$layoutFileName] |
||
905 | * @triggers View.afterLayout $this, [$layoutFileName] |
||
906 | */ |
||
907 | public function renderLayout($content, $layout = null) |
||
908 | { |
||
909 | $layoutFileName = $this->_getLayoutFileName($layout); |
||
910 | if (empty($layoutFileName)) { |
||
911 | return $this->Blocks->get('content'); |
||
912 | } |
||
913 | |||
914 | if (!empty($content)) { |
||
915 | $this->Blocks->set('content', $content); |
||
916 | } |
||
917 | |||
918 | $this->dispatchEvent('View.beforeLayout', [$layoutFileName]); |
||
919 | |||
920 | $title = $this->Blocks->get('title'); |
||
921 | if ($title === '') { |
||
922 | $title = Inflector::humanize($this->templatePath); |
||
923 | $this->Blocks->set('title', $title); |
||
924 | } |
||
925 | |||
926 | $this->_currentType = static::TYPE_LAYOUT; |
||
927 | $this->Blocks->set('content', $this->_render($layoutFileName)); |
||
928 | |||
929 | $this->dispatchEvent('View.afterLayout', [$layoutFileName]); |
||
930 | |||
931 | return $this->Blocks->get('content'); |
||
932 | } |
||
933 | |||
934 | /** |
||
935 | * Returns a list of variables available in the current View context |
||
936 | * |
||
937 | * @return string[] Array of the set view variable names. |
||
938 | */ |
||
939 | public function getVars() |
||
940 | { |
||
941 | return array_keys($this->viewVars); |
||
0 ignored issues
–
show
|
|||
942 | } |
||
943 | |||
944 | /** |
||
945 | * Returns the contents of the given View variable. |
||
946 | * |
||
947 | * @param string $var The view var you want the contents of. |
||
948 | * @param mixed $default The default/fallback content of $var. |
||
949 | * @return mixed The content of the named var if its set, otherwise $default. |
||
950 | */ |
||
951 | public function get($var, $default = null) |
||
952 | { |
||
953 | if (!isset($this->viewVars[$var])) { |
||
0 ignored issues
–
show
The property
Cake\View\ViewVarsTrait::$viewVars has been deprecated with message: 3.7.0 Use `$this->set()` instead, also see `$this->viewBuilder()->getVar()`.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
954 | return $default; |
||
955 | } |
||
956 | |||
957 | return $this->viewVars[$var]; |
||
0 ignored issues
–
show
The property
Cake\View\ViewVarsTrait::$viewVars has been deprecated with message: 3.7.0 Use `$this->set()` instead, also see `$this->viewBuilder()->getVar()`.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
958 | } |
||
959 | |||
960 | /** |
||
961 | * Get the names of all the existing blocks. |
||
962 | * |
||
963 | * @return array An array containing the blocks. |
||
964 | * @see \Cake\View\ViewBlock::keys() |
||
965 | */ |
||
966 | public function blocks() |
||
967 | { |
||
968 | return $this->Blocks->keys(); |
||
969 | } |
||
970 | |||
971 | /** |
||
972 | * Start capturing output for a 'block' |
||
973 | * |
||
974 | * You can use start on a block multiple times to |
||
975 | * append or prepend content in a capture mode. |
||
976 | * |
||
977 | * ``` |
||
978 | * // Append content to an existing block. |
||
979 | * $this->start('content'); |
||
980 | * echo $this->fetch('content'); |
||
981 | * echo 'Some new content'; |
||
982 | * $this->end(); |
||
983 | * |
||
984 | * // Prepend content to an existing block |
||
985 | * $this->start('content'); |
||
986 | * echo 'Some new content'; |
||
987 | * echo $this->fetch('content'); |
||
988 | * $this->end(); |
||
989 | * ``` |
||
990 | * |
||
991 | * @param string $name The name of the block to capture for. |
||
992 | * @return $this |
||
993 | * @see \Cake\View\ViewBlock::start() |
||
994 | */ |
||
995 | public function start($name) |
||
996 | { |
||
997 | $this->Blocks->start($name); |
||
998 | |||
999 | return $this; |
||
1000 | } |
||
1001 | |||
1002 | /** |
||
1003 | * Append to an existing or new block. |
||
1004 | * |
||
1005 | * Appending to a new block will create the block. |
||
1006 | * |
||
1007 | * @param string $name Name of the block |
||
1008 | * @param mixed $value The content for the block. Value will be type cast |
||
1009 | * to string. |
||
1010 | * @return $this |
||
1011 | * @see \Cake\View\ViewBlock::concat() |
||
1012 | */ |
||
1013 | public function append($name, $value = null) |
||
1014 | { |
||
1015 | $this->Blocks->concat($name, $value); |
||
1016 | |||
1017 | return $this; |
||
1018 | } |
||
1019 | |||
1020 | /** |
||
1021 | * Prepend to an existing or new block. |
||
1022 | * |
||
1023 | * Prepending to a new block will create the block. |
||
1024 | * |
||
1025 | * @param string $name Name of the block |
||
1026 | * @param mixed $value The content for the block. Value will be type cast |
||
1027 | * to string. |
||
1028 | * @return $this |
||
1029 | * @see \Cake\View\ViewBlock::concat() |
||
1030 | */ |
||
1031 | public function prepend($name, $value) |
||
1032 | { |
||
1033 | $this->Blocks->concat($name, $value, ViewBlock::PREPEND); |
||
1034 | |||
1035 | return $this; |
||
1036 | } |
||
1037 | |||
1038 | /** |
||
1039 | * Set the content for a block. This will overwrite any |
||
1040 | * existing content. |
||
1041 | * |
||
1042 | * @param string $name Name of the block |
||
1043 | * @param mixed $value The content for the block. Value will be type cast |
||
1044 | * to string. |
||
1045 | * @return $this |
||
1046 | * @see \Cake\View\ViewBlock::set() |
||
1047 | */ |
||
1048 | public function assign($name, $value) |
||
1049 | { |
||
1050 | $this->Blocks->set($name, $value); |
||
1051 | |||
1052 | return $this; |
||
1053 | } |
||
1054 | |||
1055 | /** |
||
1056 | * Reset the content for a block. This will overwrite any |
||
1057 | * existing content. |
||
1058 | * |
||
1059 | * @param string $name Name of the block |
||
1060 | * @return $this |
||
1061 | * @see \Cake\View\ViewBlock::set() |
||
1062 | */ |
||
1063 | public function reset($name) |
||
1064 | { |
||
1065 | $this->assign($name, ''); |
||
1066 | |||
1067 | return $this; |
||
1068 | } |
||
1069 | |||
1070 | /** |
||
1071 | * Fetch the content for a block. If a block is |
||
1072 | * empty or undefined '' will be returned. |
||
1073 | * |
||
1074 | * @param string $name Name of the block |
||
1075 | * @param string $default Default text |
||
1076 | * @return string The block content or $default if the block does not exist. |
||
1077 | * @see \Cake\View\ViewBlock::get() |
||
1078 | */ |
||
1079 | public function fetch($name, $default = '') |
||
1080 | { |
||
1081 | return $this->Blocks->get($name, $default); |
||
1082 | } |
||
1083 | |||
1084 | /** |
||
1085 | * End a capturing block. The compliment to View::start() |
||
1086 | * |
||
1087 | * @return $this |
||
1088 | * @see \Cake\View\ViewBlock::end() |
||
1089 | */ |
||
1090 | public function end() |
||
1091 | { |
||
1092 | $this->Blocks->end(); |
||
1093 | |||
1094 | return $this; |
||
1095 | } |
||
1096 | |||
1097 | /** |
||
1098 | * Check if a block exists |
||
1099 | * |
||
1100 | * @param string $name Name of the block |
||
1101 | * |
||
1102 | * @return bool |
||
1103 | */ |
||
1104 | public function exists($name) |
||
1105 | { |
||
1106 | return $this->Blocks->exists($name); |
||
1107 | } |
||
1108 | |||
1109 | /** |
||
1110 | * Provides template or element extension/inheritance. Views can extends a |
||
1111 | * parent view and populate blocks in the parent template. |
||
1112 | * |
||
1113 | * @param string $name The template or element to 'extend' the current one with. |
||
1114 | * @return $this |
||
1115 | * @throws \LogicException when you extend a template with itself or make extend loops. |
||
1116 | * @throws \LogicException when you extend an element which doesn't exist |
||
1117 | */ |
||
1118 | public function extend($name) |
||
1119 | { |
||
1120 | if ($name[0] === '/' || $this->_currentType === static::TYPE_TEMPLATE) { |
||
1121 | $parent = $this->_getViewFileName($name); |
||
1122 | } else { |
||
1123 | switch ($this->_currentType) { |
||
1124 | case static::TYPE_ELEMENT: |
||
1125 | $parent = $this->_getElementFileName($name); |
||
1126 | if (!$parent) { |
||
1127 | list($plugin, $name) = $this->pluginSplit($name); |
||
1128 | $paths = $this->_paths($plugin); |
||
1129 | $defaultPath = $paths[0] . static::NAME_ELEMENT . DIRECTORY_SEPARATOR; |
||
1130 | throw new LogicException(sprintf( |
||
1131 | 'You cannot extend an element which does not exist (%s).', |
||
1132 | $defaultPath . $name . $this->_ext |
||
1133 | )); |
||
1134 | } |
||
1135 | break; |
||
1136 | case static::TYPE_LAYOUT: |
||
1137 | $parent = $this->_getLayoutFileName($name); |
||
1138 | break; |
||
1139 | default: |
||
1140 | $parent = $this->_getViewFileName($name); |
||
1141 | } |
||
1142 | } |
||
1143 | |||
1144 | if ($parent == $this->_current) { |
||
1145 | throw new LogicException('You cannot have views extend themselves.'); |
||
1146 | } |
||
1147 | if (isset($this->_parents[$parent]) && $this->_parents[$parent] == $this->_current) { |
||
1148 | throw new LogicException('You cannot have views extend in a loop.'); |
||
1149 | } |
||
1150 | $this->_parents[$this->_current] = $parent; |
||
1151 | |||
1152 | return $this; |
||
1153 | } |
||
1154 | |||
1155 | /** |
||
1156 | * Generates a unique, non-random DOM ID for an object, based on the object type and the target URL. |
||
1157 | * |
||
1158 | * @param string $object Type of object, i.e. 'form' or 'link' |
||
1159 | * @param string $url The object's target URL |
||
1160 | * @return string |
||
1161 | * @deprecated 3.7.0 This method is deprecated and will be removed in 4.0.0. |
||
1162 | */ |
||
1163 | public function uuid($object, $url) |
||
1164 | { |
||
1165 | deprecationWarning('View::uuid() is deprecated and will be removed in 4.0.0.'); |
||
1166 | |||
1167 | $c = 1; |
||
1168 | $url = Router::url($url); |
||
1169 | $hash = $object . substr(md5($object . $url), 0, 10); |
||
1170 | while (in_array($hash, $this->uuids)) { |
||
1171 | $hash = $object . substr(md5($object . $url . $c), 0, 10); |
||
1172 | $c++; |
||
1173 | } |
||
1174 | $this->uuids[] = $hash; |
||
1175 | |||
1176 | return $hash; |
||
1177 | } |
||
1178 | |||
1179 | /** |
||
1180 | * Retrieve the current view type |
||
1181 | * |
||
1182 | * @return string |
||
1183 | */ |
||
1184 | public function getCurrentType() |
||
1185 | { |
||
1186 | return $this->_currentType; |
||
1187 | } |
||
1188 | |||
1189 | /** |
||
1190 | * Magic accessor for helpers. |
||
1191 | * |
||
1192 | * @param string $name Name of the attribute to get. |
||
1193 | * @return mixed |
||
1194 | */ |
||
1195 | public function __get($name) |
||
1196 | { |
||
1197 | try { |
||
1198 | $registry = $this->helpers(); |
||
1199 | if (isset($registry->{$name})) { |
||
1200 | $this->{$name} = $registry->{$name}; |
||
1201 | |||
1202 | return $registry->{$name}; |
||
1203 | } |
||
1204 | } catch (MissingHelperException $exception) { |
||
1205 | } |
||
1206 | |||
1207 | $deprecated = [ |
||
1208 | 'view' => 'getTemplate', |
||
1209 | 'viewPath' => 'getTemplatePath', |
||
1210 | ]; |
||
1211 | if (isset($deprecated[$name])) { |
||
1212 | $method = $deprecated[$name]; |
||
1213 | deprecationWarning(sprintf( |
||
1214 | 'View::$%s is deprecated. Use View::%s() instead.', |
||
1215 | $name, |
||
1216 | $method |
||
1217 | )); |
||
1218 | |||
1219 | return $this->{$method}(); |
||
1220 | } |
||
1221 | |||
1222 | $protected = [ |
||
1223 | 'templatePath' => 'getTemplatePath', |
||
1224 | 'template' => 'getTemplate', |
||
1225 | 'layout' => 'getLayout', |
||
1226 | 'layoutPath' => 'setLayoutPath', |
||
1227 | 'autoLayout' => 'isAutoLayoutEnabled', |
||
1228 | 'theme' => 'getTheme', |
||
1229 | 'request' => 'getRequest', |
||
1230 | 'response' => 'getResponse', |
||
1231 | 'subDir' => 'getSubdir', |
||
1232 | 'plugin' => 'getPlugin', |
||
1233 | 'name' => 'getName', |
||
1234 | ]; |
||
1235 | if (isset($protected[$name])) { |
||
1236 | $method = $protected[$name]; |
||
1237 | deprecationWarning(sprintf( |
||
1238 | 'View::$%s is protected now. Use View::%s() instead.', |
||
1239 | $name, |
||
1240 | $method |
||
1241 | )); |
||
1242 | |||
1243 | return $this->{$method}(); |
||
1244 | } |
||
1245 | |||
1246 | if ($name === 'Blocks') { |
||
1247 | deprecationWarning( |
||
1248 | 'View::$Blocks is protected now. ' . |
||
1249 | 'Use one of the wrapper methods like View::fetch() etc. instead.' |
||
1250 | ); |
||
1251 | |||
1252 | return $this->Blocks; |
||
1253 | } |
||
1254 | |||
1255 | if ($name === 'helpers') { |
||
1256 | deprecationWarning( |
||
1257 | 'View::$helpers is protected now. ' . |
||
1258 | 'Use the helper registry through View::helpers() to manage helpers.' |
||
1259 | ); |
||
1260 | |||
1261 | return $this->helpers; |
||
1262 | } |
||
1263 | |||
1264 | if (!empty($exception)) { |
||
1265 | throw $exception; |
||
1266 | } |
||
1267 | |||
1268 | return $this->{$name}; |
||
1269 | } |
||
1270 | |||
1271 | /** |
||
1272 | * Magic setter for deprecated properties. |
||
1273 | * |
||
1274 | * @param string $name Name to property. |
||
1275 | * @param mixed $value Value for property. |
||
1276 | * @return void |
||
1277 | */ |
||
1278 | public function __set($name, $value) |
||
1279 | { |
||
1280 | $deprecated = [ |
||
1281 | 'view' => 'setTemplate', |
||
1282 | 'viewPath' => 'setTemplatePath', |
||
1283 | ]; |
||
1284 | if (isset($deprecated[$name])) { |
||
1285 | $method = $deprecated[$name]; |
||
1286 | deprecationWarning(sprintf( |
||
1287 | 'View::$%s is deprecated. Use View::%s() instead.', |
||
1288 | $name, |
||
1289 | $method |
||
1290 | )); |
||
1291 | |||
1292 | $this->{$method}($value); |
||
1293 | |||
1294 | return; |
||
1295 | } |
||
1296 | |||
1297 | $protected = [ |
||
1298 | 'templatePath' => 'setTemplatePath', |
||
1299 | 'template' => 'setTemplate', |
||
1300 | 'layout' => 'setLayout', |
||
1301 | 'layoutPath' => 'setLayoutPath', |
||
1302 | 'autoLayout' => 'enableAutoLayout', |
||
1303 | 'theme' => 'setTheme', |
||
1304 | 'request' => 'setRequest', |
||
1305 | 'response' => 'setResponse', |
||
1306 | 'subDir' => 'setSubDir', |
||
1307 | 'plugin' => 'setPlugin', |
||
1308 | 'name' => 'setName', |
||
1309 | 'elementCache' => 'setElementCache', |
||
1310 | ]; |
||
1311 | if (isset($protected[$name])) { |
||
1312 | $method = $protected[$name]; |
||
1313 | deprecationWarning(sprintf( |
||
1314 | 'View::$%s is protected now. Use View::%s() instead.', |
||
1315 | $name, |
||
1316 | $method |
||
1317 | )); |
||
1318 | |||
1319 | $this->{$method}($value); |
||
1320 | |||
1321 | return; |
||
1322 | } |
||
1323 | |||
1324 | if ($name === 'helpers') { |
||
1325 | deprecationWarning( |
||
1326 | 'View::$helpers is protected now. ' . |
||
1327 | 'Use the helper registry through View::helpers() to manage helpers.' |
||
1328 | ); |
||
1329 | |||
1330 | return $this->helpers = $value; |
||
1331 | } |
||
1332 | |||
1333 | $this->{$name} = $value; |
||
1334 | } |
||
1335 | |||
1336 | /** |
||
1337 | * Interact with the HelperRegistry to load all the helpers. |
||
1338 | * |
||
1339 | * @return $this |
||
1340 | */ |
||
1341 | public function loadHelpers() |
||
1342 | { |
||
1343 | $registry = $this->helpers(); |
||
1344 | $helpers = $registry->normalizeArray($this->helpers); |
||
1345 | foreach ($helpers as $properties) { |
||
1346 | $this->loadHelper($properties['class'], $properties['config']); |
||
1347 | } |
||
1348 | |||
1349 | return $this; |
||
1350 | } |
||
1351 | |||
1352 | /** |
||
1353 | * Renders and returns output for given template filename with its |
||
1354 | * array of data. Handles parent/extended templates. |
||
1355 | * |
||
1356 | * @param string $viewFile Filename of the view |
||
1357 | * @param array $data Data to include in rendered view. If empty the current |
||
1358 | * View::$viewVars will be used. |
||
1359 | * @return string Rendered output |
||
1360 | * @throws \LogicException When a block is left open. |
||
1361 | * @triggers View.beforeRenderFile $this, [$viewFile] |
||
1362 | * @triggers View.afterRenderFile $this, [$viewFile, $content] |
||
1363 | */ |
||
1364 | protected function _render($viewFile, $data = []) |
||
1365 | { |
||
1366 | if (empty($data)) { |
||
1367 | $data = $this->viewVars; |
||
0 ignored issues
–
show
The property
Cake\View\ViewVarsTrait::$viewVars has been deprecated with message: 3.7.0 Use `$this->set()` instead, also see `$this->viewBuilder()->getVar()`.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
1368 | } |
||
1369 | $this->_current = $viewFile; |
||
1370 | $initialBlocks = count($this->Blocks->unclosed()); |
||
1371 | |||
1372 | $this->dispatchEvent('View.beforeRenderFile', [$viewFile]); |
||
1373 | |||
1374 | $content = $this->_evaluate($viewFile, $data); |
||
1375 | |||
1376 | $afterEvent = $this->dispatchEvent('View.afterRenderFile', [$viewFile, $content]); |
||
1377 | if ($afterEvent->getResult() !== null) { |
||
1378 | $content = $afterEvent->getResult(); |
||
1379 | } |
||
1380 | |||
1381 | if (isset($this->_parents[$viewFile])) { |
||
1382 | $this->_stack[] = $this->fetch('content'); |
||
1383 | $this->assign('content', $content); |
||
1384 | |||
1385 | $content = $this->_render($this->_parents[$viewFile]); |
||
1386 | $this->assign('content', array_pop($this->_stack)); |
||
1387 | } |
||
1388 | |||
1389 | $remainingBlocks = count($this->Blocks->unclosed()); |
||
1390 | |||
1391 | if ($initialBlocks !== $remainingBlocks) { |
||
1392 | throw new LogicException(sprintf( |
||
1393 | 'The "%s" block was left open. Blocks are not allowed to cross files.', |
||
1394 | $this->Blocks->active() |
||
1395 | )); |
||
1396 | } |
||
1397 | |||
1398 | return $content; |
||
1399 | } |
||
1400 | |||
1401 | /** |
||
1402 | * Sandbox method to evaluate a template / view script in. |
||
1403 | * |
||
1404 | * @param string $viewFile Filename of the view |
||
1405 | * @param array $dataForView Data to include in rendered view. |
||
1406 | * @return string Rendered output |
||
1407 | */ |
||
1408 | protected function _evaluate($viewFile, $dataForView) |
||
1409 | { |
||
1410 | extract($dataForView); |
||
1411 | ob_start(); |
||
1412 | |||
1413 | include func_get_arg(0); |
||
1414 | |||
1415 | return ob_get_clean(); |
||
1416 | } |
||
1417 | |||
1418 | /** |
||
1419 | * Get the helper registry in use by this View class. |
||
1420 | * |
||
1421 | * @return \Cake\View\HelperRegistry |
||
1422 | */ |
||
1423 | public function helpers() |
||
1424 | { |
||
1425 | if ($this->_helpers === null) { |
||
1426 | $this->_helpers = new HelperRegistry($this); |
||
1427 | } |
||
1428 | |||
1429 | return $this->_helpers; |
||
1430 | } |
||
1431 | |||
1432 | /** |
||
1433 | * Loads a helper. Delegates to the `HelperRegistry::load()` to load the helper |
||
1434 | * |
||
1435 | * @param string $name Name of the helper to load. |
||
1436 | * @param array $config Settings for the helper |
||
1437 | * @return \Cake\View\Helper a constructed helper object. |
||
1438 | * @see \Cake\View\HelperRegistry::load() |
||
1439 | */ |
||
1440 | public function loadHelper($name, array $config = []) |
||
1441 | { |
||
1442 | list(, $class) = pluginSplit($name); |
||
1443 | $helpers = $this->helpers(); |
||
1444 | |||
1445 | return $this->{$class} = $helpers->load($name, $config); |
||
1446 | } |
||
1447 | |||
1448 | /** |
||
1449 | * Set sub-directory for this template files. |
||
1450 | * |
||
1451 | * @param string $subDir Sub-directory name. |
||
1452 | * @return $this |
||
1453 | * @see \Cake\View\View::$subDir |
||
1454 | * @since 3.7.0 |
||
1455 | */ |
||
1456 | public function setSubDir($subDir) |
||
1457 | { |
||
1458 | $this->subDir = $subDir; |
||
1459 | |||
1460 | return $this; |
||
1461 | } |
||
1462 | |||
1463 | /** |
||
1464 | * Get sub-directory for this template files. |
||
1465 | * |
||
1466 | * @return string |
||
1467 | * @see \Cake\View\View::$subDir |
||
1468 | * @since 3.7.0 |
||
1469 | */ |
||
1470 | public function getSubDir() |
||
1471 | { |
||
1472 | return $this->subDir; |
||
1473 | } |
||
1474 | |||
1475 | /** |
||
1476 | * Returns the plugin name. |
||
1477 | * |
||
1478 | * @return string|null |
||
1479 | * @since 3.7.0 |
||
1480 | */ |
||
1481 | public function getPlugin() |
||
1482 | { |
||
1483 | return $this->plugin; |
||
1484 | } |
||
1485 | |||
1486 | /** |
||
1487 | * Sets the plugin name. |
||
1488 | * |
||
1489 | * @param string $name Plugin name. |
||
1490 | * @return $this |
||
1491 | * @since 3.7.0 |
||
1492 | */ |
||
1493 | public function setPlugin($name) |
||
1494 | { |
||
1495 | $this->plugin = $name; |
||
1496 | |||
1497 | return $this; |
||
1498 | } |
||
1499 | |||
1500 | /** |
||
1501 | * Set The cache configuration View will use to store cached elements |
||
1502 | * |
||
1503 | * @param string $elementCache Cache config name. |
||
1504 | * @return $this |
||
1505 | * @see \Cake\View\View::$elementCache |
||
1506 | * @since 3.7.0 |
||
1507 | */ |
||
1508 | public function setElementCache($elementCache) |
||
1509 | { |
||
1510 | $this->elementCache = $elementCache; |
||
1511 | |||
1512 | return $this; |
||
1513 | } |
||
1514 | |||
1515 | /** |
||
1516 | * Returns filename of given action's template file (.ctp) as a string. |
||
1517 | * CamelCased action names will be under_scored by default. |
||
1518 | * This means that you can have LongActionNames that refer to |
||
1519 | * long_action_names.ctp views. You can change the inflection rule by |
||
1520 | * overriding _inflectViewFileName. |
||
1521 | * |
||
1522 | * @param string|null $name Controller action to find template filename for |
||
1523 | * @return string Template filename |
||
1524 | * @throws \Cake\View\Exception\MissingTemplateException when a view file could not be found. |
||
1525 | */ |
||
1526 | protected function _getViewFileName($name = null) |
||
1527 | { |
||
1528 | $templatePath = $subDir = ''; |
||
1529 | |||
1530 | if ($this->templatePath) { |
||
1531 | $templatePath = $this->templatePath . DIRECTORY_SEPARATOR; |
||
1532 | } |
||
1533 | if (strlen($this->subDir)) { |
||
1534 | $subDir = $this->subDir . DIRECTORY_SEPARATOR; |
||
1535 | // Check if templatePath already terminates with subDir |
||
1536 | if ($templatePath != $subDir && substr($templatePath, -strlen($subDir)) == $subDir) { |
||
1537 | $subDir = ''; |
||
1538 | } |
||
1539 | } |
||
1540 | |||
1541 | if ($name === null) { |
||
1542 | $name = $this->template; |
||
1543 | } |
||
1544 | |||
1545 | list($plugin, $name) = $this->pluginSplit($name); |
||
1546 | $name = str_replace('/', DIRECTORY_SEPARATOR, $name); |
||
1547 | |||
1548 | if (strpos($name, DIRECTORY_SEPARATOR) === false && $name !== '' && $name[0] !== '.') { |
||
1549 | $name = $templatePath . $subDir . $this->_inflectViewFileName($name); |
||
1550 | } elseif (strpos($name, DIRECTORY_SEPARATOR) !== false) { |
||
1551 | if ($name[0] === DIRECTORY_SEPARATOR || $name[1] === ':') { |
||
1552 | $name = trim($name, DIRECTORY_SEPARATOR); |
||
1553 | } elseif (!$plugin || $this->templatePath !== $this->name) { |
||
1554 | $name = $templatePath . $subDir . $name; |
||
1555 | } else { |
||
1556 | $name = DIRECTORY_SEPARATOR . $subDir . $name; |
||
1557 | } |
||
1558 | } |
||
1559 | |||
1560 | foreach ($this->_paths($plugin) as $path) { |
||
1561 | View Code Duplication | if (file_exists($path . $name . $this->_ext)) { |
|
1562 | return $this->_checkFilePath($path . $name . $this->_ext, $path); |
||
1563 | } |
||
1564 | } |
||
1565 | throw new MissingTemplateException(['file' => $name . $this->_ext]); |
||
1566 | } |
||
1567 | |||
1568 | /** |
||
1569 | * Change the name of a view template file into underscored format. |
||
1570 | * |
||
1571 | * @param string $name Name of file which should be inflected. |
||
1572 | * @return string File name after conversion |
||
1573 | */ |
||
1574 | protected function _inflectViewFileName($name) |
||
1575 | { |
||
1576 | return Inflector::underscore($name); |
||
1577 | } |
||
1578 | |||
1579 | /** |
||
1580 | * Check that a view file path does not go outside of the defined template paths. |
||
1581 | * |
||
1582 | * Only paths that contain `..` will be checked, as they are the ones most likely to |
||
1583 | * have the ability to resolve to files outside of the template paths. |
||
1584 | * |
||
1585 | * @param string $file The path to the template file. |
||
1586 | * @param string $path Base path that $file should be inside of. |
||
1587 | * @return string The file path |
||
1588 | * @throws \InvalidArgumentException |
||
1589 | */ |
||
1590 | protected function _checkFilePath($file, $path) |
||
1591 | { |
||
1592 | if (strpos($file, '..') === false) { |
||
1593 | return $file; |
||
1594 | } |
||
1595 | $absolute = realpath($file); |
||
1596 | if (strpos($absolute, $path) !== 0) { |
||
1597 | throw new InvalidArgumentException(sprintf( |
||
1598 | 'Cannot use "%s" as a template, it is not within any view template path.', |
||
1599 | $file |
||
1600 | )); |
||
1601 | } |
||
1602 | |||
1603 | return $absolute; |
||
1604 | } |
||
1605 | |||
1606 | /** |
||
1607 | * Splits a dot syntax plugin name into its plugin and filename. |
||
1608 | * If $name does not have a dot, then index 0 will be null. |
||
1609 | * It checks if the plugin is loaded, else filename will stay unchanged for filenames containing dot |
||
1610 | * |
||
1611 | * @param string $name The name you want to plugin split. |
||
1612 | * @param bool $fallback If true uses the plugin set in the current Request when parsed plugin is not loaded |
||
1613 | * @return array Array with 2 indexes. 0 => plugin name, 1 => filename |
||
1614 | */ |
||
1615 | public function pluginSplit($name, $fallback = true) |
||
1616 | { |
||
1617 | $plugin = null; |
||
1618 | list($first, $second) = pluginSplit($name); |
||
1619 | if (Plugin::isLoaded($first) === true) { |
||
1620 | $name = $second; |
||
1621 | $plugin = $first; |
||
1622 | } |
||
1623 | if (isset($this->plugin) && !$plugin && $fallback) { |
||
1624 | $plugin = $this->plugin; |
||
1625 | } |
||
1626 | |||
1627 | return [$plugin, $name]; |
||
1628 | } |
||
1629 | |||
1630 | /** |
||
1631 | * Returns layout filename for this template as a string. |
||
1632 | * |
||
1633 | * @param string|null $name The name of the layout to find. |
||
1634 | * @return string Filename for layout file (.ctp). |
||
1635 | * @throws \Cake\View\Exception\MissingLayoutException when a layout cannot be located |
||
1636 | */ |
||
1637 | protected function _getLayoutFileName($name = null) |
||
1638 | { |
||
1639 | if ($name === null) { |
||
1640 | $name = $this->layout; |
||
1641 | } |
||
1642 | $subDir = null; |
||
1643 | |||
1644 | if ($this->layoutPath) { |
||
1645 | $subDir = $this->layoutPath . DIRECTORY_SEPARATOR; |
||
1646 | } |
||
1647 | list($plugin, $name) = $this->pluginSplit($name); |
||
1648 | |||
1649 | $layoutPaths = $this->_getSubPaths('Layout' . DIRECTORY_SEPARATOR . $subDir); |
||
1650 | |||
1651 | foreach ($this->_paths($plugin) as $path) { |
||
1652 | foreach ($layoutPaths as $layoutPath) { |
||
1653 | $currentPath = $path . $layoutPath; |
||
1654 | View Code Duplication | if (file_exists($currentPath . $name . $this->_ext)) { |
|
1655 | return $this->_checkFilePath($currentPath . $name . $this->_ext, $currentPath); |
||
1656 | } |
||
1657 | } |
||
1658 | } |
||
1659 | throw new MissingLayoutException([ |
||
1660 | 'file' => $layoutPaths[0] . $name . $this->_ext |
||
1661 | ]); |
||
1662 | } |
||
1663 | |||
1664 | /** |
||
1665 | * Finds an element filename, returns false on failure. |
||
1666 | * |
||
1667 | * @param string $name The name of the element to find. |
||
1668 | * @param bool $pluginCheck - if false will ignore the request's plugin if parsed plugin is not loaded |
||
1669 | * @return string|false Either a string to the element filename or false when one can't be found. |
||
1670 | */ |
||
1671 | protected function _getElementFileName($name, $pluginCheck = true) |
||
1672 | { |
||
1673 | list($plugin, $name) = $this->pluginSplit($name, $pluginCheck); |
||
1674 | |||
1675 | $paths = $this->_paths($plugin); |
||
1676 | $elementPaths = $this->_getSubPaths(static::NAME_ELEMENT); |
||
1677 | |||
1678 | foreach ($paths as $path) { |
||
1679 | foreach ($elementPaths as $elementPath) { |
||
1680 | if (file_exists($path . $elementPath . DIRECTORY_SEPARATOR . $name . $this->_ext)) { |
||
1681 | return $path . $elementPath . DIRECTORY_SEPARATOR . $name . $this->_ext; |
||
1682 | } |
||
1683 | } |
||
1684 | } |
||
1685 | |||
1686 | return false; |
||
1687 | } |
||
1688 | |||
1689 | /** |
||
1690 | * Find all sub templates path, based on $basePath |
||
1691 | * If a prefix is defined in the current request, this method will prepend |
||
1692 | * the prefixed template path to the $basePath, cascading up in case the prefix |
||
1693 | * is nested. |
||
1694 | * This is essentially used to find prefixed template paths for elements |
||
1695 | * and layouts. |
||
1696 | * |
||
1697 | * @param string $basePath Base path on which to get the prefixed one. |
||
1698 | * @return array Array with all the templates paths. |
||
1699 | */ |
||
1700 | protected function _getSubPaths($basePath) |
||
1701 | { |
||
1702 | $paths = [$basePath]; |
||
1703 | if ($this->request->getParam('prefix')) { |
||
1704 | $prefixPath = explode('/', $this->request->getParam('prefix')); |
||
1705 | $path = ''; |
||
1706 | foreach ($prefixPath as $prefixPart) { |
||
1707 | $path .= Inflector::camelize($prefixPart) . DIRECTORY_SEPARATOR; |
||
1708 | |||
1709 | array_unshift( |
||
1710 | $paths, |
||
1711 | $path . $basePath |
||
1712 | ); |
||
1713 | } |
||
1714 | } |
||
1715 | |||
1716 | return $paths; |
||
1717 | } |
||
1718 | |||
1719 | /** |
||
1720 | * Return all possible paths to find view files in order |
||
1721 | * |
||
1722 | * @param string|null $plugin Optional plugin name to scan for view files. |
||
1723 | * @param bool $cached Set to false to force a refresh of view paths. Default true. |
||
1724 | * @return array paths |
||
1725 | */ |
||
1726 | protected function _paths($plugin = null, $cached = true) |
||
1727 | { |
||
1728 | if ($cached === true) { |
||
1729 | if ($plugin === null && !empty($this->_paths)) { |
||
1730 | return $this->_paths; |
||
1731 | } |
||
1732 | if ($plugin !== null && isset($this->_pathsForPlugin[$plugin])) { |
||
1733 | return $this->_pathsForPlugin[$plugin]; |
||
1734 | } |
||
1735 | } |
||
1736 | $templatePaths = App::path(static::NAME_TEMPLATE); |
||
1737 | $pluginPaths = $themePaths = []; |
||
1738 | if (!empty($plugin)) { |
||
1739 | View Code Duplication | for ($i = 0, $count = count($templatePaths); $i < $count; $i++) { |
|
1740 | $pluginPaths[] = $templatePaths[$i] . 'Plugin' . DIRECTORY_SEPARATOR . $plugin . DIRECTORY_SEPARATOR; |
||
1741 | } |
||
1742 | $pluginPaths = array_merge($pluginPaths, App::path(static::NAME_TEMPLATE, $plugin)); |
||
1743 | } |
||
1744 | |||
1745 | if (!empty($this->theme)) { |
||
1746 | $themePaths = App::path(static::NAME_TEMPLATE, Inflector::camelize($this->theme)); |
||
1747 | |||
1748 | if ($plugin) { |
||
1749 | View Code Duplication | for ($i = 0, $count = count($themePaths); $i < $count; $i++) { |
|
1750 | array_unshift($themePaths, $themePaths[$i] . 'Plugin' . DIRECTORY_SEPARATOR . $plugin . DIRECTORY_SEPARATOR); |
||
1751 | } |
||
1752 | } |
||
1753 | } |
||
1754 | |||
1755 | $paths = array_merge( |
||
1756 | $themePaths, |
||
1757 | $pluginPaths, |
||
1758 | $templatePaths, |
||
1759 | [dirname(__DIR__) . DIRECTORY_SEPARATOR . static::NAME_TEMPLATE . DIRECTORY_SEPARATOR] |
||
1760 | ); |
||
1761 | |||
1762 | if ($plugin !== null) { |
||
1763 | return $this->_pathsForPlugin[$plugin] = $paths; |
||
1764 | } |
||
1765 | |||
1766 | return $this->_paths = $paths; |
||
1767 | } |
||
1768 | |||
1769 | /** |
||
1770 | * Generate the cache configuration options for an element. |
||
1771 | * |
||
1772 | * @param string $name Element name |
||
1773 | * @param array $data Data |
||
1774 | * @param array $options Element options |
||
1775 | * @return array Element Cache configuration. |
||
1776 | */ |
||
1777 | protected function _elementCache($name, $data, $options) |
||
1778 | { |
||
1779 | if (isset($options['cache']['key'], $options['cache']['config'])) { |
||
1780 | $cache = $options['cache']; |
||
1781 | $cache['key'] = 'element_' . $cache['key']; |
||
1782 | |||
1783 | return $cache; |
||
1784 | } |
||
1785 | |||
1786 | $plugin = null; |
||
1787 | list($plugin, $name) = $this->pluginSplit($name); |
||
1788 | |||
1789 | $underscored = null; |
||
1790 | if ($plugin) { |
||
1791 | $underscored = Inflector::underscore($plugin); |
||
1792 | } |
||
1793 | |||
1794 | $cache = $options['cache']; |
||
1795 | unset($options['cache'], $options['callbacks'], $options['plugin']); |
||
1796 | $keys = array_merge( |
||
1797 | [$underscored, $name], |
||
1798 | array_keys($options), |
||
1799 | array_keys($data) |
||
1800 | ); |
||
1801 | $config = [ |
||
1802 | 'config' => $this->elementCache, |
||
1803 | 'key' => implode('_', $keys) |
||
1804 | ]; |
||
1805 | if (is_array($cache)) { |
||
1806 | $defaults = [ |
||
1807 | 'config' => $this->elementCache, |
||
1808 | 'key' => $config['key'] |
||
1809 | ]; |
||
1810 | $config = $cache + $defaults; |
||
1811 | } |
||
1812 | $config['key'] = 'element_' . $config['key']; |
||
1813 | |||
1814 | return $config; |
||
1815 | } |
||
1816 | |||
1817 | /** |
||
1818 | * Renders an element and fires the before and afterRender callbacks for it |
||
1819 | * and writes to the cache if a cache is used |
||
1820 | * |
||
1821 | * @param string $file Element file path |
||
1822 | * @param array $data Data to render |
||
1823 | * @param array $options Element options |
||
1824 | * @return string |
||
1825 | * @triggers View.beforeRender $this, [$file] |
||
1826 | * @triggers View.afterRender $this, [$file, $element] |
||
1827 | */ |
||
1828 | protected function _renderElement($file, $data, $options) |
||
1829 | { |
||
1830 | $current = $this->_current; |
||
1831 | $restore = $this->_currentType; |
||
1832 | $this->_currentType = static::TYPE_ELEMENT; |
||
1833 | |||
1834 | if ($options['callbacks']) { |
||
1835 | $this->dispatchEvent('View.beforeRender', [$file]); |
||
1836 | } |
||
1837 | |||
1838 | $element = $this->_render($file, array_merge($this->viewVars, $data)); |
||
0 ignored issues
–
show
The property
Cake\View\ViewVarsTrait::$viewVars has been deprecated with message: 3.7.0 Use `$this->set()` instead, also see `$this->viewBuilder()->getVar()`.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
1839 | |||
1840 | if ($options['callbacks']) { |
||
1841 | $this->dispatchEvent('View.afterRender', [$file, $element]); |
||
1842 | } |
||
1843 | |||
1844 | $this->_currentType = $restore; |
||
1845 | $this->_current = $current; |
||
1846 | |||
1847 | return $element; |
||
1848 | } |
||
1849 | } |
||
1850 |
This property has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.