IsTraversable   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 129
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 5
Bugs 4 Features 2
Metric Value
wmc 11
c 5
b 4
f 2
lcom 1
cbo 2
dl 0
loc 129
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A check() 0 11 2
A calculateResult() 0 11 3
A checkMixed() 0 4 1
A __invoke() 0 4 1
A getCachedResult() 0 5 1
A setCachedResult() 0 5 1
A getCacheKey() 0 8 2
1
<?php
2
3
/**
4
 * Copyright (c) 2015-present Ganbaro Digital Ltd
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 *
11
 *   * Redistributions of source code must retain the above copyright
12
 *     notice, this list of conditions and the following disclaimer.
13
 *
14
 *   * Redistributions in binary form must reproduce the above copyright
15
 *     notice, this list of conditions and the following disclaimer in
16
 *     the documentation and/or other materials provided with the
17
 *     distribution.
18
 *
19
 *   * Neither the names of the copyright holders nor the names of his
20
 *     contributors may be used to endorse or promote products derived
21
 *     from this software without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 *
36
 * @category  Libraries
37
 * @package   Reflection/Checks
38
 * @author    Stuart Herbert <[email protected]>
39
 * @copyright 2015-present Ganbaro Digital Ltd www.ganbarodigital.com
40
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
41
 * @link      http://code.ganbarodigital.com/php-reflection
42
 */
43
44
namespace GanbaroDigital\Reflection\Checks;
45
46
use stdClass;
47
use IteratorAggregate;
48
use Traversable;
49
use GanbaroDigital\DataContainers\Caches\StaticDataCache;
50
use GanbaroDigital\Reflection\ValueBuilders\AllMatchingTypesList;
51
52
class IsTraversable
53
{
54
    // speed repeated things up
55
    use StaticDataCache;
56
57
    /**
58
     * list of types that we consider to be traversable
59
     *
60
     * @var array
61
     */
62
    private static $acceptableTypes = [
63
        'Array'                  => true,
64
        stdClass::class          => true,
65
        Traversable::class       => true,
66
        IteratorAggregate::class => true,
67
    ];
68
69
    /**
70
     * is $item something that can be used in a foreach() loop?
71
     *
72
     * @param  mixed $item
73
     *         the item to examine
74
     * @return boolean
75
     *         true if the item can be used in a foreach() loop
76
     *         false otherwise
77
     */
78
    public static function check($item)
79
    {
80
        if (($retval = self::getCachedResult($item)) !== null) {
81
            return $retval;
82
        }
83
84
        $retval = self::calculateResult($item);
85
86
        self::setCachedResult($item, $retval);
87
        return $retval;
88
    }
89
90
    /**
91
     * is $item something that can be used in a foreach() loop?
92
     *
93
     * @param  mixed $item
94
     *         the item to examine
95
     * @return boolean
96
     *         true if the item can be used in a foreach() loop
97
     *         false otherwise
98
     */
99
    private static function calculateResult($item)
100
    {
101
        $itemTypes = AllMatchingTypesList::from($item);
102
        foreach ($itemTypes as $itemType) {
103
            if (isset(self::$acceptableTypes[$itemType])) {
104
                return true;
105
            }
106
        }
107
108
        return false;
109
    }
110
111
    /**
112
     * is $item something that can be used in a foreach() loop?
113
     *
114
     * @deprecated since 2.10.0
115
     * @codeCoverageIgnore
116
     * @param  mixed $item
117
     *         the item to examine
118
     * @return boolean
119
     *         true if the item can be used in a foreach() loop
120
     *         false otherwise
121
     */
122
    public static function checkMixed($item)
123
    {
124
        return self::check($item);
125
    }
126
127
    /**
128
     * is $item something that can be used in a foreach() loop?
129
     *
130
     * @param  mixed $item
131
     *         the item to examine
132
     * @return boolean
133
     *         true if the item can be used in a foreach() loop
134
     *         false otherwise
135
     */
136
    public function __invoke($item)
137
    {
138
        return self::check($item);
139
    }
140
141
    /**
142
     * have we seen this kind of item before?
143
     *
144
     * @param  mixed $item
145
     * @return boolean|null
146
     */
147
    private static function getCachedResult($item)
148
    {
149
        $cacheKey = self::getCacheKey($item);
150
        return self::getFromCache($cacheKey);
151
    }
152
153
    /**
154
     * remember the result in case there is a next time
155
     *
156
     * @param mixed $item
157
     * @param boolean $result
158
     * @return void
159
     */
160
    private static function setCachedResult($item, $result)
161
    {
162
        $cacheKey = self::getCacheKey($item);
163
        self::setInCache($cacheKey, $result);
164
    }
165
166
    /**
167
     * work out what lookup key to use for this item
168
     *
169
     * @param  mixed $item
170
     * @return string
171
     */
172
    private static function getCacheKey($item)
173
    {
174
        if (is_object($item)) {
175
            return get_class($item);
176
        }
177
178
        return gettype($item);
179
    }
180
}