Merge branch 'master' of https://git.mcnd.ca/mcndave/ulmus
This commit is contained in:
		
						commit
						6f558f2923
					
				@ -56,6 +56,11 @@ abstract class Sql {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    public static function raw(string $sql) : object
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return static::identifier($sql);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static function escape($value)
 | 
					    public static function escape($value)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        switch(true) {
 | 
					        switch(true) {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,10 +4,7 @@ namespace Ulmus\Entity\Field;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class Date extends Datetime {
 | 
					class Date extends Datetime {
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    public function __toString()
 | 
					    public string $format = "Y-m-d";
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $this->format("Y-m-d");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    public function formatLocale(string $format) : string
 | 
					    public function formatLocale(string $format) : string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,9 +4,6 @@ namespace Ulmus\Entity\Field;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class Time extends Datetime {
 | 
					class Time extends Datetime {
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    public function __toString()
 | 
					    public string $format = "H:i:s";
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $this->format("H:i:s");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,8 @@ use Generator;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class EntityCollection extends \ArrayObject {
 | 
					class EntityCollection extends \ArrayObject {
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    public ? string $entityClass = null;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    public function filters(Callable $callback) : Generator
 | 
					    public function filters(Callable $callback) : Generator
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $idx = 0;
 | 
					        $idx = 0;
 | 
				
			||||||
@ -30,6 +32,17 @@ class EntityCollection extends \ArrayObject {
 | 
				
			|||||||
        return $collection;
 | 
					        return $collection;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					    public function iterate(Callable $callback) : array
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $results = [];
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        foreach($this as $item) {
 | 
				
			||||||
 | 
					            $results[] = $callback($item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $results;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    public function removeOne($value, string $field, bool $strict = true) : ? object
 | 
					    public function removeOne($value, string $field, bool $strict = true) : ? object
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        foreach($this->search($value, $field, $strict) as $key => $item) {
 | 
					        foreach($this->search($value, $field, $strict) as $key => $item) {
 | 
				
			||||||
@ -72,6 +85,17 @@ class EntityCollection extends \ArrayObject {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    public function column($field) : array
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $list = [];
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        foreach($this as $item) {
 | 
				
			||||||
 | 
					            $list[] = $item->$field;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $list;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    public function buildArray(string $keyColumn, /* string|callable|null */ $value = null) : array
 | 
					    public function buildArray(string $keyColumn, /* string|callable|null */ $value = null) : array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $list = [];
 | 
					        $list = [];
 | 
				
			||||||
@ -98,6 +122,17 @@ class EntityCollection extends \ArrayObject {
 | 
				
			|||||||
        return $list;
 | 
					        return $list;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    public function implode(string $glue, ? Callable $callback = null) : string 
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $values = [];
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        foreach($this as $item) {
 | 
				
			||||||
 | 
					            $values[] = $callback ? $callback($item) : (string) $item;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return implode($glue, $values);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    public function toArray(bool $includeRelations = false) : array {
 | 
					    public function toArray(bool $includeRelations = false) : array {
 | 
				
			||||||
        $list = [];
 | 
					        $list = [];
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -107,4 +142,30 @@ class EntityCollection extends \ArrayObject {
 | 
				
			|||||||
        
 | 
					        
 | 
				
			||||||
        return $list;
 | 
					        return $list;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    public function fromArray(array $datasets, ? string $entityClass = null) : self 
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ( ! ($this->entityClass || $entityClass) ) {
 | 
				
			||||||
 | 
					            throw new \Exception("An entity class name must be provided to be instanciated and populated before insertion into this collection.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $className = $entityClass ?: $this->entityClass;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        foreach($datasets as $dataset) {
 | 
				
			||||||
 | 
					            $this->append( (new $className() )->fromArray($dataset) );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public function mergeWith( /*array|EntityCollection*/ $datasets ) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ( is_object($datasets) ) {
 | 
				
			||||||
 | 
					            $datasets = $datasets->getArrayCopy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $this->exchangeArray( array_merge( $this->getArrayCopy(), $datasets ) );
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -110,6 +110,10 @@ trait EntityTrait {
 | 
				
			|||||||
                        $bridgeRelation = $bridgeEntity->searchFieldAnnotation($relation->field, new Relation() );
 | 
					                        $bridgeRelation = $bridgeEntity->searchFieldAnnotation($relation->field, new Relation() );
 | 
				
			||||||
                        $relationRelation = $bridgeEntity->searchFieldAnnotation($relation->foreignField, new Relation() );
 | 
					                        $relationRelation = $bridgeEntity->searchFieldAnnotation($relation->foreignField, new Relation() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if ($relationRelation === null) {
 | 
				
			||||||
 | 
					                            throw new \Exception("@Relation annotation not found for field `{$relation->foreignField}` in entity {$relation->bridge}");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
                        $repository = $relationRelation->entity()->repository();
 | 
					                        $repository = $relationRelation->entity()->repository();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        $bridgeAlias = uniqid("bridge_");
 | 
					                        $bridgeAlias = uniqid("bridge_");
 | 
				
			||||||
@ -326,9 +330,9 @@ trait EntityTrait {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @Ignore
 | 
					     * @Ignore
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function toCollection() : array
 | 
					    public function toCollection() : EntityCollection
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return new EntityCollection($this->toArray());
 | 
					        return static::entityCollection([ $this->toArray() ]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -382,7 +386,10 @@ trait EntityTrait {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public static function entityCollection(...$arguments) : EntityCollection
 | 
					    public static function entityCollection(...$arguments) : EntityCollection
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return new EntityCollection(...$arguments);
 | 
					        $collection = new EntityCollection(...$arguments);
 | 
				
			||||||
 | 
					        $collection->entityClass = static::class;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $collection;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,9 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ulmus\Event;
 | 
					namespace Ulmus\Event\Repository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use Ulmus\EntityCollection;
 | 
					use Ulmus\EntityCollection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface RepositoryCollectionFromQueryInterface {
 | 
					interface CollectionFromQueryInterface {
 | 
				
			||||||
    public function execute(EntityCollection $collection) : EntityCollection;    
 | 
					    public function execute(EntityCollection $collection) : EntityCollection;    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -12,4 +12,20 @@ abstract class Fragment {
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        return implode($glue, array_filter($segments, function($i) { return ! is_null($i) && $i !== false && $i !== ""; }));
 | 
					        return implode($glue, array_filter($segments, function($i) { return ! is_null($i) && $i !== false && $i !== ""; }));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    protected function renderTables(/*array|string*/ $tableList, ? int $maxTableCount = null) : string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $i = 0;
 | 
				
			||||||
 | 
					        $list = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach((array) $tableList as $alias => $table) {
 | 
				
			||||||
 | 
					            $list[] = ! is_numeric($alias) ? "$table $alias" : $table;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if ( ++$i === $maxTableCount ) {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return implode(", ", $list);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,8 @@ class From extends Fragment {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public array $tables = [];
 | 
					    public array $tables = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public string $sql;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    public function set(array $tables) : self
 | 
					    public function set(array $tables) : self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->tables = $tables;
 | 
					        $this->tables = $tables;
 | 
				
			||||||
@ -29,18 +31,7 @@ class From extends Fragment {
 | 
				
			|||||||
    public function render() : string
 | 
					    public function render() : string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->renderSegments([
 | 
					        return $this->renderSegments([
 | 
				
			||||||
            static::SQL_TOKEN, $this->renderTables(),
 | 
					            static::SQL_TOKEN, $this->sql ?? $this->renderTables($this->tables),
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected function renderTables() : string
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $list = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach((array) $this->tables as $alias => $table) {
 | 
					 | 
				
			||||||
            $list[] = ! is_numeric($alias) ? "$table $alias" : $table;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return implode(", ", $list);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,22 +3,23 @@
 | 
				
			|||||||
namespace Ulmus\Query;
 | 
					namespace Ulmus\Query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GroupBy extends Fragment {
 | 
					class GroupBy extends Fragment {
 | 
				
			||||||
    
 | 
					    public int $order = 75;
 | 
				
			||||||
    const SQL_TOKEN = "GROUP BY";
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    public int $order = 70;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public array $groupBy = [];
 | 
					    public array $groupBy = [];
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    const SQL_TOKEN = "GROUP BY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function set(array $order) : self
 | 
					    public function set(array $order) : self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->groupBy = $order;
 | 
					        $this->groupBy = [ $order ];
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function add(string $field, ? string $direction = null) : self
 | 
					    public function add(string $field) : self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->groupBy[] = $field;
 | 
					        $this->groupBy[] = $field;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,142 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Ulmus\Query;
 | 
					namespace Ulmus\Query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Having extends Where {
 | 
					use Ulmus\QueryBuilder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Ulmus\Common\EntityField,
 | 
				
			||||||
 | 
					    Ulmus\Common\Sql;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Having extends Fragment {
 | 
				
			||||||
    const SQL_TOKEN = "HAVING"; 
 | 
					    const SQL_TOKEN = "HAVING"; 
 | 
				
			||||||
    public int $order = 75;
 | 
					
 | 
				
			||||||
 | 
					    public int $order = 80;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public array $conditionList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public QueryBuilder $queryBuilder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ? Having $parent = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public string $condition = Where::CONDITION_AND;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(? QueryBuilder $queryBuilder, $condition = Where::CONDITION_AND)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder = $queryBuilder;
 | 
				
			||||||
 | 
					        $this->condition = $condition;
 | 
				
			||||||
 | 
					        $this->parent = $queryBuilder->having ?? null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function add($field, $value, string $operator, string $condition, bool $not = false) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->conditionList[] = [
 | 
				
			||||||
 | 
					            $field,
 | 
				
			||||||
 | 
					            $value,
 | 
				
			||||||
 | 
					            $operator ?: $this->queryBuilder->conditionOperator,
 | 
				
			||||||
 | 
					            $condition,
 | 
				
			||||||
 | 
					            $not
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function render(bool $skipToken = false) : string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $stack = [];
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        foreach ($this->conditionList ?? [] as $key => $item) {
 | 
				
			||||||
 | 
					            if ( $item instanceof static ) {
 | 
				
			||||||
 | 
					                if ( $item->conditionList ?? false ) {
 | 
				
			||||||
 | 
					                    $stack[] = ( $key !== 0 ? "{$item->condition} " : "" ) . "(" . $item->render($skipToken) . ")";
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                list($field, $value, $operator, $condition, $not) = $item;
 | 
				
			||||||
 | 
					                $stack[] = $latest = $this->havingCondition($field, $value, $operator, $key !== 0 ? $condition : "", $not);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->renderSegments([
 | 
				
			||||||
 | 
					            ! $this->parent && ! $skipToken ? static::SQL_TOKEN : "",
 | 
				
			||||||
 | 
					            implode(" ", $stack)
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function havingCondition($field, $value, string $operator = Where::OPERATOR_EQUAL, string $condition = Where::CONDITION_AND, bool $not = false) {
 | 
				
			||||||
 | 
					        return new class($this->queryBuilder, $field, $value, $operator, $condition, $not) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public $value;
 | 
				
			||||||
 | 
					            public bool $not = false;
 | 
				
			||||||
 | 
					            public string $field;
 | 
				
			||||||
 | 
					            public string $operator;
 | 
				
			||||||
 | 
					            public string $condition;
 | 
				
			||||||
 | 
					            public QueryBuilder $queryBuilder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            protected string $content = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public function __construct(QueryBuilder $queryBuilder, string $field, $value, string $operator, string $condition, bool $not) {
 | 
				
			||||||
 | 
					                $this->queryBuilder = $queryBuilder;
 | 
				
			||||||
 | 
					                $this->field = $field;
 | 
				
			||||||
 | 
					                $this->value = $value;
 | 
				
			||||||
 | 
					                $this->condition = $condition;
 | 
				
			||||||
 | 
					                $this->operator = $operator;
 | 
				
			||||||
 | 
					                $this->not = $not;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public function render() : string
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                $value = $this->value();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return $this->content ?: $this->content = implode(" ", array_filter([
 | 
				
			||||||
 | 
					                    $this->condition,
 | 
				
			||||||
 | 
					                    $this->not ? Where::CONDITION_NOT : "",
 | 
				
			||||||
 | 
					                    $this->field,
 | 
				
			||||||
 | 
					                    $this->operator(),
 | 
				
			||||||
 | 
					                    $value,
 | 
				
			||||||
 | 
					                ]));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            protected function operator() : string
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if ( is_array($this->value) ) {
 | 
				
			||||||
 | 
					                    return (in_array($this->operator, [ '!=', '<>' ]) ? Where::CONDITION_NOT . " " : "") . Where::COMPARISON_IN;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return $this->operator;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            protected function value()
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if ( is_array($this->value) ) {
 | 
				
			||||||
 | 
					                    $stack = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    foreach($this->value as $item) {
 | 
				
			||||||
 | 
					                        $stack[] = $this->filterValue($item);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return "(" . implode(", ", $stack) . ")";
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return $this->filterValue($this->value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            protected function filterValue($value)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if ( $value === null ) {
 | 
				
			||||||
 | 
					                    $this->operator = in_array($this->operator, [ '!=', '<>' ]) ? Where::COMPARISON_IS . " " . Where::CONDITION_NOT : Where::COMPARISON_IS;
 | 
				
			||||||
 | 
					                    return Where::COMPARISON_NULL;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                elseif ( is_object($value) && ( $value instanceof EntityField ) ) {
 | 
				
			||||||
 | 
					                    return $value->name();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    return $this->queryBuilder->addParameter($value);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public function __toString() : string
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return $this->render();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,9 +3,13 @@
 | 
				
			|||||||
namespace Ulmus\Query;
 | 
					namespace Ulmus\Query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use Ulmus\QueryBuilder;
 | 
					use Ulmus\QueryBuilder;
 | 
				
			||||||
 | 
					use Ulmus\Repository\ConditionTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Join extends Fragment {
 | 
					class Join extends Fragment 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use ConditionTrait;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    const SQL_OUTER = "OUTER";
 | 
				
			||||||
    const SQL_TOKEN = "JOIN";
 | 
					    const SQL_TOKEN = "JOIN";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const TYPE_LEFT = "LEFT";
 | 
					    const TYPE_LEFT = "LEFT";
 | 
				
			||||||
@ -33,8 +37,10 @@ class Join extends Fragment {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    public /* QueryBuilder */ $queryBuilder;
 | 
					    public /* QueryBuilder */ $queryBuilder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function __construct(QueryBuilder $queryBuilder) {
 | 
					    public function __construct(QueryBuilder $queryBuilder) 
 | 
				
			||||||
        $this->queryBuilder = $queryBuilder;
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder = new QueryBuilder();
 | 
				
			||||||
 | 
					        $this->queryBuilder->parent = $queryBuilder;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    public function set(string $side, /* QueryBuilder|string */ $table, string $field, /* QueryBuilder|string */ $value) 
 | 
					    public function set(string $side, /* QueryBuilder|string */ $table, string $field, /* QueryBuilder|string */ $value) 
 | 
				
			||||||
@ -47,6 +53,12 @@ class Join extends Fragment {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function render() : string
 | 
					    public function render() : string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->renderSegments([ strtoupper($this->side), static::SQL_TOKEN, $this->table, $this->alias ?? "", $this->attachment, $this->field, "=", $this->value ]);
 | 
					        if ($this->queryBuilder->where ?? false ) {
 | 
				
			||||||
 | 
					            $where = $this->renderSegments([Where::CONDITION_AND, $this->queryBuilder->render(true)]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this->renderSegments([ 
 | 
				
			||||||
 | 
					            strtoupper($this->side), $this->outer ? static::SQL_OUTER : "", static::SQL_TOKEN, $this->table, $this->alias ?? "", $this->attachment, $this->field, "=", $this->value, $where ?? ""
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
namespace Ulmus\Query;
 | 
					namespace Ulmus\Query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class OrderBy extends Fragment {
 | 
					class OrderBy extends Fragment {
 | 
				
			||||||
    public int $order = 80;
 | 
					    public int $order = 85;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public array $orderBy = [];
 | 
					    public array $orderBy = [];
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,8 @@ namespace Ulmus\Query;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class Select extends Fragment {
 | 
					class Select extends Fragment {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const FIELD_AS = "%s as %s";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    public int $order = -100;
 | 
					    public int $order = -100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public bool $distinct = false;
 | 
					    public bool $distinct = false;
 | 
				
			||||||
@ -36,6 +38,13 @@ class Select extends Fragment {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function render() : string
 | 
					    public function render() : string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        foreach($this->fields as $key => &$value) {
 | 
				
			||||||
 | 
					            if ( ! is_numeric($key) ) {
 | 
				
			||||||
 | 
					                $value = sprintf(static::FIELD_AS, $value, $key);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        return $this->renderSegments([
 | 
					        return $this->renderSegments([
 | 
				
			||||||
            ( $this->union ? 'UNION' : false ),
 | 
					            ( $this->union ? 'UNION' : false ),
 | 
				
			||||||
            static::SQL_TOKEN,
 | 
					            static::SQL_TOKEN,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										26
									
								
								src/Query/Truncate.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/Query/Truncate.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ulmus\Query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Truncate extends Fragment {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const SQL_TOKEN = "TRUNCATE TABLE";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public int $order = -100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public string $table;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public function set(string $tableName) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->table = $tableName;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function render() : string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->renderSegments([
 | 
				
			||||||
 | 
					            static::SQL_TOKEN, $this->table,
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -50,14 +50,14 @@ class Where extends Fragment {
 | 
				
			|||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function render() : string
 | 
					    public function render(bool $skipToken = false) : string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $stack = [];
 | 
					        $stack = [];
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        foreach ($this->conditionList ?? [] as $key => $item) {
 | 
					        foreach ($this->conditionList ?? [] as $key => $item) {
 | 
				
			||||||
            if ( $item instanceof Where ) {
 | 
					            if ( $item instanceof Where ) {
 | 
				
			||||||
                if ( $item->conditionList ?? false ) {
 | 
					                if ( $item->conditionList ?? false ) {
 | 
				
			||||||
                    $stack[] = ( $key !== 0 ? "{$item->condition} " : "" ) . "(" . $item->render() . ")";
 | 
					                    $stack[] = ( $key !== 0 ? "{$item->condition} " : "" ) . "(" . $item->render($skipToken) . ")";
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
@ -67,7 +67,11 @@ class Where extends Fragment {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->renderSegments([
 | 
					        return $this->renderSegments([
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ! $this->parent && ! empty($this->conditionList) ? static::SQL_TOKEN : "",
 | 
					            ! $this->parent && ! empty($this->conditionList) ? static::SQL_TOKEN : "",
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					            ! $this->parent && ! $skipToken ? static::SQL_TOKEN : "",
 | 
				
			||||||
 | 
					>>>>>>> 27d5fd0b08b98f6fda3b8a6682b2dd7c7a692d82
 | 
				
			||||||
            implode(" ", $stack)
 | 
					            implode(" ", $stack)
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,8 @@ class QueryBuilder
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public Query\Having $having;
 | 
					    public Query\Having $having;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    public QueryBuilder $parent;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Those are the parameters we are going to bind to PDO.
 | 
					     * Those are the parameters we are going to bind to PDO.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -21,7 +23,7 @@ class QueryBuilder
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    public string $whereConditionOperator = Query\Where::CONDITION_AND;
 | 
					    public string $whereConditionOperator = Query\Where::CONDITION_AND;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    public string $havingConditionOperator = Query\Having::CONDITION_AND;
 | 
					    public string $havingConditionOperator = Query\Where::CONDITION_AND;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    protected int $parameterIndex = 0;
 | 
					    protected int $parameterIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -194,7 +196,12 @@ class QueryBuilder
 | 
				
			|||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function having($field, $value, string $operator = Query\Having::OPERATOR_EQUAL, string $condition = Query\Having::CONDITION_AND, bool $not = false) : self
 | 
					    public function notWhere($field, $value, string $operator = Query\Where::CONDITION_AND) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->where($field, $value, $operator, true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function having($field, $value, string $operator = Query\Where::OPERATOR_EQUAL, string $condition = Query\Where::CONDITION_AND, bool $not = false) : self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ( $this->having ?? false ) {
 | 
					        if ( $this->having ?? false ) {
 | 
				
			||||||
            $having = $this->having;
 | 
					            $having = $this->having;
 | 
				
			||||||
@ -210,17 +217,6 @@ class QueryBuilder
 | 
				
			|||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    public function notWhere($field, $value, string $operator = Query\Where::CONDITION_AND) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $this->where($field, $value, $operator, true);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function groupBy() : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function limit(int $value) : self
 | 
					    public function limit(int $value) : self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ( null === $limit = $this->getFragment(Query\Limit::class) ) {
 | 
					        if ( null === $limit = $this->getFragment(Query\Limit::class) ) {
 | 
				
			||||||
@ -257,7 +253,26 @@ class QueryBuilder
 | 
				
			|||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function groupBy(string $field, ? string $direction = null) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ( null === $groupBy = $this->getFragment(Query\GroupBy::class) ) {
 | 
				
			||||||
 | 
					            $groupBy = new Query\GroupBy();
 | 
				
			||||||
 | 
					            $this->push($groupBy);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $groupBy->add($field, $direction);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function join(string $type, /*string | QueryBuilder*/ $table, $field, $value, bool $outer = false, ? string $alias = null) : self
 | 
					    public function join(string $type, /*string | QueryBuilder*/ $table, $field, $value, bool $outer = false, ? string $alias = null) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->withJoin(...func_get_args());
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function withJoin(string $type, $table, $field, $value, bool $outer = false, ? string $alias = null) : Query\Join
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $join = new Query\Join($this);
 | 
					        $join = new Query\Join($this);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -269,6 +284,25 @@ class QueryBuilder
 | 
				
			|||||||
        
 | 
					        
 | 
				
			||||||
        $join->alias = $alias;
 | 
					        $join->alias = $alias;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        return $join;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public function truncate(string $table, ? string $alias = null, ? string $database = null, ? string $schema = null) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ( $schema ) {
 | 
				
			||||||
 | 
					            $table = "$schema.$table";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ( $database ) {
 | 
				
			||||||
 | 
					            $table = "$database.$table";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $truncate = new Query\Truncate($this);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $this->push($truncate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $truncate->set($table);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -279,7 +313,12 @@ class QueryBuilder
 | 
				
			|||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    public function render() : string
 | 
					    public function pull(Query\Fragment $queryFragment) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return array_shift($this->queryStack);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function render(bool $skipToken = false) : string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $sql = [];
 | 
					        $sql = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -288,7 +327,7 @@ class QueryBuilder
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach($this->queryStack as $fragment) {
 | 
					        foreach($this->queryStack as $fragment) {
 | 
				
			||||||
            $sql[] = $fragment->render();
 | 
					            $sql[] = $fragment->render($skipToken);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return implode(" ", $sql);
 | 
					        return implode(" ", $sql);
 | 
				
			||||||
@ -298,10 +337,10 @@ class QueryBuilder
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->parameters = $this->values = $this->queryStack = [];
 | 
					        $this->parameters = $this->values = $this->queryStack = [];
 | 
				
			||||||
        $this->whereConditionOperator = Query\Where::CONDITION_AND;
 | 
					        $this->whereConditionOperator = Query\Where::CONDITION_AND;
 | 
				
			||||||
        $this->havingConditionOperator = Query\Having::CONDITION_AND;
 | 
					        $this->havingConditionOperator = Query\Where::CONDITION_AND;
 | 
				
			||||||
        $this->parameterIndex = 0;
 | 
					        $this->parameterIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unset($this->where);
 | 
					        unset($this->where, $this->having);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function getFragment(string $class) : ? Query\Fragment
 | 
					    public function getFragment(string $class) : ? Query\Fragment
 | 
				
			||||||
@ -331,6 +370,10 @@ class QueryBuilder
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function addParameter($value, string $key = null) : string 
 | 
					    public function addParameter($value, string $key = null) : string 
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if ( $this->parent ?? false ) {
 | 
				
			||||||
 | 
					            return $this->parent->addParameter($value, $key);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        if ( $key === null ) {
 | 
					        if ( $key === null ) {
 | 
				
			||||||
            $key = ":p" . $this->parameterIndex++;
 | 
					            $key = ":p" . $this->parameterIndex++;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ use Ulmus\Common\EntityResolver;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class Repository
 | 
					class Repository
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use EventTrait;
 | 
					    use EventTrait, Repository\ConditionTrait;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    const DEFAULT_ALIAS = "this";
 | 
					    const DEFAULT_ALIAS = "this";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,7 +27,7 @@ class Repository
 | 
				
			|||||||
        $this->alias = $alias;
 | 
					        $this->alias = $alias;
 | 
				
			||||||
        $this->entityResolver = Ulmus::resolveEntity($entity);
 | 
					        $this->entityResolver = Ulmus::resolveEntity($entity);
 | 
				
			||||||
        $this->adapter = $adapter ?? $this->entityResolver->databaseAdapter() ?? Ulmus::$defaultAdapter;
 | 
					        $this->adapter = $adapter ?? $this->entityResolver->databaseAdapter() ?? Ulmus::$defaultAdapter;
 | 
				
			||||||
        $this->queryBuilder = new QueryBuilder( $this->adapter->adapter() );
 | 
					        $this->queryBuilder = new QueryBuilder();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function loadOne() : ? object
 | 
					    public function loadOne() : ? object
 | 
				
			||||||
@ -61,7 +61,14 @@ class Repository
 | 
				
			|||||||
            $this->queryBuilder->removeFragment($select);
 | 
					            $this->queryBuilder->removeFragment($select);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        $this->select("COUNT(*)")->selectSqlQuery();
 | 
					        if ( $this->queryBuilder->getFragment(Query\GroupBy::class) ) {
 | 
				
			||||||
 | 
					            $this->select( "DISTINCT COUNT(*) OVER ()" );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            $this->select(Common\Sql::function("COUNT", "*"));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $this->selectSqlQuery();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->finalizeQuery();
 | 
					        $this->finalizeQuery();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -161,14 +168,35 @@ class Repository
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    public function truncate(? string $table = null, ? string $alias = null, ? string $schema = null) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $schema = $schema ?: $this->entityResolver->schemaName();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $this->queryBuilder->truncate($this->escapeTable($table ?: $this->entityResolver->tableName()), $alias ?: $this->alias, $this->escapeDatabase($this->adapter->adapter()->database), $schema ? $this->escapeSchema($schema) : null);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $this->finalizeQuery();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $result = Ulmus::runSelectQuery($this->queryBuilder, $this->adapter);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    public function generateDatasetDiff(object $entity) : array
 | 
					    public function generateDatasetDiff(object $entity) : array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return array_diff_assoc( array_change_key_case($entity->toArray()), array_change_key_case($entity->entityGetDataset(false, true)) );
 | 
					        return array_diff_assoc( array_change_key_case($entity->toArray()), array_change_key_case($entity->entityGetDataset(false, true)) );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
    public function yieldAll() : \Generator
 | 
					    public function yield() : \Generator
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        $class = $this->entityClass;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        $this->selectSqlQuery();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $this->finalizeQuery();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach(Ulmus::iterateQueryBuilder($this->queryBuilder, $this->adapter) as $entityData) {
 | 
				
			||||||
 | 
					            yield ( new $class() )->entityFillFromDataset($entityData);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function select($fields) : self
 | 
					    public function select($fields) : self
 | 
				
			||||||
@ -220,194 +248,23 @@ class Repository
 | 
				
			|||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function join(string $type, $table, $field, $value, ? string $alias = null) : self
 | 
					    public function join(string $type, $table, $field, $value, ? string $alias = null, ? callable $callback = null) : self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->queryBuilder->join($type, $this->escapeTable($table), $field, $value, false, $alias);
 | 
					        $join = $this->queryBuilder->withJoin($type, $this->escapeTable($table), $field, $value, false, $alias);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return $this;
 | 
					        if ( $callback ) {
 | 
				
			||||||
    }
 | 
					            $callback($join);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function outerJoin(string $type, $table, $field, $value, ? string $alias = null) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->join($type, $this->escapeTable($table), $field, $value, true, $alias);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function open(string $condition = Query\Where::CONDITION_AND) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->open($condition);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function orOpen() : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $this->open(Query\Where::CONDITION_OR);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function close() : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->close();
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function where($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_AND);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function wheres(array $fieldValues, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        foreach($fieldValues as $field => $value) {
 | 
					 | 
				
			||||||
            if ( is_array($value) ) {
 | 
					 | 
				
			||||||
                switch ($value[1]) {
 | 
					 | 
				
			||||||
                    case Query\Where::CONDITION_AND:
 | 
					 | 
				
			||||||
                        $this->where($field, $value[0], $operator);
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    case Query\Where::CONDITION_OR:
 | 
					 | 
				
			||||||
                        $this->or($field, $value[0], $operator);
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    case Query\Where::CONDITION_NOT:
 | 
					 | 
				
			||||||
                        $this->notWhere($field, $value[0], $operator);
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                $this->where($field, $value, $operator);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function and($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
					    public function outerJoin(string $type, $table, $field, $value, ? string $alias = null, ? callable $callback = null) : self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->where($field, $value, $operator);
 | 
					        $join = $this->queryBuilder->withJoin($type, $this->escapeTable($table), $field, $value, true, $alias);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    public function or($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
					        if ( $callback ) {
 | 
				
			||||||
    {
 | 
					            $callback($join);
 | 
				
			||||||
        $this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_OR);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function notWhere($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_AND, true);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function orNot($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->notWhere($field, $value, $operator, Query\Where::CONDITION_OR, true);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function having($field, $value, string $operator = Query\Having::OPERATOR_EQUAL) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->having($field, $value, $operator, Query\Having::CONDITION_AND);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function orHaving($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->having($field, $value, $operator, Query\Having::CONDITION_OR);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function notHaving($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->having($field, $value, $operator, Query\Having::CONDITION_AND, true);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function orNotHaving($field, $value) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->having($field, $value, Query\Where::OPERATOR_NOT_EQUAL, Query\Having::CONDITION_OR, true);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    public function in($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->where($field, $value, $operator);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function orIn($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_OR);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function notIn($field, $value) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->queryBuilder->where($field, $value, Query\Where::OPERATOR_NOT_EQUAL);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function orNotIn($field, $value) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $this->orNot($field, $value, Query\Where::OPERATOR_NOT_EQUAL, Query\Where::CONDITION_OR, true);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function like($field, $value) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->where($field, $value, Query\Where::OPERATOR_LIKE);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function orLike($field, $value) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->or($field, $value, Query\Where::OPERATOR_LIKE);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function notLike($field, $value) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->notWhere($field, $value, Query\Where::OPERATOR_LIKE);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function likes(array $fieldValues, string $condition = Query\Where::CONDITION_AND) : self
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        foreach($fieldValues as $field => $value) {
 | 
					 | 
				
			||||||
            if ( is_array($value) ) {
 | 
					 | 
				
			||||||
                switch ($value[1]) {
 | 
					 | 
				
			||||||
                    case Query\Where::CONDITION_AND:
 | 
					 | 
				
			||||||
                        $this->like($field, $value[0]);
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    case Query\Where::CONDITION_OR:
 | 
					 | 
				
			||||||
                        $this->orLike($field, $value[0]);
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    case Query\Where::CONDITION_NOT:
 | 
					 | 
				
			||||||
                        $this->notLike($field, $value[0]);
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                $this->like($field, $value);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
@ -433,14 +290,19 @@ class Repository
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    public function groupBy() : self
 | 
					    public function groupBy($field) : self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->groupBy($field);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function groups(array $groups) : self
 | 
					    public function groups(array $groups) : self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        # foreach($this->groups)
 | 
					        foreach($groups as $field ) {
 | 
				
			||||||
 | 
					            $this->groupBy($field);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -454,7 +316,7 @@ class Repository
 | 
				
			|||||||
    public function orders(array $orderList) : self
 | 
					    public function orders(array $orderList) : self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        foreach($orderList as $field => $direction) {
 | 
					        foreach($orderList as $field => $direction) {
 | 
				
			||||||
            $this->queryBuilder->orderBy($field, $direction);
 | 
					            $this->orderBy($field, $direction);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
@ -502,7 +364,10 @@ class Repository
 | 
				
			|||||||
    public function withJoin(/*string|array*/ $fields) : self
 | 
					    public function withJoin(/*string|array*/ $fields) : self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $resolvedEntity = Ulmus::resolveEntity($this->entityClass);
 | 
					        $resolvedEntity = Ulmus::resolveEntity($this->entityClass);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ( null === $this->queryBuilder->getFragment(Query\Select::class) ) {
 | 
				
			||||||
            $this->select("{$this->alias}.*");
 | 
					            $this->select("{$this->alias}.*");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        foreach((array) $fields as $item) {
 | 
					        foreach((array) $fields as $item) {
 | 
				
			||||||
            if ( null !== $join = $resolvedEntity->searchFieldAnnotation($item, new Annotation\Property\Join) ) {
 | 
					            if ( null !== $join = $resolvedEntity->searchFieldAnnotation($item, new Annotation\Property\Join) ) {
 | 
				
			||||||
@ -528,17 +393,21 @@ class Repository
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    public function filterServerRequest(SearchRequest\SearchRequestInterface $searchRequest) : self 
 | 
					    public function filterServerRequest(SearchRequest\SearchRequestInterface $searchRequest) : self 
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $searchRequest->count = $searchRequest->filter( clone $this )
 | 
					        $likes = $searchRequest->likes();
 | 
				
			||||||
            ->wheres($searchRequest->wheres(), Query\Where::OPERATOR_EQUAL, Query\Where::CONDITION_AND)
 | 
					        $wheres = $searchRequest->wheres();
 | 
				
			||||||
            ->likes($searchRequest->likes(), Query\Where::CONDITION_OR)
 | 
					        $groups = $searchRequest->groups();
 | 
				
			||||||
            ->groups($searchRequest->groups())
 | 
					        
 | 
				
			||||||
 | 
					        $searchRequest->count = $searchRequest->skipCount ? 0 : $searchRequest->filter( clone $this )
 | 
				
			||||||
 | 
					            ->wheres($wheres, Query\Where::OPERATOR_EQUAL, Query\Where::CONDITION_AND)
 | 
				
			||||||
 | 
					            ->likes($likes, Query\Where::CONDITION_OR)
 | 
				
			||||||
 | 
					            ->groups($groups)
 | 
				
			||||||
            ->count();
 | 
					            ->count();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return $searchRequest->filter($this)
 | 
					        return $searchRequest->filter($this)
 | 
				
			||||||
            ->wheres($searchRequest->wheres(), Query\Where::OPERATOR_EQUAL, Query\Where::CONDITION_AND)
 | 
					            ->wheres($wheres, Query\Where::OPERATOR_EQUAL, Query\Where::CONDITION_AND)
 | 
				
			||||||
            ->likes($searchRequest->likes(), Query\Where::CONDITION_OR)
 | 
					            ->likes($likes, Query\Where::CONDITION_OR)
 | 
				
			||||||
            ->orders($searchRequest->orders())
 | 
					            ->orders($searchRequest->orders())
 | 
				
			||||||
            ->groups($searchRequest->groups())
 | 
					            ->groups($groups)
 | 
				
			||||||
            ->offset($searchRequest->offset())
 | 
					            ->offset($searchRequest->offset())
 | 
				
			||||||
            ->limit($searchRequest->limit());
 | 
					            ->limit($searchRequest->limit());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -547,7 +416,7 @@ class Repository
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $class = $entityClass ?: $this->entityClass;
 | 
					        $class = $entityClass ?: $this->entityClass;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        $entityCollection = $this->instanciateEntityCollection();
 | 
					        $entityCollection = $class::entityCollection();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        $this->selectSqlQuery();
 | 
					        $this->selectSqlQuery();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -557,7 +426,7 @@ class Repository
 | 
				
			|||||||
            $entityCollection->append( ( new $class() )->entityFillFromDataset($entityData) );
 | 
					            $entityCollection->append( ( new $class() )->entityFillFromDataset($entityData) );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        $this->eventExecute(Event\RepositoryCollectionFromQueryInterface::class, $entityCollection);
 | 
					        $this->eventExecute(Event\Repository\CollectionFromQueryInterface::class, $entityCollection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $entityCollection;
 | 
					        return $entityCollection;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										153
									
								
								src/Repository/ConditionTrait.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								src/Repository/ConditionTrait.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,153 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ulmus\Repository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Ulmus\Query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trait ConditionTrait 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public function open(string $condition = Query\Where::CONDITION_AND) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->open($condition);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function orOpen() : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->open(Query\Where::CONDITION_OR);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function close() : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->close();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function where($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_AND);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function wheres(array $fieldValues, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        foreach($fieldValues as $field => $value) {
 | 
				
			||||||
 | 
					            $this->where($field, $value, $operator);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public function and($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->where($field, $value, $operator);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function or($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_OR);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function notWhere($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_AND, true);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function orNot($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->notWhere($field, $value, $operator, Query\Where::CONDITION_OR, true);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function having($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->having($field, $value, $operator, Query\Where::CONDITION_AND);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function orHaving($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->having($field, $value, $operator, Query\Where::CONDITION_OR);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function notHaving($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->having($field, $value, $operator, Query\Where::CONDITION_AND, true);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function orNotHaving($field, $value) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->having($field, $value, Query\Where::OPERATOR_NOT_EQUAL, Query\Where::CONDITION_OR, true);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public function in($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->where($field, $value, $operator);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function orIn($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_OR);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function notIn($field, $value) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->queryBuilder->where($field, $value, Query\Where::OPERATOR_NOT_EQUAL);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function orNotIn($field, $value) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->orNot($field, $value, Query\Where::OPERATOR_NOT_EQUAL, Query\Where::CONDITION_OR, true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function like($field, $value) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->where($field, $value, Query\Where::OPERATOR_LIKE);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function orLike($field, $value) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->or($field, $value, Query\Where::OPERATOR_LIKE);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function notLike($field, $value) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->notWhere($field, $value, Query\Where::OPERATOR_LIKE);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function likes(array $fieldValues, string $condition = Query\Where::CONDITION_AND) : self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        foreach($fieldValues as $field => $value) {
 | 
				
			||||||
 | 
					            $this->like($field, $value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -12,6 +12,8 @@ trait SearchRequestPaginationTrait {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    public int $limit = 25;
 | 
					    public int $limit = 25;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    public bool $skipCount = false;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    public function limit(): int 
 | 
					    public function limit(): int 
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->limit;
 | 
					        return $this->limit;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user