mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-11 01:38:41 +00:00
Reduce reflection usage by forcing private definition in mappers.
This commit is contained in:
parent
be8ae797db
commit
cdea41f714
|
|
@ -548,8 +548,8 @@ abstract class DataMapperAbstract
|
|||
return (string) \gzdeflate($value);
|
||||
} elseif ($type === 'Serializable') {
|
||||
return $value->serialize();
|
||||
} elseif (\is_object($value) && \method_exists($value, 'getId')) {
|
||||
return $value->getId();
|
||||
} elseif (\is_object($value) && isset($value->id)) {
|
||||
return $value->id;
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
|
|
|||
|
|
@ -426,38 +426,53 @@ class DataMapperFactory
|
|||
/**
|
||||
* Get id of object
|
||||
*
|
||||
* @param object $obj Model to create
|
||||
* @param string $member Member name for the id, if it is not the primary key
|
||||
* @param object $obj Model to create
|
||||
* @param string $member Member name for the id, if it is not the primary key
|
||||
* @param null|\ReflectionClass $refClass Reflection class
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function getObjectId(object $obj, string $member = null) : mixed
|
||||
public static function getObjectId(object $obj, string $member = null, \ReflectionClass &$refClass = null) : mixed
|
||||
{
|
||||
$propertyName = $member ?? static::COLUMNS[static::PRIMARYFIELD]['internal'];
|
||||
|
||||
return $obj->{$propertyName};
|
||||
if (static::COLUMNS[static::PRIMARYFIELD]['private'] ?? false) {
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
$refProp = $refClass->getProperty($propertyName);
|
||||
|
||||
return $refProp->getValue($obj);
|
||||
} else {
|
||||
return $obj->{$propertyName};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set id to model
|
||||
*
|
||||
* @param \ReflectionClass $refClass Reflection class
|
||||
* @param object $obj Object to create
|
||||
* @param mixed $objId Id to set
|
||||
* @param object $obj Object to create
|
||||
* @param mixed $objId Id to set
|
||||
* @param null|\ReflectionClass $refClass Reflection class
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function setObjectId(\ReflectionClass $refClass, object $obj, mixed $objId) : void
|
||||
public static function setObjectId(object $obj, mixed $objId, \ReflectionClass &$refClass = null) : void
|
||||
{
|
||||
$propertyName = static::COLUMNS[static::PRIMARYFIELD]['internal'];
|
||||
$refProp = $refClass->getProperty($propertyName);
|
||||
|
||||
\settype($objId, static::COLUMNS[static::PRIMARYFIELD]['type']);
|
||||
if (!$refProp->isPublic()) {
|
||||
|
||||
if (static::COLUMNS[static::PRIMARYFIELD]['private'] ?? false) {
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
$refProp = $refClass->getProperty($propertyName);
|
||||
$refProp->setValue($obj, $objId);
|
||||
} else {
|
||||
$obj->{$propertyName} = $objId;
|
||||
|
|
|
|||
|
|
@ -71,17 +71,17 @@ final class DeleteMapper extends DataMapperAbstract
|
|||
*/
|
||||
public function executeDelete(object $obj) : mixed
|
||||
{
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
$refClass = null;
|
||||
$objId = $this->mapper::getObjectId($obj);
|
||||
|
||||
if (empty($objId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->deleteSingleRelation($obj, $refClass, $this->mapper::BELONGS_TO);
|
||||
$this->deleteHasMany($refClass, $obj, $objId);
|
||||
$this->deleteSingleRelation($obj, $this->mapper::BELONGS_TO, $refClass);
|
||||
$this->deleteHasMany($obj, $objId, $refClass);
|
||||
$this->deleteModel($objId);
|
||||
$this->deleteSingleRelation($obj, $refClass, $this->mapper::OWNS_ONE);
|
||||
$this->deleteSingleRelation($obj, $this->mapper::OWNS_ONE, $refClass);
|
||||
|
||||
return $objId;
|
||||
}
|
||||
|
|
@ -111,15 +111,15 @@ final class DeleteMapper extends DataMapperAbstract
|
|||
/**
|
||||
* Delete ownsOne, belongsTo relations
|
||||
*
|
||||
* @param object $obj Object to delete
|
||||
* @param \ReflectionClass $refClass Reflection of object to delete
|
||||
* @param array $relation Relation data (e.g. ::BELONGS_TO, ::OWNS_ONE)
|
||||
* @param object $obj Object to delete
|
||||
* @param array $relation Relation data (e.g. ::BELONGS_TO, ::OWNS_ONE)
|
||||
* @param null|\ReflectionClass $refClass Reflection of object to delete
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function deleteSingleRelation(object $obj, \ReflectionClass $refClass, array $relation) : void
|
||||
private function deleteSingleRelation(object $obj, array $relation, \ReflectionClass &$refClass = null) : void
|
||||
{
|
||||
if (empty($relation)) {
|
||||
return;
|
||||
|
|
@ -137,27 +137,36 @@ final class DeleteMapper extends DataMapperAbstract
|
|||
$relMapper = $this->createRelationMapper($mapper::delete(db: $this->db), $member);
|
||||
$relMapper->depth = $this->depth + 1;
|
||||
|
||||
$refProp = $refClass->getProperty($member);
|
||||
if (!$refProp->isPublic()) {
|
||||
$relMapper->execute($refProp->getValue($obj));
|
||||
$isPrivate = $relData['private'] ?? false;
|
||||
|
||||
$value = null;
|
||||
if ($isPrivate) {
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
$refProp = $refClass->getProperty($member);
|
||||
$value = $refProp->getValue($obj);
|
||||
} else {
|
||||
$relMapper->execute($obj->{$member});
|
||||
$value = $obj->{$member};
|
||||
}
|
||||
|
||||
$relMapper->execute($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete hasMany
|
||||
*
|
||||
* @param \ReflectionClass $refClass Reflection of object to delete
|
||||
* @param object $obj Object to delete
|
||||
* @param mixed $objId Object id to delete
|
||||
* @param object $obj Object to delete
|
||||
* @param mixed $objId Object id to delete
|
||||
* @param null|\ReflectionClass $refClass Reflection of object to delete
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function deleteHasMany(\ReflectionClass $refClass, object $obj, mixed $objId) : void
|
||||
private function deleteHasMany(object $obj, mixed $objId, \ReflectionClass &$refClass = null) : void
|
||||
{
|
||||
if (empty($this->mapper::HAS_MANY)) {
|
||||
return;
|
||||
|
|
@ -169,9 +178,20 @@ final class DeleteMapper extends DataMapperAbstract
|
|||
continue;
|
||||
}
|
||||
|
||||
$objIds = [];
|
||||
$refProp = $refClass->getProperty($member);
|
||||
$values = $refProp->isPublic() ? $obj->{$member} : $refProp->getValue($obj);
|
||||
$objIds = [];
|
||||
$isPrivate = $rel['private'] ?? false;
|
||||
|
||||
$values = null;
|
||||
if ($isPrivate) {
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
$refProp = $refClass->getProperty($member);
|
||||
$values = $refProp->getValue($obj);
|
||||
} else {
|
||||
$values = $obj->{$member};
|
||||
}
|
||||
|
||||
if (!\is_array($values)) {
|
||||
// conditionals
|
||||
|
|
|
|||
|
|
@ -555,7 +555,7 @@ final class ReadMapper extends DataMapperAbstract
|
|||
*/
|
||||
public function populateAbstract(array $result, object $obj) : object
|
||||
{
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
$refClass = null;
|
||||
|
||||
foreach ($this->mapper::COLUMNS as $column => $def) {
|
||||
$alias = $column . '_d' . $this->depth;
|
||||
|
|
@ -569,28 +569,42 @@ final class ReadMapper extends DataMapperAbstract
|
|||
$hasPath = false;
|
||||
$aValue = [];
|
||||
$arrayPath = '';
|
||||
$refProp = null;
|
||||
$isPrivate = $def['private'] ?? false;
|
||||
$member = '';
|
||||
|
||||
if ($isPrivate && $refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
if (\stripos($def['internal'], '/') !== false) {
|
||||
$hasPath = true;
|
||||
$path = \explode('/', \ltrim($def['internal'], '/'));
|
||||
$member = $path[0];
|
||||
|
||||
$refProp = $refClass->getProperty($path[0]);
|
||||
$isPublic = $refProp->isPublic();
|
||||
$aValue = $isPublic ? $obj->{$path[0]} : $refProp->getValue($obj);
|
||||
if ($isPrivate) {
|
||||
$refProp = $refClass->getProperty($path[0]);
|
||||
$aValue = $refProp->getValue($obj);
|
||||
} else {
|
||||
$aValue = $obj->{$path[0]};
|
||||
}
|
||||
|
||||
\array_shift($path);
|
||||
$arrayPath = \implode('/', $path);
|
||||
} else {
|
||||
$refProp = $refClass->getProperty($def['internal']);
|
||||
$isPublic = $refProp->isPublic();
|
||||
$member = $def['internal'];
|
||||
if ($isPrivate) {
|
||||
$refProp = $refClass->getProperty($def['internal']);
|
||||
}
|
||||
|
||||
$member = $def['internal'];
|
||||
}
|
||||
|
||||
if (isset($this->mapper::OWNS_ONE[$def['internal']])) {
|
||||
$default = null;
|
||||
if (!isset($this->with[$member]) && $refProp->isInitialized($obj)) {
|
||||
$default = $isPublic ? $obj->{$def['internal']} : $refProp->getValue($obj);
|
||||
if (!isset($this->with[$member])
|
||||
&& ($isPrivate ? $refProp->isInitialized($obj) : isset($obj->{$member}))
|
||||
) {
|
||||
$default = $isPrivate ? $refProp->getValue($obj) : $obj->{$member};
|
||||
}
|
||||
|
||||
$value = $this->populateOwnsOne($def['internal'], $result, $default);
|
||||
|
|
@ -600,14 +614,16 @@ final class ReadMapper extends DataMapperAbstract
|
|||
$this->mapper::OWNS_ONE[$def['internal']]['mapper']::reader(db: $this->db)->loadHasManyRelations($value);
|
||||
}
|
||||
|
||||
if (!empty($value)) {
|
||||
if (empty($value)) {
|
||||
// @todo: find better solution. this was because of a bug with the sales billing list query depth = 4. The address was set (from the client, referral or creator) but then somehow there was a second address element which was all null and null cannot be asigned to a string variable (e.g. country). The problem with this solution is that if the model expects an initialization (e.g. at lest set the elements to null, '', 0 etc.) this is now not done.
|
||||
$refProp->setValue($obj, $value);
|
||||
$value = $isPrivate ? $refProp->getValue($obj) : $obj->{$member};
|
||||
}
|
||||
} elseif (isset($this->mapper::BELONGS_TO[$def['internal']])) {
|
||||
$default = null;
|
||||
if (!isset($this->with[$member]) && $refProp->isInitialized($obj)) {
|
||||
$default = $isPublic ? $obj->{$def['internal']} : $refProp->getValue($obj);
|
||||
if (!isset($this->with[$member])
|
||||
&& ($isPrivate ? $refProp->isInitialized($obj) : isset($obj->{$member}))
|
||||
) {
|
||||
$default = $isPrivate ? $refProp->getValue($obj) : $obj->{$member};
|
||||
}
|
||||
|
||||
$value = $this->populateBelongsTo($def['internal'], $result, $default);
|
||||
|
|
@ -616,8 +632,6 @@ final class ReadMapper extends DataMapperAbstract
|
|||
if (\is_object($value) && isset($this->mapper::BELONGS_TO[$def['internal']]['mapper'])) {
|
||||
$this->mapper::BELONGS_TO[$def['internal']]['mapper']::reader(db: $this->db)->loadHasManyRelations($value);
|
||||
}
|
||||
|
||||
$refProp->setValue($obj, $value);
|
||||
} elseif (\in_array($def['type'], ['string', 'compress', 'int', 'float', 'bool'])) {
|
||||
if ($value !== null && $def['type'] === 'compress') {
|
||||
$def['type'] = 'string';
|
||||
|
|
@ -625,44 +639,44 @@ final class ReadMapper extends DataMapperAbstract
|
|||
$value = \gzinflate($value);
|
||||
}
|
||||
|
||||
if ($value !== null || $refProp->getValue($obj) !== null) {
|
||||
$mValue = $isPrivate ? $refProp->getValue($obj) : $obj->{$member};
|
||||
if ($value !== null || $mValue !== null) {
|
||||
\settype($value, $def['type']);
|
||||
}
|
||||
|
||||
if ($hasPath) {
|
||||
$value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true);
|
||||
}
|
||||
|
||||
$refProp->setValue($obj, $value);
|
||||
} elseif ($def['type'] === 'DateTime') {
|
||||
$value = $value === null ? null : new \DateTime($value);
|
||||
$value ??= new \DateTime($value);
|
||||
if ($hasPath) {
|
||||
$value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true);
|
||||
}
|
||||
|
||||
$refProp->setValue($obj, $value);
|
||||
} elseif ($def['type'] === 'DateTimeImmutable') {
|
||||
$value = $value === null ? null : new \DateTimeImmutable($value);
|
||||
$value ??= new \DateTimeImmutable($value);
|
||||
if ($hasPath) {
|
||||
$value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true);
|
||||
}
|
||||
|
||||
$refProp->setValue($obj, $value);
|
||||
} elseif ($def['type'] === 'Json') {
|
||||
if ($hasPath) {
|
||||
$value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true);
|
||||
}
|
||||
|
||||
$refProp->setValue($obj, \json_decode($value, true));
|
||||
$value = \json_decode($value, true);
|
||||
} elseif ($def['type'] === 'Serializable') {
|
||||
$member = $isPublic ? $obj->{$def['internal']} : $refProp->getValue($obj);
|
||||
$mObj = $isPrivate ? $refProp->getValue($obj) : $obj->{$member};
|
||||
|
||||
if ($member === null || $value === null) {
|
||||
$obj->{$def['internal']} = $value;
|
||||
} else {
|
||||
$member->unserialize($value);
|
||||
if ($mObj !== null && $value !== null) {
|
||||
$mObj->unserialize($value);
|
||||
$value = $mObj;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isPrivate) {
|
||||
$refProp->setValue($obj, $value);
|
||||
} else {
|
||||
$obj->{$member} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->mapper::HAS_MANY as $member => $def) {
|
||||
|
|
@ -677,54 +691,68 @@ final class ReadMapper extends DataMapperAbstract
|
|||
$hasPath = false;
|
||||
$aValue = null;
|
||||
$arrayPath = '/';
|
||||
$refProp = null;
|
||||
$isPrivate = $def['private'] ?? false;
|
||||
|
||||
if ($isPrivate && $refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
if (\stripos($member, '/') !== false) {
|
||||
$hasPath = true;
|
||||
$path = \explode('/', $member);
|
||||
$refProp = $refClass->getProperty($path[0]);
|
||||
$isPublic = $refProp->isPublic();
|
||||
$member = $path[0];
|
||||
|
||||
if ($isPrivate) {
|
||||
$refProp = $refClass->getProperty($path[0]);
|
||||
}
|
||||
|
||||
\array_shift($path);
|
||||
$arrayPath = \implode('/', $path);
|
||||
$aValue = $isPublic ? $obj->{$path[0]} : $refProp->getValue($obj);
|
||||
} else {
|
||||
$aValue = $isPrivate ? $refProp->getValue($obj) : $obj->{$path[0]};
|
||||
} elseif ($isPrivate) {
|
||||
$refProp = $refClass->getProperty($member);
|
||||
$isPublic = $refProp->isPublic();
|
||||
}
|
||||
|
||||
if (\in_array($def['mapper']::COLUMNS[$column]['type'], ['string', 'int', 'float', 'bool'])) {
|
||||
if ($value !== null || $refProp->getValue($obj) !== null) {
|
||||
if ($value !== null
|
||||
|| ($isPrivate ? $refProp->getValue($obj) !== null : $obj->{$member} !== null)
|
||||
) {
|
||||
\settype($value, $def['mapper']::COLUMNS[$column]['type']);
|
||||
}
|
||||
|
||||
if ($hasPath) {
|
||||
$value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true);
|
||||
}
|
||||
|
||||
$refProp->setValue($obj, $value);
|
||||
} elseif ($def['mapper']::COLUMNS[$column]['type'] === 'DateTime') {
|
||||
$value = $value === null ? null : new \DateTime($value);
|
||||
$value ??= new \DateTime($value);
|
||||
if ($hasPath) {
|
||||
$value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true);
|
||||
}
|
||||
|
||||
$refProp->setValue($obj, $value);
|
||||
} elseif ($def['mapper']::COLUMNS[$column]['type'] === 'DateTimeImmutable') {
|
||||
$value = $value === null ? null : new \DateTimeImmutable($value);
|
||||
$value ??= new \DateTimeImmutable($value);
|
||||
if ($hasPath) {
|
||||
$value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true);
|
||||
}
|
||||
|
||||
$refProp->setValue($obj, $value);
|
||||
} elseif ($def['mapper']::COLUMNS[$column]['type'] === 'Json') {
|
||||
if ($hasPath) {
|
||||
$value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true);
|
||||
}
|
||||
|
||||
$refProp->setValue($obj, \json_decode($value, true));
|
||||
$value = \json_decode($value, true);
|
||||
} elseif ($def['mapper']::COLUMNS[$column]['type'] === 'Serializable') {
|
||||
$member = $isPublic ? $obj->{$member} : $refProp->getValue($obj);
|
||||
$member->unserialize($value);
|
||||
$mObj = $isPrivate ? $refProp->getValue($obj) : $obj->{$member};
|
||||
|
||||
if ($mObj !== null && $value !== null) {
|
||||
$mObj->unserialize($value);
|
||||
$value = $mObj;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isPrivate) {
|
||||
$refProp->setValue($obj, $value);
|
||||
} else {
|
||||
$obj->{$member} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -867,6 +895,8 @@ final class ReadMapper extends DataMapperAbstract
|
|||
continue;
|
||||
}
|
||||
|
||||
$isPrivate = $withData['private'] ?? false;
|
||||
|
||||
$objectMapper = $this->createRelationMapper($many['mapper']::get(db: $this->db), $member);
|
||||
if ($many['external'] === null/* same as $many['table'] !== $many['mapper']::TABLE */) {
|
||||
$objectMapper->where($many['mapper']::COLUMNS[$many['self']]['internal'], $primaryKey);
|
||||
|
|
@ -886,12 +916,12 @@ final class ReadMapper extends DataMapperAbstract
|
|||
continue;
|
||||
}
|
||||
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
if ($isPrivate) {
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
$refProp = $refClass->getProperty($member);
|
||||
if (!$refProp->isPublic()) {
|
||||
$refProp = $refClass->getProperty($member);
|
||||
$refProp->setValue($obj, !\is_array($objects) && ($many['conditional'] ?? false) === false
|
||||
? [$many['mapper']::getObjectId($objects) => $objects]
|
||||
: $objects // if conditional === true the obj will be asigned (e.g. has many localizations but only one is loaded for the model)
|
||||
|
|
@ -914,15 +944,16 @@ final class ReadMapper extends DataMapperAbstract
|
|||
continue;
|
||||
}
|
||||
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
/** @var ReadMapper $relMapper */
|
||||
$relMapper = $this->createRelationMapper($relation['mapper']::reader($this->db), $member);
|
||||
|
||||
$refProp = $refClass->getProperty($member);
|
||||
if (!$refProp->isPublic()) {
|
||||
$isPrivate = $withData['private'] ?? false;
|
||||
if ($isPrivate) {
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
$refProp = $refClass->getProperty($member);
|
||||
$relMapper->loadHasManyRelations($refProp->getValue($obj));
|
||||
} else {
|
||||
$relMapper->loadHasManyRelations($obj->{$member});
|
||||
|
|
|
|||
|
|
@ -73,14 +73,14 @@ final class UpdateMapper extends DataMapperAbstract
|
|||
*/
|
||||
public function executeUpdate(object $obj) : mixed
|
||||
{
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
$refClass = null;
|
||||
$objId = $this->mapper::getObjectId($obj);
|
||||
|
||||
if ($this->mapper::isNullModel($obj)) {
|
||||
return $objId === 0 ? null : $objId;
|
||||
}
|
||||
|
||||
$this->updateHasMany($refClass, $obj, $objId);
|
||||
$this->updateHasMany($obj, $objId, $refClass);
|
||||
|
||||
if (empty($objId)) {
|
||||
return $this->mapper::create(db: $this->db)->execute($obj);
|
||||
|
|
@ -102,7 +102,7 @@ final class UpdateMapper extends DataMapperAbstract
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function updateModel(object $obj, mixed $objId, \ReflectionClass $refClass = null) : void
|
||||
private function updateModel(object $obj, mixed $objId, \ReflectionClass &$refClass = null) : void
|
||||
{
|
||||
try {
|
||||
// Model doesn't have anything to update
|
||||
|
|
@ -124,10 +124,20 @@ final class UpdateMapper extends DataMapperAbstract
|
|||
continue;
|
||||
}
|
||||
|
||||
$refClass = $refClass ?? new \ReflectionClass($obj);
|
||||
$property = $refClass->getProperty($propertyName);
|
||||
$isPrivate = $column['private'] ?? false;
|
||||
$property = null;
|
||||
$tValue = null;
|
||||
|
||||
$tValue = $property->isPublic() ? $obj->{$propertyName} : $property->getValue($obj);
|
||||
if ($isPrivate) {
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
$property = $refClass->getProperty($propertyName);
|
||||
$tValue = $property->getValue($obj);
|
||||
} else {
|
||||
$tValue = $obj->{$propertyName};
|
||||
}
|
||||
|
||||
if (isset($this->mapper::OWNS_ONE[$propertyName])) {
|
||||
$id = \is_object($tValue) ? $this->updateOwnsOne($propertyName, $tValue) : $tValue;
|
||||
|
|
@ -218,9 +228,9 @@ final class UpdateMapper extends DataMapperAbstract
|
|||
/**
|
||||
* Update has many relations
|
||||
*
|
||||
* @param \ReflectionClass $refClass Reflection of the object containing the relations
|
||||
* @param object $obj Object which contains the relations
|
||||
* @param mixed $objId Object id which contains the relations
|
||||
* @param object $obj Object which contains the relations
|
||||
* @param mixed $objId Object id which contains the relations
|
||||
* @param null|\ReflectionClass $refClass Reflection of the object containing the relations
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
|
|
@ -228,7 +238,7 @@ final class UpdateMapper extends DataMapperAbstract
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function updateHasMany(\ReflectionClass $refClass, object $obj, mixed $objId) : void
|
||||
private function updateHasMany(object $obj, mixed $objId, \ReflectionClass &$refClass = null) : void
|
||||
{
|
||||
if (empty($this->with) || empty($this->mapper::HAS_MANY)) {
|
||||
return;
|
||||
|
|
@ -245,17 +255,33 @@ final class UpdateMapper extends DataMapperAbstract
|
|||
throw new InvalidMapperException();
|
||||
}
|
||||
|
||||
$property = $refClass->getProperty($propertyName);
|
||||
$isPrivate = $rel['private'] ?? false;
|
||||
$property = null;
|
||||
$values = null;
|
||||
|
||||
$values = ($isPublic = $property->isPublic()) ? $obj->{$propertyName} : $property->getValue($obj);
|
||||
if ($isPrivate) {
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
$property = $refClass->getProperty($propertyName);
|
||||
$values = $property->getValue($obj);
|
||||
} else {
|
||||
$values = $obj->{$propertyName};
|
||||
}
|
||||
|
||||
if (!\is_array($values) || empty($values)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var class-string<DataMapperFactory> $mapper */
|
||||
$mapper = $this->mapper::HAS_MANY[$propertyName]['mapper'];
|
||||
$relReflectionClass = new \ReflectionClass(\reset($values));
|
||||
$mapper = $this->mapper::HAS_MANY[$propertyName]['mapper'];
|
||||
$isPrivateRel = $this->mapper::HAS_MANY[$propertyName]['private'] ?? false;
|
||||
|
||||
if ($isPrivateRel) {
|
||||
$relReflectionClass = new \ReflectionClass(\reset($values));
|
||||
}
|
||||
|
||||
$objsIds[$propertyName] = [];
|
||||
|
||||
foreach ($values as $key => &$value) {
|
||||
|
|
@ -285,9 +311,8 @@ final class UpdateMapper extends DataMapperAbstract
|
|||
if ($this->mapper::HAS_MANY[$propertyName]['table'] === $this->mapper::HAS_MANY[$propertyName]['mapper']::TABLE
|
||||
&& isset($mapper::COLUMNS[$this->mapper::HAS_MANY[$propertyName]['self']])
|
||||
) {
|
||||
$relProperty = $relReflectionClass->getProperty($mapper::COLUMNS[$this->mapper::HAS_MANY[$propertyName]['self']]['internal']);
|
||||
|
||||
if (!$isPublic) {
|
||||
if ($isPrivateRel) {
|
||||
$relProperty = $relReflectionClass->getProperty($mapper::COLUMNS[$this->mapper::HAS_MANY[$propertyName]['self']]['internal']);
|
||||
$relProperty->setValue($value, $objId);
|
||||
} else {
|
||||
$value->{$mapper::COLUMNS[$this->mapper::HAS_MANY[$propertyName]['self']]['internal']} = $objId;
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ final class WriteMapper extends DataMapperAbstract
|
|||
*/
|
||||
public function executeCreate(object $obj) : mixed
|
||||
{
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
$refClass = null;
|
||||
|
||||
if ($this->mapper::isNullModel($obj)) {
|
||||
$objId = $this->mapper::getObjectId($obj);
|
||||
|
|
@ -86,10 +86,10 @@ final class WriteMapper extends DataMapperAbstract
|
|||
$objId = $id;
|
||||
} else {
|
||||
$objId = $this->createModel($obj, $refClass);
|
||||
$this->mapper::setObjectId($refClass, $obj, $objId);
|
||||
$this->mapper::setObjectId($obj, $objId, $refClass);
|
||||
}
|
||||
|
||||
$this->createHasMany($refClass, $obj, $objId);
|
||||
$this->createHasMany($obj, $objId, $refClass);
|
||||
|
||||
return $objId;
|
||||
}
|
||||
|
|
@ -97,21 +97,19 @@ final class WriteMapper extends DataMapperAbstract
|
|||
/**
|
||||
* Create model
|
||||
*
|
||||
* @param object $obj Object to create
|
||||
* @param \ReflectionClass $refClass Reflection of the object to create
|
||||
* @param object $obj Object to create
|
||||
* @param null|\ReflectionClass $refClass Reflection of the object to create
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function createModel(object $obj, \ReflectionClass $refClass) : mixed
|
||||
private function createModel(object $obj, \ReflectionClass &$refClass = null) : mixed
|
||||
{
|
||||
try {
|
||||
$query = new Builder($this->db);
|
||||
$query->into($this->mapper::TABLE);
|
||||
|
||||
$publicProperties = \get_object_vars($obj);
|
||||
|
||||
foreach ($this->mapper::COLUMNS as $column) {
|
||||
$propertyName = \stripos($column['internal'], '/') !== false
|
||||
? \explode('/', $column['internal'])[0]
|
||||
|
|
@ -123,13 +121,16 @@ final class WriteMapper extends DataMapperAbstract
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!isset($publicProperties[$propertyName])) {
|
||||
$tValue = null;
|
||||
if ($column['private'] ?? false) {
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
$property = $refClass->getProperty($propertyName);
|
||||
$property->setAccessible(true);
|
||||
$tValue = $property->getValue($obj);
|
||||
$property->setAccessible(false);
|
||||
$tValue = $property->getValue($obj);
|
||||
} else {
|
||||
$tValue = $publicProperties[$propertyName];
|
||||
$tValue = $obj->{$propertyName};
|
||||
}
|
||||
|
||||
if (isset($this->mapper::OWNS_ONE[$propertyName])) {
|
||||
|
|
@ -231,10 +232,13 @@ final class WriteMapper extends DataMapperAbstract
|
|||
if (isset($this->mapper::BELONGS_TO[$propertyName]['by'])) {
|
||||
// has by (obj is stored as a different model e.g. model = profile but reference/db is account)
|
||||
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
$refProp = $refClass->getProperty($this->mapper::BELONGS_TO[$propertyName]['by']);
|
||||
|
||||
$obj = $refProp->isPublic() ? $obj->{$this->mapper::BELONGS_TO[$propertyName]['by']} : $refProp->getValue($obj);
|
||||
if ($this->mapper::BELONGS_TO[$propertyName]['private']) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
$refProp = $refClass->getProperty($this->mapper::BELONGS_TO[$propertyName]['by']);
|
||||
$obj = $refProp->getValue($obj);
|
||||
} else {
|
||||
$obj = $obj->{$this->mapper::BELONGS_TO[$propertyName]['by']};
|
||||
}
|
||||
}
|
||||
|
||||
/** @var class-string<DataMapperFactory> $mapper */
|
||||
|
|
@ -248,9 +252,9 @@ final class WriteMapper extends DataMapperAbstract
|
|||
/**
|
||||
* Create has many models
|
||||
*
|
||||
* @param \ReflectionClass $refClass Reflection of the object to create
|
||||
* @param object $obj Object to create
|
||||
* @param mixed $objId Id of the parent object
|
||||
* @param object $obj Object to create
|
||||
* @param mixed $objId Id of the parent object
|
||||
* @param null|\ReflectionClass $refClass Reflection of the object to create
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
|
|
@ -258,15 +262,27 @@ final class WriteMapper extends DataMapperAbstract
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function createHasMany(\ReflectionClass $refClass, object $obj, mixed $objId) : void
|
||||
private function createHasMany(object $obj, mixed $objId, \ReflectionClass &$refClass = null) : void
|
||||
{
|
||||
foreach ($this->mapper::HAS_MANY as $propertyName => $_) {
|
||||
foreach ($this->mapper::HAS_MANY as $propertyName => $rel) {
|
||||
if (!isset($this->mapper::HAS_MANY[$propertyName]['mapper'])) {
|
||||
throw new InvalidMapperException(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$property = $refClass->getProperty($propertyName);
|
||||
$values = $property->isPublic() ? $obj->{$propertyName} : $property->getValue($obj);
|
||||
$isPrivate = $rel['private'] ?? false;
|
||||
$property = null;
|
||||
$values = null;
|
||||
|
||||
if ($isPrivate) {
|
||||
if ($refClass === null) {
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
}
|
||||
|
||||
$property = $refClass->getProperty($propertyName);
|
||||
$values = $property->getValue($obj);
|
||||
} else {
|
||||
$values = $obj->{$propertyName};
|
||||
}
|
||||
|
||||
/** @var class-string<DataMapperFactory> $mapper */
|
||||
$mapper = $this->mapper::HAS_MANY[$propertyName]['mapper'];
|
||||
|
|
@ -274,17 +290,16 @@ final class WriteMapper extends DataMapperAbstract
|
|||
? $mapper::COLUMNS[$this->mapper::HAS_MANY[$propertyName]['self']]['internal']
|
||||
: 'ERROR';
|
||||
|
||||
// @todo: this or $isRelPrivate is wrong, don't know which one.
|
||||
$isInternalPrivate =$mapper::COLUMNS[$this->mapper::HAS_MANY[$propertyName]['self']]['private'] ?? false;
|
||||
|
||||
if (\is_object($values)) {
|
||||
// conditionals
|
||||
$publicProperties = \get_object_vars($values);
|
||||
|
||||
if (!isset($publicProperties[$internalName])) {
|
||||
if ($isInternalPrivate) {
|
||||
$relReflectionClass = new \ReflectionClass($values);
|
||||
$relProperty = $relReflectionClass->getProperty($internalName);
|
||||
|
||||
$relProperty->setAccessible(true);
|
||||
$relProperty->setValue($values, $objId);
|
||||
$relProperty->setAccessible(false);
|
||||
} else {
|
||||
$values->{$internalName} = $objId;
|
||||
}
|
||||
|
|
@ -297,7 +312,8 @@ final class WriteMapper extends DataMapperAbstract
|
|||
}
|
||||
|
||||
$objsIds = [];
|
||||
$relReflectionClass = empty($values) ? null : new \ReflectionClass(\reset($values));
|
||||
$isRelPrivate = $mapper::COLUMNS[$this->mapper::HAS_MANY[$propertyName]['self']]['private'] ?? false;
|
||||
$relReflectionClass = $isRelPrivate && !empty($values) ? new \ReflectionClass(\reset($values)) : null;
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
if (!\is_object($value)) {
|
||||
|
|
@ -307,7 +323,6 @@ final class WriteMapper extends DataMapperAbstract
|
|||
continue;
|
||||
}
|
||||
|
||||
/** @var \ReflectionClass $relReflectionClass */
|
||||
$primaryKey = $mapper::getObjectId($value);
|
||||
|
||||
// already in db
|
||||
|
|
@ -319,26 +334,24 @@ final class WriteMapper extends DataMapperAbstract
|
|||
|
||||
// Setting relation value (id) for relation (since the relation is not stored in an extra relation table)
|
||||
if (!isset($this->mapper::HAS_MANY[$propertyName]['external'])) {
|
||||
$relProperty = $relReflectionClass->getProperty($internalName);
|
||||
$isRelPublic = $relProperty->isPublic();
|
||||
$relProperty = null;
|
||||
if ($isRelPrivate) {
|
||||
$relProperty = $relReflectionClass->getProperty($internalName);
|
||||
}
|
||||
|
||||
// todo maybe consider to just set the column type to object, and then check for that (might be faster)
|
||||
if (isset($mapper::BELONGS_TO[$internalName])
|
||||
|| isset($mapper::OWNS_ONE[$internalName])) {
|
||||
if (!$isRelPublic) {
|
||||
if ($isRelPrivate) {
|
||||
$relProperty->setValue($value, $this->mapper::createNullModel($objId));
|
||||
} else {
|
||||
$value->{$internalName} = $this->mapper::createNullModel($objId);
|
||||
}
|
||||
} elseif (!$isRelPublic) {
|
||||
} elseif ($isRelPrivate) {
|
||||
$relProperty->setValue($value, $objId);
|
||||
} else {
|
||||
$value->{$internalName} = $objId;
|
||||
}
|
||||
|
||||
if (!$isRelPublic) {
|
||||
$relProperty->setAccessible(false);
|
||||
}
|
||||
}
|
||||
|
||||
$objsIds[$key] = $mapper::create(db: $this->db)->execute($value);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user