155 Commits
Author SHA1 Message Date
Dave Mc Nicoll 447430b7bb - Fixed PDO return value of connect() in mssql 2026-07-14 20:12:03 +00:00
mcndave 00093b0398 - Error message now more verbose 2026-07-14 19:40:54 +00:00
mcndave 1dcf32e0da - Working on revamping Ulmus bases classes 2026-07-13 19:41:44 +00:00
mcndave 13b7cf06f1 - ArrayOf errors now catched in EntityTrait (event soon to be attached to it)
- Fixed some non-nullable defaulted to null vars in functions
- Added a new diff method for entities which skips nullable values if they are not defined.
2026-07-13 12:33:40 +00:00
mcndave 709ed63323 - Still working on SearchRequest for optimized and more advanced query manipulations
- Minor bugfixes in DatasetHandler and ObjectInstanciator
2026-07-01 13:00:01 -04:00
Dave Mc Nicoll 5d32d9f635 - Fixed MsSQL entity and searchRequest which caused buggy searchs 2026-06-19 19:44:41 +00:00
Dave Mc Nicoll 1e4a528d39 - Merged 2026-06-15 19:58:46 +00:00
Dev 2d86adc3e1 - Added some more info on a bad connection error 2026-06-09 19:27:17 +00:00
Dave Mc Nicoll 2a03789e7c - Defined nullable adapter 2026-06-01 15:11:07 +00:00
Dave Mc Nicoll 1af0063203 - WIP on php8.5 migration 2026-05-22 20:36:35 +00:00
Dave Mc Nicoll 7b35de3258 - Work done on search request mostly 2026-05-21 15:19:35 +00:00
Dave Mc Nicoll f938e18572 - Added a 'select' attribute, WIP on ArrayCollection and ArrayOf also 2026-04-24 19:26:02 +00:00
Dave Mc Nicoll b394b9348f - Specified a bit more how debug arguments are printed 2026-04-23 18:11:31 +00:00
mcndave 009e30eb7e - Added ArrayOf attributes and DatasetFill/DatasetPull events. ArrayCollection is also working with ArrayOf attributes 2026-04-13 17:00:29 +00:00
Dave Mc Nicoll fd5d31fa17 - Merged getValue override 2026-02-25 20:09:28 +00:00
Dev b0b3aca6d9 - Fixed error throwing while building relation 2026-01-16 21:28:40 +00:00
mcndave 36162c6486 -Empty dataset can not be saved 2026-01-05 12:37:55 +00:00
Dev 11e436236c - Heavy rework on search request handling of entities 2025-12-02 00:15:54 +00:00
Dev a9b9c2cce9 - Heavy rework on search request handling of entities 2025-12-02 00:15:26 +00:00
Dave Mc Nicoll cb125545c7 - WIP on search request handling of operators 2025-11-11 18:22:44 +00:00
Dave Mc Nicoll 2271b0b034 - Added a Trim PropertyValueModifier 2025-10-15 15:03:09 +00:00
Dave Mc Nicoll 2e45eba520 - Added some more debug info, fixed missing interface on Entity 2025-09-17 20:30:22 +00:00
mcndave 033a183269 - Fixed a bug with an incorrect execute 2025-07-22 13:14:41 +00:00
mcndave 0192975f10 - Removed 'change' form sql migration alter column in sqlite 2025-07-17 18:35:27 +00:00
mcndave b33c67b594 - WIP on locale formatting since strftime is deprecated
- Added Limit and Offset attributes in RelationBuilder
2025-07-14 16:54:45 +00:00
Dave Mc Nicoll 2f482324b2 - Added callable field in search, searchOne, remove, removeOne, etc... 2025-06-26 14:34:12 +00:00
Dave Mc Nicoll a5d65025f8 - Fixed a bug within mssql migration 2025-06-20 13:11:56 +00:00
mcndave b53327a6ed - Refactored PdoObject class a bit 2025-06-10 14:46:37 +00:00
Dave Mc Nicoll fb644b0b0a - Added withJoin from attributes in RelationBuilder (can't understand why it wasn't already..) 2025-06-03 20:27:15 +00:00
Dave Mc Nicoll c719e4a6d1 - WIp on Migration for mssql 2025-05-26 18:21:37 +00:00
Dave Mc Nicoll fb4985160a - WIP on Migration of MsSQL 2025-05-21 18:46:34 +00:00
Dave Mc Nicoll c54de30069 - Fixed evalClosure() missing type which converted EntityField into string 2025-05-16 12:59:31 +00:00
Dave Mc Nicoll 8fff21ecb0 - Fixed RelationBuilder problem whenever a field wasn't set 2025-05-15 18:09:52 +00:00
Dave Mc Nicoll cc6048d4ee - WIP on migration and some bug fixes linked to withJoin() select problems 2025-05-15 18:05:23 +00:00
Dave Mc Nicoll 761e0401b0 - Fixed SQLite truncate, added AdapterProxy autoloading 2025-05-12 15:11:00 +00:00
Dave Mc Nicoll 1ec582d1ac - Comparison made before transforming to string was skipping nulls and not nulls but empty 2025-04-03 19:38:48 +00:00
Dave Mc Nicoll 9556dea849 - Fixed a bug where withJoin() would mess with previous select() done on querybuilding
- Fixed a problem related with distinct in select whenever another select on fields was done
2025-03-20 17:31:19 +00:00
Dave Mc Nicoll bfddf84564 - Added partial support for Index as primary keys 2025-03-11 19:36:00 +00:00
Dave Mc Nicoll e0ec140661 - Sqlite now handles concurrency with transactions 2025-02-25 14:09:41 +00:00
Dave Mc Nicoll 0fd6889c6f - ID attribute is now readonly by default (since autoincremented) 2025-02-03 19:56:35 +00:00
mcndave bd0d928f35 - Added SearchableInterace as base of EntityInterface 2024-12-16 19:44:07 +00:00
mcndave 5a5d326d70 - Merging 2024-12-16 18:57:01 +00:00
mcndave b5e96eb7e0 - WIP on Collation 2024-12-16 18:46:24 +00:00
Dave Mc Nicoll 7c589ab7b4 - Fixed forgotten return value form listColumns in SQLite driver 2024-12-09 20:42:37 +00:00
Dave Mc Nicoll 589524ca3a - Added limitation on fixedValue in Where attribute 2024-12-09 16:40:50 +00:00
Dave Mc Nicoll 1fac12c928 - Added relation's shortcut attributes 2024-12-02 21:36:03 +00:00
Dave Mc Nicoll 9eed2fe1a8 - Added caching mechanism as an event listener 2024-12-02 15:22:30 -05:00
mcndave b601939459 - Bugfixes in search request, WIP on JsonTrait 2024-11-21 19:16:40 -05:00
mcndave e3314f40ac - WIP on JsonConditionTrait for SQL flavors that supports it; fixed a bug within Entity initialization from a new method to instanciate it which was implemented 2024-11-16 16:05:26 +00:00
mcndave 4ad44f73d7 - Fixed month() and days() format which were prepending zero ; adjusted to make it's behaviour like MySQL method 2024-11-14 13:40:47 +00:00
mcndave 68a6636c06 - Fixed a bug where default value was set to empty instead of nothing 2024-11-13 20:48:38 -05:00
Dave Mc Nicoll 70c6cde603 - Latest commit into this branch, merging after 2024-11-13 14:02:03 -05:00
Dave Mc Nicoll 079a3fd110 Merge branch 'notes-2.x' of https://git.mcnd.ca/mcndave/ulmus into notes-2.x 2024-11-11 20:42:51 +00:00
Dave Mc Nicoll ec4d02b9d9 - Removed 'description' property and moved it into an appropriate attribute from lean-api package 2024-11-11 20:42:29 +00:00
Dave Mc Nicoll 35ceb97241 - Added Exists method 2024-11-10 13:08:05 +00:00
Dave Mc Nicoll 83f673b37f - Mostly bug fixes done on this code push 2024-11-01 16:14:14 -04:00
Dave Mc Nicoll 411992c7a8 - Added a new Field Mapper to SQLs Adapters.
- Defined missing MySQL fields attributes
- WIP on lean-console's migration methods
2024-10-21 18:12:24 +00:00
Dave Mc Nicoll 5f4f23a8e4 - Allowed a JOINed entity to be null if nothing is loaded from a query and it's field is nullable 2024-10-14 16:32:23 +00:00
Dave Mc Nicoll 2fda7e82d7 Merge branch 'notes-2.x' of https://git.mcnd.ca/mcndave/ulmus into notes-2.x 2024-10-14 16:07:28 +00:00
Dave Mc Nicoll 573d4cc06b - RelationBuilder now returns NULL if no entity were found AND given field is nullable 2024-10-14 16:07:12 +00:00
Dave Mc Nicoll 18313fd7f5 - Forgot to set escapeIdentifier as static 2024-10-14 14:43:03 +00:00
Dave Mc Nicoll 9503b24467 - Fixed some bugs within SearchRequestFromRequestTrait 2024-10-14 14:41:35 +00:00
Dave Mc Nicoll 3c2ae86653 - Field mapper is now removed from Adapters and set into it's own object
- Added a PK to Column (IS)
2024-10-14 12:53:15 +00:00
Dave Mc Nicoll 9977a25cf5 - Forgot a dump() 2024-10-07 19:39:52 +00:00
Dave Mc Nicoll 3ba8a2a5d0 - Fixed 'value' for SearchRequestOrderBy and also fixed a typo where SearchManual would not be set 2024-10-07 19:38:29 +00:00
Dave Mc Nicoll 4106c8db91 Merge branch 'notes-2.x' of https://git.mcnd.ca/mcndave/ulmus into notes-2.x 2024-10-07 19:37:10 +00:00
Dave Mc Nicoll d5cca085bc - Removed offset if limit = 0 2024-10-07 19:36:53 +00:00
mcndave c56b584140 - Merges 2024-10-02 14:18:35 -04:00
Dave Mc Nicoll 8b1c11676d - Added OrderBy (heavy WIP, will be recoded 2024-08-30 18:59:48 +00:00
mcndave aa07c728fe - Fixed transactions in SQLite 2024-06-28 07:47:53 -04:00
Dave Mc Nicoll d4181065cf Merge branch 'notes-2.x' of https://git.mcnd.ca/mcndave/ulmus into notes-2.x 2024-06-28 11:46:46 +00:00
Dave Mc Nicoll 62998faf40 - WIP on SearchRequest enums and manual searchs 2024-06-28 11:46:09 +00:00
mcndave feee26cd26 Merge branch 'notes-2.x' of https://git.mcnd.ca/mcndave/ulmus into notes-2.x 2024-06-21 13:01:48 +00:00
mcndave e37944c63a - Began WIP on SQL specific PdoObject 2024-06-21 13:01:21 +00:00
mcndave 1d38ae8245 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus into notes-2.x 2024-06-21 13:00:57 +00:00
Dave Mc Nicoll 0c8591f238 - Added multiple parameters on SearchParameter 2024-06-05 17:47:31 +00:00
Dave Mc Nicoll bbfd7c02b4 - WIP on SearchAttributes supporting Request's attributes 2024-06-04 13:33:48 +00:00
Dave Mc Nicoll bd9078230d - Multiple bug fixes related to notes 2.x 2024-05-31 12:26:39 +00:00
mcndave f3be11a590 - WIP on notes 2.x 2024-05-28 08:59:12 -04:00
Dave Mc Nicoll 2de3139c80 - Added description to most attributes 2024-05-27 18:09:22 +00:00
Dave Mc Nicoll e37eeb85f1 Merge branch 'master' into notes-2.x 2024-05-21 14:01:50 +00:00
Dave Mc Nicoll 7de0ecb028 - Fixed SearchLike attribute 2024-05-21 13:00:19 +00:00
mcndave 75231f32b3 - WIP on Notes v2.x 2024-05-09 19:49:27 +00:00
Dave Mc Nicoll 1dd9da6eb6 - Fixes done for QueryBuilderInterface 2024-04-24 11:23:10 -04:00
mcndave b38b81d03c - Still WIP on SearchRequest attributes migration 2024-04-22 13:54:48 +00:00
mcndave 950df5eb99 - Continued work on SearchRequest migration and fixed some more QueryBuilder migration too 2024-04-18 19:59:28 +00:00
Dave Mc Nicoll 9fdebf454d - Started working on decoupling QueryBuilder from SqlQueryBuilder
- WIP on SearchRequest attributes
- Began working on removing 'Ulmus' class
- WIP on removing SQL query building from Repository (which will become SqlRepository)
2024-04-17 15:54:48 -04:00
Dave Mc Nicoll 4571517dc8 - Added some SearchRequest attributes ; now it's even simpler to add searchable fields
- Began decoupling of QueryBuilder from native MySQL method ; some works needs to be done on for the Repository object splitting also.
2024-04-09 19:14:27 -04:00
mcndave 15be1597b8 - Fixed a recurrent bug within deleteOne() method 2024-02-01 16:17:08 +00:00
mcndave fa4e686f35 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-12-04 12:36:20 -05:00
mcndave d9fa51fa18 - Still WIP on removing annotations 2023-12-04 12:36:06 -05:00
Dave Mc Nicoll d4d68a029d - Fixed a problem of invalid comparison types in empty IN() query fragment 2023-11-24 11:31:54 -05:00
Dave Mc Nicoll ea667db552 - Testing another boolean handling method 2023-11-20 15:24:23 -05:00
Dave Mc Nicoll afe5144dc7 - Added a new value binding methods 2023-11-20 15:21:17 -05:00
mcndave 62792e8325 - Fixed a bug within INSERT query 2023-11-17 23:34:55 -05:00
mcndave 3a80fee9c3 - Added support for Ignore attribute in dataset export of EntityTrait
- Work done on JSONification of entity
2023-11-17 22:40:21 -05:00
Dave Mc Nicoll 7f8780d328 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-11-17 16:00:59 -05:00
Dave Mc Nicoll 9a9f473f3f - PDO Params are now properly (mostly..) binded, bool, null and int are now handled correctly 2023-11-17 16:00:29 -05:00
mcndave fab70aec6a fixed a missing alias 2023-11-17 08:19:12 -05:00
Dave Mc Nicoll c1755d250b Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-11-08 09:27:26 -05:00
Dave Mc Nicoll acab934f6f - Some bugfixes applied live 2023-11-08 09:27:03 -05:00
mcndave 2e377374d4 - Removed unused annotations 2023-11-08 06:52:38 -05:00
Dave Mc Nicoll c2cccc0222 - Fixed a proble within EntityInterface with field(s) which needed a false instead of bool 2023-11-07 11:12:59 -05:00
Dave Mc Nicoll ab582c9318 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-11-07 11:02:06 -05:00
Dave Mc Nicoll a4b81f1932 - Added support for closure in Virtual field 2023-11-07 11:01:55 -05:00
mcndave ab1d7e4f5b Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-11-03 19:45:31 -04:00
mcndave bfc1e1cf93 - WIP on removing annotations 2023-11-03 19:45:21 -04:00
mcndave 531908b04c Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-11-03 08:26:16 -04:00
mcndave 07ae8faaac - Worked on SQLite adapter mostly 2023-11-03 08:25:35 -04:00
Dave Mc Nicoll 756474d460 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-11-01 11:26:10 -04:00
Dave Mc Nicoll d297fd9e86 - Fixed a bug which caused a problem using offset without limits 2023-11-01 11:25:59 -04:00
mcndave fed7d2e302 - Some minors adjustments to match PHP 8.x coding styles 2023-11-01 09:55:19 -04:00
mcndave 3736fbe0f6 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-10-31 18:05:00 +00:00
mcndave 667c1fe9ab - Fixed an alias problem within deleteFromPk() method 2023-10-31 18:04:49 +00:00
mcndave d2bd6c2f58 - minor fixes 2023-10-31 16:34:45 +00:00
mcndave 953fc35680 - Completed SQLite pragma's missing code 2023-10-31 16:11:23 +00:00
mcndave 6c6733b503 - Merging.. 2023-10-31 14:40:02 +00:00
mcndave e641bc321d - SQLite pragma handling was not applied ; fixed 2023-10-31 14:37:46 +00:00
mcndave da5d203768 - Small quick fix on espaceIdentifier whichi misses a type 2023-10-31 14:17:56 +00:00
mcndave f77c93ad20 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-10-30 19:41:50 +00:00
mcndave c9d9281c63 - Added a new clone() method to Repository() base class 2023-10-30 19:41:40 +00:00
Dave Mc Nicoll 8e0dce3e71 - Still WIP on Api's wrapper 2023-10-27 18:33:48 -04:00
mcndave 1927b43999 - Some overdue modification made to allow more flexibility 2023-10-27 17:53:55 +00:00
Dave Mc Nicoll cc741566fb - Bugfixes made while working on lean/console database migrations 2023-08-31 09:15:50 -04:00
Dave Mc Nicoll 8489cb4841 - Added some options to withJoin() method of repository 2023-08-29 16:32:25 -04:00
mcndave 9ebf7b05d7 - Bugfixes made while working on lean/console 2023-08-29 20:29:33 +00:00
mcndave 338b599d39 - Added a default searchRequest() method to entityTrait 2023-07-31 14:28:19 -04:00
mcndave d01624b8aa - WIP on relations, constrains and foreign keys 2023-07-14 19:57:29 -04:00
mcndave 01ab6e82d4 - Some small bugfixes made 2023-07-09 12:38:52 -04:00
Dave Mc Nicoll a4743b471c - saveAll() now also supports arrays 2023-05-12 18:56:59 +00:00
Dave Mc Nicoll bd61522a07 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-04-13 15:39:21 -04:00
Dave Mc Nicoll f3712c9cc7 - Changed returned object from PdoObject runQuery method correcting 'Creation of dynamic property PDOStatement:: is deprecated' 2023-04-13 15:39:16 -04:00
mcndave cfaebbecc4 - Minor enhancements 2023-04-05 17:42:02 +00:00
mcndave eb6434bb72 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-03-30 15:24:58 +00:00
mcndave 2ad52aba85 - WIP on Alter table for lean-console 2023-03-30 15:24:48 +00:00
Dave Mc Nicoll 3c5aa51850 - WIP on PHP 8.2 conversion 2023-03-29 11:30:46 -04:00
mcndave 9514a46ae7 - WIP on SQLite Adapter and migration 2023-03-27 18:38:31 +00:00
mcndave cee978ecfd Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-03-23 15:09:56 +00:00
mcndave 43880eb428 - Migrated Entity's file into attributes 2023-03-23 15:09:42 +00:00
mcndave 58bdce0ea8 - Some small bugfixes done 2023-03-23 14:56:13 +00:00
mcndave fa8adcace1 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-02-23 17:16:31 +00:00
mcndave 36cddf8f78 - Upgraded doc intro to match new attribute uses. 2023-02-23 17:16:22 +00:00
Dave Mc Nicoll c6bfaa05f2 - Added support for field value in Where attribute 2023-02-23 12:15:31 -05:00
Dave Mc Nicoll c9c6a11ebd - Fixed a bug caused by the addition of Attributes (on Ignore tags) and ajusted the EntityTrait with it 2023-02-08 16:37:48 +00:00
mcndave d4a9fc8463 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-02-07 16:49:39 +00:00
mcndave 94edb09352 - Added a new RelationTypeEnum 2023-02-07 16:49:25 +00:00
Dave Mc Nicoll dcccce7893 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-02-03 14:06:13 +00:00
Dave Mc Nicoll 31f031715d - Fixed a bug within notIn() statement 2023-02-03 14:06:00 +00:00
mcndave 26ffecbb6e - WIP on PHP 8 attributes 2023-02-01 03:50:09 +00:00
Dave Mc Nicoll 88e9f048db - Select now only query existing entity's fields on select() and withJoin() statements. 2023-01-27 15:46:16 +00:00
Dave Mc Nicoll 70021d829d - WIP on attributes 2023-01-26 18:47:53 +00:00
mcndave e6d0279c1a - WIP on attributes ; on testing phase 2023-01-26 13:25:59 +00:00
mcndave 5295a335b3 Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus 2023-01-16 14:19:52 +00:00
mcndave 43a913a602 - Fixed IN() query from Where rendering 2023-01-16 14:19:37 +00:00
mcndave b6752f4364 WIP on docs and added basic enums supports 2023-01-14 02:19:42 +00:00
227 changed files with 6398 additions and 2677 deletions

No files matched your search

+1 -1
View File
@@ -6,7 +6,7 @@
"authors": [
{
"name": "Dave Mc Nicoll",
"email": "mcndave@gmail.com"
"email": "info@mcnd.ca"
}
],
"require": {
+6 -16
View File
@@ -4,7 +4,7 @@ Welcome to the official Ulmus documentation.
## Quick start
Creating a simple user entity:
Creating a simple user exemple entity:
*/app/entity/user.php*
```php
@@ -21,29 +21,19 @@ class User
{
use \Ulmus\EntityTrait;
/**
* @Id
*/
#[Field\Id]
public int $id;
/**
* @Field
*/
#[Field]
public string $fullname;
/**
* @Field
*/
#[Field]
public ? string $email;
/**
* @Field('name' => 'is_admin')
*/
#[Field]
public bool $isAdmin = false;
/**
* @DateTime
*/
#[Field\Datetime]
public Datetime $birthday;
}
```
+7
View File
@@ -0,0 +1,7 @@
# Search Request
Ulmus comes with a simple search request processor which allows both flexibility and simplicity.
## Quick start
Creating a simple user exemple entity:
View File
Whitespace-only changes.
+1 -12
View File
@@ -2,7 +2,6 @@
namespace Ulmus\Adapter;
use Ulmus\Common\PdoObject;
use Ulmus\Migration\FieldDefinition;
interface AdapterInterface {
@@ -12,20 +11,10 @@ interface AdapterInterface {
public const IDENTIFIER_SCHEMA = 4;
public const IDENTIFIER_VALUE = 5;
public function connect() : object /* | PdoObject|mixed */;
public function connect() : object;
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;
}
-95
View File
@@ -1,95 +0,0 @@
<?php
namespace Ulmus\Adapter;
use Ulmus\{ConnectionAdapter, Entity\InformationSchema\Table, Migration\FieldDefinition, Repository, QueryBuilder};
trait DefaultAdapterTrait
{
public function repositoryClass() : string
{
return Repository::class;
}
public function queryBuilderClass() : string
{
return QueryBuilder::class;
}
public function tableSyntax() : array
{
return [
'ai' => "AUTO_INCREMENT",
'pk' => "PRIMARY KEY",
'unsigned' => "UNSIGNED",
];
}
public function databaseName() : string
{
return $this->database;
}
public function schemaTable(ConnectionAdapter $parent, $databaseName, string $tableName) /* : ? object */
{
return Table::repository(Repository::DEFAULT_ALIAS, $parent)->where($this->escapeIdentifier('table_schema', AdapterInterface::IDENTIFIER_FIELD), $databaseName)->loadOneFromField($this->escapeIdentifier('table_name', AdapterInterface::IDENTIFIER_FIELD), $tableName);
}
public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string
{
$type = $field->type;
$length = $field->length;
if ( is_a($type, Entity\Field\Date::class, true) ) {
$type = "DATE";
}
elseif ( is_a($type, Entity\Field\Time::class, true) ) {
$type = "TIME";
}
elseif ( is_a($type, \DateTime::class, true) ) {
$type = "DATETIME";
}
switch($type) {
case "bool":
$type = "TINYINT";
$length = 1;
break;
case "array":
case "string":
if ($length && $length <= 255) {
$type = "VARCHAR";
break;
}
elseif (! $length || ( $length <= 65535 ) ) {
$type = "TEXT";
}
elseif ( $length <= 16777215 ) {
$type = "MEDIUMTEXT";
}
elseif ($length <= 4294967295) {
$type = "LONGTEXT";
}
else {
throw new \Exception("A column with size bigger than 4GB cannot be created.");
}
# Length is unnecessary on TEXT fields
unset($length);
break;
case "float":
$type = "DOUBLE";
break;
default:
$type = strtoupper($type);
break;
}
return $typeOnly ? $type : $type . ( isset($length) ? "($length" . ( ! empty($precision) ? ",$precision" : "" ) . ")" : "" );
}
}
+37 -29
View File
@@ -2,17 +2,26 @@
namespace Ulmus\Adapter;
use Ulmus\Common\PdoObject;
use Ulmus\Pdo;
use Ulmus\Exception\AdapterConfigurationException;
use Ulmus\Ulmus;
use Ulmus\Migration\FieldDefinition;
use Ulmus\{Entity\InformationSchema\Table, Repository, QueryBuilder};
use Ulmus\{ConnectionAdapter,
Entity\InformationSchema\Table,
Migration\MigrateInterface,
Migration\SqlMigrationTrait,
Repository,
QueryBuilder};
class MsSQL implements AdapterInterface {
use DefaultAdapterTrait;
class MsSQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface {
use SqlAdapterTrait, SqlMigrationTrait;
const ALLOWED_ATTRIBUTES = [
'default', 'primary_key', 'auto_increment',
];
const DSN_PREFIX = "sqlsrv";
@@ -47,7 +56,9 @@ class MsSQL implements AdapterInterface {
public function __construct(
?string $server = null,
?string $database = null,
#[\SensitiveParameter]
?string $username = null,
#[\SensitiveParameter]
?string $password = null,
?int $port = null
) {
@@ -72,15 +83,15 @@ class MsSQL implements AdapterInterface {
}
}
public function connect() : PdoObject
public function connect() : \PDO
{
try {
$pdo = new PdoObject($this->buildDataSourceName(), $this->username, $this->password);
$pdo = new Pdo\Mssql($this->buildDataSourceName(), $this->username, $this->password);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$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 {
@@ -200,9 +211,17 @@ class MsSQL implements AdapterInterface {
}
}
public function escapeIdentifier(string $segment, int $type) : string
public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string
{
$mapper = new MsSQLFieldMapper($field);
return $typeOnly ? $mapper->type : $mapper->render();
}
public static function escapeIdentifier(string $segment, int $type) : string
{
switch($type) {
default:
case static::IDENTIFIER_SCHEMA:
case static::IDENTIFIER_DATABASE:
case static::IDENTIFIER_TABLE:
@@ -214,26 +233,6 @@ class MsSQL implements AdapterInterface {
}
}
public function writableValue(mixed $value) /*: mixed*/
{
switch (true) {
case $value instanceof \UnitEnum:
return Ulmus::convertEnum($value);
case is_object($value):
return Ulmus::convertObject($value);
case is_array($value):
return json_encode($array);
case is_bool($value):
return (int) $value;
}
return $value;
}
public function defaultEngine(): ? string
{
return null;
@@ -246,6 +245,15 @@ class MsSQL implements AdapterInterface {
public function queryBuilderClass() : string
{
return QueryBuilder\MssqlQueryBuilder::class;
return QueryBuilder\Sql\MssqlQueryBuilder::class;
}
public function schemaTable(ConnectionAdapter $adapter, $databaseName, string $tableName) : null|object
{
return \Ulmus\Entity\Mssql\Table::repository(Repository::DEFAULT_ALIAS, $adapter)
->select(\Ulmus\Common\Sql::raw('this.*'))
->where($this->escapeIdentifier('table_schema', AdapterInterface::IDENTIFIER_FIELD), $databaseName)
->or($this->escapeIdentifier('table_catalog', AdapterInterface::IDENTIFIER_FIELD), $databaseName)
->loadOneFromField($this->escapeIdentifier('table_name', AdapterInterface::IDENTIFIER_FIELD), $tableName);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace Ulmus\Adapter;
use Ulmus\Migration\FieldDefinition;
class MsSQLFieldMapper extends SqlFieldMapper
{
public function map() : void
{
parent::map();
if (in_array($this->type, [ 'CHAR', 'VARCHAR', 'TEXT', ])) {
$this->type = "N" . $this->type;
};
}
/* @TODO !
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);
}
}
* */
}
+65 -33
View File
@@ -2,17 +2,23 @@
namespace Ulmus\Adapter;
use Ulmus\Entity\InformationSchema\Table;
use Ulmus\QueryBuilder;
use Ulmus\Repository;
use Ulmus\Common\PdoObject;
use Ulmus\ConnectionAdapter;
use Ulmus\Entity\Mysql\Table;
use Ulmus\Migration\FieldDefinition;
use Ulmus\Migration\MigrateInterface;
use Ulmus\Migration\SqlMigrationTrait;
use Ulmus\QueryBuilder\Sql;
use Ulmus\Pdo;
use Ulmus\Exception\AdapterConfigurationException;
use Ulmus\Ulmus;
use Ulmus\Migration\FieldDefinition;
use Ulmus\Repository;
class MySQL implements AdapterInterface {
use DefaultAdapterTrait;
class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface {
use SqlAdapterTrait, SqlMigrationTrait;
const ALLOWED_ATTRIBUTES = [
'default', 'primary_key', 'auto_increment', 'update',
];
const DSN_PREFIX = "mysql";
@@ -20,9 +26,9 @@ class MySQL implements AdapterInterface {
public string $database;
public string $username;
protected string $username;
public string $password;
protected string $password;
public string $charset = "utf8mb4";
@@ -33,7 +39,9 @@ class MySQL implements AdapterInterface {
public function __construct(
?string $hostname = null,
?string $database = null,
#[\SensitiveParameter]
?string $username = null,
#[\SensitiveParameter]
?string $password = null,
?int $port = null,
?string $charset = null
@@ -63,17 +71,17 @@ class MySQL implements AdapterInterface {
}
}
public function connect() : PdoObject
public function connect() : \PDO
{
try {
$pdo = new PdoObject($this->buildDataSourceName(), $this->username, $this->password);
$pdo = new Pdo\Mysql($this->buildDataSourceName(), $this->username, $this->password);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(\PDO::ATTR_AUTOCOMMIT, false);
$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 {
@@ -135,9 +143,17 @@ class MySQL implements AdapterInterface {
}
}
public function escapeIdentifier(string $segment, int $type) : string
public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string
{
$mapper = new MySQLFieldMapper($field);
return $typeOnly ? $mapper->type : $mapper->render();
}
public static function escapeIdentifier(string $segment, int $type) : string
{
switch($type) {
default:
case static::IDENTIFIER_DATABASE:
case static::IDENTIFIER_TABLE:
case static::IDENTIFIER_FIELD:
@@ -148,27 +164,43 @@ class MySQL implements AdapterInterface {
}
}
public function writableValue(mixed $value) : mixed
{
switch (true) {
case $value instanceof \UnitEnum:
return Ulmus::convertEnum($value);
case is_object($value):
return Ulmus::convertObject($value);
case is_array($value):
return json_encode($value);
case is_bool($value):
return (int) $value;
}
return $value;
}
public function defaultEngine(): ? string
{
return "InnoDB";
}
public function queryBuilderClass() : string
{
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);
}
public function generateAlterColumn(FieldDefinition $definition, array $field) : string|\Stringable
{
if ($field['action'] === 'add') {
if (! empty($field['previous'])) {
$position = sprintf('AFTER %s', $this->escapeIdentifier($field['previous']->field, AdapterInterface::IDENTIFIER_FIELD));
}
else {
$position = "FIRST";
}
}
return implode(" ", array_filter([
strtoupper($field['action']),
$this->escapeIdentifier($definition->getSqlName(), AdapterInterface::IDENTIFIER_FIELD),
$definition->getSqlType(),
$definition->getSqlParams(),
$position ?? null,
]));
}
}
+37
View File
@@ -0,0 +1,37 @@
<?php
namespace Ulmus\Adapter;
use Ulmus\Migration\FieldDefinition;
class MySQLFieldMapper extends SqlFieldMapper
{
public function map() : void
{
$type = $this->field->type;
$length = $this->field->length;
if ( enum_exists($type) ) {
# Haven't found a better way yet to check for BackendEnum without an instance of the object
if ( ! method_exists($type, 'tryFrom') ) {
throw new \Ulmus\Exception\BackedEnumRequired(sprintf("You must define your enum as a BackedEnum instead of an UnitEnum for field '%s'.", $this->field->getColumnName()));
}
$this->length = implode(',', array_map(fn($e) => MySQL::escapeIdentifier($e->value, MySQL::IDENTIFIER_VALUE) , $type::cases()));
$this->type = "ENUM";
}
else {
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);
}
}
}
+133 -65
View File
@@ -2,46 +2,45 @@
namespace Ulmus\Adapter;
use Ulmus\Common\PdoObject;
use Ulmus\Entity\Sqlite\Table;
use Ulmus\Exception\AdapterConfigurationException;
use Collator;
use Ulmus\Pdo;
use Ulmus\ConnectionAdapter;
use Ulmus\Entity;
use Ulmus\Migration\FieldDefinition;
use Ulmus\{Repository, QueryBuilder, Ulmus};
use Ulmus\{Migration\MigrateInterface, Migration\SqlMigrationTrait, Repository, QueryBuilder};
class SQLite implements AdapterInterface {
use DefaultAdapterTrait;
class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface {
use SqlAdapterTrait, SqlMigrationTrait;
const ALLOWED_ATTRIBUTES = [
'default', 'primary_key', 'auto_increment', 'collate nocase', 'collate binary', 'collate rtrim',
];
const DSN_PREFIX = "sqlite";
public string $path;
public array $pragma;
public function __construct(
? string $path = null,
? array $pragma = null
) {
if ($path !== null) {
$this->path = $path;
}
public null|string $path = null,
public null|array $pragmaBegin = null,
public null|array $pragmaClose = null,
) { }
if ($pragma !== null) {
$this->pragma = $pragma;
}
}
public function connect() : PdoObject
public function connect() : \Pdo
{
try {
$pdo = new PdoObject($this->buildDataSourceName(), null, null);
$pdo = new Pdo\Sqlite($this->buildDataSourceName(), null, null);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
$pdo->onClose = function(\PDO $obj) {
static::registerPragma($obj, $this->pragmaClose);
};
$this->exportFunctions($pdo);
$this->exportCollations($pdo);
$this->registerPragma($pdo, $this->pragmaBegin);
}
catch(PDOException $ex){
catch(\PDOException $ex){
throw $ex;
}
@@ -58,13 +57,15 @@ class SQLite implements AdapterInterface {
public function setup(array $configuration) : void
{
$this->path = $configuration['path'] ?? "";
$this->pragma = $configuration['pragma'] ?? [];
$this->pragmaBegin = array_filter($configuration['pragma_begin'] ?? []);
$this->pragmaClose = array_filter($configuration['pragma_close'] ?? []);
}
# https://sqlite.org/lang_keywords.html
public function escapeIdentifier(string $segment, int $type) : string
public static function escapeIdentifier(string $segment, int $type) : string
{
switch($type) {
default:
case static::IDENTIFIER_DATABASE:
case static::IDENTIFIER_TABLE:
case static::IDENTIFIER_FIELD:
@@ -87,20 +88,22 @@ class SQLite implements AdapterInterface {
return substr($base, 0, strrpos($base, '.') ?: strlen($base));
}
public function schemaTable(string $databaseName, string $tableName) : null|object
public function schemaTable(ConnectionAdapter $adapter, string $databaseName, string $tableName) : null|object
{
return Table::repository()->loadOneFromField(Table::field('tableName'), $tableName);
return Entity\Sqlite\Table::repository(Repository::DEFAULT_ALIAS, $adapter)
->select(\Ulmus\Common\Sql::raw('this.*'))
->loadOneFromField(Entity\Sqlite\Table::field('tableName'), $tableName);
}
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) ) {
$type = "TEXT";
$length = strlen((string) $type);
#$length = strlen((string) $type);
}
else {
switch($type) {
@@ -113,6 +116,10 @@ class SQLite implements AdapterInterface {
break;
case "array":
$type = "JSON";
$length = null;
break;
case "string":
$type = "TEXT";
$length = null;
@@ -128,26 +135,7 @@ class SQLite implements AdapterInterface {
}
}
return $typeOnly ? $type : $type . ( $length ? "($length" . ( isset($precision) ? ",$precision" : "" ) . ")" : "" );
}
public function writableValue(mixed $value) /*: mixed*/
{
switch (true) {
case $value instanceof \UnitEnum:
return Ulmus::convertEnum($value);
case is_object($value):
return Ulmus::convertObject($value);
case is_array($value):
return json_encode($value);
case is_bool($value):
return (int) $value;
}
return $value;
return $typeOnly ? $type : $type . ( $length ? "($length" . ")" : "" );
}
public function tableSyntax() : array
@@ -166,23 +154,31 @@ class SQLite implements AdapterInterface {
public function queryBuilderClass() : string
{
return QueryBuilder\SqliteQueryBuilder::class;
return QueryBuilder\Sql\SqliteQueryBuilder::class;
}
public function exportFunctions(PdoObject $pdo) : void
public function exportFunctions(\PDO $pdo) : void
{
$pdo->sqliteCreateFunction('if', fn($comparison, $yes, $no) => $comparison ? $yes : $no, 3);
$pdo->sqliteCreateFunction('length', fn($string) => strlen($string), 1);
$pdo->sqliteCreateFunction('lcase', fn($string) => strtolower($string), 1);
$pdo->sqliteCreateFunction('ucase', fn($string) => strtoupper($string), 1);
$pdo->sqliteCreateFunction('left', fn($string, $length) => substr($string, 0, $length), 2);
$pdo->sqliteCreateFunction('right', fn($string, $length) => substr($string, -$length), 2);
$pdo->sqliteCreateFunction('strcmp', fn($s1, $s2) => strcmp($s1, $s2), 2);
$pdo->sqliteCreateFunction('lpad', fn($string, $length, $pad) => str_pad($string, $length, $pad, STR_PAD_LEFT), 3);
$pdo->sqliteCreateFunction('rpad', fn($string, $length, $pad) => str_pad($string, $length, $pad, STR_PAD_RIGHT), 3);
$pdo->sqliteCreateFunction('concat', fn(...$args) => implode('', $args), -1);
$pdo->sqliteCreateFunction('concat_ws', fn($separator, ...$args) => implode($separator, $args), -1);
$pdo->sqliteCreateFunction('find_in_set', function($string, $string_list) {
$pdo->createFunction('if', fn($comparison, $yes, $no) => $comparison ? $yes : $no, 3);
$pdo->createFunction('length', fn($string) => strlen($string), 1);
$pdo->createFunction('lcase', fn($string) => strtolower($string), 1);
$pdo->createFunction('ucase', fn($string) => strtoupper($string), 1);
$pdo->createFunction('md5', fn($string) => md5($string), 1);
$pdo->createFunction('sha1', fn($string) => sha1($string), 1);
$pdo->createFunction('sha256', fn($string) => hash('sha256', $string), 1);
$pdo->createFunction('sha512', fn($string) => hash('sha512', $string), 1);
$pdo->createFunction('whirlpool', fn($string) => hash('whirlpool', $string), 1);
$pdo->createFunction('murmur3a', fn($string) => hash('murmur3a', $string), 1);
$pdo->createFunction('murmur3c', fn($string) => hash('murmur3c', $string), 1);
$pdo->createFunction('murmur3f', fn($string) => hash('murmur3f', $string), 1);
$pdo->createFunction('left', fn($string, $length) => substr($string, 0, $length), 2);
$pdo->createFunction('right', fn($string, $length) => substr($string, -$length), 2);
$pdo->createFunction('strcmp', fn($s1, $s2) => strcmp($s1, $s2), 2);
$pdo->createFunction('lpad', fn($string, $length, $pad) => str_pad($string, $length, $pad, STR_PAD_LEFT), 3);
$pdo->createFunction('rpad', fn($string, $length, $pad) => str_pad($string, $length, $pad, STR_PAD_RIGHT), 3);
$pdo->createFunction('concat', fn(...$args) => implode('', $args), -1);
$pdo->createFunction('concat_ws', fn($separator, ...$args) => implode($separator, $args), -1);
$pdo->createFunction('find_in_set', function($string, $string_list) {
if ( $string === null || $string_list === null ) {
return null;
}
@@ -193,5 +189,77 @@ class SQLite implements AdapterInterface {
return (int) in_array($string, explode(',', $string_list));
}, 2);
$pdo->createFunction('day', fn($date) => ( new \DateTime($date) )->format('j'), 1);
$pdo->createFunction('month', fn($date) => ( new \DateTime($date) )->format('n'), 1);
$pdo->createFunction('year', fn($date) => ( new \DateTime($date) )->format('Y'), 1);
$pdo->createFunction('str_to_date', fn($value, $format) => ($f = \DateTime::createFromFormat($format, $value)) ? $f->format('Y-m-d H:i:s') : false);
}
public function exportCollations(\PDO $pdo) : void
{
if ( class_exists('Locale') ) {
# @TODO debug this, case-sensitivity not working properly !!
$collator = new Collator(\Locale::getDefault());
$collator->setStrength(Collator::TERTIARY);
$collator->setAttribute(Collator::NUMERIC_COLLATION, Collator::ON);
$pdo->createCollation('locale_cmp', fn($e1, $e2) => $collator->compare($e1, $e2));
$pdo->createCollation('locale_cmp_desc', fn($e1, $e2) => $collator->compare($e2, $e1));
$collatorCi = new Collator(\Locale::getDefault());
$collatorCi->setStrength(Collator::SECONDARY);
$collatorCi->setAttribute(Collator::NUMERIC_COLLATION, Collator::ON);
$pdo->createCollation('locale_cmp_ci', fn($e1, $e2) => $collatorCi->compare($e1, $e2));
$pdo->createCollation('locale_cmp_ci_desc', fn($e1, $e2) => $collatorCi->compare($e2, $e1));
}
else {
$comp = fn(string $e1, string $e2) => \iconv('UTF-8', 'ASCII//TRANSLIT', $e1) <=> \iconv('UTF-8', 'ASCII//TRANSLIT', $e2);
$pdo->createCollation('locale_cmp', fn($e1, $e2) => $comp);
$pdo->createCollation('locale_cmp_desc', fn($e2, $e1) => $comp);
$compCi = fn(string $e1, string $e2) => strtoupper(\iconv('UTF-8', 'ASCII//TRANSLIT', $e1)) <=> strtoupper(\iconv('UTF-8', 'ASCII//TRANSLIT', $e2));
$pdo->createCollation('locale_cmp_ci', fn($e1, $e2) => $compCi);
$pdo->createCollation('locale_cmp_ci_desc', fn($e2, $e1) => $compCi);
}
}
public static function registerPragma(\PDO $pdo, array $pragmaList) : void
{
$builder = new QueryBuilder\Sql\SqliteQueryBuilder();
foreach($pragmaList as $pragma) {
list($key, $value) = explode('=', $pragma) + [ null, null ];
$sql = $builder->pragma($key, $value)->render();
$query = $pdo->query($sql);
if ( ! $query->execute() ) {
throw new \InvalidArgumentException(sprintf("Pragma query could not be executed : %s", $sql));
}
$builder->reset();
}
}
public function generateAlterColumn(FieldDefinition $definition, array $field) : string|\Stringable
{
return implode(" ", [
strtoupper($field['action']),
$this->escapeIdentifier($definition->getSqlName(), static::IDENTIFIER_FIELD),
$definition->getSqlType(),
$definition->getSqlParams(),
]);
}
public function supportAlterColumnAction(string $action)
{
return in_array(strtolower($action), [ 'add' ]);
}
public function splitAlterQuery() : bool
{
return true;
}
}
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace Ulmus\Adapter;
interface SqlAdapterInterface
{
public static function escapeIdentifier(string $segment, int $type) : string;
public function defaultEngine() : ? string;
}
+62
View File
@@ -0,0 +1,62 @@
<?php
namespace Ulmus\Adapter;
use Ulmus\{Common\Sql,
ConnectionAdapter,
Entity\InformationSchema\Table,
Migration\FieldDefinition,
Repository,
QueryBuilder\SqlQueryBuilder,
Ulmus};
trait SqlAdapterTrait
{
public function repositoryClass() : string
{
return Repository::class;
}
public function queryBuilderClass() : string
{
return SqlQueryBuilder::class;
}
public function tableSyntax() : array
{
return [
'ai' => "AUTO_INCREMENT",
'pk' => "PRIMARY KEY",
'unsigned' => "UNSIGNED",
];
}
public function databaseName() : string
{
return $this->database;
}
public function whitelistAttributes(array &$parameters) : void
{
$parameters = array_intersect_key($parameters, array_flip(static::ALLOWED_ATTRIBUTES));
}
public function writableValue(mixed $value) : mixed
{
switch (true) {
case $value instanceof \UnitEnum:
return Ulmus::convertEnum($value);
case is_object($value):
return Ulmus::convertObject($value);
case is_array($value):
return json_encode($value);
case is_bool($value):
return (int) $value;
}
return $value;
}
}
+100
View File
@@ -0,0 +1,100 @@
<?php
namespace Ulmus\Adapter;
use Ulmus\Migration\FieldDefinition;
use Ulmus\Entity;
class SqlFieldMapper
{
public string $type;
public string $length;
public function __construct(
public FieldDefinition $field,
) {
$this->map();
}
public function map() : void
{
$type = $this->field->type;
$length = $this->field->length;
if ( is_a($type, Entity\Field\Date::class, true) ) {
$type = "DATE";
}
elseif ( is_a($type, Entity\Field\Time::class, true) ) {
$type = "TIME";
}
elseif ( is_a($type, \DateTime::class, true) ) {
$type = "DATETIME";
}
elseif ( enum_exists($type) ) {
# Haven't found a better way yet to check for BackendEnum without an instance of the object
if ( ! method_exists($type, 'tryFrom') ) {
throw new \Ulmus\Exception\BackedEnumRequired(sprintf("You must define your enum as a BackedEnum instead of an UnitEnum for field '%s'.", $this->field->getColumnName()));
}
$type = "string";
}
switch($type) {
case "bool":
$this->type = "TINYINT";
$this->length = 1;
break;
case "array":
# Was set at JSON, but for now LONGTEXT is an alias of it (with additional constraints)
$this->type = "LONGTEXT";
break;
case "string":
if ($length && $length <= 255) {
$this->type = "VARCHAR";
$this->length = $length;
break;
}
elseif (! $length || ( $length <= 65535 ) ) {
$this->type = "TEXT";
}
elseif ( $length <= 16777215 ) {
$this->type = "MEDIUMTEXT";
}
elseif ($length <= 4294967295) {
$this->type = "LONGTEXT";
}
else {
throw new \Exception("A column with a length bigger than 4GB cannot be created.");
}
# Length is unnecessary on TEXT fields
unset($length);
break;
case "float":
$this->type = "DOUBLE";
default:
if ($length) {
$this->length = $length;
}
$this->type ??= strtoupper($type);
}
$this->postProcess();
}
public function render() : string
{
return $this->type . ( isset($this->length) ? "($this->length)" : "" );
}
public function postProcess() : void
{
}
}
-7
View File
@@ -1,7 +0,0 @@
<?php
namespace Ulmus\Annotation\Classes;
class Collation implements \Notes\Annotation {
}
-7
View File
@@ -1,7 +0,0 @@
<?php
namespace Ulmus\Annotation\Classes;
class Method implements \Notes\Annotation {
}
-27
View File
@@ -1,27 +0,0 @@
<?php
namespace Ulmus\Annotation\Classes;
class Table implements \Notes\Annotation {
public string $name;
public string $database;
public string $schema;
public string $adapter;
public string $engine;
public function __construct($name = null, $engine = null)
{
if ( $name !== null ) {
$this->name = $name;
}
if ( $engine !== null ) {
$this->engine = $engine;
}
}
}
-33
View File
@@ -1,33 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
class Field implements \Notes\Annotation {
public string $type;
public string $name;
public int $length;
public int $precision;
public array $attributes = [];
public bool $nullable;
public /* mixed */ $default;
public bool $readonly = false;
public function __construct(? string $type = null, ? int $length = null)
{
if ( $type !== null ) {
$this->type = $type;
}
if ( $length !== null ) {
$this->length = $length;
}
}
}
-11
View File
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Bigint extends \Ulmus\Annotation\Property\Field
{
public function __construct(? string $type = "bigint", ? int $length = null)
{
parent::__construct($type, $length);
}
}
-11
View File
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Blob extends \Ulmus\Annotation\Property\Field
{
public function __construct(? string $type = "blob", ? int $length = null)
{
parent::__construct($type, $length);
}
}
@@ -1,13 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class CreatedAt extends \Ulmus\Annotation\Property\Field {
public function __construct()
{
$this->nullable = false;
$this->type = "timestamp";
$this->attributes['default'] = "CURRENT_TIMESTAMP";
}
}
-11
View File
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Date extends \Ulmus\Annotation\Property\Field {
public function __construct(? string $type = "date", ? int $length = null)
{
parent::__construct($type, $length);
}
}
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Datetime extends \Ulmus\Annotation\Property\Field {
public function __construct(? string $type = "datetime", ? int $length = null)
{
parent::__construct($type, $length);
}
}
@@ -1,20 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
/**
* Since we need consistancy between the declaration of our ID and FK fields, it
* was decided to extend the Id class instead of Field for this case.
*/
class ForeignKey extends PrimaryKey {
public function __construct(? string $type = null, ? int $length = null)
{
parent::__construct($type, $length);
unset($this->nullable);
$this->attributes['primary_key'] = false;
$this->attributes['auto_increment'] = false;
}
}
-15
View File
@@ -1,15 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Id extends \Ulmus\Annotation\Property\Field\PrimaryKey {
public function __construct()
{
$this->attributes['unsigned'] = true;
$this->attributes['auto_increment'] = true;
parent::__construct('bigint');
}
}
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Longblob extends \Ulmus\Annotation\Property\Field
{
public function __construct(? string $type = "longblob", ? int $length = null)
{
parent::__construct($type, $length);
}
}
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Longtext extends \Ulmus\Annotation\Property\Field
{
public function __construct(? string $type = "longtext", ? int $length = null)
{
parent::__construct($type, $length);
}
}
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Mediumblob extends \Ulmus\Annotation\Property\Field
{
public function __construct(? string $type = "mediumblob", ? int $length = null)
{
parent::__construct($type, $length);
}
}
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Mediumtext extends \Ulmus\Annotation\Property\Field
{
public function __construct(? string $type = "mediumtext", ? int $length = null)
{
parent::__construct($type, $length);
}
}
@@ -1,15 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class PrimaryKey extends \Ulmus\Annotation\Property\Field {
public function __construct(? string $type = null, ? int $length = null)
{
$this->nullable = false;
$this->attributes['primary_key'] = true;
parent::__construct($type, $length);
}
}
-11
View File
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Text extends \Ulmus\Annotation\Property\Field
{
public function __construct(? string $type = "text", ? int $length = null)
{
parent::__construct($type, $length);
}
}
-11
View File
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Time extends \Ulmus\Annotation\Property\Field {
public function __construct(? string $type = "time", ? int $length = null)
{
parent::__construct($type, $length);
}
}
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Blob extends \Ulmus\Annotation\Property\Field
{
public function __construct(? string $type = "tinyblob", ? int $length = null)
{
parent::__construct($type, $length);
}
}
-11
View File
@@ -1,11 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class Tinyint extends \Ulmus\Annotation\Property\Field
{
public function __construct(? string $type = "tinyint", ? int $length = null)
{
parent::__construct($type, $length);
}
}
@@ -1,14 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Field;
class UpdatedAt extends \Ulmus\Annotation\Property\Field {
public function __construct()
{
$this->nullable = true;
$this->type = "timestamp";
$this->attributes['update'] = "CURRENT_TIMESTAMP";
$this->attributes['default'] = null;
}
}
-15
View File
@@ -1,15 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
class Filter implements \Notes\Annotation {
public string $method;
public function __construct(string $method = null)
{
if ( $method !== null ) {
$this->method = $method;
}
}
}
-15
View File
@@ -1,15 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
class FilterJoin implements \Notes\Annotation {
public string $method;
public function __construct(string $method = null)
{
if ( $method !== null ) {
$this->method = $method;
}
}
}
-5
View File
@@ -1,5 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
class Having extends Where {}
-31
View File
@@ -1,31 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
class Join implements \Notes\Annotation {
public string $type;
public /*string|Stringable*/ $key;
public /*string|Stringable*/ $foreignKey;
public string $entity;
public string $alias;
public function __construct(? string $type = null, /*? string|Stringable*/ $key = null, /*? string|Stringable*/ $foreignKey = null)
{
if ($type !== null) {
$this->type = $type;
}
if ($key !== null) {
$this->key = $key;
}
if ($foreignKey !== null) {
$this->foreignKey = $foreignKey;
}
}
}
-5
View File
@@ -1,5 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
class On extends Where {}
-14
View File
@@ -1,14 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
use Ulmus\Query;
class OrWhere extends Where {
public function __construct(/* ? Stringable */ $field = null, $value = null, ? string $operator = null, ? string $condition = null)
{
parent::__construct($field, $value, $operator, Query\Where::CONDITION_OR);
}
}
-21
View File
@@ -1,21 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
class OrderBy implements \Notes\Annotation {
public string $field;
public string $order = "ASC";
public function __construct(string $field = null, string $order = null)
{
if ( $field !== null ) {
$this->field = $field;
}
if ( $order !== null ) {
$this->order = $order;
}
}
}
-88
View File
@@ -1,88 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
class Relation implements \Notes\Annotation {
public string $type;
public /*stringable*/ $key;
public /* callable */ $generateKey;
public /*stringable*/ $foreignKey;
public array $foreignKeys;
public string $bridge;
public /*stringable*/ $bridgeKey;
public /*stringable*/ $bridgeForeignKey;
public string $entity;
public string $join;
public string $function = "loadAll";
public function __construct(string $type = null)
{
if ( $type !== null ) {
$this->type = $type;
}
}
public function entity() {
try {
$e = $this->entity;
} catch (\Throwable $ex) {
throw new \Exception("Your @Relation annotation seems to be missing an `entity` entry.");
}
return new $e();
}
public function bridge() {
$e = $this->bridge;
return new $e();
}
public function normalizeType() : string
{
return strtolower(str_replace(['-', '_', ' '], '', $this->type));
}
public function isOneToOne() : bool
{
return $this->normalizeType() === 'onetoone';
}
public function isOneToMany() : bool
{
return $this->normalizeType() === 'onetomany';
}
public function isManyToMany() : bool
{
return $this->normalizeType() === 'manytomany';
}
public function function() : string
{
if ($this->function) {
return $this->function;
}
elseif ($this->isOneToOne()) {
return 'load';
}
return 'loadAll';
}
public function hasBridge() : bool
{
return isset($this->bridge);
}
}
@@ -1,5 +0,0 @@
<?php
namespace Ulmus\Annotation\Property\Relation;
class Ignore implements \Notes\Annotation {}
-19
View File
@@ -1,19 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
class Virtual extends Field {
public bool $readonly = true;
public \Closure $closure;
public string $method;
public function __construct(? \Closure $closure = null)
{
if ( $closure !== null ) {
$this->closure = $closure;
}
}
}
-30
View File
@@ -1,30 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
use Ulmus\Query;
class Where implements \Notes\Annotation {
public /* stringable */ $field;
public $value;
public string $operator;
public string $condition;
public function __construct(/* ? Stringable */ $field = null, $value = null, ? string $operator = null, ? string $condition = null)
{
if ( $field !== null ) {
$this->field = $field;
}
if ( $value !== null ) {
$this->value = $value;
}
$this->operator = $operator !== null ? $operator : Query\Where::OPERATOR_EQUAL;
$this->condition = $condition !== null ? $condition : Query\Where::CONDITION_AND;
}
}
-15
View File
@@ -1,15 +0,0 @@
<?php
namespace Ulmus\Annotation\Property;
class WithJoin implements \Notes\Annotation {
protected array $joins;
public function __construct(/*Stringable|array|null*/ $joins = null)
{
if ( $joins ) {
$this->joins = (array)$joins;
}
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace Ulmus\Attribute;
use Ulmus\Common\EntityField;
use Ulmus\Repository;
class Attribute
{
public static function handleArrayField(null|\Stringable|string|array $field, null|string|bool $alias = Repository::DEFAULT_ALIAS, string $separator = ', ') : mixed
{
if ( is_array($field) ) {
if (count($field) < 2) {
throw new \RuntimeException(
sprintf("Array field must be formed of at least two things, a class name, and a property. (received %s)", json_encode($field))
);
}
$class = array_shift($field);
$field[1] ??= $alias;
if (is_array($field[0])) {
$field[] = $separator;
return $class::fields(...$field);
}
return $class::field(...$field);
}
return $field;
}
}
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace Ulmus\Attribute;
enum ConstrainActionEnum : string
{
case Cascade = 'cascade';
case NoAction = 'noaction';
case Restrict = 'restrict';
case SetNull = 'setnull';
}
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace Ulmus\Attribute;
enum IndexTypeEnum : string
{
case Primary = 'primary';
case Index = 'index';
case Unique = 'unique';
case Spatial = 'spatial';
case Fulltext = 'fulltext';
}
@@ -0,0 +1,8 @@
<?php
namespace Ulmus\Attribute\Obj;
interface AdapterAttributeInterface
{
public function adapter() : false|string;
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Ulmus\Attribute\Obj;
#[\Attribute(\Attribute::TARGET_CLASS)]
class Collation {
public function __construct(
public string $name = ""
) {}
}
+23
View File
@@ -0,0 +1,23 @@
<?php
namespace Ulmus\Attribute\Obj;
use Ulmus\Attribute\Attribute;
use Ulmus\Attribute\ConstrainActionEnum;
use Ulmus\Attribute\IndexTypeEnum;
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
class Constrain {
public function __construct(
public array $columns,
public null|IndexTypeEnum $type = null,
public null|string $name = null,
public null|array|string|\Stringable $foreignKey = null,
public null|array|string|\Stringable $references = null,
public ConstrainActionEnum $onDelete = ConstrainActionEnum::NoAction,
public ConstrainActionEnum $onUpdate = ConstrainActionEnum::NoAction,
) {
$this->foreignKey = Attribute::handleArrayField($this->foreignKey, false);
$this->references = Attribute::handleArrayField($this->references, false);
}
}
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace Ulmus\Attribute\Obj;
use Ulmus\Attribute\IndexTypeEnum;
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
class Index {
public function __construct(
public string|array $column,
public IndexTypeEnum $type = IndexTypeEnum::Unique,
public null|string $name = null,
) {}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Ulmus\Attribute\Obj;
#[\Attribute(\Attribute::TARGET_CLASS)]
class JsonSerialize {
public function __construct(
public bool $includeRelations = true,
) {}
}
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace Ulmus\Attribute\Obj;
#[\Attribute(\Attribute::TARGET_CLASS)]
class Method {
}
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace Ulmus\Attribute\Obj;
#[\Attribute(\Attribute::TARGET_CLASS)]
class Table implements AdapterAttributeInterface {
public function __construct(
public ? string $name = null,
public ? string $database = null,
public ? string $schema = null,
public ? string $adapter = null,
public ? string $engine = null,
public string $description = "",
) {}
public function adapter() : false|string
{
return $this->adapter ?: false;
}
}
+76
View File
@@ -0,0 +1,76 @@
<?php
namespace Ulmus\Attribute\Property;
use Notes\Common\ReflectedProperty;
use Ulmus\Entity\EntityInterface;
use Ulmus\Entity\JsonUnserializable;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class ArrayOf implements \Ulmus\Entity\EntityValueModifier
{
public function __construct(
public readonly string $type,
) {}
public function push(mixed $value, ReflectedProperty $property): mixed
{
$return = [];
foreach($value as $index => $item) {
if (! is_object($item)) {
if (enum_exists($this->type)) {
if ($this->type::tryFrom($item) === null) {
throw new \InvalidArgumentException(
sprintf("Given item '%s' is not a valid enum for type %s ; try one of theses instead : %s", $item, $this->type, implode("', '", array_map(fn($e) => $e->value, $this->type::cases())))
);
} else {
$obj = $this->type::from($item);
}
}
elseif (class_exists($this->type)) {
if (is_subclass_of($this->type, JsonUnserializable::class)) {
$obj = (new \ReflectionClass($this->type))->newInstanceWithoutConstructor();
$obj->jsonUnserialize($item);
}
else {
$obj = new $this->type($item);
}
}
else {
throw new \InvalidArgumentException("Given type for ArrayOf is incompatible with it's use. An object should be provided");
}
$return[$index] = $obj;
}
}
if (! $property->type->builtIn) {
$cls = $property->type->type;
return new $cls($return);
}
return $return;
}
public function pull(mixed $value, ReflectedProperty $property) : mixed
{
$return = [];
foreach($value as $index => $item) {
if (is_object($item)) {
if (enum_exists($this->type)) {
$value = $item->value;
} elseif (class_exists($this->type)) {
$value = (string) $value;
}
$return[$index] = $value;
}
}
return $return;
}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Ulmus\Attribute\Property;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Collation {
public function __construct(
public string $name = ""
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Field {
public function __construct(
public ? string $name = null,
public ? string $type = null,
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 null|int $decimal = null,
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Bigint extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "bigint",
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,
) {}
}
+19
View File
@@ -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 = "",
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Bit extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "bit",
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,
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Blob extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "blob",
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,
) {}
}
+19
View File
@@ -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 = "",
) {}
}
@@ -0,0 +1,17 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class CreatedAt extends \Ulmus\Attribute\Property\Field {
public function __construct(
public ? string $name = null,
public ? string $type = "timestamp",
public array $attributes = [
'default' => "CURRENT_TIMESTAMP",
],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
) {}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Date extends \Ulmus\Attribute\Property\Field {
public function __construct(
public ? string $name = null,
public ? string $type = "date",
public array $attributes = [],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
) {}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Datetime extends \Ulmus\Attribute\Property\Field {
public function __construct(
public ? string $name = null,
public ? string $type = "datetime",
public array $attributes = [],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Decimal extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "decimal",
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,
) {}
}
+19
View File
@@ -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 = "",
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Float 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,
) {}
}
@@ -0,0 +1,32 @@
<?php
namespace Ulmus\Attribute\Property\Field;
use Ulmus\Attribute\Attribute;
use Ulmus\Attribute\ConstrainActionEnum;
/**
* Since we need consistancy between the declaration of our ID and FK fields, it
* was decided to extend the PK class instead of Field for this case.
*/
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class ForeignKey extends PrimaryKey {
public function __construct(
public ? string $name = null,
public ? string $type = null,
public null|int|string $length = null,
public ? int $precision = null,
public array $attributes = [
'primary_key' => false,
'auto_increment' => false
],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
public null|string $relation = null,
public ConstrainActionEnum $onDelete = ConstrainActionEnum::NoAction,
public ConstrainActionEnum $onUpdate = ConstrainActionEnum::NoAction,
) {
#$this->references = Attribute::handleArrayField($this->references, false);
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Id extends \Ulmus\Attribute\Property\Field {
public function __construct(
public ? string $name = null,
public ? string $type = 'bigint',
public null|int|string $length = null,
public ? int $precision = null,
public array $attributes = [
'unsigned' => true,
'auto_increment' => true,
'primary_key' => true,
],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = true,
) {}
}
+19
View File
@@ -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 = "",
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Longblob extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "longblob",
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,
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Longtext extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "longtext",
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,
) {}
}
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Mediumblob extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "mediumblob",
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,
) {}
}
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Mediumint extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "mediumint",
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,
) {}
}
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Mediumtext extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "mediumtext",
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,
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Numeric extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "numeric",
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,
) {}
}
@@ -0,0 +1,20 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class PrimaryKey extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = 'bigint',
public null|int|string $length = null,
public ? int $precision = null,
public array $attributes = [
'primary_key' => true,
],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
) {}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Select {
public function __construct(
public string $sql,
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Smallint extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "smallint",
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,
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Text extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "text",
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,
) {}
}
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Time extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "time",
public array $attributes = [],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
) {}
}
@@ -0,0 +1,16 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Timestamp extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "timestamp",
public array $attributes = [],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Blob extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "tinyblob",
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,
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Tinyint extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "tinyint",
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,
) {}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Tinytext extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "tinytext",
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,
) {}
}
@@ -0,0 +1,19 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class UpdatedAt extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "timestamp",
public array $attributes = [
'update' => "CURRENT_TIMESTAMP",
'default' => null,
],
public bool $nullable = true,
public mixed $default = null,
public bool $readonly = false,
) {}
}
@@ -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 = "",
) {}
}
+19
View File
@@ -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 = "",
) {}
}
+19
View File
@@ -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 = "",
) {}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Ulmus\Attribute\Property;
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::IS_REPEATABLE)]
class Filter {
public function __construct(
public string $method = ""
) {}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Ulmus\Attribute\Property;
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::IS_REPEATABLE)]
class FilterJoin {
public function __construct(
public string $method = ""
) {}
}
@@ -1,8 +1,9 @@
<?php
namespace Ulmus\Annotation\Property;
namespace Ulmus\Attribute\Property;
class GroupBy implements \Notes\Annotation {
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::IS_REPEATABLE)]
class GroupBy {
public array $fields = [];
+6
View File
@@ -0,0 +1,6 @@
<?php
namespace Ulmus\Attribute\Property;
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::IS_REPEATABLE)]
class Having extends Where {}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace Ulmus\Attribute\Property;
use Ulmus\Attribute\IndexTypeEnum;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Index {
public function __construct(
public IndexTypeEnum $type = IndexTypeEnum::Index,
) {}
}
+51
View File
@@ -0,0 +1,51 @@
<?php
namespace Ulmus\Attribute\Property;
use Ulmus\Attribute\Attribute;
use Ulmus\Repository;
#[\Attribute]
class Join implements ResettablePropertyInterface {
public function __construct(
public string $type,
public null|string|\Stringable|array $key = null,
public null|string|\Stringable|array $foreignKey = null,
public null|string $entity = null,
public null|string $alias = null,
) {
$this->key = Attribute::handleArrayField($this->key);
$this->foreignKey = Attribute::handleArrayField($this->foreignKey);
}
## AWAITING THE Closures in constant expression from PHP 8.5 !
public function foreignKey(? Repository $repository = null) : mixed
{
if (is_string($this->foreignKey)) {
if (str_starts_with($this->foreignKey, 'fn(') && str_contains($this->foreignKey, '=>')) {
$closure = eval("return {$this->foreignKey};");
return $repository ? $closure($repository) : $closure;
}
return $this->entity::field($this->foreignKey, $this->alias);
}
return $this->foreignKey;
}
public function isOneToOne() : bool
{
return true;
}
public function isOneToMany() : bool
{
return false;
}
public function isManyToMany() : bool
{
return false;
}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Ulmus\Attribute\Property;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class JsonSerialize {
public function __construct(
public bool $ignoreField = false,
) {}
}
Loaded 100 of 227 files, more files were not shown because too many files have changed in this diff. Show more