- Added a LoadRelation for the repository.
- Added a new @Filter() annotation to the relation; adding it to JOIN is also coming. - Some bugfixes done within the Where and ConditionTrait.
This commit is contained in:
		
							parent
							
								
									9e84bd3536
								
							
						
					
					
						commit
						7dd64abf29
					
				
							
								
								
									
										15
									
								
								src/Annotation/Property/Filter.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/Annotation/Property/Filter.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Ulmus\Annotation\Property; | ||||
| 
 | ||||
| class Filter implements \Ulmus\Annotation\Annotation { | ||||
| 
 | ||||
|     public string $method; | ||||
| 
 | ||||
|     public function __construct(string $method = null) | ||||
|     {         | ||||
|         if ( $method !== null ) { | ||||
|             $this->method = $method; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -12,7 +12,9 @@ class Where implements \Ulmus\Annotation\Annotation { | ||||
|      | ||||
|     public string $operator; | ||||
|      | ||||
|     public function __construct(? string $field = null, $value = null, ? string $operator = null) | ||||
|     public string $condition; | ||||
|      | ||||
|     public function __construct(? string $field = null, $value = null, ? string $operator = null, ? string $condition = null) | ||||
|     { | ||||
|         if ( $field !== null ) { | ||||
|             $this->field = $field; | ||||
| @ -22,11 +24,7 @@ class Where implements \Ulmus\Annotation\Annotation { | ||||
|             $this->value = $value; | ||||
|         } | ||||
|          | ||||
|         if ( $operator !== null ) { | ||||
|             $this->operator = $operator; | ||||
|         } | ||||
|         else { | ||||
|             $this->operator = Query\Where::OPERATOR_EQUAL; | ||||
|         } | ||||
|         $this->operator = $operator !== null ? $operator : Query\Where::OPERATOR_EQUAL;  | ||||
|         $this->condition = $condition !== null ? $condition : Query\Where::CONDITION_AND;  | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -26,11 +26,11 @@ class EntityCollection extends \ArrayObject { | ||||
|         } | ||||
|     } | ||||
|          | ||||
|     public function filtersCollection(Callable $callback, bool $yieldValueOnly = false, bool $replaceCollection = false) : self | ||||
|     public function filtersCollection(Callable $callback, bool $replaceCollection = false) : self | ||||
|     { | ||||
|         $collection = new static(); | ||||
|          | ||||
|         foreach($this->filters($callback, $yieldValueOnly) as $item) { | ||||
|         foreach($this->filters($callback, true) as $item) { | ||||
|             $collection->append($item); | ||||
|         } | ||||
|          | ||||
| @ -78,6 +78,13 @@ class EntityCollection extends \ArrayObject { | ||||
|         return $removed; | ||||
|     } | ||||
|      | ||||
|     public function clear() : self | ||||
|     { | ||||
|         $this->exchangeArray([]); | ||||
|          | ||||
|         return $this; | ||||
|     } | ||||
|      | ||||
|     public function search($value, string $field, bool $strict = true) : Generator  | ||||
|     { | ||||
|         foreach($this->filters(fn($v) => $strict ? $v->$field === $value : $v->$field == $value) as $key => $item) { | ||||
| @ -106,6 +113,11 @@ class EntityCollection extends \ArrayObject { | ||||
|         return $obj; | ||||
|     } | ||||
|      | ||||
|     public function searchInstances(string $className) : self | ||||
|     { | ||||
|         return $this->filtersCollection(fn($obj) => is_a($obj, $className)); | ||||
|     } | ||||
|      | ||||
|     public function column($field, bool $unique = false) : array | ||||
|     { | ||||
|         $list = []; | ||||
| @ -118,8 +130,8 @@ class EntityCollection extends \ArrayObject { | ||||
|                 $value = $item->$field; | ||||
|             } | ||||
|              | ||||
|             if ($unique && in_array($value, $list)) { | ||||
|                 break; | ||||
|             if ($unique && in_array($value, $list, true)) { | ||||
|                 continue; | ||||
|             } | ||||
|              | ||||
|             $list[] = $value; | ||||
| @ -250,13 +262,20 @@ class EntityCollection extends \ArrayObject { | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     public function mergeWith( /*array|EntityCollection*/ $datasets ) : self | ||||
|     public function mergeWith(... $datasets) : self | ||||
|     { | ||||
|         if ( is_object($datasets) ) { | ||||
|             $datasets = $datasets->getArrayCopy(); | ||||
|         $list = []; | ||||
|          | ||||
|         foreach($datasets as $dataset) { | ||||
|             if ( is_object($dataset) ) { | ||||
|                 $list = array_merge($dataset->getArrayCopy(), $list); | ||||
|             } | ||||
|             else { | ||||
|                 $list = array_merge($dataset, $list); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         $this->exchangeArray( array_merge( $this->getArrayCopy(), $datasets ) ); | ||||
|         $this->exchangeArray( array_merge( $this->getArrayCopy(), $list ) ); | ||||
|          | ||||
|         return $this; | ||||
|     } | ||||
| @ -287,4 +306,16 @@ class EntityCollection extends \ArrayObject { | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function rsort(callable $callback, $function = "uasort") : self | ||||
|     { | ||||
|         $this->sort(...func_get_args()); | ||||
| 
 | ||||
|         return $this->reverse(); | ||||
|     } | ||||
| 
 | ||||
|     public function reverse() : self | ||||
|     { | ||||
|         return $this->replaceWith(array_reverse($this->getArrayCopy()));; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -8,7 +8,7 @@ use Ulmus\Repository, | ||||
|     Ulmus\Common\EntityField; | ||||
| 
 | ||||
| use Ulmus\Annotation\Classes\{ Method, Table, Collation, }; | ||||
| use Ulmus\Annotation\Property\{ Field, Relation, OrderBy, Where, Join, Virtual }; | ||||
| use Ulmus\Annotation\Property\{ Field, Filter, Relation, OrderBy, Where, Join, Virtual }; | ||||
| use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, }; | ||||
| 
 | ||||
| trait EntityTrait { | ||||
| @ -63,14 +63,15 @@ trait EntityTrait { | ||||
| 
 | ||||
|                 $order = $entityResolver->searchFieldAnnotationList($name, new OrderBy() ); | ||||
|                 $where = $entityResolver->searchFieldAnnotationList($name, new Where() ); | ||||
| 
 | ||||
|                 $filters = $entityResolver->searchFieldAnnotationList($name, new Filter() ); | ||||
|                  | ||||
|                 if ( $relation->entity ?? false ) { | ||||
|                     $baseEntity = $relation->entity(); | ||||
| 
 | ||||
|                     $repository = $baseEntity->repository(); | ||||
| 
 | ||||
|                     foreach($where as $condition) { | ||||
|                         $repository->where($condition->field, is_callable($condition->value) ? $f = call_user_func_array($condition->value, [ $this ]) : $condition->value, $condition->operator); | ||||
|                         $repository->where($condition->field, is_callable($condition->value) ? call_user_func_array($condition->value, [ $this ]) : $condition->value, $condition->operator, $condition->condition); | ||||
|                     } | ||||
| 
 | ||||
|                     foreach($order as $item) { | ||||
| @ -79,6 +80,14 @@ trait EntityTrait { | ||||
| 
 | ||||
|                     $field = $relation->key; | ||||
|                 } | ||||
|                                  | ||||
|                 $applyFilter = function($repository) use ($filters, $name) { | ||||
|                     foreach($filters as $filter) { | ||||
|                         $repository = call_user_func_array([ $this, $filter->method ], [ $repository, $name ]); | ||||
|                     } | ||||
|                      | ||||
|                     return $repository; | ||||
|                 }; | ||||
| 
 | ||||
|                 switch( $relationType ) { | ||||
|                     case 'onetoone':        | ||||
| @ -100,9 +109,10 @@ trait EntityTrait { | ||||
|                         if ($relation->foreignKey) { | ||||
|                             $repository->where( is_object($relation->foreignKey) ? $relation->foreignKey : $baseEntity->field($relation->foreignKey), is_callable($field) ? $field($this) : $this->$field ); | ||||
|                         } | ||||
|                          | ||||
|                         $this->eventExecute(Event\EntityRelationLoadInterface::class, $name, $repository); | ||||
| 
 | ||||
|                         return $this->$name = call_user_func([$repository, $relation->function]); | ||||
|                         return $this->$name = call_user_func([$applyFilter($repository), $relation->function]); | ||||
| 
 | ||||
|                     case 'manytomany': | ||||
|                         if ( false === $relation->bridge ?? false ) { | ||||
| @ -138,7 +148,7 @@ trait EntityTrait { | ||||
| 
 | ||||
|                         $this->eventExecute(Event\EntityRelationLoadInterface::class, $name, $repository); | ||||
|                          | ||||
|                         $this->$name = call_user_func([ $repository, $relationRelation->function ]); | ||||
|                         $this->$name = call_user_func([ $applyFilter($repository), $relationRelation->function ]); | ||||
| 
 | ||||
|                         if ($relation->bridgeField ?? false) { | ||||
|                             $repository = $relationRelation->entity::repository(); | ||||
|  | ||||
| @ -176,6 +176,64 @@ class Repository | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function loadCollectionRelation(EntityCollection $collection, /*array|string*/ $fields) : void | ||||
|     { | ||||
|         foreach((array) $fields as $name) { | ||||
|             if ( null !== ( $relation = $this->entityResolver->searchFieldAnnotation($name, new Annotation\Property\Relation() ) ) ) { | ||||
|                 $relationType = strtolower(str_replace(['-', '_', ' '], '', $relation->type)); | ||||
| 
 | ||||
|                 $order = $this->entityResolver->searchFieldAnnotationList($name, new Annotation\Property\OrderBy() ); | ||||
|                 $where = $this->entityResolver->searchFieldAnnotationList($name, new Annotation\Property\Where() ); | ||||
| 
 | ||||
|                 $baseEntity = $relation->entity ?? $relation->bridge ?? $this->entityResolver->properties[$name]['type']; | ||||
|                 $baseEntityResolver = $baseEntity::resolveEntity(); | ||||
| 
 | ||||
|                 $property = ( $baseEntityResolver->field($relation->foreignKey, 01, false) ?: $baseEntityResolver->field($relation->foreignKey, 02) )['name']; | ||||
|                 $entityProperty = ( $this->entityResolver->field($relation->key, 01, false) ?: $this->entityResolver->field($relation->key, 02) )['name']; | ||||
| 
 | ||||
|                 $repository = $baseEntity::repository(); | ||||
| 
 | ||||
|                 foreach($where as $condition) { | ||||
|                     $repository->where($condition->field, is_callable($condition->value) ? call_user_func_array($condition->value, [ $this ]) : $condition->value, $condition->operator, $condition->condition); | ||||
|                 } | ||||
| 
 | ||||
|                 foreach($order as $item) { | ||||
|                     $repository->orderBy($item->field, $item->order); | ||||
|                 } | ||||
| 
 | ||||
|                 $field = $relation->key; | ||||
| 
 | ||||
|                 $values = []; | ||||
| 
 | ||||
|                 $key = is_object($relation->foreignKey) ? $relation->foreignKey : $baseEntity::field($relation->foreignKey); | ||||
| 
 | ||||
|                 foreach($collection as $item) { | ||||
|                     $values[] = is_callable($field) ? $field($item) : $item->$entityProperty; | ||||
|                 } | ||||
| 
 | ||||
|                 $repository->where($key, $values); | ||||
| 
 | ||||
|                 switch( $relationType ) { | ||||
|                     case 'onetoone': | ||||
|                         $results = call_user_func([ $repository, "loadOne" ]); | ||||
|                         $item->$name = $results ?: new $baseEntity(); | ||||
|                          | ||||
|                         break; | ||||
|                          | ||||
|                     case 'onetomany': | ||||
|                         $results = call_user_func([ $repository, $relation->function ]); | ||||
|                          | ||||
|                         foreach($collection as $item) { | ||||
|                             $item->$name = $baseEntity::entityCollection(); | ||||
|                             $item->$name->mergeWith( $results->filtersCollection(fn($e) => $e->$property === $item->$entityProperty ) ); | ||||
|                         } | ||||
|                          | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     public function truncate(? string $table = null, ? string $alias = null, ? string $schema = null) : self | ||||
|     { | ||||
|         $schema = $schema ?: $this->entityResolver->schemaName(); | ||||
|  | ||||
| @ -25,9 +25,9 @@ trait ConditionTrait | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function where($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self | ||||
|     public function where($field, $value, string $operator = Query\Where::OPERATOR_EQUAL, $condition = Query\Where::CONDITION_AND) : self | ||||
|     { | ||||
|         $this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_AND); | ||||
|         $this->queryBuilder->where($field, $value, $operator, $condition); | ||||
|          | ||||
|         return $this; | ||||
|     } | ||||
| @ -67,9 +67,9 @@ trait ConditionTrait | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function having($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self | ||||
|     public function having($field, $value, string $operator = Query\Where::OPERATOR_EQUAL, $condition = Query\Where::CONDITION_AND) : self | ||||
|     { | ||||
|         $this->queryBuilder->having($field, $value, $operator, Query\Where::CONDITION_AND); | ||||
|         $this->queryBuilder->having($field, $value, $operator, $condition); | ||||
|          | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user