Skip to content

Commit

Permalink
feat: Add the ability to strip extra params
Browse files Browse the repository at this point in the history
  • Loading branch information
dshafik committed Jan 26, 2025
1 parent 057344c commit f0c8627
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/Bag/Attributes/StripExtraParameters.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Bag\Attributes;

use Attribute;
use Bag\Attributes\Attribute as AttributeInterface;

#[Attribute(Attribute::TARGET_CLASS)]
class StripExtraParameters implements AttributeInterface
{
}
2 changes: 2 additions & 0 deletions src/Bag/Pipelines/InputPipeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Bag\Pipelines\Pipes\MissingProperties;
use Bag\Pipelines\Pipes\ProcessArguments;
use Bag\Pipelines\Pipes\ProcessParameters;
use Bag\Pipelines\Pipes\StripExtraParameters;
use Bag\Pipelines\Pipes\Transform;
use Bag\Pipelines\Pipes\Validate;
use Bag\Pipelines\Values\BagInput;
Expand All @@ -41,6 +42,7 @@ public static function process(BagInput $input): Bag
new LaravelRouteParameters(),
new MissingProperties(),
new ExtraParameters(),
new StripExtraParameters(),
new Validate(),
new CastInputValues(),
new FillBag(),
Expand Down
6 changes: 6 additions & 0 deletions src/Bag/Pipelines/Pipes/ExtraParameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

namespace Bag\Pipelines\Pipes;

use Bag\Attributes\StripExtraParameters;
use Bag\Bag;
use Bag\Exceptions\AdditionalPropertiesException;
use Bag\Internal\Reflection;
use Bag\Pipelines\Values\BagInput;

readonly class ExtraParameters
Expand All @@ -21,6 +23,10 @@ public function __invoke(BagInput $input): BagInput
return $input;
}

if ((Reflection::getAttribute(Reflection::getClass($input->bagClassname), StripExtraParameters::class) ?? false) !== false) {
return $input;
}

$extra = collect();
$input->values->each(function (mixed $_, string $key) use ($input, $extra) {
if ($input->params->has($key)) {
Expand Down
36 changes: 36 additions & 0 deletions src/Bag/Pipelines/Pipes/StripExtraParameters.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Bag\Pipelines\Pipes;

use Bag\Bag;
use Bag\Pipelines\Values\BagInput;

readonly class StripExtraParameters
{
/**
* @template T of Bag
* @param BagInput<T> $input
* @return BagInput<T>
*/
public function __invoke(BagInput $input): BagInput
{
if ($input->variadic) {
return $input;
}

$extra = collect();
$input->values->each(function (mixed $_, string $key) use ($input, $extra) {
if ($input->params->has($key)) {
return;
}

$extra->add($key);
});

$input->values = $input->values->except($extra);

return $input;
}
}
19 changes: 19 additions & 0 deletions tests/Fixtures/Values/StripExtraParametersBag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Tests\Fixtures\Values;

use Bag\Attributes\StripExtraParameters;
use Bag\Bag;

#[StripExtraParameters]
readonly class StripExtraParametersBag extends Bag
{
public function __construct(
public string $name,
public int $age,
public string $email
) {
}
}
99 changes: 99 additions & 0 deletions tests/Unit/Pipelines/Pipes/StripExtraParametersTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

declare(strict_types=1);
use Bag\Pipelines\Pipes\ExtraParameters;
use Bag\Pipelines\Pipes\IsVariadic;
use Bag\Pipelines\Pipes\MapInput;
use Bag\Pipelines\Pipes\ProcessArguments;
use Bag\Pipelines\Pipes\ProcessParameters;
use Bag\Pipelines\Pipes\StripExtraParameters;
use Bag\Pipelines\Values\BagInput;
use Illuminate\Support\Collection;
use Tests\Fixtures\Values\StripExtraParametersBag;
use Tests\Fixtures\Values\VariadicBag;

covers(ExtraParameters::class, StripExtraParameters::class);

test('it does not error on non variadic with extra parameters ignored', function () {
$input = new BagInput(StripExtraParametersBag::class, collect([
'name' => 'Davey Shafik',
'age' => 40,
'email' => '[email protected]',
'test' => true,
]));
$input = (new ProcessParameters())($input, fn (BagInput $input) => $input);
$input = (new MapInput())($input, fn (BagInput $input) => $input);
$input = (new IsVariadic())($input, fn (BagInput $input) => $input);
$input = (new ExtraParameters())($input, fn (BagInput $input) => $input);

$pipe = new StripExtraParameters();
$input = $pipe($input);

expect($input)
->toBeInstanceOf(BagInput::class)
->and($input->values)
->toBeInstanceOf(Collection::class)
->and($input->values->toArray())
->toBe([
'name' => 'Davey Shafik',
'age' => 40,
'email' => '[email protected]',
]);
});


test('it does not error on non variadic with extra positional parameters ignore', function () {
$input = new BagInput(StripExtraParametersBag::class, collect([
'Davey Shafik',
40,
'[email protected]',
true,
]));
$input = (new ProcessParameters())($input, fn (BagInput $input) => $input);
$input = (new ProcessArguments())($input, fn (BagInput $input) => $input);
$input = (new MapInput())($input, fn (BagInput $input) => $input);
$input = (new IsVariadic())($input, fn (BagInput $input) => $input);
$input = (new ExtraParameters())($input, fn (BagInput $input) => $input);

$pipe = new StripExtraParameters();
$input = $pipe($input);

expect($input)
->toBeInstanceOf(BagInput::class)
->and($input->values)
->toBeInstanceOf(Collection::class)
->and($input->values->toArray())
->toBe([
'name' => 'Davey Shafik',
'age' => 40,
'email' => '[email protected]',
]);
});

test('it does not strip extra parameters with variadic', function () {
$input = new BagInput(VariadicBag::class, collect([
'name' => 'Davey Shafik',
'age' => 40,
'email' => '[email protected]',
'test' => true,
]));
$input = (new ProcessParameters())($input, fn (BagInput $input) => $input);
$input = (new MapInput())($input, fn (BagInput $input) => $input);
$input = (new IsVariadic())($input, fn (BagInput $input) => $input);
$input = (new ExtraParameters())($input, fn (BagInput $input) => $input);

$pipe = new StripExtraParameters();
$input = $pipe($input);

expect($input)
->toBeInstanceOf(BagInput::class)
->and($input->values)
->toBeInstanceOf(Collection::class)
->and($input->values->toArray())
->toBe([
'name' => 'Davey Shafik',
'age' => 40,
'email' => '[email protected]',
'test' => true,
]);
});

0 comments on commit f0c8627

Please sign in to comment.