Instance::of()   B
last analyzed

Complexity

Conditions 10
Paths 5

Size

Total Lines 26
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 10

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 15
c 1
b 0
f 0
nc 5
nop 2
dl 0
loc 26
ccs 15
cts 15
cp 1
crap 10
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * This file is part of the "andrey-helldar/support" project.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author Andrey Helldar <[email protected]>
9
 *
10
 * @copyright 2021 Andrey Helldar
11
 *
12
 * @license MIT
13
 *
14
 * @see https://github.com/andrey-helldar/support
15
 */
16
17
namespace Helldar\Support\Helpers;
18
19
use Helldar\Support\Facades\Helpers\Arr as ArrHelper;
20
use Helldar\Support\Facades\Helpers\Is as IsHelper;
21
use Helldar\Support\Facades\Helpers\Reflection as ReflectionHelper;
22
use ReflectionClass;
23
24
class Instance
25
{
26
    /**
27
     * Checks if the item being checked inherits from other objects and interfaces.
28
     *
29
     * @param  object|string  $haystack
30
     * @param  string|string[]  $needles
31
     *
32
     * @return bool
33
     */
34 134
    public function of($haystack, $needles): bool
35
    {
36 134
        if (! $this->exists($haystack)) {
37 122
            return false;
38
        }
39
40 36
        $reflection = $this->resolve($haystack);
41 36
        $classname  = $this->classname($haystack);
42
43 36
        foreach (ArrHelper::wrap($needles) as $needle) {
44 36
            if (! $this->exists($needle)) {
45 2
                continue;
46
            }
47
48
            if (
49 36
                $haystack instanceof $needle ||
50 30
                $classname === $this->classname($needle) ||
51 30
                $reflection->isSubclassOf($needle) ||
52 30
                ($reflection->isInterface() && $reflection->implementsInterface($needle)) ||
53 36
                in_array($needle, $reflection->getTraitNames(), true)
54
            ) {
55 14
                return true;
56
            }
57
        }
58
59 30
        return false;
60
    }
61
62
    /**
63
     * Extract the trailing name component from a file path.
64
     *
65
     * @param  object|string  $class
66
     *
67
     * @return string|null
68
     */
69 2
    public function basename($class): ?string
70
    {
71 2
        $class = $this->classname($class);
72
73 2
        return basename(str_replace('\\', '/', $class)) ?: null;
74
    }
75
76
    /**
77
     * Gets the class name of the object.
78
     *
79
     * @param  object|string|null  $class
80
     *
81
     * @return string|null
82
     */
83 42
    public function classname($class = null): ?string
84
    {
85 42
        if (IsHelper::object($class)) {
86 40
            return get_class($class);
0 ignored issues
show
Bug introduced by
It seems like $class can also be of type null and 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

86
            return get_class(/** @scrutinizer ignore-type */ $class);
Loading history...
87
        }
88
89 36
        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 null and object; however, parameter $interface 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

89
        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...
Bug introduced by
It seems like $class can also be of type null and object; however, parameter $class 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

89
        return class_exists(/** @scrutinizer ignore-type */ $class) || interface_exists($class) ? $class : null;
Loading history...
90
    }
91
92
    /**
93
     * Checks if the object exists.
94
     *
95
     * @param  object|string  $haystack
96
     *
97
     * @return bool
98
     */
99 136
    public function exists($haystack): bool
100
    {
101 136
        if (IsHelper::object($haystack)) {
102 38
            return true;
103
        }
104
105 136
        return IsHelper::string($haystack) && (class_exists($haystack) || interface_exists($haystack) || trait_exists($haystack));
0 ignored issues
show
Bug introduced by
It seems like $haystack can also be of type object; however, parameter $class 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

105
        return IsHelper::string($haystack) && (class_exists(/** @scrutinizer ignore-type */ $haystack) || interface_exists($haystack) || trait_exists($haystack));
Loading history...
Bug introduced by
It seems like $haystack can also be of type object; however, parameter $interface 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

105
        return IsHelper::string($haystack) && (class_exists($haystack) || interface_exists(/** @scrutinizer ignore-type */ $haystack) || trait_exists($haystack));
Loading history...
Bug introduced by
It seems like $haystack can also be of type object; however, parameter $trait of trait_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

105
        return IsHelper::string($haystack) && (class_exists($haystack) || interface_exists($haystack) || trait_exists(/** @scrutinizer ignore-type */ $haystack));
Loading history...
106
    }
107
108
    /**
109
     * Creates a ReflectionClass object.
110
     *
111
     * @param  object|ReflectionClass|string  $class
112
     *
113
     * @return \ReflectionClass
114
     */
115 36
    protected function resolve($class): ReflectionClass
116
    {
117 36
        return ReflectionHelper::resolve($class);
118
    }
119
}
120