CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.7 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.7
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • AjaxView
  • Cell
  • Helper
  • HelperRegistry
  • JsonView
  • SerializedView
  • StringTemplate
  • View
  • ViewBlock
  • ViewBuilder
  • XmlView

Traits

  • CellTrait
  • StringTemplateTrait
  • ViewVarsTrait
   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:     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);
 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])) {
 954:             return $default;
 955:         }
 956: 
 957:         return $this->viewVars[$var];
 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' => 'getLayoutPath',
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:             'elementCache' => 'setElementCache',
1309:         ];
1310:         if (isset($protected[$name])) {
1311:             $method = $protected[$name];
1312:             deprecationWarning(sprintf(
1313:                 'View::$%s is protected now. Use View::%s() instead.',
1314:                 $name,
1315:                 $method
1316:             ));
1317: 
1318:             $this->{$method}($value);
1319: 
1320:             return;
1321:         }
1322: 
1323:         if ($name === 'helpers') {
1324:             deprecationWarning(
1325:                 'View::$helpers is protected now. ' .
1326:                 'Use the helper registry through View::helpers() to manage helpers.'
1327:             );
1328: 
1329:             return $this->helpers = $value;
1330:         }
1331: 
1332:         if ($name === 'name') {
1333:             deprecationWarning(
1334:                 'View::$name is protected now. ' .
1335:                 'You can use viewBuilder()->setName() to change the name a view uses before building it.'
1336:             );
1337:         }
1338: 
1339:         $this->{$name} = $value;
1340:     }
1341: 
1342:     /**
1343:      * Interact with the HelperRegistry to load all the helpers.
1344:      *
1345:      * @return $this
1346:      */
1347:     public function loadHelpers()
1348:     {
1349:         $registry = $this->helpers();
1350:         $helpers = $registry->normalizeArray($this->helpers);
1351:         foreach ($helpers as $properties) {
1352:             $this->loadHelper($properties['class'], $properties['config']);
1353:         }
1354: 
1355:         return $this;
1356:     }
1357: 
1358:     /**
1359:      * Renders and returns output for given template filename with its
1360:      * array of data. Handles parent/extended templates.
1361:      *
1362:      * @param string $viewFile Filename of the view
1363:      * @param array $data Data to include in rendered view. If empty the current
1364:      *   View::$viewVars will be used.
1365:      * @return string Rendered output
1366:      * @throws \LogicException When a block is left open.
1367:      * @triggers View.beforeRenderFile $this, [$viewFile]
1368:      * @triggers View.afterRenderFile $this, [$viewFile, $content]
1369:      */
1370:     protected function _render($viewFile, $data = [])
1371:     {
1372:         if (empty($data)) {
1373:             $data = $this->viewVars;
1374:         }
1375:         $this->_current = $viewFile;
1376:         $initialBlocks = count($this->Blocks->unclosed());
1377: 
1378:         $this->dispatchEvent('View.beforeRenderFile', [$viewFile]);
1379: 
1380:         $content = $this->_evaluate($viewFile, $data);
1381: 
1382:         $afterEvent = $this->dispatchEvent('View.afterRenderFile', [$viewFile, $content]);
1383:         if ($afterEvent->getResult() !== null) {
1384:             $content = $afterEvent->getResult();
1385:         }
1386: 
1387:         if (isset($this->_parents[$viewFile])) {
1388:             $this->_stack[] = $this->fetch('content');
1389:             $this->assign('content', $content);
1390: 
1391:             $content = $this->_render($this->_parents[$viewFile]);
1392:             $this->assign('content', array_pop($this->_stack));
1393:         }
1394: 
1395:         $remainingBlocks = count($this->Blocks->unclosed());
1396: 
1397:         if ($initialBlocks !== $remainingBlocks) {
1398:             throw new LogicException(sprintf(
1399:                 'The "%s" block was left open. Blocks are not allowed to cross files.',
1400:                 $this->Blocks->active()
1401:             ));
1402:         }
1403: 
1404:         return $content;
1405:     }
1406: 
1407:     /**
1408:      * Sandbox method to evaluate a template / view script in.
1409:      *
1410:      * @param string $viewFile Filename of the view
1411:      * @param array $dataForView Data to include in rendered view.
1412:      * @return string Rendered output
1413:      */
1414:     protected function _evaluate($viewFile, $dataForView)
1415:     {
1416:         extract($dataForView);
1417:         ob_start();
1418: 
1419:         include func_get_arg(0);
1420: 
1421:         return ob_get_clean();
1422:     }
1423: 
1424:     /**
1425:      * Get the helper registry in use by this View class.
1426:      *
1427:      * @return \Cake\View\HelperRegistry
1428:      */
1429:     public function helpers()
1430:     {
1431:         if ($this->_helpers === null) {
1432:             $this->_helpers = new HelperRegistry($this);
1433:         }
1434: 
1435:         return $this->_helpers;
1436:     }
1437: 
1438:     /**
1439:      * Loads a helper. Delegates to the `HelperRegistry::load()` to load the helper
1440:      *
1441:      * @param string $name Name of the helper to load.
1442:      * @param array $config Settings for the helper
1443:      * @return \Cake\View\Helper a constructed helper object.
1444:      * @see \Cake\View\HelperRegistry::load()
1445:      */
1446:     public function loadHelper($name, array $config = [])
1447:     {
1448:         list(, $class) = pluginSplit($name);
1449:         $helpers = $this->helpers();
1450: 
1451:         return $this->{$class} = $helpers->load($name, $config);
1452:     }
1453: 
1454:     /**
1455:      * Set sub-directory for this template files.
1456:      *
1457:      * @param string $subDir Sub-directory name.
1458:      * @return $this
1459:      * @see \Cake\View\View::$subDir
1460:      * @since 3.7.0
1461:      */
1462:     public function setSubDir($subDir)
1463:     {
1464:         $this->subDir = $subDir;
1465: 
1466:         return $this;
1467:     }
1468: 
1469:     /**
1470:      * Get sub-directory for this template files.
1471:      *
1472:      * @return string
1473:      * @see \Cake\View\View::$subDir
1474:      * @since 3.7.0
1475:      */
1476:     public function getSubDir()
1477:     {
1478:         return $this->subDir;
1479:     }
1480: 
1481:     /**
1482:      * Returns the View's controller name.
1483:      *
1484:      * @return string|null
1485:      * @since 3.7.7
1486:      */
1487:     public function getName()
1488:     {
1489:         return $this->name;
1490:     }
1491: 
1492:     /**
1493:      * Returns the plugin name.
1494:      *
1495:      * @return string|null
1496:      * @since 3.7.0
1497:      */
1498:     public function getPlugin()
1499:     {
1500:         return $this->plugin;
1501:     }
1502: 
1503:     /**
1504:      * Sets the plugin name.
1505:      *
1506:      * @param string $name Plugin name.
1507:      * @return $this
1508:      * @since 3.7.0
1509:      */
1510:     public function setPlugin($name)
1511:     {
1512:         $this->plugin = $name;
1513: 
1514:         return $this;
1515:     }
1516: 
1517:     /**
1518:      * Set The cache configuration View will use to store cached elements
1519:      *
1520:      * @param string $elementCache Cache config name.
1521:      * @return $this
1522:      * @see \Cake\View\View::$elementCache
1523:      * @since 3.7.0
1524:      */
1525:     public function setElementCache($elementCache)
1526:     {
1527:         $this->elementCache = $elementCache;
1528: 
1529:         return $this;
1530:     }
1531: 
1532:     /**
1533:      * Returns filename of given action's template file (.ctp) as a string.
1534:      * CamelCased action names will be under_scored by default.
1535:      * This means that you can have LongActionNames that refer to
1536:      * long_action_names.ctp views. You can change the inflection rule by
1537:      * overriding _inflectViewFileName.
1538:      *
1539:      * @param string|null $name Controller action to find template filename for
1540:      * @return string Template filename
1541:      * @throws \Cake\View\Exception\MissingTemplateException when a view file could not be found.
1542:      */
1543:     protected function _getViewFileName($name = null)
1544:     {
1545:         $templatePath = $subDir = '';
1546: 
1547:         if ($this->templatePath) {
1548:             $templatePath = $this->templatePath . DIRECTORY_SEPARATOR;
1549:         }
1550:         if (strlen($this->subDir)) {
1551:             $subDir = $this->subDir . DIRECTORY_SEPARATOR;
1552:             // Check if templatePath already terminates with subDir
1553:             if ($templatePath != $subDir && substr($templatePath, -strlen($subDir)) == $subDir) {
1554:                 $subDir = '';
1555:             }
1556:         }
1557: 
1558:         if ($name === null) {
1559:             $name = $this->template;
1560:         }
1561: 
1562:         list($plugin, $name) = $this->pluginSplit($name);
1563:         $name = str_replace('/', DIRECTORY_SEPARATOR, $name);
1564: 
1565:         if (strpos($name, DIRECTORY_SEPARATOR) === false && $name !== '' && $name[0] !== '.') {
1566:             $name = $templatePath . $subDir . $this->_inflectViewFileName($name);
1567:         } elseif (strpos($name, DIRECTORY_SEPARATOR) !== false) {
1568:             if ($name[0] === DIRECTORY_SEPARATOR || $name[1] === ':') {
1569:                 $name = trim($name, DIRECTORY_SEPARATOR);
1570:             } elseif (!$plugin || $this->templatePath !== $this->name) {
1571:                 $name = $templatePath . $subDir . $name;
1572:             } else {
1573:                 $name = DIRECTORY_SEPARATOR . $subDir . $name;
1574:             }
1575:         }
1576: 
1577:         foreach ($this->_paths($plugin) as $path) {
1578:             if (file_exists($path . $name . $this->_ext)) {
1579:                 return $this->_checkFilePath($path . $name . $this->_ext, $path);
1580:             }
1581:         }
1582:         throw new MissingTemplateException(['file' => $name . $this->_ext]);
1583:     }
1584: 
1585:     /**
1586:      * Change the name of a view template file into underscored format.
1587:      *
1588:      * @param string $name Name of file which should be inflected.
1589:      * @return string File name after conversion
1590:      */
1591:     protected function _inflectViewFileName($name)
1592:     {
1593:         return Inflector::underscore($name);
1594:     }
1595: 
1596:     /**
1597:      * Check that a view file path does not go outside of the defined template paths.
1598:      *
1599:      * Only paths that contain `..` will be checked, as they are the ones most likely to
1600:      * have the ability to resolve to files outside of the template paths.
1601:      *
1602:      * @param string $file The path to the template file.
1603:      * @param string $path Base path that $file should be inside of.
1604:      * @return string The file path
1605:      * @throws \InvalidArgumentException
1606:      */
1607:     protected function _checkFilePath($file, $path)
1608:     {
1609:         if (strpos($file, '..') === false) {
1610:             return $file;
1611:         }
1612:         $absolute = realpath($file);
1613:         if (strpos($absolute, $path) !== 0) {
1614:             throw new InvalidArgumentException(sprintf(
1615:                 'Cannot use "%s" as a template, it is not within any view template path.',
1616:                 $file
1617:             ));
1618:         }
1619: 
1620:         return $absolute;
1621:     }
1622: 
1623:     /**
1624:      * Splits a dot syntax plugin name into its plugin and filename.
1625:      * If $name does not have a dot, then index 0 will be null.
1626:      * It checks if the plugin is loaded, else filename will stay unchanged for filenames containing dot
1627:      *
1628:      * @param string $name The name you want to plugin split.
1629:      * @param bool $fallback If true uses the plugin set in the current Request when parsed plugin is not loaded
1630:      * @return array Array with 2 indexes. 0 => plugin name, 1 => filename
1631:      */
1632:     public function pluginSplit($name, $fallback = true)
1633:     {
1634:         $plugin = null;
1635:         list($first, $second) = pluginSplit($name);
1636:         if (Plugin::isLoaded($first) === true) {
1637:             $name = $second;
1638:             $plugin = $first;
1639:         }
1640:         if (isset($this->plugin) && !$plugin && $fallback) {
1641:             $plugin = $this->plugin;
1642:         }
1643: 
1644:         return [$plugin, $name];
1645:     }
1646: 
1647:     /**
1648:      * Returns layout filename for this template as a string.
1649:      *
1650:      * @param string|null $name The name of the layout to find.
1651:      * @return string Filename for layout file (.ctp).
1652:      * @throws \Cake\View\Exception\MissingLayoutException when a layout cannot be located
1653:      */
1654:     protected function _getLayoutFileName($name = null)
1655:     {
1656:         if ($name === null) {
1657:             $name = $this->layout;
1658:         }
1659:         $subDir = null;
1660: 
1661:         if ($this->layoutPath) {
1662:             $subDir = $this->layoutPath . DIRECTORY_SEPARATOR;
1663:         }
1664:         list($plugin, $name) = $this->pluginSplit($name);
1665: 
1666:         $layoutPaths = $this->_getSubPaths('Layout' . DIRECTORY_SEPARATOR . $subDir);
1667: 
1668:         foreach ($this->_paths($plugin) as $path) {
1669:             foreach ($layoutPaths as $layoutPath) {
1670:                 $currentPath = $path . $layoutPath;
1671:                 if (file_exists($currentPath . $name . $this->_ext)) {
1672:                     return $this->_checkFilePath($currentPath . $name . $this->_ext, $currentPath);
1673:                 }
1674:             }
1675:         }
1676:         throw new MissingLayoutException([
1677:             'file' => $layoutPaths[0] . $name . $this->_ext
1678:         ]);
1679:     }
1680: 
1681:     /**
1682:      * Finds an element filename, returns false on failure.
1683:      *
1684:      * @param string $name The name of the element to find.
1685:      * @param bool $pluginCheck - if false will ignore the request's plugin if parsed plugin is not loaded
1686:      * @return string|false Either a string to the element filename or false when one can't be found.
1687:      */
1688:     protected function _getElementFileName($name, $pluginCheck = true)
1689:     {
1690:         list($plugin, $name) = $this->pluginSplit($name, $pluginCheck);
1691: 
1692:         $paths = $this->_paths($plugin);
1693:         $elementPaths = $this->_getSubPaths(static::NAME_ELEMENT);
1694: 
1695:         foreach ($paths as $path) {
1696:             foreach ($elementPaths as $elementPath) {
1697:                 if (file_exists($path . $elementPath . DIRECTORY_SEPARATOR . $name . $this->_ext)) {
1698:                     return $path . $elementPath . DIRECTORY_SEPARATOR . $name . $this->_ext;
1699:                 }
1700:             }
1701:         }
1702: 
1703:         return false;
1704:     }
1705: 
1706:     /**
1707:      * Find all sub templates path, based on $basePath
1708:      * If a prefix is defined in the current request, this method will prepend
1709:      * the prefixed template path to the $basePath, cascading up in case the prefix
1710:      * is nested.
1711:      * This is essentially used to find prefixed template paths for elements
1712:      * and layouts.
1713:      *
1714:      * @param string $basePath Base path on which to get the prefixed one.
1715:      * @return array Array with all the templates paths.
1716:      */
1717:     protected function _getSubPaths($basePath)
1718:     {
1719:         $paths = [$basePath];
1720:         if ($this->request->getParam('prefix')) {
1721:             $prefixPath = explode('/', $this->request->getParam('prefix'));
1722:             $path = '';
1723:             foreach ($prefixPath as $prefixPart) {
1724:                 $path .= Inflector::camelize($prefixPart) . DIRECTORY_SEPARATOR;
1725: 
1726:                 array_unshift(
1727:                     $paths,
1728:                     $path . $basePath
1729:                 );
1730:             }
1731:         }
1732: 
1733:         return $paths;
1734:     }
1735: 
1736:     /**
1737:      * Return all possible paths to find view files in order
1738:      *
1739:      * @param string|null $plugin Optional plugin name to scan for view files.
1740:      * @param bool $cached Set to false to force a refresh of view paths. Default true.
1741:      * @return array paths
1742:      */
1743:     protected function _paths($plugin = null, $cached = true)
1744:     {
1745:         if ($cached === true) {
1746:             if ($plugin === null && !empty($this->_paths)) {
1747:                 return $this->_paths;
1748:             }
1749:             if ($plugin !== null && isset($this->_pathsForPlugin[$plugin])) {
1750:                 return $this->_pathsForPlugin[$plugin];
1751:             }
1752:         }
1753:         $templatePaths = App::path(static::NAME_TEMPLATE);
1754:         $pluginPaths = $themePaths = [];
1755:         if (!empty($plugin)) {
1756:             for ($i = 0, $count = count($templatePaths); $i < $count; $i++) {
1757:                 $pluginPaths[] = $templatePaths[$i] . 'Plugin' . DIRECTORY_SEPARATOR . $plugin . DIRECTORY_SEPARATOR;
1758:             }
1759:             $pluginPaths = array_merge($pluginPaths, App::path(static::NAME_TEMPLATE, $plugin));
1760:         }
1761: 
1762:         if (!empty($this->theme)) {
1763:             $themePaths = App::path(static::NAME_TEMPLATE, Inflector::camelize($this->theme));
1764: 
1765:             if ($plugin) {
1766:                 for ($i = 0, $count = count($themePaths); $i < $count; $i++) {
1767:                     array_unshift($themePaths, $themePaths[$i] . 'Plugin' . DIRECTORY_SEPARATOR . $plugin . DIRECTORY_SEPARATOR);
1768:                 }
1769:             }
1770:         }
1771: 
1772:         $paths = array_merge(
1773:             $themePaths,
1774:             $pluginPaths,
1775:             $templatePaths,
1776:             [dirname(__DIR__) . DIRECTORY_SEPARATOR . static::NAME_TEMPLATE . DIRECTORY_SEPARATOR]
1777:         );
1778: 
1779:         if ($plugin !== null) {
1780:             return $this->_pathsForPlugin[$plugin] = $paths;
1781:         }
1782: 
1783:         return $this->_paths = $paths;
1784:     }
1785: 
1786:     /**
1787:      * Generate the cache configuration options for an element.
1788:      *
1789:      * @param string $name Element name
1790:      * @param array $data Data
1791:      * @param array $options Element options
1792:      * @return array Element Cache configuration.
1793:      */
1794:     protected function _elementCache($name, $data, $options)
1795:     {
1796:         if (isset($options['cache']['key'], $options['cache']['config'])) {
1797:             $cache = $options['cache'];
1798:             $cache['key'] = 'element_' . $cache['key'];
1799: 
1800:             return $cache;
1801:         }
1802: 
1803:         $plugin = null;
1804:         list($plugin, $name) = $this->pluginSplit($name);
1805: 
1806:         $underscored = null;
1807:         if ($plugin) {
1808:             $underscored = Inflector::underscore($plugin);
1809:         }
1810: 
1811:         $cache = $options['cache'];
1812:         unset($options['cache'], $options['callbacks'], $options['plugin']);
1813:         $keys = array_merge(
1814:             [$underscored, $name],
1815:             array_keys($options),
1816:             array_keys($data)
1817:         );
1818:         $config = [
1819:             'config' => $this->elementCache,
1820:             'key' => implode('_', $keys)
1821:         ];
1822:         if (is_array($cache)) {
1823:             $defaults = [
1824:                 'config' => $this->elementCache,
1825:                 'key' => $config['key']
1826:             ];
1827:             $config = $cache + $defaults;
1828:         }
1829:         $config['key'] = 'element_' . $config['key'];
1830: 
1831:         return $config;
1832:     }
1833: 
1834:     /**
1835:      * Renders an element and fires the before and afterRender callbacks for it
1836:      * and writes to the cache if a cache is used
1837:      *
1838:      * @param string $file Element file path
1839:      * @param array $data Data to render
1840:      * @param array $options Element options
1841:      * @return string
1842:      * @triggers View.beforeRender $this, [$file]
1843:      * @triggers View.afterRender $this, [$file, $element]
1844:      */
1845:     protected function _renderElement($file, $data, $options)
1846:     {
1847:         $current = $this->_current;
1848:         $restore = $this->_currentType;
1849:         $this->_currentType = static::TYPE_ELEMENT;
1850: 
1851:         if ($options['callbacks']) {
1852:             $this->dispatchEvent('View.beforeRender', [$file]);
1853:         }
1854: 
1855:         $element = $this->_render($file, array_merge($this->viewVars, $data));
1856: 
1857:         if ($options['callbacks']) {
1858:             $this->dispatchEvent('View.afterRender', [$file, $element]);
1859:         }
1860: 
1861:         $this->_currentType = $restore;
1862:         $this->_current = $current;
1863: 
1864:         return $element;
1865:     }
1866: }
1867: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs