Completed
Pull Request — master (#5569)
by Jérémy
10:47
created

EntityGenerator::setGenerateAnnotations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
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\Util\Inflector;
24
use Doctrine\DBAL\Types\Type;
25
26
/**
27
 * Generic class used to generate PHP5 entity classes from ClassMetadataInfo instances.
28
 *
29
 *     [php]
30
 *     $classes = $em->getClassMetadataFactory()->getAllMetadata();
31
 *
32
 *     $generator = new \Doctrine\ORM\Tools\EntityGenerator();
33
 *     $generator->setGenerateAnnotations(true);
34
 *     $generator->setGenerateStubMethods(true);
35
 *     $generator->setRegenerateEntityIfExists(false);
36
 *     $generator->setUpdateEntityIfExists(true);
37
 *     $generator->generate($classes, '/path/to/generate/entities');
38
 *
39
 *
40
 * @link    www.doctrine-project.org
41
 * @since   2.0
42
 * @author  Benjamin Eberlei <[email protected]>
43
 * @author  Guilherme Blanco <[email protected]>
44
 * @author  Jonathan Wage <[email protected]>
45
 * @author  Roman Borschel <[email protected]>
46
 */
47
class EntityGenerator
48
{
49
    /**
50
     * Specifies class fields should be protected.
51
     */
52
    const FIELD_VISIBLE_PROTECTED = 'protected';
53
54
    /**
55
     * Specifies class fields should be private.
56
     */
57
    const FIELD_VISIBLE_PRIVATE = 'private';
58
59
    /**
60
     * @var bool
61
     */
62
    protected $backupExisting = true;
63
64
    /**
65
     * The extension to use for written php files.
66
     *
67
     * @var string
68
     */
69
    protected $extension = '.php';
70
71
    /**
72
     * Whether or not the current ClassMetadataInfo instance is new or old.
73
     *
74
     * @var boolean
75
     */
76
    protected $isNew = true;
77
78
    /**
79
     * @var array
80
     */
81
    protected $staticReflection = array();
82
83
    /**
84
     * Number of spaces to use for indention in generated code.
85
     */
86
    protected $numSpaces = 4;
87
88
    /**
89
     * The actual spaces to use for indention.
90
     *
91
     * @var string
92
     */
93
    protected $spaces = '    ';
94
95
    /**
96
     * The class all generated entities should extend.
97
     *
98
     * @var string
99
     */
100
    protected $classToExtend;
101
102
    /**
103
     * Whether or not to generation annotations.
104
     *
105
     * @var boolean
106
     */
107
    protected $generateAnnotations = false;
108
109
    /**
110
     * @var string
111
     */
112
    protected $annotationsPrefix = '';
113
114
    /**
115
     * Whether or not to generate sub methods.
116
     *
117
     * @var boolean
118
     */
119
    protected $generateEntityStubMethods = false;
120
121
    /**
122
     * Whether or not to update the entity class if it exists already.
123
     *
124
     * @var boolean
125
     */
126
    protected $updateEntityIfExists = false;
127
128
    /**
129
     * Whether or not to re-generate entity class if it exists already.
130
     *
131
     * @var boolean
132
     */
133
    protected $regenerateEntityIfExists = false;
134
135
    /**
136
     * Visibility of the field
137
     *
138
     * @var string
139
     */
140
    protected $fieldVisibility = 'private';
141
142
    /**
143
     * Whether or not to make generated embeddables immutable.
144
     *
145
     * @var boolean.
146
     */
147
    protected $embeddablesImmutable = false;
148
149
    /**
150
     * Whether or not to add PHP strict types.
151
     *
152
     * @var boolean
153
     */
154
    protected $strictTypes = false;
155
156
    /**
157
     * Whether or not to force type hinting for method result and scalar parameters.
158
     *
159
     * @var boolean
160
     */
161
    protected $generateMethodsTypeHinting = false;
162
163
    /**
164
     * Hash-map for handle types.
165
     *
166
     * @var array
167
     */
168
    protected $typeAlias = array(
169
        Type::DATETIMETZ    => '\DateTime',
170
        Type::DATETIME      => '\DateTime',
171
        Type::DATE          => '\DateTime',
172
        Type::TIME          => '\DateTime',
173
        Type::OBJECT        => '\stdClass',
174
        Type::INTEGER       => 'int',
175
        Type::BIGINT        => 'int',
176
        Type::SMALLINT      => 'int',
177
        Type::TEXT          => 'string',
178
        Type::BLOB          => 'string',
179
        Type::DECIMAL       => 'string',
180
        Type::JSON_ARRAY    => 'array',
181
        Type::SIMPLE_ARRAY  => 'array',
182
        Type::BOOLEAN       => 'bool',
183
    );
184
185
    /**
186
     * Hash-map for handle strict types
187
     *
188
     * @var array
189
     */
190
    protected $typeHintingAlias = array(
191
        Type::TARRAY        => 'array',
192
        Type::SIMPLE_ARRAY  => 'array',
193
        Type::JSON_ARRAY    => 'array',
194
        Type::STRING        => 'string',
195
        Type::FLOAT         => 'float',
196
        Type::GUID          => 'string',
197
    );
198
199
    /**
200
     * Hash-map to handle generator types string.
201
     *
202
     * @var array
203
     */
204
    protected static $generatorStrategyMap = array(
205
        ClassMetadataInfo::GENERATOR_TYPE_AUTO      => 'AUTO',
206
        ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE  => 'SEQUENCE',
207
        ClassMetadataInfo::GENERATOR_TYPE_TABLE     => 'TABLE',
208
        ClassMetadataInfo::GENERATOR_TYPE_IDENTITY  => 'IDENTITY',
209
        ClassMetadataInfo::GENERATOR_TYPE_NONE      => 'NONE',
210
        ClassMetadataInfo::GENERATOR_TYPE_UUID      => 'UUID',
211
        ClassMetadataInfo::GENERATOR_TYPE_CUSTOM    => 'CUSTOM'
212
    );
213
214
    /**
215
     * Hash-map to handle the change tracking policy string.
216
     *
217
     * @var array
218
     */
219
    protected static $changeTrackingPolicyMap = array(
220
        ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT  => 'DEFERRED_IMPLICIT',
221
        ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT  => 'DEFERRED_EXPLICIT',
222
        ClassMetadataInfo::CHANGETRACKING_NOTIFY             => 'NOTIFY',
223
    );
224
225
    /**
226
     * Hash-map to handle the inheritance type string.
227
     *
228
     * @var array
229
     */
230
    protected static $inheritanceTypeMap = array(
231
        ClassMetadataInfo::INHERITANCE_TYPE_NONE            => 'NONE',
232
        ClassMetadataInfo::INHERITANCE_TYPE_JOINED          => 'JOINED',
233
        ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_TABLE    => 'SINGLE_TABLE',
234
        ClassMetadataInfo::INHERITANCE_TYPE_TABLE_PER_CLASS => 'TABLE_PER_CLASS',
235
    );
236
237
    /**
238
     * @var string
239
     */
240
    protected static $classTemplate =
241
'<?php
242
<strictTypes>
243
<namespace>
244
<useStatement>
245
<entityAnnotation>
246
<entityClassName>
247
{
248
<entityBody>
249
}
250
';
251
252
    /**
253
     * @var string
254
     */
255
    protected static $getMethodTemplate =
256
'/**
257
 * <description>
258
 *
259
 * @return <variableType>
260
 */
261
public function <methodName>() <methodTypeReturn>
262
{
263
<spaces>return $this-><fieldName>;
264
}';
265
266
    /**
267
     * @var string
268
     */
269
    protected static $setMethodTemplate =
270
'/**
271
 * <description>
272
 *
273
 * @param <variableType> $<variableName>
274
 *
275
 * @return <entity>
276
 */
277
public function <methodName>(<methodTypeHint>$<variableName><variableDefault>) <methodTypeReturn>
278
{
279
<spaces>$this-><fieldName> = $<variableName>;
280
281
<spaces>return $this;
282
}';
283
284
    /**
285
     * @var string
286
     */
287
    protected static $addMethodTemplate =
288
'/**
289
 * <description>
290
 *
291
 * @param <variableType> $<variableName>
292
 *
293
 * @return <entity>
294
 */
295
public function <methodName>(<methodTypeHint>$<variableName>) <methodTypeReturn>
296
{
297
<spaces>$this-><fieldName>[] = $<variableName>;
298
299
<spaces>return $this;
300
}';
301
302
    /**
303
     * @var string
304
     */
305
    protected static $removeMethodTemplate =
306
'/**
307
 * <description>
308
 *
309
 * @param <variableType> $<variableName>
310
 *
311
 * @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
312
 */
313
public function <methodName>(<methodTypeHint>$<variableName>) <methodTypeReturn>
314
{
315
<spaces>return $this-><fieldName>->removeElement($<variableName>);
316
}';
317
318
    /**
319
     * @var string
320
     */
321
    protected static $lifecycleCallbackMethodTemplate =
322
'/**
323
 * @<name>
324
 */
325
public function <methodName>()
326
{
327
<spaces>// Add your code here
328
}';
329
330
    /**
331
     * @var string
332
     */
333
    protected static $constructorMethodTemplate =
334
'/**
335
 * Constructor
336
 */
337
public function __construct()
338
{
339
<spaces><collections>
340
}
341
';
342
343
    /**
344
     * @var string
345
     */
346
    protected static $embeddableConstructorMethodTemplate =
347
'/**
348
 * Constructor
349
 *
350
 * <paramTags>
351
 */
352
public function __construct(<params>)
353
{
354
<spaces><fields>
355
}
356
';
357
358
    /**
359
     * Constructor.
360
     */
361 50
    public function __construct()
362
    {
363 50
        if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) {
364 50
            $this->annotationsPrefix = 'ORM\\';
365
        }
366 50
    }
367
368
    /**
369
     * Generates and writes entity classes for the given array of ClassMetadataInfo instances.
370
     *
371
     * @param array  $metadatas
372
     * @param string $outputDirectory
373
     *
374
     * @return void
375
     */
376
    public function generate(array $metadatas, $outputDirectory)
377
    {
378
        foreach ($metadatas as $metadata) {
379
            $this->writeEntityClass($metadata, $outputDirectory);
380
        }
381
    }
382
383
    /**
384
     * Generates and writes entity class to disk for the given ClassMetadataInfo instance.
385
     *
386
     * @param ClassMetadataInfo $metadata
387
     * @param string            $outputDirectory
388
     *
389
     * @return void
390
     *
391
     * @throws \RuntimeException
392
     */
393 40
    public function writeEntityClass(ClassMetadataInfo $metadata, $outputDirectory)
394
    {
395 40
        $path = $outputDirectory . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $metadata->name) . $this->extension;
396 40
        $dir = dirname($path);
397
398 40
        if ( ! is_dir($dir)) {
399 2
            mkdir($dir, 0775, true);
400
        }
401
402 40
        $this->isNew = !file_exists($path) || (file_exists($path) && $this->regenerateEntityIfExists);
403
404 40
        if ( ! $this->isNew) {
405 3
            $this->parseTokensInEntityFile(file_get_contents($path));
406
        } else {
407 39
            $this->staticReflection[$metadata->name] = array('properties' => array(), 'methods' => array());
408
        }
409
410 40
        if ($this->backupExisting && file_exists($path)) {
411 3
            $backupPath = dirname($path) . DIRECTORY_SEPARATOR . basename($path) . "~";
412 3
            if (!copy($path, $backupPath)) {
413
                throw new \RuntimeException("Attempt to backup overwritten entity file but copy operation failed.");
414
            }
415
        }
416
417
        // If entity doesn't exist or we're re-generating the entities entirely
418 40
        if ($this->isNew) {
419 39
            file_put_contents($path, $this->generateEntityClass($metadata));
420
        // If entity exists and we're allowed to update the entity class
421 3
        } elseif ( ! $this->isNew && $this->updateEntityIfExists) {
422 3
            file_put_contents($path, $this->generateUpdatedEntityClass($metadata, $path));
423
        }
424 40
        chmod($path, 0664);
425 40
    }
426
427
    /**
428
     * Generates a PHP5 Doctrine 2 entity class from the given ClassMetadataInfo instance.
429
     *
430
     * @param ClassMetadataInfo $metadata
431
     *
432
     * @return string
433
     */
434 40
    public function generateEntityClass(ClassMetadataInfo $metadata)
435
    {
436
        $placeHolders = array(
437 40
            '<strictTypes>',
438
            '<namespace>',
439
            '<useStatement>',
440
            '<entityAnnotation>',
441
            '<entityClassName>',
442
            '<entityBody>'
443
        );
444
445
        $replacements = array(
446 40
            $this->generateEntityStrictTypes(),
447 40
            $this->generateEntityNamespace($metadata),
448 40
            $this->generateEntityUse(),
449 40
            $this->generateEntityDocBlock($metadata),
450 40
            $this->generateEntityClassName($metadata),
451 40
            $this->generateEntityBody($metadata)
452
        );
453
454 40
        $code = str_replace($placeHolders, $replacements, static::$classTemplate) . "\n";
455
456 40
        return str_replace('<spaces>', $this->spaces, $code);
457
    }
458
459
    /**
460
     * Generates the updated code for the given ClassMetadataInfo and entity at path.
461
     *
462
     * @param ClassMetadataInfo $metadata
463
     * @param string            $path
464
     *
465
     * @return string
466
     */
467 3
    public function generateUpdatedEntityClass(ClassMetadataInfo $metadata, $path)
468
    {
469 3
        $currentCode = file_get_contents($path);
470
471 3
        $body = $this->generateEntityBody($metadata);
472 3
        $body = str_replace('<spaces>', $this->spaces, $body);
473 3
        $last = strrpos($currentCode, '}');
474
475 3
        return substr($currentCode, 0, $last) . $body . (strlen($body) > 0 ? "\n" : '') . "}\n";
476
    }
477
478
    /**
479
     * Sets the number of spaces the exported class should have.
480
     *
481
     * @param integer $numSpaces
482
     *
483
     * @return void
484
     */
485
    public function setNumSpaces($numSpaces)
486
    {
487
        $this->spaces = str_repeat(' ', $numSpaces);
488
        $this->numSpaces = $numSpaces;
489
    }
490
491
    /**
492
     * Sets the extension to use when writing php files to disk.
493
     *
494
     * @param string $extension
495
     *
496
     * @return void
497
     */
498
    public function setExtension($extension)
499
    {
500
        $this->extension = $extension;
501
    }
502
503
    /**
504
     * Sets the name of the class the generated classes should extend from.
505
     *
506
     * @param string $classToExtend
507
     *
508
     * @return void
509
     */
510 1
    public function setClassToExtend($classToExtend)
511
    {
512 1
        $this->classToExtend = $classToExtend;
513 1
    }
514
515
    /**
516
     * Sets whether or not to generate annotations for the entity.
517
     *
518
     * @param bool $bool
519
     *
520
     * @return void
521
     */
522 49
    public function setGenerateAnnotations($bool)
523
    {
524 49
        $this->generateAnnotations = $bool;
525 49
    }
526
527
    /**
528
     * Sets the class fields visibility for the entity (can either be private or protected).
529
     *
530
     * @param bool $visibility
531
     *
532
     * @return void
533
     *
534
     * @throws \InvalidArgumentException
535
     */
536 48
    public function setFieldVisibility($visibility)
537
    {
538 48
        if ($visibility !== static::FIELD_VISIBLE_PRIVATE && $visibility !== static::FIELD_VISIBLE_PROTECTED) {
539
            throw new \InvalidArgumentException('Invalid provided visibility (only private and protected are allowed): ' . $visibility);
540
        }
541
542 48
        $this->fieldVisibility = $visibility;
543 48
    }
544
545
    /**
546
     * Sets whether or not to generate immutable embeddables.
547
     *
548
     * @param boolean $embeddablesImmutable
549
     */
550 1
    public function setEmbeddablesImmutable($embeddablesImmutable)
551
    {
552 1
        $this->embeddablesImmutable = (boolean) $embeddablesImmutable;
553 1
    }
554
555
    /**
556
     * Sets an annotation prefix.
557
     *
558
     * @param string $prefix
559
     *
560
     * @return void
561
     */
562 49
    public function setAnnotationPrefix($prefix)
563
    {
564 49
        $this->annotationsPrefix = $prefix;
565 49
    }
566
567
    /**
568
     * Sets whether or not to try and update the entity if it already exists.
569
     *
570
     * @param bool $bool
571
     *
572
     * @return void
573
     */
574 49
    public function setUpdateEntityIfExists($bool)
575
    {
576 49
        $this->updateEntityIfExists = $bool;
577 49
    }
578
579
    /**
580
     * Sets whether or not to regenerate the entity if it exists.
581
     *
582
     * @param bool $bool
583
     *
584
     * @return void
585
     */
586 49
    public function setRegenerateEntityIfExists($bool)
587
    {
588 49
        $this->regenerateEntityIfExists = $bool;
589 49
    }
590
591
    /**
592
     * Sets whether or not to generate stub methods for the entity.
593
     *
594
     * @param bool $bool
595
     *
596
     * @return void
597
     */
598 49
    public function setGenerateStubMethods($bool)
599
    {
600 49
        $this->generateEntityStubMethods = $bool;
601 49
    }
602
603
    /**
604
     * Should an existing entity be backed up if it already exists?
605
     *
606
     * @param bool $bool
607
     *
608
     * @return void
609
     */
610 1
    public function setBackupExisting($bool)
