386 lines
9.0 KiB
PHP

<?php
use Joomla\CMS\Factory;
// No direct access.
defined('_JEXEC') or die;
abstract class AbstractCommonClubsModel
{
// TODO Add data validator
// TODO Make setting of values attribute fail in case of problems
// FIXME Add Joins in select statements
private $id;
private $new;
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
private $values = null;
protected function getValues($force = false)
{
if(is_null($this->values) || $force)
$this->loadDataFromDatabase();
return $this->values;
}
public function isNew()
{
return $this->new;
}
public function setValues($values, $unpack = false)
{
if($unpack)
$this->values = $this->unpackExternalReferencesFromKeys($values);
else
$this->values = $values;
}
public function applyAndMergeValues($values, $unpack = true)
{
$vals = $this->getValues();
if($unpack)
$vals = $this->packExternalReferencesAsKeys($vals);
foreach($this->getFactory()->getAttributes() as $column)
{
if(array_key_exists($column->getAlias(), $values))
{
$vals[$column->getAlias()] = $values[$column->getAlias()];
}
}
if($unpack)
$vals = $this->unpackExternalReferencesFromKeys($vals);
$this->setValues($vals, false);
}
protected function setValue($key, $value)
{
if(is_null($this->values))
$this->loadDataFromDatabase();
$this->values[$key] = $value;
}
public function markAsNew($new)
{
$this->new = $new;
}
public function fillDefaultValues()
{}
/**
* @return AbstractCommonClubsModelFactory
*/
protected abstract function getFactory();
public function save()
{
$factory = $this->getFactory();
$attribs = $factory->getAttributes();
$db = Factory::getDbo();
$q = $db->getQuery(true);
$db->transactionStart();
if($this->new)
$this->prepareInsert($attribs, $factory, $q);
else
$this->prepareUpdate($attribs, $factory, $q);
$db->setQuery($q);
$db->execute();
if($this->new)
{
$this->finishInsert($db);
}
$db->transactionCommit();
}
private function loadDataFromDatabase()
{
$factory = $this->getFactory();
$attribs = $factory->getAttributes();
$db = Factory::getDbo();
$q = $db->getQuery(true);
foreach($attribs as $a)
{
$a->select($q);
}
$q->from($factory->getTableName());
$q->where("id = {$this->id}");
$joins = $factory->getJoins();
foreach($joins as $j)
{
$j->join($q);
}
$db->setQuery($q);
$db->execute();
$values = $db->loadAssoc();
$values = $this->unpackExternalReferencesFromKeys($values);
$this->values = $values;
}
private function packExternalReferencesAsKeys($vals)
{
foreach($this->getFactory()->getAttributes() as $a)
{
$alias = $a->getAlias();
$vals[$alias] = $a->packValue($vals[$alias]);
}
// XXX Joins
return $vals;
}
private function unpackExternalReferencesFromKeys($vals)
{
$factory = $this->getFactory();
foreach($factory->getAttributes() as $a)
{
$alias = $a->getAlias();
if(isset($vals[$alias]))
$vals[$alias] = $a->unpackValue($vals[$alias]);
}
$joins = $factory->getJoins();
foreach($joins as $join)
{
$join->unpackExternalReferencesFromKeys($vals);
}
return $vals;
}
/**
*
* @param array $rawData
* @param AbstractCommonClubsModelColumn[] $attribs
* @param JDatabaseQuery $q
* @return string[]|number[]|NULL[]
*/
private function quoteData($rawData, $attribs, $q)
{
$quotedData = array();
foreach($attribs as $a)
{
$alias = $a->getAlias();
$quotedData[$alias] = $a->getQuotedValue($q, $rawData[$alias]);
}
return $quotedData;
}
protected function filterDatabaseRawData($values)
{
return $values;
}
protected function filterDatabaseQuotedData($quoted)
{
return $quoted;
}
/**
*
* @param array $attribs
* @param JDatabaseQuery $q
* @return array
*/
private function getQuotedData($attribs, $q)
{
$rawData = $this->getValues();
$rawData = $this->filterDatabaseRawData($rawData);
$quotedData = $this->quoteData($rawData, $attribs, $q);
$quotedData = $this->filterDatabaseQuotedData($quotedData);
return $quotedData;
}
/**
*
* @param AbstractCommonClubsModelColumn[] $attribs
* @param AbstractCommonClubsModelFactory $factory
* @param JDatabaseQuery $q
*/
private function prepareInsert($attribs, $factory, $q)
{
$q->insert($factory->getTableName());
$dbcols = array();
foreach($attribs as $a)
{
$dbcols[] = $a->getColumn();
}
$q->columns($q->qn($dbcols));
$quotedData = $this->getQuotedData($attribs, $q);
$q->values(join(', ', $quotedData));
}
/**
*
* @param JDatabaseDriver $db
*/
private function finishInsert($db)
{
$this->id = $db->insertid();
$this->new = false;
}
/**
*
* @param AbstractCommonClubsModelColumn[] $attribs
* @param AbstractCommonClubsModelFactory $factory
* @param JDatabaseQuery $q
*/
private function prepareUpdate($attribs, $factory, $q)
{
$q->update($factory->getTableName());
$dbcols = array();
foreach($attribs as $a)
$dbcols[] = $a->getColumn();
$quotedData = $this->getQuotedData($attribs, $q);
$q->set(array_map(function($col, $data){
return "$col = $data";
}, $dbcols, $quotedData));
$q->where("id = {$this->id}");
}
/**
*
* @param JDatabaseDriver $db
*/
protected function prepareDelete($db)
{}
public function delete()
{
$db = Factory::getDbo();
$q = $db->getQuery(true);
$factory = $this->getFactory();
$q->delete($factory->getTableName());
$q->where("id = {$this->id}");
$db->transactionStart(true);
$this->prepareDelete($db);
$db->setQuery($q);
$db->execute();
$db->transactionCommit(true);
}
/**
*
* @param AbstractCommonClubsModelFactory $factory
* @param string $colName
* @param array $constraints
*/
protected function fetchAssociatedElements($factory, $colName, $constraints = null, $sorting = null)
{
$condition = "main.$colName = {$this->id}";
if(isset($constraints))
{
if(is_array($constraints))
$allConstraints = clone $constraints;
elseif(is_string($constraints))
$allConstraints = array($constraints);
else
throw new Exception('Unknown type of constraint');
// Add the manual condition to match the current object
$allConstraints[] = $condition;
return $factory->loadElements($allConstraints, $sorting);
}
else
return $factory->loadElements($condition, $sorting);
}
protected function filterPackData($values)
{
return $values;
}
protected function filterUnpackData($values)
{
return $values;
}
/**
* @return string
*/
public function pack()
{
$vals = $this->getValues();
$vals = $this->packExternalReferencesAsKeys($vals);
$vals = $this->filterPackData($vals);
$json = json_encode($vals);
return urlencode($json);
}
/**
* @param string $str
* @param boolean $decode
*/
public function unpack($str, $decode = false)
{
if($decode)
$json = urldecode($str);
else
$json = $str;
$data = json_decode($json, true);
$vals = $this->unpackExternalReferencesFromKeys($data);
$vals = $this->filterUnpackData($vals);
$this->setValues($vals);
}
public function dataIsValid()
{
return true;
}
}