Passed
Push — master ( d17173...2c21ba )
by Pieter
05:43
created

SchemaSynchronizer::updateTable()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 1
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
1
<?php
2
3
namespace Avoran\RapidoAdapter\DoctrineDbalStorage;
4
5
use Avoran\Rapido\ReadModel\DataType\DateTime;
6
use Doctrine\DBAL\Schema\AbstractSchemaManager;
7
use Doctrine\DBAL\Schema\Comparator;
8
use Doctrine\DBAL\Schema\Table;
9
use Avoran\Rapido\ReadModel\ReadModelConfiguration;
10
use Avoran\Rapido\ReadModel\ReadModelField;
11
12
class SchemaSynchronizer
13
{
14
    private $schemaManager;
15
    private $schemaComparator;
16
    private $tableNameGenerator;
17
    private $idColumnName;
18
    private $columnFactory;
19
20
    public function __construct
21
    (
22
        AbstractSchemaManager $schemaManager,
23
        Comparator $schemaComparator,
24
        NameGenerator $tableNameGenerator,
25
        $idColumnName,
26
        ColumnFactory $columnFactory
27
    )
28
    {
29
        $this->schemaManager = $schemaManager;
30
        $this->schemaComparator = $schemaComparator;
31
        $this->tableNameGenerator = $tableNameGenerator;
32
        $this->idColumnName = $idColumnName;
33
        $this->columnFactory = $columnFactory;
34
    }
35
36
    public function ensureTableExists(ReadModelConfiguration $metadata)
37
    {
38
        $table = $this->generateTable($metadata);
39
        $table->setPrimaryKey([$this->idColumnName]);
40
41
        $this->updateTable($table);
42
43
        if (!$metadata->generateSnapshot()) return;
44
45
        $table = $this->generateTable($metadata, true);
46
        $table->setPrimaryKey([$this->idColumnName, $metadata->getSnapshotColumnName()]);
47
48
        $this->updateTable($table);
49
    }
50
51
    private function generateTable(ReadModelConfiguration $metadata, $snapshot = false)
52
    {
53
        $predefinedColumns = [$this->columnFactory->createColumn($metadata->getId()->getDataType(), $this->idColumnName)];
54
        $name = $this->tableNameGenerator->generate($metadata->getName());
55
56
        if ($snapshot) {
57
            $predefinedColumns[] = $this->columnFactory->createColumn(new DateTime(), $metadata->getSnapshotColumnName());
58
            $name = $this->tableNameGenerator->generateWithSuffix($metadata->getName());
59
        }
60
61
        return new Table($name,
62
            array_merge($predefinedColumns, array_map(function(ReadModelField $field) {
63
                return $this->columnFactory->createColumn($field->getDataType(), $field->getId());
64
            }, $metadata->getFields()))
65
        );
66
    }
67
68
    private function updateTable(Table $table)
69
    {
70
        $existingTables = array_filter(
71
            $this->schemaManager->listTables(),
72
            function(Table $existingTable) use ($table) { return $table->getName() == $existingTable->getName(); }
73
        );
74
75
        if (count($existingTables) > 1)
76
            throw new \UnexpectedValueException(sprintf("Multiple tables with the name '%s' exist.", $table->getName()));
77
78
        if (count($existingTables) == 1) {
79
            $tableDiff = $this->schemaComparator->diffTable(current($existingTables), $table);
80
            if ($tableDiff)
81
                $this->schemaManager->alterTable($tableDiff);
82
        } else {
83
            $this->schemaManager->createTable($table);
84
        }
85
    }
86
}
87