611
    {
612 1
        $this->backupExisting = $bool;
613 1
    }
614
615
    /**
616
     * Set whether or not to add PHP strict types.
617
     *
618
     * @param bool $bool
619
     *
620
     * @return void
621
     */
622 46
    public function setStrictTypes($bool)
623
    {
624 46
        $this->strictTypes = $bool;
625 46
    }
626
627
    /**
628
     * Set whether or not to force type hinting for method result and scalar parameters.
629
     *
630
     * @param bool $bool
631
     *
632
     * @param void
633
     */
634 46
    public function setGenerateMethodsTypeHinting($bool)
635
    {
636 46
        $this->generateMethodsTypeHinting = $bool;
637 46
    }
638
639
    /**
640
     * @param string $type
641
     *
642
     * @return string
643
     */
644 40
    protected function getType($type)
645
    {
646 40
        if (isset($this->typeAlias[$type])) {
647 39
            return $this->typeAlias[$type];
648
        }
649
650 19
        return $type;
651
    }
652
653
    /**
654
     * @return string
655
     */
656 40
    protected function generateEntityStrictTypes()
657
    {
658 40
        if ($this->strictTypes) {
659
            return "\n".'declare(strict_types=1);'."\n";
660
        }
661
662 40
        return '';
663
    }
664
665
    /**
666
     * @param ClassMetadataInfo $metadata
667
     *
668
     * @return string
669
     */
670 40
    protected function generateEntityNamespace(ClassMetadataInfo $metadata)
671
    {
672 40
        if ($this->hasNamespace($metadata)) {
673 40
            return 'namespace ' . $this->getNamespace($metadata) .';';
674
        }
675 2
    }
676
677 40
    protected function generateEntityUse()
678
    {
679 40
        if ($this->generateAnnotations) {
680 40
            return "\n".'use Doctrine\ORM\Mapping as ORM;'."\n";
681
        } else {
682
            return "";
683
        }
684
    }
685
686
    /**
687
     * @param ClassMetadataInfo $metadata
688
     *
689
     * @return string
690
     */
691 40
    protected function generateEntityClassName(ClassMetadataInfo $metadata)
692
    {
693 40
        return 'class ' . $this->getClassName($metadata) .
694 40
            ($this->extendsClass() ? ' extends ' . $this->getClassToExtendName() : null);
695
    }
696
697
    /**
698
     * @param ClassMetadataInfo $metadata
699
     *
700
     * @return string
701
     */
702 41
    protected function generateEntityBody(ClassMetadataInfo $metadata)
703
    {
704 41
        $fieldMappingProperties = $this->generateEntityFieldMappingProperties($metadata);
705 41
        $embeddedProperties = $this->generateEntityEmbeddedProperties($metadata);
706 41
        $associationMappingProperties = $this->generateEntityAssociationMappingProperties($metadata);
707 41
        $stubMethods = $this->generateEntityStubMethods ? $this->generateEntityStubMethods($metadata) : null;
708 41
        $lifecycleCallbackMethods = $this->generateEntityLifecycleCallbackMethods($metadata);
709
710 41
        $code = array();
711
712 41
        if ($fieldMappingProperties) {
713 38
            $code[] = $fieldMappingProperties;
714
        }
715
716 41
        if ($embeddedProperties) {
717 8
            $code[] = $embeddedProperties;
718
        }
719
720 41
        if ($associationMappingProperties) {
721 12
            $code[] = $associationMappingProperties;
722
        }
723
724 41
        $code[] = $this->generateEntityConstructor($metadata);
725
726 41
        if ($stubMethods) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $stubMethods of type string|null 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...
727 39
            $code[] = $stubMethods;
728
        }
729
730 41
        if ($lifecycleCallbackMethods) {
731 11
            $code[] = $lifecycleCallbackMethods;
732
        }
733
734 41
        return implode("\n", $code);
735
    }
736
737
    /**
738
     * @param ClassMetadataInfo $metadata
739
     *
740
     * @return string
741
     */
742 41
    protected function generateEntityConstructor(ClassMetadataInfo $metadata)
743
    {
744 41
        if ($this->hasMethod('__construct', $metadata)) {
745 2
            return '';
746
        }
747
748 41
        if ($metadata->isEmbeddedClass && $this->embeddablesImmutable) {
749 1
            return $this->generateEmbeddableConstructor($metadata);
750
        }
751
752 40
        $collections = array();
753
754 40
        foreach ($metadata->associationMappings as $mapping) {
755 14
            if ($mapping['type'] & ClassMetadataInfo::TO_MANY) {
756 14
                $collections[] = '$this->'.$mapping['fieldName'].' = new \Doctrine\Common\Collections\ArrayCollection();';
757
            }
758
        }
759
760 40
        if ($collections) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $collections 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...
761 12
            return $this->prefixCodeWithSpaces(str_replace("<collections>", implode("\n".$this->spaces, $collections), static::$constructorMethodTemplate));
762
        }
763
764 35
        return '';
765
    }
766
767
    /**
768
     * @param ClassMetadataInfo $metadata
769
     *
770
     * @return string
771
     */
772 1
    private function generateEmbeddableConstructor(ClassMetadataInfo $metadata)
773
    {
774 1
        $paramTypes = array();
775 1
        $paramVariables = array();
776 1
        $params = array();
777 1
        $fields = array();
778
779
        // Resort fields to put optional fields at the end of the method signature.
780 1
        $requiredFields = array();
781 1
        $optionalFields = array();
782
783 1
        foreach ($metadata->fieldMappings as $fieldMapping) {
784 1
            if (empty($fieldMapping['nullable'])) {
785 1
                $requiredFields[] = $fieldMapping;
786
787 1
                continue;
788
            }
789
790 1
            $optionalFields[] = $fieldMapping;
791
        }
792
793 1
        $fieldMappings = array_merge($requiredFields, $optionalFields);
794
795 1
        foreach ($metadata->embeddedClasses as $fieldName => $embeddedClass) {
796 1
            $paramType = '\\' . ltrim($embeddedClass['class'], '\\');
797 1
            $paramVariable = '$' . $fieldName;
798
799 1
            $paramTypes[] = $paramType;
800 1
            $paramVariables[] = $paramVariable;
801 1
            $params[] = $paramType . ' ' . $paramVariable;
802 1
            $fields[] = '$this->' . $fieldName . ' = ' . $paramVariable . ';';
803
        }
804
805 1
        foreach ($fieldMappings as $fieldMapping) {
806 1
            if (isset($fieldMapping['declaredField']) &&
807 1
                isset($metadata->embeddedClasses[$fieldMapping['declaredField']])
808
            ) {
809
                continue;
810
            }
811
812 1
            $paramTypes[] = $this->getType($fieldMapping['type']) . (!empty($fieldMapping['nullable']) ? '|null' : '');
813 1
            $param = '$' . $fieldMapping['fieldName'];
814 1
            $paramVariables[] = $param;
815
816 1
            if ($fieldMapping['type'] === 'datetime') {
817 1
                $param = $this->getType($fieldMapping['type']) . ' ' . $param;
818
            }
819
820 1
            if (!empty($fieldMapping['nullable'])) {
821 1
                $param .= ' = null';
822
            }
823
824 1
            $params[] = $param;
825
826 1
            $fields[] = '$this->' . $fieldMapping['fieldName'] . ' = $' . $fieldMapping['fieldName'] . ';';
827
        }
828
829 1
        $maxParamTypeLength = max(array_map('strlen', $paramTypes));
830 1
        $paramTags = array_map(
831 1
            function ($type, $variable) use ($maxParamTypeLength) {
832 1
                return '@param ' . $type . str_repeat(' ', $maxParamTypeLength - strlen($type) + 1) . $variable;
833 1
            },
834
            $paramTypes,
835
            $paramVariables
836
        );
837
838
        // Generate multi line constructor if the signature exceeds 120 characters.
839 1
        if (array_sum(array_map('strlen', $params)) + count($params) * 2 + 29 > 120) {
840 1
            $delimiter = "\n" . $this->spaces;
841 1
            $params = $delimiter . implode(',' . $delimiter, $params) . "\n";
842
        } else {
843 1
            $params = implode(', ', $params);
844
        }
845
846
        $replacements = array(
847 1
            '<paramTags>' => implode("\n * ", $paramTags),
848 1
            '<params>'    => $params,
849 1
            '<fields>'    => implode("\n" . $this->spaces, $fields),
850
        );
851
852 1
        $constructor = str_replace(
853
            array_keys($replacements),
854
            array_values($replacements),
855 1
            static::$embeddableConstructorMethodTemplate
856
        );
857
858 1
        return $this->prefixCodeWithSpaces($constructor);
859
    }
860
861
    /**
862
     * @todo this won't work if there is a namespace in brackets and a class outside of it.
863
     *
864
     * @param string $src
865
     *
866
     * @return void
867
     */
868 8
    protected function parseTokensInEntityFile($src)
869
    {
870 8
        $tokens = token_get_all($src);
871 8
        $lastSeenNamespace = "";
872 8
        $lastSeenClass = false;
873
874 8
        $inNamespace = false;
875 8
        $inClass = false;
876
877 8
        for ($i = 0; $i < count($tokens); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
878 8
            $token = $tokens[$i];
879 8
            if (in_array($token[0], array(T_WHITESPACE, T_COMMENT, T_DOC_COMMENT))) {
880 8
                continue;
881
            }
882
883 8
            if ($inNamespace) {
884 8
                if ($token[0] == T_NS_SEPARATOR || $token[0] == T_STRING) {
885 8
                    $lastSeenNamespace .= $token[1];
886 8
                } elseif (is_string($token) && in_array($token, array(';', '{'))) {
887 8
                    $inNamespace = false;
888
                }
889
            }
890
891 8
            if ($inClass) {
892 8
                $inClass = false;
893 8
                $lastSeenClass = $lastSeenNamespace . ($lastSeenNamespace ? '\\' : '') . $token[1];
894 8
                $this->staticReflection[$lastSeenClass]['properties'] = array();
895 8
                $this->staticReflection[$lastSeenClass]['methods'] = array();
896
            }
897
898 8
            if ($token[0] == T_NAMESPACE) {
899 8
                $lastSeenNamespace = "";
900 8
                $inNamespace = true;
901 8
            } elseif ($token[0] == T_CLASS && $tokens[$i-1][0] != T_DOUBLE_COLON) {
902 8
                $inClass = true;
903 8
            } elseif ($token[0] == T_FUNCTION) {
904 3
                if ($tokens[$i+2][0] == T_STRING) {
905 3
                    $this->staticReflection[$lastSeenClass]['methods'][] = strtolower($tokens[$i+2][1]);
906
                } elseif ($tokens[$i+2] == "&" && $tokens[$i+3][0] == T_STRING) {
907 3
                    $this->staticReflection[$lastSeenClass]['methods'][] = strtolower($tokens[$i+3][1]);
908
                }
909 8
            } elseif (in_array($token[0], array(T_VAR, T_PUBLIC, T_PRIVATE, T_PROTECTED)) && $tokens[$i+2][0] != T_FUNCTION) {
910 4
                $this->staticReflection[$lastSeenClass]['properties'][] = substr($tokens[$i+2][1], 1);
911
            }
912
        }
913 8
    }
914
915
    /**
916
     * @param string            $property
917
     * @param ClassMetadataInfo $metadata
918
     *
919
     * @return bool
920
     */
921 40
    protected function hasProperty($property, ClassMetadataInfo $metadata)
922
    {
923 40
        if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) {
924
            // don't generate property if its already on the base class.
925 2
            $reflClass = new \ReflectionClass($this->getClassToExtend() ?: $metadata->name);
926 2
            if ($reflClass->hasProperty($property)) {
927 1
                return true;
928
            }
929
        }
930
931
        // check traits for existing property
932 39
        foreach ($this->getTraits($metadata) as $trait) {
933 2
            if ($trait->hasProperty($property)) {
934 2
                return true;
935
            }
936
        }
937
938
        return (
939 39
            isset($this->staticReflection[$metadata->name]) &&
940 39
            in_array($property, $this->staticReflection[$metadata->name]['properties'])
941
        );
942
    }
943
944
    /**
945
     * @param string            $method
946
     * @param ClassMetadataInfo $metadata
947
     *
948
     * @return bool
949
     */
950 41
    protected function hasMethod($method, ClassMetadataInfo $metadata)
951
    {
952 41
        if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) {
953
            // don't generate method if its already on the base class.
954 2
            $reflClass = new \ReflectionClass($this->getClassToExtend() ?: $metadata->name);
955
956 2
            if ($reflClass->hasMethod($method)) {
957 1
                return true;
958
            }
959
        }
960
961
        // check traits for existing method
962 41
        foreach ($this->getTraits($metadata) as $trait) {
963 2
            if ($trait->hasMethod($method)) {
964 2
                return true;
965
            }
966
        }
967
968
        return (
969 41
            isset($this->staticReflection[$metadata->name]) &&
970 41
            in_array(strtolower($method), $this->staticReflection[$metadata->name]['methods'])
971
        );
972
    }
973
974
    /**
975
     * @param ClassMetadataInfo $metadata
976
     *
977
     * @return array
978
     */
979 41
    protected function getTraits(ClassMetadataInfo $metadata)
980
    {
981 41
        if (! ($metadata->reflClass !== null || class_exists($metadata->name))) {
982 35
            return [];
983
        }
984
985 7
        $reflClass = $metadata->reflClass === null
986 1
            ? new \ReflectionClass($metadata->name)
987 7
            : $metadata->reflClass;
988
989 7
        $traits = array();
990
991 7
        while ($reflClass !== false) {
992 7
            $traits = array_merge($traits, $reflClass->getTraits());
993
994 7
            $reflClass = $reflClass->getParentClass();
995
        }
996
997 7
        return $traits;
998
    }
999
1000
    /**
1001
     * @param ClassMetadataInfo $metadata
1002
     *
1003
     * @return bool
1004
     */
1005 40
    protected function hasNamespace(ClassMetadataInfo $metadata)
1006
    {
1007 40
        return strpos($metadata->name, '\\') ? true : false;
1008
    }
1009
1010
    /**
1011
     * @return bool
1012
     */
1013 41
    protected function extendsClass()
1014
    {
1015 41
        return $this->classToExtend ? true : false;
1016
    }
1017
1018
    /**
1019
     * @return string
1020
     */
1021 2
    protected function getClassToExtend()
1022
    {
1023 2
        return $this->classToExtend;
1024
    }
1025
1026
    /**
1027
     * @return string
1028
     */
1029 1
    protected function getClassToExtendName()
1030
    {
1031 1
        $refl = new \ReflectionClass($this->getClassToExtend());
1032
1033 1
        return '\\' . $refl->getName();
1034
    }
1035
1036
    /**
1037
     * @param ClassMetadataInfo $metadata
1038
     *
1039
     * @return string
1040
     */
1041 41
    protected function getClassName(ClassMetadataInfo $metadata)
1042
    {
1043 41
        return ($pos = strrpos($metadata->name, '\\'))
1044 41
            ? substr($metadata->name, $pos + 1, strlen($metadata->name)) : $metadata->name;
1045
    }
1046
1047
    /**
1048
     * @param ClassMetadataInfo $metadata
1049
     *
1050
     * @return string
1051
     */
1052 40
    protected function getNamespace(ClassMetadataInfo $metadata)
1053
    {
1054 40
        return substr($metadata->name, 0, strrpos($metadata->name, '\\'));
1055
    }
1056
1057
    /**
1058
     * @param ClassMetadataInfo $metadata
1059
     *
1060
     * @return string
1061
     */
1062 40
    protected function generateEntityDocBlock(ClassMetadataInfo $metadata)
1063
    {
1064 40
        $lines = array();
1065 40
        $lines[] = '/**';
1066 40
        $lines[] = ' * ' . $this->getClassName($metadata);
1067
1068 40
        if ($this->generateAnnotations) {
1069 40
            $lines[] = ' *';
1070
1071
            $methods = array(
1072 40
                'generateTableAnnotation',
1073
                'generateInheritanceAnnotation',
1074
                'generateDiscriminatorColumnAnnotation',
1075
                'generateDiscriminatorMapAnnotation',
1076
                'generateEntityAnnotation',
1077
            );
1078
1079 40
            foreach ($methods as $method) {
1080 40
                if ($code = $this->$method($metadata)) {
1081 40
                    $lines[] = ' * ' . $code;
1082
                }
1083
            }
1084
1085 40
            if (isset($metadata->lifecycleCallbacks) && $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...
1086 11
                $lines[] = ' * @' . $this->annotationsPrefix . 'HasLifecycleCallbacks';
1087
            }
1088
        }
1089
1090 40
        $lines[] = ' */';
1091
1092 40
        return implode("\n", $lines);
1093
    }
1094
1095
    /**
1096
     * @param ClassMetadataInfo $metadata
1097
     *
1098
     * @return string
1099
     */
1100 40
    protected function generateEntityAnnotation(ClassMetadataInfo $metadata)
1101
    {
1102 40
        $prefix = '@' . $this->annotationsPrefix;
1103
1104 40
        if ($metadata->isEmbeddedClass) {
1105 9
            return $prefix . 'Embeddable';
1106
        }
1107
1108 38
        $customRepository = $metadata->customRepositoryClassName
1109 12
            ? '(repositoryClass="' . $metadata->customRepositoryClassName . '")'
1110 38
            : '';
1111
1112 38
        return $prefix . ($metadata->isMappedSuperclass ? 'MappedSuperclass' : 'Entity') . $customRepository;
1113
    }
1114
1115
    /**
1116
     * @param ClassMetadataInfo $metadata
1117
     *
1118
     * @return string
1119
     */
1120 40
    protected function generateTableAnnotation($metadata)
1121
    {
1122 40
        if ($metadata->isEmbeddedClass) {
1123 9
            return '';
1124
        }
1125
1126 38
        $table = array();
1127
1128 38
        if (isset($metadata->table['schema'])) {
1129
            $table[] = 'schema="' . $metadata->table['schema'] . '"';
1130
        }
1131
1132 38
        if (isset($metadata->table['name'])) {
1133 35
            $table[] = 'name="' . $metadata->table['name'] . '"';
1134
        }
1135
1136 38
        if (isset($metadata->table['options']) && $metadata->table['options']) {
1137 1
            $table[] = 'options={' . $this->exportTableOptions((array) $metadata->table['options']) . '}';
1138
        }
1139
1140 38
        if (isset($metadata->table['uniqueConstraints']) && $metadata->table['uniqueConstraints']) {
1141 10
            $constraints = $this->generateTableConstraints('UniqueConstraint', $metadata->table['uniqueConstraints']);
1142 10
            $table[] = 'uniqueConstraints={' . $constraints . '}';
1143
        }
1144
1145 38
        if (isset($metadata->table['indexes']) && $metadata->table['indexes']) {
1146 10
            $constraints = $this->generateTableConstraints('Index', $metadata->table['indexes']);
1147 10
            $table[] = 'indexes={' . $constraints . '}';
1148
        }
1149
1150 38
        return '@' . $this->annotationsPrefix . 'Table(' . implode(', ', $table) . ')';
1151
    }
1152
1153
    /**
1154
     * @param string $constraintName
1155
     * @param array  $constraints
1156
     *
1157
     * @return string
1158
     */
1159 10
    protected function generateTableConstraints($constraintName, $constraints)
1160
    {
1161 10
        $annotations = array();
1162 10
        foreach ($constraints as $name => $constraint) {
1163 10
            $columns = array();
1164 10
            foreach ($constraint['columns'] as $column) {
1165 10
                $columns[] = '"' . $column . '"';
1166
            }
1167 10
            $annotations[] = '@' . $this->annotationsPrefix . $constraintName . '(name="' . $name . '", columns={' . implode(', ', $columns) . '})';
1168
        }
1169
1170 10
        return implode(', ', $annotations);
1171
    }
1172
1173
    /**
1174
     * @param ClassMetadataInfo $metadata
1175
     *
1176
     * @return string
1177
     */
1178 40
    protected function generateInheritanceAnnotation($metadata)
1179
    {
1180 40
        if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) {
1181
            return '@' . $this->annotationsPrefix . 'InheritanceType("'.$this->getInheritanceTypeString($metadata->inheritanceType).'")';
1182
        }
1183 40
    }
1184
1185
    /**
1186
     * @param ClassMetadataInfo $metadata
1187
     *
1188
     * @return string
1189
     */
1190 40
    protected function generateDiscriminatorColumnAnnotation($metadata)
1191
    {
1192 40
        if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) {
1193
            $discrColumn = $metadata->discriminatorColumn;
1194
            $columnDefinition = 'name="' . $discrColumn['name']
1195
                . '", type="' . $discrColumn['type']
1196
                . '", length=' . $discrColumn['length'];
1197
1198
            return '@' . $this->annotationsPrefix . 'DiscriminatorColumn(' . $columnDefinition . ')';
1199
        }
1200 40
    }
1201
1202
    /**
1203
     * @param ClassMetadataInfo $metadata
1204
     *
1205
     * @return string
1206
     */
1207 40
    protected function generateDiscriminatorMapAnnotation($metadata)
1208
    {
1209 40
        if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) {
1210
            $inheritanceClassMap = array();
1211
1212
            foreach ($metadata->discriminatorMap as $type => $class) {
1213
                $inheritanceClassMap[] .= '"' . $type . '" = "' . $class . '"';
1214
            }
1215
1216
            return '@' . $this->annotationsPrefix . 'DiscriminatorMap({' . implode(', ', $inheritanceClassMap) . '})';
1217
        }
1218 40
    }
1219
1220
    /**
1221
     * @param ClassMetadataInfo $metadata
1222
     *
1223
     * @return string
1224
     */
1225 40
    protected function generateEntityStubMethods(ClassMetadataInfo $metadata)
