Skip to content

Commit

Permalink
Improve request management
Browse files Browse the repository at this point in the history
  • Loading branch information
NastuzziSamy committed Oct 30, 2021
1 parent 1c31a7b commit 138c661
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 40 deletions.
25 changes: 20 additions & 5 deletions src/Exceptions/FilterException.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,39 @@ class FilterException extends LaramoreException

protected $errors;

public function __construct(Filter $filter, $errors, int $code=400)
public function __construct(Filter|string $filter, $errors, int $code=400)
{
$this->filter = $filter;
$this->errors = Arr::wrap($errors);

parent::__construct("Filter {$filter->getName()} excepted: ".implode('. ', $this->errors), $code);
parent::__construct("Filter {$this->name()} excepted: ".implode('. ', $this->errors), $code);
}

/**
* Return the filter that threw the exception.
*
* @return Filter
* @return Filter|string
*/
public function filter(): Filter
public function filter(): Filter|string
{
return $this->filter;
}

/**
* Return the filter name that threw the exception.
*
* @return Filter|string
*/
public function name(): string
{
if ($this->filter instanceof Filter) {
return $this->filter->getName();
}

return $this->filter;
}


/**
* Return the filter that threw the exception.
*
Expand All @@ -45,7 +60,7 @@ public function filter(): Filter
public function errors(): array
{
return [
$this->filter->getName() => $this->errors,
$this->name() => $this->errors,
];
}
}
34 changes: 21 additions & 13 deletions src/Http/Filters/BaseFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Str;
use Laramore\Contracts\Http\Filters\Filter;
use Laramore\Exceptions\FilterException;
use Laramore\Traits\{
HasLockedMacros, HasProperties, IsLocked, IsOwned
};
Expand Down Expand Up @@ -117,28 +118,35 @@ public function getName(): string

public function buildParams($params): Collection
{
$builtParams = collect();

if (!\is_array($params)) {
$params = ['value' => $this->checkValue($params)];
if (! \is_array($params)) {
$params = ['value' => $params];
}

$defaultParams = $this->getDefaultParams();
$params = \array_merge($defaultParams, $params);
$params = new Collection(\array_merge($defaultParams, $params));

foreach ($params as $subName => $subValue) {
if (\method_exists($this, $method = 'check'.Str::studly($subName))) {
$subValue = \call_user_func([$this, $method], $subValue, $params);
}
if (! $params->has('value')) {
throw new FilterException($this, 'Missing value for filter');
}

if (count($params) !== count($defaultParams)) {
$keys = implode(', ', array_diff(array_keys($params->toArray()), array_keys($defaultParams)));

$builtParams->put($subName, $subValue);
throw new FilterException($this, 'Some parameters are not allowed for this filter: '.$keys);
}

if (!$builtParams->has('value')) {
throw new \Exception('Missing value for filter !');
// Follow keys and retrieve at execution the value.
$keys = $params->keys();

foreach ($keys as $key) {
if (\method_exists($this, $method = 'check'.Str::studly($key))) {
$subValue = \call_user_func([$this, $method], $params->get($key), $params);
}

$params->put($key, $subValue);
}

return $builtParams;
return $params;
}

protected function locking()
Expand Down
2 changes: 1 addition & 1 deletion src/Http/Filters/OrderBy.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function getDefaultParams(): array
];
}

public function checkValue($value=null, array $params=[])
public function checkValue($value=null, Collection $params=null)
{
if (\in_array($value, $this->allowedValues)) {
if ($value === 'random' && !\is_null($params['field'])) {
Expand Down
2 changes: 1 addition & 1 deletion src/Http/Filters/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function getDefaultParams(): array
];
}

public function checkValue($value=null)
public function checkValue($value)
{
return (int) $value;
}
Expand Down
38 changes: 29 additions & 9 deletions src/Http/Filters/Filter.php → src/Http/Filters/Related.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Filter to filter values on a specific field.
* Filter values on a specific field.
* Ex: show only users with a specific father.
* Both father or father_id can be used (the composed field or the unique attribute).
*
Expand All @@ -17,11 +17,15 @@

use Illuminate\Support\Collection;
use Laramore\Contracts\Eloquent\LaramoreBuilder;
use Laramore\Contracts\Field\ComposedField;
use Laramore\Contracts\Field\{
Field, ComposedField,
RelationField
};
use Laramore\Contracts\Http\Filters\BuilderFilter;
use Laramore\Elements\OperatorElement;
use Laramore\Traits\Http\Filters\HasOperatorParameter;

class Filter extends BaseFilter implements BuilderFilter
class Related extends BaseFilter implements BuilderFilter
{
use HasOperatorParameter;

Expand All @@ -35,7 +39,7 @@ public function getDefaultParams(): array
];
}

public function getField()
public function getField(): Field
{
$this->needsToBeOwned();

Expand All @@ -49,21 +53,37 @@ protected function owned()
$meta = $this->getOwner()->getMeta();

$this->field = $meta->getField($this->getName());

if (! ($this->field instanceof RelationField)) {
throw new \Exception("The field {$this->getName()} is not a relation field");
}
}

public function checkValue($value=null)
public function checkValue($value=null, Collection $params=null)
{
// TODO.

if ($this->getField() instanceof ComposedField) {
return explode(',', $value);
if ($params->get('operator')->needs(OperatorElement::COLLECTION_TYPE)) {
return $value->map(function ($subValue) {
return new Collection(explode(',', $subValue));
});
}

return new Collection(explode(',', $value));
}

return $value;
}

public function filterBuilder(LaramoreBuilder $builder, Collection $params): ?LaramoreBuilder
{
return $this->getField()->where($builder, $params->get('operator'), $params->get('value'));
$field = $this->getField();
$operator = $params->get('operator');
$method = $operator->getWhereMethod();

if (method_exists($field, $method) || $field::hasMacro($method)) {
return \call_user_func([$field, $method], $builder, collect($params->get('value')));
}

return $field->where($builder, $operator, $params->get('value'));
}
}
11 changes: 9 additions & 2 deletions src/Traits/Http/Filters/HasOperatorParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,28 @@

namespace Laramore\Traits\Http\Filters;

use Illuminate\Support\Collection;
use Laramore\Elements\OperatorElement;
use Laramore\Facades\Operator;

trait HasOperatorParameter
{
protected $operators;

public function checkOperator($operator=null): OperatorElement
public function checkOperator($operator, Collection $params): OperatorElement
{
$operator = ($operator ?? '=');

if (\is_array($this->operators) && !\in_array($operator, $this->operators)) {
throw new \Error("Wrong operator `$operator`");
}

return Operator::find($operator);
$opElement = Operator::find($operator);

if ($opElement->needs(OperatorElement::COLLECTION_TYPE)) {
$params->put('value', collect($params->get('value')));
}

return $opElement;
}
}
22 changes: 13 additions & 9 deletions src/Traits/Http/Requests/HasLaramoreRelatedRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
namespace Laramore\Traits\Http\Requests;

use Illuminate\Support\Str;
use Laramore\Contracts\Field\ComposedField;
use Laramore\Contracts\Field\RelationField;

trait HasLaramoreRelatedRequest
Expand Down Expand Up @@ -119,17 +120,20 @@ public function fields(): array
$fields = parent::fields();
$relatedField = $this->relatedField();
$fieldsToRemove = [$relatedField->getName()];
$decomposed = $relatedField->decompose();

if (isset($decomposed[$this->modelClass()])) {
$fieldsToRemove = array_merge($fieldsToRemove, array_map(function ($field) {
return $field->getName();
}, $decomposed[$this->modelClass()]));
}
if ($relatedField instanceof ComposedField) {
$decomposed = $relatedField->decompose();

if (isset($decomposed[$this->modelClass()])) {
$fieldsToRemove = array_merge($fieldsToRemove, array_map(function ($field) {
return $field->getName();
}, $decomposed[$this->modelClass()]));
}

foreach ($fieldsToRemove as $name) {
if (($key = array_search($name, $fields)) !== false) {
unset($fields[$key]);
foreach ($fieldsToRemove as $name) {
if (($key = array_search($name, $fields)) !== false) {
unset($fields[$key]);
}
}
}

Expand Down

0 comments on commit 138c661

Please sign in to comment.