Skip to content

Commit

Permalink
Add 'uses' filter option
Browse files Browse the repository at this point in the history
  • Loading branch information
chadicus committed May 29, 2020
1 parent de16cb0 commit 3f9ecb8
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 7 deletions.
5 changes: 5 additions & 0 deletions src/FilterOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ final class FilterOptions
* @var string
*/
const CONFLICTS_WITH = 'conflictsWith';

/**
* @var string
*/
const USES = 'uses';
}
38 changes: 31 additions & 7 deletions src/Filterer.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,21 @@ public function __construct(array $specification, array $options = [], array $fi
public function execute(array $input) : FilterResponse
{
$filterAliases = $this->getAliases();
$inputToFilter = array_intersect_key($input, $this->specification);
$leftOverSpec = array_diff_key($this->specification, $input);
$leftOverInput = array_diff_key($input, $this->specification);
$inputToFilter = [];
$leftOverSpec = [];

foreach ($this->specification as $field => $specification) {
if (array_key_exists($field, $input)) {
$inputToFilter[$field] = $input[$field];
continue;
}

$leftOverSpec[$field] = $specification;
}

$leftOverInput = array_diff_key($input, $inputToFilter);

$filteredInput = [];
$errors = [];
$conflicts = [];
foreach ($inputToFilter as $field => $input) {
Expand All @@ -132,6 +143,9 @@ public function execute(array $input) : FilterResponse
unset($filters[FilterOptions::DEFAULT_VALUE]);//doesn't matter if there is a default since we have a value
$conflicts = self::extractConflicts($filters, $field, $conflicts);

$uses = $filters[FilterOptions::USES] ?? [];
unset($filters[FilterOptions::USES]);

foreach ($filters as $filter) {
self::assertFilterIsNotArray($filter, $field);

Expand All @@ -146,31 +160,41 @@ public function execute(array $input) : FilterResponse

array_unshift($filter, $input);
try {
foreach ($uses as $usedField) {
if (!array_key_exists($usedField, $filteredInput)) {
throw new FilterException(
"{$field} uses {$usedField} but {$usedField} was not given."
);
}

array_push($filter, $filteredInput[$usedField]);
}

$input = call_user_func_array($function, $filter);
} catch (Exception $exception) {
$errors = self::handleCustomError($field, $input, $exception, $errors, $customError);
continue 2;//next field
}
}

$inputToFilter[$field] = $input;
$filteredInput[$field] = $input;
}

foreach ($leftOverSpec as $field => $filters) {
self::assertFiltersIsAnArray($filters, $field);
$required = self::getRequired($filters, $this->defaultRequired, $field);
if (array_key_exists(FilterOptions::DEFAULT_VALUE, $filters)) {
$inputToFilter[$field] = $filters[FilterOptions::DEFAULT_VALUE];
$filteredInput[$field] = $filters[FilterOptions::DEFAULT_VALUE];
continue;
}

$errors = self::handleRequiredFields($required, $field, $errors);
}

$errors = self::handleAllowUnknowns($this->allowUnknowns, $leftOverInput, $errors);
$errors = self::handleConflicts($inputToFilter, $conflicts, $errors);
$errors = self::handleConflicts($filteredInput, $conflicts, $errors);

return new FilterResponse($inputToFilter, $errors, $leftOverInput);
return new FilterResponse($filteredInput, $errors, $leftOverInput);
}

/**
Expand Down
81 changes: 81 additions & 0 deletions tests/FiltererTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,87 @@ public function provideValidFilterData() : array
[],
],
],
'uses' => [
'spec' => [
'fieldOne' => [['uint']],
'fieldTwo' => [
FilterOptions::USES => ['fieldOne'],
['uint'],
[
function (int $input, int $fieldOneValue) : int {
return $input * $fieldOneValue;
},
],
],
],
'input' => [
'fieldOne' => '5',
'fieldTwo' => '2',
],
'options' => [],
'result' => [
true,
[
'fieldOne' => 5,
'fieldTwo' => 10,
],
null,
[],
],
],
'input order does not matter for uses' => [
'spec' => [
'fieldOne' => [['uint']],
'fieldTwo' => [
FilterOptions::USES => ['fieldOne'],
['uint'],
[
function (int $input, int $fieldOneValue) : int {
return $input * $fieldOneValue;
},
],
],
],
'input' => [
'fieldTwo' => '2',
'fieldOne' => '5',
],
'options' => [],
'result' => [
true,
[
'fieldOne' => 5,
'fieldTwo' => 10,
],
null,
[],
],
],
'uses missing field' => [
'spec' => [
'fieldOne' => [['uint']],
'fieldTwo' => [
FilterOptions::USES => ['fieldOne'],
['uint'],
[
function (int $input, int $fieldOneValue) : int {
return $input * $fieldOneValue;
},
],
],
],
'input' => [
'fieldTwo' => '2',
],
'options' => [],
'result' => [
false,
null,
"Field 'fieldTwo' with value '2' failed filtering, message 'fieldTwo uses fieldOne but fieldOne was"
. " not given.'",
[],
],
],
];
}

Expand Down

0 comments on commit 3f9ecb8

Please sign in to comment.