3414 lines
76 KiB
PHP
3414 lines
76 KiB
PHP
<?php
|
|
/**
|
|
* @package FrameworkOnFramework
|
|
* @subpackage controller
|
|
* @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 controller class. F0F is based on the thin controller
|
|
* paradigm, where the controller is mainly used to set up the model state and
|
|
* spawn the view.
|
|
*
|
|
* @package FrameworkOnFramework
|
|
* @since 1.0
|
|
*/
|
|
class F0FController extends F0FUtilsObject
|
|
{
|
|
/**
|
|
* @var int Bit mask to enable Routing on redirects.
|
|
* 0 = never
|
|
* 1 = frontend only
|
|
* 2 = backend only
|
|
* 3 = always
|
|
*/
|
|
protected $autoRouting = 0;
|
|
|
|
/**
|
|
* The current component's name without the com_ prefix
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $bareComponent = 'foobar';
|
|
|
|
/**
|
|
* The base path of the controller
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $basePath;
|
|
|
|
/**
|
|
* The tasks for which caching should be enabled by default
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $cacheableTasks = array('browse', 'read');
|
|
|
|
/**
|
|
* The current component's name; you can override it in the configuration
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $component = 'com_foobar';
|
|
|
|
/**
|
|
* A cached copy of the class configuration parameter passed during initialisation
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $config = array();
|
|
|
|
/**
|
|
* An instance of F0FConfigProvider to provision configuration overrides
|
|
*
|
|
* @var F0FConfigProvider
|
|
*/
|
|
protected $configProvider = null;
|
|
|
|
/**
|
|
* Set to true to enable CSRF protection on selected tasks. The possible
|
|
* values are:
|
|
* 0 Disabled; no token checks are performed
|
|
* 1 Enabled; token checks are always performed
|
|
* 2 Only on HTML requests and backend; token checks are always performed in the back-end and in the front-end only when format is 'html'
|
|
* 3 Only on back-end; token checks are performer only in the back-end
|
|
*
|
|
* @var integer
|
|
*/
|
|
protected $csrfProtection = 2;
|
|
|
|
/**
|
|
* The default view for the display method.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $default_view;
|
|
|
|
/**
|
|
* The mapped task that was performed.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $doTask;
|
|
|
|
/**
|
|
* The input object for this MVC triad; you can override it in the configuration
|
|
*
|
|
* @var F0FInput
|
|
*/
|
|
protected $input = array();
|
|
|
|
/**
|
|
* Redirect message.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $message;
|
|
|
|
/**
|
|
* Redirect message type.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $messageType;
|
|
|
|
/**
|
|
* The current layout; you can override it in the configuration
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $layout = null;
|
|
|
|
/**
|
|
* Array of class methods
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $methods;
|
|
|
|
/**
|
|
* The prefix of the models
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $model_prefix;
|
|
|
|
/**
|
|
* Overrides the name of the view's default model
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $modelName = null;
|
|
|
|
/**
|
|
* The set of search directories for resources (views).
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $paths;
|
|
|
|
/**
|
|
* URL for redirection.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $redirect;
|
|
|
|
/**
|
|
* Current or most recently performed task.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $task;
|
|
|
|
/**
|
|
* Array of class methods to call for a given task.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $taskMap;
|
|
|
|
/**
|
|
* The name of the controller
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $name;
|
|
|
|
/**
|
|
* The current view name; you can override it in the configuration
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $view = '';
|
|
|
|
/**
|
|
* Overrides the name of the view's default view
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $viewName = null;
|
|
|
|
/**
|
|
* A copy of the F0FView object used in this triad
|
|
*
|
|
* @var F0FView
|
|
*/
|
|
private $_viewObject = null;
|
|
|
|
/**
|
|
* A cache for the view item objects created in this controller
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $viewsCache = array();
|
|
|
|
/**
|
|
* A copy of the F0FModel object used in this triad
|
|
*
|
|
* @var F0FModel
|
|
*/
|
|
private $_modelObject = null;
|
|
|
|
/**
|
|
* Does this tried have a F0FForm which will be used to render it?
|
|
*
|
|
* @var boolean
|
|
*/
|
|
protected $hasForm = false;
|
|
|
|
/**
|
|
* Gets a static (Singleton) instance of a controller class. It loads the
|
|
* relevant controller file from the component's directory or, if it doesn't
|
|
* exist, creates a new controller object out of thin air.
|
|
*
|
|
* @param string $option Component name, e.g. com_foobar
|
|
* @param string $view The view name, also used for the controller name
|
|
* @param array $config Configuration parameters
|
|
*
|
|
* @return F0FController
|
|
*/
|
|
public static function &getAnInstance($option = null, $view = null, $config = array())
|
|
{
|
|
static $instances = array();
|
|
|
|
// Make sure $config is an array
|
|
if (is_object($config))
|
|
{
|
|
$config = (array) $config;
|
|
}
|
|
elseif (!is_array($config))
|
|
{
|
|
$config = array();
|
|
}
|
|
|
|
$hash = $option . $view;
|
|
|
|
if (!array_key_exists($hash, $instances))
|
|
{
|
|
$instances[$hash] = self::getTmpInstance($option, $view, $config);
|
|
}
|
|
|
|
return $instances[$hash];
|
|
}
|
|
|
|
/**
|
|
* Gets a temporary instance of a controller object. A temporary instance is
|
|
* not a Singleton and can be disposed off after use.
|
|
*
|
|
* @param string $option The component name, e.g. com_foobar
|
|
* @param string $view The view name, e.g. cpanel
|
|
* @param array $config Configuration parameters
|
|
*
|
|
* @return \F0FController A disposable class instance
|
|
*/
|
|
public static function &getTmpInstance($option = null, $view = null, $config = array())
|
|
{
|
|
// Make sure $config is an array
|
|
if (is_object($config))
|
|
{
|
|
$config = (array) $config;
|
|
}
|
|
elseif (!is_array($config))
|
|
{
|
|
$config = array();
|
|
}
|
|
|
|
// Get an input object
|
|
if (array_key_exists('input', $config))
|
|
{
|
|
$input = $config['input'];
|
|
}
|
|
else
|
|
{
|
|
$input = null;
|
|
}
|
|
|
|
if (array_key_exists('input_options', $config))
|
|
{
|
|
$input_options = $config['input_options'];
|
|
}
|
|
else
|
|
{
|
|
$input_options = array();
|
|
}
|
|
|
|
if (!($input instanceof F0FInput))
|
|
{
|
|
$input = new F0FInput($input, $input_options);
|
|
}
|
|
|
|
// Determine the option (component name) and view
|
|
$config['option'] = !is_null($option) ? $option : $input->getCmd('option', 'com_foobar');
|
|
$config['view'] = !is_null($view) ? $view : $input->getCmd('view', 'cpanel');
|
|
|
|
// Get the class base name, e.g. FoobarController
|
|
$classBaseName = ucfirst(str_replace('com_', '', $config['option'])) . 'Controller';
|
|
|
|
// Get the class name suffixes, in the order to be searched for: plural, singular, 'default'
|
|
$classSuffixes = array(
|
|
F0FInflector::pluralize($config['view']),
|
|
F0FInflector::singularize($config['view']),
|
|
'default'
|
|
);
|
|
|
|
// Get the path names for the component
|
|
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($config['option']);
|
|
$filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem');
|
|
|
|
// Look for the best classname match
|
|
foreach ($classSuffixes as $suffix)
|
|
{
|
|
$className = $classBaseName . ucfirst($suffix);
|
|
|
|
if (class_exists($className))
|
|
{
|
|
// The class is already loaded. We have a match!
|
|
break;
|
|
}
|
|
|
|
// The class is not already loaded. Try to find and load it.
|
|
$searchPaths = array(
|
|
$componentPaths['main'] . '/controllers',
|
|
$componentPaths['admin'] . '/controllers'
|
|
);
|
|
|
|
// If we have a searchpath in the configuration please search it first
|
|
|
|
if (array_key_exists('searchpath', $config))
|
|
{
|
|
array_unshift($searchPaths, $config['searchpath']);
|
|
}
|
|
else
|
|
{
|
|
$configProvider = new F0FConfigProvider;
|
|
$searchPath = $configProvider->get($config['option'] . '.views.' . F0FInflector::singularize($config['view']) . '.config.searchpath', null);
|
|
|
|
if ($searchPath)
|
|
{
|
|
array_unshift($searchPaths, $componentPaths['admin'] . '/' . $searchPath);
|
|
array_unshift($searchPaths, $componentPaths['main'] . '/' . $searchPath);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Try to find the path to this file. First try to find the
|
|
* format-specific controller file, e.g. foobar.json.php for
|
|
* format=json, then the regular one-size-fits-all controller
|
|
*/
|
|
|
|
$format = $input->getCmd('format', 'html');
|
|
$path = null;
|
|
|
|
if (!empty($format))
|
|
{
|
|
$path = $filesystem->pathFind(
|
|
$searchPaths, strtolower($suffix) . '.' . strtolower($format) . '.php'
|
|
);
|
|
}
|
|
|
|
if (!$path)
|
|
{
|
|
$path = $filesystem->pathFind(
|
|
$searchPaths, strtolower($suffix) . '.php'
|
|
);
|
|
}
|
|
|
|
// The path is found. Load the file and make sure the expected class name exists.
|
|
|
|
if ($path)
|
|
{
|
|
require_once $path;
|
|
|
|
if (class_exists($className))
|
|
{
|
|
// The class was loaded successfully. We have a match!
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!class_exists($className))
|
|
{
|
|
// If no specialised class is found, instantiate the generic F0FController
|
|
$className = 'F0FController';
|
|
}
|
|
|
|
$instance = new $className($config);
|
|
|
|
return $instance;
|
|
}
|
|
|
|
/**
|
|
* Public constructor of the Controller class
|
|
*
|
|
* @param array $config Optional configuration parameters
|
|
*/
|
|
public function __construct($config = array())
|
|
{
|
|
// Make sure $config is an array
|
|
if (is_object($config))
|
|
{
|
|
$config = (array) $config;
|
|
}
|
|
elseif (!is_array($config))
|
|
{
|
|
$config = array();
|
|
}
|
|
|
|
$this->methods = array();
|
|
$this->message = null;
|
|
$this->messageType = 'message';
|
|
$this->paths = array();
|
|
$this->redirect = null;
|
|
$this->taskMap = array();
|
|
|
|
// Cache the config
|
|
$this->config = $config;
|
|
|
|
// Get the input for this MVC triad
|
|
|
|
if (array_key_exists('input', $config))
|
|
{
|
|
$input = $config['input'];
|
|
}
|
|
else
|
|
{
|
|
$input = null;
|
|
}
|
|
|
|
if (array_key_exists('input_options', $config))
|
|
{
|
|
$input_options = $config['input_options'];
|
|
}
|
|
else
|
|
{
|
|
$input_options = array();
|
|
}
|
|
|
|
if ($input instanceof F0FInput)
|
|
{
|
|
$this->input = $input;
|
|
}
|
|
else
|
|
{
|
|
$this->input = new F0FInput($input, $input_options);
|
|
}
|
|
|
|
// Load the configuration provider
|
|
$this->configProvider = new F0FConfigProvider;
|
|
|
|
// Determine the methods to exclude from the base class.
|
|
$xMethods = get_class_methods('F0FController');
|
|
|
|
// Some methods must always be considered valid tasks
|
|
$iMethods = array('accesspublic', 'accessregistered', 'accessspecial',
|
|
'add', 'apply', 'browse', 'cancel', 'copy', 'edit', 'orderdown',
|
|
'orderup', 'publish', 'read', 'remove', 'save', 'savenew',
|
|
'saveorder', 'unpublish', 'display', 'archive', 'trash', 'loadhistory');
|
|
|
|
// Get the public methods in this class using reflection.
|
|
$r = new ReflectionClass($this);
|
|
$rMethods = $r->getMethods(ReflectionMethod::IS_PUBLIC);
|
|
|
|
foreach ($rMethods as $rMethod)
|
|
{
|
|
$mName = $rMethod->getName();
|
|
|
|
// If the developer screwed up and declared one of the helper method public do NOT make them available as
|
|
// tasks.
|
|
if ((substr($mName, 0, 8) == 'onBefore') || (substr($mName, 0, 7) == 'onAfter') || substr($mName, 0, 1) == '_')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Add default display method if not explicitly declared.
|
|
if (!in_array($mName, $xMethods) || in_array($mName, $iMethods))
|
|
{
|
|
$this->methods[] = strtolower($mName);
|
|
|
|
// Auto register the methods as tasks.
|
|
$this->taskMap[strtolower($mName)] = $mName;
|
|
}
|
|
}
|
|
|
|
// Get the default values for the component and view names
|
|
$classNameParts = F0FInflector::explode(get_class($this));
|
|
|
|
if (count($classNameParts) == 3)
|
|
{
|
|
$defComponent = "com_" . $classNameParts[0];
|
|
$defView = $classNameParts[2];
|
|
}
|
|
else
|
|
{
|
|
$defComponent = 'com_foobar';
|
|
$defView = 'cpanel';
|
|
}
|
|
|
|
$this->component = $this->input->get('option', $defComponent, 'cmd');
|
|
$this->view = $this->input->get('view', $defView, 'cmd');
|
|
$this->layout = $this->input->get('layout', null, 'cmd');
|
|
|
|
// Overrides from the config
|
|
if (array_key_exists('option', $config))
|
|
{
|
|
$this->component = $config['option'];
|
|
}
|
|
|
|
if (array_key_exists('view', $config))
|
|
{
|
|
$this->view = $config['view'];
|
|
}
|
|
|
|
if (array_key_exists('layout', $config))
|
|
{
|
|
$this->layout = $config['layout'];
|
|
}
|
|
|
|
$this->layout = $this->configProvider->get($this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.layout', $this->layout);
|
|
|
|
$this->input->set('option', $this->component);
|
|
|
|
// Set the bareComponent variable
|
|
$this->bareComponent = str_replace('com_', '', strtolower($this->component));
|
|
|
|
// Set the $name variable
|
|
$this->name = $this->bareComponent;
|
|
|
|
// Set the basePath variable
|
|
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($this->component);
|
|
$basePath = $componentPaths['main'];
|
|
|
|
if (array_key_exists('base_path', $config))
|
|
{
|
|
$basePath = $config['base_path'];
|
|
}
|
|
|
|
$altBasePath = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.config.base_path', null
|
|
);
|
|
|
|
if (!is_null($altBasePath))
|
|
{
|
|
$platformDirs = F0FPlatform::getInstance()->getPlatformBaseDirs();
|
|
$basePath = $platformDirs['public'] . '/' . $altBasePath;
|
|
}
|
|
|
|
$this->basePath = $basePath;
|
|
|
|
// If the default task is set, register it as such
|
|
$defaultTask = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.config.default_task', 'display'
|
|
);
|
|
|
|
if (array_key_exists('default_task', $config))
|
|
{
|
|
$this->registerDefaultTask($config['default_task']);
|
|
}
|
|
else
|
|
{
|
|
$this->registerDefaultTask($defaultTask);
|
|
}
|
|
|
|
// Set the models prefix
|
|
|
|
if (empty($this->model_prefix))
|
|
{
|
|
if (array_key_exists('model_prefix', $config))
|
|
{
|
|
// User-defined prefix
|
|
$this->model_prefix = $config['model_prefix'];
|
|
}
|
|
else
|
|
{
|
|
$this->model_prefix = $this->name . 'Model';
|
|
$this->model_prefix = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.config.model_prefix', $this->model_prefix
|
|
);
|
|
}
|
|
}
|
|
|
|
// Set the default model search path
|
|
|
|
if (array_key_exists('model_path', $config))
|
|
{
|
|
// User-defined dirs
|
|
$this->addModelPath($config['model_path'], $this->model_prefix);
|
|
}
|
|
else
|
|
{
|
|
$modelPath = $this->basePath . '/models';
|
|
$altModelPath = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.config.model_path', null
|
|
);
|
|
|
|
if (!is_null($altModelPath))
|
|
{
|
|
$modelPath = $this->basePath . '/' . $altModelPath;
|
|
}
|
|
|
|
$this->addModelPath($modelPath, $this->model_prefix);
|
|
}
|
|
|
|
// Set the default view search path
|
|
if (array_key_exists('view_path', $config))
|
|
{
|
|
// User-defined dirs
|
|
$this->setPath('view', $config['view_path']);
|
|
}
|
|
else
|
|
{
|
|
$viewPath = $this->basePath . '/views';
|
|
$altViewPath = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.config.view_path', null
|
|
);
|
|
|
|
if (!is_null($altViewPath))
|
|
{
|
|
$viewPath = $this->basePath . '/' . $altViewPath;
|
|
}
|
|
|
|
$this->setPath('view', $viewPath);
|
|
}
|
|
|
|
// Set the default view.
|
|
|
|
if (array_key_exists('default_view', $config))
|
|
{
|
|
$this->default_view = $config['default_view'];
|
|
}
|
|
else
|
|
{
|
|
if (empty($this->default_view))
|
|
{
|
|
$this->default_view = $this->getName();
|
|
}
|
|
|
|
$this->default_view = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.config.default_view', $this->default_view
|
|
);
|
|
}
|
|
|
|
// Set the CSRF protection
|
|
if (array_key_exists('csrf_protection', $config))
|
|
{
|
|
$this->csrfProtection = $config['csrf_protection'];
|
|
}
|
|
|
|
$this->csrfProtection = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.config.csrf_protection', $this->csrfProtection
|
|
);
|
|
|
|
// Set any model/view name overrides
|
|
if (array_key_exists('viewName', $config))
|
|
{
|
|
$this->setThisViewName($config['viewName']);
|
|
}
|
|
else
|
|
{
|
|
$overrideViewName = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.config.viewName', null
|
|
);
|
|
|
|
if ($overrideViewName)
|
|
{
|
|
$this->setThisViewName($overrideViewName);
|
|
}
|
|
}
|
|
|
|
if (array_key_exists('modelName', $config))
|
|
{
|
|
$this->setThisModelName($config['modelName']);
|
|
}
|
|
else
|
|
{
|
|
$overrideModelName = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.config.modelName', null
|
|
);
|
|
|
|
if ($overrideModelName)
|
|
{
|
|
$this->setThisModelName($overrideModelName);
|
|
}
|
|
}
|
|
|
|
// Caching
|
|
if (array_key_exists('cacheableTasks', $config))
|
|
{
|
|
if (is_array($config['cacheableTasks']))
|
|
{
|
|
$this->cacheableTasks = $config['cacheableTasks'];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$cacheableTasks = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.config.cacheableTasks', null
|
|
);
|
|
|
|
if ($cacheableTasks)
|
|
{
|
|
$cacheableTasks = explode(',', $cacheableTasks);
|
|
|
|
if (count($cacheableTasks))
|
|
{
|
|
$temp = array();
|
|
|
|
foreach ($cacheableTasks as $t)
|
|
{
|
|
$temp[] = trim($t);
|
|
}
|
|
|
|
$temp = array_unique($temp);
|
|
$this->cacheableTasks = $temp;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Bit mask for auto routing on setRedirect
|
|
$this->autoRouting = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.config.autoRouting', $this->autoRouting
|
|
);
|
|
|
|
if (array_key_exists('autoRouting', $config))
|
|
{
|
|
$this->autoRouting = $config['autoRouting'];
|
|
}
|
|
|
|
// Apply task map
|
|
$taskmap = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.taskmap'
|
|
);
|
|
|
|
if (is_array($taskmap) && !empty($taskmap))
|
|
{
|
|
foreach ($taskmap as $aliasedtask => $realmethod)
|
|
{
|
|
$this->registerTask($aliasedtask, $realmethod);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds to the stack of model paths in LIFO order.
|
|
*
|
|
* @param mixed $path The directory (string) , or list of directories (array) to add.
|
|
* @param string $prefix A prefix for models
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function addModelPath($path, $prefix = '')
|
|
{
|
|
F0FModel::addIncludePath($path, $prefix);
|
|
}
|
|
|
|
/**
|
|
* Adds to the search path for templates and resources.
|
|
*
|
|
* @param string $type The path type (e.g. 'model', 'view').
|
|
* @param mixed $path The directory string or stream array to search.
|
|
*
|
|
* @return F0FController A F0FController object to support chaining.
|
|
*/
|
|
protected function addPath($type, $path)
|
|
{
|
|
// Just force path to array
|
|
settype($path, 'array');
|
|
|
|
$filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem');
|
|
|
|
if (!isset($this->paths[$type]))
|
|
{
|
|
$this->paths[$type] = array();
|
|
}
|
|
|
|
// Loop through the path directories
|
|
foreach ($path as $dir)
|
|
{
|
|
// No surrounding spaces allowed!
|
|
$dir = rtrim($filesystem->pathCheck($dir, '/'), '/') . '/';
|
|
|
|
// Add to the top of the search dirs
|
|
array_unshift($this->paths[$type], $dir);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Add one or more view paths to the controller's stack, in LIFO order.
|
|
*
|
|
* @param mixed $path The directory (string) or list of directories (array) to add.
|
|
*
|
|
* @return F0FController This object to support chaining.
|
|
*/
|
|
public function addViewPath($path)
|
|
{
|
|
$this->addPath('view', $path);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Authorisation check
|
|
*
|
|
* @param string $task The ACO Section Value to check access on.
|
|
*
|
|
* @return boolean True if authorised
|
|
*
|
|
* @deprecated 2.0 Use JAccess instead.
|
|
*/
|
|
public function authorise($task)
|
|
{
|
|
F0FPlatform::getInstance()->logDeprecated(__CLASS__ . '::' .__METHOD__ . ' is deprecated. Use checkACL() instead.');
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 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. Optional.
|
|
*
|
|
* @return string The filename.
|
|
*/
|
|
protected static function createFileName($type, $parts = array())
|
|
{
|
|
$filename = '';
|
|
|
|
switch ($type)
|
|
{
|
|
case 'controller':
|
|
if (!empty($parts['format']))
|
|
{
|
|
if ($parts['format'] == 'html')
|
|
{
|
|
$parts['format'] = '';
|
|
}
|
|
else
|
|
{
|
|
$parts['format'] = '.' . $parts['format'];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$parts['format'] = '';
|
|
}
|
|
|
|
$filename = strtolower($parts['name'] . $parts['format'] . '.php');
|
|
break;
|
|
|
|
case 'view':
|
|
if (!empty($parts['type']))
|
|
{
|
|
$parts['type'] = '.' . $parts['type'];
|
|
}
|
|
else
|
|
{
|
|
$parts['type'] = '';
|
|
}
|
|
|
|
$filename = strtolower($parts['name'] . '/view' . $parts['type'] . '.php');
|
|
break;
|
|
}
|
|
|
|
return $filename;
|
|
}
|
|
|
|
/**
|
|
* Executes a given controller task. The onBefore<task> and onAfter<task>
|
|
* methods are called automatically if they exist.
|
|
*
|
|
* @param string $task The task to execute, e.g. "browse"
|
|
*
|
|
* @throws Exception Exception thrown if the onBefore<task> returns false
|
|
*
|
|
* @return null|bool False on execution failure
|
|
*/
|
|
public function execute($task)
|
|
{
|
|
$this->task = $task;
|
|
|
|
$method_name = 'onBefore' . ucfirst($task);
|
|
|
|
if (!method_exists($this, $method_name))
|
|
{
|
|
$result = $this->onBeforeGenericTask($task);
|
|
}
|
|
elseif (method_exists($this, $method_name))
|
|
{
|
|
$result = $this->$method_name();
|
|
}
|
|
else
|
|
{
|
|
$result = true;
|
|
}
|
|
|
|
if ($result)
|
|
{
|
|
$plugin_event = F0FInflector::camelize('on before ' . $this->bareComponent . ' controller ' . $this->view . ' ' . $task);
|
|
$plugin_result = F0FPlatform::getInstance()->runPlugins($plugin_event, array(&$this, &$this->input));
|
|
|
|
if (in_array(false, $plugin_result, true))
|
|
{
|
|
$result = false;
|
|
}
|
|
}
|
|
|
|
if (!$result)
|
|
{
|
|
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403);
|
|
}
|
|
|
|
// Do not allow the display task to be directly called
|
|
$task = strtolower($task);
|
|
|
|
if (isset($this->taskMap[$task]))
|
|
{
|
|
$doTask = $this->taskMap[$task];
|
|
}
|
|
elseif (isset($this->taskMap['__default']))
|
|
{
|
|
$doTask = $this->taskMap['__default'];
|
|
}
|
|
else
|
|
{
|
|
$doTask = null;
|
|
}
|
|
|
|
if ($doTask == 'display')
|
|
{
|
|
F0FPlatform::getInstance()->setHeader('Status', '400 Bad Request', true);
|
|
|
|
throw new Exception('Bad Request', 400);
|
|
}
|
|
|
|
$this->doTask = $doTask;
|
|
|
|
$ret = $this->$doTask();
|
|
|
|
$method_name = 'onAfter' . ucfirst($task);
|
|
|
|
if (method_exists($this, $method_name))
|
|
{
|
|
$result = $this->$method_name();
|
|
}
|
|
else
|
|
{
|
|
$result = true;
|
|
}
|
|
|
|
if ($result)
|
|
{
|
|
$plugin_event = F0FInflector::camelize('on after ' . $this->bareComponent . ' controller ' . $this->view . ' ' . $task);
|
|
$plugin_result = F0FPlatform::getInstance()->runPlugins($plugin_event, array(&$this, &$this->input, &$ret));
|
|
|
|
if (in_array(false, $plugin_result, true))
|
|
{
|
|
$result = false;
|
|
}
|
|
}
|
|
|
|
if (!$result)
|
|
{
|
|
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403);
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Default task. Assigns a model to the view and asks the view to render
|
|
* itself.
|
|
*
|
|
* YOU MUST NOT USETHIS TASK DIRECTLY IN A URL. It is supposed to be
|
|
* used ONLY inside your code. In the URL, use task=browse instead.
|
|
*
|
|
* @param bool $cachable Is this view cacheable?
|
|
* @param bool $urlparams Add your safe URL parameters (see further down in the code)
|
|
* @param string $tpl The name of the template file to parse
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function display($cachable = false, $urlparams = false, $tpl = null)
|
|
{
|
|
$document = F0FPlatform::getInstance()->getDocument();
|
|
|
|
if ($document instanceof JDocument)
|
|
{
|
|
$viewType = $document->getType();
|
|
}
|
|
else
|
|
{
|
|
$viewType = $this->input->getCmd('format', 'html');
|
|
}
|
|
|
|
$view = $this->getThisView();
|
|
|
|
// Get/Create the model
|
|
|
|
if ($model = $this->getThisModel())
|
|
{
|
|
// Push the model into the view (as default)
|
|
$view->setModel($model, true);
|
|
}
|
|
|
|
// Set the layout
|
|
$view->setLayout(is_null($this->layout) ? 'default' : $this->layout);
|
|
|
|
// Display the view
|
|
$conf = F0FPlatform::getInstance()->getConfig();
|
|
|
|
if (F0FPlatform::getInstance()->isFrontend() && $cachable && ($viewType != 'feed') && $conf->get('caching') >= 1)
|
|
{
|
|
// Get a JCache object
|
|
$option = $this->input->get('option', 'com_foobar', 'cmd');
|
|
$cache = JFactory::getCache($option, 'view');
|
|
|
|
// Set up a cache ID based on component, view, task and user group assignment
|
|
$user = F0FPlatform::getInstance()->getUser();
|
|
|
|
if ($user->guest)
|
|
{
|
|
$groups = array();
|
|
}
|
|
else
|
|
{
|
|
$groups = $user->groups;
|
|
}
|
|
|
|
$importantParameters = array();
|
|
|
|
// Set up safe URL parameters
|
|
if (!is_array($urlparams))
|
|
{
|
|
$urlparams = array(
|
|
'option' => 'CMD',
|
|
'view' => 'CMD',
|
|
'task' => 'CMD',
|
|
'format' => 'CMD',
|
|
'layout' => 'CMD',
|
|
'id' => 'INT',
|
|
);
|
|
}
|
|
|
|
if (is_array($urlparams))
|
|
{
|
|
$app = JFactory::getApplication();
|
|
|
|
$registeredurlparams = null;
|
|
|
|
if (version_compare(JVERSION, '3.0', 'ge'))
|
|
{
|
|
if (property_exists($app, 'registeredurlparams'))
|
|
{
|
|
$registeredurlparams = $app->registeredurlparams;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$registeredurlparams = $app->get('registeredurlparams');
|
|
}
|
|
|
|
if (empty($registeredurlparams))
|
|
{
|
|
$registeredurlparams = new stdClass;
|
|
}
|
|
|
|
foreach ($urlparams AS $key => $value)
|
|
{
|
|
// Add your safe url parameters with variable type as value {@see JFilterInput::clean()}.
|
|
$registeredurlparams->$key = $value;
|
|
|
|
// Add the URL-important parameters into the array
|
|
$importantParameters[$key] = $this->input->get($key, null, $value);
|
|
}
|
|
|
|
if (version_compare(JVERSION, '3.0', 'ge'))
|
|
{
|
|
$app->registeredurlparams = $registeredurlparams;
|
|
}
|
|
else
|
|
{
|
|
$app->set('registeredurlparams', $registeredurlparams);
|
|
}
|
|
}
|
|
|
|
// Create the cache ID after setting the registered URL params, as they are used to generate the ID
|
|
$cacheId = md5(serialize(array(JCache::makeId(), $view->getName(), $this->doTask, $groups, $importantParameters)));
|
|
|
|
// Get the cached view or cache the current view
|
|
$cache->get($view, 'display', $cacheId);
|
|
}
|
|
else
|
|
{
|
|
// Display without caching
|
|
$view->display($tpl);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Implements a default browse task, i.e. read a bunch of records and send
|
|
* them to the browser.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function browse()
|
|
{
|
|
if ($this->input->get('savestate', -999, 'int') == -999)
|
|
{
|
|
$this->input->set('savestate', true);
|
|
}
|
|
|
|
// Do I have a form?
|
|
$model = $this->getThisModel();
|
|
|
|
if (empty($this->layout))
|
|
{
|
|
$formname = 'form.default';
|
|
}
|
|
else
|
|
{
|
|
$formname = 'form.' . $this->layout;
|
|
}
|
|
|
|
$model->setState('form_name', $formname);
|
|
|
|
$form = $model->getForm();
|
|
|
|
if ($form !== false)
|
|
{
|
|
$this->hasForm = true;
|
|
}
|
|
|
|
$this->display(in_array('browse', $this->cacheableTasks));
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Single record read. The id set in the request is passed to the model and
|
|
* then the item layout is used to render the result.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function read()
|
|
{
|
|
// Load the model
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
// Set the layout to item, if it's not set in the URL
|
|
if (is_null($this->layout))
|
|
{
|
|
$this->layout = 'item';
|
|
}
|
|
|
|
// Do I have a form?
|
|
$model->setState('form_name', 'form.' . $this->layout);
|
|
|
|
$item = $model->getItem();
|
|
|
|
if (!($item instanceof F0FTable))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$itemKey = $item->getKeyName();
|
|
|
|
if ($item->$itemKey != $model->getId())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$formData = is_object($item) ? $item->getData() : array();
|
|
$form = $model->getForm($formData);
|
|
|
|
if ($form !== false)
|
|
{
|
|
$this->hasForm = true;
|
|
}
|
|
|
|
// Display
|
|
$this->display(in_array('read', $this->cacheableTasks));
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Single record add. The form layout is used to present a blank page.
|
|
*
|
|
* @return false|void
|
|
*/
|
|
public function add()
|
|
{
|
|
// Load and reset the model
|
|
$model = $this->getThisModel();
|
|
$model->reset();
|
|
|
|
// Set the layout to form, if it's not set in the URL
|
|
|
|
if (!$this->layout)
|
|
{
|
|
$this->layout = 'form';
|
|
}
|
|
|
|
// Do I have a form?
|
|
$model->setState('form_name', 'form.' . $this->layout);
|
|
|
|
$item = $model->getItem();
|
|
|
|
if (!($item instanceof F0FTable))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$formData = is_object($item) ? $item->getData() : array();
|
|
$form = $model->getForm($formData);
|
|
|
|
if ($form !== false)
|
|
{
|
|
$this->hasForm = true;
|
|
}
|
|
|
|
// Display
|
|
$this->display(in_array('add', $this->cacheableTasks));
|
|
}
|
|
|
|
/**
|
|
* Single record edit. The ID set in the request is passed to the model,
|
|
* then the form layout is used to edit the result.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function edit()
|
|
{
|
|
// Load the model
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$status = $model->checkout();
|
|
|
|
if (!$status)
|
|
{
|
|
// Redirect on error
|
|
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
$this->setRedirect($url, $model->getError(), 'error');
|
|
|
|
return false;
|
|
}
|
|
|
|
// Set the layout to form, if it's not set in the URL
|
|
|
|
if (is_null($this->layout))
|
|
{
|
|
$this->layout = 'form';
|
|
}
|
|
|
|
// Do I have a form?
|
|
$model->setState('form_name', 'form.' . $this->layout);
|
|
|
|
$item = $model->getItem();
|
|
|
|
if (!($item instanceof F0FTable))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$itemKey = $item->getKeyName();
|
|
|
|
if ($item->$itemKey != $model->getId())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$formData = is_object($item) ? $item->getData() : array();
|
|
$form = $model->getForm($formData);
|
|
|
|
if ($form !== false)
|
|
{
|
|
$this->hasForm = true;
|
|
}
|
|
|
|
// Display
|
|
$this->display(in_array('edit', $this->cacheableTasks));
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Save the incoming data and then return to the Edit task
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function apply()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
$model = $this->getThisModel();
|
|
$result = $this->applySave();
|
|
|
|
// Redirect to the edit task
|
|
if ($result)
|
|
{
|
|
$id = $this->input->get('id', 0, 'int');
|
|
$textkey = strtoupper($this->component) . '_LBL_' . strtoupper($this->view) . '_SAVED';
|
|
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=edit&id=' . $id . $this->getItemidURLSuffix();
|
|
$this->setRedirect($url, JText::_($textkey));
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Duplicates selected items
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function copy()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$status = $model->copy();
|
|
|
|
// Redirect
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
|
|
if (!$status)
|
|
{
|
|
$this->setRedirect($url, $model->getError(), 'error');
|
|
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if(!F0FPlatform::getInstance()->isCli())
|
|
{
|
|
F0FPlatform::getInstance()->setHeader('Status', '201 Created', true);
|
|
}
|
|
|
|
$this->setRedirect($url);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save the incoming data and then return to the Browse task
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function save()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
$result = $this->applySave();
|
|
|
|
// Redirect to the display task
|
|
if ($result)
|
|
{
|
|
$textkey = strtoupper($this->component) . '_LBL_' . strtoupper($this->view) . '_SAVED';
|
|
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
$this->setRedirect($url, JText::_($textkey));
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Save the incoming data and then return to the Add task
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function savenew()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
$result = $this->applySave();
|
|
|
|
// Redirect to the display task
|
|
|
|
if ($result)
|
|
{
|
|
$textkey = strtoupper($this->component) . '_LBL_' . strtoupper($this->view) . '_SAVED';
|
|
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=add' . $this->getItemidURLSuffix();
|
|
$this->setRedirect($url, JText::_($textkey));
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Cancel the edit, check in the record and return to the Browse task
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function cancel()
|
|
{
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$model->checkin();
|
|
|
|
// Remove any saved data
|
|
JFactory::getSession()->set($model->getHash() . 'savedata', null);
|
|
|
|
// Redirect to the display task
|
|
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
$this->setRedirect($url);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Method to load a row from version history
|
|
*
|
|
* @return boolean True if the content history is reverted, false otherwise
|
|
*
|
|
* @since 2.2
|
|
*/
|
|
public function loadhistory()
|
|
{
|
|
$app = JFactory::getApplication();
|
|
$lang = JFactory::getLanguage();
|
|
$model = $this->getThisModel();
|
|
$table = $model->getTable();
|
|
$historyId = $app->input->get('version_id', null, 'integer');
|
|
$status = $model->checkout();
|
|
$alias = $this->component . '.' . $this->view;
|
|
|
|
if (!$model->loadhistory($historyId, $table, $alias))
|
|
{
|
|
$this->setMessage($model->getError(), 'error');
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
$this->setRedirect($url);
|
|
|
|
return false;
|
|
}
|
|
|
|
// Determine the name of the primary key for the data.
|
|
if (empty($key))
|
|
{
|
|
$key = $table->getKeyName();
|
|
}
|
|
|
|
$recordId = $table->$key;
|
|
|
|
// To avoid data collisions the urlVar may be different from the primary key.
|
|
$urlVar = empty($this->urlVar) ? $key : $this->urlVar;
|
|
|
|
// Access check.
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.edit', 'core.edit'
|
|
);
|
|
|
|
if (!$this->checkACL($privilege))
|
|
{
|
|
$this->setError(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'));
|
|
$this->setMessage($this->getError(), 'error');
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
$this->setRedirect($url);
|
|
$table->checkin();
|
|
|
|
return false;
|
|
}
|
|
|
|
$table->store();
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
$this->setRedirect($url);
|
|
|
|
$this->setMessage(JText::sprintf('JLIB_APPLICATION_SUCCESS_LOAD_HISTORY', $model->getState('save_date'), $model->getState('version_note')));
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Sets the access to public. Joomla! 1.5 compatibility.
|
|
*
|
|
* @return bool
|
|
*
|
|
* @deprecated since 2.0
|
|
*/
|
|
public function accesspublic()
|
|
{
|
|
// CSRF prevention
|
|
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
return $this->setaccess(0);
|
|
}
|
|
|
|
/**
|
|
* Sets the access to registered. Joomla! 1.5 compatibility.
|
|
*
|
|
* @return bool
|
|
*
|
|
* @deprecated since 2.0
|
|
*/
|
|
public function accessregistered()
|
|
{
|
|
// CSRF prevention
|
|
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
return $this->setaccess(1);
|
|
}
|
|
|
|
/**
|
|
* Sets the access to special. Joomla! 1.5 compatibility.
|
|
*
|
|
* @return bool
|
|
*
|
|
* @deprecated since 2.0
|
|
*/
|
|
public function accessspecial()
|
|
{
|
|
// CSRF prevention
|
|
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
return $this->setaccess(2);
|
|
}
|
|
|
|
/**
|
|
* Publish (set enabled = 1) an item.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function publish()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
return $this->setstate(1);
|
|
}
|
|
|
|
/**
|
|
* Unpublish (set enabled = 0) an item.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function unpublish()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
return $this->setstate(0);
|
|
}
|
|
|
|
/**
|
|
* Archive (set enabled = 2) an item.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function archive()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
return $this->setstate(2);
|
|
}
|
|
|
|
/**
|
|
* Trash (set enabled = -2) an item.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function trash()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
return $this->setstate(-2);
|
|
}
|
|
|
|
/**
|
|
* Saves the order of the items
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function saveorder()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$ordering = $model->getTable()->getColumnAlias('ordering');
|
|
$ids = $model->getIds();
|
|
$orders = $this->input->get('order', array(), 'array');
|
|
|
|
if ($n = count($ids))
|
|
{
|
|
for ($i = 0; $i < $n; $i++)
|
|
{
|
|
$model->setId($ids[$i]);
|
|
$neworder = (int) $orders[$i];
|
|
|
|
$item = $model->getItem();
|
|
|
|
if (!($item instanceof F0FTable))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$key = $item->getKeyName();
|
|
|
|
if ($item->$key == $ids[$i])
|
|
{
|
|
$item->$ordering = $neworder;
|
|
$model->save($item);
|
|
}
|
|
}
|
|
}
|
|
|
|
$status = $model->reorder();
|
|
|
|
// Redirect
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
$this->setRedirect($url);
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Moves selected items one position down the ordering list
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function orderdown()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$status = $model->move(1);
|
|
|
|
// Redirect
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
|
|
if (!$status)
|
|
{
|
|
$this->setRedirect($url, $model->getError(), 'error');
|
|
}
|
|
else
|
|
{
|
|
$this->setRedirect($url);
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Moves selected items one position up the ordering list
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function orderup()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$status = $model->move(-1);
|
|
|
|
// Redirect
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
|
|
if (!$status)
|
|
{
|
|
$this->setRedirect($url, $model->getError(), 'error');
|
|
}
|
|
else
|
|
{
|
|
$this->setRedirect($url);
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Delete selected item(s)
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function remove()
|
|
{
|
|
// CSRF prevention
|
|
if ($this->csrfProtection)
|
|
{
|
|
$this->_csrfProtection();
|
|
}
|
|
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$status = $model->delete();
|
|
|
|
// Redirect
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
|
|
if (!$status)
|
|
{
|
|
$this->setRedirect($url, $model->getError(), 'error');
|
|
}
|
|
else
|
|
{
|
|
$this->setRedirect($url);
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Redirects the browser or returns false if no redirect is set.
|
|
*
|
|
* @return boolean False if no redirect exists.
|
|
*/
|
|
public function redirect()
|
|
{
|
|
if ($this->redirect)
|
|
{
|
|
$app = JFactory::getApplication();
|
|
$app->enqueueMessage($this->message, $this->messageType);
|
|
$app->redirect($this->redirect);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns true if there is a redirect set in the controller
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function hasRedirect()
|
|
{
|
|
return !empty($this->redirect);
|
|
}
|
|
|
|
/**
|
|
* Register the default task to perform if a mapping is not found.
|
|
*
|
|
* @param string $method The name of the method in the derived class to perform if a named task is not found.
|
|
*
|
|
* @return F0FController A F0FController object to support chaining.
|
|
*/
|
|
public function registerDefaultTask($method)
|
|
{
|
|
$this->registerTask('__default', $method);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Register (map) a task to a method in the class.
|
|
*
|
|
* @param string $task The task.
|
|
* @param string $method The name of the method in the derived class to perform for this task.
|
|
*
|
|
* @return F0FController A F0FController object to support chaining.
|
|
*/
|
|
public function registerTask($task, $method)
|
|
{
|
|
if (in_array(strtolower($method), $this->methods))
|
|
{
|
|
$this->taskMap[strtolower($task)] = $method;
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Unregister (unmap) a task in the class.
|
|
*
|
|
* @param string $task The task.
|
|
*
|
|
* @return F0FController This object to support chaining.
|
|
*/
|
|
public function unregisterTask($task)
|
|
{
|
|
unset($this->taskMap[strtolower($task)]);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Sets the internal message that is passed with a redirect
|
|
*
|
|
* @param string $text Message to display on redirect.
|
|
* @param string $type Message type. Optional, defaults to 'message'.
|
|
*
|
|
* @return string Previous message
|
|
*/
|
|
public function setMessage($text, $type = 'message')
|
|
{
|
|
$previous = $this->message;
|
|
$this->message = $text;
|
|
$this->messageType = $type;
|
|
|
|
return $previous;
|
|
}
|
|
|
|
/**
|
|
* Sets an entire array of search paths for resources.
|
|
*
|
|
* @param string $type The type of path to set, typically 'view' or 'model'.
|
|
* @param string $path The new set 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->paths[$type] = array();
|
|
|
|
// Actually add the user-specified directories
|
|
$this->addPath($type, $path);
|
|
}
|
|
|
|
/**
|
|
* Registers a redirection with an optional message. The redirection is
|
|
* carried out when you use the redirect method.
|
|
*
|
|
* @param string $url The URL to redirect to
|
|
* @param string $msg The message to be pushed to the application
|
|
* @param string $type The message type to be pushed to the application, e.g. 'error'
|
|
*
|
|
* @return F0FController This object to support chaining
|
|
*/
|
|
public function setRedirect($url, $msg = null, $type = null)
|
|
{
|
|
// Do the logic only if we're parsing a raw url (index.php?foo=bar&etc=etc)
|
|
if (strpos($url, 'index.php') === 0)
|
|
{
|
|
$isAdmin = F0FPlatform::getInstance()->isBackend();
|
|
$auto = false;
|
|
|
|
if (($this->autoRouting == 2 || $this->autoRouting == 3) && $isAdmin)
|
|
{
|
|
$auto = true;
|
|
}
|
|
elseif (($this->autoRouting == 1 || $this->autoRouting == 3) && !$isAdmin)
|
|
{
|
|
$auto = true;
|
|
}
|
|
|
|
if ($auto)
|
|
{
|
|
$url = JRoute::_($url, false);
|
|
}
|
|
}
|
|
|
|
$this->redirect = $url;
|
|
|
|
if ($msg !== null)
|
|
{
|
|
// Controller may have set this directly
|
|
$this->message = $msg;
|
|
}
|
|
|
|
// Ensure the type is not overwritten by a previous call to setMessage.
|
|
if (empty($type))
|
|
{
|
|
if (empty($this->messageType))
|
|
{
|
|
$this->messageType = 'message';
|
|
}
|
|
}
|
|
// If the type is explicitly set, set it.
|
|
else
|
|
{
|
|
$this->messageType = $type;
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Sets the published state (the enabled field) of the selected item(s)
|
|
*
|
|
* @param integer $state The desired state. 0 is unpublished, 1 is published.
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function setstate($state = 0)
|
|
{
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$status = $model->publish($state);
|
|
|
|
// Redirect
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
|
|
if (!$status)
|
|
{
|
|
$this->setRedirect($url, $model->getError(), 'error');
|
|
}
|
|
else
|
|
{
|
|
$this->setRedirect($url);
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Sets the access level of the selected item(s).
|
|
*
|
|
* @param integer $level The desired viewing access level ID
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function setaccess($level = 0)
|
|
{
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$id = $model->getId();
|
|
$item = $model->getItem();
|
|
|
|
if (!($item instanceof F0FTable))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$accessField = $item->getColumnAlias('access');
|
|
$key = $item->getKeyName();
|
|
$loadedid = $item->$key;
|
|
|
|
if ($id == $loadedid)
|
|
{
|
|
$item->$accessField = $level;
|
|
$status = $model->save($item);
|
|
}
|
|
else
|
|
{
|
|
$status = false;
|
|
}
|
|
|
|
// Redirect
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix();
|
|
|
|
if (!$status)
|
|
{
|
|
$this->setRedirect($url, $model->getError(), 'error');
|
|
}
|
|
else
|
|
{
|
|
$this->setRedirect($url);
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Common method to handle apply and save tasks
|
|
*
|
|
* @return boolean Returns true on success
|
|
*/
|
|
final private function applySave()
|
|
{
|
|
// Load the model
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$id = $model->getId();
|
|
|
|
$data = $this->input->getData();
|
|
|
|
if (!$this->onBeforeApplySave($data))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Set the layout to form, if it's not set in the URL
|
|
|
|
if (is_null($this->layout))
|
|
{
|
|
$this->layout = 'form';
|
|
}
|
|
|
|
// Do I have a form?
|
|
$model->setState('form_name', 'form.' . $this->layout);
|
|
|
|
$status = $model->save($data);
|
|
|
|
if ($status && ($id != 0))
|
|
{
|
|
F0FPlatform::getInstance()->setHeader('Status', '201 Created', true);
|
|
|
|
// Try to check-in the record if it's not a new one
|
|
$status = $model->checkin();
|
|
}
|
|
|
|
if ($status)
|
|
{
|
|
$status = $this->onAfterApplySave();
|
|
}
|
|
|
|
$this->input->set('id', $model->getId());
|
|
|
|
if (!$status)
|
|
{
|
|
// Redirect on error
|
|
$id = $model->getId();
|
|
|
|
if ($customURL = $this->input->get('returnurl', '', 'string'))
|
|
{
|
|
$customURL = base64_decode($customURL);
|
|
}
|
|
|
|
if (!empty($customURL))
|
|
{
|
|
$url = $customURL;
|
|
}
|
|
elseif ($id != 0)
|
|
{
|
|
$url = 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=edit&id=' . $id . $this->getItemidURLSuffix();
|
|
}
|
|
else
|
|
{
|
|
$url = 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=add' . $this->getItemidURLSuffix();
|
|
}
|
|
|
|
$this->setRedirect($url, '<li>' . implode('</li><li>', $model->getErrors()) . '</li>', 'error');
|
|
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
$session = JFactory::getSession();
|
|
$session->set($model->getHash() . 'savedata', null);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the default model associated with the current view
|
|
*
|
|
* @param array $config Configuration variables for the model
|
|
*
|
|
* @return F0FModel The global instance of the model (singleton)
|
|
*/
|
|
final public function getThisModel($config = array())
|
|
{
|
|
if (!is_object($this->_modelObject))
|
|
{
|
|
// Make sure $config is an array
|
|
if (is_object($config))
|
|
{
|
|
$config = (array) $config;
|
|
}
|
|
elseif (!is_array($config))
|
|
{
|
|
$config = array();
|
|
}
|
|
|
|
if (!empty($this->modelName))
|
|
{
|
|
$parts = F0FInflector::explode($this->modelName);
|
|
$modelName = ucfirst(array_pop($parts));
|
|
$prefix = F0FInflector::implode($parts);
|
|
}
|
|
else
|
|
{
|
|
$prefix = ucfirst($this->bareComponent) . 'Model';
|
|
$modelName = ucfirst(F0FInflector::pluralize($this->view));
|
|
}
|
|
|
|
if (!array_key_exists('input', $config) || !($config['input'] instanceof F0FInput))
|
|
{
|
|
$config['input'] = $this->input;
|
|
}
|
|
|
|
$this->_modelObject = $this->getModel($modelName, $prefix, $config);
|
|
}
|
|
|
|
return $this->_modelObject;
|
|
}
|
|
|
|
/**
|
|
* Method to get a model object, loading it if required.
|
|
*
|
|
* @param string $name The model name. Optional.
|
|
* @param string $prefix The class prefix. Optional.
|
|
* @param array $config Configuration array for model. Optional.
|
|
*
|
|
* @return object The model.
|
|
*/
|
|
public function getModel($name = '', $prefix = '', $config = array())
|
|
{
|
|
// Make sure $config is an array
|
|
if (is_object($config))
|
|
{
|
|
$config = (array) $config;
|
|
}
|
|
elseif (!is_array($config) || empty($config))
|
|
{
|
|
// array_merge is required to create a copy instead of assigning by reference
|
|
$config = array_merge($this->config);
|
|
}
|
|
|
|
if (empty($name))
|
|
{
|
|
$name = $this->getName();
|
|
}
|
|
|
|
if (empty($prefix))
|
|
{
|
|
$prefix = $this->model_prefix;
|
|
}
|
|
|
|
if ($model = $this->createModel($name, $prefix, $config))
|
|
{
|
|
// Task is a reserved state
|
|
$model->setState('task', $this->task);
|
|
|
|
// Let's get the application object and set menu information if it's available
|
|
if (!F0FPlatform::getInstance()->isCli())
|
|
{
|
|
$app = JFactory::getApplication();
|
|
$menu = $app->getMenu();
|
|
|
|
if (is_object($menu))
|
|
{
|
|
if ($item = $menu->getActive())
|
|
{
|
|
$params = $menu->getParams($item->id);
|
|
|
|
// Set default state data
|
|
$model->setState('parameters.menu', $params);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $model;
|
|
}
|
|
|
|
/**
|
|
* Returns current view object
|
|
*
|
|
* @param array $config Configuration variables for the model
|
|
*
|
|
* @return F0FView The global instance of the view object (singleton)
|
|
*/
|
|
final public function getThisView($config = array())
|
|
{
|
|
if (!is_object($this->_viewObject))
|
|
{
|
|
// Make sure $config is an array
|
|
if (is_object($config))
|
|
{
|
|
$config = (array) $config;
|
|
}
|
|
elseif (!is_array($config) || empty($config))
|
|
{
|
|
// array_merge is required to create a copy instead of assigning by reference
|
|
$config = array_merge($this->config);
|
|
}
|
|
|
|
$prefix = null;
|
|
$viewName = null;
|
|
$viewType = null;
|
|
|
|
if (!empty($this->viewName))
|
|
{
|
|
$parts = F0FInflector::explode($this->viewName);
|
|
$viewName = ucfirst(array_pop($parts));
|
|
$prefix = F0FInflector::implode($parts);
|
|
}
|
|
else
|
|
{
|
|
$prefix = ucfirst($this->bareComponent) . 'View';
|
|
$viewName = ucfirst($this->view);
|
|
}
|
|
|
|
$document = F0FPlatform::getInstance()->getDocument();
|
|
|
|
if ($document instanceof JDocument)
|
|
{
|
|
$viewType = $document->getType();
|
|
}
|
|
else
|
|
{
|
|
$viewType = $this->input->getCmd('format', 'html');
|
|
}
|
|
|
|
if (($viewType == 'html') && $this->hasForm)
|
|
{
|
|
$viewType = 'form';
|
|
}
|
|
|
|
if (!array_key_exists('input', $config) || !($config['input'] instanceof F0FInput))
|
|
{
|
|
$config['input'] = $this->input;
|
|
}
|
|
|
|
$config['input']->set('base_path', $this->basePath);
|
|
|
|
$this->_viewObject = $this->getView($viewName, $viewType, $prefix, $config);
|
|
}
|
|
|
|
return $this->_viewObject;
|
|
}
|
|
|
|
/**
|
|
* Method to get the controller name
|
|
*
|
|
* The dispatcher name is set by default parsed using the classname, or it can be set
|
|
* by passing a $config['name'] in the class constructor
|
|
*
|
|
* @throws Exception
|
|
*
|
|
* @return string The name of the dispatcher
|
|
*/
|
|
public function getName()
|
|
{
|
|
if (empty($this->name))
|
|
{
|
|
if (empty($this->bareComponent))
|
|
{
|
|
$r = null;
|
|
|
|
if (!preg_match('/(.*)Controller/i', get_class($this), $r))
|
|
{
|
|
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_CONTROLLER_GET_NAME'), 500);
|
|
}
|
|
|
|
$this->name = strtolower($r[1]);
|
|
}
|
|
else
|
|
{
|
|
$this->name = $this->bareComponent;
|
|
}
|
|
}
|
|
|
|
return $this->name;
|
|
}
|
|
|
|
/**
|
|
* Get the last task that is being performed or was most recently performed.
|
|
*
|
|
* @return string The task that is being performed or was most recently performed.
|
|
*/
|
|
public function getTask()
|
|
{
|
|
return $this->task;
|
|
}
|
|
|
|
/**
|
|
* Gets the available tasks in the controller.
|
|
*
|
|
* @return array Array[i] of task names.
|
|
*/
|
|
public function getTasks()
|
|
{
|
|
return $this->methods;
|
|
}
|
|
|
|
/**
|
|
* Method to get a reference to the current view and load it if necessary.
|
|
*
|
|
* @param string $name The view name. Optional, defaults to the controller name.
|
|
* @param string $type The view type. Optional.
|
|
* @param string $prefix The class prefix. Optional.
|
|
* @param array $config Configuration array for view. Optional.
|
|
*
|
|
* @throws Exception
|
|
*
|
|
* @return F0FView Reference to the view or an error.
|
|
*/
|
|
public function getView($name = '', $type = '', $prefix = '', $config = array())
|
|
{
|
|
// Make sure $config is an array
|
|
if (is_object($config))
|
|
{
|
|
$config = (array) $config;
|
|
}
|
|
elseif (!is_array($config))
|
|
{
|
|
$config = array();
|
|
}
|
|
|
|
if (empty($name))
|
|
{
|
|
$name = $this->getName();
|
|
}
|
|
|
|
if (empty($prefix))
|
|
{
|
|
$prefix = $this->getName() . 'View';
|
|
}
|
|
|
|
$signature = md5($name . $type . $prefix . serialize($config));
|
|
|
|
if (empty($this->viewsCache[$signature]))
|
|
{
|
|
if ($view = $this->createView($name, $prefix, $type, $config))
|
|
{
|
|
$this->viewsCache[$signature] = & $view;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_VIEW_NOT_FOUND', $name, $type, $prefix), 500);
|
|
}
|
|
}
|
|
|
|
return $this->viewsCache[$signature];
|
|
}
|
|
|
|
/**
|
|
* Creates a new model object
|
|
*
|
|
* @param string $name The name of the model class, e.g. Items
|
|
* @param string $prefix The prefix of the model class, e.g. FoobarModel
|
|
* @param array $config The configuration parameters for the model class
|
|
*
|
|
* @return F0FModel The model object
|
|
*/
|
|
protected function createModel($name, $prefix = '', $config = array())
|
|
{
|
|
// Make sure $config is an array
|
|
|
|
if (is_object($config))
|
|
{
|
|
$config = (array) $config;
|
|
}
|
|
elseif (!is_array($config))
|
|
{
|
|
$config = array();
|
|
}
|
|
|
|
$result = null;
|
|
|
|
// Clean the model name
|
|
$modelName = preg_replace('/[^A-Z0-9_]/i', '', $name);
|
|
$classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
|
|
|
|
$result = F0FModel::getAnInstance($modelName, $classPrefix, $config);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Method to load and return a model object.
|
|
*
|
|
* @param string $name The name of the model.
|
|
* @param string $prefix Optional model prefix.
|
|
* @param array $config Configuration array for the model. Optional.
|
|
*
|
|
* @return mixed Model object on success; otherwise null
|
|
*/
|
|
protected function &_createModel($name, $prefix = '', $config = array())
|
|
{
|
|
F0FPlatform::getInstance()->logDeprecated(__CLASS__ . '::' .__METHOD__ . ' is deprecated. Use createModel() instead.');
|
|
|
|
return $this->createModel($name, $prefix, $config);
|
|
}
|
|
|
|
/**
|
|
* Creates a View object instance and returns it
|
|
*
|
|
* @param string $name The name of the view, e.g. Items
|
|
* @param string $prefix The prefix of the view, e.g. FoobarView
|
|
* @param string $type The type of the view, usually one of Html, Raw, Json or Csv
|
|
* @param array $config The configuration variables to use for creating the view
|
|
*
|
|
* @return F0FView
|
|
*/
|
|
protected function createView($name, $prefix = '', $type = '', $config = array())
|
|
{
|
|
// Make sure $config is an array
|
|
|
|
if (is_object($config))
|
|
{
|
|
$config = (array) $config;
|
|
}
|
|
elseif (!is_array($config))
|
|
{
|
|
$config = array();
|
|
}
|
|
|
|
$result = null;
|
|
|
|
// Clean the view name
|
|
$viewName = preg_replace('/[^A-Z0-9_]/i', '', $name);
|
|
$classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
|
|
$viewType = preg_replace('/[^A-Z0-9_]/i', '', $type);
|
|
|
|
if (!isset($config['input']))
|
|
{
|
|
$config['input'] = $this->input;
|
|
}
|
|
|
|
if (($config['input'] instanceof F0FInput))
|
|
{
|
|
$tmpInput = $config['input'];
|
|
}
|
|
else
|
|
{
|
|
$tmpInput = new F0FInput($config['input']);
|
|
}
|
|
|
|
// Guess the component name and view
|
|
|
|
if (!empty($prefix))
|
|
{
|
|
preg_match('/(.*)View$/', $prefix, $m);
|
|
$component = 'com_' . strtolower($m[1]);
|
|
}
|
|
else
|
|
{
|
|
$component = '';
|
|
}
|
|
|
|
if (empty($component) && array_key_exists('input', $config))
|
|
{
|
|
$component = $tmpInput->get('option', $component, 'cmd');
|
|
}
|
|
|
|
if (array_key_exists('option', $config))
|
|
{
|
|
if ($config['option'])
|
|
{
|
|
$component = $config['option'];
|
|
}
|
|
}
|
|
|
|
$config['option'] = $component;
|
|
|
|
$view = strtolower($viewName);
|
|
|
|
if (empty($view) && array_key_exists('input', $config))
|
|
{
|
|
$view = $tmpInput->get('view', $view, 'cmd');
|
|
}
|
|
|
|
if (array_key_exists('view', $config))
|
|
{
|
|
if ($config['view'])
|
|
{
|
|
$view = $config['view'];
|
|
}
|
|
}
|
|
|
|
$config['view'] = $view;
|
|
|
|
if (array_key_exists('input', $config))
|
|
{
|
|
$tmpInput->set('option', $config['option']);
|
|
$tmpInput->set('view', $config['view']);
|
|
$config['input'] = $tmpInput;
|
|
}
|
|
|
|
// Get the component directories
|
|
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($config['option']);
|
|
|
|
// Get the base paths where the view class files are expected to live
|
|
$basePaths = array(
|
|
$componentPaths['main'],
|
|
$componentPaths['alt']
|
|
);
|
|
$basePaths = array_merge($this->paths['view']);
|
|
|
|
// Get the alternate (singular/plural) view name
|
|
$altViewName = F0FInflector::isPlural($viewName) ? F0FInflector::singularize($viewName) : F0FInflector::pluralize($viewName);
|
|
|
|
$suffixes = array(
|
|
$viewName,
|
|
$altViewName,
|
|
'default'
|
|
);
|
|
|
|
$filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem');
|
|
|
|
foreach ($suffixes as $suffix)
|
|
{
|
|
// Build the view class name
|
|
$viewClass = $classPrefix . ucfirst($suffix);
|
|
|
|
if (class_exists($viewClass))
|
|
{
|
|
// The class is already loaded
|
|
break;
|
|
}
|
|
|
|
// The class is not loaded. Let's load it!
|
|
$viewPath = $this->createFileName('view', array('name' => $suffix, 'type' => $viewType));
|
|
$path = $filesystem->pathFind($basePaths, $viewPath);
|
|
|
|
if ($path)
|
|
{
|
|
require_once $path;
|
|
}
|
|
|
|
if (class_exists($viewClass))
|
|
{
|
|
// The class was loaded successfully
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!class_exists($viewClass))
|
|
{
|
|
$viewClass = 'F0FView' . ucfirst($type);
|
|
}
|
|
|
|
$templateOverridePath = F0FPlatform::getInstance()->getTemplateOverridePath($config['option']);
|
|
|
|
// Setup View configuration options
|
|
|
|
if (!array_key_exists('template_path', $config))
|
|
{
|
|
$config['template_path'][] = $componentPaths['main'] . '/views/' . F0FInflector::pluralize($config['view']) . '/tmpl';
|
|
|
|
if ($templateOverridePath)
|
|
{
|
|
$config['template_path'][] = $templateOverridePath . '/' . F0FInflector::pluralize($config['view']);
|
|
}
|
|
|
|
$config['template_path'][] = $componentPaths['main'] . '/views/' . F0FInflector::singularize($config['view']) . '/tmpl';
|
|
|
|
if ($templateOverridePath)
|
|
{
|
|
$config['template_path'][] = $templateOverridePath . '/' . F0FInflector::singularize($config['view']);
|
|
}
|
|
|
|
$config['template_path'][] = $componentPaths['main'] . '/views/' . $config['view'] . '/tmpl';
|
|
|
|
if ($templateOverridePath)
|
|
{
|
|
$config['template_path'][] = $templateOverridePath . '/' . $config['view'];
|
|
}
|
|
}
|
|
|
|
$extraTemplatePath = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.template_path', null);
|
|
|
|
if ($extraTemplatePath)
|
|
{
|
|
array_unshift($config['template_path'], $componentPaths['main'] . '/' . $extraTemplatePath);
|
|
}
|
|
|
|
if (!array_key_exists('helper_path', $config))
|
|
{
|
|
$config['helper_path'] = array(
|
|
$componentPaths['main'] . '/helpers',
|
|
$componentPaths['admin'] . '/helpers'
|
|
);
|
|
}
|
|
|
|
$extraHelperPath = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.helper_path', null);
|
|
|
|
if ($extraHelperPath)
|
|
{
|
|
$config['helper_path'][] = $componentPaths['main'] . '/' . $extraHelperPath;
|
|
}
|
|
|
|
// Set up the page title
|
|
$setFrontendPageTitle = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.setFrontendPageTitle', null);
|
|
|
|
if ($setFrontendPageTitle)
|
|
{
|
|
$setFrontendPageTitle = strtolower($setFrontendPageTitle);
|
|
$config['setFrontendPageTitle'][] = in_array($setFrontendPageTitle, array('1', 'yes', 'true', 'on'));
|
|
}
|
|
|
|
$defaultPageTitle = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.defaultPageTitle', null);
|
|
|
|
if ($defaultPageTitle)
|
|
{
|
|
$config['defaultPageTitle'][] = in_array($defaultPageTitle, array('1', 'yes', 'true', 'on'));
|
|
}
|
|
|
|
// Set the use_hypermedia flag in $config if it's not already set
|
|
if (!isset($config['use_hypermedia']))
|
|
{
|
|
$config['use_hypermedia'] = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.use_hypermedia', false);
|
|
}
|
|
|
|
// Set also the linkbar_style
|
|
if (!isset($config['linkbar_style']))
|
|
{
|
|
$style = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.linkbar_style', false);
|
|
|
|
if ($style) {
|
|
$config['linkbar_style'] = $style;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Some administrative templates force format=utf (yeah, I know, what the heck, right?) when a format
|
|
* URL parameter does not exist in the URL. Of course there is no such thing as F0FViewUtf (why the heck would
|
|
* it be, there is no such thing as a format=utf in Joomla! for crying out loud) which causes a Fatal Error. So
|
|
* we have to detect that and force $type='html'...
|
|
*/
|
|
if (!class_exists($viewClass) && ($type != 'html'))
|
|
{
|
|
$type = 'html';
|
|
$result = $this->createView($name, $prefix, $type, $config);
|
|
}
|
|
else
|
|
{
|
|
$result = new $viewClass($config);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Deprecated function to create a View object instance
|
|
*
|
|
* @param string $name The name of the view, e.g. 'Items'
|
|
* @param string $prefix The prefix of the view, e.g. 'FoobarView'
|
|
* @param string $type The view type, e.g. 'html'
|
|
* @param array $config The configuration array for the view
|
|
*
|
|
* @return F0FView
|
|
*
|
|
* @see F0FController::createView
|
|
*
|
|
* @deprecated since version 2.0
|
|
*/
|
|
protected function &_createView($name, $prefix = '', $type = '', $config = array())
|
|
{
|
|
F0FPlatform::getInstance()->logDeprecated(__CLASS__ . '::' . __METHOD__ . ' is deprecated. Use createView() instead.');
|
|
|
|
return $this->createView($name, $prefix, $type, $config);
|
|
}
|
|
|
|
/**
|
|
* Set the name of the view to be used by this Controller
|
|
*
|
|
* @param string $viewName The name of the view
|
|
*
|
|
* @return void
|
|
*/
|
|
public function setThisViewName($viewName)
|
|
{
|
|
$this->viewName = $viewName;
|
|
}
|
|
|
|
/**
|
|
* Set the name of the model to be used by this Controller
|
|
*
|
|
* @param string $modelName The name of the model
|
|
*
|
|
* @return void
|
|
*/
|
|
public function setThisModelName($modelName)
|
|
{
|
|
$this->modelName = $modelName;
|
|
}
|
|
|
|
/**
|
|
* Checks if the current user has enough privileges for the requested ACL
|
|
* area.
|
|
*
|
|
* @param string $area The ACL area, e.g. core.manage.
|
|
*
|
|
* @return boolean True if the user has the ACL privilege specified
|
|
*/
|
|
protected function checkACL($area)
|
|
{
|
|
if (in_array(strtolower($area), array('false','0','no','403')))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (in_array(strtolower($area), array('true','1','yes')))
|
|
{
|
|
return true;
|
|
}
|
|
elseif (empty($area))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// Check if we're dealing with ids
|
|
$ids = null;
|
|
|
|
// First, check if there is an asset for this record
|
|
$table = $this->getThisModel()->getTable();
|
|
|
|
if ($table && $table->isAssetsTracked())
|
|
{
|
|
$ids = $this->getThisModel()->getId() ? $this->getThisModel()->getId() : null;
|
|
}
|
|
|
|
// Generic or Asset tracking
|
|
|
|
if (empty($ids))
|
|
{
|
|
return F0FPlatform::getInstance()->authorise($area, $this->component);
|
|
}
|
|
else
|
|
{
|
|
if (!is_array($ids))
|
|
{
|
|
$ids = array($ids);
|
|
}
|
|
|
|
$resource = F0FInflector::singularize($this->view);
|
|
$isEditState = ($area == 'core.edit.state');
|
|
|
|
foreach ($ids as $id)
|
|
{
|
|
$asset = $this->component . '.' . $resource . '.' . $id;
|
|
|
|
// Dedicated permission found, check it!
|
|
|
|
if (F0FPlatform::getInstance()->authorise($area, $asset) )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Fallback on edit.own, if not edit.state. First test if the permission is available.
|
|
|
|
if ((!$isEditState) && (F0FPlatform::getInstance()->authorise('core.edit.own', $asset)))
|
|
{
|
|
$table = $this->getThisModel()->getTable();
|
|
$table->load($id);
|
|
|
|
$created_by = $table->getColumnAlias('created_by');
|
|
|
|
if ($table && isset($table->$created_by))
|
|
{
|
|
// Now test the owner is the user.
|
|
$owner_id = (int) $table->$created_by;
|
|
|
|
// If the owner matches 'me' then do the test.
|
|
if ($owner_id == F0FPlatform::getInstance()->getUser()->id)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* A catch-all method for all tasks without a corresponding onBefore
|
|
* method. Applies the ACL preferences defined in fof.xml.
|
|
*
|
|
* @param string $task The task being executed
|
|
*
|
|
* @return boolean True to allow execution of the task
|
|
*/
|
|
protected function onBeforeGenericTask($task)
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.' . $task, ''
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* Execute something before applySave is called. Return false to prevent
|
|
* applySave from executing.
|
|
*
|
|
* @param array &$data The data upon which applySave will act
|
|
*
|
|
* @return boolean True to allow applySave to run
|
|
*/
|
|
protected function onBeforeApplySave(&$data)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Execute something after applySave has run.
|
|
*
|
|
* @return boolean True to allow normal return, false to cause a 403 error
|
|
*/
|
|
protected function onAfterApplySave()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* ACL check before changing the access level; override to customise
|
|
*
|
|
* @return boolean True to allow accesspublic() to run
|
|
*/
|
|
protected function onBeforeAccesspublic()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.accesspublic', 'core.edit.state');
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before changing the access level; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeAccessregistered()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.accessregistered', 'core.edit.state'
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before changing the access level; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeAccessspecial()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.accessspecial', 'core.edit.state'
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before adding a new record; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeAdd()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.add', 'core.create'
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before saving a new/modified record; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeApply()
|
|
{
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$id = $model->getId();
|
|
|
|
if(!$id)
|
|
{
|
|
$defaultPrivilege = 'core.create';
|
|
}
|
|
else
|
|
{
|
|
$defaultPrivilege = 'core.edit';
|
|
}
|
|
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.apply', $defaultPrivilege
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before allowing someone to browse
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeBrowse()
|
|
{
|
|
$defaultPrivilege = '';
|
|
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.browse', $defaultPrivilege
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before cancelling an edit
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeCancel()
|
|
{
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$id = $model->getId();
|
|
|
|
if(!$id)
|
|
{
|
|
$defaultPrivilege = 'core.create';
|
|
}
|
|
else
|
|
{
|
|
$defaultPrivilege = 'core.edit';
|
|
}
|
|
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.cancel', $defaultPrivilege
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before editing a record; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeEdit()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.edit', 'core.edit'
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before changing the ordering of a record; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeOrderdown()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.orderdown', 'core.edit.state'
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before changing the ordering of a record; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeOrderup()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.orderup', 'core.edit.state'
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before changing the publish status of a record; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforePublish()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.publish', 'core.edit.state'
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before removing a record; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeRemove()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.remove', 'core.delete'
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before saving a new/modified record; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeSave()
|
|
{
|
|
$model = $this->getThisModel();
|
|
|
|
if (!$model->getId())
|
|
{
|
|
$model->setIDsFromRequest();
|
|
}
|
|
|
|
$id = $model->getId();
|
|
|
|
if(!$id)
|
|
{
|
|
$defaultPrivilege = 'core.create';
|
|
}
|
|
else
|
|
{
|
|
$defaultPrivilege = 'core.edit';
|
|
}
|
|
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.save', $defaultPrivilege
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before saving a new/modified record; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeSavenew()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.savenew', 'core.create'
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before changing the ordering of a record; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeSaveorder()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.saveorder', 'core.edit.state'
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* ACL check before changing the publish status of a record; override to customise
|
|
*
|
|
* @return boolean True to allow the method to run
|
|
*/
|
|
protected function onBeforeUnpublish()
|
|
{
|
|
$privilege = $this->configProvider->get(
|
|
$this->component . '.views.' .
|
|
F0FInflector::singularize($this->view) . '.acl.unpublish', 'core.edit.state'
|
|
);
|
|
|
|
return $this->checkACL($privilege);
|
|
}
|
|
|
|
/**
|
|
* Gets a URL suffix with the Itemid parameter. If it's not the front-end of the site, or if
|
|
* there is no Itemid set it returns an empty string.
|
|
*
|
|
* @return string The &Itemid=123 URL suffix, or an empty string if Itemid is not applicable
|
|
*/
|
|
public function getItemidURLSuffix()
|
|
{
|
|
if (F0FPlatform::getInstance()->isFrontend() && ($this->input->getCmd('Itemid', 0) != 0))
|
|
{
|
|
return '&Itemid=' . $this->input->getInt('Itemid', 0);
|
|
}
|
|
else
|
|
{
|
|
return '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Applies CSRF protection by means of a standard Joomla! token (nonce) check.
|
|
* Raises a 403 Access Forbidden error through the platform if the check fails.
|
|
*
|
|
* TODO Move this check inside the platform
|
|
*
|
|
* @return boolean True if the CSRF check is successful
|
|
*
|
|
* @throws Exception
|
|
*/
|
|
protected function _csrfProtection()
|
|
{
|
|
static $isCli = null, $isAdmin = null;
|
|
|
|
if (is_null($isCli))
|
|
{
|
|
$isCli = F0FPlatform::getInstance()->isCli();
|
|
$isAdmin = F0FPlatform::getInstance()->isBackend();
|
|
}
|
|
|
|
switch ($this->csrfProtection)
|
|
{
|
|
// Never
|
|
case 0:
|
|
return true;
|
|
break;
|
|
|
|
// Always
|
|
case 1:
|
|
break;
|
|
|
|
// Only back-end and HTML format
|
|
case 2:
|
|
if ($isCli)
|
|
{
|
|
return true;
|
|
}
|
|
elseif (!$isAdmin && ($this->input->get('format', 'html', 'cmd') != 'html'))
|
|
{
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
// Only back-end
|
|
case 3:
|
|
if (!$isAdmin)
|
|
{
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
|
|
$hasToken = false;
|
|
$session = JFactory::getSession();
|
|
|
|
// Joomla! 1.5/1.6/1.7/2.5 (classic Joomla! API) method
|
|
if (method_exists('JUtility', 'getToken'))
|
|
{
|
|
$token = JUtility::getToken();
|
|
$hasToken = $this->input->get($token, false, 'none') == 1;
|
|
|
|
if (!$hasToken)
|
|
{
|
|
$hasToken = $this->input->get('_token', null, 'none') == $token;
|
|
}
|
|
}
|
|
|
|
// Joomla! 2.5+ (Platform 12.1+) method
|
|
if (!$hasToken)
|
|
{
|
|
if (method_exists($session, 'getToken'))
|
|
{
|
|
$token = $session->getToken();
|
|
$hasToken = $this->input->get($token, false, 'none') == 1;
|
|
|
|
if (!$hasToken)
|
|
{
|
|
$hasToken = $this->input->get('_token', null, 'none') == $token;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Joomla! 2.5+ formToken method
|
|
if (!$hasToken)
|
|
{
|
|
if (method_exists($session, 'getFormToken'))
|
|
{
|
|
$token = $session->getFormToken();
|
|
$hasToken = $this->input->get($token, false, 'none') == 1;
|
|
|
|
if (!$hasToken)
|
|
{
|
|
$hasToken = $this->input->get('_token', null, 'none') == $token;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$hasToken)
|
|
{
|
|
F0FPlatform::getInstance()->raiseError(403, JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'));
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|