diff --git a/src/Query/Having.php b/src/Query/Having.php index 6b03fc0..71f6144 100644 --- a/src/Query/Having.php +++ b/src/Query/Having.php @@ -5,6 +5,8 @@ namespace Ulmus\Query; use Ulmus\Common\EntityField, Ulmus\Common\Sql; +use Ulmus\QueryBuilder\QueryBuilderInterface; + class Having extends Fragment { const SQL_TOKEN = "HAVING"; diff --git a/src/Query/Join.php b/src/Query/Join.php index bf48920..6cfdde1 100644 --- a/src/Query/Join.php +++ b/src/Query/Join.php @@ -4,6 +4,8 @@ namespace Ulmus\Query; use Ulmus\Repository\ConditionTrait; +use Ulmus\QueryBuilder\QueryBuilderInterface; + class Join extends Fragment { use ConditionTrait; diff --git a/src/Query/Set.php b/src/Query/Set.php index 11ad8aa..abca900 100644 --- a/src/Query/Set.php +++ b/src/Query/Set.php @@ -2,6 +2,8 @@ namespace Ulmus\Query; +use Ulmus\QueryBuilder\QueryBuilderInterface; + class Set extends Fragment { public int $order = 0; @@ -25,7 +27,7 @@ class Set extends Fragment { return $this; } - public function render() /* : mixed */ + public function render() : mixed { return $this->renderSegments([ 'SET', $this->renderParameterPlaceholders(), diff --git a/src/Query/Values.php b/src/Query/Values.php index 7053c43..44712b5 100644 --- a/src/Query/Values.php +++ b/src/Query/Values.php @@ -2,6 +2,8 @@ namespace Ulmus\Query; +use Ulmus\QueryBuilder\QueryBuilderInterface; + class Values extends Fragment { public int $order = 0; diff --git a/src/Query/Where.php b/src/Query/Where.php index 007df5b..ca9aef9 100644 --- a/src/Query/Where.php +++ b/src/Query/Where.php @@ -4,6 +4,8 @@ namespace Ulmus\Query; use Ulmus\Common\Sql; +use Ulmus\QueryBuilder\QueryBuilderInterface; + class Where extends Fragment { const OPERATOR_LIKE = "LIKE"; const OPERATOR_EQUAL = "="; diff --git a/src/QueryBuilder/Sql/MysqlQueryBuilder.php b/src/QueryBuilder/Sql/MysqlQueryBuilder.php index 28b5de0..86a6b72 100644 --- a/src/QueryBuilder/Sql/MysqlQueryBuilder.php +++ b/src/QueryBuilder/Sql/MysqlQueryBuilder.php @@ -507,6 +507,15 @@ class MysqlQueryBuilder extends SqlQueryBuilder $key = ":p" . $this->parameterIndex++; } + if ($value instanceof \UnitEnum) { + if ($value instanceof \BackedEnum) { + $value = $value->value; + } + else { + throw new \InvalidArgumentException("Using UnitEnum as a parameter is currently unsupported. Try using a BackedEnum instead."); + } + } + $this->parameters[$key] = $value; return $key; diff --git a/src/SearchRequest/Attribute/PropertyValueModifier.php b/src/SearchRequest/Attribute/PropertyValueModifier.php new file mode 100644 index 0000000..69755c0 --- /dev/null +++ b/src/SearchRequest/Attribute/PropertyValueModifier.php @@ -0,0 +1,9 @@ +delimiter, $value); + } +} \ No newline at end of file diff --git a/src/SearchRequest/Attribute/SearchGroupBy.php b/src/SearchRequest/Attribute/SearchGroupBy.php index 839f0b1..235516c 100644 --- a/src/SearchRequest/Attribute/SearchGroupBy.php +++ b/src/SearchRequest/Attribute/SearchGroupBy.php @@ -9,8 +9,7 @@ class SearchGroupBy extends SearchParameter { public function __construct( public ? string $parameter = null, - public ? string $field = null, - public bool $toggle = false, + public null|string|\Stringable|array $field = null, public SearchMethodEnum $method = SearchMethodEnum::GroupBy, ) {} } \ No newline at end of file diff --git a/src/SearchRequest/Attribute/SearchLike.php b/src/SearchRequest/Attribute/SearchLike.php index 28756ee..e4a25c4 100644 --- a/src/SearchRequest/Attribute/SearchLike.php +++ b/src/SearchRequest/Attribute/SearchLike.php @@ -9,7 +9,7 @@ class SearchLike extends SearchParameter { public function __construct( public ? string $parameter = null, - public ? string $field = null, + public null|string|\Stringable|array $field = null, public bool $toggle = false, public SearchMethodEnum $method = SearchMethodEnum::Like, ) {} diff --git a/src/SearchRequest/Attribute/SearchOrderBy.php b/src/SearchRequest/Attribute/SearchOrderBy.php index 9f74ee8..96c3e02 100644 --- a/src/SearchRequest/Attribute/SearchOrderBy.php +++ b/src/SearchRequest/Attribute/SearchOrderBy.php @@ -7,10 +7,13 @@ use Ulmus\SearchRequest\SearchMethodEnum; #[\Attribute(\Attribute::TARGET_PROPERTY)] class SearchOrderBy extends SearchParameter { + public const ASCENDING = "ASC"; + + public const DESCENDING = "DESC"; + public function __construct( public ? string $parameter = null, - public ? string $field = null, - public bool $toggle = false, - public SearchMethodEnum $method = SearchMethodEnum::OrderByAsc, + public null|string|\Stringable|array $field = null, + public null|SearchMethodEnum $order = null, ) {} } \ No newline at end of file diff --git a/src/SearchRequest/Attribute/SearchParameter.php b/src/SearchRequest/Attribute/SearchParameter.php index 703d4bd..c234193 100644 --- a/src/SearchRequest/Attribute/SearchParameter.php +++ b/src/SearchRequest/Attribute/SearchParameter.php @@ -7,10 +7,6 @@ use Ulmus\SearchRequest\SearchMethodEnum; #[\Attribute(\Attribute::TARGET_PROPERTY)] class SearchParameter { - public function __construct( - public ? string $parameter = null, - public ? string $field = null, - public bool $toggle = false, - public SearchMethodEnum $method = SearchMethodEnum::Manual, - ) {} + + } \ No newline at end of file diff --git a/src/SearchRequest/Attribute/SearchWhere.php b/src/SearchRequest/Attribute/SearchWhere.php index c8d4678..959672c 100644 --- a/src/SearchRequest/Attribute/SearchWhere.php +++ b/src/SearchRequest/Attribute/SearchWhere.php @@ -9,7 +9,7 @@ class SearchWhere extends SearchParameter { public function __construct( public ? string $parameter = null, - public ? string $field = null, + public null|string|\Stringable|array $field = null, public bool $toggle = false, public SearchMethodEnum $method = SearchMethodEnum::Where, ) {} diff --git a/src/SearchRequest/SearchMethodEnum.php b/src/SearchRequest/SearchMethodEnum.php index 8dfee53..d8e6e15 100644 --- a/src/SearchRequest/SearchMethodEnum.php +++ b/src/SearchRequest/SearchMethodEnum.php @@ -9,7 +9,4 @@ enum SearchMethodEnum case Like; case LikeLeft; case LikeRight; - case OrderByAsc; - case OrderByDesc; - case GroupBy; } diff --git a/src/SearchRequest/SearchRequestFromRequestTrait.php b/src/SearchRequest/SearchRequestFromRequestTrait.php index fda4aa4..d489221 100644 --- a/src/SearchRequest/SearchRequestFromRequestTrait.php +++ b/src/SearchRequest/SearchRequestFromRequestTrait.php @@ -3,6 +3,8 @@ namespace Ulmus\SearchRequest; use Psr\Http\Message\ServerRequestInterface; +use Ulmus\SearchRequest\Attribute\SearchGroupBy; +use Ulmus\SearchRequest\Attribute\SearchOrderBy; use Ulmus\SearchRequest\Attribute\SearchParameter; use Ulmus\SearchRequest\Attribute\SearchWhere; @@ -18,43 +20,71 @@ trait SearchRequestFromRequestTrait public function fromRequest(ServerRequestInterface $request) { - $get = new \ArrayObject(array_filter($request->getQueryParams(), function($i) { return $i !== ""; })); + $queryParams = new \ArrayObject(array_filter($request->getQueryParams(), function($i) { return ! is_null($i) && $i !== ""; })); - $this->page = $get->offsetExists('page') ? $get['page'] : 1; + $this->page = $queryParams->offsetExists('page') ? $queryParams['page'] : 1; $classReflection = new \ReflectionClass($this); foreach($classReflection->getProperties() as $property) { + $attributeList = $property->getAttributes(); - foreach($property->getAttributes() as $attributeReflection) { - $attribute = $attributeReflection->newInstance(); + $attributeReflection = array_filter($attributeList, fn($e) => $e->newInstance() instanceof Attribute\SearchParameter); - # We can't simply pass this class as first arguments of getAttributes() since it do not check for inheritance - if (! $attribute instanceof Attribute\SearchParameter) { - continue; + if ($attributeReflection) { + $attribute = $attributeReflection[0]->newInstance(); + + $propertyName = $property->getName(); + $fieldName = $attribute->field ?? $propertyName; + $queryParamName = $attribute->parameter ?? $propertyName; + + $field = \Ulmus\Attribute\Attribute::handleArrayField($fieldName, false);; + + $value = $queryParams->offsetExists($queryParamName) ? $this->transformValue($attributeList, $queryParams[$queryParamName]) : null; + + if ($attribute instanceof SearchWhere) { + if ($attribute->toggle) { + $this->$propertyName = $queryParams->offsetExists($queryParamName); + } + elseif ($value !== null) { + $this->$propertyName = $value; + } + + $this->parseAttributeMethod($attribute, $field, $propertyName); } + elseif ($attribute instanceof SearchOrderBy) { + if ($value !== null) { + $this->$propertyName = $value; + } - $propertyName = $property->getName(); - $fieldName = $attribute->field ?? $property->getName(); - $queryParamName = $attribute->parameter ?? $property->getName(); - - if ($attribute->toggle) { - $this->$propertyName = $get->offsetExists('rental'); - } else { - $this->$propertyName = $get->offsetExists($queryParamName) ? $get[$queryParamName] : null; + $this->parseAttributeDefaultOrder($attribute, $field, $propertyName); } - - $field = (string) $fieldName; - - $this->parseAttributeMethod($attribute, $field, $propertyName); } } return $this; } + protected function transformValue(array $attributeList, mixed $value, ) : mixed + { + $transforms = array_map(function($e) { + $instance = $e->newInstance(); + return $instance instanceof Attribute\PropertyValueModifier ? $e->newInstance() : null; + }, $attributeList); + + foreach(array_filter($transforms) as $transform) { + $value = $transform->run($value); + } + + return $value; + } + protected function parseAttributeMethod(object $attribute, string $field, string $propertyName,) : void { + if (! isset($this->$propertyName)) { + return; + } + switch ($attribute->method) { case SearchMethodEnum::Where: $this->wheres[$field] = $this->$propertyName; @@ -71,18 +101,21 @@ trait SearchRequestFromRequestTrait case SearchMethodEnum::LikeRight: $this->likes[$field] = "{$this->$propertyName}%"; break; - - case SearchMethodEnum::OrderByAsc: - $this->orders[$field] = "ASC"; - break; - - case SearchMethodEnum::OrderByDesc: - $this->orders[$field] = "DESC"; - break; - - case SearchMethodEnum::GroupBy: - $this->groups[$field] = "DESC"; - break; } } + + protected function parseAttributeDefaultOrder(object $attribute, string $field, mixed $propertyName,) : void + { + $this->orders[$field] = $this->$propertyName; + } + + # @TODO ! + /* protected function parseAttributeGroupBy(object $attribute, string $field, string $propertyName,) : void + { + switch ($attribute->order) { + case SearchMethodEnum::GroupBy: + $this->groups[$field]; + break; + } + }*/ } \ No newline at end of file