mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-13 18:48:40 +00:00
Merge localization datamapper support (not finished yet)
This commit is contained in:
commit
e12ad5212d
|
|
@ -31,6 +31,7 @@ use phpOMS\Utils\ArrayUtils;
|
|||
* @license OMS License 1.0
|
||||
* @link https://orange-management.org
|
||||
* @since 1.0.0
|
||||
* @todo: currently hasmany, owns one etc. are not using joins. In some cases this could improve the performance instead of separately querying the database
|
||||
*/
|
||||
class DataMapperAbstract implements DataMapperInterface
|
||||
{
|
||||
|
|
@ -81,6 +82,16 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $columns = [];
|
||||
|
||||
/**
|
||||
* Conditional.
|
||||
*
|
||||
* Most often used for localizations
|
||||
*
|
||||
* @var array<string, array<string, string>>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $conditionals = [];
|
||||
|
||||
/**
|
||||
* Has many relation.
|
||||
|
|
@ -361,6 +372,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
|
||||
if ($relations === RelationType::ALL) {
|
||||
self::createHasMany($refClass, $obj, $objId);
|
||||
self::createConditionals($refClass, $obj, $objId);
|
||||
}
|
||||
|
||||
return $objId;
|
||||
|
|
@ -390,6 +402,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
|
||||
if ($relations === RelationType::ALL) {
|
||||
self::createHasManyArray($obj, $objId);
|
||||
self::createConditionalsArray($refClass, $obj, $objId);
|
||||
}
|
||||
|
||||
return $objId;
|
||||
|
|
@ -1314,6 +1327,47 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
self::$db->con->prepare($query->toSql())->execute();
|
||||
}
|
||||
|
||||
private static function updateConditionals(object $obj, $objId, \ReflectionClass $refClass = null, int $relations = RelationType::ALL, int $depth = 1) : void
|
||||
{
|
||||
foreach (static::$conditionals as $table => $contidional) {
|
||||
$query = new Builder(self::$db);
|
||||
$query->prefix(self::$db->getPrefix())
|
||||
->update($table)
|
||||
->where($table . '.' . $conditional['dst'], '=', $objId);
|
||||
|
||||
foreach ($conditional['columns'] as $key => $column) {
|
||||
$propertyName = \stripos($column['internal'], '/') !== false ? \explode('/', $column['internal'])[0] : $column['internal'];
|
||||
|
||||
$refClass = $refClass ?? new \ReflectionClass($obj);
|
||||
$property = $refClass->getProperty($propertyName);
|
||||
|
||||
if (!($isPublic = $property->isPublic())) {
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
|
||||
if ($column['name'] !== $conditional['dst']) {
|
||||
$tValue = $property->getValue($obj);
|
||||
if (\stripos($column['internal'], '/') !== false) {
|
||||
$path = \explode('/', $column['internal']);
|
||||
|
||||
\array_shift($path);
|
||||
$path = \implode('/', $path);
|
||||
$tValue = ArrayUtils::getArray($path, $tValue, '/');
|
||||
}
|
||||
$value = self::parseValue($column['type'], $tValue);
|
||||
|
||||
$query->set([$table . '.' . $column['name'] => $value]);
|
||||
}
|
||||
|
||||
if (!$isPublic) {
|
||||
$property->setAccessible(false);
|
||||
}
|
||||
}
|
||||
|
||||
self::$db->con->prepare($query->toSql())->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object in db.
|
||||
*
|
||||
|
|
@ -1370,6 +1424,48 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
self::$db->con->prepare($query->toSql())->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object in db.
|
||||
*
|
||||
* @param array $obj Model to update
|
||||
* @param mixed $objId Model id
|
||||
* @param int $relations Create all relations as well
|
||||
* @param int $depth Depth of relations to update (default = 1 = none)
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function updateConditionalsArray(array $obj, $objId, int $relations = RelationType::ALL, int $depth = 1) : void
|
||||
{
|
||||
foreach (static::$conditionals as $table => $contidional) {
|
||||
$query = new Builder(self::$db);
|
||||
$query->prefix(self::$db->getPrefix())
|
||||
->update($table)
|
||||
->where($table . '.' . $conditional['dst'], '=', $objId);
|
||||
|
||||
foreach ($conditional['columns'] as $key => $column) {
|
||||
$path = $column['internal'];
|
||||
if (\stripos($column['internal'], '/') !== false) {
|
||||
$path = \explode('/', $column['internal']);
|
||||
|
||||
\array_shift($path); // todo: why am I doing this?
|
||||
$path = \implode('/', $path);
|
||||
}
|
||||
|
||||
$property = ArrayUtils::getArray($path, $obj, '/');
|
||||
|
||||
if ($column['name'] !== $conditional['dst']) {
|
||||
$value = self::parseValue($column['type'], $property);
|
||||
|
||||
$query->set([$table . '.' . $column['name'] => $value]);
|
||||
}
|
||||
}
|
||||
|
||||
self::$db->con->prepare($query->toSql())->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object in db.
|
||||
*
|
||||
|
|
@ -1401,6 +1497,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
|
||||
if ($relations === RelationType::ALL) {
|
||||
self::updateHasMany($refClass, $obj, $objId, --$depth);
|
||||
self::updateConditionals($refClass, $obj, $objId);
|
||||
}
|
||||
|
||||
if (empty($objId)) {
|
||||
|
|
@ -1447,6 +1544,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
|
||||
if ($relations === RelationType::ALL) {
|
||||
self::updateHasManyArray($obj, $objId, --$depth);
|
||||
self::updateConditionalsArray($refClass, $obj, $objId);
|
||||
}
|
||||
|
||||
if ($update) {
|
||||
|
|
@ -1576,6 +1674,25 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
return $obj;
|
||||
}
|
||||
|
||||
private static function deleteConditionals($key) : void
|
||||
{
|
||||
foreach (static::$conditionals as $table => $conditional) {
|
||||
$query = new Builder(self::$db);
|
||||
$query->prefix(self::$db->getPrefix())
|
||||
->delete()
|
||||
->from($table)
|
||||
->where(static::$conditionals[$table]['dst'], '=', $key);
|
||||
|
||||
foreach (static::$conditionals[$table]['filter'] as $column => $filter) {
|
||||
if ($filter !== null) {
|
||||
$query->where($column, '=', $filter);
|
||||
}
|
||||
}
|
||||
|
||||
self::$db->con->prepare($query->toSql())->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete object in db.
|
||||
*
|
||||
|
|
@ -1662,6 +1779,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
|
||||
if ($relations !== RelationType::NONE) {
|
||||
self::deleteHasMany($refClass, $obj, $objId, $relations);
|
||||
self::deleteConditionals($objId);
|
||||
}
|
||||
|
||||
self::deleteModel($obj, $objId, $relations, $refClass);
|
||||
|
|
@ -1669,6 +1787,8 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
return $objId;
|
||||
}
|
||||
|
||||
// @todo: implement array delete
|
||||
|
||||
/**
|
||||
* Populate data.
|
||||
*
|
||||
|
|
@ -1708,9 +1828,9 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
|
||||
foreach ($result as $element) {
|
||||
if (isset($element[static::$primaryField])) {
|
||||
$row[$element[static::$primaryField]] = self::populateAbstractArray($element);
|
||||
$row[$element[static::$primaryField]] = self::populateAbstractArray($element, [], static::$columns);
|
||||
} else {
|
||||
$row[] = self::populateAbstractArray($element);
|
||||
$row[] = self::populateAbstractArray($element, [], static::$columns);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1745,7 +1865,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
$obj = new $class();
|
||||
}
|
||||
|
||||
return self::populateAbstract($result, $obj);
|
||||
return self::populateAbstract($result, $obj, static::$columns);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1853,6 +1973,39 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data.
|
||||
*
|
||||
* @param mixed $obj Object to add the relations to
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @todo accept reflection class as parameter
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function getConditionals($key, string $table) : array
|
||||
{
|
||||
$query = new Builder(self::$db);
|
||||
$query->prefix(self::$db->getPrefix())
|
||||
->select(...static::$conditionals[$table]['columns'])
|
||||
->from($table)
|
||||
->where(static::$conditionals[$table]['dst'], '=', $key);
|
||||
|
||||
foreach (static::$conditionals[$table]['filter'] as $column => $filter) {
|
||||
if ($filter !== null) {
|
||||
$query->where($column, '=', $filter);
|
||||
}
|
||||
}
|
||||
|
||||
$sth = self::$db->con->prepare($query->toSql());
|
||||
$sth->execute();
|
||||
|
||||
$results = $sth->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
return $results === false ? [] : $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data.
|
||||
*
|
||||
|
|
@ -1958,12 +2111,12 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function populateAbstract(array $result, $obj)
|
||||
public static function populateAbstract(array $result, $obj, array $columns)
|
||||
{
|
||||
$refClass = new \ReflectionClass($obj);
|
||||
|
||||
foreach ($result as $column => $value) {
|
||||
if (!isset(static::$columns[$column]['internal']) /* && $refClass->hasProperty(static::$columns[$column]['internal']) */) {
|
||||
if (!isset($columns[$column]['internal']) /* && $refClass->hasProperty($columns[$column]['internal']) */) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1971,9 +2124,9 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
$aValue = [];
|
||||
$arrayPath = '';
|
||||
|
||||
if (\stripos(static::$columns[$column]['internal'], '/') !== false) {
|
||||
if (\stripos($columns[$column]['internal'], '/') !== false) {
|
||||
$hasPath = true;
|
||||
$path = \explode('/', static::$columns[$column]['internal']);
|
||||
$path = \explode('/', $columns[$column]['internal']);
|
||||
$refProp = $refClass->getProperty($path[0]);
|
||||
|
||||
if (!($accessible = $refProp->isPublic())) {
|
||||
|
|
@ -1984,17 +2137,17 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
$arrayPath = \implode('/', $path);
|
||||
$aValue = $refProp->getValue($obj);
|
||||
} else {
|
||||
$refProp = $refClass->getProperty(static::$columns[$column]['internal']);
|
||||
$refProp = $refClass->getProperty($columns[$column]['internal']);
|
||||
|
||||
if (!($accessible = $refProp->isPublic())) {
|
||||
$refProp->setAccessible(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (\in_array(static::$columns[$column]['type'], ['string', 'int', 'float', 'bool'])) {
|
||||
if (\in_array($columns[$column]['type'], ['string', 'int', 'float', 'bool'])) {
|
||||
// todo: what is this or condition for? seems to be wrong if obj null then it doesn't work anyways
|
||||
if ($value !== null || $refProp->getValue($obj) !== null) {
|
||||
\settype($value, static::$columns[$column]['type']);
|
||||
\settype($value, $columns[$column]['type']);
|
||||
}
|
||||
|
||||
if ($hasPath) {
|
||||
|
|
@ -2002,24 +2155,24 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
}
|
||||
|
||||
$refProp->setValue($obj, $value);
|
||||
} elseif (static::$columns[$column]['type'] === 'DateTime') {
|
||||
} elseif ($columns[$column]['type'] === 'DateTime') {
|
||||
$value = $value === null ? null : new \DateTime($value);
|
||||
if ($hasPath) {
|
||||
$value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true);
|
||||
}
|
||||
|
||||
$refProp->setValue($obj, $value);
|
||||
} elseif (static::$columns[$column]['type'] === 'Json') {
|
||||
} elseif ($columns[$column]['type'] === 'Json') {
|
||||
if ($hasPath) {
|
||||
$value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true);
|
||||
}
|
||||
|
||||
$refProp->setValue($obj, \json_decode($value, true));
|
||||
} elseif (static::$columns[$column]['type'] === 'Serializable') {
|
||||
} elseif ($columns[$column]['type'] === 'Serializable') {
|
||||
$member = $refProp->getValue($obj);
|
||||
$member->unserialize($value);
|
||||
} else {
|
||||
throw new \UnexpectedValueException('Value "' . static::$columns[$column]['type'] . '" is not supported.');
|
||||
throw new \UnexpectedValueException('Value "' . $columns[$column]['type'] . '" is not supported.');
|
||||
}
|
||||
|
||||
if (!$accessible) {
|
||||
|
|
@ -2039,12 +2192,11 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function populateAbstractArray(array $result) : array
|
||||
public static function populateAbstractArray(array $result, array $obj, array $columns) : array
|
||||
{
|
||||
$obj = [];
|
||||
foreach ($result as $column => $value) {
|
||||
if (isset(static::$columns[$column]['internal'])) {
|
||||
$path = static::$columns[$column]['internal'];
|
||||
if (isset($columns[$column]['internal'])) {
|
||||
$path = $columns[$column]['internal'];
|
||||
if (\stripos($path, '/') !== false) {
|
||||
$path = \explode('/', $path);
|
||||
|
||||
|
|
@ -2052,11 +2204,11 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
$path = \implode('/', $path);
|
||||
}
|
||||
|
||||
if (\in_array(static::$columns[$column]['type'], ['string', 'int', 'float', 'bool'])) {
|
||||
\settype($value, static::$columns[$column]['type']);
|
||||
} elseif (static::$columns[$column]['type'] === 'DateTime') {
|
||||
if (\in_array($columns[$column]['type'], ['string', 'int', 'float', 'bool'])) {
|
||||
\settype($value, $columns[$column]['type']);
|
||||
} elseif ($columns[$column]['type'] === 'DateTime') {
|
||||
$value = $value === null ? null : new \DateTime($value);
|
||||
} elseif (static::$columns[$column]['type'] === 'Json') {
|
||||
} elseif ($columns[$column]['type'] === 'Json') {
|
||||
$value = \json_decode($value, true);
|
||||
}
|
||||
|
||||
|
|
@ -2184,7 +2336,7 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
continue;
|
||||
}
|
||||
|
||||
$obj[$value] = self::populateAbstractArray(self::getRaw($value));
|
||||
$obj[$value] = self::populateAbstractArray(self::getRaw($value), [], static::$columns);
|
||||
|
||||
self::addInitializedArray(static::class, $value, $obj[$value]);
|
||||
}
|
||||
|
|
@ -2492,11 +2644,12 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
return;
|
||||
}
|
||||
|
||||
$hasMany = !empty(static::$hasMany);
|
||||
$ownsOne = !empty(static::$ownsOne);
|
||||
$belongsTo = !empty(static::$belongsTo);
|
||||
$hasMany = !empty(static::$hasMany);
|
||||
$ownsOne = !empty(static::$ownsOne);
|
||||
$belongsTo = !empty(static::$belongsTo);
|
||||
$hasConditionals = !empty(static::$conditionals);
|
||||
|
||||
if (!($hasMany || $ownsOne || $belongsTo)) {
|
||||
if (!($hasMany || $ownsOne || $belongsTo || $hasConditionals)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2513,6 +2666,12 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
if ($belongsTo) {
|
||||
self::populateBelongsTo($obj[$key], $depth);
|
||||
}
|
||||
|
||||
if ($hasConditionals) {
|
||||
foreach (static::$conditionals as $table => $conditional) {
|
||||
$obj[$key] = self::populateAbstract(self::getConditionals($key, $table), $obj[$key], $conditional['columns']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2537,14 +2696,19 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
return;
|
||||
}
|
||||
|
||||
$hasMany = !empty(static::$hasMany);
|
||||
$ownsOne = !empty(static::$ownsOne);
|
||||
$belongsTo = !empty(static::$belongsTo);
|
||||
$hasMany = !empty(static::$hasMany);
|
||||
$ownsOne = !empty(static::$ownsOne);
|
||||
$belongsTo = !empty(static::$belongsTo);
|
||||
$hasConditionals = !empty(static::$conditionals);
|
||||
|
||||
if (!($hasMany || $ownsOne || $belongsTo)) {
|
||||
if (!($hasMany || $ownsOne || $belongsTo || $hasConditionals)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($conditionals) {
|
||||
self::populateConditionalsArray();
|
||||
}
|
||||
|
||||
foreach ($obj as $key => $value) {
|
||||
/* loading relations from relations table and populating them and then adding them to the object */
|
||||
if ($hasMany) {
|
||||
|
|
@ -2558,6 +2722,12 @@ class DataMapperAbstract implements DataMapperInterface
|
|||
if ($belongsTo) {
|
||||
self::populateBelongsToArray($obj[$key], $depth);
|
||||
}
|
||||
|
||||
if ($hasConditionals) {
|
||||
foreach (static::$conditionals as $table => $conditional) {
|
||||
$obj[$key] = self::populateAbstractArray(self::getConditionals($key, $table), $obj[$key], $conditional['columns']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user