- Merging..
This commit is contained in:
		
						commit
						6c6733b503
					
				| @ -15,20 +15,7 @@ interface AdapterInterface { | ||||
|     public function connect() : object /* | PdoObject|mixed */; | ||||
|     public function buildDataSourceName() : string; | ||||
|     public function setup(array $configuration) : void; | ||||
|     public function escapeIdentifier(string $segment, int $type) : string; | ||||
|     public function defaultEngine() : ? string; | ||||
| 
 | ||||
|     public function writableValue(/* mixed */ $value); /*: mixed*/ | ||||
|      | ||||
|      | ||||
|     /*   public function databaseName() : string; | ||||
|     public function mapFieldType(FieldDefinition $field) : string; | ||||
|     public function schemaTable(string $databaseName, string $tableName) /*: object|EntityCollection | ||||
| */ | ||||
|     public function repositoryClass() : string; | ||||
|     public function queryBuilderClass() : string; | ||||
|     public function tableSyntax() : array; | ||||
|     public function whitelistAttributes(array &$parameters) : void; | ||||
|     public function generateAlterColumn(FieldDefinition $definition, array $field) : string|\Stringable; | ||||
|     public function splitAlterQuery() : bool; | ||||
| } | ||||
|  | ||||
| @ -9,10 +9,10 @@ use Ulmus\Exception\AdapterConfigurationException; | ||||
| use Ulmus\Ulmus; | ||||
| 
 | ||||
| use Ulmus\Migration\FieldDefinition; | ||||
| use Ulmus\{Entity\InformationSchema\Table, Repository, QueryBuilder}; | ||||
| use Ulmus\{Entity\InformationSchema\Table, Migration\MigrateInterface, Repository, QueryBuilder}; | ||||
| 
 | ||||
