Skip to content

Commit

Permalink
Merge pull request #65 from Lomkit/feature/more-constraints-on-relations
Browse files Browse the repository at this point in the history
✨ constraints on relations
  • Loading branch information
GautierDele authored Oct 22, 2023
2 parents 8191499 + 32290f2 commit bc30839
Show file tree
Hide file tree
Showing 12 changed files with 574 additions and 54 deletions.
5 changes: 4 additions & 1 deletion src/Relations/Relation.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ public function jsonSerialize(): mixed
'resources' => $this->types,
'relation' => $this->relation,
'constraints' => [
'requiredOnCreation' => $this->isRequiredOnCreation($request),
'required_on_creation' => $this->isRequiredOnCreation($request),
'prohibited_on_creation' => $this->isProhibitedOnCreation($request),
'required_on_update' => $this->isRequiredOnUpdate($request),
'prohibited_on_update' => $this->isProhibitedOnUpdate($request),
],
'name' => $this->name(),
];
Expand Down
131 changes: 121 additions & 10 deletions src/Relations/Traits/Constrained.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,90 @@
namespace Lomkit\Rest\Relations\Traits;

use Lomkit\Rest\Http\Requests\RestRequest;
use Lomkit\Rest\Relations\Relation;

trait Constrained
{
/**
* The callback used to determine if the relation is required.
* The callback used to determine if the relation is required on creation.
*
* @var (callable(RestRequest):bool)|bool
*/
public $relationRequiredCallback = false;
public $relationRequiredOnCreationCallback = false;

/**
* Set the callback used to determine if the relation is required.
* The callback used to determine if the relation is prohibited on creation.
*
* @var (callable(RestRequest):bool)|bool
*/
public $relationProhibitedOnCreationCallback = false;

/**
* The callback used to determine if the relation is required on update.
*
* @var (callable(RestRequest):bool)|bool
*/
public $relationRequiredOnUpdateCallback = false;

/**
* The callback used to determine if the relation is prohibited on update.
*
* @var (callable(RestRequest):bool)|bool
*/
public $relationProhibitedOnUpdateCallback = false;

/**
* Set the callback used to determine if the relation is required on creation.
*
* @param (callable(RestRequest):bool)|bool $callback
*
* @return Relation|Constrained
*/
public function requiredOnCreation(callable|bool $callback = true): self
{
$this->relationRequiredOnCreationCallback = $callback;

return $this;
}

/**
* Set the callback used to determine if the relation is prohibited on creation.
*
* @param (callable(RestRequest):bool)|bool $callback
*
* @return Relation|Constrained
*/
public function prohibitedOnCreation(callable|bool $callback = true): self
{
$this->relationProhibitedOnCreationCallback = $callback;

return $this;
}

/**
* Set the callback used to determine if the relation is required on update.
*
* @param (callable(RestRequest):bool)|bool $callback
*
* @return Relation|Constrained
*/
public function requiredOnUpdate(callable|bool $callback = true): self
{
$this->relationRequiredOnUpdateCallback = $callback;

return $this;
}

/**
* Set the callback used to determine if the relation is prohibited on update.
*
* @param (callable(RestRequest):bool)|bool $callback
*
* @return $this
* @return Relation|Constrained
*/
public function requiredOnCreation($callback = true)
public function prohibitedOnUpdate(callable|bool $callback = true): self
{
$this->relationRequiredCallback = $callback;
$this->relationProhibitedOnUpdateCallback = $callback;

return $this;
}
Expand All @@ -31,16 +95,63 @@ public function requiredOnCreation($callback = true)
* Check required on creation.
*
* @param RestRequest $request
* @param mixed $resource
*
* @return bool
*/
public function isRequiredOnCreation(RestRequest $request): bool
{
if (is_callable($this->relationRequiredCallback)) {
$this->relationRequiredCallback = call_user_func($this->relationRequiredCallback, $request, $this->resource());
if (is_callable($this->relationRequiredOnCreationCallback)) {
$this->relationRequiredOnCreationCallback = call_user_func($this->relationRequiredOnCreationCallback, $request, $this->resource());
}

return $this->relationRequiredOnCreationCallback;
}

/**
* Check prohibited on creation.
*
* @param RestRequest $request
*
* @return bool
*/
public function isProhibitedOnCreation(RestRequest $request): bool
{
if (is_callable($this->relationProhibitedOnCreationCallback)) {
$this->relationProhibitedOnCreationCallback = call_user_func($this->relationProhibitedOnCreationCallback, $request, $this->resource());
}

return $this->relationProhibitedOnCreationCallback;
}

/**
* Check required on update.
*
* @param RestRequest $request
*
* @return bool
*/
public function isRequiredOnUpdate(RestRequest $request): bool
{
if (is_callable($this->relationRequiredOnUpdateCallback)) {
$this->relationRequiredOnUpdateCallback = call_user_func($this->relationRequiredOnUpdateCallback, $request, $this->resource());
}

return $this->relationRequiredOnUpdateCallback;
}

/**
* Check prohibited on update.
*
* @param RestRequest $request
*
* @return bool
*/
public function isProhibitedOnUpdate(RestRequest $request): bool
{
if (is_callable($this->relationProhibitedOnUpdateCallback)) {
$this->relationProhibitedOnUpdateCallback = call_user_func($this->relationProhibitedOnUpdateCallback, $request, $this->resource());
}

return $this->relationRequiredCallback;
return $this->relationProhibitedOnUpdateCallback;
}
}
21 changes: 15 additions & 6 deletions src/Rules/MutateRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,26 @@ public function validate(string $attribute, mixed $value, Closure $fail): void
)
->validate();

