WIP on docs and added basic enums supports
This commit is contained in:
parent
497fe5547b
commit
b6752f4364
|
@ -0,0 +1,95 @@
|
||||||
|
# Ulmus
|
||||||
|
|
||||||
|
Welcome to the official Ulmus documentation.
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
Creating a simple user entity:
|
||||||
|
|
||||||
|
*/app/entity/user.php*
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MyApp\Entity;
|
||||||
|
|
||||||
|
use Ulmus\Entity\Field\Datetime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Table('name' => "user")
|
||||||
|
*/
|
||||||
|
class User
|
||||||
|
{
|
||||||
|
use \Ulmus\EntityTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
*/
|
||||||
|
public int $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $fullname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public ? string $email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field('name' => 'is_admin')
|
||||||
|
*/
|
||||||
|
public bool $isAdmin = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @DateTime
|
||||||
|
*/
|
||||||
|
public Datetime $birthday;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Loading a user using a Primary Key
|
||||||
|
|
||||||
|
With this entity, we could quickly load a user using the `@Id` field using:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$user = Entity\User::repository()->loadFromPk((int) $_GET['id']);
|
||||||
|
```
|
||||||
|
|
||||||
|
Or we could also, load another single entity using a specific field:
|
||||||
|
|
||||||
|
```php
|
||||||
|
# fetch a single user
|
||||||
|
$user = Entity\User::repository()->loadOneFromField((string) $_POST['email'], 'email');
|
||||||
|
|
||||||
|
# Fetch every admins
|
||||||
|
$admin_list = Entity\User::repository()->loadFromField(true, 'isAdmin');
|
||||||
|
```
|
||||||
|
|
||||||
|
Using the same entity class, we could create a new user and save it using:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$user = new Entity\User();
|
||||||
|
$user->fullname = "Johnny Does";
|
||||||
|
$user->birthday = "1980-01-15";
|
||||||
|
|
||||||
|
if ( Entity\User::repository()->save($user) ) {
|
||||||
|
echo "User created successfully !";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo "User could not be saved :\";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Which would result in the following query (from MySQL adapter) being generated and executed :
|
||||||
|
|
||||||
|
```SQL
|
||||||
|
INSERT INTO `user` VALUES fullname = :fullname, birthday = :birthday;
|
||||||
|
```
|
||||||
|
|
||||||
|
Binded using:
|
||||||
|
|
||||||
|
```PHP
|
||||||
|
'fullname' => "Johnny Does",
|
||||||
|
'birthday' => "1980-01-15",
|
||||||
|
```
|
|
@ -19,7 +19,8 @@ interface AdapterInterface {
|
||||||
public function defaultEngine() : ? string;
|
public function defaultEngine() : ? string;
|
||||||
|
|
||||||
public function writableValue(/* mixed */ $value); /*: mixed*/
|
public function writableValue(/* mixed */ $value); /*: mixed*/
|
||||||
|
|
||||||
|
|
||||||
/* public function databaseName() : string;
|
/* public function databaseName() : string;
|
||||||
public function mapFieldType(FieldDefinition $field) : string;
|
public function mapFieldType(FieldDefinition $field) : string;
|
||||||
public function schemaTable(string $databaseName, string $tableName) /*: object|EntityCollection
|
public function schemaTable(string $databaseName, string $tableName) /*: object|EntityCollection
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Ulmus\Adapter;
|
namespace Ulmus\Adapter;
|
||||||
|
|
||||||
use Ulmus\{Entity\InformationSchema\Table, Migration\FieldDefinition, Repository, QueryBuilder};
|
use Ulmus\{ConnectionAdapter, Entity\InformationSchema\Table, Migration\FieldDefinition, Repository, QueryBuilder};
|
||||||
|
|
||||||
trait DefaultAdapterTrait
|
trait DefaultAdapterTrait
|
||||||
{
|
{
|
||||||
|
@ -30,9 +30,9 @@ trait DefaultAdapterTrait
|
||||||
return $this->database;
|
return $this->database;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function schemaTable(string $databaseName, string $tableName) /* : ? object */
|
public function schemaTable(ConnectionAdapter $parent, $databaseName, string $tableName) /* : ? object */
|
||||||
{
|
{
|
||||||
return Table::repository()->where(Table::field('schema'), $databaseName)->loadOneFromField(Table::field('name'), $tableName);
|
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
|
public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string
|
||||||
|
|
|
@ -83,6 +83,9 @@ class MsSQL implements AdapterInterface {
|
||||||
catch(PDOException $ex){
|
catch(PDOException $ex){
|
||||||
throw $ex;
|
throw $ex;
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
$this->password = str_repeat('*', random_int(8,16));
|
||||||
|
}
|
||||||
|
|
||||||
return $pdo;
|
return $pdo;
|
||||||
}
|
}
|
||||||
|
@ -212,9 +215,12 @@ class MsSQL implements AdapterInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function writableValue(/* mixed */ $value) /*: mixed*/
|
public function writableValue(mixed $value) /*: mixed*/
|
||||||
{
|
{
|
||||||
switch (true) {
|
switch (true) {
|
||||||
|
case $value instanceof \UnitEnum:
|
||||||
|
return Ulmus::convertEnum($value);
|
||||||
|
|
||||||
case is_object($value):
|
case is_object($value):
|
||||||
return Ulmus::convertObject($value);
|
return Ulmus::convertObject($value);
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ class MySQL implements AdapterInterface {
|
||||||
throw $ex;
|
throw $ex;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
$this->password = str_repeat('*', strlen($this->password));
|
$this->password = str_repeat('*', random_int(8,16));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $pdo;
|
return $pdo;
|
||||||
|
@ -148,9 +148,12 @@ class MySQL implements AdapterInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writableValue(/* mixed */ $value) /*: mixed*/
|
public function writableValue(mixed $value) : mixed
|
||||||
{
|
{
|
||||||
switch (true) {
|
switch (true) {
|
||||||
|
case $value instanceof \UnitEnum:
|
||||||
|
return Ulmus::convertEnum($value);
|
||||||
|
|
||||||
case is_object($value):
|
case is_object($value):
|
||||||
return Ulmus::convertObject($value);
|
return Ulmus::convertObject($value);
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ class SQLite implements AdapterInterface {
|
||||||
return substr($base, 0, strrpos($base, '.') ?: strlen($base));
|
return substr($base, 0, strrpos($base, '.') ?: strlen($base));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function schemaTable(string $databaseName, string $tableName) /* : ? object */
|
public function schemaTable(string $databaseName, string $tableName) : null|object
|
||||||
{
|
{
|
||||||
return Table::repository()->loadOneFromField(Table::field('tableName'), $tableName);
|
return Table::repository()->loadOneFromField(Table::field('tableName'), $tableName);
|
||||||
}
|
}
|
||||||
|
@ -131,9 +131,12 @@ class SQLite implements AdapterInterface {
|
||||||
return $typeOnly ? $type : $type . ( $length ? "($length" . ( isset($precision) ? ",$precision" : "" ) . ")" : "" );
|
return $typeOnly ? $type : $type . ( $length ? "($length" . ( isset($precision) ? ",$precision" : "" ) . ")" : "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writableValue(/* mixed */ $value) /*: mixed*/
|
public function writableValue(mixed $value) /*: mixed*/
|
||||||
{
|
{
|
||||||
switch (true) {
|
switch (true) {
|
||||||
|
case $value instanceof \UnitEnum:
|
||||||
|
return Ulmus::convertEnum($value);
|
||||||
|
|
||||||
case is_object($value):
|
case is_object($value):
|
||||||
return Ulmus::convertObject($value);
|
return Ulmus::convertObject($value);
|
||||||
|
|
||||||
|
@ -168,6 +171,8 @@ class SQLite implements AdapterInterface {
|
||||||
|
|
||||||
public function exportFunctions(PdoObject $pdo) : void
|
public function exportFunctions(PdoObject $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('lcase', fn($string) => strtolower($string), 1);
|
||||||
$pdo->sqliteCreateFunction('ucase', fn($string) => strtoupper($string), 1);
|
$pdo->sqliteCreateFunction('ucase', fn($string) => strtoupper($string), 1);
|
||||||
$pdo->sqliteCreateFunction('left', fn($string, $length) => substr($string, 0, $length), 2);
|
$pdo->sqliteCreateFunction('left', fn($string, $length) => substr($string, 0, $length), 2);
|
||||||
|
|
|
@ -38,7 +38,7 @@ class ConnectionAdapter
|
||||||
|
|
||||||
$this->adapter->setup($connection);
|
$this->adapter->setup($connection);
|
||||||
|
|
||||||
unset($this->configuration['connections'][$this->name]);
|
unset($this->configuration['connections']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getConfiguration() : array
|
public function getConfiguration() : array
|
||||||
|
@ -71,7 +71,7 @@ class ConnectionAdapter
|
||||||
{
|
{
|
||||||
return $this->pdo();
|
return $this->pdo();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instanciate an adapter which interact with the data source
|
* Instanciate an adapter which interact with the data source
|
||||||
* @param string $name An Ulmus adapter or full class name implementing AdapterInterface
|
* @param string $name An Ulmus adapter or full class name implementing AdapterInterface
|
||||||
|
|
|
@ -27,7 +27,16 @@ class ObjectInstanciator {
|
||||||
|
|
||||||
return (string) $obj;
|
return (string) $obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function enum(\UnitEnum $obj)
|
||||||
|
{
|
||||||
|
if (! $obj instanceof \BackedEnum) {
|
||||||
|
throw new \Ulmus\Exception\BackedEnumRequired("Unable to extract a UnitEnum value from this variable. You must define your enum as a BackedEnum instead of an UnitEnum.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $obj->value;
|
||||||
|
}
|
||||||
|
|
||||||
public function registerObject(string $type, Callable $callback) : void
|
public function registerObject(string $type, Callable $callback) : void
|
||||||
{
|
{
|
||||||
$this->objectCallbackDefinition[$type] = $callback;
|
$this->objectCallbackDefinition[$type] = $callback;
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Entity\Sqlite;
|
||||||
|
|
||||||
|
use Ulmus\EntityCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Table
|
||||||
|
*/
|
||||||
|
class Column
|
||||||
|
{
|
||||||
|
use \Ulmus\EntityTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
*/
|
||||||
|
public int $cid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Virtual
|
||||||
|
*/
|
||||||
|
public string $tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field('name' => "notnull")
|
||||||
|
*/
|
||||||
|
public bool $notNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field('name' => 'dflt_value')
|
||||||
|
*/
|
||||||
|
public ? string $defaultValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field('name' => "pk")
|
||||||
|
*/
|
||||||
|
public bool $primaryKey;
|
||||||
|
}
|
|
@ -2,13 +2,14 @@
|
||||||
|
|
||||||
namespace Ulmus\Entity\Sqlite;
|
namespace Ulmus\Entity\Sqlite;
|
||||||
|
|
||||||
|
use Ulmus\ConnectionAdapter;
|
||||||
use Ulmus\Repository;
|
use Ulmus\Repository;
|
||||||
|
|
||||||
class Table extends Schema
|
class Table extends Schema
|
||||||
{
|
{
|
||||||
public static function repository(string $alias = Repository::DEFAULT_ALIAS): Repository
|
public static function repository(string $alias = Repository::DEFAULT_ALIAS, ConnectionAdapter $adapter = null): Repository
|
||||||
{
|
{
|
||||||
return new class(static::class, $alias) extends Repository\SqliteRepository
|
return new class(static::class, $alias, $adapter) extends Repository\SqliteRepository
|
||||||
{
|
{
|
||||||
public function finalizeQuery(): void
|
public function finalizeQuery(): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -78,11 +78,19 @@ trait EntityTrait {
|
||||||
|
|
||||||
$this->{$field['name']} = $value;
|
$this->{$field['name']} = $value;
|
||||||
}
|
}
|
||||||
|
elseif ( $value instanceof \UnitEnum ) {
|
||||||
|
$this->{$field['name']} = $value;
|
||||||
|
}
|
||||||
|
elseif (enum_exists($field['type'])) {
|
||||||
|
$this->{$field['name']} = $field['type']::from($value);
|
||||||
|
}
|
||||||
elseif ( ! $field['builtin'] ) {
|
elseif ( ! $field['builtin'] ) {
|
||||||
try {
|
try {
|
||||||
$this->{$field['name']} = Ulmus::instanciateObject($field['type'], [ $value ]);
|
$this->{$field['name']} = Ulmus::instanciateObject($field['type'], [ $value ]);
|
||||||
}
|
}
|
||||||
catch(\Error $e) {
|
catch(\Error $e) {
|
||||||
|
$f = $field['type'];
|
||||||
|
dump($f, $f::from($value));
|
||||||
throw new \Error(sprintf("%s for class '%s' on field '%s'", $e->getMessage(), get_class($this), $field['name']));
|
throw new \Error(sprintf("%s for class '%s' on field '%s'", $e->getMessage(), get_class($this), $field['name']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +107,7 @@ trait EntityTrait {
|
||||||
$this->entityLoadedDataset = array_change_key_case($dataset, \CASE_LOWER) + $this->entityLoadedDataset;
|
$this->entityLoadedDataset = array_change_key_case($dataset, \CASE_LOWER) + $this->entityLoadedDataset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,9 +293,9 @@ trait EntityTrait {
|
||||||
/**
|
/**
|
||||||
* @Ignore
|
* @Ignore
|
||||||
*/
|
*/
|
||||||
public static function repository(string $alias = Repository::DEFAULT_ALIAS) : Repository
|
public static function repository(string $alias = Repository::DEFAULT_ALIAS, ConnectionAdapter $adapter = null) : Repository
|
||||||
{
|
{
|
||||||
return Ulmus::repository(static::class, $alias);
|
return Ulmus::repository(static::class, $alias, $adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -301,7 +309,6 @@ trait EntityTrait {
|
||||||
return $collection;
|
return $collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Ignore
|
* @Ignore
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Exception;
|
||||||
|
|
||||||
|
class BackedEnumRequired extends \RuntimeException {}
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Query;
|
||||||
|
|
||||||
|
class Show extends Fragment {
|
||||||
|
|
||||||
|
public int $order = -100;
|
||||||
|
|
||||||
|
const SQL_TOKEN = "SHOW";
|
||||||
|
|
||||||
|
const SQL_TOKEN_FROM = "FROM";
|
||||||
|
|
||||||
|
const SQL_SHOW_DATABASES = "DATABASES";
|
||||||
|
|
||||||
|
const SQL_SHOW_TABLES = "TABLES";
|
||||||
|
|
||||||
|
public string $show;
|
||||||
|
|
||||||
|
public string $from;
|
||||||
|
|
||||||
|
public string $in;
|
||||||
|
|
||||||
|
public function set(string $show, ? string $from = null, ? string $in = null) : self
|
||||||
|
{
|
||||||
|
$this->show = $show;
|
||||||
|
|
||||||
|
if ( $from !== null ) {
|
||||||
|
$this->from = $from;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $in !== null ) {
|
||||||
|
$this->in = $in;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() : string
|
||||||
|
{
|
||||||
|
return $this->renderSegments([
|
||||||
|
static::SQL_TOKEN, $this->show,
|
||||||
|
] + ( ! empty($this->from) ? [ static::SQL_TOKEN_FROM, $this->from ] : [] ) + ( ! empty($this->in) ? [ static::SQL_TOKEN_IN, $this->in ] : [] ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -314,6 +314,39 @@ class QueryBuilder implements Query\QueryBuilderInterface
|
||||||
return $join;
|
return $join;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function showDatabases() : self
|
||||||
|
{
|
||||||
|
$show = new Query\Show();
|
||||||
|
|
||||||
|
$this->push($show);
|
||||||
|
|
||||||
|
$show->set(Query\Show::SQL_SHOW_DATABASES);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showTables(? string $database = null) : self
|
||||||
|
{
|
||||||
|
$show = new Query\Show();
|
||||||
|
|
||||||
|
$this->push($show);
|
||||||
|
|
||||||
|
$show->set(Query\Show::SQL_SHOW_TABLES, $database);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showColumns(string $table) : self
|
||||||
|
{
|
||||||
|
$show = new Query\Show();
|
||||||
|
|
||||||
|
$this->push($show);
|
||||||
|
|
||||||
|
$show->set(Query\Show::SQL_SHOW_COLUMNS, $table);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function truncate(string $table, ? string $alias = null, ? string $database = null, ? string $schema = null) : self
|
public function truncate(string $table, ? string $alias = null, ? string $database = null, ? string $schema = null) : self
|
||||||
{
|
{
|
||||||
if ( $schema ) {
|
if ( $schema ) {
|
||||||
|
|
|
@ -21,4 +21,22 @@ class SqliteQueryBuilder extends QueryBuilder implements Query\QueryBuilderInter
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function showColumns(string $table) : self
|
||||||
|
{
|
||||||
|
$this->pragma('table_info', $table, true);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showTables(? string $database = null) : self
|
||||||
|
{
|
||||||
|
$show = new Query\Show();
|
||||||
|
|
||||||
|
$this->push($show);
|
||||||
|
|
||||||
|
$show->set(Query\Show::SQL_SHOW_TABLES, $database);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Repository
|
||||||
|
|
||||||
public function loadOne() : ? object
|
public function loadOne() : ? object
|
||||||
{
|
{
|
||||||
return $this->limit(1)->collectionFromQuery()[0] ?? null;
|
return $this->limit(1)->selectSqlQuery()->collectionFromQuery()[0] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadOneFromField($field, $value) : ? object
|
public function loadOneFromField($field, $value) : ? object
|
||||||
|
@ -53,7 +53,7 @@ class Repository
|
||||||
|
|
||||||
public function loadAll() : EntityCollection
|
public function loadAll() : EntityCollection
|
||||||
{
|
{
|
||||||
return $this->collectionFromQuery();
|
return $this->selectSqlQuery()->collectionFromQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadAllFromField($field, $value, $operator= Query\Where::OPERATOR_EQUAL) : EntityCollection
|
public function loadAllFromField($field, $value, $operator= Query\Where::OPERATOR_EQUAL) : EntityCollection
|
||||||
|
@ -63,7 +63,7 @@ class Repository
|
||||||
|
|
||||||
public function loadFromField($field, $value, $operator= Query\Where::OPERATOR_EQUAL) : EntityCollection
|
public function loadFromField($field, $value, $operator= Query\Where::OPERATOR_EQUAL) : EntityCollection
|
||||||
{
|
{
|
||||||
return $this->where($field, $value, $operator)->collectionFromQuery();
|
return $this->selectSqlQuery()->where($field, $value, $operator)->collectionFromQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function count() : int
|
public function count() : int
|
||||||
|
@ -278,7 +278,7 @@ class Repository
|
||||||
|
|
||||||
$this->finalizeQuery();
|
$this->finalizeQuery();
|
||||||
|
|
||||||
$result = Ulmus::runSelectQuery($this->queryBuilder, $this->adapter);
|
# ??? $result = Ulmus::runSelectQuery($this->queryBuilder, $this->adapter);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -288,12 +288,26 @@ class Repository
|
||||||
return $this->createSqlQuery()->runQuery();
|
return $this->createSqlQuery()->runQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function listTables(? string $database = null)
|
||||||
|
{
|
||||||
|
return $this->showTablesSqlQuery($database)->runQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function listColumns(? string $table = null)
|
||||||
|
{
|
||||||
|
$table ??= $this->entityResolver->tableName();
|
||||||
|
|
||||||
|
$this->showColumnsSqlQuery($table);
|
||||||
|
|
||||||
|
return $this->collectionFromQuery(Entity\InformationSchema\Column::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function generateDatasetDiff(object $entity, bool $oldValues = false) : array
|
public function generateDatasetDiff(object $entity, bool $oldValues = false) : array
|
||||||
{
|
{
|
||||||
$array = array_change_key_case($entity->toArray());
|
$array = array_change_key_case($entity->toArray());
|
||||||
|
|
||||||
$dataset = array_change_key_case($entity->entityGetDataset(false, true));
|
$dataset = array_change_key_case($entity->entityGetDataset(false, true));
|
||||||
|
# dump($array, $dataset);
|
||||||
return array_udiff_assoc($oldValues ? $dataset : $array , $oldValues ? $array : $dataset, function($e1, $e2) {
|
return array_udiff_assoc($oldValues ? $dataset : $array , $oldValues ? $array : $dataset, function($e1, $e2) {
|
||||||
if ( is_array($e1) ) {
|
if ( is_array($e1) ) {
|
||||||
if (is_array($e2)) {
|
if (is_array($e2)) {
|
||||||
|
@ -584,7 +598,9 @@ class Repository
|
||||||
if ( null === $entity::resolveEntity()->searchFieldAnnotation($field['name'], new RelationIgnore) ) {
|
if ( null === $entity::resolveEntity()->searchFieldAnnotation($field['name'], new RelationIgnore) ) {
|
||||||
$escAlias = $this->escapeIdentifier($alias);
|
$escAlias = $this->escapeIdentifier($alias);
|
||||||
|
|
||||||
$this->select("$escAlias.$key as $alias\${$field['name']}");
|
$name = $entity::resolveEntity()->searchFieldAnnotation($field['name'], new Field())->name ?? $field['name'];
|
||||||
|
|
||||||
|
$this->select("$escAlias.$key as $alias\${$name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,14 +801,12 @@ class Repository
|
||||||
|
|
||||||
public function collectionFromQuery(? string $entityClass = null) : EntityCollection
|
public function collectionFromQuery(? string $entityClass = null) : EntityCollection
|
||||||
{
|
{
|
||||||
$class = $entityClass ?: $this->entityClass;
|
$class = $entityClass ?? $this->entityClass;
|
||||||
|
|
||||||
$entityCollection = $this->instanciateEntityCollection();
|
$entityCollection = $class::entityCollection();
|
||||||
|
|
||||||
$this->selectSqlQuery();
|
|
||||||
|
|
||||||
$this->finalizeQuery();
|
$this->finalizeQuery();
|
||||||
|
|
||||||
foreach(Ulmus::iterateQueryBuilder($this->queryBuilder, $this->adapter) as $entityData) {
|
foreach(Ulmus::iterateQueryBuilder($this->queryBuilder, $this->adapter) as $entityData) {
|
||||||
$entityCollection->append( ( new $class() )->resetVirtualProperties()->entityFillFromDataset($entityData) );
|
$entityCollection->append( ( new $class() )->resetVirtualProperties()->entityFillFromDataset($entityData) );
|
||||||
}
|
}
|
||||||
|
@ -916,6 +930,33 @@ class Repository
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function showDatabasesSqlQuery() : self
|
||||||
|
{
|
||||||
|
if ( null === $this->queryBuilder->getFragment(Query\Show::class) ) {
|
||||||
|
$this->queryBuilder->showDatabases();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showTablesSqlQuery() : self
|
||||||
|
{
|
||||||
|
if ( null === $this->queryBuilder->getFragment(Query\Show::class) ) {
|
||||||
|
$this->queryBuilder->showTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showColumnsSqlQuery(string $table) : self
|
||||||
|
{
|
||||||
|
if ( null === $this->queryBuilder->getFragment(Query\Show::class) ) {
|
||||||
|
$this->queryBuilder->showColumns($table);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
protected function fromRow($row) : self
|
protected function fromRow($row) : self
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Ulmus\Repository;
|
namespace Ulmus\Repository;
|
||||||
|
|
||||||
use Ulmus\{ConnectionAdapter, QueryBuilder, Repository, Query, Ulmus};
|
use Ulmus\{ConnectionAdapter, QueryBuilder, Repository, Query, Ulmus, Entity};
|
||||||
|
|
||||||
class SqliteRepository extends Repository {
|
class SqliteRepository extends Repository {
|
||||||
|
|
||||||
|
@ -18,6 +18,15 @@ class SqliteRepository extends Repository {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function listColumns(? string $table = null)
|
||||||
|
{
|
||||||
|
$table ??= $this->entityResolver->tableName();
|
||||||
|
$this->showColumnsSqlQuery($table);
|
||||||
|
|
||||||
|
return $this->collectionFromQuery(Entity\Sqlite\Column::class)->iterate(fn($e) => $e->tableName = $table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function serverRequestCountRepository() : Repository
|
protected function serverRequestCountRepository() : Repository
|
||||||
{
|
{
|
||||||
return new static($this->entityClass, $this->alias, $this->adapter);
|
return new static($this->entityClass, $this->alias, $this->adapter);
|
||||||
|
|
|
@ -107,11 +107,12 @@ abstract class Ulmus
|
||||||
return static::$resolved[$entityClass] ?? static::$resolved[$entityClass] = new Common\EntityResolver($entityClass);
|
return static::$resolved[$entityClass] ?? static::$resolved[$entityClass] = new Common\EntityResolver($entityClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function repository(string $entityClass, ...$arguments) : Repository
|
public static function repository(string $entityClass, string $alias = Repository::DEFAULT_ALIAS, ConnectionAdapter $adapter = null) : Repository
|
||||||
{
|
{
|
||||||
$cls = $entityClass::resolveEntity()->sqlAdapter()->adapter()->repositoryClass();
|
$adapter ??= $entityClass::resolveEntity()->sqlAdapter();
|
||||||
|
$cls = $adapter->adapter()->repositoryClass();
|
||||||
|
|
||||||
return new $cls($entityClass, ...$arguments);
|
return new $cls($entityClass, $alias, $adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function queryBuilder($entityClass, ...$arguments) : Query\QueryBuilderInterface
|
public static function queryBuilder($entityClass, ...$arguments) : Query\QueryBuilderInterface
|
||||||
|
@ -130,12 +131,17 @@ abstract class Ulmus
|
||||||
{
|
{
|
||||||
return ( static::$objectInstanciator ?? static::$objectInstanciator = new Entity\ObjectInstanciator() )->convert($obj);
|
return ( static::$objectInstanciator ?? static::$objectInstanciator = new Entity\ObjectInstanciator() )->convert($obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function convertEnum(\UnitEnum $enum)
|
||||||
|
{
|
||||||
|
return ( static::$objectInstanciator ?? static::$objectInstanciator = new Entity\ObjectInstanciator() )->enum($enum);
|
||||||
|
}
|
||||||
|
|
||||||
public static function encodeArray(array $array)
|
public static function encodeArray(array $array)
|
||||||
{
|
{
|
||||||
return json_encode($array);
|
return json_encode($array);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function registerAdapter(ConnectionAdapter $adapter, bool $default = false) : void
|
public static function registerAdapter(ConnectionAdapter $adapter, bool $default = false) : void
|
||||||
{
|
{
|
||||||
if ($default) {
|
if ($default) {
|
||||||
|
|
Loading…
Reference in New Issue