1226
    {
1227 40
        $methods = array();
1228
1229 40
        foreach ($metadata->fieldMappings as $fieldMapping) {
1230 39
            if (isset($fieldMapping['declaredField']) &&
1231 39
                isset($metadata->embeddedClasses[$fieldMapping['declaredField']])
1232
            ) {
1233
                continue;
1234
            }
1235
1236 39
            if (( ! isset($fieldMapping['id']) ||
1237 37
                    ! $fieldMapping['id'] ||
1238 39
                    $metadata->generatorType == ClassMetadataInfo::GENERATOR_TYPE_NONE
1239 39
                ) && (! $metadata->isEmbeddedClass || ! $this->embeddablesImmutable)
1240
            ) {
1241 36
                if ($code = $this->generateEntityStubMethod($metadata, 'set', $fieldMapping['fieldName'], $fieldMapping['type'])) {
1242 36
                    $methods[] = $code;
1243
                }
1244
            }
1245
1246 39
            if ($code = $this->generateEntityStubMethod($metadata, 'get', $fieldMapping['fieldName'], $fieldMapping['type'])) {
1247 39
                $methods[] = $code;
1248
            }
1249
        }
1250
1251 40
        foreach ($metadata->embeddedClasses as $fieldName => $embeddedClass) {
1252 8
            if (isset($embeddedClass['declaredField'])) {
1253 1
                continue;
1254
            }
1255
1256 8
            if ( ! $metadata->isEmbeddedClass || ! $this->embeddablesImmutable) {
1257 7
                if ($code = $this->generateEntityStubMethod($metadata, 'set', $fieldName, $embeddedClass['class'])) {
1258 7
                    $methods[] = $code;
1259
                }
1260
            }
1261
1262 8
            if ($code = $this->generateEntityStubMethod($metadata, 'get', $fieldName, $embeddedClass['class'])) {
1263 8
                $methods[] = $code;
1264
            }
1265
        }
1266
1267 40
        foreach ($metadata->associationMappings as $associationMapping) {
1268 13
            if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
1269 12
                $nullable = $this->isAssociationIsNullable($associationMapping) ? 'null' : null;
1270 12
                if ($code = $this->generateEntityStubMethod($metadata, 'set', $associationMapping['fieldName'], $associationMapping['targetEntity'], $nullable)) {
1271 10
                    $methods[] = $code;
1272
                }
1273 12
                if ($code = $this->generateEntityStubMethod($metadata, 'get', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
1274 12
                    $methods[] = $code;
1275
                }
1276 11
            } elseif ($associationMapping['type'] & ClassMetadataInfo::TO_MANY) {
1277 11
                if ($code = $this->generateEntityStubMethod($metadata, 'add', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
1278 11
                    $methods[] = $code;
1279
                }
1280 11
                if ($code = $this->generateEntityStubMethod($metadata, 'remove', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
1281 11
                    $methods[] = $code;
1282
                }
1283 11
                if ($code = $this->generateEntityStubMethod($metadata, 'get', $associationMapping['fieldName'], 'Doctrine\Common\Collections\Collection')) {
1284 13
                    $methods[] = $code;
1285
                }
1286
            }
1287
        }
1288
1289 40
        return implode("\n\n", $methods);
1290
    }
1291
1292
    /**
1293
     * @param array $associationMapping
1294
     *
1295
     * @return bool
1296
     */
1297 12
    protected function isAssociationIsNullable($associationMapping)
1298
    {
1299 12
        if (isset($associationMapping['id']) && $associationMapping['id']) {
1300
            return false;
1301
        }
1302
1303 12
        if (isset($associationMapping['joinColumns'])) {
1304 2
            $joinColumns = $associationMapping['joinColumns'];
1305
        } else {
1306
            //@todo there is no way to retrieve targetEntity metadata
1307 10
            $joinColumns = array();
1308
        }
1309
1310 12
        foreach ($joinColumns as $joinColumn) {
1311 2
            if (isset($joinColumn['nullable']) && !$joinColumn['nullable']) {
1312 2
                return false;
1313
            }
1314
        }
1315
1316 12
        return true;
1317
    }
1318
1319
    /**
1320
     * @param ClassMetadataInfo $metadata
1321
     *
1322
     * @return string
1323
     */
1324 41
    protected function generateEntityLifecycleCallbackMethods(ClassMetadataInfo $metadata)
1325
    {
1326 41
        if (isset($metadata->lifecycleCallbacks) && $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...
1327 11
            $methods = array();
1328
1329 11
            foreach ($metadata->lifecycleCallbacks as $name => $callbacks) {
1330 11
                foreach ($callbacks as $callback) {
1331 11
                    if ($code = $this->generateLifecycleCallbackMethod($name, $callback, $metadata)) {
1332 11
                        $methods[] = $code;
1333
                    }
1334
                }
1335
            }
1336
1337 11
            return implode("\n\n", $methods);
1338
        }
1339
1340 37
        return "";
1341
    }
1342
1343
    /**
1344
     * @param ClassMetadataInfo $metadata
1345
     *
1346
     * @return string
1347
     */
1348 41
    protected function generateEntityAssociationMappingProperties(ClassMetadataInfo $metadata)
1349
    {
1350 41
        $lines = array();
1351
1352 41
        foreach ($metadata->associationMappings as $associationMapping) {
1353 14
            if ($this->hasProperty($associationMapping['fieldName'], $metadata)) {
1354 4
                continue;
1355
            }
1356
1357 12
            $lines[] = $this->generateAssociationMappingPropertyDocBlock($associationMapping, $metadata);
1358 12
            $lines[] = $this->spaces . $this->fieldVisibility . ' $' . $associationMapping['fieldName']
1359 12
                     . ($associationMapping['type'] == 'manyToMany' ? ' = array()' : null) . ";\n";
1360
        }
1361
1362 41
        return implode("\n", $lines);
1363
    }
1364
1365
    /**
1366
     * @param ClassMetadataInfo $metadata
1367
     *
1368
     * @return string
1369
     */
1370 41
    protected function generateEntityFieldMappingProperties(ClassMetadataInfo $metadata)
1371
    {
1372 41
        $lines = array();
1373
1374 41
        foreach ($metadata->fieldMappings as $fieldMapping) {
1375 40
            if ($this->hasProperty($fieldMapping['fieldName'], $metadata) ||
1376 39
                $metadata->isInheritedField($fieldMapping['fieldName']) ||
1377
                (
1378 38
                    isset($fieldMapping['declaredField']) &&
1379 40
                    isset($metadata->embeddedClasses[$fieldMapping['declaredField']])
1380
                )
1381
            ) {
1382 4
                continue;
1383
            }
1384
1385 38
            $lines[] = $this->generateFieldMappingPropertyDocBlock($fieldMapping, $metadata);
1386 38
            $lines[] = $this->spaces . $this->fieldVisibility . ' $' . $fieldMapping['fieldName']
1387 38
                     . (isset($fieldMapping['options']['default']) ? ' = ' . var_export($fieldMapping['options']['default'], true) : null) . ";\n";
1388
        }
1389
1390 41
        return implode("\n", $lines);
1391
    }
1392
1393
    /**
1394
     * @param ClassMetadataInfo $metadata
1395
     *
1396
     * @return string
1397
     */
1398 41
    protected function generateEntityEmbeddedProperties(ClassMetadataInfo $metadata)
1399
    {
1400 41
        $lines = array();
1401
1402 41
        foreach ($metadata->embeddedClasses as $fieldName => $embeddedClass) {
1403 8
            if (isset($embeddedClass['declaredField']) || $this->hasProperty($fieldName, $metadata)) {
1404 2
                continue;
1405
            }
1406
1407 8
            $lines[] = $this->generateEmbeddedPropertyDocBlock($embeddedClass);
1408 8
            $lines[] = $this->spaces . $this->fieldVisibility . ' $' . $fieldName . ";\n";
1409
        }
1410
1411 41
        return implode("\n", $lines);
1412
    }
1413
1414
    /**
1415
     * @param ClassMetadataInfo $metadata
1416
     * @param string            $type
1417
     * @param string            $fieldName
1418
     * @param string|null       $typeHint
1419
     * @param string|null       $defaultValue
1420
     *
1421
     * @return string
1422
     */
1423 39
    protected function generateEntityStubMethod(ClassMetadataInfo $metadata, $type, $fieldName, $typeHint = null,  $defaultValue = null)
1424
    {
1425 39
        $methodName = $type . Inflector::classify($fieldName);
1426 39
        $variableName = Inflector::camelize($fieldName);
1427 39
        if (in_array($type, array("add", "remove"))) {
1428 11
            $methodName = Inflector::singularize($methodName);
1429 11
            $variableName = Inflector::singularize($variableName);
1430
        }
1431
1432 39
        if ($this->hasMethod($methodName, $metadata)) {
1433 5
            return '';
1434
        }
1435 39
        $this->staticReflection[$metadata->name]['methods'][] = strtolower($methodName);
1436
1437 39
        $var = sprintf('%sMethodTemplate', $type);
1438 39
        $template = static::$$var;
1439
1440 39
        $methodTypeHint = null;
1441 39
        $types          = Type::getTypesMap();
1442 39
        $variableType   = $typeHint ? $this->getType($typeHint) : null;
1443
1444 39
        if ($typeHint && ! isset($types[$typeHint])) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $typeHint of type string|null 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...
1445 13
            $variableType   =  '\\' . ltrim($variableType, '\\');
1446 13
            $methodTypeHint =  '\\' . $typeHint . ' ';
1447
        }
1448
1449 39
        $methodReturnType = null;
1450 39
        if ($this->generateMethodsTypeHinting) {
1451 11
            $methodReturnType = $this->getMethodReturnType($metadata, $type, $fieldName, $variableType);
1452
1453 11
            if (null === $methodTypeHint) {
1454 11
                $type = isset($this->typeHintingAlias[$variableType]) ? $this->typeHintingAlias[$variableType] : $variableType;
1455 11
                $methodTypeHint = $type.' ';
1456
            }
1457
        }
1458
1459
        $replacements = array(
1460 39
          '<description>'       => ucfirst($type) . ' ' . $variableName,
1461 39
          '<methodTypeHint>'    => $methodTypeHint,
1462 39
          '<variableType>'      => $variableType,
1463 39
          '<variableName>'      => $variableName,
1464 39
          '<methodName>'        => $methodName,
1465 39
          '<fieldName>'         => $fieldName,
1466 39
          '<variableDefault>'   => ($defaultValue !== null ) ? (' = '.$defaultValue) : '',
1467 39
          '<entity>'            => $this->getClassName($metadata),
1468 39
          '<methodTypeReturn>'  => $methodReturnType,
1469
        );
1470
1471 39
        $method = str_replace(
1472
            array_keys($replacements),
1473
            array_values($replacements),
1474
            $template
1475
        );
1476
1477 39
        return $this->prefixCodeWithSpaces($method);
1478
    }
1479
1480
    /**
1481
     * @param string            $name
1482
     * @param string            $methodName
1483
     * @param ClassMetadataInfo $metadata
1484
     *
1485
     * @return string
1486
     */
1487 11
    protected function generateLifecycleCallbackMethod($name, $methodName, $metadata)
1488
    {
1489 11
        if ($this->hasMethod($methodName, $metadata)) {
1490 2
            return '';
1491
        }
1492 11
        $this->staticReflection[$metadata->name]['methods'][] = $methodName;
1493
1494
        $replacements = array(
1495 11
            '<name>'        => $this->annotationsPrefix . ucfirst($name),
1496 11
            '<methodName>'  => $methodName,
1497
        );
1498
1499 11
        $method = str_replace(
1500
            array_keys($replacements),
1501
            array_values($replacements),
1502 11
            static::$lifecycleCallbackMethodTemplate
1503
        );
1504
1505 11
        return $this->prefixCodeWithSpaces($method);
1506
    }
1507
1508
    /**
1509
     * @param array $joinColumn
1510
     *
1511
     * @return string
1512
     */
1513 12
    protected function generateJoinColumnAnnotation(array $joinColumn)
1514
    {
1515 12
        $joinColumnAnnot = array();
1516
1517 12
        if (isset($joinColumn['name'])) {
1518 12
            $joinColumnAnnot[] = 'name="' . $joinColumn['name'] . '"';
1519
        }
1520
1521 12
        if (isset($joinColumn['referencedColumnName'])) {
1522 12
            $joinColumnAnnot[] = 'referencedColumnName="' . $joinColumn['referencedColumnName'] . '"';
1523
        }
1524
1525 12
        if (isset($joinColumn['unique']) && $joinColumn['unique']) {
1526 1
            $joinColumnAnnot[] = 'unique=' . ($joinColumn['unique'] ? 'true' : 'false');
1527
        }
1528
1529 12
        if (isset($joinColumn['nullable'])) {
1530 1
            $joinColumnAnnot[] = 'nullable=' . ($joinColumn['nullable'] ? 'true' : 'false');
1531
        }
1532
1533 12
        if (isset($joinColumn['onDelete'])) {
1534 1
            $joinColumnAnnot[] = 'onDelete="' . ($joinColumn['onDelete'] . '"');
1535
        }
1536
1537 12
        if (isset($joinColumn['columnDefinition'])) {
1538 1
            $joinColumnAnnot[] = 'columnDefinition="' . $joinColumn['columnDefinition'] . '"';
1539
        }
1540
1541 12
        return '@' . $this->annotationsPrefix . 'JoinColumn(' . implode(', ', $joinColumnAnnot) . ')';
1542
    }
1543
1544
    /**
1545
     * @param array             $associationMapping
1546
     * @param ClassMetadataInfo $metadata
1547
     *
1548
     * @return string
1549
     */
1550 12
    protected function generateAssociationMappingPropertyDocBlock(array $associationMapping, ClassMetadataInfo $metadata)
1551
    {
1552 12
        $lines = array();
1553 12
        $lines[] = $this->spaces . '/**';
1554
1555 12
        if ($associationMapping['type'] & ClassMetadataInfo::TO_MANY) {
1556 12
            $lines[] = $this->spaces . ' * @var \Doctrine\Common\Collections\Collection';
1557
        } else {
1558 11
            $lines[] = $this->spaces . ' * @var \\' . ltrim($associationMapping['targetEntity'], '\\');
1559
        }
1560
1561 12
        if ($this->generateAnnotations) {
1562 12
            $lines[] = $this->spaces . ' *';
1563
1564 12
            if (isset($associationMapping['id']) && $associationMapping['id']) {
1565
                $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Id';
1566
1567
                if ($generatorType = $this->getIdGeneratorTypeString($metadata->generatorType)) {
1568
                    $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'GeneratedValue(strategy="' . $generatorType . '")';
1569
                }
1570
            }
1571
1572 12
            $type = null;
1573 12
            switch ($associationMapping['type']) {
1574 12
                case ClassMetadataInfo::ONE_TO_ONE:
1575 11
                    $type = 'OneToOne';
1576 11
                    break;
1577 12
                case ClassMetadataInfo::MANY_TO_ONE:
1578 1
                    $type = 'ManyToOne';
1579 1
                    break;
1580 12
                case ClassMetadataInfo::ONE_TO_MANY:
1581 1
                    $type = 'OneToMany';
1582 1
                    break;
1583 12
                case ClassMetadataInfo::MANY_TO_MANY:
1584 12
                    $type = 'ManyToMany';
1585 12
                    break;
1586
            }
1587 12
            $typeOptions = array();
1588
1589 12
            if (isset($associationMapping['targetEntity'])) {
1590 12
                $typeOptions[] = 'targetEntity="' . $associationMapping['targetEntity'] . '"';
1591
            }
1592
1593 12
            if (isset($associationMapping['inversedBy'])) {
1594 1
                $typeOptions[] = 'inversedBy="' . $associationMapping['inversedBy'] . '"';
1595
            }
1596
1597 12
            if (isset($associationMapping['mappedBy'])) {
1598 11
                $typeOptions[] = 'mappedBy="' . $associationMapping['mappedBy'] . '"';
1599
            }
1600
1601 12
            if ($associationMapping['cascade']) {
1602 1
                $cascades = array();
1603
1604 1
                if ($associationMapping['isCascadePersist']) $cascades[] = '"persist"';
1605 1
                if ($associationMapping['isCascadeRemove']) $cascades[] = '"remove"';
1606 1
                if ($associationMapping['isCascadeDetach']) $cascades[] = '"detach"';
1607 1
                if ($associationMapping['isCascadeMerge']) $cascades[] = '"merge"';
1608 1
                if ($associationMapping['isCascadeRefresh']) $cascades[] = '"refresh"';
1609
1610 1
                if (count($cascades) === 5) {
1611 1
                    $cascades = array('"all"');
1612
                }
1613
1614 1
                $typeOptions[] = 'cascade={' . implode(',', $cascades) . '}';
1615
            }
1616
1617 12
            if (isset($associationMapping['orphanRemoval']) && $associationMapping['orphanRemoval']) {
1618 1
                $typeOptions[] = 'orphanRemoval=' . ($associationMapping['orphanRemoval'] ? 'true' : 'false');
1619
            }
1620
1621 12
            if (isset($associationMapping['fetch']) && $associationMapping['fetch'] !== ClassMetadataInfo::FETCH_LAZY) {
1622
                $fetchMap = array(
1623 11
                    ClassMetadataInfo::FETCH_EXTRA_LAZY => 'EXTRA_LAZY',
1624 11
                    ClassMetadataInfo::FETCH_EAGER      => 'EAGER',
1625
                );
1626
1627 11
                $typeOptions[] = 'fetch="' . $fetchMap[$associationMapping['fetch']] . '"';
1628
            }
1629
1630 12
            $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . '' . $type . '(' . implode(', ', $typeOptions) . ')';
1631
1632 12
            if (isset($associationMapping['joinColumns']) && $associationMapping['joinColumns']) {
1633 1
                $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'JoinColumns({';
1634
1635 1
                $joinColumnsLines = array();
1636
1637 1
                foreach ($associationMapping['joinColumns'] as $joinColumn) {
1638 1
                    if ($joinColumnAnnot = $this->generateJoinColumnAnnotation($joinColumn)) {
1639 1
                        $joinColumnsLines[] = $this->spaces . ' *   ' . $joinColumnAnnot;
1640
                    }
1641
                }
1642
1643 1
                $lines[] = implode(",\n", $joinColumnsLines);
1644 1
                $lines[] = $this->spaces . ' * })';
1645
            }
1646
1647 12
            if (isset($associationMapping['joinTable']) && $associationMapping['joinTable']) {
1648 12
                $joinTable = array();
1649 12
                $joinTable[] = 'name="' . $associationMapping['joinTable']['name'] . '"';
1650
1651 12
                if (isset($associationMapping['joinTable']['schema'])) {
1652
                    $joinTable[] = 'schema="' . $associationMapping['joinTable']['schema'] . '"';
1653
                }
1654
1655 12
                $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'JoinTable(' . implode(', ', $joinTable) . ',';
1656 12
                $lines[] = $this->spaces . ' *   joinColumns={';
1657
1658 12
                $joinColumnsLines = array();
1659
1660 12
                foreach ($associationMapping['joinTable']['joinColumns'] as $joinColumn) {
1661 12
                    $joinColumnsLines[] = $this->spaces . ' *     ' . $this->generateJoinColumnAnnotation($joinColumn);
1662
                }
1663
1664 12
                $lines[] = implode(",". PHP_EOL, $joinColumnsLines);
1665 12
                $lines[] = $this->spaces . ' *   },';
1666 12
                $lines[] = $this->spaces . ' *   inverseJoinColumns={';
1667
1668 12
                $inverseJoinColumnsLines = array();
1669
1670 12
                foreach ($associationMapping['joinTable']['inverseJoinColumns'] as $joinColumn) {
1671 12
                    $inverseJoinColumnsLines[] = $this->spaces . ' *     ' . $this->generateJoinColumnAnnotation($joinColumn);
1672
                }
1673
1674 12
                $lines[] = implode(",". PHP_EOL, $inverseJoinColumnsLines);
1675 12
                $lines[] = $this->spaces . ' *   }';
1676 12
                $lines[] = $this->spaces . ' * )';
1677
            }
1678
1679 12
            if (isset($associationMapping['orderBy'])) {
1680 1
                $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'OrderBy({';
1681
1682 1
                foreach ($associationMapping['orderBy'] as $name => $direction) {
1683 1
                    $lines[] = $this->spaces . ' *     "' . $name . '"="' . $direction . '",';
1684
                }
1685
1686 1
                $lines[count($lines) - 1] = substr($lines[count($lines) - 1], 0, strlen($lines[count($lines) - 1]) - 1);
1687 1
                $lines[] = $this->spaces . ' * })';
1688
            }
1689
        }
1690
1691 12
        $lines[] = $this->spaces . ' */';
1692
1693 12
        return implode("\n", $lines);
1694
    }
1695
1696
    /**
1697
     * @param array             $fieldMapping
1698
     * @param ClassMetadataInfo $metadata
1699
     *
1700
     * @return string
1701
     */
1702 38
    protected function generateFieldMappingPropertyDocBlock(array $fieldMapping, ClassMetadataInfo $metadata)
1703
    {
1704 38
        $lines = array();
1705 38
        $lines[] = $this->spaces . '/**';
1706 38
        $lines[] = $this->spaces . ' * @var ' . $this->getType($fieldMapping['type']);
1707
1708 38
        if ($this->generateAnnotations) {
1709 38
            $lines[] = $this->spaces . ' *';
1710
1711 38
            $column = array();
1712 38
            if (isset($fieldMapping['columnName'])) {
1713 38
                $column[] = 'name="' . $fieldMapping['columnName'] . '"';
1714
            }
1715
1716 38
            if (isset($fieldMapping['type'])) {
1717 38
                $column[] = 'type="' . $fieldMapping['type'] . '"';
1718
            }
1719
1720 38
            if (isset($fieldMapping['length'])) {
1721 4
                $column[] = 'length=' . $fieldMapping['length'];
1722
            }
1723
1724 38
            if (isset($fieldMapping['precision'])) {
1725 4
                $column[] = 'precision=' .  $fieldMapping['precision'];
1726
            }
1727
1728 38
            if (isset($fieldMapping['scale'])) {
1729 4
                $column[] = 'scale=' . $fieldMapping['scale'];
1730
            }
1731
1732 38
            if (isset($fieldMapping['nullable'])) {
1733 8
                $column[] = 'nullable=' .  var_export($fieldMapping['nullable'], true);
1734
            }
1735
1736 38
            $options = [];
1737
1738 38
            if (isset($fieldMapping['options']['unsigned']) && $fieldMapping['options']['unsigned']) {
1739 1
                $options[] = '"unsigned"=true';
1740
            }
1741
1742 38
            if ($options) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $options 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...
1743 1
                $column[] = 'options={'.implode(',', $options).'}';
1744
            }
1745
1746 38
            if (isset($fieldMapping['columnDefinition'])) {
1747 1
                $column[] = 'columnDefinition="' . $fieldMapping['columnDefinition'] . '"';
1748
            }
1749
1750 38
            if (isset($fieldMapping['unique'])) {
1751 4
                $column[] = 'unique=' . var_export($fieldMapping['unique'], true);
1752
            }
1753
1754 38
            $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Column(' . implode(', ', $column) . ')';
1755
1756 38
            if (isset($fieldMapping['id']) && $fieldMapping['id']) {
1757 36
                $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Id';
1758
1759 36
                if ($generatorType = $this->getIdGeneratorTypeString($metadata->generatorType)) {
1760 36
                    $lines[] = $this->spaces.' * @' . $this->annotationsPrefix . 'GeneratedValue(strategy="' . $generatorType . '")';
1761
                }
1762
1763 36
                if ($metadata->sequenceGeneratorDefinition) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $metadata->sequenceGeneratorDefinition 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...
1764 1
                    $sequenceGenerator = array();
1765
1766 1
                    if (isset($metadata->sequenceGeneratorDefinition['sequenceName'])) {
1767 1
                        $sequenceGenerator[] = 'sequenceName="' . $metadata->sequenceGeneratorDefinition['sequenceName'] . '"';
1768
                    }
1769
1770 1
                    if (isset($metadata->sequenceGeneratorDefinition['allocationSize'])) {
1771 1
                        $sequenceGenerator[] = 'allocationSize=' . $metadata->sequenceGeneratorDefinition['allocationSize'];
1772
                    }
1773
1774 1
                    if (isset($metadata->sequenceGeneratorDefinition['initialValue'])) {
1775 1
                        $sequenceGenerator[] = 'initialValue=' . $metadata->sequenceGeneratorDefinition['initialValue'];
1776
                    }
1777
1778 1
                    $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'SequenceGenerator(' . implode(', ', $sequenceGenerator) . ')';
1779
                }
1780
            }
1781
1782 38
            if (isset($fieldMapping['version']) && $fieldMapping['version']) {
1783
                $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Version';
1784
            }
1785
        }
