ClassUtils::usesTrait()   B
last analyzed

Complexity

Conditions 5
Paths 8

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 10
cts 10
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 10
nc 8
nop 3
crap 5
1
<?php
2
/*
3
 * This file is part of the  TraitorBundle, an RunOpenCode project.
4
 *
5
 * (c) 2017 RunOpenCode
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace RunOpenCode\Bundle\Traitor\Utils;
11
12
use RunOpenCode\Bundle\Traitor\Exception\InvalidArgumentException;
13
use RunOpenCode\Bundle\Traitor\Exception\RuntimeException;
14
15
/**
16
 * Class ClassUtils
17
 *
18
 * @package RunOpenCode\Bundle\Traitor\Utils
19
 */
20
final class ClassUtils
21
{
22
    final private function __construct() { /** noop */ }
0 ignored issues
show
Coding Style introduced by
Unnecessary FINAL modifier in FINAL class
Loading history...
23
24
    /**
25
     * Check if class uses trait.
26
     *
27
     * @param object|string $objectOrClass Instance of class or FQCN
28
     * @param string $trait FQCN trait
29
     * @param bool $autoload Weather to autoload class.
30
     *
31
     * @return bool TRUE if class uses trait.
32
     *
33
     * @throws \RunOpenCode\Bundle\Traitor\Exception\InvalidArgumentException
34
     * @throws \RunOpenCode\Bundle\Traitor\Exception\RuntimeException
35
     */
36 12
    public static function usesTrait($objectOrClass, $trait, $autoload = true)
37
    {
38 12
        if (is_object($objectOrClass)) {
39 1
            $objectOrClass = get_class($objectOrClass);
40
        }
41
42 12
        if (!is_string($objectOrClass)) {
43 1
            throw new InvalidArgumentException(sprintf('Full qualified class name expected, got: "%s".', gettype($objectOrClass)));
44
        }
45
46 11
        if (!class_exists($objectOrClass)) {
47 1
            throw new RuntimeException(sprintf('Class "%s" does not exists or it can not be autoloaded.', $objectOrClass));
48
        }
49
50 10
        if (in_array(ltrim($trait, '\\'), self::getTraits($objectOrClass, $autoload), false)) {
51 9
            return true;
52
        }
53
54 10
        return false;
55
    }
56
57
    /**
58
     * Get ALL traits used by one class.
59
     *
60
     * @param object|string $objectOrClass Instance of class or FQCN
61
     * @param bool $autoload Weather to autoload class.
62
     *
63
     * @throws \RunOpenCode\Bundle\Traitor\Exception\InvalidArgumentException
64
     * @throws \RunOpenCode\Bundle\Traitor\Exception\RuntimeException
65
     *
66
     * @return array Used traits.
67
     */
68 13
    public static function getTraits($objectOrClass, $autoload = true)
69
    {
70 13
        if (is_object($objectOrClass)) {
71 1
            $objectOrClass = get_class($objectOrClass);
72
        }
73
74 13
        if (!is_string($objectOrClass)) {
75 1
            throw new InvalidArgumentException(sprintf('Full qualified class name expected, got: "%s".', gettype($objectOrClass)));
76
        }
77
78 12
        if (!class_exists($objectOrClass)) {
79 1
            throw new RuntimeException(sprintf('Class "%s" does not exists or it can not be autoloaded.', $objectOrClass));
80
        }
81
82 11
        $traits = [];
83
84
        // Get traits of all parent classes
85
        do {
86 11
            $traits = array_merge(class_uses($objectOrClass, $autoload), $traits);
87 11
        } while ($objectOrClass = get_parent_class($objectOrClass));
88
89
        // Get traits of all parent traits
90 11
        $traitsToSearch = $traits;
91
92 11
        while (count($traitsToSearch) > 0) {
93 11
            $newTraits = class_uses(array_pop($traitsToSearch), $autoload);
94 11
            $traits = array_merge($newTraits, $traits);
95 11
            $traitsToSearch = array_merge($newTraits, $traitsToSearch);
96
        }
97
98 11
        foreach ($traits as $trait => $same) {
99 11
            $traits = array_merge(class_uses($trait, $autoload), $traits);
100
        }
101
102 11
        return array_unique(array_map(function ($fqcn) {
103 11
            return ltrim($fqcn, '\\');
104 11
        }, $traits));
105
    }
106
107
    /**
108
     * Check if class is within certain namespace.
109
     *
110
     * @param string|object $objectOrClass Class to check.
111
     * @param string $namespacePrefix Namespace prefix
112
     *
113
     * @return bool
114
     *
115
     * @throws \RunOpenCode\Bundle\Traitor\Exception\InvalidArgumentException
116
     * @throws \RunOpenCode\Bundle\Traitor\Exception\RuntimeException
117
     */
118 5
    public static function isWithinNamespace($objectOrClass, $namespacePrefix)
119
    {
120 5
        if (is_object($objectOrClass)) {
121 1
            $objectOrClass = get_class($objectOrClass);
122
        }
123
124 5
        if (!is_string($objectOrClass)) {
125 1
            throw new InvalidArgumentException(sprintf('Full qualified class name string expected, got: "%s".', gettype($objectOrClass)));
126
        }
127
128 4
        if (!class_exists($objectOrClass)) {
129 1
            throw new RuntimeException(sprintf('Class "%s" does not exists or it can not be autoloaded.', $objectOrClass));
130
        }
131
132 3
        $objectOrClass = ltrim($objectOrClass, '\\');
133 3
        $namespacePrefix = rtrim(ltrim($namespacePrefix, '\\'), '\\').'\\';
134
135 3
        return strpos($objectOrClass, $namespacePrefix) === 0;
136
    }
137
}
138