10 defined(
'JPATH_PLATFORM') or die;
12 jimport('joomla.filesystem.path');
33 private static $_includePaths = array();
49 protected $_tbl_key =
'';
57 protected $_tbl_keys = array();
73 protected $_trackAssets =
false;
89 protected $_locked =
false;
97 protected $_autoincrement =
true;
121 $this->_tbl = $table;
128 elseif (is_object($key))
133 $this->_tbl_keys = $key;
135 if (count($key) == 1)
137 $this->_autoincrement =
true;
141 $this->_autoincrement =
false;
145 $this->_tbl_key = $this->getKeyName();
150 $fields = $this->getFields();
154 foreach ($fields as $name => $v)
157 if (!property_exists($this, $name))
165 if (property_exists($this,
'asset_id'))
167 $this->_trackAssets =
true;
171 if (property_exists($this,
'access'))
179 JObserverMapper::attachAllObservers($this);
196 $this->_observers->attachObserver($observer);
208 public function getObserverOfClass($observerClass)
210 return $this->_observers->getObserverOfClass($observerClass);
221 public function getFields()
223 static $cache = null;
229 $fields = $this->_db->getTableColumns($name,
false);
233 throw new UnexpectedValueException(sprintf(
'No columns found for %s table', $name));
256 public static function getInstance($type, $prefix =
'JTable', $config = array())
259 $type = preg_replace(
'/[^A-Z0-9_\.-]/i',
'', $type);
260 $tableClass = $prefix . ucfirst($type);
263 if (!class_exists($tableClass))
266 $path =
JPath::find(self::addIncludePath(), strtolower($type) .
'.php');
274 if (!class_exists($tableClass))
294 return new $tableClass($db);
308 public static function addIncludePath($path = null)
311 if (empty(self::$_includePaths))
313 self::$_includePaths = array(__DIR__);
317 settype($path,
'array');
323 foreach ($path as $dir)
329 if (!in_array($dir, self::$_includePaths))
331 array_unshift(self::$_includePaths, $dir);
336 return self::$_includePaths;
348 protected function _getAssetName()
352 foreach ($this->_tbl_keys as $k)
354 $keys[] = (int) $this->$k;
357 return $this->_tbl .
'.' . implode(
'.', $keys);
372 protected function _getAssetTitle()
374 return $this->_getAssetName();
391 protected function _getAssetParentId(
JTable $table = null, $id = null)
394 $assets = self::getInstance(
'Asset',
'JTable', array(
'dbo' => $this->getDbo()));
395 $rootId = $assets->getRootId();
415 public function appendPrimaryKeys($query, $pk = null)
419 foreach ($this->_tbl_keys as $k)
421 $query->where($this->_db->quoteName($k) .
' = ' . $this->_db->quote($this->$k));
428 $pk = array($this->_tbl_key => $pk);
433 foreach ($this->_tbl_keys AS $k)
435 $query->where($this->_db->quoteName($k) .
' = ' . $this->_db->quote($pk->$k));
449 public function getTableName()
464 public function getKeyName($multiple =
false)
467 if (count($this->_tbl_keys))
472 return $this->_tbl_keys;
477 return $this->_tbl_keys[0];
492 public function getDbo()
523 public function setRules($input)
527 $this->_rules = $input;
531 $this->_rules =
new JAccessRules($input);
542 public function getRules()
544 return $this->_rules;
557 public function reset()
560 foreach ($this->getFields() as $k => $v)
563 if (!in_array($k, $this->_tbl_keys) && (strpos($k,
'_') !== 0))
565 $this->$k = $v->Default;
570 $this->_errors = array();
587 public function bind($src, $ignore = array())
590 if (!is_object($src) && !is_array($src))
592 throw new InvalidArgumentException(sprintf(
'%s::bind(*%s*)', get_class($this), gettype($src)));
598 $src = get_object_vars($src);
602 if (!is_array($ignore))
604 $ignore = explode(
' ', $ignore);
608 foreach ($this->getProperties() as $k => $v)
611 if (!in_array($k, $ignore))
615 $this->$k = $src[$k];
639 public function load($keys = null, $reset =
true)
642 $this->_observers->update(
'onBeforeLoad', array($keys, $reset));
650 foreach ($this->_tbl_keys as $key)
652 $empty = $empty && empty($this->$key);
653 $keys[$key] = $this->$key;
662 elseif (!is_array($keys))
665 $keyCount = count($this->_tbl_keys);
671 throw new InvalidArgumentException(
'Table has multiple primary keys specified, only one primary key value provided.');
673 $keys = array($this->getKeyName() => $keys);
677 throw new RuntimeException(
'No table keys defined.');
687 $query = $this->_db->getQuery(
true)
690 $fields = array_keys($this->getProperties());
692 foreach ($keys as $field => $value)
695 if (!in_array($field, $fields))
697 throw new UnexpectedValueException(sprintf(
'Missing field in database: %s   %s.', get_class($this), $field));
700 $query->where($this->_db->quoteName($field) .
' = ' . $this->_db->quote($value));
703 $this->_db->setQuery($query);
705 $row = $this->_db->loadAssoc();
715 $result = $this->bind($row);
719 $this->_observers->update(
'onAfterLoad', array(&$result, $row));
735 public function check()
754 public function store($updateNulls =
false)
756 $k = $this->_tbl_keys;
759 $this->_observers->update(
'onBeforeStore', array($updateNulls, $k));
763 if (!empty($this->asset_id))
765 $currentAssetId = $this->asset_id;
769 if ($this->_trackAssets)
771 unset($this->asset_id);
775 if ($this->hasPrimaryKey())
777 $result = $this->_db->updateObject($this->_tbl, $this, $this->_tbl_keys, $updateNulls);
781 $result = $this->_db->insertObject($this->_tbl, $this, $this->_tbl_keys[0]);
785 if ($this->_trackAssets)
795 $parentId = $this->_getAssetParentId();
796 $name = $this->_getAssetName();
797 $title = $this->_getAssetTitle();
799 $asset = self::getInstance(
'Asset',
'JTable', array(
'dbo' => $this->getDbo()));
800 $asset->loadByName($name);
803 $this->asset_id = $asset->id;
806 $error = $asset->getError();
810 $this->setError($error);
817 if (empty($this->asset_id) || $asset->parent_id != $parentId)
819 $asset->setLocation($parentId,
'last-child');
823 $asset->parent_id = $parentId;
824 $asset->name = $name;
825 $asset->title = $title;
829 $asset->rules = (string) $this->_rules;
832 if (!$asset->check() || !$asset->store($updateNulls))
834 $this->setError($asset->getError());
841 if (empty($this->asset_id) || ($currentAssetId != $this->asset_id && !empty($this->asset_id)))
844 $this->asset_id = (int) $asset->id;
846 $query = $this->_db->getQuery(
true)
847 ->update($this->_db->quoteName($this->_tbl))
848 ->
set(
'asset_id = ' . (
int) $this->asset_id);
849 $this->appendPrimaryKeys($query);
850 $this->_db->setQuery($query)->execute();
857 $this->_observers->update(
'onAfterStore', array(&$result));
880 public function save($src, $orderingFilter =
'', $ignore =
'')
883 if (!$this->bind($src, $ignore))
901 if (!$this->checkin())
909 $filterValue = $this->$orderingFilter;
910 $this->reorder($orderingFilter ? $this->_db->quoteName($orderingFilter) .
' = ' . $this->_db->quote($filterValue) :
'');
930 public function delete($pk = null)
936 foreach ($this->_tbl_keys AS $key)
938 $pk[$key] = $this->$key;
941 elseif (!is_array($pk))
943 $pk = array($this->_tbl_key => $pk);
946 foreach ($this->_tbl_keys AS $key)
948 $pk[$key] = is_null($pk[$key]) ? $this->$key : $pk[$key];
950 if ($pk[$key] === null)
952 throw new UnexpectedValueException(
'Null primary key not allowed.');
954 $this->$key = $pk[$key];
958 $this->_observers->update(
'onBeforeDelete', array($pk));
961 if ($this->_trackAssets)
964 $name = $this->_getAssetName();
965 $asset = self::getInstance(
'Asset');
967 if ($asset->loadByName($name))
969 if (!$asset->delete())
971 $this->setError($asset->getError());
978 $this->setError($asset->getError());
985 $query = $this->_db->getQuery(
true)
986 ->delete($this->_tbl);
987 $this->appendPrimaryKeys($query, $pk);
989 $this->_db->setQuery($query);
992 $this->_db->execute();
995 $this->_observers->update(
'onAfterDelete', array($pk));
1018 public function checkOut($userId, $pk = null)
1021 if (!property_exists($this,
'checked_out') || !property_exists($this,
'checked_out_time'))
1030 foreach ($this->_tbl_keys AS $key)
1032 $pk[$key] = $this->$key;
1035 elseif (!is_array($pk))
1037 $pk = array($this->_tbl_key => $pk);
1040 foreach ($this->_tbl_keys AS $key)
1042 $pk[$key] = is_null($pk[$key]) ? $this->$key : $pk[$key];
1044 if ($pk[$key] === null)
1046 throw new UnexpectedValueException(
'Null primary key not allowed.');
1054 $query = $this->_db->getQuery(
true)
1055 ->update($this->_tbl)
1056 ->set($this->_db->quoteName(
'checked_out') .
' = ' . (int) $userId)
1057 ->set($this->_db->quoteName(
'checked_out_time') .
' = ' . $this->_db->quote($time));
1058 $this->appendPrimaryKeys($query, $pk);
1059 $this->_db->setQuery($query);
1060 $this->_db->execute();
1063 $this->checked_out = (int) $userId;
1064 $this->checked_out_time = $time;
1081 public function checkIn($pk = null)
1084 if (!property_exists($this,
'checked_out') || !property_exists($this,
'checked_out_time'))
1093 foreach ($this->_tbl_keys AS $key)
1095 $pk[$this->$key] = $this->$key;
1098 elseif (!is_array($pk))
1100 $pk = array($this->_tbl_key => $pk);
1103 foreach ($this->_tbl_keys AS $key)
1105 $pk[$key] = empty($pk[$key]) ? $this->$key : $pk[$key];
1107 if ($pk[$key] === null)
1109 throw new UnexpectedValueException(
'Null primary key not allowed.');
1114 $query = $this->_db->getQuery(
true)
1115 ->update($this->_tbl)
1116 ->set($this->_db->quoteName(
'checked_out') .
' = 0')
1117 ->
set($this->_db->quoteName(
'checked_out_time') .
' = ' . $this->_db->quote($this->_db->getNullDate()));
1118 $this->appendPrimaryKeys($query, $pk);
1119 $this->_db->setQuery($query);
1122 $this->_db->execute();
1125 $this->checked_out = 0;
1126 $this->checked_out_time =
'';
1138 public function hasPrimaryKey()
1140 if ($this->_autoincrement)
1144 foreach ($this->_tbl_keys as $key)
1146 $empty = $empty && empty($this->$key);
1151 $query = $this->_db->getQuery(
true)
1152 ->select(
'COUNT(*)')
1153 ->from($this->_tbl);
1154 $this->appendPrimaryKeys($query);
1156 $this->_db->setQuery($query);
1157 $count = $this->_db->loadResult();
1183 public function hit($pk = null)
1186 if (!property_exists($this,
'hits'))
1195 foreach ($this->_tbl_keys AS $key)
1197 $pk[$key] = $this->$key;
1200 elseif (!is_array($pk))
1202 $pk = array($this->_tbl_key => $pk);
1205 foreach ($this->_tbl_keys AS $key)
1207 $pk[$key] = is_null($pk[$key]) ? $this->$key : $pk[$key];
1209 if ($pk[$key] === null)
1211 throw new UnexpectedValueException(
'Null primary key not allowed.');
1216 $query = $this->_db->getQuery(
true)
1217 ->update($this->_tbl)
1218 ->set($this->_db->quoteName(
'hits') .
' = (' . $this->_db->quoteName(
'hits') .
' + 1)');
1219 $this->appendPrimaryKeys($query, $pk);
1220 $this->_db->setQuery($query);
1221 $this->_db->execute();
1244 public function isCheckedOut($with = 0, $against = null)
1247 if (isset($this) && ($this instanceof
JTable) && is_null($against))
1249 $against = $this->
get(
'checked_out');
1253 if (!$against || ($against == $with))
1259 $db->setQuery(
'SELECT COUNT(userid) FROM ' . $db->quoteName(
'#__session') .
' WHERE ' . $db->quoteName(
'userid') .
' = ' . (int) $against);
1260 $checkedOut = (boolean) $db->loadResult();
1278 public function getNextOrder($where =
'')
1281 if (!property_exists($this,
'ordering'))
1283 throw new UnexpectedValueException(sprintf(
'%s does not support ordering.', get_class($this)));
1287 $query = $this->_db->getQuery(
true)
1288 ->select(
'MAX(ordering)')
1289 ->from($this->_tbl);
1293 $query->where($where);
1296 $this->_db->setQuery($query);
1297 $max = (int) $this->_db->loadResult();
1312 public function getPrimaryKey(array $keys = array())
1314 foreach ($this->_tbl_keys as $key)
1316 if (!isset($keys[$key]))
1318 if (!empty($this->$key))
1320 $keys[$key] = $this->$key;
1340 public function reorder($where =
'')
1343 if (!property_exists($this,
'ordering'))
1345 throw new UnexpectedValueException(sprintf(
'%s does not support ordering.', get_class($this)));
1348 $k = $this->_tbl_key;
1351 $query = $this->_db->getQuery(
true)
1352 ->select(implode(
',', $this->_tbl_keys) .
', ordering')
1354 ->where(
'ordering >= 0')
1355 ->order(
'ordering');
1360 $query->where($where);
1363 $this->_db->setQuery($query);
1364 $rows = $this->_db->loadObjectList();
1367 foreach ($rows as $i => $row)
1370 if ($row->ordering >= 0)
1373 if ($row->ordering != $i + 1)
1377 ->update($this->_tbl)
1378 ->set(
'ordering = ' . ($i + 1));
1379 $this->appendPrimaryKeys($query, $row);
1380 $this->_db->setQuery($query);
1381 $this->_db->execute();
1403 public function move($delta, $where =
'')
1406 if (!property_exists($this,
'ordering'))
1408 throw new UnexpectedValueException(sprintf(
'%s does not support ordering.', get_class($this)));
1417 $k = $this->_tbl_key;
1419 $query = $this->_db->getQuery(
true);
1422 $query->select(implode(
',', $this->_tbl_keys) .
', ordering')
1423 ->from($this->_tbl);
1428 $query->where(
'ordering < ' . (
int) $this->ordering)
1429 ->order(
'ordering DESC');
1434 $query->where(
'ordering > ' . (
int) $this->ordering)
1435 ->order(
'ordering ASC');
1441 $query->where($where);
1445 $this->_db->setQuery($query, 0, 1);
1446 $row = $this->_db->loadObject();
1453 ->update($this->_tbl)
1454 ->set(
'ordering = ' . (
int) $row->ordering);
1455 $this->appendPrimaryKeys($query);
1456 $this->_db->setQuery($query);
1457 $this->_db->execute();
1461 ->update($this->_tbl)
1462 ->set(
'ordering = ' . (
int) $this->ordering);
1463 $this->appendPrimaryKeys($query, $row);
1464 $this->_db->setQuery($query);
1465 $this->_db->execute();
1468 $this->ordering = $row->ordering;
1474 ->update($this->_tbl)
1475 ->set(
'ordering = ' . (
int) $this->ordering);
1476 $this->appendPrimaryKeys($query);
1477 $this->_db->setQuery($query);
1478 $this->_db->execute();
1499 public function publish($pks = null, $state = 1, $userId = 0)
1501 $k = $this->_tbl_keys;
1505 foreach ($pks AS $key => $pk)
1509 $pks[$key] = array($this->_tbl_key => $pk);
1514 $userId = (int) $userId;
1515 $state = (int) $state;
1522 foreach ($this->_tbl_keys AS $key)
1526 $pk[$this->$key] = $this->$key;
1538 foreach ($pks AS $pk)
1541 $query = $this->_db->getQuery(
true)
1542 ->update($this->_tbl)
1543 ->set(
'published = ' . (
int) $state);
1546 if (property_exists($this,
'checked_out') || property_exists($this,
'checked_out_time'))
1548 $query->where(
'(checked_out = 0 OR checked_out = ' . (
int) $userId .
')');
1557 $this->appendPrimaryKeys($query, $pk);
1559 $this->_db->setQuery($query);
1560 $this->_db->execute();
1563 if ($checkin && (count($pks) == $this->_db->getAffectedRows()))
1565 $this->checkin($pk);
1570 foreach ($this->_tbl_keys AS $key)
1572 if ($this->$key != $pk[$key])
1580 $this->published = $state;
1584 $this->setError(
'');
1597 protected function _lock()
1599 $this->_db->lockTable($this->_tbl);
1600 $this->_locked =
true;
1612 protected function _unlock()
1614 $this->_db->unlockTables();
1615 $this->_locked =
false;