mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-12 02:08:40 +00:00
438 lines
9.7 KiB
PHP
438 lines
9.7 KiB
PHP
<?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
|
|
* @codeCoverageIgnore
|
|
*/
|
|
private function __construct()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Clone.
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 1.0.0
|
|
* @codeCoverageIgnore
|
|
*/
|
|
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();
|
|
}
|
|
}
|