Failed Conditions
Pull Request — develop (#1577)
by Marco
66:01
created

PhpExporter::varExport()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 0
cts 0
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 10
nc 1
nop 1
crap 2
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\Export\Driver;
21
22
use Doctrine\ORM\Mapping\AssociationMetadata;
23
use Doctrine\ORM\Mapping\ClassMetadata;
24
use Doctrine\ORM\Mapping\FieldMetadata;
25
use Doctrine\ORM\Mapping\JoinColumnMetadata;
26
use Doctrine\ORM\Mapping\JoinTableMetadata;
27
use Doctrine\ORM\Mapping\ManyToManyAssociationMetadata;
28
use Doctrine\ORM\Mapping\ManyToOneAssociationMetadata;
29
use Doctrine\ORM\Mapping\OneToManyAssociationMetadata;
30
use Doctrine\ORM\Mapping\OneToOneAssociationMetadata;
31
use Doctrine\ORM\Mapping\ToOneAssociationMetadata;
32
33
/**
34
 * ClassMetadata exporter for PHP code.
35
 *
36
 * @link    www.doctrine-project.org
37
 * @since   2.0
38
 * @author  Jonathan Wage <[email protected]>
39
 */
40
class PhpExporter extends AbstractExporter
41 1
{
42
    /**
43 1
     * @var string
44 1
     */
45 1
    protected $extension = '.php';
46 1
47 1
    /**
48 1
     * {@inheritdoc}
49 1
     */
50
    public function exportClassMetadata(ClassMetadata $metadata)
51 1
    {
52
        $lines = [];
53
        $lines[] = '<?php';
54
        $lines[] = null;
55 1
        $lines[] = 'use Doctrine\DBAL\Types\Type;';
56 1
        $lines[] = 'use Doctrine\ORM\Mapping\ClassMetadata;';
57
        $lines[] = 'use Doctrine\ORM\Mapping;';
58
        $lines[] = null;
59 1
60
        if ($metadata->isMappedSuperclass) {
61
            $lines[] = '$metadata->isMappedSuperclass = true;';
62
        }
63 1
64 1
        if ($metadata->inheritanceType) {
65
            $lines[] = '$metadata->setInheritanceType(Mapping\InheritanceType::' . $metadata->inheritanceType . ');';
66
        }
67 1
68
        if ($metadata->customRepositoryClassName) {
0 ignored issues
show
Bug introduced by
The property customRepositoryClassName cannot be accessed from this context as it is declared protected in class Doctrine\ORM\Mapping\ClassMetadata.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
69
            $lines[] = '$metadata->customRepositoryClassName = "' . $metadata->customRepositoryClassName . '";';
0 ignored issues
show
Bug introduced by
The property customRepositoryClassName cannot be accessed from this context as it is declared protected in class Doctrine\ORM\Mapping\ClassMetadata.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
70
        }
71
72
        if ($metadata->table) {
73
            $table = $metadata->table;
74
75
            $lines[] = '$table = new Mapping\TableMetadata();';
76
            $lines[] = null;
77
78
            if (! empty($table->getSchema())) {
79
                $lines[] = '$table->setSchema("' . $table->getSchema() . '");';
80
            }
81
82
            $lines[] = '$table->setName("' . $table->getName() . '");';
83
            $lines[] = '$table->setOptions(' . $this->varExport($table->getOptions()) . ');';
84 1
85
            foreach ($table->getIndexes() as $index) {
86
                $lines[] = '$table->addIndex(' . $this->varExport($index) . ');';
87
            }
88 1
89 1
            foreach ($table->getUniqueConstraints() as $constraint) {
90
                $lines[] = '$table->addUniqueConstraint(' . $this->varExport($constraint) . ');';
91
            }
92 1
93 1
            $lines[] = null;
94 1
            $lines[] = '$metadata->setTable($table);';
95 1
        }
96
97
        if ($metadata->discriminatorColumn) {
98
            $discrColumn = $metadata->discriminatorColumn;
99
100 1
            $lines[] = '$discrColumn = new Mapping\DiscriminatorColumnMetadata();';
101 1
            $lines[] = null;
102 1
            $lines[] = '$discrColumn->setColumnName("' . $discrColumn->getColumnName() . '");';
103 1
            $lines[] = '$discrColumn->setType(Type::getType("' . $discrColumn->getTypeName() . '"));';
104 1
            $lines[] = '$discrColumn->setTableName("' . $discrColumn->getTableName() . '");';
105 1
106
            if (! empty($discrColumn->getColumnDefinition())) {
107
                $lines[] = '$property->setColumnDefinition("' . $discrColumn->getColumnDefinition() . '");';
108
            }
109 1
110 1
            if (! empty($discrColumn->getLength())) {
111
                $lines[] = '$property->setLength(' . $discrColumn->getLength() . ');';
112
            }
113 1
114 1
            if (! empty($discrColumn->getScale())) {
115
                $lines[] = '$property->setScale(' . $discrColumn->getScale() . ');';
116 1
            }
117 1
118 1
            if (! empty($discrColumn->getPrecision())) {
119
                $lines[] = '$property->setPrecision(' . $discrColumn->getPrecision() . ');';
120
            }
121
122 1
            $lines[] = '$discrColumn->setOptions(' . $this->varExport($discrColumn->getOptions()) . ');';
123 1
            $lines[] = '$discrColumn->setNullable(' . $this->varExport($discrColumn->isNullable()) . ');';
124
            $lines[] = '$discrColumn->setUnique(' . $this->varExport($discrColumn->isUnique()) . ');';
125
            $lines[] = null;
126
            $lines[] = '$metadata->setDiscriminatorColumn($discrColumn);';
127 1
        }
128 1
129 1
        if ($metadata->discriminatorMap) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $metadata->discriminatorMap of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
130
            $lines[] = '$metadata->setDiscriminatorMap(' . $this->varExport($metadata->discriminatorMap) . ');';
131
        }
132 1
133 1
        if ($metadata->changeTrackingPolicy) {
134
            $lines[] = '$metadata->setChangeTrackingPolicy(Mapping\ChangeTrackingPolicy::' . $metadata->changeTrackingPolicy . ');';
135
        }
136 1
137 1
        if ($metadata->lifecycleCallbacks) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $metadata->lifecycleCallbacks of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
138 1 View Code Duplication
            foreach ($metadata->lifecycleCallbacks as $event => $callbacks) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
139
                foreach ($callbacks as $callback) {
140 1
                    $lines[] = '$metadata->addLifecycleCallback("' . $callback . '", "' . $event . '");';
141 1
                }
142 1
            }
143 1
        }
144
145 1
        if (! $metadata->isIdentifierComposite()) {
146
            $lines[] = '$metadata->setIdGeneratorType(Mapping\GeneratorType::' . $metadata->generatorType . ');';
0 ignored issues
show
Bug introduced by
The property generatorType does not seem to exist in Doctrine\ORM\Mapping\ClassMetadata.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
147 1
        }
148 1
149 View Code Duplication
        foreach ($metadata->getProperties() as $property) {
0 ignored issues
show
Bug introduced by
The method getProperties() does not exist on Doctrine\ORM\Mapping\ClassMetadata. Did you maybe mean getPropertiesIterator()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
150 1
            if ($property instanceof FieldMetadata) {
151 1
                $this->exportFieldMetadata($metadata, $property, $lines);
152 1
            } else if ($property instanceof AssociationMetadata) {
153 1
                $this->exportAssociationMetadata($metadata, $property, $lines);
154
            }
155 1
        }
156
157 1
        return implode(PHP_EOL, $lines);
158 1
    }
159 1
160
    private function exportFieldMetadata(ClassMetadata $metadata, FieldMetadata $property, array &$lines)
161 1
    {
162
        $lines[] = sprintf(
163
            '$property = new Mapping\%sFieldMetadata("%s");',
164
            ($metadata->versionProperty === $property) ? 'Version' : '',
165
            $property->getName()
166 1
        );
167 1
168
        $lines[] = null;
169
        $lines[] = '$property->setColumnName("' . $property->getColumnName() . '");';
170
        $lines[] = '$property->setType(Type::getType("' . $property->getTypeName() . '"));';
171 1
        $lines[] = '$property->setTableName("' . $property->getTableName() . '");';
172
173 1
        if (! empty($property->getColumnDefinition())) {
174
            $lines[] = '$property->setColumnDefinition("' . $property->getColumnDefinition() . '");';
175 1
        }
176 1
177 1
        if (! empty($property->getLength())) {
178
            $lines[] = '$property->setLength(' . $property->getLength() . ');';
179 1
        }
180
181
        if (! empty($property->getScale())) {
182
            $lines[] = '$property->setScale(' . $property->getScale() . ');';
183
        }
184 1
185 1
        if (! empty($property->getPrecision())) {
186 1
            $lines[] = '$property->setPrecision(' . $property->getPrecision() . ');';
187
        }
188
189 1
        $lines[] = '$property->setOptions(' . $this->varExport($property->getOptions()) . ');';
190
        $lines[] = '$property->setPrimaryKey(' . $this->varExport($property->isPrimaryKey()) . ');';
191 1
        $lines[] = '$property->setNullable(' . $this->varExport($property->isNullable()) . ');';
192
        $lines[] = '$property->setUnique(' . $this->varExport($property->isUnique()) . ');';
193
        $lines[] = null;
194 1
        $lines[] = '$metadata->addProperty($property);';
195
    }
196 1
197
    private function exportAssociationMetadata(ClassMetadata $metadata, AssociationMetadata $association, array &$lines)
0 ignored issues
show
Unused Code introduced by
The parameter $metadata is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
198
    {
199 1
        $cascade = ['remove', 'persist', 'refresh'];
200
201
        foreach ($cascade as $key => $value) {
202
            if ( ! in_array($value, $association->getCascade())) {
203
                unset($cascade[$key]);
204
            }
205
        }
206
207 1
        if (count($cascade) === 5) {
208
            $cascade = ['all'];
209 1
        }
210 1
211 1
        if ($association instanceof OneToOneAssociationMetadata) {
212 1
            $this->exportJoinColumns($association->getJoinColumns(), $lines, 'joinColumns');
213 1
214 1
            $lines[] = '$association = new Mapping\OneToOneAssociationMetadata("' . $association->getName() . '");';
215 1
            $lines[] = null;
216 1
            $lines[] = '$association->setJoinColumns($joinColumns);';
217
        } else if ($association instanceof ManyToOneAssociationMetadata) {
218 1
            $this->exportJoinColumns($association->getJoinColumns(), $lines, 'joinColumns');
219
220
            $lines[] = '$association = new Mapping\ManyToOneAssociationMetadata("' . $association->getName() . '");';
221
            $lines[] = null;
222
            $lines[] = '$association->setJoinColumns($joinColumns);';
223
        } else if ($association instanceof OneToManyAssociationMetadata) {
224
            $lines[] = '$association = new Mapping\OneToManyAssociationMetadata("' . $association->getName() . '");';
225
            $lines[] = null;
226
            $lines[] = '$association->setOrderBy(' . $this->varExport($association->getOrderBy()) . ');';
227
        } else if ($association instanceof ManyToManyAssociationMetadata) {
228
            if ($association->getJoinTable()) {
229
                $this->exportJoinTable($association->getJoinTable(), $lines);
230
            }
231
232
            $lines[] = '$association = new Mapping\ManyToManyAssociationMetadata("' . $association->getName() . '");';
233
            $lines[] = null;
234
235
            if ($association->getJoinTable()) {
236
                $lines[] = '$association->setJoinTable($joinTable);';
237
            }
238
239
            if ($association->getIndexedBy()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $association->getIndexedBy() of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
240
                $lines[] = '$association->setIndexedBy("' . $association->getIndexedBy() . '");';
241
            }
242
243
            $lines[] = '$association->setOrderBy(' . $this->varExport($association->getOrderBy()) . ');';
244
        }
245
246
        $lines[] = '$association->setTargetEntity("' . $association->getTargetEntity() . '");';
247
        $lines[] = '$association->setFetchMode("' . $association->getFetchMode() . '");';
248
249
        if ($association->getMappedBy()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $association->getMappedBy() of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
250
            $lines[] = '$association->setMappedBy("' . $association->getMappedBy() . '");';
251
        }
252
253
        if ($association->getInversedBy()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $association->getInversedBy() of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
254
            $lines[] = '$association->setInversedBy("' . $association->getInversedBy() . '");';
255
        }
256
257
        $lines[] = '$association->setCascade(' . $this->varExport($cascade) . ');';
258
        $lines[] = '$association->setOrphanRemoval(' . $this->varExport($association->isOrphanRemoval()) . ');';
259
        $lines[] = '$association->setPrimaryKey(' . $this->varExport($association->isPrimaryKey()) . ');';
260
        $lines[] = null;
261
        $lines[] = '$metadata->addProperty($association);';
262
    }
