SchemaTransformer::transformTables()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
ccs 9
cts 9
cp 1
rs 9.4285
cc 3
eloc 6
nc 3
nop 1
crap 3
1
<?php
2
3
/*
4
 * This file is part of the "RocketORM" package.
5
 *
6
 * https://github.com/RocketORM/ORM
7
 *
8
 * For the full license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Rocket\ORM\Generator\Schema\Transformer;
13
14
use Rocket\ORM\Generator\Schema\Column;
15
use Rocket\ORM\Generator\Schema\Schema;
16
use Rocket\ORM\Generator\Schema\Table;
17
use Rocket\ORM\Generator\Utils\StringUtil;
18
use Rocket\ORM\Model\Map\TableMap;
19
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
20
21
/**
22
 * @author Sylvain Lorinet <[email protected]>
23
 */
24
class SchemaTransformer implements SchemaTransformerInterface
25
{
26
    /**
27
     * @var array
28
     */
29
    protected $modelsNamespace = [];
30
31
32
    /**
33
     * @param array $classes
34
     * @param array $defaultClasses
35
     */
36 7
    public function __construct(array $classes, array $defaultClasses)
37
    {
38 7
        foreach ($classes as $type => $class) {
39 7
            if (!$this->validateSchemaModelClass($class['class'], $defaultClasses[$type]['class'])) {
40 1
                throw new \InvalidArgumentException(
41 1
                    'The ' . $type . ' model ("' . $class['class'] . '") '
42 1
                    . 'model must extend "' . $defaultClasses[$type]['class'] . '"'
43 1
                );
44
            }
45
46 6
            $this->modelsNamespace[$type] = $class['class'];
47 6
        }
48 6
    }
49
50
    /**
51
     * @param array  $schemaData The schema data
52
     * @param string $path       The absolute path to the schema file
53
     *
54
     * @return Schema
55
     */
56 4
    public function transform(array $schemaData, $path)
57
    {
58
        /** @var Schema $schema */
59 4
        $class = $this->modelsNamespace['schema'];
60 4
        $classes = $this->modelsNamespace;
61 4
        unset($classes['schema']);
62
63 4
        $schema = new $class($schemaData, $classes);
64
65
        // Escape anti slashes
66 4
        $schema->namespace = str_replace('\\\\', '\\', $schema->namespace);
67 4
        $schema->escapedNamespace = str_replace('\\', '\\\\', $schema->namespace);
68
69 4
        $this->formatDirectory($schema);
70
71
        // Delete the file in the path
72 4
        $pathParams = explode(DIRECTORY_SEPARATOR, $path);
73 4
        unset($pathParams[sizeof($pathParams) - 1]);
74
75
        // TODO check if the connection name exists
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
76
77 4
        $schema->absoluteDirectory = join(DIRECTORY_SEPARATOR, $pathParams) . $schema->relativeDirectory;
78
79 4
        $this->transformTables($schema->getTables());
80
81 1
        return $schema;
82
    }
83
84
    /**
85
     * @param array|Table[] $tables
86
     */
87 4
    public function transformTables(array $tables)
88
    {
89 4
        foreach ($tables as $table) {
90 4
            if (null == $table->phpName) {
91 4
                $table->phpName = StringUtil::camelize($table->name);
92 4
            }
93
94
            // TODO check if table phpName is named "RocketBaseModel"
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
95
            // TODO check if table has a primary key, RocketORM do not support a table without PK
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
96
97 4
            $this->transformColumns($table->getColumns());
98 2
            $this->transformPrimaryKeys($table->getColumns());
99 2
        }
100 1
    }
101
102
    /**
103
     * @param array|Column[] $columns
104
     */
105 4
    public function transformColumns(array $columns)
106
    {
107 4
        foreach ($columns as $column) {
108 4
            if (null == $column->phpName) {
109 4
                $column->phpName = StringUtil::camelize($column->name, false);
110 4
            }
111
112 4
            if (true === $column->isPrimaryKey) {
113 4
                $column->isRequired = true;
114 4
            }
115
116
            // TODO check for more than one autoIncrement PK
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
117
            // TODO column TEXT can't have a default value
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
118
            // TODO column DATETIME can't have a default value
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
119
120
            // Check if default value is valid if the type is boolean
121 4
            if (TableMap::COLUMN_TYPE_BOOLEAN == $column->type && null !== $column->getDefault()
122 4
                && true !== $column->getDefault() && false !== $column->getDefault()) {
123 1
                throw new InvalidConfigurationException(
124 1
                    'The default value "' . $column->getDefault(true) . '" for boolean column "' . $column->name . '" on table "' . $column->getTable()->name . '" should be a boolean'
125 1
                );
126
            }
127
128
            // Check, for enum type, if the default value exists in the values array
129 4
            if (TableMap::COLUMN_TYPE_ENUM === $column->type && null != $column->getDefault(true)
130 4
                && !in_array($column->getDefault(true), $column->values)) {
131 1
                throw new InvalidConfigurationException(
132 1
                    'Invalid default value "' . $column->getDefault(true) . '" for enum column "' . $column->name . '" on table "' . $column->getTable()->name . '"'
133 1
                );
134
            }
135
136 4
            if ((TableMap::COLUMN_TYPE_DOUBLE == $column->type || TableMap::COLUMN_TYPE_FLOAT == $column->type)) {
137 3
                if (null === $column->size || null === $column->decimal) {
138 1
                    $column->size = null;
139 1
                    $column->decimal = null;
140 3
                } elseif ($column->decimal >= $column->size) {
141 1
                    throw new InvalidConfigurationException(
142 1
                        'Invalid size value "' . $column->size . '" for column "' . $column->name . '" on table "'
143 1
                        . $column->getTable()->name . '", the size should be greater than the decimal value "' . $column->decimal . '"'
144 1
                    );
145
                }
146 2
            }
147 4
        }
148 2
    }
149
150
    /**
151
     * @param array|Column[] $columns
152
     */
153 2
    public function transformPrimaryKeys(array $columns)
154
    {
155 2
        foreach ($columns as $column) {
156 2
            if (true === $column->isPrimaryKey) {
157 2
                $column->getTable()->addPrimaryKey($column);
158 2
            }
159 2
        }
160 2
    }
161
162
    /**
163
     * @param Schema $schema
164
     */
165 4
    protected function formatDirectory(Schema $schema)
166
    {
167
        // Add or delete slashes
168
        // Add first slash if missing
169 4
        if (0 < strpos($schema->relativeDirectory, DIRECTORY_SEPARATOR)) {
170 1
            $schema->relativeDirectory = DIRECTORY_SEPARATOR . $schema->relativeDirectory;
171 1
        }
172
173
        // Delete last slash if exists
174 4
        if (DIRECTORY_SEPARATOR === $schema->relativeDirectory[strlen($schema->relativeDirectory) - 1]) {
175 1
            $schema->relativeDirectory = substr($schema->relativeDirectory, 0, -1);
176 1
        }
177 4
    }
178
179
    /**
180
     * @param string $class
181
     * @param string $defaultClass
182
     *
183
     * @return bool
184
     */
185 7
    protected function validateSchemaModelClass($class, $defaultClass)
186
    {
187 7
        if ($class != $defaultClass) {
188 2
            $class = new \ReflectionClass($class);
189
190 2
            if (!$class->isSubclassOf($defaultClass)) {
191 1
                return false;
192
            }
193 1
        }
194
195 6
        return true;
196
    }
197
}
198