FirstMethodMatchingType::getCacheName()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 21
rs 9.3142
cc 3
eloc 12
nc 4
nop 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/ValueBuilders
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-file-system
42
 */
43
44
namespace GanbaroDigital\Reflection\ValueBuilders;
45
46
use GanbaroDigital\DataContainers\Caches\StaticDataCache;
47
use GanbaroDigital\Reflection\Exceptions\E4xx_UnsupportedType;
48
use GanbaroDigital\Reflection\Filters\FilterNamespace;
49
50
final class FirstMethodMatchingType
51
{
52
    use StaticDataCache;
53
54
    /**
55
     * find a method on a class / object that can accept a given piece of data
56
     *
57
     * @deprecated since 2.12.0
58
     *
59
     * @param  mixed $data
60
     *         the data we are looking for
61
     * @param  string|object $target
62
     *         the class or object that we want to call with $data
63
     * @param  string $methodPrefix
64
     *         the prefix to put on the front of the method name
65
     * @param  string $eUnsupportedType
66
     *         the exception to throw if no matching method found
67
     * @return string
68
     *         the first method on $target that will accept $data
69
     */
70
    public static function from($data, $target, $methodPrefix, $eUnsupportedType = E4xx_UnsupportedType::class)
71
    {
72
        // do we have this in the cache?
73
        if (($retval = self::getMethodFromCache($data, $target)) !== null) {
74
            return $retval;
75
        }
76
77
        // what method do we want to call?
78
        $retval = self::findMethodToCall($data, $target, $methodPrefix, $eUnsupportedType);
79
80
        // cache it for next time
81
        self::setMethodInCache($data, $target, $retval);
82
83
        // all done
84
        return $retval;
85
    }
86
87
    /**
88
     * what key should we use to look up information on $data in our cache?
89
     *
90
     * @param  mixed $data
91
     *         the data to examine
92
     * @param  string|object $target
93
     *         the target we want to call
94
     * @return string
95
     *         the cache key to use
96
     */
97
    private static function getCacheName($data, $target)
98
    {
99
        // our cache key to be
100
        if (is_string($target)) {
101
            $retval = $target;
102
            $suffix = 'class';
103
        }
104
        else {
105
            $retval = get_class($target);
106
            $suffix = 'object';
107
        }
108
109
        if (is_object($data)) {
110
            $retval .= '::' . get_class($data);
111
        }
112
        else {
113
            $retval .= '::' . gettype($data);
114
        }
115
116
        return $retval . '::' . $suffix;
117
    }
118
119
    /**
120
     * do we have an appropriate method in our cache?
121
     *
122
     * @param  mixed $data
123
     *         the data we want to call $target with
124
     * @param  string|object $target
125
     *         the target that we want to call
126
     * @return string|null
127
     *         the cached method name, or NULL
128
     */
129
    private static function getMethodFromCache($data, $target)
130
    {
131
        $cacheKey = self::getCacheName($data, $target);
132
        return self::getFromCache($cacheKey);
133
    }
134
135
    /**
136
     * remember the method to call for next time
137
     *
138
     * @param mixed $data
139
     *        the data we want to call $target with
140
     * @param string|object $target
141
     *        the target that we want to call
142
     * @param string $methodName
143
     *        the method name that we want to remember
144
     */
145
    private static function setMethodInCache($data, $target, $methodName)
146
    {
147
        $cacheKey = self::getCacheName($data, $target);
148
        self::setInCache($cacheKey, $methodName);
149
    }
150
151
    /**
152
     * which method should we call on $target for $data?
153
     *
154
     * @param  mixed $data
155
     *         the data we want to call $target with
156
     * @param  string|object $target
157
     *         the target that we want to call
158
     * @param  string $methodPrefix
159
     *         the prefix at the front of methods on $target
160
     * @param  string $eUnsupportedType
161
     *         the exception to throw if no matching method found
162
     * @return string
163
     *         the method that suits $data the best
164
     *
165
     * @throws E4xx_UnsupportedType
166
     */
167
    private static function findMethodToCall($data, $target, $methodPrefix, $eUnsupportedType = E4xx_UnsupportedType::class)
168
    {
169
        // is there a method that matches the data type?
170
        if (($retval = self::findFirstMatchingMethod($data, $target, $methodPrefix)) !== null) {
171
            return $retval;
172
        }
173
174
        // no match
175
        //
176
        // treat as an error
177
        throw new $eUnsupportedType(SimpleType::from($data));
178
    }
179
180
    /**
181
     * find the first method on $target that matches $data's data type
182
     *
183
     * @param  mixed $data
184
     *         the data we want to call $target with
185
     * @param  string|object $target
186
     *         the target that we want to call
187
     * @param  string $methodPrefix
188
     *         the prefix at the front of methods on $target
189
     * @return string|null
190
     *         the method that suits $data the best
191
     */
192
    private static function findFirstMatchingMethod($data, $target, $methodPrefix)
193
    {
194
        // no, so we need to build it
195
        $possibleTypes   = AllMatchingTypesList::from($data);
196
        $possibleMethods = CallableMethodsList::from($target);
197
198
        foreach ($possibleTypes as $possibleType) {
199
            $targetMethodName = $methodPrefix . FilterNamespace::fromString($possibleType);
200
            if (isset($possibleMethods[$targetMethodName])) {
201
                // all done
202
                return $targetMethodName;
203
            }
204
        }
205
206
        // no match
207
        return null;
208
    }
209
210
    /**
211
     * find a method on a class / object that can accept a given piece of data
212
     *
213
     * @deprecated since 2.10.0
214
     * @codeCoverageIgnore
215
     * @param  mixed $data
216
     *         the data we are looking for
217
     * @param  string|object $target
218
     *         the class or object that we want to call with $data
219
     * @param  string $methodPrefix
220
     *         the prefix to put on the front of the method name
221
     * @param  string $eUnsupportedType
222
     *         the exception to throw if no matching method found
223
     * @return string
224
     *         the first method on $target that will accept $data
225
     */
226
    public static function fromMixed($data, $target, $methodPrefix, $eUnsupportedType = E4xx_UnsupportedType::class)
227
    {
228
        return self::from($data, $target, $methodPrefix, $eUnsupportedType);
0 ignored issues
show
Deprecated Code introduced by
The method GanbaroDigital\Reflectio...hodMatchingType::from() has been deprecated with message: since 2.12.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
229
    }
230
231
    /**
232
     * find a method on a class / object that can accept a given piece of data
233
     *
234
     * @param  mixed $data
235
     *         the data we are looking for
236
     * @param  string|object $target
237
     *         the class or object that we want to call with $data
238
     * @param  string $methodPrefix
239
     *         the prefix to put on the front of the method name
240
     * @param  string $eUnsupportedType
241
     *         the exception to throw if no matching method found
242
     * @return string
243
     *         the first method on $target that will accept $data
244
     */
245
    public function __invoke($data, $target, $methodPrefix, $eUnsupportedType = E4xx_UnsupportedType::class)
246
    {
247
        return self::from($data, $target, $methodPrefix, $eUnsupportedType);
0 ignored issues
show
Deprecated Code introduced by
The method GanbaroDigital\Reflectio...hodMatchingType::from() has been deprecated with message: since 2.12.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
248
    }
249
}