Skip to content
This repository has been archived by the owner on Jul 8, 2023. It is now read-only.

Commit

Permalink
Make call args accessible by name or position
Browse files Browse the repository at this point in the history
  • Loading branch information
ezzatron committed Apr 10, 2023
1 parent bfe979b commit 6401ea3
Show file tree
Hide file tree
Showing 21 changed files with 321 additions and 108 deletions.
6 changes: 3 additions & 3 deletions doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6647,9 +6647,9 @@ _See [Verifying that a spy was called with specific arguments],
Get an argument by position or name.

_Negative positions are offset from the end of the positional arguments. That
is, `-1` indicates the last positional argument, and `-2` indicates the
second-to-last positional argument._
_Negative positions are offset from the end of the declared arguments. That is,
`-1` indicates the last declared argument, and `-2` indicates the second-to-last
declared argument._

_See [Verifying that a spy was called with specific arguments],
[Verifying that a call was made with specific arguments]._
Expand Down
64 changes: 59 additions & 5 deletions src/Call/CallData.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Eloquent\Phony\Call\Event\ThrewEvent;
use Eloquent\Phony\Call\Exception\UndefinedArgumentException;
use Eloquent\Phony\Call\Exception\UndefinedCallException;
use Eloquent\Phony\Call\Exception\UndefinedPositionalArgumentException;
use Eloquent\Phony\Call\Exception\UndefinedResponseException;
use Eloquent\Phony\Collection\NormalizesIndices;
use Eloquent\Phony\Event\Event;
Expand Down Expand Up @@ -58,6 +59,15 @@ public function __construct(int $index, CalledEvent $calledEvent)

$calledEvent->setCall($this);
$this->calledEvent = $calledEvent;
$this->parameterNames = $calledEvent->parameterNames();
$this->argumentKeyMap = [];
$this->definedParameterCount = 0;

foreach ($this->parameterNames as $position => $name) {
$this->argumentKeyMap[$position] = $name;
$this->argumentKeyMap[$name] = $position;
++$this->definedParameterCount;
}

$this->iterableEvents = [];
}
Expand Down Expand Up @@ -476,7 +486,7 @@ public function parameters(): array
*/
public function parameterNames(): array
{
return $this->calledEvent->parameterNames();
return $this->parameterNames;
}

/**
Expand All @@ -492,9 +502,9 @@ public function arguments(): Arguments
/**
* Get an argument by position or name.
*
* Negative positions are offset from the end of the positional arguments.
* That is, `-1` indicates the last positional argument, and `-2` indicates
* the second-to-last positional argument.
* Negative positions are offset from the end of the declared arguments.
* That is, `-1` indicates the last declared argument, and `-2` indicates
* the second-to-last declared argument.
*
* @param int|string $positionOrName The position or name.
*
Expand All @@ -503,7 +513,36 @@ public function arguments(): Arguments
*/
public function argument(int|string $positionOrName = 0)
{
return $this->calledEvent->arguments()->get($positionOrName);
if (is_int($positionOrName) && $positionOrName < 0) {
if (
!$this->normalizeIndex(
$this->definedParameterCount,
$positionOrName,
$normalized
)
) {
throw new UndefinedPositionalArgumentException($positionOrName);
}

$positionOrName = $normalized;
}

$arguments = $this->calledEvent->arguments();

try {
return $arguments->get($positionOrName);
} catch (UndefinedArgumentException $e) {
$mappedKey = $this->argumentKeyMap[$positionOrName] ?? null;

if (null !== $mappedKey) {
try {
return $arguments->get($mappedKey);
} catch (UndefinedArgumentException) {
}
}

throw $e;
}
}

/**
Expand Down Expand Up @@ -662,6 +701,21 @@ public function endTime(): ?float
*/
private $calledEvent;

/**
* @var array<int,string>
*/
private $parameterNames;

/**
* @var array<int|string,int|string>
*/
private $argumentKeyMap;

/**
* @var int
*/
private $definedParameterCount;

