Completed
Push — master ( ca4bb4...c297b8 )
by Iman
01:47
created

Facade::__callStatic()   A

Complexity

Conditions 3
Paths 5

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 3.0032

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 13
cts 14
cp 0.9286
rs 9.552
c 0
b 0
f 0
cc 3
nc 5
nop 2
crap 3.0032
1
<?php
2
3
namespace Imanghafoori\SmartFacades;
4
5
use TypeError;
6
use ReflectionMethod;
7
use RuntimeException;
8
use Illuminate\Support\Str;
9
use Illuminate\Support\Facades\Event;
10
use Illuminate\Support\Facades\Facade as LaravelFacade;
11
12
class Facade extends LaravelFacade
13
{
14 8
    protected static function getFacadeAccessor()
15
    {
16 8
        return static::class;
17
    }
18
19 8
    static function shouldProxyTo($class)
20
    {
21 8
        static::$app->singleton(self::getFacadeAccessor(), $class);
22 8
    }
23
24 3
    public static function preCall(string $method, $listener)
25
    {
26 3
        $listener = self::makeListener($method, $listener);
27
28 3
        Event::listen('calling: '. static::class.'@'. $method, $listener);
29 3
    }
30
31 2
    public static function postCall(string $method, $listener)
32
    {
33 2
        $listener = self::makeListener($method, $listener);
34
35 2
        Event::listen('called: '. static::class.'@'. $method, $listener);
36 2
    }
37
38
    /**
39
     * Handle dynamic, static calls to the object.
40
     *
41
     * @param string $method
42
     * @param array $args
43
     * @return mixed
44
     *
45
     * @throws \RuntimeException
46
     * @throws \ReflectionException
47
     */
48 8
    public static function __callStatic($method, $args)
49
    {
50 8
        $instance = static::getFacadeRoot();
51
52 8
        if (! $instance) {
53
            throw new RuntimeException('A facade root has not been set.');
54
        }
55
56
        try {
57 8
            event('calling: '. static::class.'@'. $method, [$method, $args]);
58 8
            $result =  $instance->$method(...$args);
59 7
            event('called: '. static::class.'@'. $method, [$method, $result]);
60
61 7
            return $result;
62 5
        } catch (TypeError $error) {
63 5
            $params = (new ReflectionMethod($instance, $method))->getParameters();
64 5
            self::addMissingDependencies($params, $args);
0 ignored issues
show
Documentation introduced by
$params is of type array<integer,object<ReflectionParameter>>, but the function expects a array<integer,object<Ima...s\ReflectionParameter>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
65 5
            $result = $instance->$method(...$args);
66 4
            event('called: '. static::class.'@'. $method, [$method, $result]);
67
68 4
            return $result;
69
        }
70
    }
71
72
    /**
73
     * Adds missing dependencies to the user-provided input.
74
     *
75
     * @param ReflectionParameter[] $parameters
76
     * @param array $inputData
77
     */
78 5
    private static function addMissingDependencies($parameters, array &$inputData)
79
    {
80 5
        foreach ($parameters as $i => $parameter) {
81
            // Injects missing type hinted parameters within the array
82 5
            $class = $parameter->getClass()->name ?? false;
83 5
            if ($class && ! ($inputData[$i] ?? false) instanceof $class) {
84 5
                array_splice($inputData, $i, 0, [self::$app[$class]]);
85 4
            } elseif (! array_key_exists($i, $inputData) && $parameter->isDefaultValueAvailable()) {
86 4
                $inputData[] = $parameter->getDefaultValue();
87
            }
88
        }
89 5
    }
90
91 3
    private static function makeListener(string $method, $listener)
92
    {
93 3
        if (Str::contains($method, '*')) {
94
            $listener = function ($_eventName, $methodAndArguments) use ($listener) {
95 1
                static::$app->call($listener, $methodAndArguments);
96 1
            };
97
        } else {
98
            $listener = function ($methodName, $args) use ($listener) {
99 1
                static::$app->call($listener, [
100 1
                    $methodName,
101 1
                    $args
102
                ]);
103 2
            };
104
        }
105
106 3
        return $listener;
107
    }
108
}
109