// Required relations on creation --> will be refactored soon to allow multiple requirements
$relations = $this->resource->getRelations($this->request);

$this->validator
->setRules(
collect($this->resource->getRelations($this->request))
collect($relations)
->filter(function (Relation $relation) {
return $relation->isRequiredOnCreation($this->request);
return
$relation->isRequiredOnCreation($this->request) ||
$relation->isProhibitedOnCreation($this->request) ||
$relation->isRequiredOnUpdate($this->request) ||
$relation->isProhibitedOnUpdate($this->request);
})
->mapWithKeys(function (Relation $relation, $key) use ($attribute) {
return [$attribute.'.relations.'.$relation->relation => [
RequiredRelationOnCreation::make()->resource($this->resource),
]];
return [$attribute.'.relations.'.$relation->relation => array_merge(
$relation->isRequiredOnCreation($this->request) ? [RequiredRelationOnCreation::make()->resource($this->resource)] : [],
$relation->isProhibitedOnCreation($this->request) ? [ProhibitedRelationOnCreation::make()->resource($this->resource)] : [],
$relation->isRequiredOnUpdate($this->request) ? [RequiredRelationOnUpdate::make()->resource($this->resource)] : [],
$relation->isProhibitedOnUpdate($this->request) ? [ProhibitedRelationOnUpdate::make()->resource($this->resource)] : [],
),
];
})
->toArray()
)
Expand Down
84 changes: 84 additions & 0 deletions src/Rules/ProhibitedRelationOnCreation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

namespace Lomkit\Rest\Rules;

use Closure;
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Lomkit\Rest\Concerns\Makeable;

class ProhibitedRelationOnCreation implements ValidationRule, DataAwareRule
{
use Makeable;

/**
* Indicates whether the rule should be implicit.
*
* @var bool
*/
public $implicit = true;

/**
* The resource related to.
*
* @var resource
*/
protected $resource = null;

/**
* All of the data under validation.
*
* @var array<string, mixed>
*/
protected $data = [];

/**
* Set the data under validation.
*
* @param array<string, mixed> $data
*/
public function setData(array $data): static
{
$this->data = $data;

return $this;
}

/**
* Set the resource related to.
*
* @param mixed $resource
*
* @return $this
*/
public function resource($resource)
{
$this->resource = $resource;

return $this;
}

/**
* Validate the attribute.
*
* @param string $attribute
* @param mixed $value
* @param \Closure $fail
*
* @return void
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$arrayDot = Arr::dot($this->data);

if (
isset($arrayDot[Str::of($attribute)->beforeLast('.')->beforeLast('.')->append('.operation')->toString()]) &&
$arrayDot[Str::of($attribute)->beforeLast('.')->beforeLast('.')->append('.operation')->toString()] === 'create' &&
(isset($arrayDot[$attribute.'.0.operation']) || isset($arrayDot[$attribute.'.operation']))
) {
$fail('This relation is prohibited on creation');
}
}
}
84 changes: 84 additions & 0 deletions src/Rules/ProhibitedRelationOnUpdate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

namespace Lomkit\Rest\Rules;

use Closure;
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Lomkit\Rest\Concerns\Makeable;

class ProhibitedRelationOnUpdate implements ValidationRule, DataAwareRule
{
use Makeable;

/**
* Indicates whether the rule should be implicit.
*
* @var bool
*/
public $implicit = true;

/**
* The resource related to.
*
* @var resource
*/
protected $resource = null;

/**
* All of the data under validation.
*
* @var array<string, mixed>
*/
protected $data = [];

/**
* Set the data under validation.
*
* @param array<string, mixed> $data
*/
public function setData(array $data): static
{
$this->data = $data;

return $this;
}

/**
* Set the resource related to.
*
* @param mixed $resource
*
* @return $this
*/
public function resource($resource)
{
$this->resource = $resource;

return $this;
}

/**
* Validate the attribute.
*
* @param string $attribute
* @param mixed $value
* @param \Closure $fail
*
* @return void
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$arrayDot = Arr::dot($this->data);

if (
isset($arrayDot[Str::of($attribute)->beforeLast('.')->beforeLast('.')->append('.operation')->toString()]) &&
$arrayDot[Str::of($attribute)->beforeLast('.')->beforeLast('.')->append('.operation')->toString()] === 'update' &&
(isset($arrayDot[$attribute.'.0.operation']) || isset($arrayDot[$attribute.'.operation']))
) {
$fail('This relation is prohibited on creation');
}
}
}
Loading

0 comments on commit bc30839

Please sign in to comment.