Failed Conditions
Pull Request — 2.8.x (#7946)
by
unknown
10:03
created

ConvertDoctrine1Schema::convertColumn()   F

Complexity

Conditions 16
Paths 3872

Size

Total Lines 79
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 19.2215

Importance

Changes 0
Metric Value
cc 16
eloc 43
nc 3872
nop 4
dl 0
loc 79
rs 1.4
c 0
b 0
f 0
ccs 33
cts 43
cp 0.7674
crap 19.2215

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ORM\Tools;
21
22
use Doctrine\ORM\Mapping\ClassMetadataInfo;
23
use Doctrine\Common\Inflector\Inflector;
24
use Doctrine\DBAL\Types\Type;
25
use Symfony\Component\Yaml\Yaml;
26
27
/**
28
 * Class to help with converting Doctrine 1 schema files to Doctrine 2 mapping files
29
 *
30
 *
31
 * @link    www.doctrine-project.org
32
 * @since   2.0
33
 * @author  Guilherme Blanco <[email protected]>
34
 * @author  Jonathan Wage <[email protected]>
35
 * @author  Roman Borschel <[email protected]>
36
 */
37
class ConvertDoctrine1Schema
38
{
39
    /**
40
     * @var array
41
     */
42
    private $from;
43
44
    /**
45
     * @var array
46
     */
47
    private $legacyTypeMap = [
48
        // TODO: This list may need to be updated
49
        'clob' => 'text',
50
        'timestamp' => 'datetime',
51
        'enum' => 'string'
52
    ];
53
54
    /**
55
     * Constructor passes the directory or array of directories
56
     * to convert the Doctrine 1 schema files from.
57
     *
58
     * @param array $from
59
     *
60
     * @author Jonathan Wage
61
     */
62 2
    public function __construct($from)
63
    {
64 2
        $this->from = (array) $from;
65 2
    }
66
67
    /**
68
     * Gets an array of ClassMetadataInfo instances from the passed
69
     * Doctrine 1 schema.
70
     *
71
     * @return array An array of ClassMetadataInfo instances
72
     */
73 2
    public function getMetadata()
74
    {
75 2
        $schema = [];
76 2
        foreach ($this->from as $path) {
77 1
            if (is_dir($path)) {
78 1
                $files = glob($path . '/*.yml');
79 1
                foreach ($files as $file) {
80 1
                    $schema = array_merge($schema, (array) Yaml::parse(file_get_contents($file)));
81
                }
82
            } else {
83
                $schema = array_merge($schema, (array) Yaml::parse(file_get_contents($path)));
84
            }
85
        }
86
87 2
        $metadatas = [];
88 2
        foreach ($schema as $className => $mappingInformation) {
89 1
            $metadatas[] = $this->convertToClassMetadataInfo($className, $mappingInformation);
90
        }
91
92 2
        return $metadatas;
93
    }
94
95
    /**
96
     * @param string $className
97
     * @param array  $mappingInformation
98
     *
99
     * @return \Doctrine\ORM\Mapping\ClassMetadataInfo
100
     */
101 1
    private function convertToClassMetadataInfo($className, $mappingInformation)
102
    {
103 1
        $metadata = new ClassMetadataInfo($className);
104
105 1
        $this->convertTableName($className, $mappingInformation, $metadata);
106 1
        $this->convertColumns($className, $mappingInformation, $metadata);
107 1
        $this->convertIndexes($className, $mappingInformation, $metadata);
108 1
        $this->convertRelations($className, $mappingInformation, $metadata);
109
110 1
        return $metadata;
111
    }
112
113
    /**
114
     * @param string            $className
115
     * @param array             $model
116
     * @param ClassMetadataInfo $metadata
117
     *
118
     * @return void
119
     */
120 1
    private function convertTableName($className, array $model, ClassMetadataInfo $metadata)
121
    {
122 1
        if (isset($model['tableName']) && $model['tableName']) {
123 1
            $e = explode('.', $model['tableName']);
124
125 1
            if (count($e) > 1) {
126
                $metadata->table['schema'] = $e[0];
127
                $metadata->table['name'] = $e[1];
128
            } else {
129 1
                $metadata->table['name'] = $e[0];
130
            }
131
        }
132 1
    }
133
134
    /**
135
     * @param string            $className
136
     * @param array             $model
137
     * @param ClassMetadataInfo $metadata
138
     *
139
     * @return void
140
     */
141 1
    private function convertColumns($className, array $model, ClassMetadataInfo $metadata)
142
    {
143 1
        $id = false;
144
145 1
        if (isset($model['columns']) && $model['columns']) {
146 1
            foreach ($model['columns'] as $name => $column) {
147 1
                $fieldMapping = $this->convertColumn($className, $name, $column, $metadata);
148
149 1
                if (isset($fieldMapping['id']) && $fieldMapping['id']) {
150
                    $id = true;
151
                }
152
            }
153
        }
154
155 1
        if ( ! $id) {
156
            $fieldMapping = [
157 1
                'fieldName' => 'id',
158
                'columnName' => 'id',
159
                'type' => 'integer',
160
                'id' => true
161
            ];
162 1
            $metadata->mapField($fieldMapping);
163 1
            $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
164
        }
165 1
    }
166
167
    /**
168
     * @param string            $className
169
     * @param string            $name
170
     * @param string|array      $column
171
     * @param ClassMetadataInfo $metadata
172
     *
173
     * @return array
174
     *
175
     * @throws ToolsException
176
     */
177 1
    private function convertColumn($className, $name, $column, ClassMetadataInfo $metadata)
178
    {
179 1
        if (is_string($column)) {
180 1
            $string = $column;
181 1
            $column = [];
182 1
            $column['type'] = $string;
183
        }
184
185 1
        if ( ! isset($column['name'])) {
186 1
            $column['name'] = $name;
187
        }
188
189
        // check if a column alias was used (column_name as field_name)
190 1
        if (preg_match("/(\w+)\sas\s(\w+)/i", $column['name'], $matches)) {
191 1
            $name = $matches[1];
192 1
            $column['name'] = $name;
193 1
            $column['alias'] = $matches[2];
194
        }
195
196 1
        if (preg_match("/([a-zA-Z]+)\(([0-9]+)\)/", $column['type'], $matches)) {
197 1
            $column['type'] = $matches[1];
198 1
            $column['length'] = $matches[2];
199
        }
200
201 1
        $column['type'] = strtolower($column['type']);
202
        // check if legacy column type (1.x) needs to be mapped to a 2.0 one
203 1
        if (isset($this->legacyTypeMap[$column['type']])) {
204 1
            $column['type'] = $this->legacyTypeMap[$column['type']];
205
        }
206
207 1
        if ( ! Type::hasType($column['type'])) {
208
            throw ToolsException::couldNotMapDoctrine1Type($column['type']);
209
        }
210
211 1
        $fieldMapping = [];
212
213 1
        if (isset($column['primary'])) {
214
            $fieldMapping['id'] = true;
215
        }
216
217 1
        $fieldMapping['fieldName'] = $column['alias'] ?? $name;
218 1
        $fieldMapping['columnName'] = $column['name'];
219 1
        $fieldMapping['type'] = $column['type'];
220
221 1
        if (isset($column['length'])) {
222 1
            $fieldMapping['length'] = $column['length'];
223
        }
224
225 1
        $allowed = ['precision', 'scale', 'unique', 'options', 'notnull', 'version'];
226
227 1
        foreach ($column as $key => $value) {
228 1
            if (in_array($key, $allowed)) {
229 1
                $fieldMapping[$key] = $value;
230
            }
231
        }
232
233 1
        $metadata->mapField($fieldMapping);
234
235 1
        if (isset($column['autoincrement'])) {
236
            $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
237 1
        } elseif (isset($column['sequence'])) {
238
            $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE);
239
240
            $definition = [
241
                'sequenceName' => is_array($column['sequence']) ? $column['sequence']['name']:$column['sequence']
242
            ];
243
244
            if (isset($column['sequence']['size'])) {
245
                $definition['allocationSize'] = $column['sequence']['size'];
246
            }
247
248
            if (isset($column['sequence']['value'])) {
249
                $definition['initialValue'] = $column['sequence']['value'];
250
            }
251
252
            $metadata->setSequenceGeneratorDefinition($definition);
253
        }
254
255 1
        return $fieldMapping;
256
    }
257
258
    /**
259
     * @param string            $className
260
     * @param array             $model
261
     * @param ClassMetadataInfo $metadata
262
     *
263
     * @return void
264
     */
265 1
    private function convertIndexes($className, array $model, ClassMetadataInfo $metadata)
266
    {
267 1
        if (empty($model['indexes'])) {
268 1
            return;
269
        }
270
271 1
        foreach ($model['indexes'] as $name => $index) {
272 1
            $type = (isset($index['type']) && $index['type'] == 'unique')
273 1
                ? 'uniqueConstraints' : 'indexes';
274
275 1
            $metadata->table[$type][$name] = [
276 1
                'columns' => $index['fields']
277
            ];
278
        }
279 1
    }
280
281
    /**
282
     * @param string            $className
283
     * @param array             $model
284
     * @param ClassMetadataInfo $metadata
285
     *
286
     * @return void
287
     */
288 1
    private function convertRelations($className, array $model, ClassMetadataInfo $metadata)
289
    {
290 1
        if (empty($model['relations'])) {
291 1
            return;
292
        }
293
294 1
        foreach ($model['relations'] as $name => $relation) {
295 1
            if ( ! isset($relation['alias'])) {
296 1
                $relation['alias'] = $name;
297
            }
298 1
            if ( ! isset($relation['class'])) {
299 1
                $relation['class'] = $name;
300
            }
301 1
            if ( ! isset($relation['local'])) {
302 1
                $relation['local'] = Inflector::tableize($relation['class']);
303
            }
304 1
            if ( ! isset($relation['foreign'])) {
305 1
                $relation['foreign'] = 'id';
306
            }
307 1
            if ( ! isset($relation['foreignAlias'])) {
308 1
                $relation['foreignAlias'] = $className;
309
            }
310
311 1
            if (isset($relation['refClass'])) {
312
                $type = 'many';
313
                $foreignType = 'many';
314
                $joinColumns = [];
315
            } else {
316 1
                $type = $relation['type'] ?? 'one';
317 1
                $foreignType = $relation['foreignType'] ?? 'many';
318
                $joinColumns = [
319
                    [
320 1
                        'name' => $relation['local'],
321 1
                        'referencedColumnName' => $relation['foreign'],
322 1
                        'onDelete' => $relation['onDelete'] ?? null,
323
                    ]
324
                ];
325
            }
326
327 1
            if ($type == 'one' && $foreignType == 'one') {
328 1
                $method = 'mapOneToOne';
329
            } elseif ($type == 'many' && $foreignType == 'many') {
330
                $method = 'mapManyToMany';
331
            } else {
332
                $method = 'mapOneToMany';
333
            }
334
335 1
            $associationMapping = [];
336 1
            $associationMapping['fieldName'] = $relation['alias'];
337 1
            $associationMapping['targetEntity'] = $relation['class'];
338 1
            $associationMapping['mappedBy'] = $relation['foreignAlias'];
339 1
            $associationMapping['joinColumns'] = $joinColumns;
340
341 1
            $metadata->$method($associationMapping);
342
        }
343 1
    }
344
}
345