1786
1787 38
        $lines[] = $this->spaces . ' */';
1788
1789 38
        return implode("\n", $lines);
1790
    }
1791
1792
    /**
1793
     * @param array $embeddedClass
1794
     *
1795
     * @return string
1796
     */
1797 8
    protected function generateEmbeddedPropertyDocBlock(array $embeddedClass)
1798
    {
1799 8
        $lines = array();
1800 8
        $lines[] = $this->spaces . '/**';
1801 8
        $lines[] = $this->spaces . ' * @var \\' . ltrim($embeddedClass['class'], '\\');
1802
1803 8
        if ($this->generateAnnotations) {
1804 8
            $lines[] = $this->spaces . ' *';
1805
1806 8
            $embedded = array('class="' . $embeddedClass['class'] . '"');
1807
1808 8
            if (isset($fieldMapping['columnPrefix'])) {
0 ignored issues
show
Bug introduced by
The variable $fieldMapping seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
1809
                $embedded[] = 'columnPrefix=' . var_export($embeddedClass['columnPrefix'], true);
1810
            }
1811
1812 8
            $lines[] = $this->spaces . ' * @' .
1813 8
                $this->annotationsPrefix . 'Embedded(' . implode(', ', $embedded) . ')';
1814
        }
1815
1816 8
        $lines[] = $this->spaces . ' */';
1817
1818 8
        return implode("\n", $lines);
1819
    }