263
264
    private function exportJoinTable(JoinTableMetadata $joinTable, array &$lines)
265
    {
266
        $lines[] = null;
267
        $lines[] = '$joinTable = new Mapping\JoinTableMetadata();';
268
        $lines[] = null;
269
        $lines[] = '$joinTable->setName("' . $joinTable->getName() . '");';
270
271
        if (! empty($joinTable->getSchema())) {
272
            $lines[] = '$joinTable->setSchema("' . $joinTable->getSchema() . '");';
273
        }
274
275
        $lines[] = '$joinTable->setOptions(' . $this->varExport($joinTable->getOptions()) . ');';
276
277
        $this->exportJoinColumns($joinTable->getJoinColumns(), $lines, 'joinColumns');
278
279
        $lines[] = null;
280
        $lines[] = 'foreach ($joinColumns as $joinColumn) {';
281
        $lines[] = '    $joinTable->addJoinColumn($joinColumn);';
282
        $lines[] = '}';
283
        $lines[] = null;
284
285
        $this->exportJoinColumns($joinTable->getInverseJoinColumns(), $lines, 'inverseJoinColumns');
286
287
        $lines[] = null;
288
        $lines[] = 'foreach ($inverseJoinColumns as $inverseJoinColumn) {';
289
        $lines[] = '    $joinTable->addInverseJoinColumn($inverseJoinColumn);';
290
        $lines[] = '}';
291
    }
292
293
    private function exportJoinColumns(array $joinColumns, array &$lines, $variableName)
294
    {
295
        $lines[] = '$' . $variableName . ' = array();';
296
297
        foreach ($joinColumns as $joinColumn) {
298
            /** @var JoinColumnMetadata $joinColumn */
299
            $lines[] = '$joinColumn = new Mapping\JoinColumnMetadata();';
300
            $lines[] = null;
301
            $lines[] = '$joinColumn->setTableName("' . $joinColumn->getTableName() . '");';
302
            $lines[] = '$joinColumn->setColumnName("' . $joinColumn->getColumnName() . '");';
303
            $lines[] = '$joinColumn->setReferencedColumnName("' . $joinColumn->getReferencedColumnName() . '");';
304
            $lines[] = '$joinColumn->setAliasedName("' . $joinColumn->getAliasedName() . '");';
305
            $lines[] = '$joinColumn->setColumnDefinition("' . $joinColumn->getColumnDefinition() . '");';
306
            $lines[] = '$joinColumn->setOnDelete("' . $joinColumn->getOnDelete() . '");';
307
            $lines[] = '$joinColumn->setOptions(' . $this->varExport($joinColumn->getOptions()) . ');';
308
            $lines[] = '$joinColumn->setNullable("' . $joinColumn->isNullable() . '");';
309
            $lines[] = '$joinColumn->setUnique("' . $joinColumn->isUnique() . '");';
310
            $lines[] = '$joinColumn->setPrimaryKey("' . $joinColumn->isPrimaryKey() . '");';
311
            $lines[] = null;
312
            $lines[] = '$' . $variableName . '[] = $joinColumn;';
313
        }
314
    }
315
316
    /**
317
     * @param mixed $var
318
     *
319
     * @return string
320
     */
321
    protected function varExport($var)
322
    {
323
        $export = var_export($var, true);
324
        $export = str_replace("\n", PHP_EOL . str_repeat(' ', 8), $export);
325
        $export = str_replace('  ', ' ', $export);
326
        $export = str_replace('array (', 'array(', $export);
327
        $export = str_replace('array( ', 'array(', $export);
328
        $export = str_replace(',)', ')', $export);
329
        $export = str_replace(', )', ')', $export);
330
        $export = str_replace('  ', ' ', $export);
331
332
        return $export;
333
    }
334
}
335