/**
* @var ?ResponseEvent
*/
Expand Down
18 changes: 12 additions & 6 deletions src/Call/CallFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,31 @@ public function __construct(
/**
* Record call details by invoking a callback.
*
* @param callable $callback The callback.
* @param array<int,ReflectionParameter> $parameters The parameters.
* @param Arguments $arguments The arguments.
* @param SpyData $spy The spy to record the call to.
* @param callable $callback The callback.
* @param array<int,ReflectionParameter> $parameters The parameters.
* @param array<int,string> $parameterNames The parameter names.
* @param Arguments $arguments The arguments.
* @param SpyData $spy The spy to record the call to.
*
* @return CallData The newly created call.
*/
public function record(
callable $callback,
array $parameters,
array $parameterNames,
Arguments $arguments,
SpyData $spy
): CallData {
$originalArguments = $arguments->copy();

$call = new CallData(
$spy->nextIndex(),
$this->eventFactory
->createCalled($spy, $parameters, $originalArguments)
$this->eventFactory->createCalled(
$spy,
$parameters,
$parameterNames,
$originalArguments
)
);
$spy->addCall($call);

Expand Down
6 changes: 3 additions & 3 deletions src/Call/CallVerifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -444,9 +444,9 @@ public function arguments(): Arguments
/**
* Get an argument by position or name.
*
* Negative positions are offset from the end of the positional arguments.
* That is, `-1` indicates the last positional argument, and `-2` indicates
* the second-to-last positional argument.
* Negative positions are offset from the end of the declared arguments.
* That is, `-1` indicates the last declared argument, and `-2` indicates
* the second-to-last declared argument.
*
* @param int|string $positionOrName The position or name.
*
Expand Down
9 changes: 6 additions & 3 deletions src/Call/Event/CallEventFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,25 @@ public function __construct(Sequencer $sequencer, Clock $clock)
/**
* Create a new 'called' event.
*
* @param callable $callback The callback.
* @param array<int,ReflectionParameter> $parameters The parameters.
* @param Arguments $arguments The arguments.
* @param callable $callback The callback.
* @param array<int,ReflectionParameter> $parameters The parameters.
* @param array<int,string> $parameterNames The parameter names.
* @param Arguments $arguments The arguments.
*
* @return CalledEvent The newly created event.
*/
public function createCalled(
callable $callback,
array $parameters,
array $parameterNames,
Arguments $arguments
): CalledEvent {
return new CalledEvent(
$this->sequencer->next(),
$this->clock->time(),
$callback,
$parameters,
$parameterNames,
$arguments
);
}
Expand Down
20 changes: 9 additions & 11 deletions src/Call/Event/CalledEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,22 @@ class CalledEvent implements CallEvent
* @param float $time The time at which the event occurred, in seconds since the Unix epoch.
* @param callable $callback The callback.
* @param array<int,ReflectionParameter> $parameters The parameters.
* @param array<int,string> $parameterNames The parameter names.
* @param Arguments $arguments The arguments.
*/
public function __construct(
int $sequenceNumber,
float $time,
$callback,
array $parameters,
array $parameterNames,
Arguments $arguments
) {
$this->sequenceNumber = $sequenceNumber;
$this->time = $time;
$this->callback = $callback;
$this->parameters = $parameters;
$this->parameterNames = $parameterNames;
$this->arguments = $arguments;
}

Expand Down Expand Up @@ -64,17 +67,7 @@ public function parameters(): array
*/
public function parameterNames(): array
{
$names = [];

foreach ($this->parameters as $parameter) {
if ($parameter->isVariadic()) {
break;
}

$names[] = $parameter->getName();
}

return $names;
return $this->parameterNames;
}

/**
Expand All @@ -97,6 +90,11 @@ public function arguments(): Arguments
*/
private $parameters;

/**
* @var array<int,string>
*/
private $parameterNames;

/**
* @var Arguments
*/
Expand Down
24 changes: 22 additions & 2 deletions src/Spy/SpyData.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ public function __construct(
$this->generatorSpyFactory = $generatorSpyFactory;
$this->iterableSpyFactory = $iterableSpyFactory;

$this->parameterNames = [];

foreach ($parameters as $parameter) {
if ($parameter->isVariadic()) {
break;
}

$this->parameterNames[] = $parameter->getName();
}

$this->calls = [];
$this->useGeneratorSpies = true;
$this->useIterableSpies = false;
Expand Down Expand Up @@ -386,8 +396,13 @@ public function invokeWith($arguments = [])
return $this->invoker->callWith($callback, $arguments);
}

$call = $this->callFactory
->record($callback, $this->parameters, $arguments, $this);
$call = $this->callFactory->record(
$callback,
$this->parameters,
$this->parameterNames,
$arguments,
$this
);
$responseEvent = $call->responseEvent();

if ($responseEvent instanceof ThrewEvent) {
Expand Down Expand Up @@ -431,6 +446,11 @@ public function __debugInfo(): array
*/
private $parameters;

/**
* @var array<int,string>
*/
private $parameterNames;

/**
* @var CallFactory
*/
Expand Down
11 changes: 10 additions & 1 deletion test/src/Test/TestCallEventFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function reset()
public function createCalled(
$callback = null,
array $parameters = null,
array $parameterNames = null,
Arguments $arguments = null
): CalledEvent {
if (!$callback) {
Expand All @@ -46,11 +47,19 @@ public function createCalled(
if (!$parameters) {
$parameters = [];
}
if (!$parameters) {
$parameterNames = [];
}
if (!$arguments) {
$arguments = new Arguments([]);
}

return parent::createCalled($callback, $parameters, $arguments);
return parent::createCalled(
$callback,
$parameters,
$parameterNames,
$arguments
);
}

private $sequencer;
Expand Down
2 changes: 1 addition & 1 deletion test/src/Test/TestCallFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function create(
) {
if (!$calledEvent) {
$calledEvent = $this->eventFactory
->createCalled(function () {}, [], new Arguments([]));
->createCalled(function () {}, [], [], new Arguments([]));
}

$call = new CallData($this->index++, $calledEvent);
Expand Down
4 changes: 2 additions & 2 deletions test/suite/Assertion/AssertionRendererTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ protected function setUp(): void
$eventFactory = $callFactory->eventFactory();
$this->callA = $callFactory->create(
$eventFactory
->createCalled([$this->thisObjectA, 'testClassAMethodA'], [], Arguments::create('a', 'b')),
->createCalled([$this->thisObjectA, 'testClassAMethodA'], [], [], Arguments::create('a', 'b')),
$eventFactory->createReturned('x'),
null,
$eventFactory->createReturned('x')
Expand All @@ -63,7 +63,7 @@ protected function setUp(): void
);
$this->callF = $callFactory->create(
$eventFactory
->createCalled($this->thisObjectBHandle->testClassAMethodA, [], Arguments::create()),
->createCalled($this->thisObjectBHandle->testClassAMethodA, [], [], Arguments::create()),
$eventFactory->createReturned(null),
null,
$eventFactory->createReturned(null)
Expand Down

0 comments on commit 6401ea3

Please sign in to comment.