ClassFinder   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 57
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Test Coverage

Coverage 83.87%

Importance

Changes 0
Metric Value
wmc 19
lcom 0
cbo 0
dl 0
loc 57
ccs 26
cts 31
cp 0.8387
rs 10
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
D find() 0 48 19
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the class-finder package.
7
 *
8
 * (c) Gennady Knyazkin <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Redreams\ClassFinder;
15
16
/**
17
 * Class ClassFinder
18
 *
19
 * @author Gennady Knyazkin <[email protected]>
20
 */
21
class ClassFinder
22
{
23
    /**
24
     * Find class and return fully qualified name in the source
25
     *
26
     * @param string $source PHP source code
27
     * @return string|null Fully qualified class name if found, null otherwise
28
     */
29 1
    public static function find(string $source): ?string
30
    {
31 1
        $class = false;
32 1
        $namespace = false;
33 1
        $tokens = token_get_all($source);
34 1
        if (1 === count($tokens) && T_INLINE_HTML === $tokens[0][0]) {
35
            return null;
36
        }
37 1
        for ($i = 0; isset($tokens[$i]); ++$i) {
38 1
            $token = $tokens[$i];
39 1
            if (!isset($token[1])) {
40
                continue;
41
            }
42 1
            if (true === $class && T_STRING === $token[0]) {
43 1
                return $namespace.'\\'.$token[1];
44
            }
45 1
            if (true === $namespace && T_STRING === $token[0]) {
46 1
                $namespace = $token[1];
47 1
                while (isset($tokens[++$i][1]) && in_array($tokens[$i][0], [T_NS_SEPARATOR, T_STRING], true)) {
48
                    $namespace .= $tokens[$i][1];
49
                }
50 1
                $token = $tokens[$i];
51
            }
52 1
            if (T_CLASS === $token[0]) {
53
                // Skip usage of ::class constant and anonymous classes
54 1
                $skipClassToken = false;
55 1
                for ($j = $i - 1; $j > 0; --$j) {
56 1
                    if (!isset($tokens[$j][1])
57 1
                        || !in_array($tokens[$j][0], [T_WHITESPACE, T_DOC_COMMENT, T_COMMENT], true)
58
                    ) {
59 1
                        break;
60
                    }
61 1
                    if (T_DOUBLE_COLON === $tokens[$j][0] || T_NEW === $tokens[$j][0]) {
62
                        $skipClassToken = true;
63
                        break;
64
                    }
65
                }
66 1
                if (!$skipClassToken) {
67 1
                    $class = true;
68
                }
69
            }
70 1
            if (T_NAMESPACE === $token[0]) {
71 1
                $namespace = true;
72
            }
73
        }
74
75 1
        return null;
76
    }
77
}
78