Compare commits

...

2 Commits

4 changed files with 78 additions and 55 deletions

View File

@ -9,6 +9,8 @@ class PdoObject extends PDO {
public static ? string $dump = null; public static ? string $dump = null;
public bool $executionStatus;
public function select(string $sql, array $parameters = []): PDOStatement public function select(string $sql, array $parameters = []): PDOStatement
{ {
static::$dump && call_user_func_array(static::$dump, [ $sql, $parameters ]); static::$dump && call_user_func_array(static::$dump, [ $sql, $parameters ]);
@ -29,7 +31,7 @@ class PdoObject extends PDO {
public function runQuery(string $sql, array $parameters = []): ? PDOStatement public function runQuery(string $sql, array $parameters = []): ? PDOStatement
{ {
static::$dump && call_user_func_array(static::$dump, [ $sql, $parameters ]); static::$dump && call_user_func_array(static::$dump, [ $sql, $parameters ]);
# \debogueur([ $sql, $parameters ]);
try { try {
if (false !== ( $statement = $this->prepare($sql) )) { if (false !== ( $statement = $this->prepare($sql) )) {
return $this->execute($statement, $parameters, true); return $this->execute($statement, $parameters, true);
@ -59,12 +61,16 @@ class PdoObject extends PDO {
public function execute(PDOStatement $statement, array $parameters = [], bool $commit = true): ? PDOStatement public function execute(PDOStatement $statement, array $parameters = [], bool $commit = true): ? PDOStatement
{ {
$this->executionStatus = false;
try { try {
if ( ! $this->inTransaction() ) { if ( ! $this->inTransaction() ) {
$this->beginTransaction(); $this->beginTransaction();
} }
if (empty($parameters) ? $statement->execute() : $statement->execute($parameters)) { $this->executionStatus = empty($parameters) ? $statement->execute() : $statement->execute($parameters);
if ( $this->executionStatus ) {
$statement->lastInsertId = $this->lastInsertId(); $statement->lastInsertId = $this->lastInsertId();
if ( $commit ) { if ( $commit ) {
@ -79,7 +85,7 @@ class PdoObject extends PDO {
} }
catch (\PDOException $e) { catch (\PDOException $e) {
$this->rollback(); $this->rollback();
throw $e; throw $e;
} }
catch (\Throwable $e) { catch (\Throwable $e) {

View File

@ -8,28 +8,28 @@ use Ulmus\Repository,
Ulmus\Common\EntityField; Ulmus\Common\EntityField;
use Ulmus\Annotation\Classes\{ Method, Table, Collation, }; use Ulmus\Annotation\Classes\{ Method, Table, Collation, };
use Ulmus\Annotation\Property\{ Field, Filter, Relation, OrderBy, Where, Join, Virtual, On, WithJoin, }; use Ulmus\Annotation\Property\{ Field, Filter, FilterJoin, Relation, OrderBy, Where, OrWhere, Join, Virtual, On, WithJoin, };
use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, Datetime as DateTime, Date, Time, Bigint, Tinyint, Text, Mediumtext, Longtext, }; use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, Datetime as DateTime, Date, Time, Bigint, Tinyint, Text, Mediumtext, Longtext, };
use Ulmus\Annotation\Property\Relation\{ Ignore as RelationIgnore }; use Ulmus\Annotation\Property\Relation\{ Ignore as RelationIgnore };
trait EntityTrait { trait EntityTrait {
use EventTrait; use EventTrait;
/** /**
* @Ignore * @Ignore
*/ */
protected bool $entityStrictFieldsDeclaration = false; protected bool $entityStrictFieldsDeclaration = false;
/** /**
* @Ignore * @Ignore
*/ */
protected array $entityDatasetUnmatchedFields = []; protected array $entityDatasetUnmatchedFields = [];
/** /**
* @Ignore * @Ignore
*/ */
public array $entityLoadedDataset = []; public array $entityLoadedDataset = [];
/**entityLoadedDataset /**entityLoadedDataset
* @Ignore * @Ignore
*/ */
@ -117,7 +117,7 @@ trait EntityTrait {
return $this; return $this;
} }
/** /**
* @Ignore * @Ignore
*/ */
@ -125,7 +125,7 @@ trait EntityTrait {
{ {
return $this->entityFillFromDataset($dataset); return $this->entityFillFromDataset($dataset);
} }
/** /**
* @Ignore * @Ignore
*/ */
@ -134,53 +134,53 @@ trait EntityTrait {
if ( $returnSource ) { if ( $returnSource ) {
return $this->entityLoadedDataset; return $this->entityLoadedDataset;
} }
$dataset = []; $dataset = [];
$entityResolver = $this->resolveEntity(); $entityResolver = $this->resolveEntity();
foreach($entityResolver->fieldList(Common\EntityResolver::KEY_ENTITY_NAME, true) as $key => $field) { foreach($entityResolver->fieldList(Common\EntityResolver::KEY_ENTITY_NAME, true) as $key => $field) {
$annotation = $entityResolver->searchFieldAnnotation($key, new Field() ); $annotation = $entityResolver->searchFieldAnnotation($key, new Field() );
if ( isset($this->$key) ) { if ( isset($this->$key) ) {
$realKey = $annotation->name ?? $key; $realKey = $annotation->name ?? $key;
switch (true) { switch (true) {
case is_object($this->$key): case is_object($this->$key):
$dataset[$realKey] = Ulmus::convertObject($this->$key); $dataset[$realKey] = Ulmus::convertObject($this->$key);
break; break;
case is_array($this->$key): case is_array($this->$key):
$dataset[$realKey] = Ulmus::encodeArray($this->$key); $dataset[$realKey] = Ulmus::encodeArray($this->$key);
break; break;
case is_bool($this->$key): case is_bool($this->$key):
$dataset[$realKey] = (int) $this->$key; $dataset[$realKey] = (int) $this->$key;
break; break;
default: default:
$dataset[$realKey] = $this->$key; $dataset[$realKey] = $this->$key;
} }
} }
elseif ( $field['nullable'] ) { elseif ( $field['nullable'] ) {
$dataset[ $annotation->name ?? $key ] = null; $dataset[ $annotation->name ?? $key ] = null;
} }
} }
# @TODO Must fix recursive bug ! # @TODO Must fix recursive bug !
if ($includeRelations) { if ($includeRelations) {
foreach($entityResolver->properties as $name => $field){ foreach($entityResolver->properties as $name => $field){
$relation = $entityResolver->searchFieldAnnotation($name, new Relation() ); $relation = $entityResolver->searchFieldAnnotation($name, new Relation() );
if ( $relation && isset($this->$name) && ($relation->entity ?? $relation->bridge) !== static::class ) { if ( $relation && isset($this->$name) && ($relation->entity ?? $relation->bridge) !== static::class ) {
if ( null !== $value = $this->$name ?? null ) { if ( null !== $value = $this->$name ?? null ) {
if ( is_iterable($value) ) { if ( is_iterable($value) ) {
$list = []; $list = [];
foreach($value as $entity) { foreach($value as $entity) {
$list[] = $entity->entityGetDataset(false); $list[] = $entity->entityGetDataset(false);
} }
$dataset[$name] = $list; $dataset[$name] = $list;
} }
elseif ( is_object($value) ) { elseif ( is_object($value) ) {
@ -189,11 +189,11 @@ trait EntityTrait {
} }
} }
} }
} }
return $dataset; return $dataset;
} }
/** /**
* @Ignore * @Ignore
*/ */
@ -201,7 +201,7 @@ trait EntityTrait {
{ {
return $this->entityGetDataset($includeRelations); return $this->entityGetDataset($includeRelations);
} }
/** /**
* @Ignore * @Ignore
*/ */
@ -209,7 +209,7 @@ trait EntityTrait {
{ {
return static::entityCollection([ $this ]); return static::entityCollection([ $this ]);
} }
/** /**
* @Ignore * @Ignore
*/ */
@ -218,9 +218,9 @@ trait EntityTrait {
if ( null === $pkField = $this->resolveEntity()->getPrimaryKeyField($this) ) { if ( null === $pkField = $this->resolveEntity()->getPrimaryKeyField($this) ) {
throw new Exception\EntityPrimaryKeyUnknown(sprintf("Entity %s has no field containing attributes 'primary_key'", static::class)); throw new Exception\EntityPrimaryKeyUnknown(sprintf("Entity %s has no field containing attributes 'primary_key'", static::class));
} }
$key = key($pkField); $key = key($pkField);
return isset($this->$key); return isset($this->$key);
} }
@ -282,9 +282,9 @@ trait EntityTrait {
*/ */
public function jsonSerialize() public function jsonSerialize()
{ {
return $this->entityGetDataset(); return $this->entityGetDataset();
} }
/** /**
* @Ignore * @Ignore
*/ */

View File

@ -2,7 +2,7 @@
namespace Ulmus; namespace Ulmus;
use Ulmus\Annotation\Property\{Field, Where, Having, Relation, Join, WithJoin, Relation\Ignore as RelationIgnore}; use Ulmus\Annotation\Property\{Field, Where, Having, Relation, Filter, Join, FilterJoin, WithJoin, Relation\Ignore as RelationIgnore};
use Ulmus\Common\EntityResolver; use Ulmus\Common\EntityResolver;
class Repository class Repository
@ -56,19 +56,19 @@ class Repository
return $this->collectionFromQuery(); return $this->collectionFromQuery();
} }
public function loadAllFromField($field, $value) : EntityCollection public function loadAllFromField($field, $value, $operator= Query\Where::OPERATOR_EQUAL) : EntityCollection
{ {
return $this->loadFromField($field, $value); return $this->loadFromField($field, $value, $operator);
} }
public function loadFromField($field, $value) : EntityCollection public function loadFromField($field, $value, $operator= Query\Where::OPERATOR_EQUAL) : EntityCollection
{ {
return $this->where($field, $value)->collectionFromQuery(); return $this->where($field, $value, $operator)->collectionFromQuery();
} }
public function count() : int public function count() : int
{ {
$this->removeQueryFragment($this->queryBuilder->getFragment(Query\Select::class)); $this->removeQueryFragment(Query\Select::class);
if ( $this->queryBuilder->getFragment(Query\GroupBy::class) ) { if ( $this->queryBuilder->getFragment(Query\GroupBy::class) ) {
$this->select( "DISTINCT COUNT(*) OVER ()" ); $this->select( "DISTINCT COUNT(*) OVER ()" );
@ -84,12 +84,12 @@ class Repository
return Ulmus::runSelectQuery($this->queryBuilder, $this->adapter)->fetchColumn(0); return Ulmus::runSelectQuery($this->queryBuilder, $this->adapter)->fetchColumn(0);
} }
protected function deleteOne() public function deleteOne()
{ {
return $this->limit(1)->deleteSqlQuery()->runDeleteQuery(); return $this->limit(1)->deleteSqlQuery()->runDeleteQuery();
} }
protected function deleteAll() public function deleteAll()
{ {
return $this->deleteSqlQuery()->runDeleteQuery(); return $this->deleteSqlQuery()->runDeleteQuery();
} }
@ -145,6 +145,8 @@ class Repository
$primaryKeyDefinition = Ulmus::resolveEntity($this->entityClass)->getPrimaryKeyField(); $primaryKeyDefinition = Ulmus::resolveEntity($this->entityClass)->getPrimaryKeyField();
if ( ! $entity->isLoaded() ) { if ( ! $entity->isLoaded() ) {
# $dataset = array_filter($dataset, fn($item, $field) => ! ($this->entityResolver->searchFieldAnnotation($field, new Field, false)->readonly ?? false), \ARRAY_FILTER_USE_BOTH);
$statement = $this->insertSqlQuery($fieldsAndValue ?? $dataset, $replace)->runInsertQuery(); $statement = $this->insertSqlQuery($fieldsAndValue ?? $dataset, $replace)->runInsertQuery();
if ( ( 0 !== $statement->lastInsertId ) && if ( ( 0 !== $statement->lastInsertId ) &&
@ -155,6 +157,8 @@ class Repository
} }
$entity->entityFillFromDataset($dataset, true); $entity->entityFillFromDataset($dataset, true);
return (bool) $statement->lastInsertId;
} }
else { else {
if ( $primaryKeyDefinition === null ) { if ( $primaryKeyDefinition === null ) {
@ -179,16 +183,21 @@ class Repository
return false; return false;
} }
public function saveAll(/*EntityCollection|array*/ $collection) : void public function saveAll(EntityCollection $collection) : int
{ {
foreach($collection as $entity) { $changed = 0;
$this->save($entity);
foreach ($collection as $entity) {
$this->save($entity) && $changed++;
} }
return $changed;
} }
public function loadCollectionRelation(EntityCollection $collection, /*array|string*/ $fields) : void public function loadCollectionRelation(EntityCollection $collection, /*array|string*/ $fields) : void
{ {
foreach((array) $fields as $name) { foreach ((array)$fields as $name) {
if (null !== ($relation = $this->entityResolver->searchFieldAnnotation($name, new Annotation\Property\Relation()))) { if (null !== ($relation = $this->entityResolver->searchFieldAnnotation($name, new Annotation\Property\Relation()))) {
$relationType = strtolower(str_replace(['-', '_', ' '], '', $relation->type)); $relationType = strtolower(str_replace(['-', '_', ' '], '', $relation->type));
@ -312,7 +321,7 @@ class Repository
} }
} }
public function removeQueryFragment(? Query\Fragment $fragment) : self public function removeQueryFragment(/*? Query\Fragment|string*/ $fragment) : self
{ {
$fragment && $this->queryBuilder->removeFragment($fragment); $fragment && $this->queryBuilder->removeFragment($fragment);
@ -568,13 +577,10 @@ class Repository
$this->having(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->value, $condition->operator); $this->having(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->value, $condition->operator);
} }
<<<<<<< HEAD
=======
foreach($this->entityResolver->searchFieldAnnotationList($item, new Filter() ) as $filter) { foreach($this->entityResolver->searchFieldAnnotationList($item, new Filter() ) as $filter) {
call_user_func_array([ $this->entityClass, $filter->method ], [ $this, $item, true ]); call_user_func_array([ $this->entityClass, $filter->method ], [ $this, $item, true ]);
} }
>>>>>>> dc5e0885512a39387b59e8a2af37c87ff0269931
$this->close(); $this->close();
$key = is_string($annotation->key) ? $this->entityClass::field($annotation->key) : $annotation->key; $key = is_string($annotation->key) ? $this->entityClass::field($annotation->key) : $annotation->key;
@ -596,13 +602,10 @@ class Repository
$join->where(is_object($field) ? $field : $entity::field($field, $alias), $condition->value, $condition->operator); $join->where(is_object($field) ? $field : $entity::field($field, $alias), $condition->value, $condition->operator);
} }
} }
<<<<<<< HEAD
=======
foreach($this->entityResolver->searchFieldAnnotationList($item, new FilterJoin() ) as $filter) { foreach($this->entityResolver->searchFieldAnnotationList($item, new FilterJoin() ) as $filter) {
call_user_func_array([ $this->entityClass, $filter->method ], [ $join, $item, true ]); call_user_func_array([ $this->entityClass, $filter->method ], [ $join, $item, true ]);
} }
>>>>>>> dc5e0885512a39387b59e8a2af37c87ff0269931
}); });
} }
else { else {
@ -816,7 +819,7 @@ class Repository
public function createSqlQuery() : self public function createSqlQuery() : self
{ {
if ( null === $this->queryBuilder->getFragment(Query\Create::class) ) { if ( null === $this->queryBuilder->getFragment(Query\Create::class) ) {
$this->queryBuilder->create($this->escapeFieldList($this->entityResolver->fieldList()), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName()); $this->queryBuilder->create($this->escapeFieldList($this->entityResolver->fieldList(EntityResolver::KEY_ENTITY_NAME, true)), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName());
} }
if ( null === $this->queryBuilder->getFragment(Query\Engine::class) ) { if ( null === $this->queryBuilder->getFragment(Query\Engine::class) ) {
@ -828,6 +831,16 @@ class Repository
return $this; return $this;
} }
public function alterSqlQuery(array $fields) : self
{
if ( null === $this->queryBuilder->getFragment(Query\Alter::class) ) {
$this->queryBuilder->create($this->escapeFieldList($this->entityResolver->fieldList(EntityResolver::KEY_ENTITY_NAME, true)), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName());
}
return $this;
}
protected function fromRow($row) : self protected function fromRow($row) : self
{ {

View File

@ -9,6 +9,10 @@ use Closure;
class RelationBuilder class RelationBuilder
{ {
const SUBQUERY_FIELD_SUFFIX = "%s\$collection";
const JOIN_FIELD_SEPARATOR = "%s\$";
protected Repository $repository; protected Repository $repository;
protected /*object|string*/ $entity; protected /*object|string*/ $entity;