Passed
Pull Request — master (#593)
by butschster
05:58
created

Tokenizer::scopedClassLocator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Tokenizer;
13
14
use Spiral\Core\Container\InjectorInterface;
15
use Spiral\Core\Container\SingletonInterface;
16
use Spiral\Core\Exception\Container\InjectionException;
17
use Spiral\Tokenizer\Config\TokenizerConfig;
18
use Symfony\Component\Finder\Finder;
19
20
/**
21
 * Manages automatic container injections of class and invocation locators.
22
 */
23
final class Tokenizer implements SingletonInterface, InjectorInterface
24
{
25
    /**
26
     * Token array constants.
27
     */
28
    public const TYPE = 0;
29
    public const CODE = 1;
30
    public const LINE = 2;
31
32
    /** @var TokenizerConfig */
33
    protected $config;
34
35
    /**
36
     * Tokenizer constructor.
37
     */
38
    public function __construct(TokenizerConfig $config)
39
    {
40
        $this->config = $config;
41
    }
42
43
    /**
44
     * Get pre-configured class locator for specific scope.
45
     */
46
    public function scopedClassLocator(string $scope): ClassesInterface
47
    {
48
        $dirs = $this->config->getScope($scope);
49
50
        return $this->classLocator($dirs['directories'], $dirs['exclude']);
51
    }
52
53
    /**
54
     * Get pre-configured class locator.
55
     */
56
    public function classLocator(
57
        array $directories = [],
58
        array $exclude = []
59
    ): ClassesInterface {
60
        return new ClassLocator($this->makeFinder($directories, $exclude));
61
    }
62
63
    /**
64
     * Get pre-configured invocation locator.
65
     */
66
    public function invocationLocator(
67
        array $directories = [],
68
        array $exclude = []
69
    ): InvocationsInterface {
70
        return new InvocationLocator($this->makeFinder($directories, $exclude));
71
    }
72
73
    /**
74
     * {@inheritdoc}
75
     *
76
     * @throws InjectionException
77
     */
78
    public function createInjection(\ReflectionClass $class, string $context = null)
79
    {
80
        if ($class->isSubclassOf(ClassesInterface::class)) {
81
            return $this->classLocator();
82
        } elseif ($class->isSubclassOf(InvocationsInterface::class)) {
83
            return $this->invocationLocator();
84
        }
85
86
        throw new InjectionException("Unable to create injection for {$class}");
87
    }
88
89
    /**
90
     * Get all tokes for specific file.
91
     */
92
    public static function getTokens(string $filename): array
93
    {
94
        $tokens = token_get_all(file_get_contents($filename));
95
96
        $line = 0;
97
        foreach ($tokens as &$token) {
98
            if (isset($token[self::LINE])) {
99
                $line = $token[self::LINE];
100
            }
101
102
            if (!is_array($token)) {
103
                $token = [$token, $token, $line];
104
            }
105
106
            unset($token);
107
        }
108
109
        return $tokens;
110
    }
111
112
    /**
113
     * @param array $directories Overwrites default config values.
114
     * @param array $exclude     Overwrites default config values.
115
     */
116
    private function makeFinder(array $directories = [], array $exclude = []): Finder
117
    {
118
        $finder = new Finder();
119
120
        if (empty($directories)) {
121
            $directories = $this->config->getDirectories();
122
        }
123
124
        if (empty($exclude)) {
125
            $exclude = $this->config->getExcludes();
126
        }
127
128
        return $finder->files()->in($directories)->exclude($exclude)->name('*.php');
129
    }
130
}
131