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(); } } }