1176 lines
26 KiB
PHP
1176 lines
26 KiB
PHP
<?php
|
|
/**
|
|
* @package FrameworkOnFramework
|
|
* @subpackage view
|
|
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
|
|
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
|
*/
|
|
// Protect from unauthorized access
|
|
defined('F0F_INCLUDED') or die;
|
|
|
|
/**
|
|
* FrameworkOnFramework View class. The View is the MVC component which gets the
|
|
* raw data from a Model and renders it in a way that makes sense. The usual
|
|
* rendering is HTML, but you can also output JSON, CSV, XML, or even media
|
|
* (images, videos, ...) and documents (Word, PDF, Excel...).
|
|
*
|
|
* @package FrameworkOnFramework
|
|
* @since 1.0
|
|
*/
|
|
abstract class F0FView extends F0FUtilsObject
|
|
{
|
|
/**
|
|
* The name of the view
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_name = null;
|
|
|
|
/**
|
|
* Registered models
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_models = array();
|
|
|
|
/**
|
|
* The base path of the view
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_basePath = null;
|
|
|
|
/**
|
|
* The default model
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_defaultModel = null;
|
|
|
|
/**
|
|
* Layout name
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_layout = 'default';
|
|
|
|
/**
|
|
* Layout extension
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_layoutExt = 'php';
|
|
|
|
/**
|
|
* Layout template
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_layoutTemplate = '_';
|
|
|
|
/**
|
|
* The set of search directories for resources (templates)
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_path = array('template' => array(), 'helper' => array());
|
|
|
|
/**
|
|
* The name of the default template source file.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_template = null;
|
|
|
|
/**
|
|
* The output of the template script.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_output = null;
|
|
|
|
/**
|
|
* Callback for escaping.
|
|
*
|
|
* @var string
|
|
* @deprecated 13.3
|
|
*/
|
|
protected $_escape = 'htmlspecialchars';
|
|
|
|
/**
|
|
* Charset to use in escaping mechanisms; defaults to urf8 (UTF-8)
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_charset = 'UTF-8';
|
|
|
|
/**
|
|
* The available renderer objects we can use to render views
|
|
*
|
|
* @var array Contains objects of the F0FRenderAbstract class
|
|
*/
|
|
public static $renderers = array();
|
|
|
|
/**
|
|
* Cache of the configuration array
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $config = array();
|
|
|
|
/**
|
|
* The input object of this view
|
|
*
|
|
* @var F0FInput
|
|
*/
|
|
protected $input = null;
|
|
|
|
/**
|
|
* The chosen renderer object
|
|
*
|
|
* @var F0FRenderAbstract
|
|
*/
|
|
protected $rendererObject = null;
|
|
|
|
/**
|
|
* Should I run the pre-render step?
|
|
*
|
|
* @var boolean
|
|
*/
|
|
protected $doPreRender = true;
|
|
|
|
/**
|
|
* Should I run the post-render step?
|
|
*
|
|
* @var boolean
|
|
*/
|
|
protected $doPostRender = true;
|
|
|
|
/**
|
|
* Public constructor. Instantiates a F0FView object.
|
|
*
|
|
* @param array $config The configuration data array
|
|
*/
|
|
public function __construct($config = array())
|
|
{
|
|
// Make sure $config is an array
|
|
if (is_object($config))
|
|
{
|
|
$config = (array) $config;
|
|
}
|
|
elseif (!is_array($config))
|
|
{
|
|
$config = array();
|
|
}
|
|
|
|
// Get the input
|
|
if (array_key_exists('input', $config))
|
|
{
|
|
if ($config['input'] instanceof F0FInput)
|
|
{
|
|
$this->input = $config['input'];
|
|
}
|
|
else
|
|
{
|
|
$this->input = new F0FInput($config['input']);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$this->input = new F0FInput;
|
|
}
|
|
|
|
parent::__construct($config);
|
|
|
|
$component = 'com_foobar';
|
|
|
|
// Get the component name
|
|
if (array_key_exists('input', $config))
|
|
{
|
|
if ($config['input'] instanceof F0FInput)
|
|
{
|
|
$tmpInput = $config['input'];
|
|
}
|
|
else
|
|
{
|
|
$tmpInput = new F0FInput($config['input']);
|
|
}
|
|
|
|
$component = $tmpInput->getCmd('option', '');
|
|
}
|
|
else
|
|
{
|
|
$tmpInput = $this->input;
|
|
}
|
|
|
|
if (array_key_exists('option', $config))
|
|
{
|
|
if ($config['option'])
|
|
{
|
|
$component = $config['option'];
|
|
}
|
|
}
|
|
|
|
$config['option'] = $component;
|
|
|
|
// Get the view name
|
|
$view = null;
|
|
if (array_key_exists('input', $config))
|
|
{
|
|
$view = $tmpInput->getCmd('view', '');
|
|
}
|
|
|
|
if (array_key_exists('view', $config))
|
|
{
|
|
if ($config['view'])
|
|
{
|
|
$view = $config['view'];
|
|
}
|
|
}
|
|
|
|
$config['view'] = $view;
|
|
|
|
// Set the component and the view to the input array
|
|
|
|
if (array_key_exists('input', $config))
|
|
{
|
|
$tmpInput->set('option', $config['option']);
|
|
$tmpInput->set('view', $config['view']);
|
|
}
|
|
|
|
// Set the view name
|
|
|
|
if (array_key_exists('name', $config))
|
|
{
|
|
$this->_name = $config['name'];
|
|
}
|
|
else
|
|
{
|
|
$this->_name = $config['view'];
|
|
}
|
|
|
|
$tmpInput->set('view', $this->_name);
|
|
$config['input'] = $tmpInput;
|
|
$config['name'] = $this->_name;
|
|
$config['view'] = $this->_name;
|
|
|
|
// Get the component directories
|
|
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($config['option']);
|
|
|
|
// Set the charset (used by the variable escaping functions)
|
|
|
|
if (array_key_exists('charset', $config))
|
|
{
|
|
F0FPlatform::getInstance()->logDeprecated('Setting a custom charset for escaping in F0FView\'s constructor is deprecated. Override F0FView::escape() instead.');
|
|
$this->_charset = $config['charset'];
|
|
}
|
|
|
|
// User-defined escaping callback
|
|
|
|
if (array_key_exists('escape', $config))
|
|
{
|
|
$this->setEscape($config['escape']);
|
|
}
|
|
|
|
// Set a base path for use by the view
|
|
|
|
if (array_key_exists('base_path', $config))
|
|
{
|
|
$this->_basePath = $config['base_path'];
|
|
}
|
|
else
|
|
{
|
|
$this->_basePath = $componentPaths['main'];
|
|
}
|
|
|
|
// Set the default template search path
|
|
|
|
if (array_key_exists('template_path', $config))
|
|
{
|
|
// User-defined dirs
|
|
$this->_setPath('template', $config['template_path']);
|
|
}
|
|
else
|
|
{
|
|
$altView = F0FInflector::isSingular($this->getName()) ? F0FInflector::pluralize($this->getName()) : F0FInflector::singularize($this->getName());
|
|
$this->_setPath('template', $this->_basePath . '/views/' . $altView . '/tmpl');
|
|
$this->_addPath('template', $this->_basePath . '/views/' . $this->getName() . '/tmpl');
|
|
}
|
|
|
|
// Set the default helper search path
|
|
|
|
if (array_key_exists('helper_path', $config))
|
|
{
|
|
// User-defined dirs
|
|
$this->_setPath('helper', $config['helper_path']);
|
|
}
|
|
else
|
|
{
|
|
$this->_setPath('helper', $this->_basePath . '/helpers');
|
|
}
|
|
|
|
// Set the layout
|
|
|
|
if (array_key_exists('layout', $config))
|
|
{
|
|
$this->setLayout($config['layout']);
|
|
}
|
|
else
|
|
{
|
|
$this->setLayout('default');
|
|
}
|
|
|
|
$this->config = $config;
|
|
|
|
if (!F0FPlatform::getInstance()->isCli())
|
|
{
|
|
$this->baseurl = F0FPlatform::getInstance()->URIbase(true);
|
|
|
|
$fallback = F0FPlatform::getInstance()->getTemplateOverridePath($component) . '/' . $this->getName();
|
|
$this->_addPath('template', $fallback);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads a template given any path. The path is in the format:
|
|
* [admin|site]:com_foobar/viewname/templatename
|
|
* e.g. admin:com_foobar/myview/default
|
|
*
|
|
* This function searches for Joomla! version override templates. For example,
|
|
* if you have run this under Joomla! 3.0 and you try to load
|
|
* admin:com_foobar/myview/default it will automatically search for the
|
|
* template files default.j30.php, default.j3.php and default.php, in this
|
|
* order.
|
|
*
|
|
* @param string $path See above
|
|
* @param array $forceParams A hash array of variables to be extracted in the local scope of the template file
|
|
*
|
|
* @return boolean False if loading failed
|
|
*/
|
|
public function loadAnyTemplate($path = '', $forceParams = array())
|
|
{
|
|
// Automatically check for a Joomla! version specific override
|
|
$throwErrorIfNotFound = true;
|
|
|
|
$suffixes = F0FPlatform::getInstance()->getTemplateSuffixes();
|
|
|
|
foreach ($suffixes as $suffix)
|
|
{
|
|
if (substr($path, -strlen($suffix)) == $suffix)
|
|
{
|
|
$throwErrorIfNotFound = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($throwErrorIfNotFound)
|
|
{
|
|
foreach ($suffixes as $suffix)
|
|
{
|
|
$result = $this->loadAnyTemplate($path . $suffix, $forceParams);
|
|
|
|
if ($result !== false)
|
|
{
|
|
return $result;
|
|
}
|
|
}
|
|
}
|
|
|
|
$layoutTemplate = $this->getLayoutTemplate();
|
|
|
|
// Parse the path
|
|
$templateParts = $this->_parseTemplatePath($path);
|
|
|
|
// Get the paths
|
|
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($templateParts['component']);
|
|
$templatePath = F0FPlatform::getInstance()->getTemplateOverridePath($templateParts['component']);
|
|
|
|
// Get the default paths
|
|
$paths = array();
|
|
$paths[] = $templatePath . '/' . $templateParts['view'];
|
|
$paths[] = ($templateParts['admin'] ? $componentPaths['admin'] : $componentPaths['site']) . '/views/' . $templateParts['view'] . '/tmpl';
|
|
|
|
if (isset($this->_path) || property_exists($this, '_path'))
|
|
{
|
|
$paths = array_merge($paths, $this->_path['template']);
|
|
}
|
|
elseif (isset($this->path) || property_exists($this, 'path'))
|
|
{
|
|
$paths = array_merge($paths, $this->path['template']);
|
|
}
|
|
|
|
// Look for a template override
|
|
|
|
if (isset($layoutTemplate) && $layoutTemplate != '_' && $layoutTemplate != $template)
|
|
{
|
|
$apath = array_shift($paths);
|
|
array_unshift($paths, str_replace($template, $layoutTemplate, $apath));
|
|
}
|
|
|
|
$filetofind = $templateParts['template'] . '.php';
|
|
$filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem');
|
|
|
|
$this->_tempFilePath = $filesystem->pathFind($paths, $filetofind);
|
|
|
|
if ($this->_tempFilePath)
|
|
{
|
|
// Unset from local scope
|
|
unset($template);
|
|
unset($layoutTemplate);
|
|
unset($paths);
|
|
unset($path);
|
|
unset($filetofind);
|
|
|
|
// Never allow a 'this' property
|
|
|
|
if (isset($this->this))
|
|
{
|
|
unset($this->this);
|
|
}
|
|
|
|
// Force parameters into scope
|
|
|
|
if (!empty($forceParams))
|
|
{
|
|
extract($forceParams);
|
|
}
|
|
|
|
// Start capturing output into a buffer
|
|
ob_start();
|
|
|
|
// Include the requested template filename in the local scope (this will execute the view logic).
|
|
include $this->_tempFilePath;
|
|
|
|
// Done with the requested template; get the buffer and clear it.
|
|
$this->_output = ob_get_contents();
|
|
ob_end_clean();
|
|
|
|
return $this->_output;
|
|
}
|
|
else
|
|
{
|
|
if ($throwErrorIfNotFound)
|
|
{
|
|
return new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_LAYOUTFILE_NOT_FOUND', $path), 500);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Overrides the default method to execute and display a template script.
|
|
* Instead of loadTemplate is uses loadAnyTemplate which allows for automatic
|
|
* Joomla! version overrides. A little slice of awesome pie!
|
|
*
|
|
* @param string $tpl The name of the template file to parse
|
|
*
|
|
* @return mixed A string if successful, otherwise a JError object.
|
|
*/
|
|
public function display($tpl = null)
|
|
{
|
|
F0FPlatform::getInstance()->setErrorHandling(E_ALL, 'ignore');
|
|
|
|
$result = $this->loadTemplate($tpl);
|
|
|
|
if ($result instanceof Exception)
|
|
{
|
|
F0FPlatform::getInstance()->raiseError($result->getCode(), $result->getMessage());
|
|
|
|
return $result;
|
|
}
|
|
|
|
echo $result;
|
|
}
|
|
|
|
/**
|
|
* Assigns variables to the view script via differing strategies.
|
|
*
|
|
* This method is overloaded; you can assign all the properties of
|
|
* an object, an associative array, or a single value by name.
|
|
*
|
|
* You are not allowed to set variables that begin with an underscore;
|
|
* these are either private properties for F0FView or private variables
|
|
* within the template script itself.
|
|
*
|
|
* @return boolean True on success, false on failure.
|
|
*
|
|
* @deprecated 13.3 Use native PHP syntax.
|
|
*/
|
|
public function assign()
|
|
{
|
|
F0FPlatform::getInstance()->logDeprecated(__CLASS__ . '::' . __METHOD__ . ' is deprecated. Use native PHP syntax.');
|
|
|
|
// Get the arguments; there may be 1 or 2.
|
|
$arg0 = @func_get_arg(0);
|
|
$arg1 = @func_get_arg(1);
|
|
|
|
// Assign by object
|
|
|
|
if (is_object($arg0))
|
|
{
|
|
// Assign public properties
|
|
foreach (get_object_vars($arg0) as $key => $val)
|
|
{
|
|
if (substr($key, 0, 1) != '_')
|
|
{
|
|
$this->$key = $val;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Assign by associative array
|
|
|
|
if (is_array($arg0))
|
|
{
|
|
foreach ($arg0 as $key => $val)
|
|
{
|
|
if (substr($key, 0, 1) != '_')
|
|
{
|
|
$this->$key = $val;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Assign by string name and mixed value. We use array_key_exists() instead of isset()
|
|
// because isset() fails if the value is set to null.
|
|
|
|
if (is_string($arg0) && substr($arg0, 0, 1) != '_' && func_num_args() > 1)
|
|
{
|
|
$this->$arg0 = $arg1;
|
|
|
|
return true;
|
|
}
|
|
|
|
// $arg0 was not object, array, or string.
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Assign variable for the view (by reference).
|
|
*
|
|
* You are not allowed to set variables that begin with an underscore;
|
|
* these are either private properties for F0FView or private variables
|
|
* within the template script itself.
|
|
*
|
|
* @param string $key The name for the reference in the view.
|
|
* @param mixed &$val The referenced variable.
|
|
*
|
|
* @return boolean True on success, false on failure.
|
|
*
|
|
* @deprecated 13.3 Use native PHP syntax.
|
|
*/
|
|
public function assignRef($key, &$val)
|
|
{
|
|
F0FPlatform::getInstance()->logDeprecated(__CLASS__ . '::' . __METHOD__ . ' is deprecated. Use native PHP syntax.');
|
|
|
|
if (is_string($key) && substr($key, 0, 1) != '_')
|
|
{
|
|
$this->$key = &$val;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Escapes a value for output in a view script.
|
|
*
|
|
* If escaping mechanism is either htmlspecialchars or htmlentities, uses
|
|
* {@link $_encoding} setting.
|
|
*
|
|
* @param mixed $var The output to escape.
|
|
*
|
|
* @return mixed The escaped value.
|
|
*/
|
|
public function escape($var)
|
|
{
|
|
if (in_array($this->_escape, array('htmlspecialchars', 'htmlentities')))
|
|
{
|
|
return call_user_func($this->_escape, $var, ENT_COMPAT, $this->_charset);
|
|
}
|
|
|
|
return call_user_func($this->_escape, $var);
|
|
}
|
|
|
|
/**
|
|
* Method to get data from a registered model or a property of the view
|
|
*
|
|
* @param string $property The name of the method to call on the model or the property to get
|
|
* @param string $default The name of the model to reference or the default value [optional]
|
|
*
|
|
* @return mixed The return value of the method
|
|
*/
|
|
public function get($property, $default = null)
|
|
{
|
|
// If $model is null we use the default model
|
|
if (is_null($default))
|
|
{
|
|
$model = $this->_defaultModel;
|
|
}
|
|
else
|
|
{
|
|
$model = strtolower($default);
|
|
}
|
|
|
|
// First check to make sure the model requested exists
|
|
if (isset($this->_models[$model]))
|
|
{
|
|
// Model exists, let's build the method name
|
|
$method = 'get' . ucfirst($property);
|
|
|
|
// Does the method exist?
|
|
if (method_exists($this->_models[$model], $method))
|
|
{
|
|
// The method exists, let's call it and return what we get
|
|
$result = $this->_models[$model]->$method();
|
|
|
|
return $result;
|
|
}
|
|
}
|
|
|
|
// Degrade to F0FUtilsObject::get
|
|
$result = parent::get($property, $default);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Method to get the model object
|
|
*
|
|
* @param string $name The name of the model (optional)
|
|
*
|
|
* @return mixed F0FModel object
|
|
*/
|
|
public function getModel($name = null)
|
|
{
|
|
if ($name === null)
|
|
{
|
|
$name = $this->_defaultModel;
|
|
}
|
|
|
|
return $this->_models[strtolower($name)];
|
|
}
|
|
|
|
/**
|
|
* Get the layout.
|
|
*
|
|
* @return string The layout name
|
|
*/
|
|
public function getLayout()
|
|
{
|
|
return $this->_layout;
|
|
}
|
|
|
|
/**
|
|
* Get the layout template.
|
|
*
|
|
* @return string The layout template name
|
|
*/
|
|
public function getLayoutTemplate()
|
|
{
|
|
return $this->_layoutTemplate;
|
|
}
|
|
|
|
/**
|
|
* Method to get the view name
|
|
*
|
|
* The model name by default parsed using the classname, or it can be set
|
|
* by passing a $config['name'] in the class constructor
|
|
*
|
|
* @return string The name of the model
|
|
*/
|
|
public function getName()
|
|
{
|
|
if (empty($this->_name))
|
|
{
|
|
$classname = get_class($this);
|
|
$viewpos = strpos($classname, 'View');
|
|
|
|
if ($viewpos === false)
|
|
{
|
|
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_VIEW_GET_NAME'), 500);
|
|
}
|
|
|
|
$this->_name = strtolower(substr($classname, $viewpos + 4));
|
|
}
|
|
|
|
return $this->_name;
|
|
}
|
|
|
|
/**
|
|
* Method to add a model to the view.
|
|
*
|
|
* @param F0FMOdel $model The model to add to the view.
|
|
* @param boolean $default Is this the default model?
|
|
* @param String $name optional index name to store the model
|
|
*
|
|
* @return object The added model.
|
|
*/
|
|
public function setModel($model, $default = false, $name = null)
|
|
{
|
|
if (is_null($name))
|
|
{
|
|
$name = $model->getName();
|
|
}
|
|
|
|
$name = strtolower($name);
|
|
|
|
$this->_models[$name] = $model;
|
|
|
|
if ($default)
|
|
{
|
|
$this->_defaultModel = $name;
|
|
}
|
|
|
|
return $model;
|
|
}
|
|
|
|
/**
|
|
* Sets the layout name to use
|
|
*
|
|
* @param string $layout The layout name or a string in format <template>:<layout file>
|
|
*
|
|
* @return string Previous value.
|
|
*/
|
|
public function setLayout($layout)
|
|
{
|
|
$previous = $this->_layout;
|
|
|
|
if (strpos($layout, ':') === false)
|
|
{
|
|
$this->_layout = $layout;
|
|
}
|
|
else
|
|
{
|
|
// Convert parameter to array based on :
|
|
$temp = explode(':', $layout);
|
|
$this->_layout = $temp[1];
|
|
|
|
// Set layout template
|
|
$this->_layoutTemplate = $temp[0];
|
|
}
|
|
|
|
return $previous;
|
|
}
|
|
|
|
/**
|
|
* Allows a different extension for the layout files to be used
|
|
*
|
|
* @param string $value The extension.
|
|
*
|
|
* @return string Previous value
|
|
*/
|
|
public function setLayoutExt($value)
|
|
{
|
|
$previous = $this->_layoutExt;
|
|
|
|
if ($value = preg_replace('#[^A-Za-z0-9]#', '', trim($value)))
|
|
{
|
|
$this->_layoutExt = $value;
|
|
}
|
|
|
|
return $previous;
|
|
}
|
|
|
|
/**
|
|
* Sets the _escape() callback.
|
|
*
|
|
* @param mixed $spec The callback for _escape() to use.
|
|
*
|
|
* @return void
|
|
*
|
|
* @deprecated 2.1 Override F0FView::escape() instead.
|
|
*/
|
|
public function setEscape($spec)
|
|
{
|
|
F0FPlatform::getInstance()->logDeprecated(__CLASS__ . '::' . __METHOD__ . ' is deprecated. Override F0FView::escape() instead.');
|
|
|
|
$this->_escape = $spec;
|
|
}
|
|
|
|
/**
|
|
* Adds to the stack of view script paths in LIFO order.
|
|
*
|
|
* @param mixed $path A directory path or an array of paths.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function addTemplatePath($path)
|
|
{
|
|
$this->_addPath('template', $path);
|
|
}
|
|
|
|
/**
|
|
* Adds to the stack of helper script paths in LIFO order.
|
|
*
|
|
* @param mixed $path A directory path or an array of paths.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function addHelperPath($path)
|
|
{
|
|
$this->_addPath('helper', $path);
|
|
}
|
|
|
|
/**
|
|
* Overrides the built-in loadTemplate function with an F0F-specific one.
|
|
* Our overriden function uses loadAnyTemplate to provide smarter view
|
|
* template loading.
|
|
*
|
|
* @param string $tpl The name of the template file to parse
|
|
* @param boolean $strict Should we use strict naming, i.e. force a non-empty $tpl?
|
|
*
|
|
* @return mixed A string if successful, otherwise a JError object
|
|
*/
|
|
public function loadTemplate($tpl = null, $strict = false)
|
|
{
|
|
$paths = F0FPlatform::getInstance()->getViewTemplatePaths(
|
|
$this->input->getCmd('option', ''),
|
|
$this->input->getCmd('view', ''),
|
|
$this->getLayout(),
|
|
$tpl,
|
|
$strict
|
|
);
|
|
|
|
foreach ($paths as $path)
|
|
{
|
|
$result = $this->loadAnyTemplate($path);
|
|
|
|
if (!($result instanceof Exception))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($result instanceof Exception)
|
|
{
|
|
F0FPlatform::getInstance()->raiseError($result->getCode(), $result->getMessage());
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Parses a template path in the form of admin:/component/view/layout or
|
|
* site:/component/view/layout to an array which can be used by
|
|
* loadAnyTemplate to locate and load the view template file.
|
|
*
|
|
* @param string $path The template path to parse
|
|
*
|
|
* @return array A hash array with the parsed path parts
|
|
*/
|
|
private function _parseTemplatePath($path = '')
|
|
{
|
|
$parts = array(
|
|
'admin' => 0,
|
|
'component' => $this->config['option'],
|
|
'view' => $this->config['view'],
|
|
'template' => 'default'
|
|
);
|
|
|
|
if (substr($path, 0, 6) == 'admin:')
|
|
{
|
|
$parts['admin'] = 1;
|
|
$path = substr($path, 6);
|
|
}
|
|
elseif (substr($path, 0, 5) == 'site:')
|
|
{
|
|
$path = substr($path, 5);
|
|
}
|
|
|
|
if (empty($path))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$pathparts = explode('/', $path, 3);
|
|
|
|
switch (count($pathparts))
|
|
{
|
|
case 3:
|
|
$parts['component'] = array_shift($pathparts);
|
|
|
|
case 2:
|
|
$parts['view'] = array_shift($pathparts);
|
|
|
|
case 1:
|
|
$parts['template'] = array_shift($pathparts);
|
|
break;
|
|
}
|
|
|
|
return $parts;
|
|
}
|
|
|
|
/**
|
|
* Get the renderer object for this view
|
|
*
|
|
* @return F0FRenderAbstract
|
|
*/
|
|
public function &getRenderer()
|
|
{
|
|
if (!($this->rendererObject instanceof F0FRenderAbstract))
|
|
{
|
|
$this->rendererObject = $this->findRenderer();
|
|
}
|
|
|
|
return $this->rendererObject;
|
|
}
|
|
|
|
/**
|
|
* Sets the renderer object for this view
|
|
*
|
|
* @param F0FRenderAbstract &$renderer The render class to use
|
|
*
|
|
* @return void
|
|
*/
|
|
public function setRenderer(F0FRenderAbstract &$renderer)
|
|
{
|
|
$this->rendererObject = $renderer;
|
|
}
|
|
|
|
/**
|
|
* Finds a suitable renderer
|
|
*
|
|
* @return F0FRenderAbstract
|
|
*/
|
|
protected function findRenderer()
|
|
{
|
|
$filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem');
|
|
|
|
// Try loading the stock renderers shipped with F0F
|
|
|
|
if (empty(self::$renderers) || !class_exists('F0FRenderJoomla', false))
|
|
{
|
|
$path = dirname(__FILE__) . '/../render/';
|
|
$renderFiles = $filesystem->folderFiles($path, '.php');
|
|
|
|
if (!empty($renderFiles))
|
|
{
|
|
foreach ($renderFiles as $filename)
|
|
{
|
|
if ($filename == 'abstract.php')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
@include_once $path . '/' . $filename;
|
|
|
|
$camel = F0FInflector::camelize($filename);
|
|
$className = 'F0FRender' . ucfirst(F0FInflector::getPart($camel, 0));
|
|
$o = new $className;
|
|
|
|
self::registerRenderer($o);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Try to detect the most suitable renderer
|
|
$o = null;
|
|
$priority = 0;
|
|
|
|
if (!empty(self::$renderers))
|
|
{
|
|
foreach (self::$renderers as $r)
|
|
{
|
|
$info = $r->getInformation();
|
|
|
|
if (!$info->enabled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ($info->priority > $priority)
|
|
{
|
|
$priority = $info->priority;
|
|
$o = $r;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return the current renderer
|
|
return $o;
|
|
}
|
|
|
|
/**
|
|
* Registers a renderer object with the view
|
|
*
|
|
* @param F0FRenderAbstract &$renderer The render object to register
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function registerRenderer(F0FRenderAbstract &$renderer)
|
|
{
|
|
self::$renderers[] = $renderer;
|
|
}
|
|
|
|
/**
|
|
* Sets the pre-render flag
|
|
*
|
|
* @param boolean $value True to enable the pre-render step
|
|
*
|
|
* @return void
|
|
*/
|
|
public function setPreRender($value)
|
|
{
|
|
$this->doPreRender = $value;
|
|
}
|
|
|
|
/**
|
|
* Sets the post-render flag
|
|
*
|
|
* @param boolean $value True to enable the post-render step
|
|
*
|
|
* @return void
|
|
*/
|
|
public function setPostRender($value)
|
|
{
|
|
$this->doPostRender = $value;
|
|
}
|
|
|
|
/**
|
|
* Load a helper file
|
|
*
|
|
* @param string $hlp The name of the helper source file automatically searches the helper paths and compiles as needed.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function loadHelper($hlp = null)
|
|
{
|
|
// Clean the file name
|
|
$file = preg_replace('/[^A-Z0-9_\.-]/i', '', $hlp);
|
|
|
|
// Load the template script using the default Joomla! features
|
|
$filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem');
|
|
|
|
$helper = $filesystem->pathFind($this->_path['helper'], $this->_createFileName('helper', array('name' => $file)));
|
|
|
|
if ($helper == false)
|
|
{
|
|
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($this->config['option']);
|
|
$path = $componentPaths['main'] . '/helpers';
|
|
$helper = $filesystem->pathFind($path, $this->_createFileName('helper', array('name' => $file)));
|
|
|
|
if ($helper == false)
|
|
{
|
|
$path = $path = $componentPaths['alt'] . '/helpers';
|
|
$helper = $filesystem->pathFind($path, $this->_createFileName('helper', array('name' => $file)));
|
|
}
|
|
}
|
|
|
|
if ($helper != false)
|
|
{
|
|
// Include the requested template filename in the local scope
|
|
include_once $helper;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the view's option (component name) and view name in an
|
|
* associative array.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getViewOptionAndName()
|
|
{
|
|
return array(
|
|
'option' => $this->config['option'],
|
|
'view' => $this->config['view'],
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Sets an entire array of search paths for templates or resources.
|
|
*
|
|
* @param string $type The type of path to set, typically 'template'.
|
|
* @param mixed $path The new search path, or an array of search paths. If null or false, resets to the current directory only.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function _setPath($type, $path)
|
|
{
|
|
// Clear out the prior search dirs
|
|
$this->_path[$type] = array();
|
|
|
|
// Actually add the user-specified directories
|
|
$this->_addPath($type, $path);
|
|
|
|
// Always add the fallback directories as last resort
|
|
switch (strtolower($type))
|
|
{
|
|
case 'template':
|
|
// Set the alternative template search dir
|
|
|
|
if (!F0FPlatform::getInstance()->isCli())
|
|
{
|
|
$fallback = F0FPlatform::getInstance()->getTemplateOverridePath($this->input->getCmd('option', '')) . '/' . $this->getName();
|
|
$this->_addPath('template', $fallback);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds to the search path for templates and resources.
|
|
*
|
|
* @param string $type The type of path to add.
|
|
* @param mixed $path The directory or stream, or an array of either, to search.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function _addPath($type, $path)
|
|
{
|
|
// Just force to array
|
|
settype($path, 'array');
|
|
|
|
// Loop through the path directories
|
|
foreach ($path as $dir)
|
|
{
|
|
// No surrounding spaces allowed!
|
|
$dir = trim($dir);
|
|
|
|
// Add trailing separators as needed
|
|
if (substr($dir, -1) != DIRECTORY_SEPARATOR)
|
|
{
|
|
// Directory
|
|
$dir .= DIRECTORY_SEPARATOR;
|
|
}
|
|
|
|
// Add to the top of the search dirs
|
|
array_unshift($this->_path[$type], $dir);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create the filename for a resource
|
|
*
|
|
* @param string $type The resource type to create the filename for
|
|
* @param array $parts An associative array of filename information
|
|
*
|
|
* @return string The filename
|
|
*/
|
|
protected function _createFileName($type, $parts = array())
|
|
{
|
|
$filename = '';
|
|
|
|
switch ($type)
|
|
{
|
|
case 'template':
|
|
$filename = strtolower($parts['name']) . '.' . $this->_layoutExt;
|
|
break;
|
|
|
|
default:
|
|
$filename = strtolower($parts['name']) . '.php';
|
|
break;
|
|
}
|
|
|
|
return $filename;
|
|
}
|
|
}
|