[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Document/ -> HtmlDocument.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
   7   * @license    GNU General Public License version 2 or later; see LICENSE.txt
   8   */
   9  
  10  namespace Joomla\CMS\Document;
  11  
  12  use Joomla\CMS\Cache\Cache;
  13  use Joomla\CMS\Cache\CacheControllerFactoryAwareInterface;
  14  use Joomla\CMS\Cache\CacheControllerFactoryAwareTrait;
  15  use Joomla\CMS\Cache\CacheControllerFactoryInterface;
  16  use Joomla\CMS\Factory as CmsFactory;
  17  use Joomla\CMS\Filter\InputFilter;
  18  use Joomla\CMS\Helper\ModuleHelper;
  19  use Joomla\CMS\Language\Text;
  20  use Joomla\CMS\Uri\Uri;
  21  use Joomla\CMS\Utility\Utility;
  22  use Joomla\Database\ParameterType;
  23  use Joomla\Registry\Registry;
  24  use UnexpectedValueException;
  25  
  26  // phpcs:disable PSR1.Files.SideEffects
  27  \defined('JPATH_PLATFORM') or die;
  28  // phpcs:enable PSR1.Files.SideEffects
  29  
  30  /**
  31   * HtmlDocument class, provides an easy interface to parse and display a HTML document
  32   *
  33   * @since  1.7.0
  34   */
  35  class HtmlDocument extends Document implements CacheControllerFactoryAwareInterface
  36  {
  37      use CacheControllerFactoryAwareTrait;
  38  
  39      /**
  40       * Array of Header `<link>` tags
  41       *
  42       * @var    array
  43       * @since  1.7.0
  44       */
  45      public $_links = array();
  46  
  47      /**
  48       * Array of custom tags
  49       *
  50       * @var    array
  51       * @since  1.7.0
  52       */
  53      public $_custom = array();
  54  
  55      /**
  56       * Name of the template
  57       *
  58       * @var    string
  59       * @since  1.7.0
  60       */
  61      public $template = null;
  62  
  63      /**
  64       * Base url
  65       *
  66       * @var    string
  67       * @since  1.7.0
  68       */
  69      public $baseurl = null;
  70  
  71      /**
  72       * Array of template parameters
  73       *
  74       * @var    array
  75       * @since  1.7.0
  76       */
  77      public $params = null;
  78  
  79      /**
  80       * File name
  81       *
  82       * @var    array
  83       * @since  1.7.0
  84       */
  85      public $_file = null;
  86  
  87      /**
  88       * Script nonce (string if set, null otherwise)
  89       *
  90       * @var    string|null
  91       * @since  4.0.0
  92       */
  93      public $cspNonce = null;
  94  
  95      /**
  96       * String holding parsed template
  97       *
  98       * @var    string
  99       * @since  1.7.0
 100       */
 101      protected $_template = '';
 102  
 103      /**
 104       * Array of parsed template JDoc tags
 105       *
 106       * @var    array
 107       * @since  1.7.0
 108       */
 109      protected $_template_tags = array();
 110  
 111      /**
 112       * Integer with caching setting
 113       *
 114       * @var    integer
 115       * @since  1.7.0
 116       */
 117      protected $_caching = null;
 118  
 119      /**
 120       * Set to true when the document should be output as HTML5
 121       *
 122       * @var    boolean
 123       * @since  4.0.0
 124       */
 125      private $html5 = true;
 126  
 127      /**
 128       * Class constructor
 129       *
 130       * @param   array  $options  Associative array of options
 131       *
 132       * @since   1.7.0
 133       */
 134      public function __construct($options = array())
 135      {
 136          parent::__construct($options);
 137  
 138          // Set document type
 139          $this->_type = 'html';
 140  
 141          // Set default mime type and document metadata (metadata syncs with mime type by default)
 142          $this->setMimeEncoding('text/html');
 143      }
 144  
 145      /**
 146       * Get the HTML document head data
 147       *
 148       * @return  array  The document head data in array form
 149       *
 150       * @since   1.7.0
 151       */
 152      public function getHeadData()
 153      {
 154          $data = array();
 155          $data['title']         = $this->title;
 156          $data['description']   = $this->description;
 157          $data['link']          = $this->link;
 158          $data['metaTags']      = $this->_metaTags;
 159          $data['links']         = $this->_links;
 160          $data['styleSheets']   = $this->_styleSheets;
 161          $data['style']         = $this->_style;
 162          $data['scripts']       = $this->_scripts;
 163          $data['script']        = $this->_script;
 164          $data['custom']        = $this->_custom;
 165  
 166          // @deprecated 5.0  This property is for backwards compatibility. Pass text through script options in the future
 167          $data['scriptText']    = Text::getScriptStrings();
 168  
 169          $data['scriptOptions'] = $this->scriptOptions;
 170  
 171          // Get Asset manager state
 172          $wa      = $this->getWebAssetManager();
 173          $waState = $wa->getManagerState();
 174  
 175          // Get asset objects and filter only manually added/enabled assets,
 176          // Dependencies will be picked up from registry files
 177          $waState['assets'] = [];
 178  
 179          foreach ($waState['activeAssets'] as $assetType => $assetNames) {
 180              foreach ($assetNames as $assetName => $assetState) {
 181                  $waState['assets'][$assetType][] = $wa->getAsset($assetType, $assetName);
 182              }
 183          }
 184  
 185          // We have loaded asset objects, now can remove unused stuff
 186          unset($waState['activeAssets']);
 187  
 188          $data['assetManager'] = $waState;
 189  
 190          return $data;
 191      }
 192  
 193      /**
 194       * Reset the HTML document head data
 195       *
 196       * @param   mixed  $types  type or types of the heads elements to reset
 197       *
 198       * @return  HtmlDocument  instance of $this to allow chaining
 199       *
 200       * @since   3.7.0
 201       */
 202      public function resetHeadData($types = null)
 203      {
 204          if (\is_null($types)) {
 205              $this->title         = '';
 206              $this->description   = '';
 207              $this->link          = '';
 208              $this->_metaTags     = array();
 209              $this->_links        = array();
 210              $this->_styleSheets  = array();
 211              $this->_style        = array();
 212              $this->_scripts      = array();
 213              $this->_script       = array();
 214              $this->_custom       = array();
 215              $this->scriptOptions = array();
 216          }
 217  
 218          if (\is_array($types)) {
 219              foreach ($types as $type) {
 220                  $this->resetHeadDatum($type);
 221              }
 222          }
 223  
 224          if (\is_string($types)) {
 225              $this->resetHeadDatum($types);
 226          }
 227  
 228          return $this;
 229      }
 230  
 231      /**
 232       * Reset a part the HTML document head data
 233       *
 234       * @param   string  $type  type of the heads elements to reset
 235       *
 236       * @return  void
 237       *
 238       * @since   3.7.0
 239       */
 240      private function resetHeadDatum($type)
 241      {
 242          switch ($type) {
 243              case 'title':
 244              case 'description':
 245              case 'link':
 246                  $this->{$type} = '';
 247                  break;
 248  
 249              case 'metaTags':
 250              case 'links':
 251              case 'styleSheets':
 252              case 'style':
 253              case 'scripts':
 254              case 'script':
 255              case 'custom':
 256                  $realType = '_' . $type;
 257                  $this->{$realType} = array();
 258                  break;
 259  
 260              case 'scriptOptions':
 261                  $this->{$type} = array();
 262                  break;
 263          }
 264      }
 265  
 266      /**
 267       * Set the HTML document head data
 268       *
 269       * @param   array  $data  The document head data in array form
 270       *
 271       * @return  HtmlDocument|null instance of $this to allow chaining or null for empty input data
 272       *
 273       * @since   1.7.0
 274       */
 275      public function setHeadData($data)
 276      {
 277          if (empty($data) || !\is_array($data)) {
 278              return null;
 279          }
 280  
 281          $this->title         = $data['title'] ?? $this->title;
 282          $this->description   = $data['description'] ?? $this->description;
 283          $this->link          = $data['link'] ?? $this->link;
 284          $this->_metaTags     = $data['metaTags'] ?? $this->_metaTags;
 285          $this->_links        = $data['links'] ?? $this->_links;
 286          $this->_styleSheets  = $data['styleSheets'] ?? $this->_styleSheets;
 287          $this->_style        = $data['style'] ?? $this->_style;
 288          $this->_scripts      = $data['scripts'] ?? $this->_scripts;
 289          $this->_script       = $data['script'] ?? $this->_script;
 290          $this->_custom       = $data['custom'] ?? $this->_custom;
 291          $this->scriptOptions = (isset($data['scriptOptions']) && !empty($data['scriptOptions'])) ? $data['scriptOptions'] : $this->scriptOptions;
 292  
 293          // Restore asset manager state
 294          $wa = $this->getWebAssetManager();
 295  
 296          if (!empty($data['assetManager']['registryFiles'])) {
 297              $waRegistry = $wa->getRegistry();
 298  
 299              foreach ($data['assetManager']['registryFiles'] as $registryFile) {
 300                  $waRegistry->addRegistryFile($registryFile);
 301              }
 302          }
 303  
 304          if (!empty($data['assetManager']['assets'])) {
 305              foreach ($data['assetManager']['assets'] as $assetType => $assets) {
 306                  foreach ($assets as $asset) {
 307                      $wa->registerAsset($assetType, $asset)->useAsset($assetType, $asset->getName());
 308                  }
 309              }
 310          }
 311  
 312          return $this;
 313      }
 314  
 315      /**
 316       * Merge the HTML document head data
 317       *
 318       * @param   array  $data  The document head data in array form
 319       *
 320       * @return  HtmlDocument|void instance of $this to allow chaining or void for empty input data
 321       *
 322       * @since   1.7.0
 323       */
 324      public function mergeHeadData($data)
 325      {
 326          if (empty($data) || !\is_array($data)) {
 327              return;
 328          }
 329  
 330          $this->title = (isset($data['title']) && !empty($data['title']) && !stristr($this->title, $data['title']))
 331              ? $this->title . $data['title']
 332              : $this->title;
 333          $this->description = (isset($data['description']) && !empty($data['description']) && !stristr($this->description, $data['description']))
 334              ? $this->description . $data['description']
 335              : $this->description;
 336          $this->link = $data['link'] ?? $this->link;
 337  
 338          if (isset($data['metaTags'])) {
 339              foreach ($data['metaTags'] as $type1 => $data1) {
 340                  $booldog = $type1 === 'http-equiv';
 341  
 342                  foreach ($data1 as $name2 => $data2) {
 343                      $this->setMetaData($name2, $data2, $booldog);
 344                  }
 345              }
 346          }
 347  
 348          $this->_links = (isset($data['links']) && !empty($data['links']) && \is_array($data['links']))
 349              ? array_unique(array_merge($this->_links, $data['links']), SORT_REGULAR)
 350              : $this->_links;
 351          $this->_styleSheets = (isset($data['styleSheets']) && !empty($data['styleSheets']) && \is_array($data['styleSheets']))
 352              ? array_merge($this->_styleSheets, $data['styleSheets'])
 353              : $this->_styleSheets;
 354  
 355          if (isset($data['style'])) {
 356              foreach ($data['style'] as $type => $styles) {
 357                  foreach ($styles as $hash => $style) {
 358                      if (!isset($this->_style[strtolower($type)][$hash])) {
 359                          $this->addStyleDeclaration($style, $type);
 360                      }
 361                  }
 362              }
 363          }
 364  
 365          $this->_scripts = (isset($data['scripts']) && !empty($data['scripts']) && \is_array($data['scripts']))
 366              ? array_merge($this->_scripts, $data['scripts'])
 367              : $this->_scripts;
 368  
 369          if (isset($data['script'])) {
 370              foreach ($data['script'] as $type => $scripts) {
 371                  foreach ($scripts as $hash => $script) {
 372                      if (!isset($this->_script[strtolower($type)][$hash])) {
 373                          $this->addScriptDeclaration($script, $type);
 374                      }
 375                  }
 376              }
 377          }
 378  
 379          $this->_custom = (isset($data['custom']) && !empty($data['custom']) && \is_array($data['custom']))
 380              ? array_unique(array_merge($this->_custom, $data['custom']))
 381              : $this->_custom;
 382  
 383          if (!empty($data['scriptOptions'])) {
 384              foreach ($data['scriptOptions'] as $key => $scriptOptions) {
 385                  $this->addScriptOptions($key, $scriptOptions, true);
 386              }
 387          }
 388  
 389          // Restore asset manager state
 390          $wa = $this->getWebAssetManager();
 391  
 392          if (!empty($data['assetManager']['registryFiles'])) {
 393              $waRegistry = $wa->getRegistry();
 394  
 395              foreach ($data['assetManager']['registryFiles'] as $registryFile) {
 396                  $waRegistry->addRegistryFile($registryFile);
 397              }
 398          }
 399  
 400          if (!empty($data['assetManager']['assets'])) {
 401              foreach ($data['assetManager']['assets'] as $assetType => $assets) {
 402                  foreach ($assets as $asset) {
 403                      $wa->registerAsset($assetType, $asset)->useAsset($assetType, $asset->getName());
 404                  }
 405              }
 406          }
 407  
 408          return $this;
 409      }
 410  
 411      /**
 412       * Adds `<link>` tags to the head of the document
 413       *
 414       * $relType defaults to 'rel' as it is the most common relation type used.
 415       * ('rev' refers to reverse relation, 'rel' indicates normal, forward relation.)
 416       * Typical tag: `<link href="index.php" rel="Start">`
 417       *
 418       * @param   string  $href      The link that is being related.
 419       * @param   string  $relation  Relation of link.
 420       * @param   string  $relType   Relation type attribute.  Either rel or rev (default: 'rel').
 421       * @param   array   $attribs   Associative array of remaining attributes.
 422       *
 423       * @return  HtmlDocument instance of $this to allow chaining
 424       *
 425       * @since   1.7.0
 426       */
 427      public function addHeadLink($href, $relation, $relType = 'rel', $attribs = array())
 428      {
 429          $this->_links[$href]['relation'] = $relation;
 430          $this->_links[$href]['relType'] = $relType;
 431          $this->_links[$href]['attribs'] = $attribs;
 432  
 433          return $this;
 434      }
 435  
 436      /**
 437       * Adds a shortcut icon (favicon)
 438       *
 439       * This adds a link to the icon shown in the favorites list or on
 440       * the left of the url in the address bar. Some browsers display
 441       * it on the tab, as well.
 442       *
 443       * @param   string  $href      The link that is being related.
 444       * @param   string  $type      File type
 445       * @param   string  $relation  Relation of link
 446       *
 447       * @return  HtmlDocument instance of $this to allow chaining
 448       *
 449       * @since   1.7.0
 450       */
 451      public function addFavicon($href, $type = 'image/vnd.microsoft.icon', $relation = 'shortcut icon')
 452      {
 453          $href = str_replace('\\', '/', $href);
 454          $this->addHeadLink($href, $relation, 'rel', array('type' => $type));
 455  
 456          return $this;
 457      }
 458  
 459      /**
 460       * Adds a custom HTML string to the head block
 461       *
 462       * @param   string  $html  The HTML to add to the head
 463       *
 464       * @return  HtmlDocument instance of $this to allow chaining
 465       *
 466       * @since   1.7.0
 467       */
 468      public function addCustomTag($html)
 469      {
 470          $this->_custom[] = trim($html);
 471  
 472          return $this;
 473      }
 474  
 475      /**
 476       * Returns whether the document is set up to be output as HTML5
 477       *
 478       * @return  boolean true when HTML5 is used
 479       *
 480       * @since   3.0.0
 481       */
 482      public function isHtml5()
 483      {
 484          return $this->html5;
 485      }
 486  
 487      /**
 488       * Sets whether the document should be output as HTML5
 489       *
 490       * @param   bool  $state  True when HTML5 should be output
 491       *
 492       * @return  void
 493       *
 494       * @since   3.0.0
 495       */
 496      public function setHtml5($state)
 497      {
 498          if (\is_bool($state)) {
 499              $this->html5 = $state;
 500          }
 501      }
 502  
 503      /**
 504       * Get the contents of a document include
 505       *
 506       * @param   string  $type     The type of renderer
 507       * @param   string  $name     The name of the element to render
 508       * @param   array   $attribs  Associative array of remaining attributes.
 509       *
 510       * @return  mixed|string The output of the renderer
 511       *
 512       * @since   1.7.0
 513       */
 514      public function getBuffer($type = null, $name = null, $attribs = array())
 515      {
 516          // If no type is specified, return the whole buffer
 517          if ($type === null) {
 518              return parent::$_buffer;
 519          }
 520  
 521          $title = $attribs['title'] ?? null;
 522  
 523          if (isset(parent::$_buffer[$type][$name][$title])) {
 524              return parent::$_buffer[$type][$name][$title];
 525          }
 526  
 527          $renderer = $this->loadRenderer($type);
 528  
 529          if ($this->_caching == true && $type === 'modules' && $name !== 'debug') {
 530              /** @var  \Joomla\CMS\Document\Renderer\Html\ModulesRenderer  $renderer */
 531              /** @var  \Joomla\CMS\Cache\Controller\OutputController  $cache */
 532              $cache  = $this->getCacheControllerFactory()->createCacheController('output', ['defaultgroup' => 'com_modules']);
 533              $itemId = (int) CmsFactory::getApplication()->input->get('Itemid', 0, 'int');
 534  
 535              $hash = md5(
 536                  serialize(
 537                      [
 538                          $name,
 539                          $attribs,
 540                          \get_class($renderer),
 541                          $itemId,
 542                      ]
 543                  )
 544              );
 545              $cbuffer = $cache->get('cbuffer_' . $type);
 546  
 547              if (isset($cbuffer[$hash])) {
 548                  return Cache::getWorkarounds($cbuffer[$hash], array('mergehead' => 1));
 549              }
 550  
 551              $options = array();
 552              $options['nopathway'] = 1;
 553              $options['nomodules'] = 1;
 554              $options['modulemode'] = 1;
 555  
 556              $this->setBuffer($renderer->render($name, $attribs, null), $type, $name);
 557              $data = parent::$_buffer[$type][$name][$title];
 558  
 559              $tmpdata = Cache::setWorkarounds($data, $options);
 560  
 561              $cbuffer[$hash] = $tmpdata;
 562  
 563              $cache->store($cbuffer, 'cbuffer_' . $type);
 564          } else {
 565              $this->setBuffer($renderer->render($name, $attribs, null), $type, $name, $title);
 566          }
 567  
 568          return parent::$_buffer[$type][$name][$title];
 569      }
 570  
 571      /**
 572       * Set the contents a document includes
 573       *
 574       * @param   string  $content  The content to be set in the buffer.
 575       * @param   array   $options  Array of optional elements.
 576       *
 577       * @return  HtmlDocument instance of $this to allow chaining
 578       *
 579       * @since   1.7.0
 580       */
 581      public function setBuffer($content, $options = array())
 582      {
 583          // The following code is just for backward compatibility.
 584          if (\func_num_args() > 1 && !\is_array($options)) {
 585              $args = \func_get_args();
 586              $options = array();
 587              $options['type'] = $args[1];
 588              $options['name'] = $args[2] ?? null;
 589              $options['title'] = $args[3] ?? null;
 590          }
 591  
 592          parent::$_buffer[$options['type']][$options['name']][$options['title']] = $content;
 593  
 594          return $this;
 595      }
 596  
 597      /**
 598       * Parses the template and populates the buffer
 599       *
 600       * @param   array  $params  Parameters for fetching the template
 601       *
 602       * @return  HtmlDocument instance of $this to allow chaining
 603       *
 604       * @since   1.7.0
 605       */
 606      public function parse($params = array())
 607      {
 608          return $this->_fetchTemplate($params)->_parseTemplate();
 609      }
 610  
 611      /**
 612       * Outputs the template to the browser.
 613       *
 614       * @param   boolean  $caching  If true, cache the output
 615       * @param   array    $params   Associative array of attributes
 616       *
 617       * @return  string The rendered data
 618       *
 619       * @since   1.7.0
 620       */
 621      public function render($caching = false, $params = array())
 622      {
 623          $this->_caching = $caching;
 624  
 625          if (empty($this->_template)) {
 626              $this->parse($params);
 627          }
 628  
 629          if (\array_key_exists('csp_nonce', $params) && $params['csp_nonce'] !== null) {
 630              $this->cspNonce = $params['csp_nonce'];
 631          }
 632  
 633          $data = $this->_renderTemplate();
 634          parent::render($caching, $params);
 635  
 636          return $data;
 637      }
 638  
 639      /**
 640       * Count the modules in the given position
 641       *
 642       * @param   string   $positionName     The position to use
 643       * @param   boolean  $withContentOnly  Count only a modules which actually has a content
 644       *
 645       * @return  integer  Number of modules found
 646       *
 647       * @since   1.7.0
 648       */
 649      public function countModules(string $positionName, bool $withContentOnly = false)
 650      {
 651          if ((isset(parent::$_buffer['modules'][$positionName])) && (parent::$_buffer['modules'][$positionName] === false)) {
 652              return 0;
 653          }
 654  
 655          $modules = ModuleHelper::getModules($positionName);
 656  
 657          if (!$withContentOnly) {
 658              return \count($modules);
 659          }
 660  
 661          // Now we need to count only modules which actually have a content
 662          $result   = 0;
 663          $renderer = $this->loadRenderer('module');
 664  
 665          foreach ($modules as $module) {
 666              if (empty($module->contentRendered)) {
 667                  $renderer->render($module, ['contentOnly' => true]);
 668              }
 669  
 670              if (trim($module->content) !== '') {
 671                  $result++;
 672              }
 673          }
 674  
 675          return $result;
 676      }
 677  
 678      /**
 679       * Count the number of child menu items of the current active menu item
 680       *
 681       * @return  integer  Number of child menu items
 682       *
 683       * @since   1.7.0
 684       */
 685      public function countMenuChildren()
 686      {
 687          static $children;
 688  
 689          if (!isset($children)) {
 690              $db = CmsFactory::getDbo();
 691              $app = CmsFactory::getApplication();
 692              $menu = $app->getMenu();
 693              $active = $menu->getActive();
 694              $children = 0;
 695  
 696              if ($active) {
 697                  $query = $db->getQuery(true)
 698                      ->select('COUNT(*)')
 699                      ->from($db->quoteName('#__menu'))
 700                      ->where(
 701                          [
 702                              $db->quoteName('parent_id') . ' = :id',
 703                              $db->quoteName('published') . ' = 1',
 704                          ]
 705                      )
 706                      ->bind(':id', $active->id, ParameterType::INTEGER);
 707                  $db->setQuery($query);
 708                  $children = $db->loadResult();
 709              }
 710          }
 711  
 712          return $children;
 713      }
 714  
 715      /**
 716       * Load a template file
 717       *
 718       * @param   string  $directory  The name of the template
 719       * @param   string  $filename   The actual filename
 720       *
 721       * @return  string  The contents of the template
 722       *
 723       * @since   1.7.0
 724       */
 725      protected function _loadTemplate($directory, $filename)
 726      {
 727          $contents = '';
 728  
 729          // Check to see if we have a valid template file
 730          if (is_file($directory . '/' . $filename)) {
 731              // Store the file path
 732              $this->_file = $directory . '/' . $filename;
 733  
 734              // Get the file content
 735              ob_start();
 736              require $directory . '/' . $filename;
 737              $contents = ob_get_contents();
 738              ob_end_clean();
 739          }
 740  
 741          return $contents;
 742      }
 743  
 744      /**
 745       * Fetch the template, and initialise the params
 746       *
 747       * @param   array  $params  Parameters to determine the template
 748       *
 749       * @return  HtmlDocument instance of $this to allow chaining
 750       *
 751       * @since   1.7.0
 752       */
 753      protected function _fetchTemplate($params = array())
 754      {
 755          // Check
 756          $directory = $params['directory'] ?? 'templates';
 757          $filter = InputFilter::getInstance();
 758          $template = $filter->clean($params['template'], 'cmd');
 759          $file = $filter->clean($params['file'], 'cmd');
 760          $inherits = $params['templateInherits'] ?? '';
 761          $baseDir = $directory . '/' . $template;
 762  
 763          if (!is_file($directory . '/' . $template . '/' . $file)) {
 764              if ($inherits !== '' && is_file($directory . '/' . $inherits . '/' . $file)) {
 765                  $baseDir = $directory . '/' . $inherits;
 766              } else {
 767                  $baseDir  = $directory . '/system';
 768                  $template = 'system';
 769  
 770                  if ($file !== 'index.php' && !is_file($baseDir . '/' . $file)) {
 771                      $file = 'index.php';
 772                  }
 773              }
 774          }
 775  
 776          // Load the language file for the template
 777          $lang = CmsFactory::getLanguage();
 778  
 779          // 1.5 or core then 1.6
 780          $lang->load('tpl_' . $template, JPATH_BASE)
 781              || ($inherits !== '' && $lang->load('tpl_' . $inherits, $directory . '/' . $inherits))
 782              || $lang->load('tpl_' . $template, $directory . '/' . $template);
 783  
 784          // Assign the variables
 785          $this->baseurl = Uri::base(true);
 786          $this->params = $params['params'] ?? new Registry();
 787          $this->template = $template;
 788  
 789          // Load
 790          $this->_template = $this->_loadTemplate($baseDir, $file);
 791  
 792          return $this;
 793      }
 794  
 795      /**
 796       * Parse a document template
 797       *
 798       * @return  HtmlDocument  instance of $this to allow chaining
 799       *
 800       * @since   1.7.0
 801       */
 802      protected function _parseTemplate()
 803      {
 804          $matches = array();
 805  
 806          if (preg_match_all('#<jdoc:include\ type="([^"]+)"(.*)\/>#iU', $this->_template, $matches)) {
 807              $messages = [];
 808              $template_tags_first = [];
 809              $template_tags_last = [];
 810  
 811              // Step through the jdocs in reverse order.
 812              for ($i = \count($matches[0]) - 1; $i >= 0; $i--) {
 813                  $type = $matches[1][$i];
 814                  $attribs = empty($matches[2][$i]) ? array() : Utility::parseAttributes($matches[2][$i]);
 815                  $name = $attribs['name'] ?? null;
 816  
 817                  // Separate buffers to be executed first and last
 818                  if ($type === 'module' || $type === 'modules') {
 819                      $template_tags_first[$matches[0][$i]] = ['type' => $type, 'name' => $name, 'attribs' => $attribs];
 820                  } elseif ($type === 'message') {
 821                      $messages = [$matches[0][$i] => ['type' => $type, 'name' => $name, 'attribs' => $attribs]];
 822                  } else {
 823                      $template_tags_last[$matches[0][$i]] = ['type' => $type, 'name' => $name, 'attribs' => $attribs];
 824                  }
 825              }
 826  
 827              $this->_template_tags = $template_tags_first + $messages + array_reverse($template_tags_last);
 828          }
 829  
 830          return $this;
 831      }
 832  
 833      /**
 834       * Render pre-parsed template
 835       *
 836       * @return string rendered template
 837       *
 838       * @since   1.7.0
 839       */
 840      protected function _renderTemplate()
 841      {
 842          $replace = [];
 843          $with = [];
 844  
 845          foreach ($this->_template_tags as $jdoc => $args) {
 846              $replace[] = $jdoc;
 847              $with[] = $this->getBuffer($args['type'], $args['name'], $args['attribs']);
 848          }
 849  
 850          return str_replace($replace, $with, $this->_template);
 851      }
 852  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer