Completed
Pull Request — 1.1 (#41)
by
unknown
04:23
created

FluentDriver::__construct()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.072

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 8
cts 10
cp 0.8
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 4
nop 2
crap 3.072
1
<?php
2
3
namespace LaravelDoctrine\Fluent;
4
5
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
6
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
7
use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder;
8
use Doctrine\ORM\Mapping\MappingException;
9
use InvalidArgumentException;
10
use LaravelDoctrine\Fluent\Builders\Builder;
11
use LaravelDoctrine\Fluent\Mappers\MapperSet;
12
13
class FluentDriver implements MappingDriver
14
{
15
    /**
16
     * @var MapperSet
17
     */
18
    protected $mappers;
19
20
    /**
21
     * @var callable
22
     */
23
    protected $fluentFactory;
24
25
    /**
26
     * Initializes a new FileDriver that looks in the given path(s) for mapping
27
     * documents and operates in the specified operating mode.
28
     *
29
     * @param string[]|null $mappings
30
     * @param string[]|null $paths
31
     *
32
     * @throws \Doctrine\ORM\Mapping\MappingException
33
     */
34
    public function __construct($mappings = null, $paths = null)
35
    {
36 4
        $this->fluentFactory = function (ClassMetadata $metadata) {
37 4
            return new Builder(new ClassMetadataBuilder($metadata));
38
        };
39
40 92
        $this->mappers = new MapperSet();
41
42 92
        if ($mappings !== null) {
43 79
            $this->addMappings($mappings);
44 79
        }
45
46 92
        if ($paths !== null) {
47
            $this->addPaths($paths);
48
        }
49 92
    }
50
51
    /**
52
     * Loads the metadata for the specified class into the provided container.
53
     *
54
     * @param string        $className
55
     * @param ClassMetadata $metadata
56
     */
57 6
    public function loadMetadataForClass($className, ClassMetadata $metadata)
58
    {
59 6
        $this->mappers->getMapperFor($className)->map(
60 5
            $this->getFluent($metadata)
61 5
        );
62 5
    }
63
64
    /**
65
     * Gets the names of all mapped classes known to this driver.
66
     *
67
     * @throws MappingException
68
     *
69
     * @return string[] The names of all mapped classes known to this driver.
70
     */
71 12
    public function getAllClassNames()
72
    {
73 12
        return $this->mappers->getClassNames();
74
    }
75
76
    /**
77
     * Returns whether the class with the specified name should have its metadata loaded.
78
     * This is only the case if it is either mapped as an Entity or a MappedSuperclass.
79
     *
80
     * @param string $className
81
     *
82
     * @return bool
83
     */
84 4
    public function isTransient($className)
85
    {
86
        return
87 4
            !$this->mappers->hasMapperFor($className) ||
88 4
            $this->mappers->getMapperFor($className)->isTransient();
89
    }
90
91
    /**
92
     * @param string[] $mappings
93
     */
94 82
    public function addMappings(array $mappings = [])
95
    {
96 82
        foreach ($mappings as $class) {
97 82
            if (!class_exists($class)) {
98 1
                throw new InvalidArgumentException("Mapping class [{$class}] does not exist");
99
            }
100
101 81
            $mapping = new $class();
102
103 81
            if (!$mapping instanceof Mapping) {
104 1
                throw new InvalidArgumentException("Mapping class [{$class}] should implement ".Mapping::class);
105
            }
106
107 80
            $this->addMapping($mapping);
108 80
        }
109 80
    }
110
111
    /**
112
     * @param Mapping $mapping
113
     *
114
     * @throws MappingException
115
     */
116 87
    public function addMapping(Mapping $mapping)
117
    {
118 87
        $this->mappers->add($mapping);
119 87
    }
120
121
    /**
122
     * @return MapperSet
123
     */
124 5
    public function getMappers()
125
    {
126 5
        return $this->mappers;
127
    }
128
129
    /**
130
     * Add mappings from an array of folders.
131
     *
132
     * @param string[] $paths
133
     *
134
     * @throws MappingException
135
     */
136
    public function addPaths($paths)
137
    {
138
        $includedFiles = [];
139
        foreach ($paths as $path) {
140
            if (!is_dir($path)) {
141
                throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
142
            }
143
144
            $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path), \RecursiveIteratorIterator::LEAVES_ONLY);
145
146
            foreach ($iterator as $file) {
147
                if ($file->getBasename('.php') == $file->getBasename()) {
148
                    continue;
149
                }
150
151
                $sourceFile = realpath($file->getPathName());
152
                require_once $sourceFile;
153
                $includedFiles[] = $sourceFile;
154
            }
155
        }
156
157
        $declared = get_declared_classes();
158
159
        foreach ($declared as $className) {
160
            $rc = new \ReflectionClass($className);
161
            $sourceFile = $rc->getFileName();
162
            if (in_array($sourceFile, $includedFiles) && !$this->mappers->hasMapperFor($className)) {
163
                $this->addMapping(new $className());
164
            }
165
        }
166
    }
167
168
    /**
169
     * Override the default Fluent factory method with a custom one.
170
     * Use this to implement your own Fluent builder.
171
     * The method will receive a ClassMetadata object as its only argument.
172
     *
173
     * @param callable $factory
174
     */
175 1
    public function setFluentFactory(callable $factory)
176
    {
177 1
        $this->fluentFactory = $factory;
178 1
    }
179
180
    /**
181
     * @param ClassMetadata $metadata
182
     *
183
     * @return Fluent
184
     */
185 5
    protected function getFluent(ClassMetadata $metadata)
186
    {
187 5
        return call_user_func($this->fluentFactory, $metadata);
188
    }
189
}
190