prepare($request); } $queryParams = new \ArrayObject(array_filter($request->getQueryParams(), function($i) { return ! is_null($i) && $i !== ""; })); $this->page = $queryParams->offsetExists('page') ? $queryParams['page'] : 1; $classReflection = ObjectReflection::fromClass(static::class)->reflectClass(); foreach($classReflection->getProperties() as $propertyName => $property) { $attributeList = $property->getAttributes(Attribute\SearchParameter::class); if ($attributeList) { $attribute = $attributeList[0]->object; $fieldName = $attribute->field ?? $propertyName; # Field could be defined for another entity class if (is_array($fieldName)) { $field = \Ulmus\Attribute\Attribute::handleArrayField($fieldName, false); } # Default class using it, if SearchRequestParameter is defined elseif ($classAttributes = $classReflection->getAttributes(SearchRequestParameter::class)) { $searchRequestAttribute = $classAttributes[0]->object; $className = $searchRequestAttribute->class; $field = $className::field($fieldName, $searchRequestAttribute->alias); } # Untouched string from the attribute else { $field = $fieldName; } $value = $this->getValueFromSource($request, $propertyName, $attribute); if ($value !== null) { $value = $this->transformValue($property->getAttributes(Attribute\PropertyValueModifier::class), $value); } switch(true) { case $attribute instanceof SearchGroupBy: $this->parseAttributeGroupBy($attribute, $field, $propertyName); break; case $attribute instanceof SearchWhere: case $attribute instanceof SearchLike: case $attribute instanceof SearchManual: if ($attribute->toggle) { $this->$propertyName = !empty($value); } elseif ($value !== null) { foreach ($property->getTypes() as $type) { $enum = $type->type; if (enum_exists($enum)) { try { $this->$propertyName = $value instanceof \UnitEnum ? $value : $type->type::from($value); } catch (\ValueError $ex) { $cases = implode(', ', array_map(fn($e) => $e->name, $enum::cases())); throw new \ValueError( sprintf("Given value '%s' do not exists within enum '%s'. Try one of those values instead : %s", $value, $enum, $cases) ); } } elseif ($type->builtIn) { $this->$propertyName = $value; } } } $this->parseAttributeMethod($attribute, $field, $propertyName); break; case $attribute instanceof SearchOrderBy: if ($value !== null) { $this->$propertyName = $value; } $this->parseAttributeOrderBy($attribute, $field, $propertyName); break; } } } return $this; } protected function getValueFromSource(RequestInterface $request, string $propertyName, SearchParameter $attribute) : mixed { $queryParamName = $attribute->getParameters() ?: [ $propertyName ]; foreach($attribute->getSources() as $source) { switch($source) { case PropertyValueSource::QueryParams: $queryParams = new \ArrayObject(array_filter($request->getQueryParams(), function($i) { return ! is_null($i) && $i !== ""; })); foreach($queryParamName as $param) { if ($queryParams->offsetExists($param)) { return $queryParams[$param]; } } break; case PropertyValueSource::RequestAttribute: foreach($queryParamName as $param) { $fromAttribute = $request->getAttribute($param, null); if ($fromAttribute !== null) { return $fromAttribute; } } break; } } return null; } protected function transformValue(array $valueModifierAttributes, mixed $value, ) : mixed { foreach($valueModifierAttributes as $transform) { $value = $transform->object->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; break; case SearchMethodEnum::Like: $this->likes[$field] = "%{$this->$propertyName}%"; break; case SearchMethodEnum::LikeLeft: $this->likes[$field] = "%{$this->$propertyName}"; break; case SearchMethodEnum::LikeRight: $this->likes[$field] = "{$this->$propertyName}%"; break; } } protected function parseAttributeOrderBy(object $attribute, string $field, mixed $propertyName,) : void { if ( ! empty($this->$propertyName) ) { $this->orders[$field] = $this->$propertyName; } } protected function parseAttributeGroupBy(object $attribute, string $field, mixed $propertyName,) : void { if (! empty($this->$propertyName)) { $this->groups[] = $field; } } }