1 <?php
2 3 4 5 6 7 8
9
10 defined('JPATH_PLATFORM') or die;
11
12 13 14 15 16 17 18
19 class JLayoutFile extends JLayoutBase
20 {
21 22 23 24 25 26
27 protected static $cache = array();
28
29 30 31 32 33 34
35 protected $layoutId = '';
36
37 38 39 40 41 42
43 protected $basePath = null;
44
45 46 47 48 49 50
51 protected $fullPath = null;
52
53 54 55 56 57 58
59 protected $includePaths = array();
60
61 62 63 64 65 66 67 68 69
70 public function __construct($layoutId, $basePath = null, $options = null)
71 {
72
73 $this->setOptions($options);
74
75
76 $this->setLayout($layoutId);
77 $this->basePath = $basePath;
78
79
80 $this->setComponent($this->options->get('component', 'auto'));
81 $this->setClient($this->options->get('client', 'auto'));
82 }
83
84 85 86 87 88 89 90 91 92
93 public function render($displayData = array())
94 {
95 $this->clearDebugMessages();
96
97
98 $layoutOutput = '';
99
100
101 if (is_array($displayData))
102 {
103 $displayData = array_merge($this->data, $displayData);
104 }
105
106
107 $path = $this->getPath();
108
109 if ($this->isDebugEnabled())
110 {
111 echo '<pre>' . $this->renderDebugMessages() . '</pre>';
112 }
113
114
115 if (empty($path))
116 {
117 return $layoutOutput;
118 }
119
120 ob_start();
121 include $path;
122 $layoutOutput .= ob_get_contents();
123 ob_end_clean();
124
125 return $layoutOutput;
126 }
127
128 129 130 131 132 133 134
135 protected function getPath()
136 {
137 JLoader::import('joomla.filesystem.path');
138
139 $layoutId = $this->getLayoutId();
140 $includePaths = $this->getIncludePaths();
141 $suffixes = $this->getSuffixes();
142
143 $this->addDebugMessage('<strong>Layout:</strong> ' . $this->layoutId);
144
145 if (!$layoutId)
146 {
147 $this->addDebugMessage('<strong>There is no active layout</strong>');
148
149 return;
150 }
151
152 if (!$includePaths)
153 {
154 $this->addDebugMessage('<strong>There are no folders to search for layouts:</strong> ' . $layoutId);
155
156 return;
157 }
158
159 $hash = md5(
160 json_encode(
161 array(
162 'paths' => $includePaths,
163 'suffixes' => $suffixes,
164 )
165 )
166 );
167
168 if (!empty(static::$cache[$layoutId][$hash]))
169 {
170 $this->addDebugMessage('<strong>Cached path:</strong> ' . static::$cache[$layoutId][$hash]);
171
172 return static::$cache[$layoutId][$hash];
173 }
174
175 $this->addDebugMessage('<strong>Include Paths:</strong> ' . print_r($includePaths, true));
176
177
178 if ($suffixes)
179 {
180 $this->addDebugMessage('<strong>Suffixes:</strong> ' . print_r($suffixes, true));
181
182 foreach ($suffixes as $suffix)
183 {
184 $rawPath = str_replace('.', '/', $this->layoutId) . '.' . $suffix . '.php';
185 $this->addDebugMessage('<strong>Searching layout for:</strong> ' . $rawPath);
186
187 if ($foundLayout = JPath::find($this->includePaths, $rawPath))
188 {
189 $this->addDebugMessage('<strong>Found layout:</strong> ' . $this->fullPath);
190
191 static::$cache[$layoutId][$hash] = $foundLayout;
192
193 return static::$cache[$layoutId][$hash];
194 }
195 }
196 }
197
198
199 $rawPath = str_replace('.', '/', $this->layoutId) . '.php';
200 $this->addDebugMessage('<strong>Searching layout for:</strong> ' . $rawPath);
201
202 $foundLayout = JPath::find($this->includePaths, $rawPath);
203
204 if (!$foundLayout)
205 {
206 $this->addDebugMessage('<strong>Unable to find layout: </strong> ' . $layoutId);
207
208 return;
209 }
210
211 $this->addDebugMessage('<strong>Found layout:</strong> ' . $foundLayout);
212
213 static::$cache[$layoutId][$hash] = $foundLayout;
214
215 return static::$cache[$layoutId][$hash];
216 }
217
218 219 220 221 222 223 224 225 226
227 public function addIncludePath($path)
228 {
229 $this->addIncludePaths($path);
230
231 return $this;
232 }
233
234 235 236 237 238 239 240 241 242
243 public function addIncludePaths($paths)
244 {
245 if (empty($paths))
246 {
247 return $this;
248 }
249
250 $includePaths = $this->getIncludePaths();
251
252 if (is_array($paths))
253 {
254 $includePaths = array_unique(array_merge($paths, $includePaths));
255 }
256 else
257 {
258 array_unshift($includePaths, $paths);
259 }
260
261 $this->setIncludePaths($includePaths);
262
263 return $this;
264 }
265
266 267 268 269 270 271 272
273 public function clearIncludePaths()
274 {
275 $this->includePaths = array();
276
277 return $this;
278 }
279
280 281 282 283 284 285 286
287 public function getIncludePaths()
288 {
289 if (empty($this->includePaths))
290 {
291 $this->includePaths = $this->getDefaultIncludePaths();
292 }
293
294 return $this->includePaths;
295 }
296
297 298 299 300 301 302 303
304 public function getLayoutId()
305 {
306 return $this->layoutId;
307 }
308
309 310 311 312 313 314 315
316 public function getSuffixes()
317 {
318 return $this->getOptions()->get('suffixes', array());
319 }
320
321 322 323 324 325 326 327 328
329 public function loadLanguageSuffixes()
330 {
331 $lang = JFactory::getLanguage();
332
333 $langTag = $lang->getTag();
334 $langParts = explode('-', $langTag);
335
336 $suffixes = array($langTag, $langParts[0]);
337 $suffixes[] = $lang->isRTL() ? 'rtl' : 'ltr';
338
339 $this->setSuffixes($suffixes);
340
341 return $this;
342 }
343
344 345 346 347 348 349 350 351
352 public function loadVersionSuffixes()
353 {
354 $cmsVersion = new JVersion;
355
356
357 $fullVersion = 'j' . str_replace('.', '', $cmsVersion->getShortVersion());
358
359
360 $suffixes = array(
361 $fullVersion,
362 substr($fullVersion, 0, 3),
363 substr($fullVersion, 0, 2),
364 );
365
366 $this->setSuffixes(array_unique($suffixes));
367
368 return $this;
369 }
370
371 372 373 374 375 376 377 378 379
380 public function removeIncludePath($path)
381 {
382 $this->removeIncludePaths($path);
383
384 return $this;
385 }
386
387 388 389 390 391 392 393 394 395
396 public function removeIncludePaths($paths)
397 {
398 if (!empty($paths))
399 {
400 $paths = (array) $paths;
401
402 $this->includePaths = array_diff($this->includePaths, $paths);
403 }
404
405 return $this;
406 }
407
408 409 410 411 412 413 414 415 416
417 protected function validComponent($option = null)
418 {
419
420 $component = ($option !== null) ? $option : $this->options->get('component', null);
421
422
423 if (!empty($component) && substr_count($component, 'com_'))
424 {
425
426 return JComponentHelper::isEnabled($component);
427 }
428
429 return false;
430 }
431
432 433 434 435 436 437 438 439 440
441 public function setComponent($option)
442 {
443 $component = null;
444
445 switch ((string) $option)
446 {
447 case 'none':
448 $component = null;
449 break;
450
451 case 'auto':
452 $component = JApplicationHelper::getComponentName();
453 break;
454
455 default:
456 $component = $option;
457 break;
458 }
459
460
461 if (!$this->validComponent($component))
462 {
463 $component = null;
464 }
465
466 $this->options->set('component', $component);
467
468
469 $this->refreshIncludePaths();
470 }
471
472 473 474 475 476 477 478 479 480
481 public function setClient($client)
482 {
483
484 switch ((string) $client)
485 {
486 case 'site':
487 case '0':
488 $client = 0;
489 break;
490
491 case 'admin':
492 case '1':
493 $client = 1;
494 break;
495
496 default:
497 $client = (int) JFactory::getApplication()->isClient('administrator');
498 break;
499 }
500
501 $this->options->set('client', $client);
502
503
504 $this->refreshIncludePaths();
505 }
506
507 508 509 510 511 512 513 514 515 516 517
518 public function setLayout($layoutId)
519 {
520
521 JLog::add(__METHOD__ . '() is deprecated, use JLayoutFile::setLayoutId() instead.', JLog::WARNING, 'deprecated');
522
523 return $this->setLayoutId($layoutId);
524 }
525
526 527 528 529 530 531 532 533 534
535 public function setLayoutId($layoutId)
536 {
537 $this->layoutId = $layoutId;
538 $this->fullPath = null;
539
540 return $this;
541 }
542
543 544 545 546 547 548 549 550 551
552 protected function refreshIncludePaths()
553 {
554
555 JLog::add(__METHOD__ . '() is deprecated, use JLayoutFile::clearIncludePaths() instead.', JLog::WARNING, 'deprecated');
556
557 $this->clearIncludePaths();
558
559 return $this;
560 }
561
562 563 564 565 566 567 568
569 public function getDefaultIncludePaths()
570 {
571
572 $paths = array();
573
574
575 if ($this->basePath !== null)
576 {
577 $paths[] = rtrim($this->basePath, DIRECTORY_SEPARATOR);
578 }
579
580
581 $component = $this->options->get('component', null);
582
583 if (!empty($component))
584 {
585
586 $paths[] = JPATH_THEMES . '/' . JFactory::getApplication()->getTemplate() . '/html/layouts/' . $component;
587
588
589 if ($this->options->get('client') == 0)
590 {
591 $paths[] = JPATH_SITE . '/components/' . $component . '/layouts';
592 }
593 else
594 {
595 $paths[] = JPATH_ADMINISTRATOR . '/components/' . $component . '/layouts';
596 }
597 }
598
599
600 $paths[] = JPATH_THEMES . '/' . JFactory::getApplication()->getTemplate() . '/html/layouts';
601
602
603 $paths[] = JPATH_ROOT . '/layouts';
604
605 return $paths;
606 }
607
608 609 610 611 612 613 614 615 616
617 public function setIncludePaths($paths)
618 {
619 $this->includePaths = (array) $paths;
620
621 return $this;
622 }
623
624 625 626 627 628 629 630 631 632
633 public function setSuffixes(array $suffixes)
634 {
635 $this->options->set('suffixes', $suffixes);
636
637 return $this;
638 }
639
640 641 642 643 644 645 646 647 648 649
650 public function sublayout($layoutId, $displayData)
651 {
652
653 if (!empty($this->layoutId))
654 {
655 $layoutId = $this->layoutId . '.' . $layoutId;
656 }
657
658 $sublayout = new static($layoutId, $this->basePath, $this->options);
659 $sublayout->includePaths = $this->includePaths;
660
661 return $sublayout->render($displayData);
662 }
663 }
664