PageRenderTime 52ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/joomla/libraries/joomla/document/html/html.php

https://github.com/reechalee/joomla1.6
PHP | 507 lines | 318 code | 62 blank | 127 comment | 53 complexity | 5fec75aa1b5da5750b0261b816b6fdcd MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause, JSON
  1. <?php
  2. /**
  3. * @version $Id: html.php 20196 2011-01-09 02:40:25Z ian $
  4. * @package Joomla.Framework
  5. * @subpackage Document
  6. * @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE.txt
  8. */
  9. defined('JPATH_BASE') or die;
  10. jimport('joomla.application.module.helper');
  11. /**
  12. * DocumentHTML class, provides an easy interface to parse and display an html document
  13. *
  14. * @package Joomla.Framework
  15. * @subpackage Document
  16. * @since 1.5
  17. */
  18. jimport('joomla.document.document');
  19. class JDocumentHTML extends JDocument
  20. {
  21. /**
  22. * Array of Header <link> tags
  23. *
  24. * @var array
  25. */
  26. public $_links = array();
  27. /**
  28. * Array of custom tags
  29. *
  30. * @var array
  31. */
  32. public $_custom = array();
  33. public $template = null;
  34. public $baseurl = null;
  35. public $params = null;
  36. public $_file = null;
  37. /**
  38. * String holding parsed template
  39. */
  40. protected $_template = '';
  41. /**
  42. * Array of parsed template JDoc tags
  43. */
  44. protected $_template_tags = array();
  45. /**
  46. * Integer with caching setting
  47. */
  48. protected $_caching = null;
  49. /**
  50. * Class constructor
  51. *
  52. * @param array $options Associative array of options
  53. */
  54. public function __construct($options = array())
  55. {
  56. parent::__construct($options);
  57. //set document type
  58. $this->_type = 'html';
  59. //set default mime type and document metadata (meta data syncs with mime type by default)
  60. $this->setMetaData('Content-Type', 'text/html', true);
  61. $this->setMetaData('robots', 'index, follow');
  62. }
  63. /**
  64. * Get the html document head data
  65. *
  66. * @return array The document head data in array form
  67. */
  68. public function getHeadData()
  69. {
  70. $data = array();
  71. $data['title'] = $this->title;
  72. $data['description']= $this->description;
  73. $data['link'] = $this->link;
  74. $data['metaTags'] = $this->_metaTags;
  75. $data['links'] = $this->_links;
  76. $data['styleSheets']= $this->_styleSheets;
  77. $data['style'] = $this->_style;
  78. $data['scripts'] = $this->_scripts;
  79. $data['script'] = $this->_script;
  80. $data['custom'] = $this->_custom;
  81. return $data;
  82. }
  83. /**
  84. * Set the html document head data
  85. *
  86. * @param array $data The document head data in array form
  87. */
  88. public function setHeadData($data)
  89. {
  90. if (empty($data) || !is_array($data)) {
  91. return;
  92. }
  93. $this->title = (isset($data['title']) && !empty($data['title'])) ? $data['title'] : $this->title;
  94. $this->description = (isset($data['description']) && !empty($data['description'])) ? $data['description'] : $this->description;
  95. $this->link = (isset($data['link']) && !empty($data['link'])) ? $data['link'] : $this->link;
  96. $this->_metaTags = (isset($data['metaTags']) && !empty($data['metaTags'])) ? $data['metaTags'] : $this->_metaTags;
  97. $this->_links = (isset($data['links']) && !empty($data['links'])) ? $data['links'] : $this->_links;
  98. $this->_styleSheets = (isset($data['styleSheets']) && !empty($data['styleSheets'])) ? $data['styleSheets'] : $this->_styleSheets;
  99. $this->_style = (isset($data['style']) && !empty($data['style'])) ? $data['style'] : $this->_style;
  100. $this->_scripts = (isset($data['scripts']) && !empty($data['scripts'])) ? $data['scripts'] : $this->_scripts;
  101. $this->_script = (isset($data['script']) && !empty($data['script'])) ? $data['script'] : $this->_script;
  102. $this->_custom = (isset($data['custom']) && !empty($data['custom'])) ? $data['custom'] : $this->_custom;
  103. }
  104. /**
  105. * Merge the html document head data
  106. *
  107. * @param array $data The document head data in array form
  108. */
  109. public function mergeHeadData($data)
  110. {
  111. if (empty($data) || !is_array($data)) {
  112. return;
  113. }
  114. $this->title = (isset($data['title']) && !empty($data['title']) && !stristr($this->title, $data['title'])) ? $this->title.$data['title'] : $this->title;
  115. $this->description = (isset($data['description']) && !empty($data['description']) && !stristr($this->description, $data['description'])) ? $this->description. $data['description'] : $this->description;
  116. $this->link = (isset($data['link'])) ? $data['link'] : $this->link;
  117. if (isset($data['metaTags'])) {
  118. foreach($data['metaTags'] AS $type1=>$data1)
  119. {
  120. $booldog = $type1 == 'http-equiv' ? true : false;
  121. foreach($data1 AS $name2=>$data2)
  122. {
  123. $this->setMetaData($name2, $data2, $booldog);
  124. }
  125. }
  126. }
  127. $this->_links = (isset($data['links']) && !empty($data['links']) && is_array($data['links'])) ? array_unique(array_merge($this->_links, $data['links'])) : $this->_links;
  128. $this->_styleSheets = (isset($data['styleSheets']) && !empty($data['styleSheets']) && is_array($data['styleSheets'])) ? array_merge($this->_styleSheets, $data['styleSheets']) : $this->_styleSheets;
  129. if (isset($data['style'])) {
  130. foreach($data['style'] AS $type=>$stdata)
  131. {
  132. if (!isset($this->_style[strtolower($type)]) || !stristr($this->_style[strtolower($type)],$stdata)) {
  133. $this->addStyleDeclaration($stdata, $type);
  134. }
  135. }
  136. }
  137. $this->_scripts = (isset($data['scripts']) && !empty($data['scripts']) && is_array($data['scripts'])) ? array_merge($this->_scripts, $data['scripts']) : $this->_scripts;
  138. if (isset($data['script'])) {
  139. foreach($data['script'] AS $type=>$sdata)
  140. {
  141. if (!isset($this->_script[strtolower($type)]) || !stristr($this->_script[strtolower($type)],$sdata)) {
  142. $this->addScriptDeclaration($sdata, $type);
  143. }
  144. }
  145. }
  146. $this->_custom = (isset($data['custom']) && !empty($data['custom'])&& is_array($data['custom'])) ? array_unique(array_merge($this->_custom, $data['custom'])) : $this->_custom;
  147. }
  148. /**
  149. * Adds <link> tags to the head of the document
  150. *
  151. * <p>$relType defaults to 'rel' as it is the most common relation type used.
  152. * ('rev' refers to reverse relation, 'rel' indicates normal, forward relation.)
  153. * Typical tag: <link href="index.php" rel="Start"></p>
  154. *
  155. * @param string $href The link that is being related.
  156. * @param string $relation Relation of link.
  157. * @param string $relType Relation type attribute. Either rel or rev (default: 'rel').
  158. * @param array $attributes Associative array of remaining attributes.
  159. * @return void
  160. */
  161. public function addHeadLink($href, $relation, $relType = 'rel', $attribs = array())
  162. {
  163. $attribs = JArrayHelper::toString($attribs);
  164. $generatedTag = '<link href="'.$href.'" '.$relType.'="'.$relation.'" '.$attribs;
  165. $this->_links[] = $generatedTag;
  166. }
  167. /**
  168. * Adds a shortcut icon (favicon)
  169. *
  170. * <p>This adds a link to the icon shown in the favorites list or on
  171. * the left of the url in the address bar. Some browsers display
  172. * it on the tab, as well.</p>
  173. *
  174. * @param string $href The link that is being related.
  175. * @param string $type File type
  176. * @param string $relation Relation of link
  177. */
  178. public function addFavicon($href, $type = 'image/vnd.microsoft.icon', $relation = 'shortcut icon')
  179. {
  180. $href = str_replace('\\', '/', $href);
  181. $this->_links[] = '<link href="'.$href.'" rel="'.$relation.'" type="'.$type.'"';
  182. }
  183. /**
  184. * Adds a custom html string to the head block
  185. *
  186. * @param string The html to add to the head
  187. * @return void
  188. */
  189. public function addCustomTag($html)
  190. {
  191. $this->_custom[] = trim($html);
  192. }
  193. /**
  194. * Get the contents of a document include
  195. *
  196. * @param string $type The type of renderer
  197. * @param string $name The name of the element to render
  198. * @param array $attribs Associative array of remaining attributes.
  199. * @return The output of the renderer
  200. */
  201. public function getBuffer($type = null, $name = null, $attribs = array())
  202. {
  203. // If no type is specified, return the whole buffer
  204. if ($type === null) {
  205. return parent::$_buffer;
  206. }
  207. $result = null;
  208. if (isset(parent::$_buffer[$type][$name])) {
  209. return parent::$_buffer[$type][$name];
  210. }
  211. // If the buffer has been explicitly turned off don't display or attempt to render
  212. if ($result === false) {
  213. return null;
  214. }
  215. $renderer = $this->loadRenderer($type);
  216. if ($this->_caching == true && $type == 'modules') {
  217. $cache = JFactory::getCache('com_modules','');
  218. $hash = md5(serialize(array($name, $attribs, $result, $renderer)));
  219. $cbuffer = $cache->get('cbuffer_'.$type);
  220. if (isset($cbuffer[$hash])) {
  221. return JCache::getWorkarounds($cbuffer[$hash], array('mergehead' => 1));
  222. } else {
  223. $options = array();
  224. $options['nopathway'] = 1;
  225. $options['nomodules'] = 1;
  226. $options['modulemode'] = 1;
  227. $this->setBuffer($renderer->render($name, $attribs, $result), $type, $name);
  228. $data = parent::$_buffer[$type][$name];
  229. $tmpdata = JCache::setWorkarounds($data, $options);
  230. $cbuffer[$hash] = $tmpdata;
  231. $cache->store($cbuffer, 'cbuffer_'.$type);
  232. }
  233. } else {
  234. $this->setBuffer($renderer->render($name, $attribs, $result), $type, $name);
  235. }
  236. return parent::$_buffer[$type][$name];
  237. }
  238. /**
  239. * Set the contents a document include
  240. *
  241. * @param string $content The content to be set in the buffer.
  242. * @param array $options Array of optional elements.
  243. */
  244. public function setBuffer($content, $options = array())
  245. {
  246. // The following code is just for backward compatibility.
  247. if (func_num_args() > 1 && !is_array($options)) {
  248. $args = func_get_args(); $options = array();
  249. $options['type'] = $args[1];
  250. $options['name'] = (isset($args[2])) ? $args[2] : null;
  251. }
  252. parent::$_buffer[$options['type']][$options['name']] = $content;
  253. }
  254. /**
  255. * Parses the template and populates the buffer
  256. *
  257. * @param array parameters for fetching the template
  258. */
  259. public function parse($params = array()) {
  260. $this->_fetchTemplate($params);
  261. $this->_parseTemplate();
  262. }
  263. /**
  264. * Outputs the template to the browser.
  265. *
  266. * @param boolean $cache If true, cache the output
  267. * @param array $params Associative array of attributes
  268. * @return The rendered data
  269. */
  270. public function render($caching = false, $params = array())
  271. {
  272. $this->_caching = $caching;
  273. if (!empty($this->_template)) {
  274. $data = $this->_renderTemplate();
  275. } else {
  276. $this->parse($params);
  277. $data = $this->_renderTemplate();
  278. }
  279. parent::render();
  280. return $data;
  281. }
  282. /**
  283. * Count the modules based on the given condition
  284. *
  285. * @param string $condition The condition to use
  286. * @return integer Number of modules found
  287. */
  288. public function countModules($condition)
  289. {
  290. $result = '';
  291. $operators = '(\+|\-|\*|\/|==|\!=|\<\>|\<|\>|\<=|\>=|and|or|xor)';
  292. $words = preg_split('# '.$operators.' #', $condition, null, PREG_SPLIT_DELIM_CAPTURE);
  293. for ($i = 0, $n = count($words); $i < $n; $i+=2)
  294. {
  295. // odd parts (modules)
  296. $name = strtolower($words[$i]);
  297. $words[$i] = ((isset(parent::$_buffer['modules'][$name])) && (parent::$_buffer['modules'][$name] === false)) ? 0 : count(JModuleHelper::getModules($name));
  298. }
  299. $str = 'return '.implode(' ', $words).';';
  300. return eval($str);
  301. }
  302. /**
  303. * Count the number of child menu items
  304. *
  305. * @return integer Number of child menu items
  306. */
  307. public function countMenuChildren()
  308. {
  309. static $children;
  310. if (!isset($children)) {
  311. $dbo = JFactory::getDbo();
  312. $app = JFactory::getApplication();
  313. $menu = $app->getMenu();
  314. $where = Array();
  315. $active = $menu->getActive();
  316. if ($active) {
  317. $where[] = 'parent = ' . $active->id;
  318. $where[] = 'published = 1';
  319. $dbo->setQuery('SELECT COUNT(*) FROM #__menu WHERE '. implode(' AND ', $where));
  320. $children = $dbo->loadResult();
  321. } else {
  322. $children = 0;
  323. }
  324. }
  325. return $children;
  326. }
  327. /**
  328. * Load a template file
  329. *
  330. * @param string $template The name of the template
  331. * @param string $filename The actual filename
  332. * @return string The contents of the template
  333. */
  334. private function _loadTemplate($directory, $filename)
  335. {
  336. // $component = JApplicationHelper::getComponentName();
  337. $contents = '';
  338. //Check to see if we have a valid template file
  339. if (file_exists($directory.DS.$filename))
  340. {
  341. //store the file path
  342. $this->_file = $directory.DS.$filename;
  343. //get the file content
  344. ob_start();
  345. require $directory.DS.$filename;
  346. $contents = ob_get_contents();
  347. ob_end_clean();
  348. }
  349. // Try to find a favicon by checking the template and root folder
  350. $path = $directory . DS;
  351. $dirs = array($path, JPATH_BASE.DS);
  352. foreach ($dirs as $dir)
  353. {
  354. $icon = $dir.'favicon.ico';
  355. if (file_exists($icon))
  356. {
  357. $path = str_replace(JPATH_BASE . DS, '', $dir);
  358. $path = str_replace('\\', '/', $path);
  359. $this->addFavicon(JURI::base(true).'/'.$path.'favicon.ico');
  360. break;
  361. }
  362. }
  363. return $contents;
  364. }
  365. /**
  366. * Fetch the template, and initialise the params
  367. *
  368. * @param array parameters to determine the template
  369. */
  370. protected function _fetchTemplate($params = array())
  371. {
  372. // check
  373. $directory = isset($params['directory']) ? $params['directory'] : 'templates';
  374. $filter = JFilterInput::getInstance();
  375. $template = $filter->clean($params['template'], 'cmd');
  376. $file = $filter->clean($params['file'], 'cmd');
  377. if (!file_exists($directory.DS.$template.DS.$file)) {
  378. $template = 'system';
  379. }
  380. // Load the language file for the template
  381. $lang = JFactory::getLanguage();
  382. // 1.5 or core then
  383. // 1.6
  384. $lang->load('tpl_'.$template, JPATH_BASE, null, false, false)
  385. || $lang->load('tpl_'.$template, $directory.DS.$template, null, false, false)
  386. || $lang->load('tpl_'.$template, JPATH_BASE, $lang->getDefault(), false, false)
  387. || $lang->load('tpl_'.$template, $directory.DS.$template, $lang->getDefault(), false, false);
  388. // Assign the variables
  389. $this->template = $template;
  390. $this->baseurl = JURI::base(true);
  391. $this->params = isset($params['params']) ? $params['params'] : new JRegistry;
  392. // load
  393. $this->_template = $this->_loadTemplate($directory.DS.$template, $file);
  394. }
  395. /**
  396. * Parse a document template
  397. *
  398. * @return The parsed contents of the template
  399. */
  400. private function _parseTemplate()
  401. {
  402. $replace = array();
  403. $matches = array();
  404. if (preg_match_all('#<jdoc:include\ type="([^"]+)" (.*)\/>#iU', $this->_template, $matches))
  405. {
  406. $matches[0] = array_reverse($matches[0]);
  407. $matches[1] = array_reverse($matches[1]);
  408. $matches[2] = array_reverse($matches[2]);
  409. $count = count($matches[1]);
  410. for ($i = 0; $i < $count; $i++)
  411. {
  412. $attribs = JUtility::parseAttributes($matches[2][$i]);
  413. $type = $matches[1][$i];
  414. $name = isset($attribs['name']) ? $attribs['name'] : null;
  415. $this->_template_tags[$matches[0][$i]] = array('type'=>$type, 'name' => $name, 'attribs' => $attribs);
  416. }
  417. }
  418. }
  419. /**
  420. * Render pre-parsed template
  421. *
  422. * @return string rendered template
  423. */
  424. private function _renderTemplate() {
  425. $replace = array();
  426. $with = array();
  427. foreach($this->_template_tags AS $jdoc => $args) {
  428. $replace[] = $jdoc;
  429. $with[] = $this->getBuffer($args['type'], $args['name'], $args['attribs']);
  430. }
  431. return str_replace($replace, $with, $this->_template);
  432. }
  433. }