| Current Path : /proc/1908984/root/proc/self/root/proc/self/root/proc/thread-self/root/tmp/ |
| Current File : //proc/1908984/root/proc/self/root/proc/self/root/proc/thread-self/root/tmp/phpZ6YWqq |
<?php
/**
* @package FrameworkOnFramework
* @subpackage table
* @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('FOF_INCLUDED') or die;
/**
* Normally this shouldn't be required. Some PHP versions, however, seem to
* require this. Why? No idea whatsoever. If I remove it, FOF crashes on some
* hosts. Same PHP version on another host and no problem occurs. Any takers?
*/
if (class_exists('FOFTable', false))
{
return;
}
if (!interface_exists('JTableInterface', true))
{
interface JTableInterface {}
}
/**
* FrameworkOnFramework Table class. The Table is one part controller, one part
* model and one part data adapter. It's supposed to handle operations for single
* records.
*
* @package FrameworkOnFramework
* @since 1.0
*/
class FOFTable extends FOFUtilsObject implements JTableInterface
{
/**
* Cache array for instances
*
* @var array
*/
protected static $instances = array();
/**
* Include paths for searching for FOFTable classes.
*
* @var array
*/
protected static $_includePaths = array();
/**
* The configuration parameters array
*
* @var array
*/
protected $config = array();
/**
* Name of the database table to model.
*
* @var string
*/
protected $_tbl = '';
/**
* Name of the primary key field in the table.
*
* @var string
*/
protected $_tbl_key = '';
/**
* FOFDatabaseDriver object.
*
* @var FOFDatabaseDriver
*/
protected $_db;
/**
* Should rows be tracked as ACL assets?
*
* @var boolean
*/
protected $_trackAssets = false;
/**
* Does the resource support joomla tags?
*
* @var boolean
*/
protected $_has_tags = false;
/**
* The rules associated with this record.
*
* @var JAccessRules A JAccessRules object.
*/
protected $_rules;
/**
* Indicator that the tables have been locked.
*
* @var boolean
*/
protected $_locked = false;
/**
* If this is set to true, it triggers automatically plugin events for
* table actions
*
* @var boolean
*/
protected $_trigger_events = false;
/**
* Table alias used in queries
*
* @var string
*/
protected $_tableAlias = false;
/**
* Array with alias for "special" columns such as ordering, hits etc etc
*
* @var array
*/
protected $_columnAlias = array();
/**
* If set to true, it enabled automatic checks on fields based on columns properties
*
* @var boolean
*/
protected $_autoChecks = false;
/**
* Array with fields that should be skipped by automatic checks
*
* @var array
*/
protected $_skipChecks = array();
/**
* Does the table actually exist? We need that to avoid PHP notices on
* table-less views.
*
* @var boolean
*/
protected $_tableExists = true;
/**
* The asset key for items in this table. It's usually something in the
* com_example.viewname format. They asset name will be this key appended
* with the item's ID, e.g. com_example.viewname.123
*
* @var string
*/
protected $_assetKey = '';
/**
* The input data
*
* @var FOFInput
*/
protected $input = null;
/**
* Extended query including joins with other tables
*
* @var FOFDatabaseQuery
*/
protected $_queryJoin = null;
/**
* The prefix for the table class
*
* @var string
*/
protected $_tablePrefix = '';
/**
* The known fields for this table
*
* @var array
*/
protected $knownFields = array();
/**
* A list of table fields, keyed per table
*
* @var array
*/
protected static $tableFieldCache = array();
/**
* A list of tables in the database
*
* @var array
*/
protected static $tableCache = array();
/**
* An instance of FOFConfigProvider to provision configuration overrides
*
* @var FOFConfigProvider
*/
protected $configProvider = null;
/**
* FOFTableDispatcherBehavior for dealing with extra behaviors
*
* @var FOFTableDispatcherBehavior
*/
protected $tableDispatcher = null;
/**
* List of default behaviors to apply to the table
*
* @var array
*/
protected $default_behaviors = array('tags', 'assets');
/**
* The relations object of the table. It's lazy-loaded by getRelations().
*
* @var FOFTableRelations
*/
protected $_relations = null;
/**
* The configuration provider's key for this table, e.g. foobar.tables.bar for the #__foobar_bars table. This is set
* automatically by the constructor
*
* @var string
*/
protected $_configProviderKey = '';
/**
* The content type of the table. Required if using tags or content history behaviour
*
* @var string
*/
protected $contentType = null;
/**
* Returns a static object instance of a particular table type
*
* @param string $type The table name
* @param string $prefix The prefix of the table class
* @param array $config Optional configuration variables
*
* @return FOFTable
*/
public static function getInstance($type, $prefix = 'JTable', $config = array())
{
return self::getAnInstance($type, $prefix, $config);
}
/**
* Returns a static object instance of a particular table type
*
* @param string $type The table name
* @param string $prefix The prefix of the table class
* @param array $config Optional configuration variables
*
* @return FOFTable
*/
public static function &getAnInstance($type = null, $prefix = 'JTable', $config = array())
{
// Make sure $config is an array
if (is_object($config))
{
$config = (array) $config;
}
elseif (!is_array($config))
{
$config = array();
}
// Guess the component name
if (!array_key_exists('input', $config))
{
$config['input'] = new FOFInput;
}
if ($config['input'] instanceof FOFInput)
{
$tmpInput = $config['input'];
}
else
{
$tmpInput = new FOFInput($config['input']);
}
$option = $tmpInput->getCmd('option', '');
$tmpInput->set('option', $option);
$config['input'] = $tmpInput;
if (!in_array($prefix, array('Table', 'JTable')))
{
preg_match('/(.*)Table$/', $prefix, $m);
$option = 'com_' . strtolower($m[1]);
}
if (array_key_exists('option', $config))
{
$option = $config['option'];
}
$config['option'] = $option;
if (!array_key_exists('view', $config))
{
$config['view'] = $config['input']->getCmd('view', 'cpanel');
}
if (is_null($type))
{
if ($prefix == 'JTable')
{
$prefix = 'Table';
}
$type = $config['view'];
}
$type = preg_replace('/[^A-Z0-9_\.-]/i', '', $type);
$tableClass = $prefix . ucfirst($type);
$config['_table_type'] = $type;
$config['_table_class'] = $tableClass;
$configProvider = new FOFConfigProvider;
$configProviderKey = $option . '.views.' . FOFInflector::singularize($type) . '.config.';
if (!array_key_exists($tableClass, self::$instances))
{
if (!class_exists($tableClass))
{
$componentPaths = FOFPlatform::getInstance()->getComponentBaseDirs($config['option']);
$searchPaths = array(
$componentPaths['main'] . '/tables',
$componentPaths['admin'] . '/tables'
);
if (array_key_exists('tablepath', $config))
{
array_unshift($searchPaths, $config['tablepath']);
}
$altPath = $configProvider->get($configProviderKey . 'table_path', null);
if ($altPath)
{
array_unshift($searchPaths, $componentPaths['admin'] . '/' . $altPath);
}
$filesystem = FOFPlatform::getInstance()->getIntegrationObject('filesystem');
$path = $filesystem->pathFind(
$searchPaths, strtolower($type) . '.php'
);
if ($path)
{
require_once $path;
}
}
if (!class_exists($tableClass))
{
$tableClass = 'FOFTable';
}
$component = str_replace('com_', '', $config['option']);
$tbl_common = $component . '_';
if (!array_key_exists('tbl', $config))
{
$config['tbl'] = strtolower('#__' . $tbl_common . strtolower(FOFInflector::pluralize($type)));
}
$altTbl = $configProvider->get($configProviderKey . 'tbl', null);
if ($altTbl)
{
$config['tbl'] = $altTbl;
}
if (!array_key_exists('tbl_key', $config))
{
$keyName = FOFInflector::singularize($type);
$config['tbl_key'] = strtolower($tbl_common . $keyName . '_id');
}
$altTblKey = $configProvider->get($configProviderKey . 'tbl_key', null);
if ($altTblKey)
{
$config['tbl_key'] = $altTblKey;
}
if (!array_key_exists('db', $config))
{
$config['db'] = FOFPlatform::getInstance()->getDbo();
}
// Assign the correct table alias
if (array_key_exists('table_alias', $config))
{
$table_alias = $config['table_alias'];
}
else
{
$configProviderTableAliasKey = $option . '.tables.' . FOFInflector::singularize($type) . '.tablealias';
$table_alias = $configProvider->get($configProviderTableAliasKey, false );
}
// Can we use the FOF cache?
if (!array_key_exists('use_table_cache', $config))
{
$config['use_table_cache'] = FOFPlatform::getInstance()->isGlobalFOFCacheEnabled();
}
$alt_use_table_cache = $configProvider->get($configProviderKey . 'use_table_cache', null);
if (!is_null($alt_use_table_cache))
{
$config['use_table_cache'] = $alt_use_table_cache;
}
// Create a new table instance
$instance = new $tableClass($config['tbl'], $config['tbl_key'], $config['db'], $config);
$instance->setInput($tmpInput);
$instance->setTablePrefix($prefix);
$instance->setTableAlias($table_alias);
// Determine and set the asset key for this table
$assetKey = 'com_' . $component . '.' . strtolower(FOFInflector::singularize($type));
$assetKey = $configProvider->get($configProviderKey . 'asset_key', $assetKey);
$instance->setAssetKey($assetKey);
if (array_key_exists('trigger_events', $config))
{
$instance->setTriggerEvents($config['trigger_events']);
}
if (version_compare(JVERSION, '3.1', 'ge'))
{
if (array_key_exists('has_tags', $config))
{
$instance->setHasTags($config['has_tags']);
}
$altHasTags = $configProvider->get($configProviderKey . 'has_tags', null);
if ($altHasTags)
{
$instance->setHasTags($altHasTags);
}
}
else
{
$instance->setHasTags(false);
}
$configProviderFieldmapKey = $option . '.tables.' . FOFInflector::singularize($type) . '.field';
$aliases = $configProvider->get($configProviderFieldmapKey, $instance->_columnAlias);
$instance->_columnAlias = array_merge($instance->_columnAlias, $aliases);
self::$instances[$tableClass] = $instance;
}
return self::$instances[$tableClass];
}
/**
* Force an instance inside class cache. Setting arguments to null nukes all or part of the cache
*
* @param string|null $key TableClass to replace. Set it to null to nuke the entire cache
* @param FOFTable|null $instance Instance to replace. Set it to null to nuke $key instances
*
* @return bool Did I correctly switch the instance?
*/
public static function forceInstance($key = null, $instance = null)
{
if(is_null($key))
{
self::$instances = array();
return true;
}
elseif($key && isset(self::$instances[$key]))
{
// I'm forcing an instance, but it's not a FOFTable, abort! abort!
if(!$instance || ($instance && $instance instanceof FOFTable))
{
self::$instances[$key] = $instance;
return true;
}
}
return false;
}
/**
* Class Constructor.
*
* @param string $table Name of the database table to model.
* @param string $key Name of the primary key field in the table.
* @param FOFDatabaseDriver &$db Database driver
* @param array $config The configuration parameters array
*/
public function __construct($table, $key, &$db, $config = array())
{
$this->_tbl = $table;
$this->_tbl_key = $key;
$this->_db = $db;
// Make sure the use FOF cache information is in the config
if (!array_key_exists('use_table_cache', $config))
{
$config['use_table_cache'] = FOFPlatform::getInstance()->isGlobalFOFCacheEnabled();
}
$this->config = $config;
// Load the configuration provider
$this->configProvider = new FOFConfigProvider;
// Load the behavior dispatcher
$this->tableDispatcher = new FOFTableDispatcherBehavior;
// Initialise the table properties.
if ($fields = $this->getTableFields())
{
// Do I have anything joined?
$j_fields = $this->getQueryJoinFields();
if ($j_fields)
{
$fields = array_merge($fields, $j_fields);
}
$this->setKnownFields(array_keys($fields), true);
$this->reset();
}
else
{
$this->_tableExists = false;
}
// Get the input
if (array_key_exists('input', $config))
{
if ($config['input'] instanceof FOFInput)
{
$this->input = $config['input'];
}
else
{
$this->input = new FOFInput($config['input']);
}
}
else
{
$this->input = new FOFInput;
}
// Set the $name/$_name variable
$component = $this->input->getCmd('option', 'com_foobar');
if (array_key_exists('option', $config))
{
$component = $config['option'];
}
$this->input->set('option', $component);
// Apply table behaviors
$type = explode("_", $this->_tbl);
$type = $type[count($type) - 1];
$this->_configProviderKey = $component . '.tables.' . FOFInflector::singularize($type);
$configKey = $this->_configProviderKey . '.behaviors';
if (isset($config['behaviors']))
{
$behaviors = (array) $config['behaviors'];
}
elseif ($behaviors = $this->configProvider->get($configKey, null))
{
$behaviors = explode(',', $behaviors);
}
else
{
$behaviors = $this->default_behaviors;
}
if (is_array($behaviors) && count($behaviors))
{
foreach ($behaviors as $behavior)
{
$this->addBehavior($behavior);
}
}
// If we are tracking assets, make sure an access field exists and initially set the default.
$asset_id_field = $this->getColumnAlias('asset_id');
$access_field = $this->getColumnAlias('access');
if (in_array($asset_id_field, $this->getKnownFields()))
{
JLoader::import('joomla.access.rules');
$this->_trackAssets = true;
}
// If the access property exists, set the default.
if (in_array($access_field, $this->getKnownFields()))
{
$this->$access_field = (int) FOFPlatform::getInstance()->getConfig()->get('access');
}
$this->config = $config;
}
/**
* Replace the entire known fields array
*
* @param array $fields A simple array of known field names
* @param boolean $initialise Should we initialise variables to null?
*
* @return void
*/
public function setKnownFields($fields, $initialise = false)
{
$this->knownFields = $fields;
if ($initialise)
{
foreach ($this->knownFields as $field)
{
$this->$field = null;
}
}
}
/**
* Get the known fields array
*
* @return array
*/
public function getKnownFields()
{
return $this->knownFields;
}
/**
* Does the specified field exist?
*
* @param string $fieldName The field name to search (it's OK to use aliases)
*
* @return bool
*/
public function hasField($fieldName)
{
$search = $this->getColumnAlias($fieldName);
return in_array($search, $this->knownFields);
}
/**
* Add a field to the known fields array
*
* @param string $field The name of the field to add
* @param boolean $initialise Should we initialise the variable to null?
*
* @return void
*/
public function addKnownField($field, $initialise = false)
{
if (!in_array($field, $this->knownFields))
{
$this->knownFields[] = $field;
if ($initialise)
{
$this->$field = null;
}
}
}
/**
* Remove a field from the known fields array
*
* @param string $field The name of the field to remove
*
* @return void
*/
public function removeKnownField($field)
{
if (in_array($field, $this->knownFields))
{
$pos = array_search($field, $this->knownFields);
unset($this->knownFields[$pos]);
}
}
/**
* Adds a behavior to the table
*
* @param string $name The name of the behavior
* @param array $config Optional Behavior configuration
*
* @return boolean
*/
public function addBehavior($name, $config = array())
{
// First look for ComponentnameTableViewnameBehaviorName (e.g. FoobarTableItemsBehaviorTags)
if (isset($this->config['option']))
{
$option_name = str_replace('com_', '', $this->config['option']);
$behaviorClass = $this->config['_table_class'] . 'Behavior' . ucfirst(strtolower($name));
if (class_exists($behaviorClass))
{
$behavior = new $behaviorClass($this->tableDispatcher, $config);
return true;
}
// Then look for ComponentnameTableBehaviorName (e.g. FoobarTableBehaviorTags)
$option_name = str_replace('com_', '', $this->config['option']);
$behaviorClass = ucfirst($option_name) . 'TableBehavior' . ucfirst(strtolower($name));
if (class_exists($behaviorClass))
{
$behavior = new $behaviorClass($this->tableDispatcher, $config);
return true;
}
}
// Nothing found? Return false.
$behaviorClass = 'FOFTableBehavior' . ucfirst(strtolower($name));
if (class_exists($behaviorClass) && $this->tableDispatcher)
{
$behavior = new $behaviorClass($this->tableDispatcher, $config);
return true;
}
return false;
}
/**
* Sets the events trigger switch state
*
* @param boolean $newState The new state of the switch (what else could it be?)
*
* @return void
*/
public function setTriggerEvents($newState = false)
{
$this->_trigger_events = $newState ? true : false;
}
/**
* Gets the events trigger switch state
*
* @return boolean
*/
public function getTriggerEvents()
{
return $this->_trigger_events;
}
/**
* Gets the has tags switch state
*
* @return bool
*/
public function hasTags()
{
return $this->_has_tags;
}
/**
* Sets the has tags switch state
*
* @param bool $newState
*/
public function setHasTags($newState = false)
{
$this->_has_tags = false;
// Tags are available only in 3.1+
if (version_compare(JVERSION, '3.1', 'ge'))
{
$this->_has_tags = $newState ? true : false;
}
}
/**
* Set the class prefix
*
* @param string $prefix The prefix
*/
public function setTablePrefix($prefix)
{
$this->_tablePrefix = $prefix;
}
/**
* Sets fields to be skipped from automatic checks.
*
* @param array/string $skip Fields to be skipped by automatic checks
*
* @return void
*/
public function setSkipChecks($skip)
{
$this->_skipChecks = (array) $skip;
}
/**
* Method to load a row from the database by primary key and bind the fields
* to the FOFTable instance properties.
*
* @param mixed $keys An optional primary key value to load the row by, or an array of fields to match. If not
* set the instance property value is used.
* @param boolean $reset True to reset the default values before loading the new row.
*
* @return boolean True if successful. False if row not found.
*
* @throws RuntimeException
* @throws UnexpectedValueException
*/
public function load($keys = null, $reset = true)
{
if (!$this->_tableExists)
{
$result = false;
return $this->onAfterLoad($result);
}
if (empty($keys))
{
// If empty, use the value of the current key
$keyName = $this->_tbl_key;
if (isset($this->$keyName))
{
$keyValue = $this->$keyName;
}
else
{
$keyValue = null;
}
// If empty primary key there's is no need to load anything
if (empty($keyValue))
{
$result = true;
return $this->onAfterLoad($result);
}
$keys = array($keyName => $keyValue);
}
elseif (!is_array($keys))
{
// Load by primary key.
$keys = array($this->_tbl_key => $keys);
}
if ($reset)
{
$this->reset();
}
// Initialise the query.
$query = $this->_db->getQuery(true);
$query->select($this->_tbl . '.*');
$query->from($this->_tbl);
// Joined fields are ok, since I initialized them in the constructor
$fields = $this->getKnownFields();
foreach ($keys as $field => $value)
{
// Check that $field is in the table.
if (!in_array($field, $fields))
{
throw new UnexpectedValueException(sprintf('Missing field in table %s : %s.', $this->_tbl, $field));
}
// Add the search tuple to the query.
$query->where($this->_db->qn($this->_tbl . '.' . $field) . ' = ' . $this->_db->q($value));
}
// Do I have any joined table?
$j_query = $this->getQueryJoin();
if ($j_query)
{
if ($j_query->select && $j_query->select->getElements())
{
//$query->select($this->normalizeSelectFields($j_query->select->getElements(), true));
$query->select($j_query->select->getElements());
}
if ($j_query->join)
{
foreach ($j_query->join as $join)
{
$t = (string) $join;
// Joomla doesn't provide any access to the "name" variable, so I have to work with strings...
if (stripos($t, 'inner') !== false)
{
$query->innerJoin($join->getElements());
}
elseif (stripos($t, 'left') !== false)
{
$query->leftJoin($join->getElements());
}
elseif (stripos($t, 'right') !== false)
{
$query->rightJoin($join->getElements());
}
elseif (stripos($t, 'outer') !== false)
{
$query->outerJoin($join->getElements());
}
}
}
}
$this->_db->setQuery($query);
$row = $this->_db->loadAssoc();
// Check that we have a result.
if (empty($row))
{
$result = false;
return $this->onAfterLoad($result);
}
// Bind the object with the row and return.
$result = $this->bind($row);
$this->onAfterLoad($result);
return $result;
}
/**
* Based on fields properties (nullable column), checks if the field is required or not
*
* @return boolean
*/
public function check()
{
if (!$this->_autoChecks)
{
return true;
}
$fields = $this->getTableFields();
// No fields? Why in the hell am I here?
if(!$fields)
{
return false;
}
$result = true;
$known = $this->getKnownFields();
$skipFields[] = $this->_tbl_key;
if(in_array($this->getColumnAlias('title'), $known)
&& in_array($this->getColumnAlias('slug'), $known)) $skipFields[] = $this->getColumnAlias('slug');
if(in_array($this->getColumnAlias('hits'), $known)) $skipFields[] = $this->getColumnAlias('hits');
if(in_array($this->getColumnAlias('created_on'), $known)) $skipFields[] = $this->getColumnAlias('created_on');
if(in_array($this->getColumnAlias('created_by'), $known)) $skipFields[] = $this->getColumnAlias('created_by');
if(in_array($this->getColumnAlias('modified_on'), $known)) $skipFields[] = $this->getColumnAlias('modified_on');
if(in_array($this->getColumnAlias('modified_by'), $known)) $skipFields[] = $this->getColumnAlias('modified_by');
if(in_array($this->getColumnAlias('locked_by'), $known)) $skipFields[] = $this->getColumnAlias('locked_by');
if(in_array($this->getColumnAlias('locked_on'), $known)) $skipFields[] = $this->getColumnAlias('locked_on');
// Let's merge it with custom skips
$skipFields = array_merge($skipFields, $this->_skipChecks);
foreach ($fields as $field)
{
$fieldName = $field->Field;
if (empty($fieldName))
{
$fieldName = $field->column_name;
}
// Field is not nullable but it's null, set error
if ($field->Null == 'NO' && $this->$fieldName == '' && !in_array($fieldName, $skipFields))
{
$text = str_replace('#__', 'COM_', $this->getTableName()) . '_ERR_' . $fieldName;
$this->setError(JText::_(strtoupper($text)));
$result = false;
}
}
return $result;
}
/**
* Method to reset class properties to the defaults set in the class
* definition. It will ignore the primary key as well as any private class
* properties.
*
* @return void
*/
public function reset()
{
if (!$this->onBeforeReset())
{
return false;
}
// Get the default values for the class from the table.
$fields = $this->getTableFields();
$j_fields = $this->getQueryJoinFields();
if ($j_fields)
{
$fields = array_merge($fields, $j_fields);
}
if (is_array($fields) && !empty($fields))
{
foreach ($fields as $k => $v)
{
// If the property is not the primary key or private, reset it.
if ($k != $this->_tbl_key && (strpos($k, '_') !== 0))
{
$this->$k = $v->Default;
}
}
if (!$this->onAfterReset())
{
return false;
}
}
}
/**
* Clones the current object, after resetting it
*
* @return static
*/
public function getClone()
{
$clone = clone $this;
$clone->reset();
$key = $this->getKeyName();
$clone->$key = null;
return $clone;
}
/**
* Generic check for whether dependencies exist for this object in the db schema
*
* @param integer $oid The primary key of the record to delete
* @param array $joins Any joins to foreign table, used to determine if dependent records exist
*
* @return boolean True if the record can be deleted
*/
public function canDelete($oid = null, $joins = null)
{
$k = $this->_tbl_key;
if ($oid)
{
$this->$k = intval($oid);
}
if (is_array($joins))
{
$db = $this->_db;
$query = $db->getQuery(true)
->select($db->qn('master') . '.' . $db->qn($k))
->from($db->qn($this->_tbl) . ' AS ' . $db->qn('master'));
$tableNo = 0;
foreach ($joins as $table)
{
$tableNo++;
$query->select(
array(
'COUNT(DISTINCT ' . $db->qn('t' . $tableNo) . '.' . $db->qn($table['idfield']) . ') AS ' . $db->qn($table['idalias'])
)
);
$query->join('LEFT', $db->qn($table['name']) .
' AS ' . $db->qn('t' . $tableNo) .
' ON ' . $db->qn('t' . $tableNo) . '.' . $db->qn($table['joinfield']) .
' = ' . $db->qn('master') . '.' . $db->qn($k)
);
}
$query->where($db->qn('master') . '.' . $db->qn($k) . ' = ' . $db->q($this->$k));
$query->group($db->qn('master') . '.' . $db->qn($k));
$this->_db->setQuery((string) $query);
if (version_compare(JVERSION, '3.0', 'ge'))
{
try
{
$obj = $this->_db->loadObject();
}
catch (Exception $e)
{
$this->setError($e->getMessage());
}
}
else
{
if (!$obj = $this->_db->loadObject())
{
$this->setError($this->_db->getErrorMsg());
return false;
}
}
$msg = array();
$i = 0;
foreach ($joins as $table)
{
$k = $table['idalias'];
if ($obj->$k > 0)
{
$msg[] = JText::_($table['label']);
}
$i++;
}
if (count($msg))
{
$option = $this->input->getCmd('option', 'com_foobar');
$comName = str_replace('com_', '', $option);
$tview = str_replace('#__' . $comName . '_', '', $this->_tbl);
$prefix = $option . '_' . $tview . '_NODELETE_';
foreach ($msg as $key)
{
$this->setError(JText::_($prefix . $key));
}
return false;
}
else
{
return true;
}
}
return true;
}
/**
* Method to bind an associative array or object to the FOFTable instance.This
* method only binds properties that are publicly accessible and optionally
* takes an array of properties to ignore when binding.
*
* @param mixed $src An associative array or object to bind to the FOFTable instance.
* @param mixed $ignore An optional array or space separated list of properties to ignore while binding.
*
* @return boolean True on success.
*
* @throws InvalidArgumentException
*/
public function bind($src, $ignore = array())
{
if (!$this->onBeforeBind($src))
{
return false;
}
// If the source value is not an array or object return false.
if (!is_object($src) && !is_array($src))
{
throw new InvalidArgumentException(sprintf('%s::bind(*%s*)', get_class($this), gettype($src)));
}
// If the source value is an object, get its accessible properties.
if (is_object($src))
{
$src = get_object_vars($src);
}
// If the ignore value is a string, explode it over spaces.
if (!is_array($ignore))
{
$ignore = explode(' ', $ignore);
}
// Bind the source value, excluding the ignored fields.
foreach ($this->getKnownFields() as $k)
{
// Only process fields not in the ignore array.
if (!in_array($k, $ignore))
{
if (isset($src[$k]))
{
$this->$k = $src[$k];
}
}
}
$result = $this->onAfterBind($src);
return $result;
}
/**
* Method to store a row in the database from the FOFTable instance properties.
* If a primary key value is set the row with that primary key value will be
* updated with the instance property values. If no primary key value is set
* a new row will be inserted into the database with the properties from the
* FOFTable instance.
*
* @param boolean $updateNulls True to update fields even if they are null.
*
* @return boolean True on success.
*/
public function store($updateNulls = false)
{
if (!$this->onBeforeStore($updateNulls))
{
return false;
}
$k = $this->_tbl_key;
if ($this->$k == 0)
{
$this->$k = null;
}
// Create the object used for inserting/updating data to the database
$fields = $this->getTableFields();
$properties = $this->getKnownFields();
$keys = array();
foreach ($properties as $property)
{
// 'input' property is a reserved name
if (isset($fields[$property]))
{
$keys[] = $property;
}
}
$updateObject = array();
foreach ($keys as $key)
{
$updateObject[$key] = $this->$key;
}
$updateObject = (object)$updateObject;
/**
* While the documentation for update/insertObject and execute() say they return a boolean,
* not all of the implemtnations. Depending on the version of J! and the specific driver,
* they may return a database object, or boolean, or a mix, or toss an exception. So try/catch,
* and test for false.
*/
try
{
// If a primary key exists update the object, otherwise insert it.
if ($this->$k)
{
$result = $this->_db->updateObject($this->_tbl, $updateObject, $this->_tbl_key, $updateNulls);
}
else
{
$result = $this->_db->insertObject($this->_tbl, $updateObject, $this->_tbl_key);
}
if ($result === false)
{
$this->setError($this->_db->getErrorMsg());
return false;
}
}
catch (Exception $e)
{
$this->setError($e->getMessage());
}
$this->bind($updateObject);
if ($this->_locked)
{
$this->_unlock();
}
$result = $this->onAfterStore();
return $result;
}
/**
* Method to move a row in the ordering sequence of a group of rows defined by an SQL WHERE clause.
* Negative numbers move the row up in the sequence and positive numbers move it down.
*
* @param integer $delta The direction and magnitude to move the row in the ordering sequence.
* @param string $where WHERE clause to use for limiting the selection of rows to compact the
* ordering values.
*
* @return mixed Boolean True on success.
*
* @throws UnexpectedValueException
*/
public function move($delta, $where = '')
{
if (!$this->onBeforeMove($delta, $where))
{
return false;
}
// If there is no ordering field set an error and return false.
$ordering_field = $this->getColumnAlias('ordering');
if (!in_array($ordering_field, $this->getKnownFields()))
{
throw new UnexpectedValueException(sprintf('%s does not support ordering.', $this->_tbl));
}
// If the change is none, do nothing.
if (empty($delta))
{
$result = $this->onAfterMove();
return $result;
}
$k = $this->_tbl_key;
$row = null;
$query = $this->_db->getQuery(true);
// If the table is not loaded, return false
if (empty($this->$k))
{
return false;
}
// Select the primary key and ordering values from the table.
$query->select(array($this->_db->qn($this->_tbl_key), $this->_db->qn($ordering_field)));
$query->from($this->_tbl);
// If the movement delta is negative move the row up.
if ($delta < 0)
{
$query->where($this->_db->qn($ordering_field) . ' < ' . $this->_db->q((int) $this->$ordering_field));
$query->order($this->_db->qn($ordering_field) . ' DESC');
}
// If the movement delta is positive move the row down.
elseif ($delta > 0)
{
$query->where($this->_db->qn($ordering_field) . ' > ' . $this->_db->q((int) $this->$ordering_field));
$query->order($this->_db->qn($ordering_field) . ' ASC');
}
// Add the custom WHERE clause if set.
if ($where)
{
$query->where($where);
}
// Select the first row with the criteria.
$this->_db->setQuery($query, 0, 1);
$row = $this->_db->loadObject();
// If a row is found, move the item.
if (!empty($row))
{
// Update the ordering field for this instance to the row's ordering value.
$query = $this->_db->getQuery(true);
$query->update($this->_tbl);
$query->set($this->_db->qn($ordering_field) . ' = ' . $this->_db->q((int) $row->$ordering_field));
$query->where($this->_tbl_key . ' = ' . $this->_db->q($this->$k));
$this->_db->setQuery($query);
$this->_db->execute();
// Update the ordering field for the row to this instance's ordering value.
$query = $this->_db->getQuery(true);
$query->update($this->_tbl);
$query->set($this->_db->qn($ordering_field) . ' = ' . $this->_db->q((int) $this->$ordering_field));
$query->where($this->_tbl_key . ' = ' . $this->_db->q($row->$k));
$this->_db->setQuery($query);
$this->_db->execute();
// Update the instance value.
$this->$ordering_field = $row->$ordering_field;
}
else
{
// Update the ordering field for this instance.
$query = $this->_db->getQuery(true);
$query->update($this->_tbl);
$query->set($this->_db->qn($ordering_field) . ' = ' . $this->_db->q((int) $this->$ordering_field));
$query->where($this->_tbl_key . ' = ' . $this->_db->q($this->$k));
$this->_db->setQuery($query);
$this->_db->execute();
}
$result = $this->onAfterMove();
return $result;
}
/**
* Change the ordering of the records of the table
*
* @param string $where The WHERE clause of the SQL used to fetch the order
*
* @return boolean True is successful
*
* @throws UnexpectedValueException
*/
public function reorder($where = '')
{
if (!$this->onBeforeReorder($where))
{
return false;
}
// If there is no ordering field set an error and return false.
$order_field = $this->getColumnAlias('ordering');
if (!in_array($order_field, $this->getKnownFields()))
{
throw new UnexpectedValueException(sprintf('%s does not support ordering.', $this->_tbl_key));
}
$k = $this->_tbl_key;
// Get the primary keys and ordering values for the selection.
$query = $this->_db->getQuery(true);
$query->select($this->_tbl_key . ', ' . $this->_db->qn($order_field));
$query->from($this->_tbl);
$query->where($this->_db->qn($order_field) . ' >= ' . $this->_db->q(0));
$query->order($this->_db->qn($order_field));
// Setup the extra where and ordering clause data.
if ($where)
{
$query->where($where);
}
$this->_db->setQuery($query);
$rows = $this->_db->loadObjectList();
// Compact the ordering values.
foreach ($rows as $i => $row)
{
// Make sure the ordering is a positive integer.
if ($row->$order_field >= 0)
{
// Only update rows that are necessary.
if ($row->$order_field != $i + 1)
{
// Update the row ordering field.
$query = $this->_db->getQuery(true);
$query->update($this->_tbl);
$query->set($this->_db->qn($order_field) . ' = ' . $this->_db->q($i + 1));
$query->where($this->_tbl_key . ' = ' . $this->_db->q($row->$k));
$this->_db->setQuery($query);
$this->_db->execute();
}
}
}
$result = $this->onAfterReorder();
return $result;
}
/**
* Check out (lock) a record
*
* @param integer $userId The locking user's ID
* @param integer $oid The primary key value of the record to lock
*
* @return boolean True on success
*/
public function checkout($userId, $oid = null)
{
$fldLockedBy = $this->getColumnAlias('locked_by');
$fldLockedOn = $this->getColumnAlias('locked_on');
if (!(in_array($fldLockedBy, $this->getKnownFields())
|| in_array($fldLockedOn, $this->getKnownFields())))
{
return true;
}
$k = $this->_tbl_key;
if ($oid !== null)
{
$this->$k = $oid;
}
// No primary key defined, stop here
if (!$this->$k)
{
return false;
}
$date = FOFPlatform::getInstance()->getDate();
if (method_exists($date, 'toSql'))
{
$time = $date->toSql();
}
else
{
$time = $date->toMySQL();
}
$query = $this->_db->getQuery(true)
->update($this->_db->qn($this->_tbl))
->set(
array(
$this->_db->qn($fldLockedBy) . ' = ' . $this->_db->q((int) $userId),
$this->_db->qn($fldLockedOn) . ' = ' . $this->_db->q($time)
)
)
->where($this->_db->qn($this->_tbl_key) . ' = ' . $this->_db->q($this->$k));
$this->_db->setQuery((string) $query);
$this->$fldLockedBy = $userId;
$this->$fldLockedOn = $time;
return $this->_db->execute();
}
/**
* Check in (unlock) a record
*
* @param integer $oid The primary key value of the record to unlock
*
* @return boolean True on success
*/
public function checkin($oid = null)
{
$fldLockedBy = $this->getColumnAlias('locked_by');
$fldLockedOn = $this->getColumnAlias('locked_on');
if (!(in_array($fldLockedBy, $this->getKnownFields())
|| in_array($fldLockedOn, $this->getKnownFields())))
{
return true;
}
$k = $this->_tbl_key;
if ($oid !== null)
{
$this->$k = $oid;
}
if ($this->$k == null)
{
return false;
}
$query = $this->_db->getQuery(true)
->update($this->_db->qn($this->_tbl))
->set(
array(
$this->_db->qn($fldLockedBy) . ' = 0',
$this->_db->qn($fldLockedOn) . ' = ' . $this->_db->q($this->_db->getNullDate())
)
)
->where($this->_db->qn($this->_tbl_key) . ' = ' . $this->_db->q($this->$k));
$this->_db->setQuery((string) $query);
$this->$fldLockedBy = 0;
$this->$fldLockedOn = '';
return $this->_db->execute();
}
/**
* Is a record locked?
*
* @param integer $with The userid to preform the match with. If an item is checked
* out by this user the function will return false.
* @param integer $unused_against Junk inherited from JTable; ignore
*
* @throws UnexpectedValueException
*
* @return boolean True if the record is locked by another user
*/
public function isCheckedOut($with = 0, $unused_against = null)
{
$against = null;
$fldLockedBy = $this->getColumnAlias('locked_by');
$k = $this->_tbl_key;
// If no primary key is given, return false.
if ($this->$k === null)
{
throw new UnexpectedValueException('Null primary key not allowed.');
}
if (isset($this) && is_a($this, 'FOFTable') && !$against)
{
$against = $this->get($fldLockedBy);
}
// Item is not checked out, or being checked out by the same user
if (!$against || $against == $with)
{
return false;
}
$session = JTable::getInstance('session');
return $session->exists($against);
}
/**
* Copy (duplicate) one or more records
*
* @param integer|array $cid The primary key value (or values) or the record(s) to copy
*
* @return boolean True on success
*/
public function copy($cid = null)
{
//We have to cast the id as array, or the helper function will return an empty set
if($cid)
{
$cid = (array) $cid;
}
FOFUtilsArray::toInteger($cid);
$k = $this->_tbl_key;
if (count($cid) < 1)
{
if ($this->$k)
{
$cid = array($this->$k);
}
else
{
$this->setError("No items selected.");
return false;
}
}
$created_by = $this->getColumnAlias('created_by');
$created_on = $this->getColumnAlias('created_on');
$modified_by = $this->getColumnAlias('modified_by');
$modified_on = $this->getColumnAlias('modified_on');
$locked_byName = $this->getColumnAlias('locked_by');
$checkin = in_array($locked_byName, $this->getKnownFields());
foreach ($cid as $item)
{
// Prevent load with id = 0
if (!$item)
{
continue;
}
$this->load($item);
if