Pull merge.
[yaffs-website] / vendor / phpspec / prophecy / src / Prophecy / Argument / Token / ArrayEntryToken.php
1 <?php
2
3 /*
4  * This file is part of the Prophecy.
5  * (c) Konstantin Kudryashov <ever.zet@gmail.com>
6  *     Marcello Duarte <marcello.duarte@gmail.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Prophecy\Argument\Token;
13
14 use Prophecy\Exception\InvalidArgumentException;
15
16 /**
17  * Array entry token.
18  *
19  * @author Boris Mikhaylov <kaguxmail@gmail.com>
20  */
21 class ArrayEntryToken implements TokenInterface
22 {
23     /** @var \Prophecy\Argument\Token\TokenInterface */
24     private $key;
25     /** @var \Prophecy\Argument\Token\TokenInterface */
26     private $value;
27
28     /**
29      * @param mixed $key   exact value or token
30      * @param mixed $value exact value or token
31      */
32     public function __construct($key, $value)
33     {
34         $this->key = $this->wrapIntoExactValueToken($key);
35         $this->value = $this->wrapIntoExactValueToken($value);
36     }
37
38     /**
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.
41      *
42      * @param array|\ArrayAccess|\Traversable $argument
43      *
44      * @throws \Prophecy\Exception\InvalidArgumentException
45      * @return bool|int
46      */
47     public function scoreArgument($argument)
48     {
49         if ($argument instanceof \Traversable) {
50             $argument = iterator_to_array($argument);
51         }
52
53         if ($argument instanceof \ArrayAccess) {
54             $argument = $this->convertArrayAccessToEntry($argument);
55         }
56
57         if (!is_array($argument) || empty($argument)) {
58             return false;
59         }
60
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;
65         };
66
67         return max(array_map($scoreEntry, $valueScores, $keyScores));
68     }
69
70     /**
71      * Returns false.
72      *
73      * @return boolean
74      */
75     public function isLast()
76     {
77         return false;
78     }
79
80     /**
81      * Returns string representation for token.
82      *
83      * @return string
84      */
85     public function __toString()
86     {
87         return sprintf('[..., %s => %s, ...]', $this->key, $this->value);
88     }
89
90     /**
91      * Returns key
92      *
93      * @return TokenInterface
94      */
95     public function getKey()
96     {
97         return $this->key;
98     }
99
100     /**
101      * Returns value
102      *
103      * @return TokenInterface
104      */
105     public function getValue()
106     {
107         return $this->value;
108     }
109
110     /**
111      * Wraps non token $value into ExactValueToken
112      *
113      * @param $value
114      * @return TokenInterface
115      */
116     private function wrapIntoExactValueToken($value)
117     {
118         return $value instanceof TokenInterface ? $value : new ExactValueToken($value);
119     }
120
121     /**
122      * Converts instance of \ArrayAccess to key => value array entry
123      *
124      * @param \ArrayAccess $object
125      *
126      * @return array|null
127      * @throws \Prophecy\Exception\InvalidArgumentException
128      */
129     private function convertArrayAccessToEntry(\ArrayAccess $object)
130     {
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`.',
135                 $this->key
136             ));
137         }
138
139         $key = $this->key->getValue();
140
141         return $object->offsetExists($key) ? array($key => $object[$key]) : array();
142     }
143 }