Test Failed
Pull Request — master (#97)
by Aleksei
02:29
created

CompositedSchemaConveyor   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 31
c 1
b 0
f 0
dl 0
loc 85
rs 10
wmc 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getEntityClassLocator() 0 17 3
A getGenerators() 0 4 1
A addMetadataGenerators() 0 19 2
A addEntityPaths() 0 3 1
A getMetadataReader() 0 5 1
A setTableNaming() 0 5 1
A getTableNaming() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Cycle\Schema\Conveyor;
6
7
use Cycle\Annotated\Embeddings;
8
use Cycle\Annotated\Entities;
9
use Cycle\Annotated\MergeColumns;
10
use Cycle\Annotated\MergeIndexes;
11
use JetBrains\PhpStorm\ExpectedValues;
12
use Spiral\Attributes\AnnotationReader;
13
use Spiral\Attributes\AttributeReader;
14
use Spiral\Attributes\Composite\SelectiveReader;
15
use Spiral\Attributes\ReaderInterface;
16
use Spiral\Tokenizer\ClassLocator;
17
use Symfony\Component\Finder\Finder;
18
use Yiisoft\Aliases\Aliases;
19
use Yiisoft\Yii\Cycle\Exception\EmptyEntityPathsException;
20
21
class CompositedSchemaConveyor extends SchemaConveyor
22
{
23
    /** @var string[] */
24
    private array $entityPaths = [];
25
26
    private int $tableNaming = Entities::TABLE_NAMING_SINGULAR;
27
28
    private bool $isAddedMetadataGenerators = false;
29
30
    final public function setTableNaming(
31
        #[ExpectedValues(valuesFromClass: Entities::class)]
32
        int $type
33
    ): void {
34
        $this->tableNaming = $type;
35
    }
36
37
    final public function getTableNaming(): int
38
    {
39
        return $this->tableNaming;
40
    }
41
42
    /**
43
     * @param string[] $paths
44
     */
45
    final public function addEntityPaths(array $paths): void
46
    {
47
        $this->entityPaths = array_merge($this->entityPaths, $paths);
48
    }
49
50
    public function getGenerators(): array
51
    {
52
        $this->addMetadataGenerators();
53
        return parent::getGenerators();
54
    }
55
56
    protected function getMetadataReader(): ?ReaderInterface
57
    {
58
        return new SelectiveReader([
59
            new AttributeReader(),
60
            new AnnotationReader(),
61
        ]);
62
    }
63
64
    /**
65
     * Add some generators in this conveyor into the INDEX stage
66
     * Added generators will search for entity classes and read their annotations
67
     */
68
    private function addMetadataGenerators(): void
69
    {
70
        if ($this->isAddedMetadataGenerators) {
71
            return;
72
        }
73
        $classLocator = $this->getEntityClassLocator();
74
75
        $reader = $this->getMetadataReader();
76
77
        // register embeddable entities
78
        $this->conveyor[SchemaConveyor::STAGE_INDEX][] = new Embeddings($classLocator, $reader);
79
        // register annotated entities
80
        $this->conveyor[SchemaConveyor::STAGE_INDEX][] = new Entities($classLocator, $reader, $this->tableNaming);
81
        // add @Table(columns) declarations
82
        $this->conveyor[SchemaConveyor::STAGE_INDEX][] = new MergeColumns($reader);
83
        // add @Table(indexes) declarations
84
        $this->conveyor[SchemaConveyor::STAGE_RENDER][] = new MergeIndexes($reader);
85
86
        $this->isAddedMetadataGenerators = true;
87
    }
88
89
    private function getEntityClassLocator(): ClassLocator
90
    {
91
        $aliases = $this->container->get(Aliases::class);
92
        $list = [];
93
        foreach ($this->entityPaths as $path) {
94
            $list[] = $aliases->get($path);
95
        }
96
97
        if (!count($list)) {
98
            throw new EmptyEntityPathsException();
99
        }
100
101
        $finder = (new Finder())
102
            ->files()
103
            ->in($list);
104
105
        return new ClassLocator($finder);
106
    }
107
}
108