1 <?php
2 3 4 5 6 7 8
9
10 defined('JPATH_PLATFORM') or die;
11
12 use Joomla\Registry\Registry;
13
14 jimport('joomla.utilities.utility');
15
16 17 18 19 20
21 class JDocumentHtml extends JDocument
22 {
23 24 25 26 27 28
29 public $_links = array();
30
31 32 33 34 35 36
37 public $_custom = array();
38
39 40 41 42 43 44
45 public $template = null;
46
47 48 49 50 51 52
53 public $baseurl = null;
54
55 56 57 58 59 60
61 public $params = null;
62
63 64 65 66 67 68
69 public $_file = null;
70
71 72 73 74 75 76
77 protected $_template = '';
78
79 80 81 82 83 84
85 protected $_template_tags = array();
86
87 88 89 90 91 92
93 protected $_caching = null;
94
95 96 97 98 99 100 101 102
103 private $_html5 = null;
104
105 106 107 108 109 110 111
112 public function __construct($options = array())
113 {
114 parent::__construct($options);
115
116
117 $this->_type = 'html';
118
119
120 $this->setMimeEncoding('text/html');
121 }
122
123 124 125 126 127 128 129
130 public function getHeadData()
131 {
132 $data = array();
133 $data['title'] = $this->title;
134 $data['description'] = $this->description;
135 $data['link'] = $this->link;
136 $data['metaTags'] = $this->_metaTags;
137 $data['links'] = $this->_links;
138 $data['styleSheets'] = $this->_styleSheets;
139 $data['style'] = $this->_style;
140 $data['scripts'] = $this->_scripts;
141 $data['script'] = $this->_script;
142 $data['custom'] = $this->_custom;
143 $data['scriptText'] = JText::script();
144
145 return $data;
146 }
147
148 149 150 151 152 153 154 155 156
157 public function resetHeadData($types = null)
158 {
159 if (is_null($types))
160 {
161 $this->title = '';
162 $this->description = '';
163 $this->link = '';
164 $this->_metaTags = array();
165 $this->_links = array();
166 $this->_styleSheets = array();
167 $this->_style = array();
168 $this->_scripts = array();
169 $this->_script = array();
170 $this->_custom = array();
171 }
172
173 if (is_array($types))
174 {
175 foreach ($types as $type)
176 {
177 $this->resetHeadDatum($type);
178 }
179 }
180
181 if (is_string($types))
182 {
183 $this->resetHeadDatum($types);
184 }
185
186 return $this;
187 }
188
189 190 191 192 193 194 195 196 197
198 private function resetHeadDatum($type)
199 {
200 switch ($type)
201 {
202 case 'title':
203 case 'description':
204 case 'link':
205 $this->{$type} = '';
206 break;
207
208 case 'metaTags':
209 case 'links':
210 case 'styleSheets':
211 case 'style':
212 case 'scripts':
213 case 'script':
214 case 'custom':
215 $realType = '_' . $type;
216 $this->{$realType} = array();
217 break;
218 }
219 }
220
221 222 223 224 225 226 227 228 229
230 public function setHeadData($data)
231 {
232 if (empty($data) || !is_array($data))
233 {
234 return;
235 }
236
237 $this->title = (isset($data['title']) && !empty($data['title'])) ? $data['title'] : $this->title;
238 $this->description = (isset($data['description']) && !empty($data['description'])) ? $data['description'] : $this->description;
239 $this->link = (isset($data['link']) && !empty($data['link'])) ? $data['link'] : $this->link;
240 $this->_metaTags = (isset($data['metaTags']) && !empty($data['metaTags'])) ? $data['metaTags'] : $this->_metaTags;
241 $this->_links = (isset($data['links']) && !empty($data['links'])) ? $data['links'] : $this->_links;
242 $this->_styleSheets = (isset($data['styleSheets']) && !empty($data['styleSheets'])) ? $data['styleSheets'] : $this->_styleSheets;
243 $this->_style = (isset($data['style']) && !empty($data['style'])) ? $data['style'] : $this->_style;
244 $this->_scripts = (isset($data['scripts']) && !empty($data['scripts'])) ? $data['scripts'] : $this->_scripts;
245 $this->_script = (isset($data['script']) && !empty($data['script'])) ? $data['script'] : $this->_script;
246 $this->_custom = (isset($data['custom']) && !empty($data['custom'])) ? $data['custom'] : $this->_custom;
247
248 if (isset($data['scriptText']) && !empty($data['scriptText']))
249 {
250 foreach ($data['scriptText'] as $key => $string)
251 {
252 JText::script($key, $string);
253 }
254 }
255
256 return $this;
257 }
258
259 260 261 262 263 264 265 266 267
268 public function mergeHeadData($data)
269 {
270 if (empty($data) || !is_array($data))
271 {
272 return;
273 }
274
275 $this->title = (isset($data['title']) && !empty($data['title']) && !stristr($this->title, $data['title']))
276 ? $this->title . $data['title']
277 : $this->title;
278 $this->description = (isset($data['description']) && !empty($data['description']) && !stristr($this->description, $data['description']))
279 ? $this->description . $data['description']
280 : $this->description;
281 $this->link = (isset($data['link'])) ? $data['link'] : $this->link;
282
283 if (isset($data['metaTags']))
284 {
285 foreach ($data['metaTags'] as $type1 => $data1)
286 {
287 $booldog = $type1 == 'http-equiv' ? true : false;
288
289 foreach ($data1 as $name2 => $data2)
290 {
291 $this->setMetaData($name2, $data2, $booldog);
292 }
293 }
294 }
295
296 $this->_links = (isset($data['links']) && !empty($data['links']) && is_array($data['links']))
297 ? array_unique(array_merge($this->_links, $data['links']), SORT_REGULAR)
298 : $this->_links;
299 $this->_styleSheets = (isset($data['styleSheets']) && !empty($data['styleSheets']) && is_array($data['styleSheets']))
300 ? array_merge($this->_styleSheets, $data['styleSheets'])
301 : $this->_styleSheets;
302
303 if (isset($data['style']))
304 {
305 foreach ($data['style'] as $type => $stdata)
306 {
307 if (!isset($this->_style[strtolower($type)]) || !stristr($this->_style[strtolower($type)], $stdata))
308 {
309 $this->addStyleDeclaration($stdata, $type);
310 }
311 }
312 }
313
314 $this->_scripts = (isset($data['scripts']) && !empty($data['scripts']) && is_array($data['scripts']))
315 ? array_merge($this->_scripts, $data['scripts'])
316 : $this->_scripts;
317
318 if (isset($data['script']))
319 {
320 foreach ($data['script'] as $type => $sdata)
321 {
322 if (!isset($this->_script[strtolower($type)]) || !stristr($this->_script[strtolower($type)], $sdata))
323 {
324 $this->addScriptDeclaration($sdata, $type);
325 }
326 }
327 }
328
329 $this->_custom = (isset($data['custom']) && !empty($data['custom']) && is_array($data['custom']))
330 ? array_unique(array_merge($this->_custom, $data['custom']))
331 : $this->_custom;
332
333 return $this;
334 }
335
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
352 public function addHeadLink($href, $relation, $relType = 'rel', $attribs = array())
353 {
354 $this->_links[$href]['relation'] = $relation;
355 $this->_links[$href]['relType'] = $relType;
356 $this->_links[$href]['attribs'] = $attribs;
357
358 return $this;
359 }
360
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
376 public function addFavicon($href, $type = 'image/vnd.microsoft.icon', $relation = 'shortcut icon')
377 {
378 $href = str_replace('\\', '/', $href);
379 $this->addHeadLink($href, $relation, 'rel', array('type' => $type));
380
381 return $this;
382 }
383
384 385 386 387 388 389 390 391 392
393 public function addCustomTag($html)
394 {
395 $this->_custom[] = trim($html);
396
397 return $this;
398 }
399
400 401 402 403 404 405 406
407 public function isHtml5()
408 {
409 return $this->_html5;
410 }
411
412 413 414 415 416 417 418 419 420
421 public function setHtml5($state)
422 {
423 if (is_bool($state))
424 {
425 $this->_html5 = $state;
426 }
427 }
428
429 430 431 432 433 434 435 436 437 438 439
440 public function getBuffer($type = null, $name = null, $attribs = array())
441 {
442
443 if ($type === null)
444 {
445 return parent::$_buffer;
446 }
447
448 $title = (isset($attribs['title'])) ? $attribs['title'] : null;
449
450 if (isset(parent::$_buffer[$type][$name][$title]))
451 {
452 return parent::$_buffer[$type][$name][$title];
453 }
454
455 $renderer = $this->loadRenderer($type);
456
457 if ($this->_caching == true && $type == 'modules')
458 {
459 $cache = JFactory::getCache('com_modules', '');
460 $hash = md5(serialize(array($name, $attribs, null, $renderer)));
461 $cbuffer = $cache->get('cbuffer_' . $type);
462
463 if (isset($cbuffer[$hash]))
464 {
465 return JCache::getWorkarounds($cbuffer[$hash], array('mergehead' => 1));
466 }
467 else
468 {
469 $options = array();
470 $options['nopathway'] = 1;
471 $options['nomodules'] = 1;
472 $options['modulemode'] = 1;
473
474 $this->setBuffer($renderer->render($name, $attribs, null), $type, $name);
475 $data = parent::$_buffer[$type][$name][$title];
476
477 $tmpdata = JCache::setWorkarounds($data, $options);
478
479 $cbuffer[$hash] = $tmpdata;
480
481 $cache->store($cbuffer, 'cbuffer_' . $type);
482 }
483 }
484 else
485 {
486 $this->setBuffer($renderer->render($name, $attribs, null), $type, $name, $title);
487 }
488
489 return parent::$_buffer[$type][$name][$title];
490 }
491
492 493 494 495 496 497 498 499 500 501
502 public function setBuffer($content, $options = array())
503 {
504
505 if (func_num_args() > 1 && !is_array($options))
506 {
507 $args = func_get_args();
508 $options = array();
509 $options['type'] = $args[1];
510 $options['name'] = (isset($args[2])) ? $args[2] : null;
511 $options['title'] = (isset($args[3])) ? $args[3] : null;
512 }
513
514 parent::$_buffer[$options['type']][$options['name']][$options['title']] = $content;
515
516 return $this;
517 }
518
519 520 521 522 523 524 525 526 527
528 public function parse($params = array())
529 {
530 return $this->_fetchTemplate($params)->_parseTemplate();
531 }
532
533 534 535 536 537 538 539 540 541 542
543 public function render($caching = false, $params = array())
544 {
545 $this->_caching = $caching;
546
547 if (empty($this->_template))
548 {
549 $this->parse($params);
550 }
551
552 $data = $this->_renderTemplate();
553 parent::render();
554
555 return $data;
556 }
557
558 559 560 561 562 563 564 565 566
567 public function countModules($condition)
568 {
569 $operators = '(\+|\-|\*|\/|==|\!=|\<\>|\<|\>|\<=|\>=|and|or|xor)';
570 $words = preg_split('# ' . $operators . ' #', $condition, null, PREG_SPLIT_DELIM_CAPTURE);
571
572 if (count($words) === 1)
573 {
574 $name = strtolower($words[0]);
575 $result = ((isset(parent::$_buffer['modules'][$name])) && (parent::$_buffer['modules'][$name] === false))
576 ? 0 : count(JModuleHelper::getModules($name));
577
578 return $result;
579 }
580
581 JLog::add('Using an expression in JDocumentHtml::countModules() is deprecated.', JLog::WARNING, 'deprecated');
582
583 for ($i = 0, $n = count($words); $i < $n; $i += 2)
584 {
585
586 $name = strtolower($words[$i]);
587 $words[$i] = ((isset(parent::$_buffer['modules'][$name])) && (parent::$_buffer['modules'][$name] === false))
588 ? 0
589 : count(JModuleHelper::getModules($name));
590 }
591
592 $str = 'return ' . implode(' ', $words) . ';';
593
594 return eval($str);
595 }
596
597 598 599 600 601 602 603
604 public function ()
605 {
606 static $children;
607
608 if (!isset($children))
609 {
610 $db = JFactory::getDbo();
611 $app = JFactory::getApplication();
612 $menu = $app->getMenu();
613 $active = $menu->getActive();
614 $children = 0;
615
616 if ($active)
617 {
618 $query = $db->getQuery(true)
619 ->select('COUNT(*)')
620 ->from('#__menu')
621 ->where('parent_id = ' . $active->id)
622 ->where('published = 1');
623 $db->setQuery($query);
624 $children = $db->loadResult();
625 }
626 }
627
628 return $children;
629 }
630
631 632 633 634 635 636 637 638 639 640
641 protected function _loadTemplate($directory, $filename)
642 {
643 $contents = '';
644
645
646 if (file_exists($directory . '/' . $filename))
647 {
648
649 $this->_file = $directory . '/' . $filename;
650
651
652 ob_start();
653 require $directory . '/' . $filename;
654 $contents = ob_get_contents();
655 ob_end_clean();
656 }
657
658
659 $icon = '/favicon.ico';
660
661 foreach (array($directory, JPATH_BASE) as $dir)
662 {
663 if (file_exists($dir . $icon))
664 {
665 $path = str_replace(JPATH_BASE, '', $dir);
666 $path = str_replace('\\', '/', $path);
667 $this->addFavicon(JUri::base(true) . $path . $icon);
668 break;
669 }
670 }
671
672 return $contents;
673 }
674
675 676 677 678 679 680 681 682 683
684 protected function _fetchTemplate($params = array())
685 {
686
687 $directory = isset($params['directory']) ? $params['directory'] : 'templates';
688 $filter = JFilterInput::getInstance();
689 $template = $filter->clean($params['template'], 'cmd');
690 $file = $filter->clean($params['file'], 'cmd');
691
692 if (!file_exists($directory . '/' . $template . '/' . $file))
693 {
694 $template = 'system';
695 }
696
697 if (!file_exists($directory . '/' . $template . '/' . $file))
698 {
699 $file = 'index.php';
700 }
701
702
703 $lang = JFactory::getLanguage();
704
705
706 $lang->load('tpl_' . $template, JPATH_BASE, null, false, true)
707 || $lang->load('tpl_' . $template, $directory . '/' . $template, null, false, true);
708
709
710 $this->template = $template;
711 $this->baseurl = JUri::base(true);
712 $this->params = isset($params['params']) ? $params['params'] : new Registry;
713
714
715 $this->_template = $this->_loadTemplate($directory . '/' . $template, $file);
716
717 return $this;
718 }
719
720 721 722 723 724 725 726
727 protected function _parseTemplate()
728 {
729 $matches = array();
730
731 if (preg_match_all('#<jdoc:include\ type="([^"]+)"(.*)\/>#iU', $this->_template, $matches))
732 {
733 $template_tags_first = array();
734 $template_tags_last = array();
735
736
737 for ($i = count($matches[0]) - 1; $i >= 0; $i--)
738 {
739 $type = $matches[1][$i];
740 $attribs = empty($matches[2][$i]) ? array() : JUtility::parseAttributes($matches[2][$i]);
741 $name = isset($attribs['name']) ? $attribs['name'] : null;
742
743
744 if ($type == 'module' || $type == 'modules')
745 {
746 $template_tags_first[$matches[0][$i]] = array('type' => $type, 'name' => $name, 'attribs' => $attribs);
747 }
748 else
749 {
750 $template_tags_last[$matches[0][$i]] = array('type' => $type, 'name' => $name, 'attribs' => $attribs);
751 }
752 }
753
754 $template_tags_last = array_reverse($template_tags_last);
755
756 $this->_template_tags = $template_tags_first + $template_tags_last;
757 }
758
759 return $this;
760 }
761
762 763 764 765 766 767 768
769 protected function _renderTemplate()
770 {
771 $replace = array();
772 $with = array();
773
774 foreach ($this->_template_tags as $jdoc => $args)
775 {
776 $replace[] = $jdoc;
777 $with[] = $this->getBuffer($args['type'], $args['name'], $args['attribs']);
778 }
779
780 return str_replace($replace, $with, $this->_template);
781 }
782 }
783