mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-19 04:58:41 +00:00
experiment with CRUD pull-out
This commit is contained in:
parent
354ca75009
commit
d278918dfa
511
DataStorage/Database/CreateMapperAbstract.php
Normal file
511
DataStorage/Database/CreateMapperAbstract.php
Normal file
|
|
@ -0,0 +1,511 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.1
|
||||
*
|
||||
* @category TBD
|
||||
* @package TBD
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link http://orange-management.com
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\DataStorage\Database;
|
||||
|
||||
use phpOMS\DataStorage\Database\Query\Builder;
|
||||
use phpOMS\DataStorage\DataMapperBaseAbstract;
|
||||
use phpOMS\Message\RequestAbstract;
|
||||
use phpOMS\DataStorage\Database\Exception\InvalidMapperException;
|
||||
|
||||
/**
|
||||
* Datamapper for databases.
|
||||
*
|
||||
* DB, Cache, Session
|
||||
*
|
||||
* @category Framework
|
||||
* @package phpOMS\DataStorage\Database
|
||||
* @license OMS License 1.0
|
||||
* @link http://orange-management.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class CreateMapperAbstract extends DataMapperBaseAbstract
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function __clone()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create object in db.
|
||||
*
|
||||
* @param mixed $obj Object reference (gets filled with insert id)
|
||||
* @param int $relations Create all relations as well
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function create($obj, int $relations = RelationType::ALL)
|
||||
{
|
||||
self::extend(__CLASS__);
|
||||
|
||||
if($obj === null ||
|
||||
(is_object($obj) && strpos($className = get_class($obj), '\Null') !== false)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$reflectionClass = new \ReflectionClass($className);
|
||||
$objId = self::createModel($obj, $reflectionClass);
|
||||
self::setObjectId($reflectionClass, $obj, $objId);
|
||||
|
||||
if ($relations === RelationType::ALL) {
|
||||
self::createHasMany($reflectionClass, $obj, $objId);
|
||||
}
|
||||
|
||||
return $objId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create object in db.
|
||||
*
|
||||
* @param array $obj Object reference (gets filled with insert id)
|
||||
* @param int $relations Create all relations as well
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function createArray(array &$obj, int $relations = RelationType::ALL)
|
||||
{
|
||||
self::extend(__CLASS__);
|
||||
|
||||
$objId = self::createModelArray($obj);
|
||||
settype($objId, static::$columns[static::$primaryField]['type']);
|
||||
$obj[static::$columns[static::$primaryField]['internal']] = $objId;
|
||||
|
||||
if ($relations === RelationType::ALL) {
|
||||
self::createHasManyArray($obj, $objId);
|
||||
}
|
||||
|
||||
return $objId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create base model.
|
||||
*
|
||||
* @param Object $obj Model to create
|
||||
* @param \ReflectionClass $reflectionClass Reflection class
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function createModel($obj, \ReflectionClass $reflectionClass)
|
||||
{
|
||||
$query = new Builder(self::$db);
|
||||
$query->prefix(self::$db->getPrefix())->into(static::$table);
|
||||
|
||||
$properties = $reflectionClass->getProperties();
|
||||
|
||||
foreach ($properties as $property) {
|
||||
$propertyName = $property->getName();
|
||||
|
||||
if (isset(static::$hasMany[$propertyName]) || isset(static::$hasOne[$propertyName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!($isPublic = $property->isPublic())) {
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
|
||||
foreach (static::$columns as $key => $column) {
|
||||
if (isset(static::$ownsOne[$propertyName]) && $column['internal'] === $propertyName) {
|
||||
$id = self::createOwnsOne($propertyName, $property->getValue($obj));
|
||||
$value = self::parseValue($column['type'], $id);
|
||||
|
||||
$query->insert($column['name'])->value($value, $column['type']);
|
||||
break;
|
||||
} elseif (isset(static::$belongsTo[$propertyName]) && $column['internal'] === $propertyName) {
|
||||
$id = self::createBelongsTo($propertyName, $property->getValue($obj));
|
||||
$value = self::parseValue($column['type'], $id);
|
||||
|
||||
$query->insert($column['name'])->value($value, $column['type']);
|
||||
break;
|
||||
} elseif ($column['internal'] === $propertyName && $column['type'] !== static::$primaryField) {
|
||||
$value = self::parseValue($column['type'], $property->getValue($obj));
|
||||
|
||||
$query->insert($column['name'])->value($value, $column['type']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!($isPublic)) {
|
||||
$property->setAccessible(false);
|
||||
}
|
||||
}
|
||||
|
||||
self::$db->con->prepare($query->toSql())->execute();
|
||||
|
||||
return self::$db->con->lastInsertId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create base model.
|
||||
*
|
||||
* @param Object $obj Model to create
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function createModelArray($obj)
|
||||
{
|
||||
$query = new Builder(self::$db);
|
||||
$query->prefix(self::$db->getPrefix())->into(static::$table);
|
||||
|
||||
foreach ($obj as $propertyName => &$property) {
|
||||
if (isset(static::$hasMany[$propertyName]) || isset(static::$hasOne[$propertyName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (static::$columns as $key => $column) {
|
||||
if (isset(static::$ownsOne[$propertyName]) && $column['internal'] === $propertyName) {
|
||||
$id = self::createOwnsOneArray($propertyName, $property);
|
||||
$value = self::parseValue($column['type'], $id);
|
||||
|
||||
$query->insert($column['name'])->value($value, $column['type']);
|
||||
break;
|
||||
} elseif (isset(static::$belongsTo[$propertyName]) && $column['internal'] === $propertyName) {
|
||||
$id = self::createBelongsToArray($propertyName, $property);
|
||||
$value = self::parseValue($column['type'], $id);
|
||||
|
||||
$query->insert($column['name'])->value($value, $column['type']);
|
||||
break;
|
||||
} elseif ($column['internal'] === $propertyName && $column['type'] !== static::$primaryField) {
|
||||
$value = self::parseValue($column['type'], $property);
|
||||
|
||||
$query->insert($column['name'])->value($value, $column['type']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self::$db->con->prepare($query->toSql())->execute();
|
||||
|
||||
return self::$db->con->lastInsertId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create has many
|
||||
*
|
||||
* @param \ReflectionClass $reflectionClass Reflection class
|
||||
* @param Object $obj Object to create
|
||||
* @param mixed $objId Id to set
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws InvalidMapperException
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function createHasMany(\ReflectionClass $reflectionClass, $obj, $objId) /* : void */
|
||||
{
|
||||
foreach (static::$hasMany as $propertyName => $rel) {
|
||||
$property = $reflectionClass->getProperty($propertyName);
|
||||
|
||||
if (!($isPublic = $property->isPublic())) {
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
|
||||
$values = $property->getValue($obj);
|
||||
|
||||
if (!($isPublic)) {
|
||||
$property->setAccessible(false);
|
||||
}
|
||||
|
||||
if (!isset(static::$hasMany[$propertyName]['mapper'])) {
|
||||
throw new InvalidMapperException();
|
||||
}
|
||||
|
||||
/** @var DataMapperAbstract $mapper */
|
||||
$mapper = static::$hasMany[$propertyName]['mapper'];
|
||||
$objsIds = [];
|
||||
$relReflectionClass = null;
|
||||
|
||||
foreach ($values as $key => &$value) {
|
||||
if (!is_object($value)) {
|
||||
// Is scalar => already in database
|
||||
$objsIds[$key] = $value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($relReflectionClass)) {
|
||||
$relReflectionClass = new \ReflectionClass(get_class($value));
|
||||
}
|
||||
|
||||
$primaryKey = $mapper::getObjectId($value, $relReflectionClass);
|
||||
|
||||
// already in db
|
||||
if (!empty($primaryKey)) {
|
||||
$objsIds[$key] = $value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Setting relation value (id) for relation (since the relation is not stored in an extra relation table)
|
||||
/** @var string $table */
|
||||
/** @var array $columns */
|
||||
if (static::$hasMany[$propertyName]['table'] === static::$hasMany[$propertyName]['mapper']::$table) {
|
||||
$relProperty = $relReflectionClass->getProperty($mapper::$columns[static::$hasMany[$propertyName]['dst']]['internal']);
|
||||
|
||||
if (!$isPublic) {
|
||||
$relProperty->setAccessible(true);
|
||||
}
|
||||
|
||||
$relProperty->setValue($value, $objId);
|
||||
|
||||
if (!($isPublic)) {
|
||||
$relProperty->setAccessible(false);
|
||||
}
|
||||
}
|
||||
|
||||
$objsIds[$key] = $mapper::create($value);
|
||||
}
|
||||
|
||||
self::createRelationTable($propertyName, $objsIds, $objId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create has many
|
||||
*
|
||||
* @param array $obj Object to create
|
||||
* @param mixed $objId Id to set
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws InvalidMapperException
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function createHasManyArray(array &$obj, $objId) /* : void */
|
||||
{
|
||||
foreach (static::$hasMany as $propertyName => $rel) {
|
||||
$values = $obj[$propertyName];
|
||||
|
||||
if (!isset(static::$hasMany[$propertyName]['mapper'])) {
|
||||
throw new InvalidMapperException();
|
||||
}
|
||||
|
||||
/** @var DataMapperAbstract $mapper */
|
||||
$mapper = static::$hasMany[$propertyName]['mapper'];
|
||||
$objsIds = [];
|
||||
|
||||
foreach ($values as $key => &$value) {
|
||||
if (!is_object($value)) {
|
||||
// Is scalar => already in database
|
||||
$objsIds[$key] = $value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$primaryKey = $obj[static::$columns[static::$primaryField]['internal']];
|
||||
|
||||
// already in db
|
||||
if (!empty($primaryKey)) {
|
||||
$objsIds[$key] = $value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Setting relation value (id) for relation (since the relation is not stored in an extra relation table)
|
||||
/** @var string $table */
|
||||
/** @var array $columns */
|
||||
if (static::$hasMany[$propertyName]['table'] === static::$hasMany[$propertyName]['mapper']::$table) {
|
||||
$value[$mapper::$columns[static::$hasMany[$propertyName]['dst']]['internal']] = $objId;
|
||||
}
|
||||
|
||||
$objsIds[$key] = $mapper::createArray($value);
|
||||
}
|
||||
|
||||
self::createRelationTable($propertyName, $objsIds, $objId);
|
||||
}
|
||||
}
|
||||
|
||||
private static function createHasOne(\ReflectionClass $reflectionClass, $obj)
|
||||
{
|
||||
throw new \Exception();
|
||||
|
||||
foreach (static::$hasOne as $propertyName => $rel) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create owns one
|
||||
*
|
||||
* The reference is stored in the main model
|
||||
*
|
||||
* @param string $propertyName Property name to initialize
|
||||
* @param Object $obj Object to create
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function createOwnsOne(string $propertyName, $obj)
|
||||
{
|
||||
if (is_object($obj)) {
|
||||
$mapper = static::$ownsOne[$propertyName]['mapper'];
|
||||
$primaryKey = $mapper::getObjectId($obj);
|
||||
|
||||
if (empty($primaryKey)) {
|
||||
return $mapper::create($obj);
|
||||
}
|
||||
|
||||
return $primaryKey;
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create owns one
|
||||
*
|
||||
* The reference is stored in the main model
|
||||
*
|
||||
* @param string $propertyName Property name to initialize
|
||||
* @param array $obj Object to create
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function createOwnsOneArray(string $propertyName, array &$obj)
|
||||
{
|
||||
if (is_array($obj)) {
|
||||
$mapper = static::$ownsOne[$propertyName]['mapper'];
|
||||
$primaryKey = $obj[static::$columns[static::$primaryField]['internal']];
|
||||
|
||||
if (empty($primaryKey)) {
|
||||
return $mapper::createArray($obj);
|
||||
}
|
||||
|
||||
return $primaryKey;
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create owns one
|
||||
*
|
||||
* The reference is stored in the main model
|
||||
*
|
||||
* @param string $propertyName Property name to initialize
|
||||
* @param Object $obj Object to create
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function createBelongsTo(string $propertyName, $obj)
|
||||
{
|
||||
if (is_object($obj)) {
|
||||
/** @var DataMapperAbstract $mapper */
|
||||
$mapper = static::$belongsTo[$propertyName]['mapper'];
|
||||
$primaryKey = $mapper::getObjectId($obj);
|
||||
|
||||
if (empty($primaryKey)) {
|
||||
return $mapper::create($obj);
|
||||
}
|
||||
|
||||
return $primaryKey;
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create owns one
|
||||
*
|
||||
* The reference is stored in the main model
|
||||
*
|
||||
* @param string $propertyName Property name to initialize
|
||||
* @param Object $obj Object to create
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function createBelongsToArray(string $propertyName, array $obj)
|
||||
{
|
||||
if (is_array($obj)) {
|
||||
/** @var DataMapperAbstract $mapper */
|
||||
$mapper = static::$belongsTo[$propertyName]['mapper'];
|
||||
$primaryKey = $obj[static::$columns[static::$primaryField]['internal']];
|
||||
|
||||
if (empty($primaryKey)) {
|
||||
return $mapper::createArray($obj);
|
||||
}
|
||||
|
||||
return $primaryKey;
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create relation table entry
|
||||
*
|
||||
* In case of a many to many relation the relation has to be stored in a relation table
|
||||
*
|
||||
* @param string $propertyName Property name to initialize
|
||||
* @param array $objsIds Object ids to insert
|
||||
* @param mixed $objId Model to reference
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function createRelationTable(string $propertyName, array $objsIds, $objId)
|
||||
{
|
||||
/** @var string $table */
|
||||
if (
|
||||
!empty($objsIds)
|
||||
&& static::$hasMany[$propertyName]['table'] !== static::$table
|
||||
&& static::$hasMany[$propertyName]['table'] !== static::$hasMany[$propertyName]['mapper']::$table
|
||||
) {
|
||||
$relQuery = new Builder(self::$db);
|
||||
$relQuery->prefix(self::$db->getPrefix())
|
||||
->into(static::$hasMany[$propertyName]['table'])
|
||||
->insert(static::$hasMany[$propertyName]['src'], static::$hasMany[$propertyName]['dst']);
|
||||
|
||||
foreach ($objsIds as $key => $src) {
|
||||
$relQuery->values($src, $objId);
|
||||
}
|
||||
|
||||
self::$db->con->prepare($relQuery->toSql())->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
435
DataStorage/Database/DataMapperBaseAbstract.php
Normal file
435
DataStorage/Database/DataMapperBaseAbstract.php
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.1
|
||||
*
|
||||
* @category TBD
|
||||
* @package TBD
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link http://orange-management.com
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\DataStorage\Database;
|
||||
|
||||
use phpOMS\DataStorage\Database\Connection\ConnectionAbstract;
|
||||
use phpOMS\DataStorage\Database\Query\Builder;
|
||||
|
||||
/**
|
||||
* Datamapper for databases.
|
||||
*
|
||||
* DB, Cache, Session
|
||||
*
|
||||
* @category Framework
|
||||
* @package phpOMS\DataStorage\Database
|
||||
* @license OMS License 1.0
|
||||
* @link http://orange-management.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class DataMapperBaseAbstract
|
||||
{
|
||||
/**
|
||||
* Database connection.
|
||||
*
|
||||
* @var ConnectionAbstract
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $db = null;
|
||||
|
||||
/**
|
||||
* Overwriting extended values.
|
||||
*
|
||||
* @var bool
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $overwrite = true;
|
||||
|
||||
/**
|
||||
* Primary field name.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $primaryField = '';
|
||||
|
||||
/**
|
||||
* Primary field name.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $createdAt = '';
|
||||
|
||||
/**
|
||||
* Language
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $language_field = '';
|
||||
|
||||
/**
|
||||
* Columns.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $columns = [];
|
||||
|
||||
/**
|
||||
* Relations.
|
||||
*
|
||||
* Relation is defined in a relation table
|
||||
*
|
||||
* @var string[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $hasMany = [];
|
||||
|
||||
/**
|
||||
* Relations.
|
||||
*
|
||||
* Relation is defined in the model
|
||||
*
|
||||
* @var string[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $hasOne = [];
|
||||
|
||||
/**
|
||||
* Relations.
|
||||
*
|
||||
* Relation is defined in current mapper
|
||||
*
|
||||
* @var string[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $ownsOne = [];
|
||||
|
||||
/**
|
||||
* Relations.
|
||||
*
|
||||
* Relation is defined in current mapper
|
||||
*
|
||||
* @var string[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $belongsTo = [];
|
||||
|
||||
/**
|
||||
* Table.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $table = '';
|
||||
|
||||
/**
|
||||
* Fields to load.
|
||||
*
|
||||
* @var array[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $fields = [];
|
||||
|
||||
/**
|
||||
* Initialized objects for cross reference to reduce initialization costs
|
||||
*
|
||||
* @var array[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $initObjects = [];
|
||||
|
||||
/**
|
||||
* Highest mapper to know when to clear initialized objects
|
||||
*
|
||||
* @var DataMapperAbstract
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $parentMapper = null;
|
||||
|
||||
/**
|
||||
* Extended value collection.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static $collection = [
|
||||
'primaryField' => [],
|
||||
'createdAt' => [],
|
||||
'columns' => [],
|
||||
'hasMany' => [],
|
||||
'hasOne' => [],
|
||||
'ownsOne' => [],
|
||||
'table' => [],
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function __clone()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set database connection.
|
||||
*
|
||||
* @param ConnectionAbstract $con Database connection
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function setConnection(ConnectionAbstract $con) /* : void */
|
||||
{
|
||||
self::$db = $con;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get primary field.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function getPrimaryField() : string
|
||||
{
|
||||
return static::$primaryField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get main table.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function getTable() : string
|
||||
{
|
||||
return static::$table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect values from extension.
|
||||
*
|
||||
* @param mixed $class Current extended mapper
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function extend($class) /* : void */
|
||||
{
|
||||
/* todo: have to implement this in the queries, so far not used */
|
||||
self::$collection['primaryField'][] = $class::$primaryField;
|
||||
self::$collection['createdAt'][] = $class::$createdAt;
|
||||
self::$collection['columns'][] = $class::$columns;
|
||||
self::$collection['hasMany'][] = $class::$hasMany;
|
||||
self::$collection['hasOne'][] = $class::$hasOne;
|
||||
self::$collection['ownsOne'][] = $class::$ownsOne;
|
||||
self::$collection['table'][] = $class::$table;
|
||||
|
||||
if (($parent = get_parent_class($class)) !== false && !$class::$overwrite) {
|
||||
self::extend($parent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all loaded mapper variables.
|
||||
*
|
||||
* This is used after one action is performed otherwise other models would use wrong settings.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function clear() /* : void */
|
||||
{
|
||||
self::$overwrite = true;
|
||||
self::$primaryField = '';
|
||||
self::$createdAt = '';
|
||||
self::$columns = [];
|
||||
self::$hasMany = [];
|
||||
self::$hasOne = [];
|
||||
self::$ownsOne = [];
|
||||
self::$table = '';
|
||||
self::$fields = [];
|
||||
self::$collection = [
|
||||
'primaryField' => [],
|
||||
'createdAt' => [],
|
||||
'columns' => [],
|
||||
'hasOne' => [],
|
||||
'ownsMany' => [],
|
||||
'ownsOne' => [],
|
||||
'table' => [],
|
||||
];
|
||||
|
||||
// clear parent and objects
|
||||
if(static::class === self::$parentMapper) {
|
||||
self::$initObjects = [];
|
||||
self::$parentMapper = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get created at column
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function getCreatedAt() : string
|
||||
{
|
||||
return static::$createdAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id of object
|
||||
*
|
||||
* @param Object $obj Model to create
|
||||
* @param \ReflectionClass $reflectionClass Reflection class
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function getObjectId($obj, \ReflectionClass $reflectionClass = null)
|
||||
{
|
||||
$reflectionClass = $reflectionClass ?? new \ReflectionClass(get_class($obj));
|
||||
$reflectionProperty = $reflectionClass->getProperty(static::$columns[static::$primaryField]['internal']);
|
||||
|
||||
if (!($isPublic = $reflectionProperty->isPublic())) {
|
||||
$reflectionProperty->setAccessible(true);
|
||||
}
|
||||
|
||||
$objectId = $reflectionProperty->getValue($obj);
|
||||
|
||||
if (!$isPublic) {
|
||||
$reflectionProperty->setAccessible(false);
|
||||
}
|
||||
|
||||
return $objectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set id to model
|
||||
*
|
||||
* @param \ReflectionClass $reflectionClass Reflection class
|
||||
* @param Object $obj Object to create
|
||||
* @param mixed $objId Id to set
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function setObjectId(\ReflectionClass $reflectionClass, $obj, $objId) /* : void */
|
||||
{
|
||||
$reflectionProperty = $reflectionClass->getProperty(static::$columns[static::$primaryField]['internal']);
|
||||
|
||||
if (!($isPublic = $reflectionProperty->isPublic())) {
|
||||
$reflectionProperty->setAccessible(true);
|
||||
}
|
||||
|
||||
settype($objId, static::$columns[static::$primaryField]['type']);
|
||||
$reflectionProperty->setValue($obj, $objId);
|
||||
|
||||
if (!$isPublic) {
|
||||
$reflectionProperty->setAccessible(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse value
|
||||
*
|
||||
* @param string $type Value type
|
||||
* @param mixed $value Value to parse
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function parseValue(string $type, $value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return null;
|
||||
} elseif ($type === 'DateTime') {
|
||||
return $value->format('Y-m-d H:i:s');
|
||||
} elseif ($type === 'Json' || $type === 'jsonSerializable') {
|
||||
return json_encode($value);
|
||||
} elseif ($type === 'Serializable') {
|
||||
return $value->serialize();
|
||||
} elseif ($value instanceof \JsonSerializable) {
|
||||
return json_encode($value->jsonSerialize());
|
||||
} elseif (is_object($value) && method_exists($value, 'getId')) {
|
||||
return $value->getId();
|
||||
} elseif ($type === 'int') {
|
||||
return (int) $value;
|
||||
} elseif ($type === 'string') {
|
||||
return (string) $value;
|
||||
} elseif ($type === 'float') {
|
||||
return (float) $value;
|
||||
} elseif ($type === 'bool') {
|
||||
return (bool) $value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mapper specific builder
|
||||
*
|
||||
* @param Builder $query Query to fill
|
||||
*
|
||||
* @return Builder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function getQuery(Builder $query = null) : Builder
|
||||
{
|
||||
$query = $query ?? new Builder(self::$db);
|
||||
$query->prefix(self::$db->getPrefix())
|
||||
->select('*')
|
||||
->from(static::$table);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the highest mapper of this request
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function setUpParentMapper() /* : void */
|
||||
{
|
||||
self::$parentMapper = static::class;
|
||||
}
|
||||
|
||||
private static function getColumnByMember(string $name) : string
|
||||
{
|
||||
foreach(static::$columns as $cName => $column) {
|
||||
if($column['internal'] === $name) {
|
||||
return $cName;
|
||||
}
|
||||
}
|
||||
|
||||
throw \Exception();
|
||||
}
|
||||
}
|
||||
295
DataStorage/Database/DeleteMapperAbstract.php
Normal file
295
DataStorage/Database/DeleteMapperAbstract.php
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.1
|
||||
*
|
||||
* @category TBD
|
||||
* @package TBD
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link http://orange-management.com
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\DataStorage\Database;
|
||||
|
||||
use phpOMS\DataStorage\Database\Query\Builder;
|
||||
use phpOMS\DataStorage\DataMapperBaseAbstract;
|
||||
use phpOMS\Message\RequestAbstract;
|
||||
use phpOMS\DataStorage\Database\Exception\InvalidMapperException;
|
||||
|
||||
/**
|
||||
* Datamapper for databases.
|
||||
*
|
||||
* DB, Cache, Session
|
||||
*
|
||||
* @category Framework
|
||||
* @package phpOMS\DataStorage\Database
|
||||
* @license OMS License 1.0
|
||||
* @link http://orange-management.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class DeleteMapperAbstract extends DataMapperBaseAbstract
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function __clone()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete has many
|
||||
*
|
||||
* @param \ReflectionClass $reflectionClass Reflection class
|
||||
* @param Object $obj Object to create
|
||||
* @param mixed $objId Id to set
|
||||
* @param int $relations Delete all relations as well
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws InvalidMapperException
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function deleteHasMany(\ReflectionClass $reflectionClass, $obj, $objId, int $relations) /* : void */
|
||||
{
|
||||
foreach (static::$hasMany as $propertyName => $rel) {
|
||||
$property = $reflectionClass->getProperty($propertyName);
|
||||
|
||||
if (!($isPublic = $property->isPublic())) {
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
|
||||
$values = $property->getValue($obj);
|
||||
|
||||
if (!($isPublic)) {
|
||||
$property->setAccessible(false);
|
||||
}
|
||||
|
||||
if (!isset(static::$hasMany[$propertyName]['mapper'])) {
|
||||
throw new InvalidMapperException();
|
||||
}
|
||||
|
||||
/** @var DataMapperAbstract $mapper */
|
||||
$mapper = static::$hasMany[$propertyName]['mapper'];
|
||||
$objsIds = [];
|
||||
$relReflectionClass = null;
|
||||
|
||||
foreach ($values as $key => &$value) {
|
||||
if (!is_object($value)) {
|
||||
// Is scalar => already in database
|
||||
$objsIds[$key] = $value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($relReflectionClass)) {
|
||||
$relReflectionClass = new \ReflectionClass(get_class($value));
|
||||
}
|
||||
|
||||
$primaryKey = $mapper::getObjectId($value, $relReflectionClass);
|
||||
|
||||
// already in db
|
||||
if (!empty($primaryKey)) {
|
||||
if($relations === RelationType::ALL) {
|
||||
$objsIds[$key] = $mapper::delete($value);
|
||||
} else {
|
||||
$objsIds[$key] = $primaryKey;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// todo: could be a problem, relation needs to be removed first?!
|
||||
|
||||
}
|
||||
|
||||
self::deleteRelationTable($propertyName, $objsIds, $objId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete owns one
|
||||
*
|
||||
* The reference is stored in the main model
|
||||
*
|
||||
* @param string $propertyName Property name to initialize
|
||||
* @param Object $obj Object to delete
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function deleteOwnsOne(string $propertyName, $obj)
|
||||
{
|
||||
if (is_object($obj)) {
|
||||
/** @var DataMapperAbstract $mapper */
|
||||
$mapper = static::$ownsOne[$propertyName]['mapper'];
|
||||
|
||||
// todo: delete owned one object is not recommended since it can be owned by by something else? or does owns one mean that nothing else can have a relation to this one?
|
||||
return $mapper::delete($obj);
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete owns one
|
||||
*
|
||||
* The reference is stored in the main model
|
||||
*
|
||||
* @param string $propertyName Property name to initialize
|
||||
* @param Object $obj Object to delete
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function deleteBelongsTo(string $propertyName, $obj)
|
||||
{
|
||||
if (is_object($obj)) {
|
||||
/** @var DataMapperAbstract $mapper */
|
||||
$mapper = static::$belongsTo[$propertyName]['mapper'];
|
||||
|
||||
return $mapper::delete($obj);
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete object in db.
|
||||
*
|
||||
* @param Object $obj Model to delete
|
||||
* @param mixed $objId Model id
|
||||
* @param int $relations Delete all relations as well
|
||||
* @param \ReflectionClass $reflectionClass Reflection class
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function deleteModel($obj, $objId, int $relations = RelationType::REFERENCE, \ReflectionClass $reflectionClass = null) /* : void */
|
||||
{
|
||||
$query = new Builder(self::$db);
|
||||
$query->prefix(self::$db->getPrefix())
|
||||
->delete()
|
||||
->into(static::$table)
|
||||
->where(static::$primaryField, '=', $objId);
|
||||
|
||||
$properties = $reflectionClass->getProperties();
|
||||
|
||||
if($relations === RelationType::ALL) {
|
||||
foreach ($properties as $property) {
|
||||
$propertyName = $property->getName();
|
||||
|
||||
if (isset(static::$hasMany[$propertyName]) || isset(static::$hasOne[$propertyName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!($isPublic = $property->isPublic())) {
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
|
||||
// todo: the order of deletion could be a problem. maybe looping through ownsOne and belongsTo first is better.
|
||||
// todo: support other relation types as well (belongsto, ownsone) = for better control
|
||||
|
||||
foreach (static::$columns as $key => $column) {
|
||||
if ($relations === RelationType::ALL && isset(static::$ownsOne[$propertyName]) && $column['internal'] === $propertyName) {
|
||||
self::deleteOwnsOne($propertyName, $property->getValue($obj));
|
||||
break;
|
||||
} elseif ($relations === RelationType::ALL && isset(static::$belongsTo[$propertyName]) && $column['internal'] === $propertyName) {
|
||||
self::deleteBelongsTo($propertyName, $property->getValue($obj));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!($isPublic)) {
|
||||
$property->setAccessible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self::$db->con->prepare($query->toSql())->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete object in db.
|
||||
*
|
||||
* @param mixed $obj Object reference (gets filled with insert id)
|
||||
* @param int $relations Create all relations as well
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function delete($obj, int $relations = RelationType::REFERENCE)
|
||||
{
|
||||
self::extend(__CLASS__);
|
||||
$reflectionClass = new \ReflectionClass(get_class($obj));
|
||||
$objId = self::getObjectId($obj, $reflectionClass);
|
||||
|
||||
if(empty($objId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($relations !== RelationType::NONE) {
|
||||
self::deleteHasMany($reflectionClass, $obj, $objId, $relations);
|
||||
}
|
||||
|
||||
self::deleteModel($obj, $objId, $relations, $reflectionClass);
|
||||
|
||||
return $objId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete relation table entry
|
||||
*
|
||||
* @param string $propertyName Property name to initialize
|
||||
* @param array $objsIds Object ids to insert
|
||||
* @param mixed $objId Model to reference
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function deleteRelationTable(string $propertyName, array $objsIds, $objId)
|
||||
{
|
||||
/** @var string $table */
|
||||
if (
|
||||
!empty($objsIds)
|
||||
&& static::$hasMany[$propertyName]['table'] !== static::$table
|
||||
&& static::$hasMany[$propertyName]['table'] !== static::$hasMany[$propertyName]['mapper']::$table
|
||||
) {
|
||||
foreach ($objsIds as $key => $src) {
|
||||
$relQuery = new Builder(self::$db);
|
||||
$relQuery->prefix(self::$db->getPrefix())
|
||||
->into(static::$hasMany[$propertyName]['table'])
|
||||
->delete();
|
||||
|
||||
$relQuery->where(static::$hasMany[$propertyName]['src'], '=', $src)
|
||||
->where(static::$hasMany[$propertyName]['dst'], '=', $objId, 'and');
|
||||
|
||||
self::$db->con->prepare($relQuery->toSql())->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1126
DataStorage/Database/ReadMapperAbstract.php
Normal file
1126
DataStorage/Database/ReadMapperAbstract.php
Normal file
File diff suppressed because it is too large
Load Diff
326
DataStorage/Database/UpdateMapperAbstract.php
Normal file
326
DataStorage/Database/UpdateMapperAbstract.php
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
<?php
|
||||
/**
|
||||
* Orange Management
|
||||
*
|
||||
* PHP Version 7.1
|
||||
*
|
||||
* @category TBD
|
||||
* @package TBD
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link http://orange-management.com
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\DataStorage\Database;
|
||||
|
||||
use phpOMS\DataStorage\Database\Query\Builder;
|
||||
use phpOMS\DataStorage\DataMapperBaseAbstract;
|
||||
use phpOMS\Message\RequestAbstract;
|
||||
use phpOMS\DataStorage\Database\Exception\InvalidMapperException;
|
||||
|
||||
/**
|
||||
* Datamapper for databases.
|
||||
*
|
||||
* DB, Cache, Session
|
||||
*
|
||||
* @category Framework
|
||||
* @package phpOMS\DataStorage\Database
|
||||
* @license OMS License 1.0
|
||||
* @link http://orange-management.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class UpdateMapperAbstract extends DataMapperBaseAbstract
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function __clone()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Update has many
|
||||
*
|
||||
* @param \ReflectionClass $reflectionClass Reflection class
|
||||
* @param Object $obj Object to create
|
||||
* @param mixed $objId Id to set
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws InvalidMapperException
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function updateHasMany(\ReflectionClass $reflectionClass, $obj, $objId) /* : void */
|
||||
{
|
||||
foreach (static::$hasMany as $propertyName => $rel) {
|
||||
$property = $reflectionClass->getProperty($propertyName);
|
||||
|
||||
if (!($isPublic = $property->isPublic())) {
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
|
||||
$values = $property->getValue($obj);
|
||||
|
||||
if (!($isPublic)) {
|
||||
$property->setAccessible(false);
|
||||
}
|
||||
|
||||
if (!isset(static::$hasMany[$propertyName]['mapper'])) {
|
||||
throw new InvalidMapperException();
|
||||
}
|
||||
|
||||
/** @var DataMapperAbstract $mapper */
|
||||
$mapper = static::$hasMany[$propertyName]['mapper'];
|
||||
$objsIds = [];
|
||||
$relReflectionClass = null;
|
||||
|
||||
foreach ($values as $key => &$value) {
|
||||
if (!is_object($value)) {
|
||||
// Is scalar => already in database
|
||||
$objsIds[$key] = $value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($relReflectionClass)) {
|
||||
$relReflectionClass = new \ReflectionClass(get_class($value));
|
||||
}
|
||||
|
||||
$primaryKey = $mapper::getObjectId($value, $relReflectionClass);
|
||||
|
||||
// already in db
|
||||
if (!empty($primaryKey)) {
|
||||
$objsIds[$key] = $value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// create if not existing
|
||||
/** @var string $table */
|
||||
/** @var array $columns */
|
||||
if (static::$hasMany[$propertyName]['table'] === static::$hasMany[$propertyName]['mapper']::$table) {
|
||||
$relProperty = $relReflectionClass->getProperty($mapper::$columns[static::$hasMany[$propertyName]['dst']]['internal']);
|
||||
|
||||
if (!$isPublic) {
|
||||
$relProperty->setAccessible(true);
|
||||
}
|
||||
|
||||
$relProperty->setValue($value, $objId);
|
||||
|
||||
if (!($isPublic)) {
|
||||
$relProperty->setAccessible(false);
|
||||
}
|
||||
}
|
||||
|
||||
$objsIds[$key] = $mapper::create($value);
|
||||
}
|
||||
|
||||
self::updateRelationTable($propertyName, $objsIds, $objId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update relation table entry
|
||||
*
|
||||
* Deletes old entries and creates new ones
|
||||
*
|
||||
* @param string $propertyName Property name to initialize
|
||||
* @param array $objsIds Object ids to insert
|
||||
* @param mixed $objId Model to reference
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function updateRelationTable(string $propertyName, array $objsIds, $objId)
|
||||
{
|
||||
/** @var string $table */
|
||||
if (
|
||||
!empty($objsIds)
|
||||
&& static::$hasMany[$propertyName]['table'] !== static::$table
|
||||
&& static::$hasMany[$propertyName]['table'] !== static::$hasMany[$propertyName]['mapper']::$table
|
||||
) {
|
||||
$many = self::getHasManyRaw($objId);
|
||||
|
||||
foreach(static::$hasMany as $member => $value) {
|
||||
// todo: definately an error here. needs testing
|
||||
throw new \Exception();
|
||||
$removes = array_diff_key($many[$member], $objsIds[$member]);
|
||||
$adds = array_diff_key($objsIds[$member], $many[$member]);
|
||||
|
||||
if(!empty($removes)) {
|
||||
self::deleteRelationTable($propertyName, $removes, $objId);
|
||||
}
|
||||
|
||||
if(!empty($adds)) {
|
||||
self::createRelationTable($propertyName, $adds, $objId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update owns one
|
||||
*
|
||||
* The reference is stored in the main model
|
||||
*
|
||||
* @param string $propertyName Property name to initialize
|
||||
* @param Object $obj Object to update
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function updateOwnsOne(string $propertyName, $obj)
|
||||
{
|
||||
if (is_object($obj)) {
|
||||
/** @var DataMapperAbstract $mapper */
|
||||
$mapper = static::$ownsOne[$propertyName]['mapper'];
|
||||
|
||||
// todo: delete owned one object is not recommended since it can be owned by by something else? or does owns one mean that nothing else can have a relation to this one?
|
||||
|
||||
return $mapper::update($obj);
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update owns one
|
||||
*
|
||||
* The reference is stored in the main model
|
||||
*
|
||||
* @param string $propertyName Property name to initialize
|
||||
* @param Object $obj Object to update
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function updateBelongsTo(string $propertyName, $obj)
|
||||
{
|
||||
if (is_object($obj)) {
|
||||
/** @var DataMapperAbstract $mapper */
|
||||
$mapper = static::$belongsTo[$propertyName]['mapper'];
|
||||
|
||||
return $mapper::update($obj);
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object in db.
|
||||
*
|
||||
* @param Object $obj Model to update
|
||||
* @param mixed $objId Model id
|
||||
* @param \ReflectionClass $reflectionClass Reflection class
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function updateModel($obj, $objId, \ReflectionClass $reflectionClass = null) /* : void */
|
||||
{
|
||||
$query = new Builder(self::$db);
|
||||
$query->prefix(self::$db->getPrefix())
|
||||
->into(static::$table)
|
||||
->where(static::$primaryField, '=', $objId);
|
||||
|
||||
$properties = $reflectionClass->getProperties();
|
||||
|
||||
foreach ($properties as $property) {
|
||||
$propertyName = $property->getName();
|
||||
|
||||
if (isset(static::$hasMany[$propertyName]) || isset(static::$hasOne[$propertyName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!($isPublic = $property->isPublic())) {
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
|
||||
// todo: the order of updating could be a problem. maybe looping through ownsOne and belongsTo first is better.
|
||||
|
||||
foreach (static::$columns as $key => $column) {
|
||||
if (isset(static::$ownsOne[$propertyName]) && $column['internal'] === $propertyName) {
|
||||
$id = self::updateOwnsOne($propertyName, $property->getValue($obj));
|
||||
$value = self::parseValue($column['type'], $id);
|
||||
|
||||
// todo: should not be done if the id didn't change. but for now don't know if id changed
|
||||
$query->update($column['name'])->value($value, $column['type']);
|
||||
break;
|
||||
} elseif (isset(static::$belongsTo[$propertyName]) && $column['internal'] === $propertyName) {
|
||||
$id = self::updateBelongsTo($propertyName, $property->getValue($obj));
|
||||
$value = self::parseValue($column['type'], $id);
|
||||
|
||||
// todo: should not be done if the id didn't change. but for now don't know if id changed
|
||||
$query->update($column['name'])->value($value, $column['type']);
|
||||
break;
|
||||
} elseif ($column['internal'] === $propertyName && $column['type'] !== static::$primaryField) {
|
||||
$value = self::parseValue($column['type'], $property->getValue($obj));
|
||||
|
||||
$query->update($column['name'])->value($value, $column['type']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!($isPublic)) {
|
||||
$property->setAccessible(false);
|
||||
}
|
||||
}
|
||||
|
||||
self::$db->con->prepare($query->toSql())->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object in db.
|
||||
*
|
||||
* @param mixed $obj Object reference (gets filled with insert id)
|
||||
* @param int $relations Create all relations as well
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function update($obj, int $relations = RelationType::ALL) : int
|
||||
{
|
||||
self::extend(__CLASS__);
|
||||
$reflectionClass = new \ReflectionClass(get_class($obj));
|
||||
$objId = self::getObjectId($obj, $reflectionClass);
|
||||
$update = true;
|
||||
|
||||
if(empty($objId)) {
|
||||
$update = false;
|
||||
self::create($obj, $relations);
|
||||
}
|
||||
|
||||
if ($relations === RelationType::ALL) {
|
||||
self::updateHasMany($reflectionClass, $obj, $objId);
|
||||
}
|
||||
|
||||
if($update) {
|
||||
self::updateModel($obj, $objId, $reflectionClass);
|
||||
}
|
||||
|
||||
return $objId;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user