1820
1821
    /**
1822
     * @param string $code
1823
     * @param int    $num
1824
     *
1825
     * @return string
1826
     */
1827 40
    protected function prefixCodeWithSpaces($code, $num = 1)
1828
    {
1829 40
        $lines = explode("\n", $code);
1830
1831 40
        foreach ($lines as $key => $value) {
1832 40
            if ( ! empty($value)) {
1833 40
                $lines[$key] = str_repeat($this->spaces, $num) . $lines[$key];
1834
            }
1835
        }
1836
1837 40
        return implode("\n", $lines);
1838
    }
1839
1840
    /**
1841
     * @param integer $type The inheritance type used by the class and its subclasses.
1842
     *
1843
     * @return string The literal string for the inheritance type.
1844
     *
1845
     * @throws \InvalidArgumentException When the inheritance type does not exist.
1846
     */
1847 1
    protected function getInheritanceTypeString($type)
1848
    {
1849 1
        if ( ! isset(static::$inheritanceTypeMap[$type])) {
1850 1
            throw new \InvalidArgumentException(sprintf('Invalid provided InheritanceType: %s', $type));
1851
        }
1852
1853 1
        return static::$inheritanceTypeMap[$type];
1854
    }
1855
1856
    /**
1857
     * @param integer $type The policy used for change-tracking for the mapped class.
1858
     *
1859
     * @return string The literal string for the change-tracking type.
1860
     *
1861
     * @throws \InvalidArgumentException When the change-tracking type does not exist.
1862
     */
1863 1
    protected function getChangeTrackingPolicyString($type)
1864
    {
1865 1
        if ( ! isset(static::$changeTrackingPolicyMap[$type])) {
1866 1
            throw new \InvalidArgumentException(sprintf('Invalid provided ChangeTrackingPolicy: %s', $type));
1867
        }
1868
1869 1
        return static::$changeTrackingPolicyMap[$type];
1870
    }
1871
1872
    /**
1873
     * @param integer $type The generator to use for the mapped class.
1874
     *
1875
     * @return string The literal string for the generator type.
1876
     *
1877
     * @throws \InvalidArgumentException    When the generator type does not exist.
1878
     */
1879 37
    protected function getIdGeneratorTypeString($type)
1880
    {
1881 37
        if ( ! isset(static::$generatorStrategyMap[$type])) {
1882 1
            throw new \InvalidArgumentException(sprintf('Invalid provided IdGeneratorType: %s', $type));
1883
        }
1884
1885 37
        return static::$generatorStrategyMap[$type];
1886
    }
1887
1888
    /**
1889
     * Exports (nested) option elements.
1890
     *
1891
     * @param array $options
1892
     *
1893
     * @return string
1894
     */
1895 1
    private function exportTableOptions(array $options)
1896
    {
1897 1
        $optionsStr = array();
1898
1899 1
        foreach ($options as $name => $option) {
1900 1
            if (is_array($option)) {
1901 1
                $optionsStr[] = '"' . $name . '"={' . $this->exportTableOptions($option) . '}';
1902
            } else {
1903 1
                $optionsStr[] = '"' . $name . '"="' . (string) $option . '"';
1904
            }
1905
        }
1906
1907 1
        return implode(',', $optionsStr);
1908
    }
1909
1910
    /**
1911
     * @param ClassMetadataInfo $metadata
1912
     * @param string            $type
1913
     * @param string            $fieldName
1914
     * @param string            $variableType
1915
     * @return string
1916
     */
1917 11
    private function getMethodReturnType(ClassMetadataInfo $metadata, $type, $fieldName, $variableType)
1918
    {
1919 11
        if (in_array($type, array('set', 'add'))) {
1920 11
            return sprintf(': self', $this->getClassName($metadata));
1921
        }
1922
1923 11
        if ('get' === $type) {
1924
            if (
1925 11
                $metadata->isSingleValuedAssociation($fieldName) ||
1926 11
                (!$metadata->hasAssociation($fieldName) && $metadata->isNullable($fieldName))
1927
            ) {
1928 1
                return null;
1929
            }
1930
1931 11
            $type = isset($this->typeHintingAlias[$variableType]) ? $this->typeHintingAlias[$variableType] : $variableType;
1932 11
            return sprintf(': %s', $type);
1933
        }
1934
1935 1
        if ('remove' === $type) {
1936 1
            return ': bool';
1937
        }
1938
1939
        return null;
1940
    }
1941
}
1942