Passed
Push — master ( abb18c...83efca )
by Divine Niiquaye
02:29
created

Embeddings::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 5
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Biurad opensource projects.
7
 *
8
 * PHP version 7.2 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 Biurad Group (https://biurad.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
18
namespace Biurad\Cycle\Annotated;
19
20
use Cycle\Annotated\Annotation\Embeddable;
21
use Cycle\Annotated\Annotation\Relation\RelationInterface;
22
use Cycle\Annotated\Configurator;
23
use Cycle\Annotated\Exception\AnnotationException;
24
use Cycle\Schema\Definition\Entity as EntitySchema;
25
use Cycle\Schema\GeneratorInterface;
26
use Cycle\Schema\Registry;
27
use Doctrine\Common\Annotations\AnnotationException as DoctrineException;
28
use Doctrine\Common\Annotations\AnnotationReader;
29
use ReflectionClass;
30
31
/**
32
 * Generates ORM schema based on annotated classes.
33
 */
34
final class Embeddings implements GeneratorInterface
35
{
36
    /** @var class-string[] */
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string[] at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string[].
Loading history...
37
    private $locator;
38
39
    /** @var AnnotationReader */
40
    private $reader;
41
42
    /** @var Configurator */
43
    private $generator;
44
45
    /**
46
     * @param class-string[]        $locator
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string[] at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string[].
Loading history...
47
     * @param null|AnnotationReader $reader
48
     */
49
    public function __construct(array $classes, AnnotationReader $reader = null)
50
    {
51
        $this->locator   = $classes;
52
        $this->reader    = $reader ?? new AnnotationReader();
53
        $this->generator = new Configurator($this->reader);
54
    }
55
56
    /**
57
     * @param Registry $registry
58
     *
59
     * @return Registry
60
     */
61
    public function run(Registry $registry): Registry
62
    {
63
        foreach ($this->locator as $class) {
64
            try {
65
                $class = new ReflectionClass($class);
66
67
                /** @var Embeddable $em */
68
                $em = $this->reader->getClassAnnotation($class, Embeddable::class);
69
            } catch (DoctrineException $e) {
70
                throw new AnnotationException($e->getMessage(), $e->getCode(), $e);
71
            }
72
73
            if ($em === null) {
74
                continue;
75
            }
76
77
            $e = $this->generator->initEmbedding($em, $class);
78
79
            $this->verifyNoRelations($e, $class);
80
81
            // columns
82
            $this->generator->initFields($e, $class, $em->getColumnPrefix());
83
84
            // register entity (OR find parent)
85
            $registry->register($e);
86
        }
87
88
        return $registry;
89
    }
90
91
    /**
92
     * @param EntitySchema    $entity
93
     * @param ReflectionClass $class
94
     */
95
    public function verifyNoRelations(EntitySchema $entity, ReflectionClass $class): void
96
    {
97
        foreach ($class->getProperties() as $property) {
98
            try {
99
                $ann = $this->reader->getPropertyAnnotations($property);
100
            } catch (DoctrineException $e) {
101
                throw new AnnotationException($e->getMessage(), $e->getCode(), $e);
102
            }
103
104
            foreach ($ann as $ra) {
105
                if ($ra instanceof RelationInterface) {
106
                    throw new AnnotationException(
107
                        "Relations are not allowed within embeddable entities in `{$entity->getClass()}`"
108
                    );
109
                }
110
            }
111
        }
112
    }
113
}
114