1 <?php
2 /**
3 * @package FrameworkOnFramework
4 * @subpackage view
5 * @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
6 * @license GNU General Public License version 2 or later; see LICENSE.txt
7 */
8 // Protect from unauthorized access
9 defined('FOF_INCLUDED') or die;
10
11 /**
12 * FrameworkOnFramework View class. The View is the MVC component which gets the
13 * raw data from a Model and renders it in a way that makes sense. The usual
14 * rendering is HTML, but you can also output JSON, CSV, XML, or even media
15 * (images, videos, ...) and documents (Word, PDF, Excel...).
16 *
17 * @package FrameworkOnFramework
18 * @since 1.0
19 */
20 abstract class FOFView extends FOFUtilsObject
21 {
22 /**
23 * The name of the view
24 *
25 * @var array
26 */
27 protected $_name = null;
28
29 /**
30 * Registered models
31 *
32 * @var array
33 */
34 protected $_models = array();
35
36 /**
37 * The base path of the view
38 *
39 * @var string
40 */
41 protected $_basePath = null;
42
43 /**
44 * The default model
45 *
46 * @var string
47 */
48 protected $_defaultModel = null;
49
50 /**
51 * Layout name
52 *
53 * @var string
54 */
55 protected $_layout = 'default';
56
57 /**
58 * Layout extension
59 *
60 * @var string
61 */
62 protected $_layoutExt = 'php';
63
64 /**
65 * Layout template
66 *
67 * @var string
68 */
69 protected $_layoutTemplate = '_';
70
71 /**
72 * The set of search directories for resources (templates)
73 *
74 * @var array
75 */
76 protected $_path = array('template' => array(), 'helper' => array());
77
78 /**
79 * The name of the default template source file.
80 *
81 * @var string
82 */
83 protected $_template = null;
84
85 /**
86 * The output of the template script.
87 *
88 * @var string
89 */
90 protected $_output = null;
91
92 /**
93 * Callback for escaping.
94 *
95 * @var string
96 * @deprecated 13.3
97 */
98 protected $_escape = 'htmlspecialchars';
99
100 /**
101 * Charset to use in escaping mechanisms; defaults to urf8 (UTF-8)
102 *
103 * @var string
104 */
105 protected $_charset = 'UTF-8';
106
107 /**
108 * The available renderer objects we can use to render views
109 *
110 * @var array Contains objects of the FOFRenderAbstract class
111 */
112 public static $renderers = array();
113
114 /**
115 * Cache of the configuration array
116 *
117 * @var array
118 */
119 protected $config = array();
120
121 /**
122 * The input object of this view
123 *
124 * @var FOFInput
125 */
126 protected $input = null;
127
128 /**
129 * The chosen renderer object
130 *
131 * @var FOFRenderAbstract
132 */
133 protected $rendererObject = null;
134
135 /**
136 * Should I run the pre-render step?
137 *
138 * @var boolean
139 */
140 protected $doPreRender = true;
141
142 /**
143 * Should I run the post-render step?
144 *
145 * @var boolean
146 */
147 protected $doPostRender = true;
148
149 /**
150 * Public constructor. Instantiates a FOFView object.
151 *
152 * @param array $config The configuration data array
153 */
154 public function __construct($config = array())
155 {
156 // Make sure $config is an array
157 if (is_object($config))
158 {
159 $config = (array) $config;
160 }
161 elseif (!is_array($config))
162 {
163 $config = array();
164 }
165
166 // Get the input
167 if (array_key_exists('input', $config))
168 {
169 if ($config['input'] instanceof FOFInput)
170 {
171 $this->input = $config['input'];
172 }
173 else
174 {
175 $this->input = new FOFInput($config['input']);
176 }
177 }
178 else
179 {
180 $this->input = new FOFInput;
181 }
182
183 parent::__construct($config);
184
185 $component = 'com_foobar';
186
187 // Get the component name
188 if (array_key_exists('input', $config))
189 {
190 if ($config['input'] instanceof FOFInput)
191 {
192 $tmpInput = $config['input'];
193 }
194 else
195 {
196 $tmpInput = new FOFInput($config['input']);
197 }
198
199 $component = $tmpInput->getCmd('option', '');
200 }
201 else
202 {
203 $tmpInput = $this->input;
204 }
205
206 if (array_key_exists('option', $config))
207 {
208 if ($config['option'])
209 {
210 $component = $config['option'];
211 }
212 }
213
214 $config['option'] = $component;
215
216 // Get the view name
217 $view = null;
218 if (array_key_exists('input', $config))
219 {
220 $view = $tmpInput->getCmd('view', '');
221 }
222
223 if (array_key_exists('view', $config))
224 {
225 if ($config['view'])
226 {
227 $view = $config['view'];
228 }
229 }
230
231 $config['view'] = $view;
232
233 // Set the component and the view to the input array
234
235 if (array_key_exists('input', $config))
236 {
237 $tmpInput->set('option', $config['option']);
238 $tmpInput->set('view', $config['view']);
239 }
240
241 // Set the view name
242
243 if (array_key_exists('name', $config))
244 {
245 $this->_name = $config['name'];
246 }
247 else
248 {
249 $this->_name = $config['view'];
250 }
251
252 $tmpInput->set('view', $this->_name);
253 $config['input'] = $tmpInput;
254 $config['name'] = $this->_name;
255 $config['view'] = $this->_name;
256
257 // Get the component directories
258 $componentPaths = FOFPlatform::getInstance()->getComponentBaseDirs($config['option']);
259
260 // Set the charset (used by the variable escaping functions)
261
262 if (array_key_exists('charset', $config))
263 {
264 FOFPlatform::getInstance()->logDeprecated('Setting a custom charset for escaping in FOFView\'s constructor is deprecated. Override FOFView::escape() instead.');
265 $this->_charset = $config['charset'];
266 }
267
268 // User-defined escaping callback
269
270 if (array_key_exists('escape', $config))
271 {
272 $this->setEscape($config['escape']);
273 }
274
275 // Set a base path for use by the view
276
277 if (array_key_exists('base_path', $config))
278 {
279 $this->_basePath = $config['base_path'];
280 }
281 else
282 {
283 $this->_basePath = $componentPaths['main'];
284 }
285
286 // Set the default template search path
287
288 if (array_key_exists('template_path', $config))
289 {
290 // User-defined dirs
291 $this->_setPath('template', $config['template_path']);
292 }
293 else
294 {
295 $altView = FOFInflector::isSingular($this->getName()) ? FOFInflector::pluralize($this->getName()) : FOFInflector::singularize($this->getName());
296 $this->_setPath('template', $this->_basePath . '/views/' . $altView . '/tmpl');
297 $this->_addPath('template', $this->_basePath . '/views/' . $this->getName() . '/tmpl');
298 }
299
300 // Set the default helper search path
301
302 if (array_key_exists('helper_path', $config))
303 {
304 // User-defined dirs
305 $this->_setPath('helper', $config['helper_path']);
306 }
307 else
308 {
309 $this->_setPath('helper', $this->_basePath . '/helpers');
310 }
311
312 // Set the layout
313
314 if (array_key_exists('layout', $config))
315 {
316 $this->setLayout($config['layout']);
317 }
318 else
319 {
320 $this->setLayout('default');
321 }
322
323 $this->config = $config;
324
325 if (!FOFPlatform::getInstance()->isCli())
326 {
327 $this->baseurl = FOFPlatform::getInstance()->URIbase(true);
328
329 $fallback = FOFPlatform::getInstance()->getTemplateOverridePath($component) . '/' . $this->getName();
330 $this->_addPath('template', $fallback);
331 }
332 }
333
334 /**
335 * Loads a template given any path. The path is in the format:
336 * [admin|site]:com_foobar/viewname/templatename
337 * e.g. admin:com_foobar/myview/default
338 *
339 * This function searches for Joomla! version override templates. For example,
340 * if you have run this under Joomla! 3.0 and you try to load
341 * admin:com_foobar/myview/default it will automatically search for the
342 * template files default.j30.php, default.j3.php and default.php, in this
343 * order.
344 *
345 * @param string $path See above
346 * @param array $forceParams A hash array of variables to be extracted in the local scope of the template file
347 *
348 * @return boolean False if loading failed
349 */
350 public function loadAnyTemplate($path = '', $forceParams = array())
351 {
352 // Automatically check for a Joomla! version specific override
353 $throwErrorIfNotFound = true;
354
355 $suffixes = FOFPlatform::getInstance()->getTemplateSuffixes();
356
357 foreach ($suffixes as $suffix)
358 {
359 if (substr($path, -strlen($suffix)) == $suffix)
360 {
361 $throwErrorIfNotFound = false;
362 break;
363 }
364 }
365
366 if ($throwErrorIfNotFound)
367 {
368 foreach ($suffixes as $suffix)
369 {
370 $result = $this->loadAnyTemplate($path . $suffix, $forceParams);
371
372 if ($result !== false)
373 {
374 return $result;
375 }
376 }
377 }
378
379 $layoutTemplate = $this->getLayoutTemplate();
380
381 // Parse the path
382 $templateParts = $this->_parseTemplatePath($path);
383
384 // Get the paths
385 $componentPaths = FOFPlatform::getInstance()->getComponentBaseDirs($templateParts['component']);
386 $templatePath = FOFPlatform::getInstance()->getTemplateOverridePath($templateParts['component']);
387
388 // Get the default paths
389 $paths = array();
390 $paths[] = $templatePath . '/' . $templateParts['view'];
391 $paths[] = ($templateParts['admin'] ? $componentPaths['admin'] : $componentPaths['site']) . '/views/' . $templateParts['view'] . '/tmpl';
392
393 if (isset($this->_path) || property_exists($this, '_path'))
394 {
395 $paths = array_merge($paths, $this->_path['template']);
396 }
397 elseif (isset($this->path) || property_exists($this, 'path'))
398 {
399 $paths = array_merge($paths, $this->path['template']);
400 }
401
402 // Look for a template override
403
404 if (isset($layoutTemplate) && $layoutTemplate != '_' && $layoutTemplate != $template)
405 {
406 $apath = array_shift($paths);
407 array_unshift($paths, str_replace($template, $layoutTemplate, $apath));
408 }
409
410 $filetofind = $templateParts['template'] . '.php';
411 $filesystem = FOFPlatform::getInstance()->getIntegrationObject('filesystem');
412
413 $this->_tempFilePath = $filesystem->pathFind($paths, $filetofind);
414
415 if ($this->_tempFilePath)
416 {
417 // Unset from local scope
418 unset($template);
419 unset($layoutTemplate);
420 unset($paths);
421 unset($path);
422 unset($filetofind);
423
424 // Never allow a 'this' property
425
426 if (isset($this->this))
427 {
428 unset($this->this);
429 }
430
431 // Force parameters into scope
432
433 if (!empty($forceParams))
434 {
435 extract($forceParams);
436 }
437
438 // Start capturing output into a buffer
439 ob_start();
440
441 // Include the requested template filename in the local scope (this will execute the view logic).
442 include $this->_tempFilePath;
443
444 // Done with the requested template; get the buffer and clear it.
445 $this->_output = ob_get_contents();
446 ob_end_clean();
447
448 return $this->_output;
449 }
450 else
451 {
452 if ($throwErrorIfNotFound)
453 {
454 return new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_LAYOUTFILE_NOT_FOUND', $path), 500);
455 }
456
457 return false;
458 }
459 }
460
461 /**
462 * Overrides the default method to execute and display a template script.
463 * Instead of loadTemplate is uses loadAnyTemplate which allows for automatic
464 * Joomla! version overrides. A little slice of awesome pie!
465 *
466 * @param string $tpl The name of the template file to parse
467 *
468 * @return mixed A string if successful, otherwise a JError object.
469 */
470 public function display($tpl = null)
471 {
472 FOFPlatform::getInstance()->setErrorHandling(E_ALL, 'ignore');
473
474 $result = $this->loadTemplate($tpl);
475
476 if ($result instanceof Exception)
477 {
478 FOFPlatform::getInstance()->raiseError($result->getCode(), $result->getMessage());
479
480 return $result;
481 }
482
483 echo $result;
484 }
485
486 /**
487 * Assigns variables to the view script via differing strategies.
488 *
489 * This method is overloaded; you can assign all the properties of
490 * an object, an associative array, or a single value by name.
491 *
492 * You are not allowed to set variables that begin with an underscore;
493 * these are either private properties for FOFView or private variables
494 * within the template script itself.
495 *
496 * @return boolean True on success, false on failure.
497 *
498 * @deprecated 13.3 Use native PHP syntax.
499 */
500 public function assign()
501 {
502 FOFPlatform::getInstance()->logDeprecated(__CLASS__ . '::' . __METHOD__ . ' is deprecated. Use native PHP syntax.');
503
504 // Get the arguments; there may be 1 or 2.
505 $arg0 = @func_get_arg(0);
506 $arg1 = @func_get_arg(1);
507
508 // Assign by object
509
510 if (is_object($arg0))
511 {
512 // Assign public properties
513 foreach (get_object_vars($arg0) as $key => $val)
514 {
515 if (substr($key, 0, 1) != '_')
516 {
517 $this->$key = $val;
518 }
519 }
520
521 return true;
522 }
523
524 // Assign by associative array
525
526 if (is_array($arg0))
527 {
528 foreach ($arg0 as $key => $val)
529 {
530 if (substr($key, 0, 1) != '_')
531 {
532 $this->$key = $val;
533 }
534 }
535
536 return true;
537 }
538
539 // Assign by string name and mixed value. We use array_key_exists() instead of isset()
540 // because isset() fails if the value is set to null.
541
542 if (is_string($arg0) && substr($arg0, 0, 1) != '_' && func_num_args() > 1)
543 {
544 $this->$arg0 = $arg1;
545
546 return true;
547 }
548
549 // $arg0 was not object, array, or string.
550 return false;
551 }
552
553 /**
554 * Assign variable for the view (by reference).
555 *
556 * You are not allowed to set variables that begin with an underscore;
557 * these are either private properties for FOFView or private variables
558 * within the template script itself.
559 *
560 * @param string $key The name for the reference in the view.
561 * @param mixed &$val The referenced variable.
562 *
563 * @return boolean True on success, false on failure.
564 *
565 * @deprecated 13.3 Use native PHP syntax.
566 */
567 public function assignRef($key, &$val)
568 {
569 FOFPlatform::getInstance()->logDeprecated(__CLASS__ . '::' . __METHOD__ . ' is deprecated. Use native PHP syntax.');
570
571 if (is_string($key) && substr($key, 0, 1) != '_')
572 {
573 $this->$key = &$val;
574
575 return true;
576 }
577
578 return false;
579 }
580
581 /**
582 * Escapes a value for output in a view script.
583 *
584 * If escaping mechanism is either htmlspecialchars or htmlentities, uses
585 * {@link $_encoding} setting.
586 *
587 * @param mixed $var The output to escape.
588 *
589 * @return mixed The escaped value.
590 */
591 public function escape($var)
592 {
593 if (in_array($this->_escape, array('htmlspecialchars', 'htmlentities')))
594 {
595 return call_user_func($this->_escape, $var, ENT_COMPAT, $this->_charset);
596 }
597
598 return call_user_func($this->_escape, $var);
599 }
600
601 /**
602 * Method to get data from a registered model or a property of the view
603 *
604 * @param string $property The name of the method to call on the model or the property to get
605 * @param string $default The name of the model to reference or the default value [optional]
606 *
607 * @return mixed The return value of the method
608 */
609 public function get($property, $default = null)
610 {
611 // If $model is null we use the default model
612 if (is_null($default))
613 {
614 $model = $this->_defaultModel;
615 }
616 else
617 {
618 $model = strtolower($default);
619 }
620
621 // First check to make sure the model requested exists
622 if (isset($this->_models[$model]))
623 {
624 // Model exists, let's build the method name
625 $method = 'get' . ucfirst($property);
626
627 // Does the method exist?
628 if (method_exists($this->_models[$model], $method))
629 {
630 // The method exists, let's call it and return what we get
631 $result = $this->_models[$model]->$method();
632
633 return $result;
634 }
635 }
636
637 // Degrade to FOFUtilsObject::get
638 $result = parent::get($property, $default);
639
640 return $result;
641 }
642
643 /**
644 * Method to get the model object
645 *
646 * @param string $name The name of the model (optional)
647 *
648 * @return mixed FOFModel object
649 */
650 public function getModel($name = null)
651 {
652 if ($name === null)
653 {
654 $name = $this->_defaultModel;
655 }
656
657 return $this->_models[strtolower($name)];
658 }
659
660 /**
661 * Get the layout.
662 *
663 * @return string The layout name
664 */
665 public function getLayout()
666 {
667 return $this->_layout;
668 }
669
670 /**
671 * Get the layout template.
672 *
673 * @return string The layout template name
674 */
675 public function getLayoutTemplate()
676 {
677 return $this->_layoutTemplate;
678 }
679
680 /**
681 * Method to get the view name
682 *
683 * The model name by default parsed using the classname, or it can be set
684 * by passing a $config['name'] in the class constructor
685 *
686 * @return string The name of the model
687 */
688 public function getName()
689 {
690 if (empty($this->_name))
691 {
692 $classname = get_class($this);
693 $viewpos = strpos($classname, 'View');
694
695 if ($viewpos === false)
696 {
697 throw new Exception(JText::_('JLIB_APPLICATION_ERROR_VIEW_GET_NAME'), 500);
698 }
699
700 $this->_name = strtolower(substr($classname, $viewpos + 4));
701 }
702
703 return $this->_name;
704 }
705
706 /**
707 * Method to add a model to the view.
708 *
709 * @param FOFMOdel $model The model to add to the view.
710 * @param boolean $default Is this the default model?
711 * @param String $name optional index name to store the model
712 *
713 * @return object The added model.
714 */
715 public function setModel($model, $default = false, $name = null)
716 {
717 if (is_null($name))
718 {
719 $name = $model->getName();
720 }
721
722 $name = strtolower($name);
723
724 $this->_models[$name] = $model;
725
726 if ($default)
727 {
728 $this->_defaultModel = $name;
729 }
730
731 return $model;
732 }
733
734 /**
735 * Sets the layout name to use
736 *
737 * @param string $layout The layout name or a string in format <template>:<layout file>
738 *
739 * @return string Previous value.
740 */
741 public function setLayout($layout)
742 {
743 $previous = $this->_layout;
744
745 if (strpos($layout, ':') === false)
746 {
747 $this->_layout = $layout;
748 }
749 else
750 {
751 // Convert parameter to array based on :
752 $temp = explode(':', $layout);
753 $this->_layout = $temp[1];
754
755 // Set layout template
756 $this->_layoutTemplate = $temp[0];
757 }
758
759 return $previous;
760 }
761
762 /**
763 * Allows a different extension for the layout files to be used
764 *
765 * @param string $value The extension.
766 *
767 * @return string Previous value
768 */
769 public function setLayoutExt($value)
770 {
771 $previous = $this->_layoutExt;
772
773 if ($value = preg_replace('#[^A-Za-z0-9]#', '', trim($value)))
774 {
775 $this->_layoutExt = $value;
776 }
777
778 return $previous;
779 }
780
781 /**
782 * Sets the _escape() callback.
783 *
784 * @param mixed $spec The callback for _escape() to use.
785 *
786 * @return void
787 *
788 * @deprecated 2.1 Override FOFView::escape() instead.
789 */
790 public function setEscape($spec)
791 {
792 FOFPlatform::getInstance()->logDeprecated(__CLASS__ . '::' . __METHOD__ . ' is deprecated. Override FOFView::escape() instead.');
793
794 $this->_escape = $spec;
795 }
796
797 /**
798 * Adds to the stack of view script paths in LIFO order.
799 *
800 * @param mixed $path A directory path or an array of paths.
801 *
802 * @return void
803 */
804 public function addTemplatePath($path)
805 {
806 $this->_addPath('template', $path);
807 }
808
809 /**
810 * Adds to the stack of helper script paths in LIFO order.
811 *
812 * @param mixed $path A directory path or an array of paths.
813 *
814 * @return void
815 */
816 public function addHelperPath($path)
817 {
818 $this->_addPath('helper', $path);
819 }
820
821 /**
822 * Overrides the built-in loadTemplate function with an FOF-specific one.
823 * Our overriden function uses loadAnyTemplate to provide smarter view
824 * template loading.
825 *
826 * @param string $tpl The name of the template file to parse
827 * @param boolean $strict Should we use strict naming, i.e. force a non-empty $tpl?
828 *
829 * @return mixed A string if successful, otherwise a JError object
830 */
831 public function loadTemplate($tpl = null, $strict = false)
832 {
833 $paths = FOFPlatform::getInstance()->getViewTemplatePaths(
834 $this->input->getCmd('option', ''),
835 $this->input->getCmd('view', ''),
836 $this->getLayout(),
837 $tpl,
838 $strict
839 );
840
841 foreach ($paths as $path)
842 {
843 $result = $this->loadAnyTemplate($path);
844
845 if (!($result instanceof Exception))
846 {
847 break;
848 }
849 }
850
851 if ($result instanceof Exception)
852 {
853 FOFPlatform::getInstance()->raiseError($result->getCode(), $result->getMessage());
854 }
855
856 return $result;
857 }
858
859 /**
860 * Parses a template path in the form of admin:/component/view/layout or
861 * site:/component/view/layout to an array which can be used by
862 * loadAnyTemplate to locate and load the view template file.
863 *
864 * @param string $path The template path to parse
865 *
866 * @return array A hash array with the parsed path parts
867 */
868 private function _parseTemplatePath($path = '')
869 {
870 $parts = array(
871 'admin' => 0,
872 'component' => $this->config['option'],
873 'view' => $this->config['view'],
874 'template' => 'default'
875 );
876
877 if (substr($path, 0, 6) == 'admin:')
878 {
879 $parts['admin'] = 1;
880 $path = substr($path, 6);
881 }
882 elseif (substr($path, 0, 5) == 'site:')
883 {
884 $path = substr($path, 5);
885 }
886
887 if (empty($path))
888 {
889 return;
890 }
891
892 $pathparts = explode('/', $path, 3);
893
894 switch (count($pathparts))
895 {
896 case 3:
897 $parts['component'] = array_shift($pathparts);
898
899 case 2:
900 $parts['view'] = array_shift($pathparts);
901
902 case 1:
903 $parts['template'] = array_shift($pathparts);
904 break;
905 }
906
907 return $parts;
908 }
909
910 /**
911 * Get the renderer object for this view
912 *
913 * @return FOFRenderAbstract
914 */
915 public function &getRenderer()
916 {
917 if (!($this->rendererObject instanceof FOFRenderAbstract))
918 {
919 $this->rendererObject = $this->findRenderer();
920 }
921
922 return $this->rendererObject;
923 }
924
925 /**
926 * Sets the renderer object for this view
927 *
928 * @param FOFRenderAbstract &$renderer The render class to use
929 *
930 * @return void
931 */
932 public function setRenderer(FOFRenderAbstract &$renderer)
933 {
934 $this->rendererObject = $renderer;
935 }
936
937 /**
938 * Finds a suitable renderer
939 *
940 * @return FOFRenderAbstract
941 */
942 protected function findRenderer()
943 {
944 $filesystem = FOFPlatform::getInstance()->getIntegrationObject('filesystem');
945
946 // Try loading the stock renderers shipped with FOF
947
948 if (empty(self::$renderers) || !class_exists('FOFRenderJoomla', false))
949 {
950 $path = dirname(__FILE__) . '/../render/';
951 $renderFiles = $filesystem->folderFiles($path, '.php');
952
953 if (!empty($renderFiles))
954 {
955 foreach ($renderFiles as $filename)
956 {
957 if ($filename == 'abstract.php')
958 {
959 continue;
960 }
961
962 @include_once $path . '/' . $filename;
963
964 $camel = FOFInflector::camelize($filename);
965 $className = 'FOFRender' . ucfirst(FOFInflector::getPart($camel, 0));
966 $o = new $className;
967
968 self::registerRenderer($o);
969 }
970 }
971 }
972
973 // Try to detect the most suitable renderer
974 $o = null;
975 $priority = 0;
976
977 if (!empty(self::$renderers))
978 {
979 foreach (self::$renderers as $r)
980 {
981 $info = $r->getInformation();
982
983 if (!$info->enabled)
984 {
985 continue;
986 }
987
988 if ($info->priority > $priority)
989 {
990 $priority = $info->priority;
991 $o = $r;
992 }
993 }
994 }
995
996 // Return the current renderer
997 return $o;
998 }
999
1000 /**
1001 * Registers a renderer object with the view
1002 *
1003 * @param FOFRenderAbstract &$renderer The render object to register
1004 *
1005 * @return void
1006 */
1007 public static function registerRenderer(FOFRenderAbstract &$renderer)
1008 {
1009 self::$renderers[] = $renderer;
1010 }
1011
1012 /**
1013 * Sets the pre-render flag
1014 *
1015 * @param boolean $value True to enable the pre-render step
1016 *
1017 * @return void
1018 */
1019 public function setPreRender($value)
1020 {
1021 $this->doPreRender = $value;
1022 }
1023
1024 /**
1025 * Sets the post-render flag
1026 *
1027 * @param boolean $value True to enable the post-render step
1028 *
1029 * @return void
1030 */
1031 public function setPostRender($value)
1032 {
1033 $this->doPostRender = $value;
1034 }
1035
1036 /**
1037 * Load a helper file
1038 *
1039 * @param string $hlp The name of the helper source file automatically searches the helper paths and compiles as needed.
1040 *
1041 * @return void
1042 */
1043 public function loadHelper($hlp = null)
1044 {
1045 // Clean the file name
1046 $file = preg_replace('/[^A-Z0-9_\.-]/i', '', $hlp);
1047
1048 // Load the template script using the default Joomla! features
1049 $filesystem = FOFPlatform::getInstance()->getIntegrationObject('filesystem');
1050
1051 $helper = $filesystem->pathFind($this->_path['helper'], $this->_createFileName('helper', array('name' => $file)));
1052
1053 if ($helper == false)
1054 {
1055 $componentPaths = FOFPlatform::getInstance()->getComponentBaseDirs($this->config['option']);
1056 $path = $componentPaths['main'] . '/helpers';
1057 $helper = $filesystem->pathFind($path, $this->_createFileName('helper', array('name' => $file)));
1058
1059 if ($helper == false)
1060 {
1061 $path = $path = $componentPaths['alt'] . '/helpers';
1062 $helper = $filesystem->pathFind($path, $this->_createFileName('helper', array('name' => $file)));
1063 }
1064 }
1065
1066 if ($helper != false)
1067 {
1068 // Include the requested template filename in the local scope
1069 include_once $helper;
1070 }
1071 }
1072
1073 /**
1074 * Returns the view's option (component name) and view name in an
1075 * associative array.
1076 *
1077 * @return array
1078 */
1079 public function getViewOptionAndName()
1080 {
1081 return array(
1082 'option' => $this->config['option'],
1083 'view' => $this->config['view'],
1084 );
1085 }
1086
1087 /**
1088 * Sets an entire array of search paths for templates or resources.
1089 *
1090 * @param string $type The type of path to set, typically 'template'.
1091 * @param mixed $path The new search path, or an array of search paths. If null or false, resets to the current directory only.
1092 *
1093 * @return void
1094 */
1095 protected function _setPath($type, $path)
1096 {
1097 // Clear out the prior search dirs
1098 $this->_path[$type] = array();
1099
1100 // Actually add the user-specified directories
1101 $this->_addPath($type, $path);
1102
1103 // Always add the fallback directories as last resort
1104 switch (strtolower($type))
1105 {
1106 case 'template':
1107 // Set the alternative template search dir
1108
1109 if (!FOFPlatform::getInstance()->isCli())
1110 {
1111 $fallback = FOFPlatform::getInstance()->getTemplateOverridePath($this->input->getCmd('option', '')) . '/' . $this->getName();
1112 $this->_addPath('template', $fallback);
1113 }
1114
1115 break;
1116 }
1117 }
1118
1119 /**
1120 * Adds to the search path for templates and resources.
1121 *
1122 * @param string $type The type of path to add.
1123 * @param mixed $path The directory or stream, or an array of either, to search.
1124 *
1125 * @return void
1126 */
1127 protected function _addPath($type, $path)
1128 {
1129 // Just force to array
1130 settype($path, 'array');
1131
1132 // Loop through the path directories
1133 foreach ($path as $dir)
1134 {
1135 // No surrounding spaces allowed!
1136 $dir = trim($dir);
1137
1138 // Add trailing separators as needed
1139 if (substr($dir, -1) != DIRECTORY_SEPARATOR)
1140 {
1141 // Directory
1142 $dir .= DIRECTORY_SEPARATOR;
1143 }
1144
1145 // Add to the top of the search dirs
1146 array_unshift($this->_path[$type], $dir);
1147 }
1148 }
1149
1150 /**
1151 * Create the filename for a resource
1152 *
1153 * @param string $type The resource type to create the filename for
1154 * @param array $parts An associative array of filename information
1155 *
1156 * @return string The filename
1157 */
1158 protected function _createFileName($type, $parts = array())
1159 {
1160 $filename = '';
1161
1162 switch ($type)
1163 {
1164 case 'template':
1165 $filename = strtolower($parts['name']) . '.' . $this->_layoutExt;
1166 break;
1167
1168 default:
1169 $filename = strtolower($parts['name']) . '.php';
1170 break;
1171 }
1172
1173 return $filename;
1174 }
1175 }
1176