Passed
Push — main ( 16ab53...91f55c )
by Andrey
01:26
created

Instance::basename()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 2
rs 10
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
    /**
13
     * Checks if the item being checked inherits from other objects and interfaces.
14
     *
15
     * @param  object|string  $haystack
16
     * @param  string|string[]  $needles
17
     *
18
     * @return bool
19
     */
20 40
    public function of($haystack, $needles): bool
21
    {
22 40
        if (! $this->exists($haystack)) {
23 34
            return false;
24
        }
25
26 12
        $reflection = $this->resolve($haystack);
0 ignored issues
show
Bug introduced by
It seems like $haystack can also be of type string; however, parameter $class of Helldar\Support\Helpers\Instance::resolve() does only seem to accept ReflectionClass|object, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

26
        $reflection = $this->resolve(/** @scrutinizer ignore-type */ $haystack);
Loading history...
27 12
        $classname  = $this->classname($haystack);
28
29 12
        foreach (Arr::wrap($needles) as $needle) {
30 12
            if (! $this->exists($needle)) {
31 2
                continue;
32
            }
33
34
            if (
35 12
                $haystack instanceof $needle ||
36 4
                $classname === $this->classname($needle) ||
37 4
                $reflection->isSubclassOf($needle) ||
38 12
                ($reflection->isInterface() && $reflection->implementsInterface($needle))
39
            ) {
40 12
                return true;
41
            }
42
        }
43
44 6
        return false;
45
    }
46
47
    /**
48
     * Extract the trailing name component from a file path.
49
     *
50
     * @param  object|string  $class
51
     *
52
     * @return string|null
53
     */
54 2
    public function basename($class): ?string
55
    {
56 2
        $class = $this->classname($class);
57
58 2
        return basename(str_replace('\\', '/', $class)) ?: null;
59
    }
60
61
    /**
62
     * Gets the class name of the object.
63
     *
64
     * @param  object|string|null  $class
65
     *
66
     * @return string|null
67
     */
68 18
    public function classname($class = null): ?string
69
    {
70 18
        if (Is::object($class)) {
71 16
            return get_class($class);
0 ignored issues
show
Bug introduced by
It seems like $class can also be of type string; however, parameter $object of get_class() does only seem to accept object, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

71
            return get_class(/** @scrutinizer ignore-type */ $class);
Loading history...
72
        }
73
74 10
        return class_exists($class) || interface_exists($class) ? $class : null;
0 ignored issues
show
Bug introduced by
It seems like $class can also be of type object; however, parameter $class_name of class_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

74
        return class_exists(/** @scrutinizer ignore-type */ $class) || interface_exists($class) ? $class : null;
Loading history...
Bug introduced by
It seems like $class can also be of type object; however, parameter $interface_name of interface_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

74
        return class_exists($class) || interface_exists(/** @scrutinizer ignore-type */ $class) ? $class : null;
Loading history...
Bug Best Practice introduced by
The expression return class_exists($cla...$class) ? $class : null could return the type object which is incompatible with the type-hinted return null|string. Consider adding an additional type-check to rule them out.
Loading history...
75
    }
76
77
    /**
78
     * Checks if the object exists.
79
     *
80
     * @param  object|string  $haystack
81
     *
82
     * @return bool
83
     */
84 42
    public function exists($haystack): bool
85
    {
86 42
        if (Is::object($haystack)) {
87 14
            return true;
88
        }
89
90 42
        return Is::string($haystack) ? class_exists($haystack) || interface_exists($haystack) : false;
0 ignored issues
show
Bug introduced by
It seems like $haystack can also be of type object; however, parameter $class_name of class_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

90
        return Is::string($haystack) ? class_exists(/** @scrutinizer ignore-type */ $haystack) || interface_exists($haystack) : false;
Loading history...
Bug introduced by
It seems like $haystack can also be of type object; however, parameter $interface_name of interface_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

90
        return Is::string($haystack) ? class_exists($haystack) || interface_exists(/** @scrutinizer ignore-type */ $haystack) : false;
Loading history...
91
    }
92
93
    /**
94
     * Calls a method on an object.
95
     *
96
     * @param  object  $object
97
     * @param  string  $method
98
     * @param  null  $default
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $default is correct as it would always require null to be passed?
Loading history...
99
     *
100
     * @return false|mixed|null
101
     */
102 6
    public function call($object, string $method, $default = null)
103
    {
104 6
        if (Is::object($object) && method_exists($object, $method)) {
105 6
            return call_user_func([$object, $method]);
106
        }
107
108 4
        return $default;
109
    }
110
111
    /**
112
     * Calls the object's methods one by one and returns the first non-empty value.
113
     *
114
     * @param  object  $object
115
     * @param  string|string[]  $methods
116
     * @param  null  $default
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $default is correct as it would always require null to be passed?
Loading history...
117
     *
118
     * @return false|mixed|null
119
     */
120 2
    public function callWhen($object, $methods, $default = null)
121
    {
122 2
        foreach (Arr::wrap($methods) as $method) {
123 2
            if ($value = $this->call($object, $method)) {
124 2
                return $value;
125
            }
126
        }
127
128 2
        return $default;
129
    }
130
131
    /**
132
     * Calls a method of an object that matches a class.
133
     *
134
     * @param  array  $map
135
     * @param  object  $value
136
     * @param  null  $default
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $default is correct as it would always require null to be passed?
Loading history...
137
     *
138
     * @return false|mixed|null
139
     */
140 4
    public function callOf(array $map, $value, $default = null)
141
    {
142 4
        foreach ($map as $class => $method) {
143 4
            if (Is::object($value) && $this->of($value, $class)) {
144 2
                return $this->call($value, $method, $default);
145
            }
146
        }
147
148 4
        return $default;
149
    }
150
151
    /**
152
     * Creates a ReflectionClass object.
153
     *
154
     * @param  object|ReflectionClass  $class
155
     *
156
     * @return \ReflectionClass
157
     */
158 12
    protected function resolve($class): ReflectionClass
159
    {
160 12
        return Reflection::resolve($class);
161
    }
162
}
163