| class MsSQL implements AdapterInterface { | ||||
|     use DefaultAdapterTrait; | ||||
| class MsSQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface { | ||||
|     use SqlAdapterTrait; | ||||
| 
 | ||||
|     const ALLOWED_ATTRIBUTES = [ | ||||
|         'default', 'primary_key', 'auto_increment', | ||||
| @ -84,7 +84,7 @@ class MsSQL implements AdapterInterface { | ||||
|             $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC); | ||||
|             $pdo->setAttribute(\PDO::SQLSRV_ATTR_ENCODING, \PDO::SQLSRV_ENCODING_UTF8); | ||||
|         } | ||||
|         catch(PDOException $ex){ | ||||
|         catch(\PDOException $ex){ | ||||
|             throw $ex; | ||||
|         } | ||||
|         finally { | ||||
|  | ||||
| @ -3,6 +3,7 @@ | ||||
| namespace Ulmus\Adapter; | ||||
| 
 | ||||
| use Ulmus\Entity\InformationSchema\Table; | ||||
| use Ulmus\Migration\MigrateInterface; | ||||
| use Ulmus\QueryBuilder; | ||||
| use Ulmus\Repository; | ||||
| use Ulmus\Common\PdoObject; | ||||
| @ -11,8 +12,8 @@ use Ulmus\Exception\AdapterConfigurationException; | ||||
| use Ulmus\Ulmus; | ||||
| use Ulmus\Migration\FieldDefinition; | ||||
| 
 | ||||
| class MySQL implements AdapterInterface { | ||||
|     use DefaultAdapterTrait; | ||||
| class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface { | ||||
|     use SqlAdapterTrait; | ||||
| 
 | ||||
|     const ALLOWED_ATTRIBUTES = [ | ||||
|         'default', 'primary_key', 'auto_increment', 'update', | ||||
| @ -21,13 +22,13 @@ class MySQL implements AdapterInterface { | ||||
|     const DSN_PREFIX = "mysql"; | ||||
| 
 | ||||
|     public string $hostname; | ||||
|      | ||||
| 
 | ||||
|     public string $database; | ||||
|      | ||||
|     public string $username; | ||||
|      | ||||
|     public string $password; | ||||
|      | ||||
| 
 | ||||
|     protected string $username; | ||||
| 
 | ||||
|     protected string $password; | ||||
| 
 | ||||
|     public string $charset = "utf8mb4"; | ||||
| 
 | ||||
|     public ? string $socket; | ||||
| @ -77,7 +78,7 @@ class MySQL implements AdapterInterface { | ||||
|             $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC); | ||||
|             $pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); | ||||
|         } | ||||
|         catch(PDOException $ex){ | ||||
|         catch(\PDOException $ex){ | ||||
|             throw $ex; | ||||
|         } | ||||
|         finally { | ||||
|  | ||||
| @ -8,10 +8,10 @@ use Ulmus\ConnectionAdapter; | ||||
| use Ulmus\Entity\Sqlite\Table; | ||||
| use Ulmus\Exception\AdapterConfigurationException; | ||||
| use Ulmus\Migration\FieldDefinition; | ||||
| use Ulmus\{Repository, QueryBuilder, Ulmus}; | ||||
| use Ulmus\{Migration\MigrateInterface, Repository, QueryBuilder, Ulmus}; | ||||
| 
 | ||||
| class SQLite implements AdapterInterface { | ||||
|     use DefaultAdapterTrait; | ||||
| class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface { | ||||
|     use SqlAdapterTrait; | ||||
| 
 | ||||
|     const ALLOWED_ATTRIBUTES = [ | ||||
|         'default', 'primary_key', 'auto_increment' | ||||
| @ -40,7 +40,7 @@ class SQLite implements AdapterInterface { | ||||
|             $this->exportFunctions($pdo); | ||||
|             $this->registerPragma($pdo, $this->pragmaBegin); | ||||
|         } | ||||
|         catch(PDOException $ex){ | ||||
|         catch(\PDOException $ex){ | ||||
|             throw $ex; | ||||
|         } | ||||
| 
 | ||||
| @ -65,6 +65,7 @@ class SQLite implements AdapterInterface { | ||||
|     public function escapeIdentifier(string $segment, int $type) : string  | ||||
|     { | ||||
|         switch($type) { | ||||
|             default: | ||||
|             case static::IDENTIFIER_DATABASE: | ||||
|             case static::IDENTIFIER_TABLE: | ||||
|             case static::IDENTIFIER_FIELD: | ||||
|  | ||||
							
								
								
									
										9
									
								
								src/Adapter/SqlAdapterInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/Adapter/SqlAdapterInterface.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Ulmus\Adapter; | ||||
| 
 | ||||
| interface SqlAdapterInterface | ||||
| { | ||||
|     public function escapeIdentifier(string $segment, int $type) : string; | ||||
|     public function defaultEngine() : ? string; | ||||
| } | ||||
| @ -2,14 +2,15 @@ | ||||
| 
 | ||||
| namespace Ulmus\Adapter; | ||||
| 
 | ||||
| use Ulmus\{ConnectionAdapter, | ||||
| use Ulmus\{Common\Sql, | ||||
|     ConnectionAdapter, | ||||
|     Entity\InformationSchema\Table, | ||||
|     Migration\FieldDefinition, | ||||
|     Repository, | ||||
|     QueryBuilder, | ||||
|     Ulmus}; | ||||
| 
 | ||||
| trait DefaultAdapterTrait | ||||
| trait SqlAdapterTrait | ||||
| { | ||||
|     public function repositoryClass() : string | ||||
|     { | ||||
| @ -133,7 +134,7 @@ trait DefaultAdapterTrait | ||||
|             case is_object($value): | ||||
|                 return Ulmus::convertObject($value); | ||||
| 
 | ||||
|             case is_array($value): | ||||
|                 case is_array($value): | ||||
|                 return json_encode($value); | ||||
| 
 | ||||
|             case is_bool($value): | ||||
| @ -8,7 +8,7 @@ class Field implements \Notes\Annotation { | ||||
| 
 | ||||
|     public string $name; | ||||
|      | ||||
|     public int $length; | ||||
|     public int|string $length; | ||||
| 
 | ||||
|     public int $precision; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										8
									
								
								src/Attribute/Obj/AdapterAttributeInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Attribute/Obj/AdapterAttributeInterface.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Ulmus\Attribute\Obj; | ||||
| 
 | ||||
| interface AdapterAttributeInterface | ||||
| { | ||||
|     public function adapter() : false|string; | ||||
| } | ||||
| @ -3,7 +3,7 @@ | ||||
| namespace Ulmus\Attribute\Obj; | ||||
| 
 | ||||
| #[\Attribute(\Attribute::TARGET_CLASS)]
 | ||||
| class Table { | ||||
| class Table implements AdapterAttributeInterface { | ||||
|     public function __construct( | ||||
|         public ? string $name = null, | ||||
|         public ? string $database = null, | ||||
| @ -11,4 +11,9 @@ class Table { | ||||
|         public ? string $adapter = null, | ||||
|         public ? string $engine = null, | ||||
|     ) {} | ||||
| 
 | ||||
|     public function adapter() : false|string | ||||
|     { | ||||
|         return $this->adapter ?: false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -61,16 +61,7 @@ class EntityResolver { | ||||
| 
 | ||||
|     public function searchField($name) : null|array | ||||
|     { | ||||
|         try{ | ||||
|             return $this->field($name, self::KEY_ENTITY_NAME, false) ?: $this->field($name, self::KEY_COLUMN_NAME, false); | ||||
|         } | ||||
|         catch(\Throwable $e) { | ||||
|             if ( $throwException) { | ||||
|                 throw new \InvalidArgumentException("Can't find entity field's column named `$name` from entity {$this->entityClass}"); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return null; | ||||
|         return $this->field($name, self::KEY_ENTITY_NAME, false) ?: $this->field($name, self::KEY_COLUMN_NAME, false); | ||||
|     } | ||||
| 
 | ||||
|     public function fieldList($fieldKey = self::KEY_ENTITY_NAME, bool $skipVirtual = false) : array | ||||
| @ -173,7 +164,7 @@ class EntityResolver { | ||||
|         return $table->name ?? ""; | ||||
|     } | ||||
| 
 | ||||
|     public function tableAnnotation($required = false) : Table|Attribute\Obj\Table | ||||
|     public function tableAnnotation($required = false) : null|Table|Attribute\Obj\Table | ||||
|     { | ||||
|         if ( null === $table = $this->getTableAttribute() ) { | ||||
|             if ($required) { | ||||
| @ -191,10 +182,10 @@ class EntityResolver { | ||||
| 
 | ||||
|     public function sqlAdapter() : \Ulmus\ConnectionAdapter | ||||
|     { | ||||
|         if ( null !== $table = $this->getTableAttribute() ) { | ||||
|             if ( $table->adapter ?? null ) { | ||||
|                 if ( null === ( $adapter = \Ulmus\Ulmus::$registeredAdapters[$table->adapter] ?? null ) ) { | ||||
|                     throw new \Exception("Requested database adapter `{$table->adapter}` is not registered."); | ||||
|         if ( $adapterObj = $this->getAdapterInterfaceAttribute()) { | ||||
|             if ( false !== $adapterName = $adapterObj->adapter() ) { | ||||
|                 if ( null === ( $adapter = \Ulmus\Ulmus::$registeredAdapters[$adapterName] ?? null ) ) { | ||||
|                     throw new \Exception("Requested database adapter `$adapterName` is not registered."); | ||||
|                 } | ||||
|                 else { | ||||
|                     return $adapter; | ||||
| @ -250,6 +241,11 @@ class EntityResolver { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     protected function getAdapterInterfaceAttribute() : null|object | ||||
|     { | ||||
|         return $this->getAttributeImplementing(Attribute\Obj\AdapterAttributeInterface::class); | ||||
|     } | ||||
| 
 | ||||
|     protected function getTableAttribute() | ||||
|     { | ||||
|         return $this->getAnnotationFromClassname(Attribute\Obj\Table::class, false) ?: $this->getAnnotationFromClassname( Table::class, false ); | ||||
| @ -294,6 +290,17 @@ class EntityResolver { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     public function getAttributeImplementing(string $interface) : ? object | ||||
|     { | ||||
|         foreach (array_reverse($this->class['tags']) as $item) { | ||||
|             if ($item['object'] instanceof $interface) { | ||||
|                 return $item['object']; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     public function instanciateAnnotationObject(array|\ReflectionAttribute $tagDefinition) : object | ||||
|     { | ||||
|         if ($tagDefinition instanceof \ReflectionAttribute) { | ||||
|  | ||||
| @ -68,7 +68,7 @@ abstract class Sql { | ||||
|         return static::identifier($sql); | ||||
|     } | ||||
| 
 | ||||
|     public static function escape($value) | ||||
|     public static function escape($value) : mixed | ||||
|     { | ||||
|         switch(true) { | ||||
|             case is_object($value): | ||||
|  | ||||
| @ -53,7 +53,7 @@ class ConnectionAdapter | ||||
|     public function connect() : self | ||||
|     { | ||||
|         $this->pdo = $this->adapter->connect(); | ||||
|          | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
|      | ||||
|  | ||||
| @ -346,6 +346,18 @@ class EntityCollection extends \ArrayObject implements \JsonSerializable { | ||||
|         return ( new $className() )->fromArray($dataset); | ||||
|     } | ||||
| 
 | ||||
|     public function arrayToEntities(array $list, ? string /*stringable*/ $entityClass = null) : self | ||||
|     { | ||||
|         $collection = new static(); | ||||
|         $collection->entityClass = $entityClass ?? $this->entityClass; | ||||
| 
 | ||||
|         foreach($list as $dataset) { | ||||
|             $collection->append($this->arrayToEntity($dataset, $entityClass)); | ||||
|         } | ||||
| 
 | ||||
|         return $collection; | ||||
|     } | ||||
| 
 | ||||
|     public function jsonSerialize(): mixed | ||||
|     { | ||||
|         return $this->toArray(); | ||||
|  | ||||
| @ -27,7 +27,7 @@ trait EntityTrait { | ||||
|     public array $entityLoadedDataset = []; | ||||
| 
 | ||||
|     #[Ignore]
 | ||||
|     public function __construct() { | ||||
|     public function __construct(array $dataset = null) { | ||||
|         $this->resetVirtualProperties(); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										15
									
								
								src/Migration/MigrateInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/Migration/MigrateInterface.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Ulmus\Migration; | ||||
| 
 | ||||
| interface MigrateInterface | ||||
| { | ||||
|     public function tableSyntax() : array; | ||||
|     public function whitelistAttributes(array &$parameters) : void; | ||||
|     public function generateAlterColumn(FieldDefinition $definition, array $field) : string|\Stringable; | ||||
|     public function splitAlterQuery() : bool; | ||||
| 
 | ||||
|     /*   public function databaseName() : string; | ||||
|     public function mapFieldType(FieldDefinition $field) : string; | ||||
|     public function schemaTable(string $databaseName, string $tableName) /*: object|EntityCollection */ | ||||
| } | ||||
| @ -16,7 +16,7 @@ class OrderBy extends Fragment { | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function add(string $field, ? string $direction = null) : self | ||||
|     public function add(object|string $field, ? string $direction = null) : self | ||||
|     { | ||||
|         $this->validateFieldType($field); | ||||
| 
 | ||||
|  | ||||
| @ -2,6 +2,8 @@ | ||||
| 
 | ||||
| namespace Ulmus\Query; | ||||
| 
 | ||||
| use Ulmus\Query; | ||||
| 
 | ||||
| interface QueryBuilderInterface | ||||
| { | ||||
|     public function push(Fragment $queryFragment) : self; | ||||
| @ -9,5 +11,5 @@ interface QueryBuilderInterface | ||||
|     public function render(bool $skipToken = false) /* mixed */; | ||||
|     public function reset() : void; | ||||
|     public function getFragment(string $class, int $index = 0) : ? Fragment; | ||||
|     public function removeFragment(Fragment $fragment) : void; | ||||
|     public function removeFragment(Query\Fragment|array|\Stringable|string $fragment) : void; | ||||
| } | ||||
| @ -278,7 +278,7 @@ class QueryBuilder implements Query\QueryBuilderInterface | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function groupBy(string|\Stringable $field, ? string $direction = null) : self | ||||
|     public function groupBy(string|object $field, ? string $direction = null) : self | ||||
|     { | ||||
|         if ( null === $groupBy = $this->getFragment(Query\GroupBy::class) ) { | ||||
|             $groupBy = new Query\GroupBy(); | ||||
|  | ||||
| @ -65,7 +65,7 @@ class Repository | ||||
|         return $primaryKey ? $this->loadOneFromField($primaryKey, $value) : $this->wherePrimaryKey($value)->loadOne(); | ||||
|     } | ||||
| 
 | ||||
|     public function loadAll() : EntityCollection | ||||
|     public function loadAll () : EntityCollection | ||||
|     { | ||||
|         return $this->selectSqlQuery()->collectionFromQuery(); | ||||
|     } | ||||
| @ -144,6 +144,15 @@ class Repository | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function clone(object|array $entity) : bool | ||||
|     { | ||||
|         foreach(Ulmus::resolveEntity($this->entityClass)->getPrimaryKeyField() as $key => $field) { | ||||
|             unset($entity->$key); | ||||
|         } | ||||
| 
 | ||||
|         return $this->save($entity); | ||||
|     } | ||||
|      | ||||
|     public function save(object|array $entity, ? array $fieldsAndValue = null, bool $replace = false) : bool | ||||
|     { | ||||
|         if ( is_array($entity) ) { | ||||
| @ -532,7 +541,7 @@ class Repository | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function orderBy(string|\Stringable $field, ? string $direction = null) : self | ||||
|     public function orderBy(string|object $field, ? string $direction = null) : self | ||||
|     { | ||||
|         $this->queryBuilder->orderBy($field, $direction); | ||||
| 
 | ||||
| @ -550,7 +559,13 @@ class Repository | ||||
|     public function orders(array $orderList) : self | ||||
|     { | ||||
|         foreach($orderList as $field => $direction) { | ||||
|             $this->orderBy($field, $direction); | ||||
|             if (is_numeric($field)) { | ||||
|                 $this->orderBy($direction); | ||||
|             } | ||||
|             else { | ||||
|                 # Associative array with direction
 | ||||
|                 $this->orderBy($field, $direction); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return $this; | ||||
| @ -590,7 +605,7 @@ class Repository | ||||
| 
 | ||||
|         $pkField = key($primaryKeyField); | ||||
| 
 | ||||
|         return $this->where($primaryKeyField[$pkField]->name ?? $pkField, $value); | ||||
|         return $this->where($this->entityClass::field($primaryKeyField[$pkField]->name ?? $pkField), $value); | ||||
|     } | ||||
| 
 | ||||
|     public function withJoin(string|array $fields, array $options = []) : self | ||||
|  | ||||
| @ -187,7 +187,7 @@ class RelationBuilder | ||||
|                 return $relation->bridgeField ?? false ? $relation->bridge::entityCollection() : $relationRelation->entity::entityCollection(); | ||||
|         } | ||||
| 
 | ||||
|         return new $class(); | ||||
|         throw new \InvalidArgumentException("Unknown or no relation was provided as relation type."); | ||||
|     } | ||||
| 
 | ||||
|     protected function fetchFromDataset($name, ? array $data = null) : object|bool | ||||
| @ -227,6 +227,9 @@ class RelationBuilder | ||||
|                 elseif ( substr($key, 0, $len ) === sprintf(static::JOIN_FIELD_SEPARATOR, strtolower($name)) ) { | ||||
|                     $vars[substr($key, $len)] = $value; | ||||
|                 } | ||||
|                 else { | ||||
|                     # load here for API objects !
 | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if ($vars) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user