PageRenderTime 96ms CodeModel.GetById 20ms app.highlight 45ms RepoModel.GetById 25ms app.codeStats 1ms

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

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