Completed
Pull Request — master (#24)
by
unknown
01:17
created

ClassIterator::attribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * This program is free software. It comes without any warranty, to
4
 * the extent permitted by applicable law. You can redistribute it
5
 * and/or modify it under the terms of the Do What The Fuck You Want
6
 * To Public License, Version 2, as published by Sam Hocevar. See
7
 * http://www.wtfpl.net/ for more details.
8
 */
9
10
declare(strict_types = 1);
11
12
namespace hanneskod\classtools\Iterator;
13
14
use Symfony\Component\Finder\Finder;
15
use hanneskod\classtools\Transformer\Writer;
16
use hanneskod\classtools\Transformer\MinimizingWriter;
17
use hanneskod\classtools\Iterator\Filter\CacheFilter;
18
use hanneskod\classtools\Iterator\Filter\NameFilter;
19
use hanneskod\classtools\Iterator\Filter\NamespaceFilter;
20
use hanneskod\classtools\Iterator\Filter\NotFilter;
21
use hanneskod\classtools\Iterator\Filter\TypeFilter;
22
use hanneskod\classtools\Iterator\Filter\WhereFilter;
23
use hanneskod\classtools\Iterator\Filter\AttributeFilter;
24
use hanneskod\classtools\Exception\LogicException;
25
use hanneskod\classtools\Loader\ClassLoader;
26
use hanneskod\classtools\Exception\ReaderException;
27
28
/**
29
 * Iterate over classes found in filesystem
30
 *
31
 * @author Hannes Forsgård <[email protected]>
32
 */
33
class ClassIterator implements ClassIteratorInterface
34
{
35
    /**
36
     * @var SplFileInfo[] Maps names to SplFileInfo objects
37
     */
38
    private $classMap = [];
39
40
    /**
41
     * @var string[]
42
     */
43
    private $errors = [];
44
45
    /**
46
     * @var ClassLoader
47
     */
48
    private $loader;
49
50
    /**
51
     * Scan filesystem for classes, interfaces and traits
52
     */
53
    public function __construct(Finder $finder = null)
54
    {
55
        /** @var \Symfony\Component\Finder\SplFileInfo $fileInfo */
56
        foreach (($finder ?: []) as $fileInfo) {
57
            $fileInfo = new SplFileInfo($fileInfo);
58
            try {
59
                foreach ($fileInfo->getReader()->getDefinitionNames() as $name) {
60
                    $this->classMap[$name] = $fileInfo;
61
                }
62
            } catch (ReaderException $exception) {
63
                $this->errors[] = $exception->getMessage();
64
            }
65
        }
66
    }
67
68
    /**
69
     * Enable garbage collection of the autoloader at destruct
70
     */
71
    public function __destruct()
72
    {
73
        $this->disableAutoloading();
74
    }
75
76
    public function getErrors(): array
77
    {
78
        return $this->errors;
79
    }
80
81
    public function getClassMap(): array
82
    {
83
        return $this->classMap;
84
    }
85
86
    public function enableAutoloading(): void
87
    {
88
        $this->loader = new ClassLoader($this, true);
89
    }
90
91
    public function disableAutoloading(): void
92
    {
93
        if (isset($this->loader)) {
94
            $this->loader->unregister();
95
            unset($this->loader);
96
        }
97
    }
98
99
    public function getIterator(): iterable
100
    {
101
        /** @var SplFileInfo $fileInfo */
102
        foreach ($this->getClassMap() as $name => $fileInfo) {
103
            try {
104
                yield $name => new \ReflectionClass($name);
105
            } catch (\ReflectionException $e) {
106
                $msg = "Unable to iterate, {$e->getMessage()}, is autoloading enabled?";
107
                throw new LogicException($msg, 0, $e);
108
            }
109
        }
110
    }
111
112
    public function filter(Filter $filter): Filter
113
    {
114
        $filter->bindTo($this);
115
        return $filter;
116
    }
117
118
    public function type(string $typename): Filter
119
    {
120
        return $this->filter(new TypeFilter($typename));
121
    }
122
123
    public function name(string $pattern): Filter
124
    {
125
        return $this->filter(new NameFilter($pattern));
126
    }
127
128
    public function inNamespace(string $namespace): Filter
129
    {
130
        return $this->filter(new NamespaceFilter($namespace));
131
    }
132
133
    public function where(string $methodName, $expectedReturn = true): Filter
134
    {
135
        return $this->filter(new WhereFilter($methodName, $expectedReturn));
136
    }
137
138
    public function not(Filter $filter): Filter
139
    {
140
        return $this->filter(new NotFilter($filter));
141
    }
142
143
    public function cache(): Filter
144
    {
145
        return $this->filter(new CacheFilter);
146
    }
147
148
    public function attribute(string $attribute_class_name): Filter
149
    {
150
        return $this->filter(new AttributeFilter($attribute_class_name));
151
    }
152
153
    public function transform(Writer $writer): string
154
    {
155
        $code = '';
156
157
        /** @var SplFileInfo $fileInfo */
158
        foreach ($this->getClassMap() as $name => $fileInfo) {
159
            $code .= $writer->write($fileInfo->getReader()->read($name)) . "\n";
160
        }
161
162
        return "<?php $code";
163
    }
164
165
    public function minimize(): string
166
    {
167
        return $this->transform(new MinimizingWriter);
168
    }
169
}
170