4 * This file is part of the Prophecy.
5 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
6 * Marcello Duarte <marcello.duarte@gmail.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Prophecy\Argument\Token;
14 use Prophecy\Exception\InvalidArgumentException;
19 * @author Boris Mikhaylov <kaguxmail@gmail.com>
21 class ArrayEntryToken implements TokenInterface
23 /** @var \Prophecy\Argument\Token\TokenInterface */
25 /** @var \Prophecy\Argument\Token\TokenInterface */
29 * @param mixed $key exact value or token
30 * @param mixed $value exact value or token
32 public function __construct($key, $value)
34 $this->key = $this->wrapIntoExactValueToken($key);
35 $this->value = $this->wrapIntoExactValueToken($value);
39 * Scores half of combined scores from key and value tokens for same entry. Capped at 8.
40 * If argument implements \ArrayAccess without \Traversable, then key token is restricted to ExactValueToken.
42 * @param array|\ArrayAccess|\Traversable $argument
44 * @throws \Prophecy\Exception\InvalidArgumentException
47 public function scoreArgument($argument)
49 if ($argument instanceof \Traversable) {
50 $argument = iterator_to_array($argument);
53 if ($argument instanceof \ArrayAccess) {
54 $argument = $this->convertArrayAccessToEntry($argument);
57 if (!is_array($argument) || empty($argument)) {
61 $keyScores = array_map(array($this->key,'scoreArgument'), array_keys($argument));
62 $valueScores = array_map(array($this->value,'scoreArgument'), $argument);
63 $scoreEntry = function ($value, $key) {
64 return $value && $key ? min(8, ($key + $value) / 2) : false;
67 return max(array_map($scoreEntry, $valueScores, $keyScores));
75 public function isLast()
81 * Returns string representation for token.
85 public function __toString()
87 return sprintf('[..., %s => %s, ...]', $this->key, $this->value);
93 * @return TokenInterface
95 public function getKey()
103 * @return TokenInterface
105 public function getValue()
111 * Wraps non token $value into ExactValueToken
114 * @return TokenInterface
116 private function wrapIntoExactValueToken($value)
118 return $value instanceof TokenInterface ? $value : new ExactValueToken($value);
122 * Converts instance of \ArrayAccess to key => value array entry
124 * @param \ArrayAccess $object
127 * @throws \Prophecy\Exception\InvalidArgumentException
129 private function convertArrayAccessToEntry(\ArrayAccess $object)
131 if (!$this->key instanceof ExactValueToken) {
132 throw new InvalidArgumentException(sprintf(
133 'You can only use exact value tokens to match key of ArrayAccess object'.PHP_EOL.
134 'But you used `%s`.',
139 $key = $this->key->getValue();
141 return $object->offsetExists($key) ? array($key => $object[$key]) : array();