<?php
/**
* Kunena Component
* @package Kunena.Framework
* @subpackage Tables
*
* @copyright (C) 2008 - 2014 Kunena Team. All rights reserved.
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
* @link http://www.kunena.org
**/
defined ( '_JEXEC' ) or die ();
abstract class KunenaTable extends JTable {
protected $_exists = false;
public function exists($exists = null) {
$return = $this->_exists;
if ($exists !== null) $this->_exists = $exists;
return $return;
}
public function load($keys = null, $reset = true) {
// Implement JObservableInterface: Pre-processing by observers
// TODO: remove if when we're only supporting J!3.5+.
if (isset($this->_observers)) $this->_observers->update('onBeforeLoad', array($keys, $reset));
// Workaround Joomla 3.2 change.
// TODO: remove check when we're only supporting J!3.5+.
$tbl_keys = isset($this->_tbl_keys) ? $this->_tbl_keys : (array) $this->_tbl_key;
if (empty($keys)) {
$empty = true;
$keys = array();
// If empty, use the value of the current key
foreach ($tbl_keys as $key) {
$empty = $empty && empty($this->$key);
$keys[$key] = $this->$key;
}
// If empty primary key there's is no need to load anything
if ($empty) {
return false;
}
} elseif (!is_array($keys)) {
// Load by primary key.
$keyCount = count($tbl_keys);
if (!$keyCount) {
throw new RuntimeException('No table keys defined.');
} elseif ($keyCount > 1) {
throw new InvalidArgumentException('Table has multiple primary keys specified, only one primary key value provided.');
}
$keys = array($this->getKeyName() => $keys);
}
if ($reset) $this->reset();
// Initialise the query.
$query = $this->_db->getQuery(true)
->select('*')
->from($this->_tbl);
$fields = array_keys($this->getProperties());
foreach ($keys as $field => $value)
{
// Check that $field is in the table.
if (!in_array($field, $fields))
{
throw new UnexpectedValueException(sprintf('Missing field in database: %s   %s.', get_class($this), $field));
}
// Add the search tuple to the query.
$query->where($this->_db->quoteName($field) . ' = ' . $this->_db->quote($value));
}
$this->_db->setQuery($query);
$row = $this->_db->loadAssoc();
if ($this->_db->getErrorNum()) {
throw new RuntimeException($this->_db->getErrorMsg(), $this->_db->getErrorNum());
}
if (empty($row)) {
// Check that we have a result.
$result = false;
} else {
// Bind the object with the row and return.
$result = $this->_exists = $this->bind($row);
}
// Implement JObservableInterface: Post-processing by observers
// TODO: remove if when we're only supporting J!3.5+.
if (isset($this->_observers)) $this->_observers->update('onAfterLoad', array(&$result, $row));
// Bind the object with the row and return.
return $result;
}
public function store($updateNulls = false) {
// Workaround Joomla 3.2 change.
// TODO: remove check when we're only supporting J!3.5+.
$k = isset($this->_tbl_keys) ? $this->_tbl_keys : (array) $this->_tbl_key;
// Implement JObservableInterface: Pre-processing by observers
// TODO: remove if when we're only supporting J!3.5+.
if (isset($this->_observers)) $this->_observers->update('onBeforeStore', array($updateNulls, $k));
if ($this->exists()) {
$result = $this->updateObject($updateNulls);
} else {
$result = $this->insertObject();
}
if (!$result) {
$this->setError(get_class($this) . '::store() failed - ' . $this->_db->getErrorMsg());
return false;
}
$this->_exists = true;
// Implement JObservableInterface: Post-processing by observers
// TODO: remove if when we're only supporting J!3.5+.
if (isset($this->_observers)) $this->_observers->update('onAfterStore', array(&$result));
return true;
}
/**
* Inserts a row into a table based on an object's properties.
*
* @return boolean True on success.
*
* @throws RuntimeException
*/
protected function insertObject()
{
$fields = array();
$values = array();
// Workaround Joomla 3.2 change.
// TODO: remove check when we're only supporting J!3.5+.
$tbl_keys = isset($this->_tbl_keys) ? $this->_tbl_keys : (array) $this->_tbl_key;
// Iterate over the object variables to build the query fields and values.
foreach (get_object_vars($this) as $k => $v)
{
// Only process non-null scalars.
if (is_array($v) or is_object($v) or $v === null)
{
continue;
}
// Ignore any internal fields.
if ($k[0] == '_')
{
continue;
}
// Prepare and sanitize the fields and values for the database query.
$fields[] = $this->_db->quoteName($k);
$values[] = $this->_db->quote($v);
}
// Create the base insert statement.
$query = $this->_db->getQuery(true)
->insert($this->_db->quoteName($this->_tbl))
->columns($fields)
->values(implode(',', $values));
// Set the query and execute the insert.
$this->_db->setQuery($query);
if (!$this->_db->execute())
{
return false;
}
// Update the primary key if it exists.
$id = $this->_db->insertid();
if (count($tbl_keys) == 1 && $id)
{
$key = reset($tbl_keys);
$this->$key = $id;
}
return true;
}
/**
* Updates a row in a table based on an object's properties.
*
* @param boolean $nulls True to update null fields or false to ignore them.
*
* @return boolean True on success.
*
* @throws RuntimeException
*/
public function updateObject($nulls = false)
{
$fields = array();
$where = array();
// Workaround Joomla 3.2 change.
// TODO: remove check when we're only supporting J!3.5+.
$tbl_keys = isset($this->_tbl_keys) ? $this->_tbl_keys : (array) $this->_tbl_key;
// Create the base update statement.
$statement = 'UPDATE ' . $this->_db->quoteName($this->_tbl) . ' SET %s WHERE %s';
// Iterate over the object variables to build the query fields/value pairs.
foreach (get_object_vars($this) as $k => $v)
{
// Only process scalars that are not internal fields.
if (is_array($v) or is_object($v) or $k[0] == '_')
{
continue;
}
// Set the primary key to the WHERE clause instead of a field to update.
if (in_array($k, $tbl_keys))
{
$where[] = $this->_db->quoteName($k) . '=' . $this->_db->quote($v);
continue;
}
// Prepare and sanitize the fields and values for the database query.
if ($v === null)
{
// If the value is null and we want to update nulls then set it.
if ($nulls)
{
$val = 'NULL';
}
// If the value is null and we do not want to update nulls then ignore this field.
else
{
continue;
}
}
// The field is not null so we prep it for update.
else
{
$val = $this->_db->quote($v);
}
// Add the field to be updated.
$fields[] = $this->_db->quoteName($k) . '=' . $val;
}
// We don't have any fields to update.
if (empty($fields))
{
return true;
}
// Set the query and execute the update.
$this->_db->setQuery(sprintf($statement, implode(",", $fields), implode(' AND ', $where)));
return $this->_db->execute();
}
public function delete($pk = null)
{
// Workaround Joomla 3.2 change.
// TODO: remove check when we're only supporting J!3.5+.
$tbl_keys = isset($this->_tbl_keys) ? $this->_tbl_keys : (array) $this->_tbl_key;
if (is_null($pk)) {
$pk = array();
foreach ($tbl_keys AS $key) {
$pk[$key] = $this->$key;
}
} elseif (!is_array($pk)) {
$key = reset($tbl_keys);
$pk = array($key => $pk);
}
foreach ($tbl_keys AS $key) {
$pk[$key] = is_null($pk[$key]) ? $this->$key : $pk[$key];
if ($pk[$key] === null) {
throw new UnexpectedValueException('Null primary key not allowed.');
}
$this->$key = $pk[$key];
}
// Implement JObservableInterface: Pre-processing by observers
// TODO: remove if when we're only supporting J!3.5+.
if (isset($this->_observers)) $this->_observers->update('onBeforeDelete', array($pk));
// Delete the row by primary key.
$query = $this->_db->getQuery(true)
->delete($this->_tbl);
foreach ($pk as $key=>$value) {
$query->where("{$this->_db->quoteName($key)} = {$this->_db->quote($value)}");
}
$this->_db->setQuery($query);
// Check for a database error.
$this->_db->execute();
// Check for a database error.
if ($this->_db->getErrorNum()) {
throw new RuntimeException($this->_db->getErrorMsg(), $this->_db->getErrorNum());
}
// Implement JObservableInterface: Post-processing by observers
// TODO: remove if when we're only supporting J!3.5+.
if (isset($this->_observers)) $this->_observers->update('onAfterDelete', array($pk));
return true;
}
}