KeysMatcher::getDefaultTemplate()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 0
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Peridot\Leo\Matcher;
4
5
use Peridot\Leo\Matcher\Template\ArrayTemplate;
6
use Peridot\Leo\Matcher\Template\TemplateInterface;
7
8
/**
9
 * KeysMatcher determines if the actual array or object has the expected keys. If the Assertion has
10
 * a 'contain' flag set, it will check if the expected keys are included in the object or array.
11
 *
12
 * @package Peridot\Leo\Matcher
13
 */
14
class KeysMatcher extends AbstractMatcher
15
{
16
    /**
17
     * The verb used in the template. Uses "have" if the 'contain' flag is not used, otherwise
18
     * "contain" is used.
19
     *
20
     * @var string
21
     */
22
    protected $verb = 'have';
23
24
    /**
25
     * {@inheritdoc}
26
     *
27
     * @return TemplateInterface
28
     */
29
    public function getDefaultTemplate()
30
    {
31
        $subject = 'key';
32
33
        if (count($this->expected) > 1) {
34
            $subject = 'keys';
35
        }
36
37
        $template = new ArrayTemplate([
38
            'default' => "Expected {{actual}} to {$this->verb} $subject {{keys}}",
39
            'negated' => "Expected {{actual}} to not {$this->verb} $subject {{keys}}",
40
        ]);
41
42
        return $template->setTemplateVars(['keys' => $this->getKeyString()]);
43
    }
44
45
    /**
46
     * Assert that the actual value is an array or object with the expected keys.
47
     *
48
     * @param $actual
49
     * @return mixed
50
     */
51
    protected function doMatch($actual)
52
    {
53
        $actual = $this->getArrayValue($actual);
54
        if ($this->assertion->flag('contain')) {
55
            $this->verb = 'contain';
56
57
            return $this->matchInclusion($actual);
58
        }
59
        $keys = array_keys($actual);
60
61
        return $keys == $this->expected;
62
    }
63
64
    /**
65
     * Normalize the actual value into an array, whether it is an object
66
     * or an array.
67
     *
68
     * @param object|array $actual
69
     */
70
    protected function getArrayValue($actual)
71
    {
72
        if (is_object($actual)) {
73
            return get_object_vars($actual);
74
        }
75
76
        if (is_array($actual)) {
77
            return $actual;
78
        }
79
80
        throw new \InvalidArgumentException('KeysMatcher expects object or array');
81
    }
82
83
    /**
84
     * Returns a formatted string of expected keys.
85
     *
86
     * @return string keys
87
     */
88
    protected function getKeyString()
89
    {
90
        $expected = $this->expected;
91
        $keys = '';
92
        $tail = array_pop($expected);
93
94
        if (!empty($expected)) {
95
            $keys = implode('","', $expected) . '", and "';
96
        }
97
98
        $keys .= $tail;
99
100
        return $keys;
101
    }
102
103
    /**
104
     * Used when the 'contain' flag exists on the Assertion. Checks
105
     * if the expected keys are included in the object or array.
106
     *
107
     * @param  array $actual
108
     * @return true
109
     */
110
    protected function matchInclusion($actual)
111
    {
112
        foreach ($this->expected as $key) {
113
            if (!array_key_exists($key, $actual)) {
114
                return false;
115
            }
116
        }
117
118
        return true;
119
    }
120
}
121