GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Repository::computeClassToCall()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 11
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 3
crap 12
1
<?php
2
declare(strict_types=1);
3
4
/*
5
 * This file is part of Underscore.php
6
 *
7
 * (c) Maxime Fabre <[email protected]>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace Underscore\Traits;
14
15
use BadMethodCallException;
16
use Closure;
17
use JsonException;
18
use RuntimeException;
19
use Underscore\Dispatch;
20
use Underscore\Method;
21
use Underscore\Methods\ArraysMethods;
22
use Underscore\Methods\StringsMethods;
23
use Underscore\Parse;
24
25
/**
26
 * Base abstract class for repositories.
27
 */
28
abstract class Repository implements \Stringable
29
{
30
    /**
31
     * The subject of the repository.
32
     */
33
    protected mixed $subject;
34
35
    /**
36
     * Custom functions.
37
     */
38
    protected static array $macros = [];
39
40
    /**
41
     * The method used to convert new subjects.
42
     */
43
    protected string $typecaster = '';
44
45
    ////////////////////////////////////////////////////////////////////
46
    /////////////////////////// PUBLIC METHODS /////////////////////////
47
    ////////////////////////////////////////////////////////////////////
48
49
    /**
50
     * Create a new instance of the repository.
51
     *
52
     * @param  mixed|null  $subject  The repository subject
53
     */
54
    public function __construct(mixed $subject = null)
55
    {
56
        // Assign subject
57 22
        $this->subject = $subject ?: $this->getDefault();
58
59
        // Convert it if necessary
60 22
        $typecaster = $this->typecaster;
61
        if ($typecaster !== '' && $typecaster !== '0') {
62
            $this->$typecaster();
63 22
        }
64 22
    }
65 22
66
    /**
67
     * Transform subject to Strings on toString.
68 22
     *
69
     * @throws JsonException
70
     */
71
    public function __toString() : string
72
    {
73
        return Parse::toString($this->subject);
74
    }
75
76 2
    /**
77
     * Create a new Repository.
78 2
     */
79
    public static function create() : Repository
80
    {
81
        return new static();
82
    }
83
84 7
    /**
85
     * Create a new Repository from a subject.
86 7
     *
87
     * @param $subject
88
     */
89
    public static function from($subject) : Repository
90
    {
91
        return new static($subject);
92
    }
93
94
    /**
95
     * Get a key from the subject.
96 12
     *
97
     * @param $key
98 12
     *
99
     * @return mixed
100
     */
101
    public function __get($key)
102
    {
103
        return ArraysMethods::get($this->subject, $key);
104
    }
105
106
    /**
107
     * Set a value on the subject.
108 1
     *
109
     * @param $key
110 1
     * @param $value
111
     */
112
    public function __set(string $key, $value)
113
    {
114
        $this->subject = ArraysMethods::set($this->subject, $key, $value);
115
    }
116
117
118
    /**
119 1
     * Check if the subject is empty.
120
     */
121 1
    public function isEmpty() : bool
122 1
    {
123
        return empty($this->subject);
124
    }
125
126
    /**
127
     * Replace the Subject while maintaining chain.
128
     *
129 1
     *
130
     */
131 1
    public function setSubject(mixed $value) : Repository
132
    {
133
        $this->subject = $value;
134
135
        return $this;
136
    }
137
138
    /**
139
     * Get the subject from the object.
140
     */
141 1
    public function obtain() : mixed
142
    {
143 1
        return $this->subject;
144
    }
145 1
146
    /**
147
     * Extend the class with a custom function.
148
     *
149
     * @param  string  $method  The macro's name
150
     * @param  Closure  $closure  The macro
151
     */
152
    public static function extend(string $method, Closure $closure) : void
153 13
    {
154
        static::$macros[static::class][$method] = $closure;
155 13
    }
156
157
    ////////////////////////////////////////////////////////////////////
158
    //////////////////////// METHODS DISPATCHING ///////////////////////
159
    ////////////////////////////////////////////////////////////////////
160
161
    /**
162
     * Catch aliases and reroute them to the right methods.
163
     *
164 2
     * @param $method
165
     * @param $parameters
166 2
     *
167 2
     * @return mixed
168
     */
169
    public static function __callStatic(string $method, $parameters)
170
    {
171
        // Get base class and methods class
172
        $callingClass = static::computeClassToCall(static::class, $method, $parameters);
173
        $methodsClass = Method::getMethodsFromType($callingClass);
174
175
        // Defer to Methods class
176
        if (method_exists($methodsClass, $method)) {
177
            return self::callMethod($methodsClass, $method, $parameters);
178
        }
179
180
        // Check for an alias
181 163
        $alias = Method::getAliasOf($method);
182
        if ($alias) {
183
            return self::callMethod($methodsClass, $alias, $parameters);
184 163
        }
185 163
186
        // Check for parsers
187
        if (method_exists(Parse::class, $method)) {
188 163
            return self::callMethod(Parse::class, $method, $parameters);
189 139
        }
190
191
        // Defered methods
192
        $defered = Dispatch::toNative($callingClass, $method);
193 33
        if ($defered) {
194 33
            return \call_user_func_array($defered, $parameters);
195 1
        }
196
197
        // Look in the macros
198
        $macro = ArraysMethods::get(static::$macros, $callingClass.'.'.$method);
199 32
        if ($macro) {
200 24
            return \call_user_func_array($macro, $parameters);
201
        }
202
203
        throw new BadMethodCallException('The method '.$callingClass.'::'.$method.' does not exist');
204 13
    }
205 13
206 9
    /**
207
     * Allow the chained calling of methods.
208
     *
209
     * @param $method
210 4
     * @param $arguments
211 4
     *
212 2
     * @return Repository
213
     */
214
    public function __call(string $method, $arguments)
215 2
    {
216
        // Get correct class
217
        $class = Dispatch::toClass($this->subject);
218
219
        // Check for unchainable methods
220
        if (Method::isUnchainable($class, $method)) {
221
            throw new BadMethodCallException('The method '.$class.'::'.$method." can't be chained");
222
        }
223
224
        // Prepend subject to arguments and call the method
225
        if ( ! Method::isSubjectless($method)) {
226 22
            array_unshift($arguments, $this->subject);
227
        }
228
229 22
        $result = $class::__callStatic($method, $arguments);
230
231
        // If the method is a breaker, return just the result
232 22
        if (Method::isBreaker($method)) {
233 1
            return $result;
234
        }
235
236
        $this->subject = $result;
237 22
238 22
        return $this;
239
    }
240 22
241
    ////////////////////////////////////////////////////////////////////
242
    ///////////////////////////// HELPERS //////////////////////////////
243 22
    ////////////////////////////////////////////////////////////////////
244 5
245
    /**
246
     * Tries to find the right class to call.
247 22
     *
248
     * @param  string  $callingClass  The original class
249 22
     * @param  string  $method  The method
250
     * @param array  $arguments    The arguments
251
     *
252
     * @return string The correct class
253
     */
254
    protected static function computeClassToCall(string $callingClass, string $method, ...$arguments) : string
255
    {
256
        if ( ! StringsMethods::find($callingClass, 'Underscore\Types')) {
257
            if (isset($arguments[0])) {
258
                $callingClass = Dispatch::toClass($arguments[0]);
259
            } else {
260
                $callingClass = Method::findInClasses($callingClass, $method);
261
            }
262
        }
263
264
        return $callingClass;
265 163
    }
266
267 163
    /**
268 3
     * Simpler version of call_user_func_array (for performances).
269 3
     *
270
     * @param string $class      The class
271
     * @param string $method     The method
272
     * @param array  $parameters The arguments
273
     */
274
    protected static function callMethod(string $class, string $method, array $parameters) : mixed
275
    {
276 163
        return match (\count($parameters)) {
277
            0 => $class::$method(),
278
            1 => $class::$method($parameters[0]),
279
            2 => $class::$method($parameters[0], $parameters[1]),
280
            3 => $class::$method($parameters[0], $parameters[1], $parameters[2]),
281
            4 => $class::$method($parameters[0], $parameters[1], $parameters[2], $parameters[3]),
282
            5 => $class::$method($parameters[0], $parameters[1], $parameters[2], $parameters[3], $parameters[4]),
283
            default => throw new RuntimeException('No appropriate method found'),
284
        };
285
    }
286
287
    /**
288 156
     * Get a default value for a new repository.
289
     */
290 156
    protected function getDefault() : mixed
291 156
    {
292
        return '';
293 156
    }
294
}
295