fix datamapper bugs

This commit is contained in:
Dennis Eichhorn 2020-11-29 18:29:35 +01:00
parent 6443ab6c14
commit 1e19f72fc4
4 changed files with 119 additions and 127 deletions

View File

@ -548,36 +548,42 @@ class DataMapperAbstract implements DataMapperInterface
} }
$property = $refClass->getProperty($propertyName); $property = $refClass->getProperty($propertyName);
if (!$property->isPublic()) {
if (!($isPublic = $property->isPublic())) {
$property->setAccessible(true); $property->setAccessible(true);
$tValue = $property->getValue($obj);
$property->setAccessible(false);
} else {
$tValue = $obj->$propertyName;
} }
if (isset(static::$ownsOne[$propertyName])) { if (isset(static::$ownsOne[$propertyName])) {
$id = self::createOwnsOne($propertyName, $property->getValue($obj)); $id = self::createOwnsOne($propertyName, $tValue);
$value = self::parseValue($column['type'], $id); $value = self::parseValue($column['type'], $id);
$query->insert($column['name'])->value($value); $query->insert($column['name'])->value($value);
} elseif (isset(static::$belongsTo[$propertyName])) { } elseif (isset(static::$belongsTo[$propertyName])) {
$id = self::createBelongsTo($propertyName, $property->getValue($obj)); $id = self::createBelongsTo($propertyName, $tValue);
$value = self::parseValue($column['type'], $id); $value = self::parseValue($column['type'], $id);
$query->insert($column['name'])->value($value); $query->insert($column['name'])->value($value);
} elseif ($column['name'] !== static::$primaryField || !empty($property->getValue($obj))) { } elseif ($column['name'] !== static::$primaryField || !empty($tValue)) {
$tValue = $property->getValue($obj);
if (\stripos($column['internal'], '/') !== false) { if (\stripos($column['internal'], '/') !== false) {
$path = \substr($column['internal'], \stripos($column['internal'], '/') + 1); $path = \substr($column['internal'], \stripos($column['internal'], '/') + 1);
$tValue = ArrayUtils::getArray($path, $tValue, '/'); $tValue = ArrayUtils::getArray($path, $tValue, '/');
} }
/*
if (($column['type'] === 'int' || $column['type'] === 'string')
&& \is_object($tValue) && \property_exists($tValue, 'id')
) {
$tValue =
}
*/
$value = self::parseValue($column['type'], $tValue); $value = self::parseValue($column['type'], $tValue);
$query->insert($column['name'])->value($value); $query->insert($column['name'])->value($value);
} }
if (!$isPublic) {
$property->setAccessible(false);
}
} }
// if a table only has a single column = primary key column. This must be done otherwise the query is empty // if a table only has a single column = primary key column. This must be done otherwise the query is empty
@ -664,17 +670,16 @@ class DataMapperAbstract implements DataMapperInterface
*/ */
public static function getObjectId(object $obj, \ReflectionClass $refClass = null) public static function getObjectId(object $obj, \ReflectionClass $refClass = null)
{ {
$refClass ??= new \ReflectionClass($obj); $refClass ??= new \ReflectionClass($obj);
$refProp = $refClass->getProperty(static::$columns[static::$primaryField]['internal']); $propertyName = static::$columns[static::$primaryField]['internal'];
$refProp = $refClass->getProperty($propertyName);
if (!($isPublic = $refProp->isPublic())) { if (!$refProp->isPublic()) {
$refProp->setAccessible(true); $refProp->setAccessible(true);
} $objectId = $refProp->getValue($obj);
$objectId = $refProp->getValue($obj);
if (!$isPublic) {
$refProp->setAccessible(false); $refProp->setAccessible(false);
} else {
$objectId = $obj->$propertyName;
} }
return $objectId; return $objectId;
@ -693,17 +698,16 @@ class DataMapperAbstract implements DataMapperInterface
*/ */
private static function setObjectId(\ReflectionClass $refClass, object $obj, $objId) : void private static function setObjectId(\ReflectionClass $refClass, object $obj, $objId) : void
{ {
$refProp = $refClass->getProperty(static::$columns[static::$primaryField]['internal']); $propertyName = static::$columns[static::$primaryField]['internal'];
$refProp = $refClass->getProperty($propertyName);
if (!($isPublic = $refProp->isPublic())) {
$refProp->setAccessible(true);
}
\settype($objId, static::$columns[static::$primaryField]['type']); \settype($objId, static::$columns[static::$primaryField]['type']);
$refProp->setValue($obj, $objId); if (!$refProp->isPublic()) {
$refProp->setAccessible(true);
if (!$isPublic) { $refProp->setValue($obj, $objId);
$refProp->setAccessible(false); $refProp->setAccessible(false);
} else {
$obj->$propertyName = $objId;
} }
} }
@ -756,10 +760,11 @@ class DataMapperAbstract implements DataMapperInterface
if (!($isPublic = $property->isPublic())) { if (!($isPublic = $property->isPublic())) {
$property->setAccessible(true); $property->setAccessible(true);
$values = $property->getValue($obj);
} else {
$values = $obj->$propertyName;
} }
$values = $property->getValue($obj);
/** @var self $mapper */ /** @var self $mapper */
$mapper = static::$hasMany[$propertyName]['mapper']; $mapper = static::$hasMany[$propertyName]['mapper'];
$internalName = isset($mapper::$columns[static::$hasMany[$propertyName]['self']]) ? $mapper::$columns[static::$hasMany[$propertyName]['self']]['internal'] : 'ERROR'; $internalName = isset($mapper::$columns[static::$hasMany[$propertyName]['self']]) ? $mapper::$columns[static::$hasMany[$propertyName]['self']]['internal'] : 'ERROR';
@ -769,22 +774,19 @@ class DataMapperAbstract implements DataMapperInterface
$relReflectionClass = new \ReflectionClass($values); $relReflectionClass = new \ReflectionClass($values);
$relProperty = $relReflectionClass->getProperty($internalName); $relProperty = $relReflectionClass->getProperty($internalName);
if (!($isPublicRel = $relProperty->isPublic())) { if (!$relProperty->isPublic()) {
$relProperty->setAccessible(true); $relProperty->setAccessible(true);
} $relProperty->setValue($values, $objId);
$relProperty->setValue($values, $objId);
if (!$isPublicRel) {
$relProperty->setAccessible(false); $relProperty->setAccessible(false);
} else {
$values->$internalName = $objId;
} }
$mapper::create($values);
if (!$isPublic) { if (!$isPublic) {
$property->setAccessible(false); $property->setAccessible(false);
} }
$mapper::create($values);
continue; continue;
} elseif (!\is_array($values)) { } elseif (!\is_array($values)) {
if (!$isPublic) { if (!$isPublic) {
@ -832,9 +834,17 @@ class DataMapperAbstract implements DataMapperInterface
if (isset($mapper::$belongsTo[$internalName]) if (isset($mapper::$belongsTo[$internalName])
|| isset($mapper::$ownsOne[$internalName]) || isset($mapper::$ownsOne[$internalName])
) { ) {
$relProperty->setValue($value, self::createNullModel($objId)); if (!$isPublic) {
$relProperty->setValue($value, self::createNullModel($objId));
} else {
$value->$internalName = self::createNullModel($objId);
}
} else { } else {
$relProperty->setValue($value, $objId); if (!$isPublic) {
$relProperty->setValue($value, $objId);
} else {
$value->$internalName = $objId;
}
} }
if (!$isPublic) { if (!$isPublic) {
@ -1125,19 +1135,17 @@ class DataMapperAbstract implements DataMapperInterface
if (!($isPublic = $property->isPublic())) { if (!($isPublic = $property->isPublic())) {
$property->setAccessible(true); $property->setAccessible(true);
$values = $property->getValue($obj);
$property->setAccessible(false);
} else {
$values = $obj->$propertyName;
} }
$values = $property->getValue($obj);
if (!\is_array($values)) { if (!\is_array($values)) {
// conditionals // conditionals
continue; continue;
} }
if (!$isPublic) {
$property->setAccessible(false);
}
/** @var self $mapper */ /** @var self $mapper */
$mapper = static::$hasMany[$propertyName]['mapper']; $mapper = static::$hasMany[$propertyName]['mapper'];
$relReflectionClass = !empty($values) ? new \ReflectionClass(\reset($values)) : null; $relReflectionClass = !empty($values) ? new \ReflectionClass(\reset($values)) : null;
@ -1171,12 +1179,10 @@ class DataMapperAbstract implements DataMapperInterface
if (!$isPublic) { if (!$isPublic) {
$relProperty->setAccessible(true); $relProperty->setAccessible(true);
} $relProperty->setValue($value, $objId);
$relProperty->setValue($value, $objId);
if (!$isPublic) {
$relProperty->setAccessible(false); $relProperty->setAccessible(false);
} else {
$value->$mapper::$columns[static::$hasMany[$propertyName]['self']]['internal'] = $objId;
} }
} }
@ -1446,10 +1452,14 @@ class DataMapperAbstract implements DataMapperInterface
if (!($isPublic = $property->isPublic())) { if (!($isPublic = $property->isPublic())) {
$property->setAccessible(true); $property->setAccessible(true);
$tValue = $property->getValue($obj);
$property->setAccessible(false);
} else {
$tValue = $obj->$propertyName;
} }
if (isset(static::$ownsOne[$propertyName])) { if (isset(static::$ownsOne[$propertyName])) {
$id = self::updateOwnsOne($propertyName, $property->getValue($obj), $depth); $id = self::updateOwnsOne($propertyName, $tValue, $depth);
$value = self::parseValue($column['type'], $id); $value = self::parseValue($column['type'], $id);
/** /**
@ -1460,7 +1470,7 @@ class DataMapperAbstract implements DataMapperInterface
*/ */
$query->set([static::$table . '.' . $column['name'] => $value]); $query->set([static::$table . '.' . $column['name'] => $value]);
} elseif (isset(static::$belongsTo[$propertyName])) { } elseif (isset(static::$belongsTo[$propertyName])) {
$id = self::updateBelongsTo($propertyName, $property->getValue($obj), $depth); $id = self::updateBelongsTo($propertyName, $tValue, $depth);
$value = self::parseValue($column['type'], $id); $value = self::parseValue($column['type'], $id);
/** /**
@ -1471,7 +1481,6 @@ class DataMapperAbstract implements DataMapperInterface
*/ */
$query->set([static::$table . '.' . $column['name'] => $value]); $query->set([static::$table . '.' . $column['name'] => $value]);
} elseif ($column['name'] !== static::$primaryField) { } elseif ($column['name'] !== static::$primaryField) {
$tValue = $property->getValue($obj);
if (\stripos($column['internal'], '/') !== false) { if (\stripos($column['internal'], '/') !== false) {
$path = \substr($column['internal'], \stripos($column['internal'], '/') + 1); $path = \substr($column['internal'], \stripos($column['internal'], '/') + 1);
$tValue = ArrayUtils::getArray($path, $tValue, '/'); $tValue = ArrayUtils::getArray($path, $tValue, '/');
@ -1481,10 +1490,6 @@ class DataMapperAbstract implements DataMapperInterface
$query->set([static::$table . '.' . $column['name'] => $value]); $query->set([static::$table . '.' . $column['name'] => $value]);
} }
if (!$isPublic) {
$property->setAccessible(false);
}
} }
self::$db->con->prepare($query->toSql())->execute(); self::$db->con->prepare($query->toSql())->execute();
@ -1668,19 +1673,17 @@ class DataMapperAbstract implements DataMapperInterface
if (!($isPublic = $property->isPublic())) { if (!($isPublic = $property->isPublic())) {
$property->setAccessible(true); $property->setAccessible(true);
$values = $property->getValue($obj);
$property->setAccessible(false);
} else {
$values = $obj->$propertyName;
} }
$values = $property->getValue($obj);
if (!\is_array($values)) { if (!\is_array($values)) {
// conditionals // conditionals
continue; continue;
} }
if (!$isPublic) {
$property->setAccessible(false);
}
/** @var self $mapper */ /** @var self $mapper */
$mapper = static::$hasMany[$propertyName]['mapper']; $mapper = static::$hasMany[$propertyName]['mapper'];
$objsIds = []; $objsIds = [];
@ -1807,11 +1810,18 @@ class DataMapperAbstract implements DataMapperInterface
* The exception is of course the belongsTo relation. * The exception is of course the belongsTo relation.
*/ */
foreach (static::$columns as $key => $column) { foreach (static::$columns as $key => $column) {
if (self::$relations === RelationType::ALL && isset(static::$ownsOne[$propertyName]) && $column['internal'] === $propertyName) { $value = $isPublic ? $obj->$propertyName : $property->getValue($obj);
self::deleteOwnsOne($propertyName, $property->getValue($obj)); if (self::$relations === RelationType::ALL
&& isset(static::$ownsOne[$propertyName])
&& $column['internal'] === $propertyName
) {
self::deleteOwnsOne($propertyName, $value);
break; break;
} elseif (self::$relations === RelationType::ALL && isset(static::$belongsTo[$propertyName]) && $column['internal'] === $propertyName) { } elseif (self::$relations === RelationType::ALL
self::deleteBelongsTo($propertyName, $property->getValue($obj)); && isset(static::$belongsTo[$propertyName])
&& $column['internal'] === $propertyName
) {
self::deleteBelongsTo($propertyName, $value);
break; break;
} }
} }
@ -1965,18 +1975,21 @@ class DataMapperAbstract implements DataMapperInterface
$mapper = static::$hasMany[$member]['mapper']; $mapper = static::$hasMany[$member]['mapper'];
$refProp = $refClass->getProperty($member); $refProp = $refClass->getProperty($member);
if (!($accessible = $refProp->isPublic())) {
$refProp->setAccessible(true);
}
$objects = !isset(static::$hasMany[$member]['by']) $objects = !isset(static::$hasMany[$member]['by'])
? $mapper::get($values, RelationType::ALL, $depth) ? $mapper::get($values, RelationType::ALL, $depth)
: $mapper::get($values, RelationType::ALL, $depth, static::$hasMany[$member]['by']); : $mapper::get($values, RelationType::ALL, $depth, static::$hasMany[$member]['by']);
$refProp->setValue($obj, !\is_array($objects) && !isset(static::$hasMany[$member]['conditional']) ? [$mapper::getObjectId($objects) => $objects] : $objects); if (!($isPublic = $refProp->isPublic())) {
$refProp->setAccessible(true);
if (!$accessible) { $refProp->setValue($obj, !\is_array($objects) && !isset(static::$hasMany[$member]['conditional'])
? [$mapper::getObjectId($objects) => $objects]
: $objects
);
$refProp->setAccessible(false); $refProp->setAccessible(false);
} else {
$obj->$member = !\is_array($objects) && !isset(static::$hasMany[$member]['conditional'])
? [$mapper::getObjectId($objects) => $objects]
: $objects;
} }
} }
} }
@ -2205,17 +2218,17 @@ class DataMapperAbstract implements DataMapperInterface
$path = \explode('/', $def['internal']); $path = \explode('/', $def['internal']);
$refProp = $refClass->getProperty($path[0]); $refProp = $refClass->getProperty($path[0]);
if (!($accessible = $refProp->isPublic())) { if (!($isPublic = $refProp->isPublic())) {
$refProp->setAccessible(true); $refProp->setAccessible(true);
} }
\array_shift($path); \array_shift($path);
$arrayPath = \implode('/', $path); $arrayPath = \implode('/', $path);
$aValue = $refProp->getValue($obj); $aValue = $isPublic ? $obj->{$path[0]} : $refProp->getValue($obj);
} else { } else {
$refProp = $refClass->getProperty($def['internal']); $refProp = $refClass->getProperty($def['internal']);
if (!($accessible = $refProp->isPublic())) { if (!($isPublic = $refProp->isPublic())) {
$refProp->setAccessible(true); $refProp->setAccessible(true);
} }
} }
@ -2223,7 +2236,7 @@ class DataMapperAbstract implements DataMapperInterface
if (isset(static::$ownsOne[$def['internal']])) { if (isset(static::$ownsOne[$def['internal']])) {
$default = null; $default = null;
if ($depth - 1 < 1 && $refProp->isInitialized($obj)) { if ($depth - 1 < 1 && $refProp->isInitialized($obj)) {
$default = $refProp->getValue($obj); $default = $isPublic ? $obj->{$def['internal']} : $refProp->getValue($obj);
} }
$value = self::populateOwnsOne($def['internal'], $result, $depth - 1, $default); $value = self::populateOwnsOne($def['internal'], $result, $depth - 1, $default);
@ -2236,7 +2249,7 @@ class DataMapperAbstract implements DataMapperInterface
} elseif (isset(static::$belongsTo[$def['internal']])) { } elseif (isset(static::$belongsTo[$def['internal']])) {
$default = null; $default = null;
if ($depth - 1 < 1 && $refProp->isInitialized($obj)) { if ($depth - 1 < 1 && $refProp->isInitialized($obj)) {
$default = $refProp->getValue($obj); $default = $isPublic ? $obj->{$def['internal']} : $refProp->getValue($obj);
} }
$value = self::populateBelongsTo($def['internal'], $result, $depth - 1, $default); $value = self::populateBelongsTo($def['internal'], $result, $depth - 1, $default);
@ -2277,11 +2290,11 @@ class DataMapperAbstract implements DataMapperInterface
$refProp->setValue($obj, \json_decode($value, true)); $refProp->setValue($obj, \json_decode($value, true));
} elseif ($def['type'] === 'Serializable') { } elseif ($def['type'] === 'Serializable') {
$member = $refProp->getValue($obj); $member = $isPublic ? $obj->{$def['internal']} : $refProp->getValue($obj);
$member->unserialize($value); $member->unserialize($value);
} }
if (!$accessible) { if (!$isPublic) {
$refProp->setAccessible(false); $refProp->setAccessible(false);
} }
} }
@ -2304,17 +2317,17 @@ class DataMapperAbstract implements DataMapperInterface
$path = \explode('/', $member); $path = \explode('/', $member);
$refProp = $refClass->getProperty($path[0]); $refProp = $refClass->getProperty($path[0]);
if (!($accessible = $refProp->isPublic())) { if (!($isPublic = $refProp->isPublic())) {
$refProp->setAccessible(true); $refProp->setAccessible(true);
} }
\array_shift($path); \array_shift($path);
$arrayPath = \implode('/', $path); $arrayPath = \implode('/', $path);
$aValue = $refProp->getValue($obj); $aValue = $isPublic ? $obj->{$path[0]} : $refProp->getValue($obj);
} else { } else {
$refProp = $refClass->getProperty($member); $refProp = $refClass->getProperty($member);
if (!($accessible = $refProp->isPublic())) { if (!($isPublic = $refProp->isPublic())) {
$refProp->setAccessible(true); $refProp->setAccessible(true);
} }
} }
@ -2350,11 +2363,11 @@ class DataMapperAbstract implements DataMapperInterface
$refProp->setValue($obj, \json_decode($value, true)); $refProp->setValue($obj, \json_decode($value, true));
} elseif ($def['mapper']::$columns[$column]['type'] === 'Serializable') { } elseif ($def['mapper']::$columns[$column]['type'] === 'Serializable') {
$member = $refProp->getValue($obj); $member = $isPublic ? $obj->$member : $refProp->getValue($obj);
$member->unserialize($value); $member->unserialize($value);
} }
if (!$accessible) { if (!$isPublic) {
$refProp->setAccessible(false); $refProp->setAccessible(false);
} }
} }
@ -2768,10 +2781,8 @@ class DataMapperAbstract implements DataMapperInterface
{ {
$result = self::get(null, $relations, $depth); $result = self::get(null, $relations, $depth);
if (\is_object($result)) { if (\is_object($result) && \stripos(\get_class($result), '\Null') !== false) {
if (\stripos(\get_class($result), '\Null') !== false) { return [];
return [];
}
} }
return !\is_array($result) ? [$result] : $result; return !\is_array($result) ? [$result] : $result;
@ -2855,10 +2866,8 @@ class DataMapperAbstract implements DataMapperInterface
{ {
$result = self::get(null, $relations, $depth, null, $query); $result = self::get(null, $relations, $depth, null, $query);
if (\is_object($result)) { if (\is_object($result) && \stripos(\get_class($result), '\Null') !== false) {
if (\stripos(\get_class($result), '\Null') !== false) { return [];
return [];
}
} }
return !\is_array($result) ? [$result] : $result; return !\is_array($result) ? [$result] : $result;
@ -2901,20 +2910,14 @@ class DataMapperAbstract implements DataMapperInterface
*/ */
public static function fillRelations($obj, int $relations = RelationType::ALL, int $depth = 3) : void public static function fillRelations($obj, int $relations = RelationType::ALL, int $depth = 3) : void
{ {
if ($depth < 1) { if ($depth < 1
return; || empty(static::$hasMany)
} || $relations === RelationType::NONE
) {
if ($relations === RelationType::NONE) {
return;
}
if (empty(static::$hasMany)) {
return; return;
} }
$key = self::getObjectId($obj); $key = self::getObjectId($obj);
if (empty($key)) { if (empty($key)) {
return; return;
} }
@ -2951,20 +2954,14 @@ class DataMapperAbstract implements DataMapperInterface
*/ */
public static function fillRelationsArray(array &$obj, int $relations = RelationType::ALL, int $depth = 3) : void public static function fillRelationsArray(array &$obj, int $relations = RelationType::ALL, int $depth = 3) : void
{ {
if ($depth < 1) { if ($depth < 1
return; || empty(static::$hasMany)
} || $relations === RelationType::NONE
) {
if ($relations === RelationType::NONE) {
return;
}
if (empty(static::$hasMany)) {
return; return;
} }
$key = $obj[static::$columns[static::$primaryField]['internal']]; $key = $obj[static::$columns[static::$primaryField]['internal']];
if (empty($key)) { if (empty($key)) {
return; return;
} }

View File

@ -180,14 +180,7 @@ final class FileLogger implements LoggerInterface
*/ */
public static function startTimeLog(string $id = '') : bool public static function startTimeLog(string $id = '') : bool
{ {
if (isset(self::$timings[$id])) { self::$timings[$id] = ['start' => \microtime(true), 'end' => 0.0, 'time' => 0.0];
return false;
}
$temp = \explode(' ', \microtime());
$mtime = ((float) $temp[1]) + ((float) $temp[0]);
self::$timings[$id] = ['start' => $mtime, 'end' => 0.0, 'time' => 0.0];
return true; return true;
} }
@ -197,14 +190,13 @@ final class FileLogger implements LoggerInterface
* *
* @param string $id the ID by which this time measurement gets identified * @param string $id the ID by which this time measurement gets identified
* *
* @return float The time measurement in ms * @return float The time measurement in seconds
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public static function endTimeLog(string $id = '') : float public static function endTimeLog(string $id = '') : float
{ {
$temp = \explode(' ', \microtime()); $mtime = \microtime(true);
$mtime = ((float) $temp[1]) + ((float) $temp[0]);
self::$timings[$id]['end'] = $mtime; self::$timings[$id]['end'] = $mtime;
self::$timings[$id]['time'] = $mtime - self::$timings[$id]['start']; self::$timings[$id]['time'] = $mtime - self::$timings[$id]['start'];

View File

@ -338,8 +338,11 @@ final class HttpRequest extends RequestAbstract
} }
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
$components = \explode(';', $_SERVER['HTTP_ACCEPT_LANGUAGE']); $components = \explode(';', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
$locals = \stripos($components[0], ',') !== false ? $locals = \explode(',', $components[0]) : $components; $locals = \stripos($components[0], ',') !== false
? $locals = \explode(',', $components[0])
: $components;
$firstLocalComponents = \explode('-', $locals[0]); $firstLocalComponents = \explode('-', $locals[0]);
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd

View File

@ -20,5 +20,5 @@ class ManyToManyDirectModel
public $string = 'ManyToManyDirect'; public $string = 'ManyToManyDirect';
public $to = 0; public int $to = 0;
} }