diff --git a/src/Adapter/MySQL.php b/src/Adapter/MySQL.php index d020889..d698c9e 100644 --- a/src/Adapter/MySQL.php +++ b/src/Adapter/MySQL.php @@ -2,12 +2,15 @@ namespace Ulmus\Adapter; +use Ulmus\ConnectionAdapter; +use Ulmus\Entity\Mysql\Table; use Ulmus\Migration\FieldDefinition; use Ulmus\Migration\MigrateInterface; use Ulmus\QueryBuilder\Sql; use Ulmus\Common\PdoObject; use Ulmus\Exception\AdapterConfigurationException; +use Ulmus\Repository; class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface { use SqlAdapterTrait; @@ -166,4 +169,12 @@ class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface { { return Sql\MysqlQueryBuilder::class; } + + public function schemaTable(ConnectionAdapter $adapter, $databaseName, string $tableName) : null|object + { + return Table::repository(Repository::DEFAULT_ALIAS, $adapter) + ->select(\Ulmus\Common\Sql::raw('this.*')) + ->where($this->escapeIdentifier('table_schema', AdapterInterface::IDENTIFIER_FIELD), $databaseName) + ->loadOneFromField($this->escapeIdentifier('table_name', AdapterInterface::IDENTIFIER_FIELD), $tableName); + } } diff --git a/src/Adapter/MySQLFieldMapper.php b/src/Adapter/MySQLFieldMapper.php index e080083..fb9e867 100644 --- a/src/Adapter/MySQLFieldMapper.php +++ b/src/Adapter/MySQLFieldMapper.php @@ -28,4 +28,14 @@ class MySQLFieldMapper extends SqlFieldMapper parent::map(); } } + + public function postProcess() : void + { + if ( + in_array($this->type, [ 'BLOB', 'TINYBLOB', 'MEDIUMBLOB', 'LONGBLOB', 'JSON', 'TEXT', 'TINYTEXT', 'MEDIUMTEXT', 'LONGTEXT', 'GEOMETRY' ]) && + ! is_object($this->field->default ?? false) # Could be a functional default, which would now be valid + ) { + unset($this->field->default); + } + } } \ No newline at end of file diff --git a/src/Adapter/SQLite.php b/src/Adapter/SQLite.php index c890648..17329ed 100644 --- a/src/Adapter/SQLite.php +++ b/src/Adapter/SQLite.php @@ -97,7 +97,6 @@ class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string { $type = $field->type; - $length = $field->length; if ( is_a($type, Entity\Field\Date::class, true) || is_a($type, Entity\Field\Time::class, true) || is_a($type, \DateTime::class, true) ) { @@ -115,6 +114,10 @@ class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface break; case "array": + $type = "JSON"; + $length = null; + break; + case "string": $type = "TEXT"; $length = null; @@ -130,6 +133,10 @@ class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface } } + if (in_array($type, [ 'JSON', 'TEXT', 'BLOB', 'GEOMETRY' ])) { + $field->default = ""; + } + return $typeOnly ? $type : $type . ( $length ? "($length" . ")" : "" ); } diff --git a/src/Adapter/SqlFieldMapper.php b/src/Adapter/SqlFieldMapper.php index e06447e..281e267 100644 --- a/src/Adapter/SqlFieldMapper.php +++ b/src/Adapter/SqlFieldMapper.php @@ -46,6 +46,9 @@ class SqlFieldMapper break; case "array": + $this->type = "JSON"; + break; + case "string": if ($length && $length <= 255) { $this->type = "VARCHAR"; @@ -75,13 +78,18 @@ class SqlFieldMapper default: $this->type = strtoupper($type); - break; } + + $this->postProcess(); } public function render() : string { return $this->type . ( isset($this->length) ? "($this->length)" : "" ); } + + public function postProcess() : void + { + } } \ No newline at end of file diff --git a/src/Attribute/Property/Field/Binary.php b/src/Attribute/Property/Field/Binary.php new file mode 100644 index 0000000..284810a --- /dev/null +++ b/src/Attribute/Property/Field/Binary.php @@ -0,0 +1,19 @@ +<?php + +namespace Ulmus\Attribute\Property\Field; + +#[\Attribute(\Attribute::TARGET_PROPERTY)] +class Binary extends \Ulmus\Attribute\Property\Field +{ + public function __construct( + public ? string $name = null, + public ? string $type = "binary", + public null|int|string $length = null, + public ? int $precision = null, + public array $attributes = [], + public bool $nullable = false, + public mixed $default = null, + public bool $readonly = false, + public string $description = "", + ) {} +} \ No newline at end of file diff --git a/src/Attribute/Property/Field/Char.php b/src/Attribute/Property/Field/Char.php new file mode 100644 index 0000000..46b0076 --- /dev/null +++ b/src/Attribute/Property/Field/Char.php @@ -0,0 +1,19 @@ +<?php + +namespace Ulmus\Attribute\Property\Field; + +#[\Attribute(\Attribute::TARGET_PROPERTY)] +class Char extends \Ulmus\Attribute\Property\Field +{ + public function __construct( + public ? string $name = null, + public ? string $type = "char", + public null|int|string $length = null, + public ? int $precision = null, + public array $attributes = [], + public bool $nullable = false, + public mixed $default = null, + public bool $readonly = false, + public string $description = "", + ) {} +} \ No newline at end of file diff --git a/src/Attribute/Property/Field/Double.php b/src/Attribute/Property/Field/Double.php new file mode 100644 index 0000000..e6cc3b9 --- /dev/null +++ b/src/Attribute/Property/Field/Double.php @@ -0,0 +1,19 @@ +<?php + +namespace Ulmus\Attribute\Property\Field; + +#[\Attribute(\Attribute::TARGET_PROPERTY)] +class Double extends \Ulmus\Attribute\Property\Field +{ + public function __construct( + public ? string $name = null, + public ? string $type = "float", + public null|int|string $length = null, + public ? int $precision = null, + public array $attributes = [], + public bool $nullable = false, + public mixed $default = null, + public bool $readonly = false, + public string $description = "", + ) {} +} \ No newline at end of file diff --git a/src/Attribute/Property/Field/Json.php b/src/Attribute/Property/Field/Json.php new file mode 100644 index 0000000..7044e8e --- /dev/null +++ b/src/Attribute/Property/Field/Json.php @@ -0,0 +1,19 @@ +<?php + +namespace Ulmus\Attribute\Property\Field; + +#[\Attribute(\Attribute::TARGET_PROPERTY)] +class Json extends \Ulmus\Attribute\Property\Field +{ + public function __construct( + public ? string $name = null, + public ? string $type = "json", + public null|int|string $length = null, + public ? int $precision = null, + public array $attributes = [], + public bool $nullable = false, + public mixed $default = null, + public bool $readonly = false, + public string $description = "", + ) {} +} \ No newline at end of file diff --git a/src/Attribute/Property/Field/Varbinary.php b/src/Attribute/Property/Field/Varbinary.php new file mode 100644 index 0000000..2100158 --- /dev/null +++ b/src/Attribute/Property/Field/Varbinary.php @@ -0,0 +1,19 @@ +<?php + +namespace Ulmus\Attribute\Property\Field; + +#[\Attribute(\Attribute::TARGET_PROPERTY)] +class Varbinary extends \Ulmus\Attribute\Property\Field +{ + public function __construct( + public ? string $name = null, + public ? string $type = "varbinary", + public null|int|string $length = null, + public ? int $precision = null, + public array $attributes = [], + public bool $nullable = false, + public mixed $default = null, + public bool $readonly = false, + public string $description = "", + ) {} +} \ No newline at end of file diff --git a/src/Attribute/Property/Field/Varchar.php b/src/Attribute/Property/Field/Varchar.php new file mode 100644 index 0000000..585b364 --- /dev/null +++ b/src/Attribute/Property/Field/Varchar.php @@ -0,0 +1,19 @@ +<?php + +namespace Ulmus\Attribute\Property\Field; + +#[\Attribute(\Attribute::TARGET_PROPERTY)] +class Varchar extends \Ulmus\Attribute\Property\Field +{ + public function __construct( + public ? string $name = null, + public ? string $type = "varchar", + public null|int|string $length = null, + public ? int $precision = null, + public array $attributes = [], + public bool $nullable = false, + public mixed $default = null, + public bool $readonly = false, + public string $description = "", + ) {} +} \ No newline at end of file diff --git a/src/Attribute/Property/Field/Year.php b/src/Attribute/Property/Field/Year.php new file mode 100644 index 0000000..66769f5 --- /dev/null +++ b/src/Attribute/Property/Field/Year.php @@ -0,0 +1,19 @@ +<?php + +namespace Ulmus\Attribute\Property\Field; + +#[\Attribute(\Attribute::TARGET_PROPERTY)] +class Year extends \Ulmus\Attribute\Property\Field +{ + public function __construct( + public ? string $name = null, + public ? string $type = "year", + public null|int|string $length = null, + public ? int $precision = null, + public array $attributes = [], + public bool $nullable = false, + public mixed $default = null, + public bool $readonly = false, + public string $description = "", + ) {} +} \ No newline at end of file diff --git a/src/Entity/InformationSchema/Column.php b/src/Entity/InformationSchema/Column.php index b141e20..734c8d4 100644 --- a/src/Entity/InformationSchema/Column.php +++ b/src/Entity/InformationSchema/Column.php @@ -84,11 +84,13 @@ class Column public function matchFieldDefinition(ReflectedProperty $definition) : bool { - if ($this->nullable === $definition->allowsNull()) { + $nullable = $this->nullable === 'YES'; + + if ($nullable !== $definition->allowsNull()) { return false; } - if (isset($definition->value)) { + if ( isset($definition->value) && $this->canHaveDefaultValue() ) { if ( $definition->value !== $this->defaultValue()) { return false; } @@ -115,4 +117,9 @@ class Column return $this->default; } + + protected function canHaveDefaultValue() : bool + { + return true; + } } \ No newline at end of file diff --git a/src/Entity/Mysql/Column.php b/src/Entity/Mysql/Column.php new file mode 100644 index 0000000..23db000 --- /dev/null +++ b/src/Entity/Mysql/Column.php @@ -0,0 +1,15 @@ +<?php + +namespace Ulmus\Entity\Mysql; + +class Column extends \Ulmus\Entity\InformationSchema\Column +{ + # TODO ! Handle FUNCTIONAL default value + protected function canHaveDefaultValue(): bool + { + return ! in_array(strtoupper($this->dataType), [ + 'BLOB', 'TINYBLOB', 'MEDIUMBLOB', 'LONGBLOB', 'JSON', 'TEXT', 'TINYTEXT', 'MEDIUMTEXT', 'LONGTEXT', 'GEOMETRY' + ]); + } + +} \ No newline at end of file diff --git a/src/Entity/Mysql/Table.php b/src/Entity/Mysql/Table.php new file mode 100644 index 0000000..05f8c1e --- /dev/null +++ b/src/Entity/Mysql/Table.php @@ -0,0 +1,17 @@ +<?php + +namespace Ulmus\Entity\Mysql; + +use Ulmus\EntityCollection, + Ulmus\Entity\Field\Datetime; + +use Ulmus\{Attribute\Obj\Table as TableObj}; +use Ulmus\Attribute\Property\{Field, Filter, FilterJoin, Relation, Join, Virtual, Where}; + +#[TableObj(name: "tables", database: "information_schema")] +class Table extends \Ulmus\Entity\InformationSchema\Table +{ + #[Relation(type: "oneToMany", key: "name", foreignKey: [ Column::class, 'tableName' ], entity: Column::class)] + #[Where('TABLE_SCHEMA', fieldValue: [ Column::class, 'tableSchema' ])] + public EntityCollection $columns; +} \ No newline at end of file diff --git a/src/EntityTrait.php b/src/EntityTrait.php index 2cb9005..d9c5df2 100644 --- a/src/EntityTrait.php +++ b/src/EntityTrait.php @@ -251,7 +251,7 @@ trait EntityTrait { } #[Ignore] - public static function searchRequest(...$arguments) : SearchRequestInterface + public static function searchRequest(...$arguments) : SearchRequest\SearchRequestInterface { return new /* #[SearchRequest\Attribute\SearchRequestParameter(YourEntityClass::class)] */ class(... $arguments) extends SearchRequest\SearchRequest { # Define searchable properties here, some ex: diff --git a/src/SearchRequest/SearchRequestFromRequestTrait.php b/src/SearchRequest/SearchRequestFromRequestTrait.php index a2db547..d55a44e 100644 --- a/src/SearchRequest/SearchRequestFromRequestTrait.php +++ b/src/SearchRequest/SearchRequestFromRequestTrait.php @@ -74,8 +74,6 @@ trait SearchRequestFromRequestTrait case $attribute instanceof SearchWhere: case $attribute instanceof SearchLike: case $attribute instanceof SearchManual: - - if ($attribute->toggle) { $this->$propertyName = !empty($value); } elseif ($value !== null) { diff --git a/src/SearchRequest/SearchRequestPaginationTrait.php b/src/SearchRequest/SearchRequestPaginationTrait.php index e9bb170..e8beeaa 100644 --- a/src/SearchRequest/SearchRequestPaginationTrait.php +++ b/src/SearchRequest/SearchRequestPaginationTrait.php @@ -44,7 +44,7 @@ trait SearchRequestPaginationTrait { public function pageCount() : int { - return $this->pageCount = ceil($this->count() / $this->limit()); + return $this->limit() ? $this->pageCount = ceil($this->count() / $this->limit()) : 1; } public function hasPagination() : int