Passed
Pull Request — main (#22)
by Andrey
20:42 queued 05:40
created

Instance::of()   B

Complexity

Conditions 9
Paths 5

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 14
c 1
b 0
f 0
nc 5
nop 2
dl 0
loc 25
rs 8.0555
1
<?php
2
3
namespace Helldar\Support\Helpers;
4
5
use Helldar\Support\Facades\Helpers\Arr;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Helldar\Support\Helpers\Arr. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
use Helldar\Support\Facades\Helpers\Is;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Helldar\Support\Helpers\Is. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
7
use Helldar\Support\Facades\Helpers\Reflection;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Helldar\Support\Helpers\Reflection. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
8
use ReflectionClass;
9
10
final class Instance
11
{
12
    public function of($haystack, $needles): bool
13
    {
14
        if (! $this->exists($haystack)) {
15
            return false;
16
        }
17
18
        $reflection = $this->resolve($haystack);
19
        $classname  = $this->classname($haystack);
20
21
        foreach (Arr::wrap($needles) as $needle) {
22
            if (! $this->exists($needle)) {
23
                continue;
24
            }
25
26
            if (
27
                $haystack instanceof $needle ||
28
                $classname === $this->classname($needle) ||
29
                $reflection->isSubclassOf($needle) ||
30
                ($reflection->isInterface() && $reflection->implementsInterface($needle))
31
            ) {
32
                return true;
33
            }
34
        }
35
36
        return false;
37
    }
38
39
    public function basename($class): ?string
40
    {
41
        $class = $this->classname($class);
42
43
        return basename(str_replace('\\', '/', $class)) ?: null;
44
    }
45
46
    public function classname($class = null): ?string
47
    {
48
        if (Is::object($class)) {
49
            return get_class($class);
50
        }
51
52
        return class_exists($class) || interface_exists($class) ? $class : null;
53
    }
54
55
    public function exists($haystack): bool
56
    {
57
        if (Is::object($haystack)) {
58
            return true;
59
        }
60
61
        if (Is::string($haystack)) {
62
            return class_exists($haystack) || interface_exists($haystack);
63
        }
64
65
        return false;
66
    }
67
68
    public function call($object, string $method, $default = null)
69
    {
70
        if (Is::object($object) && method_exists($object, $method)) {
71
            return call_user_func([$object, $method]);
72
        }
73
74
        return $default;
75
    }
76
77
    public function callWhen($object, $methods, $default = null)
78
    {
79
        foreach (Arr::wrap($methods) as $method) {
80
            if ($value = $this->call($object, $method)) {
81
                return $value;
82
            }
83
        }
84
85
        return $default;
86
    }
87
88
    public function callOf(array $map, $value, $default = null)
89
    {
90
        foreach ($map as $class => $method) {
91
            if (Is::object($value) && $this->of($value, $class)) {
92
                return $this->call($value, $method, $default);
93
            }
94
        }
95
96
        return $default;
97
    }
98
99
    protected function resolve($class): ReflectionClass
100
    {
101
        return Reflection::resolve($class);
102
    }
103
}
104