| Current Path : /home/w/u/e/wuectly/www/03cbe/ |
| Current File : /home/w/u/e/wuectly/www/03cbe/model.tar |
model.php 0000604 00000220316 15245561006 0006361 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 Model class. The Model is the workhorse. It performs all
* of the business logic based on its state and then returns the raw (processed)
* data to the caller, or modifies its own state. It's important to note that
* the model doesn't get data directly from the request (this is the
* Controller's business) and that it doesn't output anything (that the View's
* business).
*
* @package FrameworkOnFramework
* @since 1.0
*/
class F0FModel extends F0FUtilsObject
{
/**
* Indicates if the internal state has been set
*
* @var boolean
* @since 12.2
*/
protected $__state_set = null;
/**
* Database Connector
*
* @var object
* @since 12.2
*/
protected $_db;
/**
* The event to trigger after deleting the data.
* @var string
*/
protected $event_after_delete = 'onContentAfterDelete';
/**
* The event to trigger after saving the data.
* @var string
*/
protected $event_after_save = 'onContentAfterSave';
/**
* The event to trigger before deleting the data.
* @var string
*/
protected $event_before_delete = 'onContentBeforeDelete';
/**
* The event to trigger before saving the data.
* @var string
*/
protected $event_before_save = 'onContentBeforeSave';
/**
* The event to trigger after changing the published state of the data.
* @var string
*/
protected $event_change_state = 'onContentChangeState';
/**
* The event to trigger when cleaning cache.
*
* @var string
* @since 12.2
*/
protected $event_clean_cache = null;
/**
* Stores a list of IDs passed to the model's state
* @var array
*/
protected $id_list = array();
/**
* The first row ID passed to the model's state
* @var int
*/
protected $id = null;
/**
* Input variables, passed on from the controller, in an associative array
* @var F0FInput
*/
protected $input = array();
/**
* The list of records made available through getList
* @var array
*/
protected $list = null;
/**
* The model (base) name
*
* @var string
* @since 12.2
*/
protected $name;
/**
* The URL option for the component.
*
* @var string
* @since 12.2
*/
protected $option = null;
/**
* The table object, populated when saving data
* @var F0FTable
*/
protected $otable = null;
/**
* Pagination object
* @var JPagination
*/
protected $pagination = null;
/**
* The table object, populated when retrieving data
* @var F0FTable
*/
protected $record = null;
/**
* A state object
*
* @var string
* @since 12.2
*/
protected $state;
/**
* The name of the table to use
* @var string
*/
protected $table = null;
/**
* Total rows based on the filters set in the model's state
* @var int
*/
protected $total = null;
/**
* Should I save the model's state in the session?
* @var bool
*/
protected $_savestate = null;
/**
* Array of form objects.
*
* @var array
* @since 2.0
*/
protected $_forms = array();
/**
* The data to load into a form
*
* @var array
* @since 2.0
*/
protected $_formData = array();
/**
* An instance of F0FConfigProvider to provision configuration overrides
*
* @var F0FConfigProvider
*/
protected $configProvider = null;
/**
* F0FModelDispatcherBehavior for dealing with extra behaviors
*
* @var F0FModelDispatcherBehavior
*/
protected $modelDispatcher = null;
/**
* Default behaviors to apply to the model
*
* @var array
*/
protected $default_behaviors = array('filters');
/**
* Behavior parameters
*
* @var array
*/
protected $_behaviorParams = array();
/**
* Returns a new model object. Unless overriden by the $config array, it will
* try to automatically populate its state from the request variables.
*
* @param string $type Model type, e.g. 'Items'
* @param string $prefix Model prefix, e.g. 'FoobarModel'
* @param array $config Model configuration variables
*
* @return F0FModel
*/
public static function &getAnInstance($type, $prefix = '', $config = array())
{
// Make sure $config is an array
if (is_object($config))
{
$config = (array) $config;
}
elseif (!is_array($config))
{
$config = array();
}
$type = preg_replace('/[^A-Z0-9_\.-]/i', '', $type);
$modelClass = $prefix . ucfirst($type);
$result = false;
// Guess the component name and include path
if (!empty($prefix))
{
preg_match('/(.*)Model$/', $prefix, $m);
$component = 'com_' . strtolower($m[1]);
}
else
{
$component = '';
}
if (array_key_exists('input', $config))
{
if (!($config['input'] instanceof F0FInput))
{
if (!is_array($config['input']))
{
$config['input'] = (array) $config['input'];
}
$config['input'] = array_merge($_REQUEST, $config['input']);
$config['input'] = new F0FInput($config['input']);
}
}
else
{
$config['input'] = new F0FInput;
}
if (empty($component))
{
$component = $config['input']->get('option', 'com_foobar');
}
$config['option'] = $component;
$needsAView = true;
if (array_key_exists('view', $config))
{
if (!empty($config['view']))
{
$needsAView = false;
}
}
if ($needsAView)
{
$config['view'] = strtolower($type);
}
$config['input']->set('option', $config['option']);
// Get the component directories
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($component);
$filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem');
// Try to load the requested model class
if (!class_exists($modelClass))
{
$include_paths = self::addIncludePath();
$extra_paths = array(
$componentPaths['main'] . '/models',
$componentPaths['alt'] . '/models'
);
$include_paths = array_merge($extra_paths, $include_paths);
// Try to load the model file
$path = $filesystem->pathFind(
$include_paths, self::_createFileName('model', array('name' => $type))
);
if ($path)
{
require_once $path;
}
}
// Fallback to the Default model class, e.g. FoobarModelDefault
if (!class_exists($modelClass))
{
$modelClass = $prefix . 'Default';
if (!class_exists($modelClass))
{
$include_paths = self::addIncludePath();
$extra_paths = array(
$componentPaths['main'] . '/models',
$componentPaths['alt'] . '/models'
);
$include_paths = array_merge($extra_paths, $include_paths);
// Try to load the model file
$path = $filesystem->pathFind(
$include_paths, self::_createFileName('model', array('name' => 'default'))
);
if ($path)
{
require_once $path;
}
}
}
// Fallback to the generic F0FModel model class
if (!class_exists($modelClass))
{
$modelClass = 'F0FModel';
}
$result = new $modelClass($config);
return $result;
}
/**
* Adds a behavior to the model
*
* @param string $name The name of the behavior
* @param array $config Optional Behavior configuration
*
* @return boolean True if the behavior is found and added
*/
public function addBehavior($name, $config = array())
{
// Sanity check: this objects needs a non-null behavior handler
if (!is_object($this->modelDispatcher))
{
return false;
}
// Sanity check: this objects needs a behavior handler of the correct class type
if (!($this->modelDispatcher instanceof F0FModelDispatcherBehavior))
{
return false;
}
// First look for ComponentnameModelViewnameBehaviorName (e.g. FoobarModelItemsBehaviorFilter)
$option_name = str_replace('com_', '', $this->option);
$behaviorClass = ucfirst($option_name) . 'Model' . F0FInflector::pluralize($this->name) . 'Behavior' . ucfirst(strtolower($name));
if (class_exists($behaviorClass))
{
$behavior = new $behaviorClass($this->modelDispatcher, $config);
return true;
}
// Then look for ComponentnameModelBehaviorName (e.g. FoobarModelBehaviorFilter)
$option_name = str_replace('com_', '', $this->option);
$behaviorClass = ucfirst($option_name) . 'ModelBehavior' . ucfirst(strtolower($name));
if (class_exists($behaviorClass))
{
$behavior = new $behaviorClass($this->modelDispatcher, $config);
return true;
}
// Then look for F0FModelBehaviorName (e.g. F0FModelBehaviorFilter)
$behaviorClassAlt = 'F0FModelBehavior' . ucfirst(strtolower($name));
if (class_exists($behaviorClassAlt))
{
$behavior = new $behaviorClassAlt($this->modelDispatcher, $config);
return true;
}
// Nothing found? Return false.
return false;
}
/**
* Returns a new instance of a model, with the state reset to defaults
*
* @param string $type Model type, e.g. 'Items'
* @param string $prefix Model prefix, e.g. 'FoobarModel'
* @param array $config Model configuration variables
*
* @return F0FModel
*/
public static function &getTmpInstance($type, $prefix = '', $config = array())
{
// Make sure $config is an array
if (is_object($config))
{
$config = (array) $config;
}
elseif (!is_array($config))
{
$config = array();
}
if (!array_key_exists('savestate', $config))
{
$config['savestate'] = false;
}
$ret = self::getAnInstance($type, $prefix, $config)
->getClone()
->clearState()
->clearInput()
->reset()
->savestate(0)
->limitstart(0)
->limit(0);
return $ret;
}
/**
* Add a directory where F0FModel should search for models. You may
* either pass a string or an array of directories.
*
* @param mixed $path A path or array[sting] of paths to search.
* @param string $prefix A prefix for models.
*
* @return array An array with directory elements. If prefix is equal to '', all directories are returned.
*
* @since 12.2
*/
public static function addIncludePath($path = '', $prefix = '')
{
static $paths;
if (!isset($paths))
{
$paths = array();
}
if (!isset($paths[$prefix]))
{
$paths[$prefix] = array();
}
if (!isset($paths['']))
{
$paths[''] = array();
}
if (!empty($path))
{
$filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem');
if (!in_array($path, $paths[$prefix]))
{
array_unshift($paths[$prefix], $filesystem->pathClean($path));
}
if (!in_array($path, $paths['']))
{
array_unshift($paths[''], $filesystem->pathClean($path));
}
}
return $paths[$prefix];
}
/**
* Adds to the stack of model table paths in LIFO order.
*
* @param mixed $path The directory as a string or directories as an array to add.
*
* @return void
*
* @since 12.2
*/
public static function addTablePath($path)
{
F0FTable::addIncludePath($path);
}
/**
* 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
*
* @since 12.2
*/
protected static function _createFileName($type, $parts = array())
{
$filename = '';
switch ($type)
{
case 'model':
$filename = strtolower($parts['name']) . '.php';
break;
}
return $filename;
}
/**
* Public class constructor
*
* @param array $config The configuration 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;
}
// Load the configuration provider
$this->configProvider = new F0FConfigProvider;
// Load the behavior dispatcher
$this->modelDispatcher = new F0FModelDispatcherBehavior;
// Set the $name/$_name variable
$component = $this->input->getCmd('option', 'com_foobar');
if (array_key_exists('option', $config))
{
$component = $config['option'];
}
// Set the $name variable
$this->input->set('option', $component);
$component = $this->input->getCmd('option', 'com_foobar');
if (array_key_exists('option', $config))
{
$component = $config['option'];
}
$this->input->set('option', $component);
$bareComponent = str_replace('com_', '', strtolower($component));
// Get the view name
$className = get_class($this);
if ($className == 'F0FModel')
{
if (array_key_exists('view', $config))
{
$view = $config['view'];
}
if (empty($view))
{
$view = $this->input->getCmd('view', 'cpanel');
}
}
else
{
if (array_key_exists('view', $config))
{
$view = $config['view'];
}
if (empty($view))
{
$eliminatePart = ucfirst($bareComponent) . 'Model';
$view = strtolower(str_replace($eliminatePart, '', $className));
}
}
if (array_key_exists('name', $config))
{
$name = $config['name'];
}
else
{
$name = $view;
}
$this->name = $name;
$this->option = $component;
// Set the model state
if (array_key_exists('state', $config))
{
$this->state = $config['state'];
}
else
{
$this->state = new F0FUtilsObject;
}
// Set the model dbo
if (array_key_exists('dbo', $config))
{
$this->_db = $config['dbo'];
}
else
{
$this->_db = F0FPlatform::getInstance()->getDbo();
}
// Set the default view search path
if (array_key_exists('table_path', $config))
{
$this->addTablePath($config['table_path']);
}
else
{
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($this->option);
$path = $componentPaths['admin'] . '/tables';
$altPath = $this->configProvider->get($this->option . '.views.' . F0FInflector::singularize($this->name) . '.config.table_path', null);
if ($altPath)
{
$path = $componentPaths['main'] . '/' . $altPath;
}
$this->addTablePath($path);
}
// Assign the correct table
if (array_key_exists('table', $config))
{
$this->table = $config['table'];
}
else
{
$table = $this->configProvider->get(
$this->option . '.views.' . F0FInflector::singularize($this->name) .
'.config.table', F0FInflector::singularize($view)
);
$this->table = $table;
}
// Set the internal state marker - used to ignore setting state from the request
if (!empty($config['ignore_request']) || !is_null(
$this->configProvider->get(
$this->option . '.views.' . F0FInflector::singularize($this->name) .
'.config.ignore_request', null
)
))
{
$this->__state_set = true;
}
// Get and store the pagination request variables
$defaultSaveState = array_key_exists('savestate', $config) ? $config['savestate'] : -999;
$this->populateSavestate($defaultSaveState);
if (F0FPlatform::getInstance()->isCli())
{
$limit = 20;
$limitstart = 0;
}
else
{
$app = JFactory::getApplication();
if (method_exists($app, 'getCfg'))
{
$default_limit = $app->getCfg('list_limit');
}
else
{
$default_limit = 20;
}
$limit = $this->getUserStateFromRequest($component . '.' . $view . '.limit', 'limit', $default_limit, 'int', $this->_savestate);
$limitstart = $this->getUserStateFromRequest($component . '.' . $view . '.limitstart', 'limitstart', 0, 'int', $this->_savestate);
}
$this->setState('limit', $limit);
$this->setState('limitstart', $limitstart);
// Get the ID or list of IDs from the request or the configuration
if (array_key_exists('cid', $config))
{
$cid = $config['cid'];
}
elseif ($cid = $this->configProvider->get(
$this->option . '.views.' . F0FInflector::singularize($this->name) . '.config.cid', null
)
)
{
$cid = explode(',', $cid);
}
else
{
$cid = $this->input->get('cid', array(), 'array');
}
if (array_key_exists('id', $config))
{
$id = $config['id'];
}
elseif ($id = $this->configProvider->get(
$this->option . '.views.' . F0FInflector::singularize($this->name) . '.config.id', null
)
)
{
$id = explode(',', $id);
$id = array_shift($id);
}
else
{
$id = $this->input->getInt('id', 0);
}
if (is_array($cid) && !empty($cid))
{
$this->setIds($cid);
}
else
{
$this->setId($id);
}
// Populate the event names from the $config array
$configKey = $this->option . '.views.' . F0FInflector::singularize($view) . '.config.';
// Assign after delete event handler
if (isset($config['event_after_delete']))
{
$this->event_after_delete = $config['event_after_delete'];
}
else
{
$this->event_after_delete = $this->configProvider->get(
$configKey . 'event_after_delete',
$this->event_after_delete
);
}
// Assign after save event handler
if (isset($config['event_after_save']))
{
$this->event_after_save = $config['event_after_save'];
}
else
{
$this->event_after_save = $this->configProvider->get(
$configKey . 'event_after_save',
$this->event_after_save
);
}
// Assign before delete event handler
if (isset($config['event_before_delete']))
{
$this->event_before_delete = $config['event_before_delete'];
}
else
{
$this->event_before_delete = $this->configProvider->get(
$configKey . 'event_before_delete',
$this->event_before_delete
);
}
// Assign before save event handler
if (isset($config['event_before_save']))
{
$this->event_before_save = $config['event_before_save'];
}
else
{
$this->event_before_save = $this->configProvider->get(
$configKey . 'event_before_save',
$this->event_before_save
);
}
// Assign state change event handler
if (isset($config['event_change_state']))
{
$this->event_change_state = $config['event_change_state'];
}
else
{
$this->event_change_state = $this->configProvider->get(
$configKey . 'event_change_state',
$this->event_change_state
);
}
// Assign cache clean event handler
if (isset($config['event_clean_cache']))
{
$this->event_clean_cache = $config['event_clean_cache'];
}
else
{
$this->event_clean_cache = $this->configProvider->get(
$configKey . 'event_clean_cache',
$this->event_clean_cache
);
}
// Apply model behaviors
if (isset($config['behaviors']))
{
$behaviors = (array) $config['behaviors'];
}
elseif ($behaviors = $this->configProvider->get($configKey . 'behaviors', null))
{
$behaviors = explode(',', $behaviors);
}
else
{
$behaviors = $this->default_behaviors;
}
if (is_array($behaviors) && count($behaviors))
{
foreach ($behaviors as $behavior)
{
$this->addBehavior($behavior);
}
}
}
/**
* Sets the list of IDs from the request data
*
* @return F0FModel
*/
public function setIDsFromRequest()
{
// Get the ID or list of IDs from the request or the configuration
$cid = $this->input->get('cid', array(), 'array');
$id = $this->input->getInt('id', 0);
$kid = $this->input->getInt($this->getTable($this->table)->getKeyName(), 0);
if (is_array($cid) && !empty($cid))
{
$this->setIds($cid);
}
else
{
if (empty($id))
{
$this->setId($kid);
}
else
{
$this->setId($id);
}
}
return $this;
}
/**
* Sets the ID and resets internal data
*
* @param integer $id The ID to use
*
* @throws InvalidArgumentException
*
* @return F0FModel
*/
public function setId($id = 0)
{
// If this is an array extract the first item
if (is_array($id))
{
F0FPlatform::getInstance()->logDeprecated('Passing arrays to F0FModel::setId is deprecated. Use setIds() instead.');
$id = array_shift($id);
}
// No string or no integer? What are you trying to do???
if (!is_string($id) && !is_numeric($id))
{
throw new InvalidArgumentException(sprintf('%s::setId()', get_class($this)));
}
$this->reset();
$this->id = (int) $id;
$this->id_list = array($this->id);
return $this;
}
/**
* Returns the currently set ID
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Sets a list of IDs for batch operations from an array and resets the model
*
* @param array $idlist An array of item IDs to be set to the model's state
*
* @return F0FModel
*/
public function setIds($idlist)
{
$this->reset();
$this->id_list = array();
$this->id = 0;
if (is_array($idlist) && !empty($idlist))
{
foreach ($idlist as $value)
{
// Protect vs fatal error (objects) and wrong behavior (nested array)
if(!is_object($value) && !is_array($value))
{
$this->id_list[] = (int) $value;
}
}
if(count($this->id_list))
{
$this->id = $this->id_list[0];
}
}
return $this;
}
/**
* Returns the list of IDs for batch operations
*
* @return array An array of integers
*/
public function getIds()
{
return $this->id_list;
}
/**
* Resets the model, like it was freshly loaded
*
* @return F0FModel
*/
public function reset()
{
$this->id = 0;
$this->id_list = null;
$this->record = null;
$this->list = null;
$this->pagination = null;
$this->total = null;
$this->otable = null;
return $this;
}
/**
* Clears the model state, but doesn't touch the internal lists of records,
* record tables or record id variables. To clear these values, please use
* reset().
*
* @return F0FModel
*/
public function clearState()
{
$this->state = new F0FUtilsObject;
return $this;
}
/**
* Clears the input array.
*
* @return F0FModel
*/
public function clearInput()
{
$defSource = array();
$this->input = new F0FInput($defSource);
return $this;
}
/**
* Set the internal input field
*
* @param $input
*
* @return F0FModel
*/
public function setInput($input)
{
if (!($input instanceof F0FInput))
{
if (!is_array($input))
{
$input = (array) $input;
}
$input = array_merge($_REQUEST, $input);
$input = new F0FInput($input);
}
$this->input = $input;
return $this;
}
/**
* Resets the saved state for this view
*
* @return F0FModel
*/
public function resetSavedState()
{
JFactory::getApplication()->setUserState(substr($this->getHash(), 0, -1), null);
return $this;
}
/**
* Method to load a row for editing from the version history table.
*
* @param integer $version_id Key to the version history table.
* @param F0FTable &$table Content table object being loaded.
* @param string $alias The type_alias in #__content_types
*
* @return boolean False on failure or error, true otherwise.
*
* @since 2.3
*/
public function loadhistory($version_id, F0FTable &$table, $alias)
{
// Only attempt to check the row in if it exists.
if ($version_id)
{
$user = JFactory::getUser();
// Get an instance of the row to checkout.
$historyTable = JTable::getInstance('Contenthistory');
if (!$historyTable->load($version_id))
{
$this->setError($historyTable->getError());
return false;
}
$rowArray = JArrayHelper::fromObject(json_decode($historyTable->version_data));
$typeId = JTable::getInstance('Contenttype')->getTypeId($alias);
if ($historyTable->ucm_type_id != $typeId)
{
$this->setError(JText::_('JLIB_APPLICATION_ERROR_HISTORY_ID_MISMATCH'));
$key = $table->getKeyName();
if (isset($rowArray[$key]))
{
$table->checkIn($rowArray[$key]);
}
return false;
}
}
$this->setState('save_date', $historyTable->save_date);
$this->setState('version_note', $historyTable->version_note);
return $table->bind($rowArray);
}
/**
* Returns a single item. It uses the id set with setId, or the first ID in
* the list of IDs for batch operations
*
* @param integer $id Force a primary key ID to the model. Use null to use the id from the state.
*
* @return F0FTable A copy of the item's F0FTable array
*/
public function &getItem($id = null)
{
if (!is_null($id))
{
$this->record = null;
$this->setId($id);
}
if (empty($this->record))
{
$table = $this->getTable($this->table);
$table->load($this->id);
$this->record = $table;
// Do we have saved data?
$session = JFactory::getSession();
if ($this->_savestate)
{
$serialized = $session->get($this->getHash() . 'savedata', null);
if (!empty($serialized))
{
$data = @unserialize($serialized);
if ($data !== false)
{
$k = $table->getKeyName();
if (!array_key_exists($k, $data))
{
$data[$k] = null;
}
if ($data[$k] != $this->id)
{
$session->set($this->getHash() . 'savedata', null);
}
else
{
$this->record->bind($data);
}
}
}
}
$this->onAfterGetItem($this->record);
}
return $this->record;
}
/**
* Alias for getItemList
*
* @param boolean $overrideLimits Should I override set limits?
* @param string $group The group by clause
* @codeCoverageIgnore
*
* @return array
*/
public function &getList($overrideLimits = false, $group = '')
{
return $this->getItemList($overrideLimits, $group);
}
/**
* Returns a list of items
*
* @param boolean $overrideLimits Should I override set limits?
* @param string $group The group by clause
*
* @return array
*/
public function &getItemList($overrideLimits = false, $group = '')
{
if (empty($this->list))
{
$query = $this->buildQuery($overrideLimits);
if (!$overrideLimits)
{
$limitstart = $this->getState('limitstart');
$limit = $this->getState('limit');
$this->list = $this->_getList((string) $query, $limitstart, $limit, $group);
}
else
{
$this->list = $this->_getList((string) $query, 0, 0, $group);
}
}
return $this->list;
}
/**
* Returns a F0FDatabaseIterator over a list of items.
*
* THERE BE DRAGONS. Unlike the getItemList() you have a few restrictions:
* - The onProcessList event does not run when you get an iterator
* - The Iterator returns F0FTable instances. By default, $this->table is used. If you have JOINs, GROUPs or a
* complex query in general you will need to create a custom F0FTable subclass and pass its type in $tableType.
*
* The getIterator() method is a great way to sift through a large amount of records which would otherwise not fit
* in memory since it only keeps one record in PHP memory at a time. It works best with simple models, returning
* all the contents of a single database table.
*
* @param boolean $overrideLimits Should I ignore set limits?
* @param string $tableClass The table class for the iterator, e.g. FoobarTableBar. Leave empty to use
* the default Table class for this Model.
*
* @return F0FDatabaseIterator
*/
public function &getIterator($overrideLimits = false, $tableClass = null)
{
// Get the table name (required by the Iterator)
if (empty($tableClass))
{
$name = $this->table;
if (empty($name))
{
$name = F0FInflector::singularize($this->getName());
}
$bareComponent = str_replace('com_', '', $this->option);
$prefix = ucfirst($bareComponent) . 'Table';
$tableClass = $prefix . ucfirst($name);
}
// Get the query
$query = $this->buildQuery($overrideLimits);
// Apply limits
if ($overrideLimits)
{
$limitStart = 0;
$limit = 0;
}
else
{
$limitStart = $this->getState('limitstart');
$limit = $this->getState('limit');
}
// This is required to prevent one relation from killing the db cursor used in a different relation...
$oldDb = $this->getDbo();
$oldDb->disconnect(); // YES, WE DO NEED TO DISCONNECT BEFORE WE CLONE THE DB OBJECT. ARGH!
$db = clone $oldDb;
// Execute the query, get a db cursor and return the iterator
$db->setQuery($query, $limitStart, $limit);
$cursor = $db->execute();
$iterator = F0FDatabaseIterator::getIterator($db->name, $cursor, null, $tableClass);
return $iterator;
}
/**
* A cross-breed between getItem and getItemList. It runs the complete query,
* like getItemList does. However, instead of returning an array of ad-hoc
* objects, it binds the data from the first item fetched on the list to an
* instance of the table object and returns that table object instead.
*
* @param boolean $overrideLimits Should I override set limits?
*
* @return F0FTable
*/
public function &getFirstItem($overrideLimits = false)
{
/**
* We have to clone the instance, or when multiple getFirstItem calls occur,
* we'll update EVERY instance created
*/
$table = clone $this->getTable($this->table);
$list = $this->getItemList($overrideLimits);
if (!empty($list))
{
$firstItem = array_shift($list);
$table->bind($firstItem);
}
unset($list);
return $table;
}
/**
* Binds the data to the model and tries to save it
*
* @param array|object $data The source data array or object
*
* @return boolean True on success
*/
public function save($data)
{
$this->otable = null;
$table = $this->getTable($this->table);
if (is_object($data))
{
$data = clone($data);
}
$key = $table->getKeyName();
if (array_key_exists($key, (array) $data))
{
$aData = (array) $data;
$oid = $aData[$key];
$table->load($oid);
}
if ($data instanceof F0FTable)
{
$allData = $data->getData();
}
elseif (is_object($data))
{
$allData = (array) $data;
}
else
{
$allData = $data;
}
// Get the form if there is any
$form = $this->getForm($allData, false);
if ($form instanceof F0FForm)
{
// Make sure that $allData has for any field a key
$fieldset = $form->getFieldset();
foreach ($fieldset as $nfield => $fldset)
{
if (!array_key_exists($nfield, $allData))
{
$field = $form->getField($fldset->fieldname, $fldset->group);
$type = strtolower($field->type);
switch ($type)
{
case 'checkbox':
$allData[$nfield] = 0;
break;
default:
$allData[$nfield] = '';
break;
}
}
}
$serverside_validate = strtolower($form->getAttribute('serverside_validate'));
$validateResult = true;
if (in_array($serverside_validate, array('true', 'yes', '1', 'on')))
{
$validateResult = $this->validateForm($form, $allData);
}
if ($validateResult === false)
{
if ($this->_savestate)
{
$session = JFactory::getSession();
$hash = $this->getHash() . 'savedata';
$session->set($hash, serialize($allData));
}
return false;
}
}
if (!$this->onBeforeSave($allData, $table))
{
if ($this->_savestate)
{
$session = JFactory::getSession();
$hash = $this->getHash() . 'savedata';
$session->set($hash, serialize($allData));
}
return false;
}
else
{
// If onBeforeSave successful, refetch the possibly modified data
if ($data instanceof F0FTable)
{
$data->bind($allData);
}
elseif (is_object($data))
{
$data = (object) $allData;
}
else
{
$data = $allData;
}
}
if (!$table->save($data))
{
foreach ($table->getErrors() as $error)
{
if (!empty($error))
{
$this->setError($error);
$session = JFactory::getSession();
$tableprops = $table->getProperties(true);
unset($tableprops['input']);
unset($tableprops['config']['input']);
unset($tableprops['config']['db']);
unset($tableprops['config']['dbo']);
if ($this->_savestate)
{
$hash = $this->getHash() . 'savedata';
$session->set($hash, serialize($tableprops));
}
}
}
return false;
}
else
{
$this->id = $table->$key;
// Remove the session data
if ($this->_savestate)
{
JFactory::getSession()->set($this->getHash() . 'savedata', null);
}
}
$this->onAfterSave($table);
$this->otable = $table;
return true;
}
/**
* Copy one or more records
*
* @return boolean True on success
*/
public function copy()
{
if (is_array($this->id_list) && !empty($this->id_list))
{
$table = $this->getTable($this->table);
if (!$this->onBeforeCopy($table))
{
return false;
}
if (!$table->copy($this->id_list))
{
$this->setError($table->getError());
return false;
}
else
{
// Call our internal event
$this->onAfterCopy($table);
// @todo Should we fire the content plugin?
}
}
return true;
}
/**
* Returns the table object after the last save() operation
*
* @return F0FTable
*/
public function getSavedTable()
{
return $this->otable;
}
/**
* Deletes one or several items
*
* @return boolean True on success
*/
public function delete()
{
if (is_array($this->id_list) && !empty($this->id_list))
{
$table = $this->getTable($this->table);
foreach ($this->id_list as $id)
{
if (!$this->onBeforeDelete($id, $table))
{
continue;
}
if (!$table->delete($id))
{
$this->setError($table->getError());
return false;
}
else
{
$this->onAfterDelete($id);
}
}
}
return true;
}
/**
* Toggles the published state of one or several items
*
* @param integer $publish The publishing state to set (e.g. 0 is unpublished)
* @param integer $user The user ID performing this action
*
* @return boolean True on success
*/
public function publish($publish = 1, $user = null)
{
if (is_array($this->id_list) && !empty($this->id_list))
{
if (empty($user))
{
$oUser = F0FPlatform::getInstance()->getUser();
$user = $oUser->id;
}
$table = $this->getTable($this->table);
if (!$this->onBeforePublish($table))
{
return false;
}
if (!$table->publish($this->id_list, $publish, $user))
{
$this->setError($table->getError());
return false;
}
else
{
// Call our internal event
$this->onAfterPublish($table);
// Call the plugin events
F0FPlatform::getInstance()->importPlugin('content');
$name = $this->name;
$context = $this->option . '.' . $name;
// @TODO should we do anything with this return value?
$result = F0FPlatform::getInstance()->runPlugins($this->event_change_state, array($context, $this->id_list, $publish));
}
}
return true;
}
/**
* Checks out the current item
*
* @return boolean
*/
public function checkout()
{
$table = $this->getTable($this->table);
$status = $table->checkout(F0FPlatform::getInstance()->getUser()->id, $this->id);
if (!$status)
{
$this->setError($table->getError());
}
return $status;
}
/**
* Checks in the current item
*
* @return boolean
*/
public function checkin()
{
$table = $this->getTable($this->table);
$status = $table->checkin($this->id);
if (!$status)
{
$this->setError($table->getError());
}
return $status;
}
/**
* Tells you if the current item is checked out or not
*
* @return boolean
*/
public function isCheckedOut()
{
$table = $this->getTable($this->table);
$status = $table->isCheckedOut($this->id);
if (!$status)
{
$this->setError($table->getError());
}
return $status;
}
/**
* Increments the hit counter
*
* @return boolean
*/
public function hit()
{
$table = $this->getTable($this->table);
if (!$this->onBeforeHit($table))
{
return false;
}
$status = $table->hit($this->id);
if (!$status)
{
$this->setError($table->getError());
}
else
{
$this->onAfterHit($table);
}
return $status;
}
/**
* Moves the current item up or down in the ordering list
*
* @param string $dirn The direction and magnitude to use (2 means move up by 2 positions, -3 means move down three positions)
*
* @return boolean True on success
*/
public function move($dirn)
{
$table = $this->getTable($this->table);
$id = $this->getId();
$status = $table->load($id);
if (!$status)
{
$this->setError($table->getError());
}
if (!$status)
{
return false;
}
if (!$this->onBeforeMove($table))
{
return false;
}
$status = $table->move($dirn);
if (!$status)
{
$this->setError($table->getError());
}
else
{
$this->onAfterMove($table);
}
return $status;
}
/**
* Reorders all items in the table
*
* @return boolean
*/
public function reorder()
{
$table = $this->getTable($this->table);
if (!$this->onBeforeReorder($table))
{
return false;
}
$status = $table->reorder($this->getReorderWhere());
if (!$status)
{
$this->setError($table->getError());
}
else
{
if (!$this->onAfterReorder($table))
{
return false;
}
}
return $status;
}
/**
* Get a pagination object
*
* @return JPagination
*/
public function getPagination()
{
if (empty($this->pagination))
{
// Import the pagination library
JLoader::import('joomla.html.pagination');
// Prepare pagination values
$total = $this->getTotal();
$limitstart = $this->getState('limitstart');
$limit = $this->getState('limit');
// Create the pagination object
$this->pagination = new JPagination($total, $limitstart, $limit);
}
return $this->pagination;
}
/**
* Get the number of all items
*
* @return integer
*/
public function getTotal()
{
if (is_null($this->total))
{
$query = $this->buildCountQuery();
if ($query === false)
{
$subquery = $this->buildQuery(false);
$subquery->clear('order');
$query = $this->_db->getQuery(true)
->select('COUNT(*)')
->from("(" . (string) $subquery . ") AS a");
}
$this->_db->setQuery((string) $query);
$this->total = $this->_db->loadResult();
}
return $this->total;
}
/**
* Returns a record count for the query
*
* @param string $query The query.
*
* @return integer Number of rows for query
*
* @since 12.2
*/
protected function _getListCount($query)
{
return $this->getTotal();
}
/**
* Get a filtered state variable
*
* @param string $key The name of the state variable
* @param mixed $default The default value to use
* @param string $filter_type Filter type
*
* @return mixed The variable's value
*/
public function getState($key = null, $default = null, $filter_type = 'raw')
{
if (empty($key))
{
return $this->_real_getState();
}
// Get the savestate status
$value = $this->_real_getState($key);
if (is_null($value))
{
$value = $this->getUserStateFromRequest($this->getHash() . $key, $key, $value, 'none', $this->_savestate);
if (is_null($value))
{
return $default;
}
}
if (strtoupper($filter_type) == 'RAW')
{
return $value;
}
else
{
JLoader::import('joomla.filter.filterinput');
$filter = new JFilterInput;
return $filter->clean($value, $filter_type);
}
}
/**
* Method to get model state variables
*
* @param string $property Optional parameter name
* @param mixed $default Optional default value
*
* @return object The property where specified, the state object where omitted
*
* @since 12.2
*/
protected function _real_getState($property = null, $default = null)
{
if (!$this->__state_set)
{
// Protected method to auto-populate the model state.
$this->populateState();
// Set the model state set flag to true.
$this->__state_set = true;
}
return $property === null ? $this->state : $this->state->get($property, $default);
}
/**
* Returns a hash for this component and view, e.g. "foobar.items.", used
* for determining the keys of the variables which will be placed in the
* session storage.
*
* @return string The hash
*/
public function getHash()
{
$option = $this->input->getCmd('option', 'com_foobar');
$view = F0FInflector::pluralize($this->input->getCmd('view', 'cpanel'));
return "$option.$view.";
}
/**
* Gets the value of a user state variable.
*
* @param string $key The key of the user state variable.
* @param string $request The name of the variable passed in a request.
* @param string $default The default value for the variable if not found. Optional.
* @param string $type Filter for the variable, for valid values see {@link JFilterInput::clean()}. Optional.
* @param boolean $setUserState Should I save the variable in the user state? Default: true. Optional.
*
* @return string The request user state.
*/
protected function getUserStateFromRequest($key, $request, $default = null, $type = 'none', $setUserState = true)
{
return F0FPlatform::getInstance()->getUserStateFromRequest($key, $request, $this->input, $default, $type, $setUserState);
}
/**
* Returns an object list
*
* @param string $query The query
* @param integer $limitstart Offset from start
* @param integer $limit The number of records
* @param string $group The group by clause
*
* @return array Array of objects
*/
protected function &_getList($query, $limitstart = 0, $limit = 0, $group = '')
{
$this->_db->setQuery($query, $limitstart, $limit);
$result = $this->_db->loadObjectList($group);
$this->onProcessList($result);
return $result;
}
/**
* Method to get a table object, load it if necessary.
*
* @param string $name The table name. Optional.
* @param string $prefix The class prefix. Optional.
* @param array $options Configuration array for model. Optional.
*
* @throws Exception
*
* @return F0FTable A F0FTable object
*/
public function getTable($name = '', $prefix = null, $options = array())
{
if (empty($name))
{
$name = $this->table;
if (empty($name))
{
$name = F0FInflector::singularize($this->getName());
}
}
if (empty($prefix))
{
$bareComponent = str_replace('com_', '', $this->option);
$prefix = ucfirst($bareComponent) . 'Table';
}
if (empty($options))
{
$options = array('input' => $this->input);
}
if ($table = $this->_createTable($name, $prefix, $options))
{
return $table;
}
F0FPlatform::getInstance()->raiseError(0, JText::sprintf('JLIB_APPLICATION_ERROR_TABLE_NAME_NOT_SUPPORTED', $name));
return null;
}
/**
* Method to load and return a model object.
*
* @param string $name The name of the view
* @param string $prefix The class prefix. Optional.
* @param array $config The configuration array to pass to the table
*
* @return F0FTable Table object or boolean false if failed
*/
protected function &_createTable($name, $prefix = 'Table', $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
$name = preg_replace('/[^A-Z0-9_]/i', '', $name);
$prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
// Make sure we are returning a DBO object
if (!array_key_exists('dbo', $config))
{
$config['dbo'] = $this->getDBO();
}
$instance = F0FTable::getAnInstance($name, $prefix, $config);
return $instance;
}
/**
* Creates the WHERE part of the reorder query
*
* @return string
*/
public function getReorderWhere()
{
return '';
}
/**
* Builds the SELECT query
*
* @param boolean $overrideLimits Are we requested to override the set limits?
*
* @return F0FDatabaseQuery
*/
public function buildQuery($overrideLimits = false)
{
$table = $this->getTable();
$tableName = $table->getTableName();
$tableKey = $table->getKeyName();
$db = $this->getDbo();
$query = $db->getQuery(true);
// Call the behaviors
$this->modelDispatcher->trigger('onBeforeBuildQuery', array(&$this, &$query));
$alias = $this->getTableAlias();
if ($alias)
{
$alias = ' AS ' . $db->qn($alias);
}
else
{
$alias = '';
}
$select = $this->getTableAlias() ? $db->qn($this->getTableAlias()) . '.*' : $db->qn($tableName) . '.*';
$query->select($select)->from($db->qn($tableName) . $alias);
if (!$overrideLimits)
{
$order = $this->getState('filter_order', null, 'cmd');
if (!in_array($order, array_keys($table->getData())))
{
$order = $tableKey;
}
$order = $db->qn($order);
if ($alias)
{
$order = $db->qn($this->getTableAlias()) . '.' . $order;
}
$dir = strtoupper($this->getState('filter_order_Dir', 'ASC', 'cmd'));
$dir = in_array($dir, array('DESC', 'ASC')) ? $dir : 'ASC';
// If the table cache is broken you may end up with an empty order by.
if (!empty($order) && ($order != $db->qn('')))
{
$query->order($order . ' ' . $dir);
}
}
// Call the behaviors
$this->modelDispatcher->trigger('onAfterBuildQuery', array(&$this, &$query));
return $query;
}
/**
* Returns a list of the fields of the table associated with this model
*
* @return array
*/
public function getTableFields()
{
$tableName = $this->getTable()->getTableName();
if (version_compare(JVERSION, '3.0', 'ge'))
{
$fields = $this->getDbo()->getTableColumns($tableName, true);
}
else
{
$fieldsArray = $this->getDbo()->getTableFields($tableName, true);
$fields = array_shift($fieldsArray);
}
return $fields;
}
/**
* Get the alias set for this model's table
*
* @return string The table alias
*/
public function getTableAlias()
{
return $this->getTable($this->table)->getTableAlias();
}
/**
* Builds the count query used in getTotal()
*
* @return boolean
*/
public function buildCountQuery()
{
return false;
}
/**
* Clones the model object and returns the clone
*
* @return F0FModel
*/
public function &getClone()
{
$clone = clone($this);
return $clone;
}
/**
* Magic getter; allows to use the name of model state keys as properties
*
* @param string $name The name of the variable to get
*
* @return mixed The value of the variable
*/
public function __get($name)
{
return $this->getState($name);
}
/**
* Magic setter; allows to use the name of model state keys as properties
*
* @param string $name The name of the variable
* @param mixed $value The value to set the variable to
*
* @return void
*/
public function __set($name, $value)
{
return $this->setState($name, $value);
}
/**
* Magic caller; allows to use the name of model state keys as methods to
* set their values.
*
* @param string $name The name of the state variable to set
* @param mixed $arguments The value to set the state variable to
*
* @return F0FModel Reference to self
*/
public function __call($name, $arguments)
{
$arg1 = array_shift($arguments);
$this->setState($name, $arg1);
return $this;
}
/**
* Sets the model state auto-save status. By default the model is set up to
* save its state to the session.
*
* @param boolean $newState True to save the state, false to not save it.
*
* @return F0FModel Reference to self
*/
public function &savestate($newState)
{
$this->_savestate = $newState ? true : false;
return $this;
}
/**
* Initialises the _savestate variable
*
* @param integer $defaultSaveState The default value for the savestate
*
* @return void
*/
public function populateSavestate($defaultSaveState = -999)
{
if (is_null($this->_savestate))
{
$savestate = $this->input->getInt('savestate', $defaultSaveState);
if ($savestate == -999)
{
$savestate = true;
}
$this->savestate($savestate);
}
}
/**
* Method to auto-populate the model state.
*
* This method should only be called once per instantiation and is designed
* to be called on the first call to the getState() method unless the model
* configuration flag to ignore the request is set.
*
* @return void
*
* @note Calling getState in this method will result in recursion.
* @since 12.2
*/
protected function populateState()
{
}
/**
* Applies view access level filtering for the specified user. Useful to
* filter a front-end items listing.
*
* @param integer $userID The user ID to use. Skip it to use the currently logged in user.
*
* @return F0FModel Reference to self
*/
public function applyAccessFiltering($userID = null)
{
$user = F0FPlatform::getInstance()->getUser($userID);
$table = $this->getTable();
$accessField = $table->getColumnAlias('access');
$this->setState($accessField, $user->getAuthorisedViewLevels());
return $this;
}
/**
* A method for getting the form from the model.
*
* @param array $data Data for the form.
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
* @param boolean $source The name of the form. If not set we'll try the form_name state variable or fall back to default.
*
* @return mixed A F0FForm object on success, false on failure
*
* @since 2.0
*/
public function getForm($data = array(), $loadData = true, $source = null)
{
$this->_formData = $data;
if (empty($source))
{
$source = $this->getState('form_name', null);
}
if (empty($source))
{
$source = 'form.' . $this->name;
}
$name = $this->input->getCmd('option', 'com_foobar') . '.' . $this->name . '.' . $source;
$options = array(
'control' => false,
'load_data' => $loadData,
);
$this->onBeforeLoadForm($name, $source, $options);
$form = $this->loadForm($name, $source, $options);
if ($form instanceof F0FForm)
{
$this->onAfterLoadForm($form, $name, $source, $options);
}
return $form;
}
/**
* Method to get a form object.
*
* @param string $name The name of the form.
* @param string $source The form filename (e.g. form.browse)
* @param array $options Optional array of options for the form creation.
* @param boolean $clear Optional argument to force load a new form.
* @param bool|string $xpath An optional xpath to search for the fields.
*
* @return mixed F0FForm object on success, False on error.
*
* @throws Exception
*
* @see F0FForm
* @since 2.0
*/
protected function loadForm($name, $source, $options = array(), $clear = false, $xpath = false)
{
// Handle the optional arguments.
$options['control'] = isset($options['control']) ? $options['control'] : false;
// Create a signature hash.
$hash = md5($source . serialize($options));
// Check if we can use a previously loaded form.
if (isset($this->_forms[$hash]) && !$clear)
{
return $this->_forms[$hash];
}
// Try to find the name and path of the form to load
$formFilename = $this->findFormFilename($source);
// No form found? Quit!
if ($formFilename === false)
{
return false;
}
// Set up the form name and path
$source = basename($formFilename, '.xml');
F0FForm::addFormPath(dirname($formFilename));
// Set up field paths
$option = $this->input->getCmd('option', 'com_foobar');
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($option);
$view = $this->name;
$file_root = $componentPaths['main'];
$alt_file_root = $componentPaths['alt'];
F0FForm::addFieldPath($file_root . '/fields');
F0FForm::addFieldPath($file_root . '/models/fields');
F0FForm::addFieldPath($alt_file_root . '/fields');
F0FForm::addFieldPath($alt_file_root . '/models/fields');
F0FForm::addHeaderPath($file_root . '/fields/header');
F0FForm::addHeaderPath($file_root . '/models/fields/header');
F0FForm::addHeaderPath($alt_file_root . '/fields/header');
F0FForm::addHeaderPath($alt_file_root . '/models/fields/header');
// Get the form.
try
{
$form = F0FForm::getInstance($name, $source, $options, false, $xpath);
if (isset($options['load_data']) && $options['load_data'])
{
// Get the data for the form.
$data = $this->loadFormData();
}
else
{
$data = array();
}
// Allows data and form manipulation before preprocessing the form
$this->onBeforePreprocessForm($form, $data);
// Allow for additional modification of the form, and events to be triggered.
// We pass the data because plugins may require it.
$this->preprocessForm($form, $data);
// Allows data and form manipulation After preprocessing the form
$this->onAfterPreprocessForm($form, $data);
// Load the data into the form after the plugins have operated.
$form->bind($data);
}
catch (Exception $e)
{
// The above try-catch statement will catch EVERYTHING, even PhpUnit exceptions while testing
if(stripos(get_class($e), 'phpunit') !== false)
{
throw $e;
}
else
{
$this->setError($e->getMessage());
return false;
}
}
// Store the form for later.
$this->_forms[$hash] = $form;
return $form;
}
/**
* Guesses the best candidate for the path to use for a particular form.
*
* @param string $source The name of the form file to load, without the .xml extension.
* @param array $paths The paths to look into. You can declare this to override the default F0F paths.
*
* @return mixed A string if the path and filename of the form to load is found, false otherwise.
*
* @since 2.0
*/
public function findFormFilename($source, $paths = array())
{
// TODO Should we read from internal variables instead of the input? With a temp instance we have no input
$option = $this->input->getCmd('option', 'com_foobar');
$view = $this->name;
$componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($option);
$file_root = $componentPaths['main'];
$alt_file_root = $componentPaths['alt'];
$template_root = F0FPlatform::getInstance()->getTemplateOverridePath($option);
if (empty($paths))
{
// Set up the paths to look into
// PLEASE NOTE: If you ever change this, please update Model Unit tests, too, since we have to
// copy these default folders (we have to add the protocol for the virtual filesystem)
$paths = array(
// In the template override
$template_root . '/' . $view,
$template_root . '/' . F0FInflector::singularize($view),
$template_root . '/' . F0FInflector::pluralize($view),
// In this side of the component
$file_root . '/views/' . $view . '/tmpl',
$file_root . '/views/' . F0FInflector::singularize($view) . '/tmpl',
$file_root . '/views/' . F0FInflector::pluralize($view) . '/tmpl',
// In the other side of the component
$alt_file_root . '/views/' . $view . '/tmpl',
$alt_file_root . '/views/' . F0FInflector::singularize($view) . '/tmpl',
$alt_file_root . '/views/' . F0FInflector::pluralize($view) . '/tmpl',
// In the models/forms of this side
$file_root . '/models/forms',
// In the models/forms of the other side
$alt_file_root . '/models/forms',
);
}
$paths = array_unique($paths);
// Set up the suffixes to look into
$suffixes = array();
$temp_suffixes = F0FPlatform::getInstance()->getTemplateSuffixes();
if (!empty($temp_suffixes))
{
foreach ($temp_suffixes as $suffix)
{
$suffixes[] = $suffix . '.xml';
}
}
$suffixes[] = '.xml';
// Look for all suffixes in all paths
$result = false;
$filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem');
foreach ($paths as $path)
{
foreach ($suffixes as $suffix)
{
$filename = $path . '/' . $source . $suffix;
if ($filesystem->fileExists($filename))
{
$result = $filename;
break;
}
}
if ($result)
{
break;
}
}
return $result;
}
/**
* Method to get the data that should be injected in the form.
*
* @return array The default data is an empty array.
*
* @since 2.0
*/
protected function loadFormData()
{
if (empty($this->_formData))
{
return array();
}
else
{
return $this->_formData;
}
}
/**
* Method to allow derived classes to preprocess the form.
*
* @param F0FForm $form A F0FForm object.
* @param mixed &$data The data expected for the form.
* @param string $group The name of the plugin group to import (defaults to "content").
*
* @return void
*
* @see F0FFormField
* @since 2.0
* @throws Exception if there is an error in the form event.
*/
protected function preprocessForm(F0FForm &$form, &$data, $group = 'content')
{
// Import the appropriate plugin group.
F0FPlatform::getInstance()->importPlugin($group);
// Trigger the form preparation event.
$results = F0FPlatform::getInstance()->runPlugins('onContentPrepareForm', array($form, $data));
// Check for errors encountered while preparing the form.
if (count($results) && in_array(false, $results, true))
{
// Get the last error.
$dispatcher = F0FUtilsObservableDispatcher::getInstance();
$error = $dispatcher->getError();
if (!($error instanceof Exception))
{
throw new Exception($error);
}
}
}
/**
* Method to validate the form data.
*
* @param F0FForm $form The form to validate against.
* @param array $data The data to validate.
* @param string $group The name of the field group to validate.
*
* @return mixed Array of filtered data if valid, false otherwise.
*
* @see JFormRule
* @see JFilterInput
* @since 2.0
*/
public function validateForm($form, $data, $group = null)
{
// Filter and validate the form data.
$data = $form->filter($data);
$return = $form->validate($data, $group);
// Check for an error.
if ($return instanceof Exception)
{
$this->setError($return->getMessage());
return false;
}
// Check the validation results.
if ($return === false)
{
// Get the validation messages from the form.
foreach ($form->getErrors() as $message)
{
if ($message instanceof Exception)
{
$this->setError($message->getMessage());
}
else
{
$this->setError($message);
}
}
return false;
}
return $data;
}
/**
* Allows the manipulation before the form is loaded
*
* @param string &$name The name of the form.
* @param string &$source The form source. Can be XML string if file flag is set to false.
* @param array &$options Optional array of options for the form creation.
* @codeCoverageIgnore
*
* @return void
*/
public function onBeforeLoadForm(&$name, &$source, &$options)
{
}
/**
* Allows the manipulation after the form is loaded
*
* @param F0FForm $form A F0FForm object.
* @param string &$name The name of the form.
* @param string &$source The form source. Can be XML string if file flag is set to false.
* @param array &$options Optional array of options for the form creation.
* @codeCoverageIgnore
*
* @return void
*/
public function onAfterLoadForm(F0FForm &$form, &$name, &$source, &$options)
{
}
/**
* Allows data and form manipulation before preprocessing the form
*
* @param F0FForm $form A F0FForm object.
* @param array &$data The data expected for the form.
* @codeCoverageIgnore
*
* @return void
*/
public function onBeforePreprocessForm(F0FForm &$form, &$data)
{
}
/**
* Allows data and form manipulation after preprocessing the form
*
* @param F0FForm $form A F0FForm object.
* @param array &$data The data expected for the form.
* @codeCoverageIgnore
*
* @return void
*/
public function onAfterPreprocessForm(F0FForm &$form, &$data)
{
}
/**
* This method can be overriden to automatically do something with the
* list results array. You are supposed to modify the list which was passed
* in the parameters; DO NOT return a new array!
*
* @param array &$resultArray An array of objects, each row representing a record
*
* @return void
*/
protected function onProcessList(&$resultArray)
{
}
/**
* This method runs after an item has been gotten from the database in a read
* operation. You can modify it before it's returned to the MVC triad for
* further processing.
*
* @param F0FTable &$record The table instance we fetched
*
* @return void
*/
protected function onAfterGetItem(&$record)
{
try
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onAfterGetItem', array(&$this, &$record));
}
catch (Exception $e)
{
// Oops, an exception occured!
$this->setError($e->getMessage());
}
}
/**
* This method runs before the $data is saved to the $table. Return false to
* stop saving.
*
* @param array &$data The data to save
* @param F0FTable &$table The table to save the data to
*
* @return boolean Return false to prevent saving, true to allow it
*/
protected function onBeforeSave(&$data, &$table)
{
// Let's import the plugin only if we're not in CLI (content plugin needs a user)
F0FPlatform::getInstance()->importPlugin('content');
try
{
// Do I have a new record?
$key = $table->getKeyName();
$pk = (!empty($data[$key])) ? $data[$key] : 0;
$this->_isNewRecord = $pk <= 0;
// Bind the data
$table->bind($data);
// Call the behaviors
$result = $this->modelDispatcher->trigger('onBeforeSave', array(&$this, &$data));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
// Call the plugin
$name = $this->name;
$result = F0FPlatform::getInstance()->runPlugins($this->event_before_save, array($this->option . '.' . $name, &$table, $this->_isNewRecord));
if (in_array(false, $result, true))
{
// Plugin failed, return false
$this->setError($table->getError());
return false;
}
}
catch (Exception $e)
{
// Oops, an exception occured!
$this->setError($e->getMessage());
return false;
}
return true;
}
/**
* This method runs after the data is saved to the $table.
*
* @param F0FTable &$table The table which was saved
*
* @return boolean
*/
protected function onAfterSave(&$table)
{
// Let's import the plugin only if we're not in CLI (content plugin needs a user)
F0FPlatform::getInstance()->importPlugin('content');
try
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onAfterSave', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
$name = $this->name;
F0FPlatform::getInstance()->runPlugins($this->event_after_save, array($this->option . '.' . $name, &$table, $this->_isNewRecord));
return true;
}
catch (Exception $e)
{
// Oops, an exception occured!
$this->setError($e->getMessage());
return false;
}
}
/**
* This method runs before the record with key value of $id is deleted from $table
*
* @param integer &$id The ID of the record being deleted
* @param F0FTable &$table The table instance used to delete the record
*
* @return boolean
*/
protected function onBeforeDelete(&$id, &$table)
{
// Let's import the plugin only if we're not in CLI (content plugin needs a user)
F0FPlatform::getInstance()->importPlugin('content');
try
{
$table->load($id);
// Call the behaviors
$result = $this->modelDispatcher->trigger('onBeforeDelete', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
$name = $this->name;
$context = $this->option . '.' . $name;
$result = F0FPlatform::getInstance()->runPlugins($this->event_before_delete, array($context, $table));
if (in_array(false, $result, true))
{
// Plugin failed, return false
$this->setError($table->getError());
return false;
}
$this->_recordForDeletion = clone $table;
}
catch (Exception $e)
{
// Oops, an exception occured!
$this->setError($e->getMessage());
return false;
}
return true;
}
/**
* This method runs after a record with key value $id is deleted
*
* @param integer $id The id of the record which was deleted
*
* @return boolean Return false to raise an error, true otherwise
*/
protected function onAfterDelete($id)
{
F0FPlatform::getInstance()->importPlugin('content');
// Call the behaviors
$result = $this->modelDispatcher->trigger('onAfterDelete', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
try
{
$name = $this->name;
$context = $this->option . '.' . $name;
$result = F0FPlatform::getInstance()->runPlugins($this->event_after_delete, array($context, $this->_recordForDeletion));
unset($this->_recordForDeletion);
}
catch (Exception $e)
{
// Oops, an exception occured!
$this->setError($e->getMessage());
return false;
}
}
/**
* This method runs before a record is copied
*
* @param F0FTable &$table The table instance of the record being copied
*
* @return boolean True to allow the copy
*/
protected function onBeforeCopy(&$table)
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onBeforeCopy', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
return true;
}
/**
* This method runs after a record has been copied
*
* @param F0FTable &$table The table instance of the record which was copied
*
* @return boolean True to allow the copy
*/
protected function onAfterCopy(&$table)
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onAfterCopy', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
return true;
}
/**
* This method runs before a record is published
*
* @param F0FTable &$table The table instance of the record being published
*
* @return boolean True to allow the operation
*/
protected function onBeforePublish(&$table)
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onBeforePublish', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
return true;
}
/**
* This method runs after a record has been published
*
* @param F0FTable &$table The table instance of the record which was published
*
* @return boolean True to allow the operation
*/
protected function onAfterPublish(&$table)
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onAfterPublish', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
return true;
}
/**
* This method runs before a record is hit
*
* @param F0FTable &$table The table instance of the record being hit
*
* @return boolean True to allow the operation
*/
protected function onBeforeHit(&$table)
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onBeforeHit', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
return true;
}
/**
* This method runs after a record has been hit
*
* @param F0FTable &$table The table instance of the record which was hit
*
* @return boolean True to allow the operation
*/
protected function onAfterHit(&$table)
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onAfterHit', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
return true;
}
/**
* This method runs before a record is moved
*
* @param F0FTable &$table The table instance of the record being moved
*
* @return boolean True to allow the operation
*/
protected function onBeforeMove(&$table)
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onBeforeMove', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
return true;
}
/**
* This method runs after a record has been moved
*
* @param F0FTable &$table The table instance of the record which was moved
*
* @return boolean True to allow the operation
*/
protected function onAfterMove(&$table)
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onAfterMove', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
return true;
}
/**
* This method runs before a table is reordered
*
* @param F0FTable &$table The table instance being reordered
*
* @return boolean True to allow the operation
*/
protected function onBeforeReorder(&$table)
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onBeforeReorder', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
return true;
}
/**
* This method runs after a table is reordered
*
* @param F0FTable &$table The table instance which was reordered
*
* @return boolean True to allow the operation
*/
protected function onAfterReorder(&$table)
{
// Call the behaviors
$result = $this->modelDispatcher->trigger('onAfterReorder', array(&$this));
if (in_array(false, $result, true))
{
// Behavior failed, return false
return false;
}
return true;
}
/**
* Method to get the database driver object
*
* @return F0FDatabaseDriver
*/
public function getDbo()
{
return $this->_db;
}
/**
* Method to get the model 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
*
* @throws Exception
*/
public function getName()
{
if (empty($this->name))
{
$r = null;
if (!preg_match('/Model(.*)/i', get_class($this), $r))
{
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500);
}
$this->name = strtolower($r[1]);
}
return $this->name;
}
/**
* Method to set the database driver object
*
* @param F0FDatabaseDriver $db A F0FDatabaseDriver based object
*
* @return void
*/
public function setDbo($db)
{
$this->_db = $db;
}
/**
* Method to set model state variables
*
* @param string $property The name of the property.
* @param mixed $value The value of the property to set or null.
*
* @return mixed The previous value of the property or null if not set.
*/
public function setState($property, $value = null)
{
return $this->state->set($property, $value);
}
/**
* Clean the cache
*
* @param string $group The cache group
* @param integer $client_id The ID of the client
*
* @return void
*/
protected function cleanCache($group = null, $client_id = 0)
{
$conf = JFactory::getConfig();
$platformDirs = F0FPlatform::getInstance()->getPlatformBaseDirs();
$options = array(
'defaultgroup' => ($group) ? $group : (isset($this->option) ? $this->option : JFactory::getApplication()->input->get('option')),
'cachebase' => ($client_id) ? $platformDirs['admin'] . '/cache' : $conf->get('cache_path', $platformDirs['public'] . '/cache'));
$cache = JCache::getInstance('callback', $options);
$cache->clean();
// Trigger the onContentCleanCache event.
F0FPlatform::getInstance()->runPlugins($this->event_clean_cache, $options);
}
/**
* Set a behavior param
*
* @param string $name The name of the param
* @param mixed $value The param value to set
*
* @return FOFModel
*/
public function setBehaviorParam($name, $value)
{
$this->_behaviorParams[$name] = $value;
return $this;
}
/**
* Get a behavior param
*
* @param string $name The name of the param
* @param mixed $default The default value returned if not set
*
* @return mixed
*/
public function getBehaviorParam($name, $default = null)
{
return isset($this->_behaviorParams[$name]) ? $this->_behaviorParams[$name] : $default;
}
/**
* Set or get the backlisted filters
*
* @param mixed $list A filter or list of filters to backlist. If null return the list of backlisted filter
* @param boolean $reset Reset the blacklist if true
*
* @return void|array Return an array of value if $list is null
*/
public function blacklistFilters($list = null, $reset = false)
{
if (!isset($list))
{
return $this->getBehaviorParam('blacklistFilters', array());
}
if (is_string($list))
{
$list = (array) $list;
}
if (!$reset)
{
$list = array_unique(array_merge($this->getBehaviorParam('blacklistFilters', array()), $list));
}
$this->setBehaviorParam('blacklistFilters', $list);
}
}
base.php 0000604 00000002472 15245561006 0006174 0 ustar 00 <?php
/**
* @package Joomla.Platform
* @subpackage Model
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE
*/
defined('JPATH_PLATFORM') or die;
use Joomla\Registry\Registry;
/**
* Joomla Platform Base Model Class
*
* @since 3.0.0
* @deprecated 4.0 Use the default MVC library
*/
abstract class JModelBase implements JModel
{
/**
* The model state.
*
* @var Registry
* @since 3.0.0
*/
protected $state;
/**
* Instantiate the model.
*
* @param Registry $state The model state.
*
* @since 3.0.0
*/
public function __construct(Registry $state = null)
{
// Setup the model.
$this->state = isset($state) ? $state : $this->loadState();
}
/**
* Get the model state.
*
* @return Registry The state object.
*
* @since 3.0.0
*/
public function getState()
{
return $this->state;
}
/**
* Set the model state.
*
* @param Registry $state The state object.
*
* @return void
*
* @since 3.0.0
*/
public function setState(Registry $state)
{
$this->state = $state;
}
/**
* Load the model state.
*
* @return Registry The state object.
*
* @since 3.0.0
*/
protected function loadState()
{
return new Registry;
}
}
database.php 0000604 00000002735 15245561006 0007030 0 ustar 00 <?php
/**
* @package Joomla.Platform
* @subpackage Model
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE
*/
defined('JPATH_PLATFORM') or die;
use Joomla\Registry\Registry;
/**
* Joomla Platform Database Model Class
*
* @since 3.0.0
* @deprecated 4.0 Use the default MVC library
*/
abstract class JModelDatabase extends JModelBase
{
/**
* The database driver.
*
* @var JDatabaseDriver
* @since 3.0.0
*/
protected $db;
/**
* Instantiate the model.
*
* @param Registry $state The model state.
* @param JDatabaseDriver $db The database adapter.
*
* @since 3.0.0
*/
public function __construct(Registry $state = null, JDatabaseDriver $db = null)
{
parent::__construct($state);
// Setup the model.
$this->db = isset($db) ? $db : $this->loadDb();
}
/**
* Get the database driver.
*
* @return JDatabaseDriver The database driver.
*
* @since 3.0.0
*/
public function getDb()
{
return $this->db;
}
/**
* Set the database driver.
*
* @param JDatabaseDriver $db The database driver.
*
* @return void
*
* @since 3.0.0
*/
public function setDb(JDatabaseDriver $db)
{
$this->db = $db;
}
/**
* Load the database driver.
*
* @return JDatabaseDriver The database driver.
*
* @since 3.0.0
*/
protected function loadDb()
{
return JFactory::getDbo();
}
}
behavior.php 0000604 00000010503 15245561374 0007063 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class. It defines the events which are
* called by a Model.
*
* @codeCoverageIgnore
* @package FrameworkOnFramework
* @since 2.1
*/
abstract class F0FModelBehavior extends F0FUtilsObservableEvent
{
/**
* This event runs before saving data in the model
*
* @param F0FModel &$model The model which calls this event
* @param array &$data The data to save
*
* @return void
*/
public function onBeforeSave(&$model, &$data)
{
}
/**
* This event runs before deleting a record in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onBeforeDelete(&$model)
{
}
/**
* This event runs before copying a record in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onBeforeCopy(&$model)
{
}
/**
* This event runs before publishing a record in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onBeforePublish(&$model)
{
}
/**
* This event runs before registering a hit on a record in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onBeforeHit(&$model)
{
}
/**
* This event runs before moving a record in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onBeforeMove(&$model)
{
}
/**
* This event runs before changing the records' order in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onBeforeReorder(&$model)
{
}
/**
* This event runs when we are building the query used to fetch a record
* list in a model
*
* @param F0FModel &$model The model which calls this event
* @param F0FDatabaseQuery &$query The query being built
*
* @return void
*/
public function onBeforeBuildQuery(&$model, &$query)
{
}
/**
* This event runs after saving a record in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onAfterSave(&$model)
{
}
/**
* This event runs after deleting a record in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onAfterDelete(&$model)
{
}
/**
* This event runs after copying a record in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onAfterCopy(&$model)
{
}
/**
* This event runs after publishing a record in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onAfterPublish(&$model)
{
}
/**
* This event runs after registering a hit on a record in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onAfterHit(&$model)
{
}
/**
* This event runs after moving a record in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onAfterMove(&$model)
{
}
/**
* This event runs after reordering records in a model
*
* @param F0FModel &$model The model which calls this event
*
* @return void
*/
public function onAfterReorder(&$model)
{
}
/**
* This event runs after we have built the query used to fetch a record
* list in a model
*
* @param F0FModel &$model The model which calls this event
* @param F0FDatabaseQuery &$query The query being built
*
* @return void
*/
public function onAfterBuildQuery(&$model, &$query)
{
}
/**
* This event runs after getting a single item
*
* @param F0FModel &$model The model which calls this event
* @param F0FTable &$record The record loaded by this model
*
* @return void
*/
public function onAfterGetItem(&$model, &$record)
{
}
}
behavior/private.php 0000604 00000004660 15245561374 0010544 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class to filter front-end access to items
* craeted by the currently logged in user only.
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FModelBehaviorPrivate extends F0FModelBehavior
{
/**
* This event runs after we have built the query used to fetch a record
* list in a model. It is used to apply automatic query filters.
*
* @param F0FModel &$model The model which calls this event
* @param F0FDatabaseQuery &$query The model which calls this event
*
* @return void
*/
public function onAfterBuildQuery(&$model, &$query)
{
// This behavior only applies to the front-end.
if (!F0FPlatform::getInstance()->isFrontend())
{
return;
}
// Get the name of the access field
$table = $model->getTable();
$createdField = $table->getColumnAlias('created_by');
// Make sure the access field actually exists
if (!in_array($createdField, $table->getKnownFields()))
{
return;
}
// Get the current user's id
$user_id = F0FPlatform::getInstance()->getUser()->id;
// And filter the query output by the user id
$db = F0FPlatform::getInstance()->getDbo();
$alias = $model->getTableAlias();
$alias = $alias ? $db->qn($alias) . '.' : '';
$query->where($alias . $db->qn($createdField) . ' = ' . $db->q($user_id));
}
/**
* The event runs after F0FModel has called F0FTable and retrieved a single
* item from the database. It is used to apply automatic filters.
*
* @param F0FModel &$model The model which was called
* @param F0FTable &$record The record loaded from the databae
*
* @return void
*/
public function onAfterGetItem(&$model, &$record)
{
if ($record instanceof F0FTable)
{
$keyName = $record->getKeyName();
if ($record->$keyName === null)
{
return;
}
$fieldName = $record->getColumnAlias('created_by');
// Make sure the field actually exists
if (!in_array($fieldName, $record->getKnownFields()))
{
return;
}
$user_id = F0FPlatform::getInstance()->getUser()->id;
if ($record->$fieldName != $user_id)
{
$record = null;
}
}
}
}
behavior/emptynonzero.php 0000604 00000001532 15245561374 0011636 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FModelBehaviorEmptynonzero extends F0FModelBehavior
{
/**
* This event runs when we are building the query used to fetch a record
* list in a model
*
* @param F0FModel &$model The model which calls this event
* @param F0FDatabaseQuery &$query The query being built
*
* @return void
*/
public function onBeforeBuildQuery(&$model, &$query)
{
$model->setState('_emptynonzero', '1');
}
}
behavior/access.php 0000604 00000004133 15245561374 0010326 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class to filter front-end access to items
* based on the viewing access levels.
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FModelBehaviorAccess extends F0FModelBehavior
{
/**
* This event runs after we have built the query used to fetch a record
* list in a model. It is used to apply automatic query filters.
*
* @param F0FModel &$model The model which calls this event
* @param F0FDatabaseQuery &$query The model which calls this event
*
* @return void
*/
public function onAfterBuildQuery(&$model, &$query)
{
// This behavior only applies to the front-end.
if (!F0FPlatform::getInstance()->isFrontend())
{
return;
}
// Get the name of the access field
$table = $model->getTable();
$accessField = $table->getColumnAlias('access');
// Make sure the field actually exists
if (!in_array($accessField, $table->getKnownFields()))
{
return;
}
$model->applyAccessFiltering(null);
}
/**
* The event runs after F0FModel has called F0FTable and retrieved a single
* item from the database. It is used to apply automatic filters.
*
* @param F0FModel &$model The model which was called
* @param F0FTable &$record The record loaded from the databae
*
* @return void
*/
public function onAfterGetItem(&$model, &$record)
{
if ($record instanceof F0FTable)
{
$fieldName = $record->getColumnAlias('access');
// Make sure the field actually exists
if (!in_array($fieldName, $record->getKnownFields()))
{
return;
}
// Get the user
$user = F0FPlatform::getInstance()->getUser();
// Filter by authorised access levels
if (!in_array($record->$fieldName, $user->getAuthorisedViewLevels()))
{
$record = null;
}
}
}
}
behavior/language.php 0000604 00000010601 15245561374 0010645 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class to filter front-end access to items
* based on the language.
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FModelBehaviorLanguage extends F0FModelBehavior
{
/**
* This event runs before we have built the query used to fetch a record
* list in a model. It is used to blacklist the language filter
*
* @param F0FModel &$model The model which calls this event
* @param F0FDatabaseQuery &$query The model which calls this event
*
* @return void
*/
public function onBeforeBuildQuery(&$model, &$query)
{
if (F0FPlatform::getInstance()->isFrontend())
{
$model->blacklistFilters('language');
}
}
/**
* This event runs after we have built the query used to fetch a record
* list in a model. It is used to apply automatic query filters.
*
* @param F0FModel &$model The model which calls this event
* @param F0FDatabaseQuery &$query The model which calls this event
*
* @return void
*/
public function onAfterBuildQuery(&$model, &$query)
{
// This behavior only applies to the front-end.
if (!F0FPlatform::getInstance()->isFrontend())
{
return;
}
// Get the name of the language field
$table = $model->getTable();
$languageField = $table->getColumnAlias('language');
// Make sure the access field actually exists
if (!in_array($languageField, $table->getKnownFields()))
{
return;
}
// Make sure it is a multilingual site and get a list of languages
$app = JFactory::getApplication();
$hasLanguageFilter = method_exists($app, 'getLanguageFilter');
if ($hasLanguageFilter)
{
$hasLanguageFilter = $app->getLanguageFilter();
}
if (!$hasLanguageFilter)
{
return;
}
$lang_filter_plugin = JPluginHelper::getPlugin('system', 'languagefilter');
$lang_filter_params = new JRegistry($lang_filter_plugin->params);
$languages = array('*');
if ($lang_filter_params->get('remove_default_prefix'))
{
// Get default site language
$lg = F0FPlatform::getInstance()->getLanguage();
$languages[] = $lg->getTag();
}
else
{
$languages[] = JFactory::getApplication()->input->getCmd('language', '*');
}
// Filter out double languages
$languages = array_unique($languages);
// And filter the query output by these languages
$db = F0FPlatform::getInstance()->getDbo();
// Alias
$alias = $model->getTableAlias();
$alias = $alias ? $db->qn($alias) . '.' : '';
$languages = array_map(array($db, 'quote'), $languages);
$query->where($alias . $db->qn($languageField) . ' IN (' . implode(',', $languages) . ')');
}
/**
* The event runs after F0FModel has called F0FTable and retrieved a single
* item from the database. It is used to apply automatic filters.
*
* @param F0FModel &$model The model which was called
* @param F0FTable &$record The record loaded from the databae
*
* @return void
*/
public function onAfterGetItem(&$model, &$record)
{
if ($record instanceof F0FTable)
{
$fieldName = $record->getColumnAlias('language');
// Make sure the field actually exists
if (!in_array($fieldName, $record->getKnownFields()))
{
return;
}
// Make sure it is a multilingual site and get a list of languages
$app = JFactory::getApplication();
$hasLanguageFilter = method_exists($app, 'getLanguageFilter');
if ($hasLanguageFilter)
{
$hasLanguageFilter = $app->getLanguageFilter();
}
if (!$hasLanguageFilter)
{
return;
}
$lang_filter_plugin = JPluginHelper::getPlugin('system', 'languagefilter');
$lang_filter_params = new JRegistry($lang_filter_plugin->params);
$languages = array('*');
if ($lang_filter_params->get('remove_default_prefix'))
{
// Get default site language
$lg = F0FPlatform::getInstance()->getLanguage();
$languages[] = $lg->getTag();
}
else
{
$languages[] = JFactory::getApplication()->input->getCmd('language', '*');
}
// Filter out double languages
$languages = array_unique($languages);
if (!in_array($record->$fieldName, $languages))
{
$record = null;
}
}
}
}
behavior/enabled.php 0000604 00000004204 15245561374 0010456 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class to filter front-end access to items
* that are enabled.
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FModelBehaviorEnabled extends F0FModelBehavior
{
/**
* This event runs after we have built the query used to fetch a record
* list in a model. It is used to apply automatic query filters.
*
* @param F0FModel &$model The model which calls this event
* @param F0FDatabaseQuery &$query The model which calls this event
*
* @return void
*/
public function onAfterBuildQuery(&$model, &$query)
{
// This behavior only applies to the front-end.
if (!F0FPlatform::getInstance()->isFrontend())
{
return;
}
// Get the name of the enabled field
$table = $model->getTable();
$enabledField = $table->getColumnAlias('enabled');
// Make sure the field actually exists
if (!in_array($enabledField, $table->getKnownFields()))
{
return;
}
// Filter by enabled fields only
$db = F0FPlatform::getInstance()->getDbo();
// Alias
$alias = $model->getTableAlias();
$alias = $alias ? $db->qn($alias) . '.' : '';
$query->where($alias . $db->qn($enabledField) . ' = ' . $db->q(1));
}
/**
* The event runs after F0FModel has called F0FTable and retrieved a single
* item from the database. It is used to apply automatic filters.
*
* @param F0FModel &$model The model which was called
* @param F0FTable &$record The record loaded from the databae
*
* @return void
*/
public function onAfterGetItem(&$model, &$record)
{
if ($record instanceof F0FTable)
{
$fieldName = $record->getColumnAlias('enabled');
// Make sure the field actually exists
if (!in_array($fieldName, $record->getKnownFields()))
{
return;
}
if ($record->$fieldName != 1)
{
$record = null;
}
}
}
}
behavior/filters.php 0000604 00000005145 15245561374 0010541 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FModelBehaviorFilters extends F0FModelBehavior
{
/**
* This event runs after we have built the query used to fetch a record
* list in a model. It is used to apply automatic query filters.
*
* @param F0FModel &$model The model which calls this event
* @param F0FDatabaseQuery &$query The model which calls this event
*
* @return void
*/
public function onAfterBuildQuery(&$model, &$query)
{
$table = $model->getTable();
$tableName = $table->getTableName();
$tableKey = $table->getKeyName();
$db = $model->getDBO();
$filterzero = $model->getState('_emptynonzero', null);
$fields = $model->getTableFields();
$backlist = $model->blacklistFilters();
foreach ($fields as $fieldname => $fieldtype)
{
if (in_array($fieldname, $backlist)) {
continue;
}
$field = new stdClass;
$field->name = $fieldname;
$field->type = $fieldtype;
$field->filterzero = $filterzero;
$filterName = ($field->name == $tableKey) ? 'id' : $field->name;
$filterState = $model->getState($filterName, null);
$field = F0FModelField::getField($field, array('dbo' => $db, 'table_alias' => $model->getTableAlias()));
if ((is_array($filterState) && (
array_key_exists('value', $filterState) ||
array_key_exists('from', $filterState) ||
array_key_exists('to', $filterState)
)) || is_object($filterState))
{
$options = new JRegistry($filterState);
}
else
{
$options = new JRegistry;
$options->set('value', $filterState);
}
$methods = $field->getSearchMethods();
$method = $options->get('method', $field->getDefaultSearchMethod());
if (!in_array($method, $methods))
{
$method = 'exact';
}
switch ($method)
{
case 'between':
case 'outside':
case 'range' :
$sql = $field->$method($options->get('from', null), $options->get('to'));
break;
case 'interval':
case 'modulo':
$sql = $field->$method($options->get('value', null), $options->get('interval'));
break;
case 'exact':
case 'partial':
case 'search':
default:
$sql = $field->$method($options->get('value', null));
break;
}
if ($sql)
{
$query->where($sql);
}
}
}
}
field.php 0000604 00000020264 15245561374 0006354 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class
*
* @package FrameworkOnFramework
* @since 2.1
*/
abstract class F0FModelField
{
protected $_db = null;
/**
* The column name of the table field
*
* @var string
*/
protected $name = '';
/**
* The column type of the table field
*
* @var string
*/
protected $type = '';
/**
* The alias of the table used for filtering
*
* @var string
*/
protected $table_alias = false;
/**
* The null value for this type
*
* @var mixed
*/
public $null_value = null;
/**
* Constructor
*
* @param F0FDatabaseDriver $db The database object
* @param object $field The field informations as taken from the db
* @param string $table_alias The table alias to use when filtering
*/
public function __construct($db, $field, $table_alias = false)
{
$this->_db = $db;
$this->name = $field->name;
$this->type = $field->type;
$this->filterzero = $field->filterzero;
$this->table_alias = $table_alias;
}
/**
* Is it a null or otherwise empty value?
*
* @param mixed $value The value to test for emptiness
*
* @return boolean
*/
public function isEmpty($value)
{
return (($value === $this->null_value) || empty($value))
&& !($this->filterzero && $value === "0");
}
/**
* Returns the default search method for a field. This always returns 'exact'
* and you are supposed to override it in specialised classes. The possible
* values are exact, partial, between and outside, unless something
* different is returned by getSearchMethods().
*
* @see self::getSearchMethods()
*
* @return string
*/
public function getDefaultSearchMethod()
{
return 'exact';
}
/**
* Return the search methods available for this field class,
*
* @return array
*/
public function getSearchMethods()
{
$ignore = array('isEmpty', 'getField', 'getFieldType', '__construct', 'getDefaultSearchMethod', 'getSearchMethods');
$class = new ReflectionClass(__CLASS__);
$methods = $class->getMethods(ReflectionMethod::IS_PUBLIC);
$tmp = array();
foreach ($methods as $method)
{
$tmp[] = $method->name;
}
$methods = $tmp;
if ($methods = array_diff($methods, $ignore))
{
return $methods;
}
return array();
}
/**
* Perform an exact match (equality matching)
*
* @param mixed $value The value to compare to
*
* @return string The SQL where clause for this search
*/
public function exact($value)
{
if ($this->isEmpty($value))
{
return '';
}
if (is_array($value))
{
$db = F0FPlatform::getInstance()->getDbo();
$value = array_map(array($db, 'quote'), $value);
return '(' . $this->getFieldName() . ' IN (' . implode(',', $value) . '))';
}
else
{
return $this->search($value, '=');
}
}
/**
* Perform a partial match (usually: search in string)
*
* @param mixed $value The value to compare to
*
* @return string The SQL where clause for this search
*/
abstract public function partial($value);
/**
* Perform a between limits match (usually: search for a value between
* two numbers or a date between two preset dates). When $include is true
* the condition tested is:
* $from <= VALUE <= $to
* When $include is false the condition tested is:
* $from < VALUE < $to
*
* @param mixed $from The lowest value to compare to
* @param mixed $to The higherst value to compare to
* @param boolean $include Should we include the boundaries in the search?
*
* @return string The SQL where clause for this search
*/
abstract public function between($from, $to, $include = true);
/**
* Perform an outside limits match (usually: search for a value outside an
* area or a date outside a preset period). When $include is true
* the condition tested is:
* (VALUE <= $from) || (VALUE >= $to)
* When $include is false the condition tested is:
* (VALUE < $from) || (VALUE > $to)
*
* @param mixed $from The lowest value of the excluded range
* @param mixed $to The higherst value of the excluded range
* @param boolean $include Should we include the boundaries in the search?
*
* @return string The SQL where clause for this search
*/
abstract public function outside($from, $to, $include = false);
/**
* Perform an interval search (usually: a date interval check)
*
* @param string $from The value to search
* @param string|array|object $interval The interval
*
* @return string The SQL where clause for this search
*/
abstract public function interval($from, $interval);
/**
* Perform a between limits match (usually: search for a value between
* two numbers or a date between two preset dates). When $include is true
* the condition tested is:
* $from <= VALUE <= $to
* When $include is false the condition tested is:
* $from < VALUE < $to
*
* @param mixed $from The lowest value to compare to
* @param mixed $to The higherst value to compare to
* @param boolean $include Should we include the boundaries in the search?
*
* @return string The SQL where clause for this search
*/
abstract public function range($from, $to, $include = true);
/**
* Perform an modulo search
*
* @param integer|float $value The starting value of the search space
* @param integer|float $interval The interval period of the search space
* @param boolean $include Should I include the boundaries in the search?
*
* @return string The SQL where clause
*/
abstract public function modulo($from, $interval, $include = true);
/**
* Return the SQL where clause for a search
*
* @param mixed $value The value to search for
* @param string $operator The operator to use
*
* @return string The SQL where clause for this search
*/
public function search($value, $operator = '=')
{
if ($this->isEmpty($value))
{
return '';
}
return '(' . $this->getFieldName() . ' ' . $operator . ' ' . $this->_db->quote($value) . ')';
}
/**
* Get the field name with the given table alias
*
* @return string The field name
*/
public function getFieldName()
{
$name = $this->_db->qn($this->name);
if ($this->table_alias)
{
$name = $this->_db->qn($this->table_alias) . '.' . $name;
}
return $name;
}
/**
* Creates a field Object based on the field column type
*
* @param object $field The field informations
* @param array $config The field configuration (like the db object to use)
*
* @return F0FModelField The Field object
*/
public static function getField($field, $config = array())
{
$type = $field->type;
$classType = self::getFieldType($type);
$className = 'F0FModelField' . $classType;
if (class_exists($className))
{
if (isset($config['dbo']))
{
$db = $config['dbo'];
}
else
{
$db = F0FPlatform::getInstance()->getDbo();
}
if (isset($config['table_alias']))
{
$table_alias = $config['table_alias'];
}
else
{
$table_alias = false;
}
$field = new $className($db, $field, $table_alias);
return $field;
}
return false;
}
/**
* Get the classname based on the field Type
*
* @param string $type The type of the field
*
* @return string the class suffix
*/
public static function getFieldType($type)
{
switch ($type)
{
case 'varchar':
case 'text':
case 'smalltext':
case 'longtext':
case 'char':
case 'mediumtext':
case 'character varying':
case 'nvarchar':
case 'nchar':
$type = 'Text';
break;
case 'date':
case 'datetime':
case 'time':
case 'year':
case 'timestamp':
case 'timestamp without time zone':
case 'timestamp with time zone':
$type = 'Date';
break;
case 'tinyint':
case 'smallint':
$type = 'Boolean';
break;
default:
$type = 'Number';
break;
}
return $type;
}
}
field/date.php 0000604 00000011673 15245561374 0007275 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FModelFieldDate extends F0FModelFieldText
{
/**
* Returns the default search method for this field.
*
* @return string
*/
public function getDefaultSearchMethod()
{
return 'exact';
}
/**
* Perform a between limits match. When $include is true
* the condition tested is:
* $from <= VALUE <= $to
* When $include is false the condition tested is:
* $from < VALUE < $to
*
* @param mixed $from The lowest value to compare to
* @param mixed $to The higherst value to compare to
* @param boolean $include Should we include the boundaries in the search?
*
* @return string The SQL where clause for this search
*/
public function between($from, $to, $include = true)
{
if ($this->isEmpty($from) || $this->isEmpty($to))
{
return '';
}
$extra = '';
if ($include)
{
$extra = '=';
}
$sql = '((' . $this->getFieldName() . ' >' . $extra . ' "' . $from . '") AND ';
$sql .= '(' . $this->getFieldName() . ' <' . $extra . ' "' . $to . '"))';
return $sql;
}
/**
* Perform an outside limits match. When $include is true
* the condition tested is:
* (VALUE <= $from) || (VALUE >= $to)
* When $include is false the condition tested is:
* (VALUE < $from) || (VALUE > $to)
*
* @param mixed $from The lowest value of the excluded range
* @param mixed $to The higherst value of the excluded range
* @param boolean $include Should we include the boundaries in the search?
*
* @return string The SQL where clause for this search
*/
public function outside($from, $to, $include = false)
{
if ($this->isEmpty($from) || $this->isEmpty($to))
{
return '';
}
$extra = '';
if ($include)
{
$extra = '=';
}
$sql = '((' . $this->getFieldName() . ' <' . $extra . ' "' . $from . '") OR ';
$sql .= '(' . $this->getFieldName() . ' >' . $extra . ' "' . $to . '"))';
return $sql;
}
/**
* Interval date search
*
* @param string $value The value to search
* @param string|array|object $interval The interval. Can be (+1 MONTH or array('value' => 1, 'unit' => 'MONTH', 'sign' => '+'))
* @param boolean $include If the borders should be included
*
* @return string the sql string
*/
public function interval($value, $interval, $include = true)
{
if ($this->isEmpty($value) || $this->isEmpty($interval))
{
return '';
}
$interval = $this->getInterval($interval);
if ($interval['sign'] == '+')
{
$function = 'DATE_ADD';
}
else
{
$function = 'DATE_SUB';
}
$extra = '';
if ($include)
{
$extra = '=';
}
$sql = '(' . $this->getFieldName() . ' >' . $extra . ' ' . $function;
$sql .= '(' . $this->getFieldName() . ', INTERVAL ' . $interval['value'] . ' ' . $interval['unit'] . '))';
return $sql;
}
/**
* Perform a between limits match. When $include is true
* the condition tested is:
* $from <= VALUE <= $to
* When $include is false the condition tested is:
* $from < VALUE < $to
*
* @param mixed $from The lowest value to compare to
* @param mixed $to The higherst value to compare to
* @param boolean $include Should we include the boundaries in the search?
*
* @return string The SQL where clause for this search
*/
public function range($from, $to, $include = true)
{
if ($this->isEmpty($from) && $this->isEmpty($to))
{
return '';
}
$extra = '';
if ($include)
{
$extra = '=';
}
if ($from)
$sql[] = '(' . $this->getFieldName() . ' >' . $extra . ' "' . $from . '")';
if ($to)
$sql[] = '(' . $this->getFieldName() . ' <' . $extra . ' "' . $to . '")';
$sql = '(' . implode(' AND ', $sql) . ')';
return $sql;
}
/**
* Parses an interval –which may be given as a string, array or object– into
* a standardised hash array that can then be used bu the interval() method.
*
* @param string|array|object $interval The interval expression to parse
*
* @return array The parsed, hash array form of the interval
*/
protected function getInterval($interval)
{
if (is_string($interval))
{
if (strlen($interval) > 2)
{
$interval = explode(" ", $interval);
$sign = ($interval[0] == '-') ? '-' : '+';
$value = (int) substr($interval[0], 1);
$interval = array(
'unit' => $interval[1],
'value' => $value,
'sign' => $sign
);
}
else
{
$interval = array(
'unit' => 'MONTH',
'value' => 1,
'sign' => '+'
);
}
}
else
{
$interval = (array) $interval;
}
return $interval;
}
}
field/boolean.php 0000604 00000001312 15245561374 0007764 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FModelFieldBoolean extends F0FModelFieldNumber
{
/**
* Is it a null or otherwise empty value?
*
* @param mixed $value The value to test for emptiness
*
* @return boolean
*/
public function isEmpty($value)
{
return is_null($value) || ($value === '');
}
}
field/number.php 0000604 00000012011 15245561374 0007633 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FModelFieldNumber extends F0FModelField
{
/**
* The partial match is mapped to an exact match
*
* @param mixed $value The value to compare to
*
* @return string The SQL where clause for this search
*/
public function partial($value)
{
return $this->exact($value);
}
/**
* Perform a between limits match. When $include is true
* the condition tested is:
* $from <= VALUE <= $to
* When $include is false the condition tested is:
* $from < VALUE < $to
*
* @param mixed $from The lowest value to compare to
* @param mixed $to The higherst value to compare to
* @param boolean $include Should we include the boundaries in the search?
*
* @return string The SQL where clause for this search
*/
public function between($from, $to, $include = true)
{
if ($this->isEmpty($from) || $this->isEmpty($to))
{
return '';
}
$extra = '';
if ($include)
{
$extra = '=';
}
$sql = '((' . $this->getFieldName() . ' >' . $extra . ' ' . $from . ') AND ';
$sql .= '(' . $this->getFieldName() . ' <' . $extra . ' ' . $to . '))';
return $sql;
}
/**
* Perform an outside limits match. When $include is true
* the condition tested is:
* (VALUE <= $from) || (VALUE >= $to)
* When $include is false the condition tested is:
* (VALUE < $from) || (VALUE > $to)
*
* @param mixed $from The lowest value of the excluded range
* @param mixed $to The higherst value of the excluded range
* @param boolean $include Should we include the boundaries in the search?
*
* @return string The SQL where clause for this search
*/
public function outside($from, $to, $include = false)
{
if ($this->isEmpty($from) || $this->isEmpty($to))
{
return '';
}
$extra = '';
if ($include)
{
$extra = '=';
}
$sql = '((' . $this->getFieldName() . ' <' . $extra . ' ' . $from . ') OR ';
$sql .= '(' . $this->getFieldName() . ' >' . $extra . ' ' . $to . '))';
return $sql;
}
/**
* Perform an interval match. It's similar to a 'between' match, but the
* from and to values are calculated based on $value and $interval:
* $value - $interval < VALUE < $value + $interval
*
* @param integer|float $value The center value of the search space
* @param integer|float $interval The width of the search space
* @param boolean $include Should I include the boundaries in the search?
*
* @return string The SQL where clause
*/
public function interval($value, $interval, $include = true)
{
if ($this->isEmpty($value))
{
return '';
}
$from = $value - $interval;
$to = $value + $interval;
$extra = '';
if ($include)
{
$extra = '=';
}
$sql = '((' . $this->getFieldName() . ' >' . $extra . ' ' . $from . ') AND ';
$sql .= '(' . $this->getFieldName() . ' <' . $extra . ' ' . $to . '))';
return $sql;
}
/**
* Perform a range limits match. When $include is true
* the condition tested is:
* $from <= VALUE <= $to
* When $include is false the condition tested is:
* $from < VALUE < $to
*
* @param mixed $from The lowest value to compare to
* @param mixed $to The higherst value to compare to
* @param boolean $include Should we include the boundaries in the search?
*
* @return string The SQL where clause for this search
*/
public function range($from, $to, $include = true)
{
if ($this->isEmpty($from) && $this->isEmpty($to))
{
return '';
}
$extra = '';
if ($include)
{
$extra = '=';
}
if ($from)
$sql[] = '(' . $this->getFieldName() . ' >' . $extra . ' ' . $from . ')';
if ($to)
$sql[] = '(' . $this->getFieldName() . ' <' . $extra . ' ' . $to . ')';
$sql = '(' . implode(' AND ', $sql) . ')';
return $sql;
}
/**
* Perform an interval match. It's similar to a 'between' match, but the
* from and to values are calculated based on $value and $interval:
* $value - $interval < VALUE < $value + $interval
*
* @param integer|float $value The starting value of the search space
* @param integer|float $interval The interval period of the search space
* @param boolean $include Should I include the boundaries in the search?
*
* @return string The SQL where clause
*/
public function modulo($value, $interval, $include = true)
{
if ($this->isEmpty($value) || $this->isEmpty($interval))
{
return '';
}
$extra = '';
if ($include)
{
$extra = '=';
}
$sql = '(' . $this->getFieldName() . ' >' . $extra . ' ' . $value . ' AND ';
$sql .= '(' . $this->getFieldName() . ' - ' . $value . ') % ' . $interval . ' = 0)';
return $sql;
}
}
field/text.php 0000604 00000006210 15245561374 0007333 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior class
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FModelFieldText extends F0FModelField
{
/**
* Constructor
*
* @param F0FDatabaseDriver $db The database object
* @param object $field The field informations as taken from the db
*/
public function __construct($db, $field, $table_alias = false)
{
parent::__construct($db, $field, $table_alias);
$this->null_value = '';
}
/**
* Returns the default search method for this field.
*
* @return string
*/
public function getDefaultSearchMethod()
{
return 'partial';
}
/**
* Perform a partial match (search in string)
*
* @param mixed $value The value to compare to
*
* @return string The SQL where clause for this search
*/
public function partial($value)
{
if ($this->isEmpty($value))
{
return '';
}
return '(' . $this->getFieldName() . ' LIKE ' . $this->_db->quote('%' . $value . '%') . ')';
}
/**
* Perform an exact match (match string)
*
* @param mixed $value The value to compare to
*
* @return string The SQL where clause for this search
*/
public function exact($value)
{
if ($this->isEmpty($value))
{
return '';
}
return '(' . $this->getFieldName() . ' LIKE ' . $this->_db->quote($value) . ')';
}
/**
* Dummy method; this search makes no sense for text fields
*
* @param mixed $from Ignored
* @param mixed $to Ignored
* @param boolean $include Ignored
*
* @return string Empty string
*/
public function between($from, $to, $include = true)
{
return '';
}
/**
* Dummy method; this search makes no sense for text fields
*
* @param mixed $from Ignored
* @param mixed $to Ignored
* @param boolean $include Ignored
*
* @return string Empty string
*/
public function outside($from, $to, $include = false)
{
return '';
}
/**
* Dummy method; this search makes no sense for text fields
*
* @param mixed $value Ignored
* @param mixed $interval Ignored
* @param boolean $include Ignored
*
* @return string Empty string
*/
public function interval($value, $interval, $include = true)
{
return '';
}
/**
* Dummy method; this search makes no sense for text fields
*
* @param mixed $from Ignored
* @param mixed $to Ignored
* @param boolean $include Ignored
*
* @return string Empty string
*/
public function range($from, $to, $include = false)
{
return '';
}
/**
* Dummy method; this search makes no sense for text fields
*
* @param mixed $from Ignored
* @param mixed $to Ignored
* @param boolean $include Ignored
*
* @return string Empty string
*/
public function modulo($from, $to, $include = false)
{
return '';
}
}
dispatcher/behavior.php 0000604 00000001002 15245561374 0011203 0 ustar 00 <?php
/**
* @package FrameworkOnFramework
* @subpackage model
* @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 model behavior dispatcher class
*
* @package FrameworkOnFramework
* @since 2.1
*/
class F0FModelDispatcherBehavior extends F0FUtilsObservableDispatcher
{
}
form.php 0000604 00000021104 15245611463 0006221 0 ustar 00 <?php
/**
* @package Joomla.Site
* @subpackage com_config
*
* @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Utilities\ArrayHelper;
/**
* Prototype form model.
*
* @see JForm
* @see JFormField
* @see JFormRule
* @since 3.2
*/
abstract class ConfigModelForm extends ConfigModelCms
{
/**
* Array of form objects.
*
* @var array
* @since 3.2
*/
protected $forms = array();
/**
* Method to checkin a row.
*
* @param integer $pk The numeric id of the primary key.
*
* @return boolean False on failure or error, true otherwise.
*
* @since 3.2
* @throws RuntimeException
*/
public function checkin($pk = null)
{
// Only attempt to check the row in if it exists.
if ($pk)
{
$user = JFactory::getUser();
// Get an instance of the row to checkin.
$table = $this->getTable();
if (!$table->load($pk))
{
throw new RuntimeException($table->getError());
}
// Check if this is the user has previously checked out the row.
if ($table->checked_out > 0 && $table->checked_out != $user->get('id') && !$user->authorise('core.admin', 'com_checkin'))
{
throw new RuntimeException($table->getError());
}
// Attempt to check the row in.
if (!$table->checkin($pk))
{
throw new RuntimeException($table->getError());
}
}
return true;
}
/**
* Method to check-out a row for editing.
*
* @param integer $pk The numeric id of the primary key.
*
* @return boolean False on failure or error, true otherwise.
*
* @since 3.2
*/
public function checkout($pk = null)
{
// Only attempt to check the row in if it exists.
if ($pk)
{
$user = JFactory::getUser();
// Get an instance of the row to checkout.
$table = $this->getTable();
if (!$table->load($pk))
{
throw new RuntimeException($table->getError());
}
// Check if this is the user having previously checked out the row.
if ($table->checked_out > 0 && $table->checked_out != $user->get('id'))
{
throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_CHECKOUT_USER_MISMATCH'));
}
// Attempt to check the row out.
if (!$table->checkout($user->get('id'), $pk))
{
throw new RuntimeException($table->getError());
}
}
return true;
}
/**
* Abstract method for getting the form from the model.
*
* @param array $data Data for the form.
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
*
* @return mixed A JForm object on success, false on failure
*
* @since 3.2
*/
abstract public function getForm($data = array(), $loadData = true);
/**
* Method to get a form object.
*
* @param string $name The name of the form.
* @param string $source The form source. Can be XML string if file flag is set to false.
* @param array $options Optional array of options for the form creation.
* @param boolean $clear Optional argument to force load a new form.
* @param string $xpath An optional xpath to search for the fields.
*
* @return mixed JForm object on success, False on error.
*
* @see JForm
* @since 3.2
*/
protected function loadForm($name, $source = null, $options = array(), $clear = false, $xpath = false)
{
// Handle the optional arguments.
$options['control'] = ArrayHelper::getValue($options, 'control', false);
// Create a signature hash.
$hash = sha1($source . serialize($options));
// Check if we can use a previously loaded form.
if (isset($this->_forms[$hash]) && !$clear)
{
return $this->_forms[$hash];
}
// Get the form.
// Register the paths for the form -- failing here
$paths = new SplPriorityQueue;
$paths->insert(JPATH_COMPONENT_ADMINISTRATOR . '/model/form', 'normal');
$paths->insert(JPATH_COMPONENT_ADMINISTRATOR . '/model/field', 'normal');
$paths->insert(JPATH_COMPONENT . '/model/form', 'normal');
$paths->insert(JPATH_COMPONENT . '/model/field', 'normal');
$paths->insert(JPATH_COMPONENT . '/model/rule', 'normal');
// Legacy support to be removed in 4.0. -- failing here
$paths->insert(JPATH_COMPONENT . '/models/forms', 'normal');
$paths->insert(JPATH_COMPONENT . '/models/fields', 'normal');
$paths->insert(JPATH_COMPONENT . '/models/rules', 'normal');
// Solution until JForm supports splqueue
JForm::addFormPath(JPATH_COMPONENT . '/models/forms');
JForm::addFieldPath(JPATH_COMPONENT . '/models/fields');
JForm::addFormPath(JPATH_COMPONENT_ADMINISTRATOR . '/model/form');
JForm::addFieldPath(JPATH_COMPONENT_ADMINISTRATOR . '/model/field');
JForm::addFormPath(JPATH_COMPONENT . '/model/form');
JForm::addFieldPath(JPATH_COMPONENT . '/model/field');
try
{
$form = JForm::getInstance($name, $source, $options, false, $xpath);
if (isset($options['load_data']) && $options['load_data'])
{
// Get the data for the form.
$data = $this->loadFormData();
}
else
{
$data = array();
}
// Allow for additional modification of the form, and events to be triggered.
// We pass the data because plugins may require it.
$this->preprocessForm($form, $data);
// Load the data into the form after the plugins have operated.
$form->bind($data);
}
catch (Exception $e)
{
JFactory::getApplication()->enqueueMessage($e->getMessage());
return false;
}
// Store the form for later.
$this->_forms[$hash] = $form;
return $form;
}
/**
* Method to get the data that should be injected in the form.
*
* @return array The default data is an empty array.
*
* @since 3.2
*/
protected function loadFormData()
{
return array();
}
/**
* Method to allow derived classes to preprocess the data.
*
* @param string $context The context identifier.
* @param mixed &$data The data to be processed. It gets altered directly.
*
* @return void
*
* @since 3.2
*/
protected function preprocessData($context, &$data)
{
// Get the dispatcher and load the users plugins.
$dispatcher = JEventDispatcher::getInstance();
JPluginHelper::importPlugin('content');
// Trigger the data preparation event.
$results = $dispatcher->trigger('onContentPrepareData', array($context, $data));
// Check for errors encountered while preparing the data.
if (count($results) > 0 && in_array(false, $results, true))
{
JFactory::getApplication()->enqueueMessage($dispatcher->getError(), 'error');
}
}
/**
* Method to allow derived classes to preprocess the form.
*
* @param JForm $form A JForm object.
* @param mixed $data The data expected for the form.
* @param string $group The name of the plugin group to import (defaults to "content").
*
* @return void
*
* @see JFormField
* @since 3.2
* @throws Exception if there is an error in the form event.
*/
protected function preprocessForm(JForm $form, $data, $group = 'content')
{
// Import the appropriate plugin group.
JPluginHelper::importPlugin($group);
// Get the dispatcher.
$dispatcher = JEventDispatcher::getInstance();
// Trigger the form preparation event.
$results = $dispatcher->trigger('onContentPrepareForm', array($form, $data));
// Check for errors encountered while preparing the form.
if (count($results) && in_array(false, $results, true))
{
// Get the last error.
$error = $dispatcher->getError();
if (!($error instanceof Exception))
{
throw new Exception($error);
}
}
}
/**
* Method to validate the form data.
*
* @param JForm $form The form to validate against.
* @param array $data The data to validate.
* @param string $group The name of the field group to validate.
*
* @return mixed Array of filtered data if valid, false otherwise.
*
* @see JFormRule
* @see JFilterInput
* @since 3.2
*/
public function validate($form, $data, $group = null)
{
// Filter and validate the form data.
$data = $form->filter($data);
$return = $form->validate($data, $group);
// Check for an error.
if ($return instanceof Exception)
{
JFactory::getApplication()->enqueueMessage($return->getMessage(), 'error');
return false;
}
// Check the validation results.
if ($return === false)
{
// Get the validation messages from the form.
foreach ($form->getErrors() as $message)
{
if ($message instanceof Exception)
{
$message = $message->getMessage();
}
JFactory::getApplication()->enqueueMessage($message, 'error');
}
return false;
}
return $data;
}
}
form/modules.xml 0000604 00000005704 15245611463 0007712 0 ustar 00 <?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset>
<field
name="id"
type="number"
label="JGLOBAL_FIELD_ID_LABEL"
description="JGLOBAL_FIELD_ID_DESC"
default="0"
readonly="true"
/>
<field
name="title"
type="text"
label="JGLOBAL_TITLE"
description="COM_MODULES_FIELD_TITLE_DESC"
maxlength="100"
required="true"
size="35"
/>
<field
name="note"
type="text"
label="COM_MODULES_FIELD_NOTE_LABEL"
description="COM_MODULES_FIELD_NOTE_DESC"
maxlength="255"
size="35"
/>
<field
name="module"
type="hidden"
label="COM_MODULES_FIELD_MODULE_LABEL"
description="COM_MODULES_FIELD_MODULE_DESC"
readonly="readonly"
size="20"
/>
<field
name="showtitle"
type="radio"
label="COM_MODULES_FIELD_SHOWTITLE_LABEL"
description="COM_MODULES_FIELD_SHOWTITLE_DESC"
class="btn-group btn-group-yesno"
default="1"
size="1"
>
<option value="1">JSHOW</option>
<option value="0">JHIDE</option>
</field>
<field
name="published"
type="radio"
label="JSTATUS"
description="COM_MODULES_FIELD_PUBLISHED_DESC"
class="btn-group"
default="1"
size="1"
>
<option value="1">JPUBLISHED</option>
<option value="0">JUNPUBLISHED</option>
<option value="-2">JTRASHED</option>
</field>
<field
name="publish_up"
type="calendar"
label="COM_MODULES_FIELD_PUBLISH_UP_LABEL"
description="COM_MODULES_FIELD_PUBLISH_UP_DESC"
filter="user_utc"
class="input-medium"
translateformat="true"
showtime="true"
size="22"
/>
<field
name="publish_down"
type="calendar"
label="COM_MODULES_FIELD_PUBLISH_DOWN_LABEL"
description="COM_MODULES_FIELD_PUBLISH_DOWN_DESC"
filter="user_utc"
class="input-medium"
translateformat="true"
showtime="true"
size="22"
/>
<field
name="client_id"
type="hidden"
label="COM_MODULES_FIELD_CLIENT_ID_LABEL"
description="COM_MODULES_FIELD_CLIENT_ID_DESC"
readonly="true"
size="1"
/>
<field
name="position"
type="moduleposition"
label="COM_MODULES_FIELD_POSITION_LABEL"
description="COM_MODULES_FIELD_POSITION_DESC"
default=""
maxlength="50"
/>
<field
name="access"
type="accesslevel"
label="JFIELD_ACCESS_LABEL"
description="JFIELD_ACCESS_DESC"
size="1"
/>
<field
name="ordering"
type="moduleorder"
label="JFIELD_ORDERING_LABEL"
description="JFIELD_ORDERING_DESC"
/>
<field
name="content"
type="editor"
label="COM_MODULES_FIELD_CONTENT_LABEL"
description="COM_MODULES_FIELD_CONTENT_DESC"
buttons="true"
class="inputbox"
filter="JComponentHelper::filterText"
hide="readmore,pagebreak"
/>
<field
name="language"
type="contentlanguage"
label="JFIELD_LANGUAGE_LABEL"
description="JFIELD_MODULE_LANGUAGE_DESC"
>
<option value="*">JALL</option>
</field>
<field name="assignment" type="hidden" />
<field name="assigned" type="hidden" />
</fieldset>
</form>
form/config.xml 0000604 00000005261 15245611463 0007505 0 ustar 00 <?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset
name="metadata"
label="COM_CONFIG_METADATA_SETTINGS">
<field
name="MetaDesc"
type="textarea"
label="COM_CONFIG_FIELD_METADESC_LABEL"
description="COM_CONFIG_FIELD_METADESC_DESC"
filter="string"
cols="60"
rows="3"
/>
<field
name="MetaKeys"
type="textarea"
label="COM_CONFIG_FIELD_METAKEYS_LABEL"
description="COM_CONFIG_FIELD_METAKEYS_DESC"
filter="string"
cols="60"
rows="3"
/>
<field
name="MetaRights"
type="textarea"
label="JFIELD_META_RIGHTS_LABEL"
description="JFIELD_META_RIGHTS_DESC"
filter="string"
cols="60"
rows="2"
/>
</fieldset>
<fieldset
name="seo"
label="CONFIG_SEO_SETTINGS_LABEL">
<field
name="sef"
type="radio"
label="COM_CONFIG_FIELD_SEF_URL_LABEL"
description="COM_CONFIG_FIELD_SEF_URL_DESC"
default="1"
class="btn-group"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="sitename_pagetitles"
type="list"
label="COM_CONFIG_FIELD_SITENAME_PAGETITLES_LABEL"
description="COM_CONFIG_FIELD_SITENAME_PAGETITLES_DESC"
default="0"
filter="integer"
>
<option value="2">COM_CONFIG_FIELD_VALUE_AFTER</option>
<option value="1">COM_CONFIG_FIELD_VALUE_BEFORE</option>
<option value="0">JNO</option>
</field>
</fieldset>
<fieldset
name="site"
label="CONFIG_SITE_SETTINGS_LABEL">
<field
name="sitename"
type="text"
label="COM_CONFIG_FIELD_SITE_NAME_LABEL"
description="COM_CONFIG_FIELD_SITE_NAME_DESC"
required="true"
filter="string"
size="50"
/>
<field
name="offline"
type="radio"
label="COM_CONFIG_FIELD_SITE_OFFLINE_LABEL"
description="COM_CONFIG_FIELD_SITE_OFFLINE_DESC"
default="0"
class="btn-group"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="access"
type="accesslevel"
label="COM_CONFIG_FIELD_DEFAULT_ACCESS_LEVEL_LABEL"
description="COM_CONFIG_FIELD_DEFAULT_ACCESS_LEVEL_DESC"
default="1"
filter="integer"
/>
<field
name="list_limit"
type="list"
label="COM_CONFIG_FIELD_DEFAULT_LIST_LIMIT_LABEL"
description="COM_CONFIG_FIELD_DEFAULT_LIST_LIMIT_DESC"
default="20"
filter="integer"
>
<option value="5">J5</option>
<option value="10">J10</option>
<option value="15">J15</option>
<option value="20">J20</option>
<option value="25">J25</option>
<option value="30">J30</option>
<option value="50">J50</option>
<option value="100">J100</option>
</field>
</fieldset>
<fieldset>
<field
name="asset_id"
type="hidden"
/>
</fieldset>
</form>
form/modules_advanced.xml 0000604 00000002050 15245611463 0011526 0 ustar 00 <?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="params">
<fieldset
name="advanced">
<field
name="module_tag"
type="moduletag"
label="COM_MODULES_FIELD_MODULE_TAG_LABEL"
description="COM_MODULES_FIELD_MODULE_TAG_DESC"
default="div"
validate="options"
/>
<field
name="bootstrap_size"
type="integer"
label="COM_MODULES_FIELD_BOOTSTRAP_SIZE_LABEL"
description="COM_MODULES_FIELD_BOOTSTRAP_SIZE_DESC"
first="0"
last="12"
step="1"
/>
<field
name="header_tag"
type="headertag"
label="COM_MODULES_FIELD_HEADER_TAG_LABEL"
description="COM_MODULES_FIELD_HEADER_TAG_DESC"
default="h3"
validate="options"
/>
<field
name="header_class"
type="text"
label="COM_MODULES_FIELD_HEADER_CLASS_LABEL"
description="COM_MODULES_FIELD_HEADER_CLASS_DESC"
/>
<field
name="style"
type="chromestyle"
label="COM_MODULES_FIELD_MODULE_STYLE_LABEL"
description="COM_MODULES_FIELD_MODULE_STYLE_DESC"
/>
</fieldset>
</fields>
</form>
form/templates.xml 0000604 00000001576 15245611463 0010243 0 ustar 00 <?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset>
<field
name="id"
type="number"
label="JGLOBAL_FIELD_ID_LABEL"
description="JGLOBAL_FIELD_ID_DESC"
id="id"
default="0"
readonly="true"
class="readonly"
/>
<field
name="template"
type="text"
label="COM_TEMPLATES_FIELD_TEMPLATE_LABEL"
description="COM_TEMPLATES_FIELD_TEMPLATE_DESC"
class="readonly"
size="30"
readonly="true"
/>
<field
name="client_id"
type="hidden"
label="COM_TEMPLATES_FIELD_CLIENT_LABEL"
description="COM_TEMPLATES_FIELD_CLIENT_DESC"
class="readonly"
default="0"
readonly="true"
/>
<field
name="title"
type="text"
label="COM_TEMPLATES_FIELD_TITLE_LABEL"
description="COM_TEMPLATES_FIELD_TITLE_DESC"
class="inputbox"
size="50"
required="true"
/>
<field name="assigned" type="hidden" />
</fieldset>
</form>
config.php 0000604 00000001631 15245611463 0006526 0 ustar 00 <?php
/**
* @package Joomla.Site
* @subpackage com_config
*
* @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Model for the global configuration
*
* @since 3.2
*/
class ConfigModelConfig extends ConfigModelForm
{
/**
* Method to get a form object.
*
* @param array $data Data for the form.
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
*
* @return mixed A JForm object on success, false on failure
*
* @since 3.2
*/
public function getForm($data = array(), $loadData = true)
{
// Get the form.
$form = $this->loadForm('com_config.config', 'config', array('control' => 'jform', 'load_data' => $loadData));
if (empty($form))
{
return false;
}
return $form;
}
}
modules.php 0000604 00000015022 15245611463 0006730 0 ustar 00 <?php
/**
* @package Joomla.Site
* @subpackage com_config
*
* @copyright (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Config Module model.
*
* @since 3.2
*/
class ConfigModelModules extends ConfigModelForm
{
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* @return void
*
* @since 3.2
*/
protected function populateState()
{
$app = JFactory::getApplication('administrator');
// Load the User state.
$pk = $app->input->getInt('id');
$state = $this->loadState();
$state->set('module.id', $pk);
$this->setState($state);
}
/**
* Method to get the record form.
*
* @param array $data Data for the form.
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
*
* @return JForm A JForm object on success, false on failure
*
* @since 3.2
*/
public function getForm($data = array(), $loadData = true)
{
// Get the form.
$form = $this->loadForm('com_config.modules', 'modules', array('control' => 'jform', 'load_data' => $loadData));
if (empty($form))
{
return false;
}
$form->setFieldAttribute('position', 'client', 'site');
return $form;
}
/**
* Method to preprocess the form
*
* @param JForm $form A form object.
* @param mixed $data The data expected for the form.
* @param string $group The name of the plugin group to import (defaults to "content").
*
* @return void
*
* @since 3.2
* @throws Exception if there is an error loading the form.
*/
protected function preprocessForm(JForm $form, $data, $group = 'content')
{
jimport('joomla.filesystem.path');
$lang = JFactory::getLanguage();
$module = $this->getState()->get('module.name');
$basePath = JPATH_BASE;
$formFile = JPath::clean($basePath . '/modules/' . $module . '/' . $module . '.xml');
// Load the core and/or local language file(s).
$lang->load($module, $basePath, null, false, true)
|| $lang->load($module, $basePath . '/modules/' . $module, null, false, true);
if (file_exists($formFile))
{
// Get the module form.
if (!$form->loadFile($formFile, false, '//config'))
{
throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
}
// Attempt to load the xml file.
if (!$xml = simplexml_load_file($formFile))
{
throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
}
}
// Load the default advanced params
JForm::addFormPath(JPATH_BASE . '/components/com_config/model/form');
$form->loadFile('modules_advanced', false);
// Trigger the default form events.
parent::preprocessForm($form, $data, $group);
}
/**
* Method to get list of module positions in current template
*
* @return array
*
* @since 3.2
*/
public function getPositions()
{
$lang = JFactory::getLanguage();
$templateName = JFactory::getApplication()->getTemplate();
// Load templateDetails.xml file
$path = JPath::clean(JPATH_BASE . '/templates/' . $templateName . '/templateDetails.xml');
$currentTemplatePositions = array();
if (file_exists($path))
{
$xml = simplexml_load_file($path);
if (isset($xml->positions[0]))
{
// Load language files
$lang->load('tpl_' . $templateName . '.sys', JPATH_BASE, null, false, true)
|| $lang->load('tpl_' . $templateName . '.sys', JPATH_BASE . '/templates/' . $templateName, null, false, true);
foreach ($xml->positions[0] as $position)
{
$value = (string) $position;
$text = preg_replace('/[^a-zA-Z0-9_\-]/', '_', 'TPL_' . strtoupper($templateName) . '_POSITION_' . strtoupper($value));
// Construct list of positions
$currentTemplatePositions[] = self::createOption($value, JText::_($text) . ' [' . $value . ']');
}
}
}
$templateGroups = array();
// Add an empty value to be able to deselect a module position
$option = self::createOption();
$templateGroups[''] = self::createOptionGroup('', array($option));
$templateGroups[$templateName] = self::createOptionGroup($templateName, $currentTemplatePositions);
// Add custom position to options
$customGroupText = JText::_('COM_MODULES_CUSTOM_POSITION');
$editPositions = true;
$customPositions = self::getActivePositions(0, $editPositions);
$templateGroups[$customGroupText] = self::createOptionGroup($customGroupText, $customPositions);
return $templateGroups;
}
/**
* Get a list of modules positions
*
* @param integer $clientId Client ID
* @param boolean $editPositions Allow to edit the positions
*
* @return array A list of positions
*
* @since 3.6.3
*/
public static function getActivePositions($clientId, $editPositions = false)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select('DISTINCT position')
->from($db->quoteName('#__modules'))
->where($db->quoteName('client_id') . ' = ' . (int) $clientId)
->order($db->quoteName('position'));
$db->setQuery($query);
try
{
$positions = $db->loadColumn();
$positions = is_array($positions) ? $positions : array();
}
catch (RuntimeException $e)
{
JError::raiseWarning(500, $e->getMessage());
return;
}
// Build the list
$options = array();
foreach ($positions as $position)
{
if (!$position && !$editPositions)
{
$options[] = JHtml::_('select.option', 'none', ':: ' . JText::_('JNONE') . ' ::');
}
else
{
$options[] = JHtml::_('select.option', $position, $position);
}
}
return $options;
}
/**
* Create and return a new Option
*
* @param string $value The option value [optional]
* @param string $text The option text [optional]
*
* @return object The option as an object (stdClass instance)
*
* @since 3.6.3
*/
private static function createOption($value = '', $text = '')
{
if (empty($text))
{
$text = $value;
}
$option = new stdClass;
$option->value = $value;
$option->text = $text;
return $option;
}
/**
* Create and return a new Option Group
*
* @param string $label Value and label for group [optional]
* @param array $options Array of options to insert into group [optional]
*
* @return array Return the new group as an array
*
* @since 3.6.3
*/
private static function createOptionGroup($label = '', $options = array())
{
$group = array();
$group['value'] = $label;
$group['text'] = $label;
$group['items'] = $options;
return $group;
}
}
templates.php 0000604 00000006112 15245611463 0007256 0 ustar 00 <?php
/**
* @package Joomla.Site
* @subpackage com_config
*
* @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Template style model.
*
* @since 3.2
*/
class ConfigModelTemplates extends ConfigModelForm
{
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* @return null
*
* @since 3.2
*/
protected function populateState()
{
$state = $this->loadState();
// Load the parameters.
$params = JComponentHelper::getParams('com_templates');
$state->set('params', $params);
$this->setState($state);
}
/**
* Method to get the record form.
*
* @param array $data An optional array of data for the form to interrogate.
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
*
* @return JForm A JForm object on success, false on failure
*
* @since 3.2
*/
public function getForm($data = array(), $loadData = true)
{
// Get the form.
$form = $this->loadForm('com_config.templates', 'templates', array('control' => 'jform', 'load_data' => $loadData));
try
{
$form = new JForm('com_config.templates');
$data = array();
$this->preprocessForm($form, $data);
// Load the data into the form
$form->bind($data);
}
catch (Exception $e)
{
JFactory::getApplication()->enqueueMessage($e->getMessage());
return false;
}
if (empty($form))
{
return false;
}
return $form;
}
/**
* Method to preprocess the form
*
* @param JForm $form A form object.
* @param mixed $data The data expected for the form.
* @param string $group Plugin group to load
*
* @return void
*
* @since 3.2
* @throws Exception if there is an error in the form event.
*/
protected function preprocessForm(JForm $form, $data, $group = 'content')
{
$lang = JFactory::getLanguage();
$template = JFactory::getApplication()->getTemplate();
jimport('joomla.filesystem.path');
// Load the core and/or local language file(s).
$lang->load('tpl_' . $template, JPATH_BASE, null, false, true)
|| $lang->load('tpl_' . $template, JPATH_BASE . '/templates/' . $template, null, false, true);
// Look for com_config.xml, which contains fields to display
$formFile = JPath::clean(JPATH_BASE . '/templates/' . $template . '/com_config.xml');
if (!file_exists($formFile))
{
// If com_config.xml not found, fall back to templateDetails.xml
$formFile = JPath::clean(JPATH_BASE . '/templates/' . $template . '/templateDetails.xml');
}
// Get the template form.
if (file_exists($formFile) && !$form->loadFile($formFile, false, '//config'))
{
throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
}
// Attempt to load the xml file.
if (!$xml = simplexml_load_file($formFile))
{
throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
}
// Trigger the default form events.
parent::preprocessForm($form, $data, $group);
}
}
cms.php 0000604 00000014060 15245611463 0006043 0 ustar 00 <?php
/**
* @package Joomla.Site
* @subpackage com_config
*
* @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Registry\Registry;
/**
* Prototype admin model.
*
* @since 3.2
*/
abstract class ConfigModelCms extends JModelDatabase
{
/**
* The model (base) name
*
* @var string
* @since 3.2
*/
protected $name;
/**
* The URL option for the component.
*
* @var string
* @since 3.2
*/
protected $option = null;
/**
* The prefix to use with controller messages.
*
* @var string
* @since 3.2
*/
protected $text_prefix = null;
/**
* Indicates if the internal state has been set
*
* @var boolean
* @since 3.2
*/
protected $__state_set = null;
/**
* Constructor
*
* @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request).
*
* @since 3.2
* @throws Exception
*/
public function __construct($config = array())
{
// Guess the option from the class name (Option)Model(View).
if (empty($this->option))
{
$r = null;
if (!preg_match('/(.*)Model/i', get_class($this), $r))
{
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500);
}
$this->option = 'com_' . strtolower($r[1]);
}
// Set the view name
if (empty($this->name))
{
if (array_key_exists('name', $config))
{
$this->name = $config['name'];
}
else
{
$this->name = $this->getName();
}
}
// Set the model state
if (array_key_exists('state', $config))
{
$this->state = $config['state'];
}
else
{
$this->state = new Registry;
}
// Set the model dbo
if (array_key_exists('dbo', $config))
{
$this->db = $config['dbo'];
}
// Register the paths for the form
$paths = $this->registerTablePaths($config);
// Set the internal state marker - used to ignore setting state from the request
if (!empty($config['ignore_request']))
{
$this->__state_set = true;
}
// Set the clean cache event
if (isset($config['event_clean_cache']))
{
$this->event_clean_cache = $config['event_clean_cache'];
}
elseif (empty($this->event_clean_cache))
{
$this->event_clean_cache = 'onContentCleanCache';
}
$state = new Registry($config);
parent::__construct($state);
}
/**
* Method to get the model 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
*
* @since 3.2
* @throws Exception
*/
public function getName()
{
if (empty($this->name))
{
$r = null;
if (!preg_match('/Model(.*)/i', get_class($this), $r))
{
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500);
}
$this->name = strtolower($r[1]);
}
return $this->name;
}
/**
* Method to get model state variables
*
* @return object The property where specified, the state object where omitted
*
* @since 3.2
*/
public function getState()
{
if (!$this->__state_set)
{
// Protected method to auto-populate the model state.
$this->populateState();
// Set the model state set flag to true.
$this->__state_set = true;
}
return $this->state;
}
/**
* Method to register paths for tables
*
* @param array $config Configuration array
*
* @return object The property where specified, the state object where omitted
*
* @since 3.2
*/
public function registerTablePaths($config = array())
{
// Set the default view search path
if (array_key_exists('table_path', $config))
{
$this->addTablePath($config['table_path']);
}
elseif (defined('JPATH_COMPONENT_ADMINISTRATOR'))
{
// Register the paths for the form
$paths = new SplPriorityQueue;
$paths->insert(JPATH_COMPONENT_ADMINISTRATOR . '/table', 'normal');
// For legacy purposes. Remove for 4.0
$paths->insert(JPATH_COMPONENT_ADMINISTRATOR . '/tables', 'normal');
}
}
/**
* Clean the cache
*
* @param string $group The cache group
* @param integer $clientId The ID of the client
*
* @return void
*
* @since 3.2
*/
protected function cleanCache($group = null, $clientId = 0)
{
$conf = JFactory::getConfig();
$dispatcher = JEventDispatcher::getInstance();
$options = array(
'defaultgroup' => $group ?: (isset($this->option) ? $this->option : JFactory::getApplication()->input->get('option')),
'cachebase' => $clientId ? JPATH_ADMINISTRATOR . '/cache' : $conf->get('cache_path', JPATH_SITE . '/cache'));
$cache = JCache::getInstance('callback', $options);
$cache->clean();
// Trigger the onContentCleanCache event.
$dispatcher->trigger($this->event_clean_cache, $options);
}
/**
* Method to auto-populate the model state.
*
* This method should only be called once per instantiation and is designed
* to be called on the first call to the getState() method unless the model
* configuration flag to ignore the request is set.
*
* @return void
*
* @note Calling getState in this method will result in recursion.
* @since 3.2
*/
protected function populateState()
{
$this->loadState();
}
/**
* Method to test whether a record can be deleted.
*
* @param object $record A record object.
*
* @return boolean True if allowed to delete the record. Defaults to the permission set in the component.
*
* @since 3.2
*/
protected function canDelete($record)
{
if (empty($record->id) || $record->published != -2)
{
return false;
}
return JFactory::getUser()->authorise('core.delete', $this->option);
}
/**
* Method to test whether a record can have its state changed.
*
* @param object $record A record object.
*
* @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component.
*
* @since 3.2
*/
protected function canEditState($record)
{
return JFactory::getUser()->authorise('core.edit.state', $this->option);
}
}