Completed
Push — master ( 1340df...e03243 )
by Neomerx
03:41
created

SeedTrait::createAttributeTypeGetter()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 1
nop 1
crap 2
1
<?php namespace Limoncello\Data\Seeds;
2
3
/**
4
 * Copyright 2015-2017 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use Closure;
20
use DateTimeImmutable;
21
use Doctrine\DBAL\Connection;
22
use Doctrine\DBAL\DBALException;
23
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
24
use Doctrine\DBAL\Schema\AbstractSchemaManager;
25
use Doctrine\DBAL\Types\Type;
26
use Exception;
27
use Limoncello\Contracts\Data\ModelSchemaInfoInterface;
28
use Limoncello\Contracts\Data\SeedInterface;
29
use PDO;
30
use Psr\Container\ContainerInterface;
31
32
/**
33
 * @package Limoncello\Data
34
 */
35
trait SeedTrait
36
{
37
    /**
38
     * @var ContainerInterface
39
     */
40
    private $container;
41
42
    /**
43
     * @inheritdoc
44
     */
45 1
    public function init(ContainerInterface $container): SeedInterface
46
    {
47 1
        $this->container = $container;
48
49
        /** @var SeedInterface $self */
50 1
        $self = $this;
51
52 1
        return $self;
53
    }
54
55
    /**
56
     * @return ContainerInterface
57
     */
58 1
    protected function getContainer(): ContainerInterface
59
    {
60 1
        return $this->container;
61
    }
62
63
    /**
64
     * @return Connection
65
     */
66 1
    protected function getConnection(): Connection
67
    {
68 1
        assert($this->getContainer()->has(Connection::class) === true);
69
70 1
        return $this->getContainer()->get(Connection::class);
71
    }
72
73
    /**
74
     * @return ModelSchemaInfoInterface
75
     */
76 1
    protected function getModelSchemas(): ModelSchemaInfoInterface
77
    {
78 1
        assert($this->getContainer()->has(ModelSchemaInfoInterface::class) === true);
79
80 1
        return $this->getContainer()->get(ModelSchemaInfoInterface::class);
81
    }
82
83
    /**
84
     * @return AbstractSchemaManager
85
     */
86 1
    protected function getSchemaManager(): AbstractSchemaManager
87
    {
88 1
        return $this->getConnection()->getSchemaManager();
89
    }
90
91
    /**
92
     * @return string
93
     *
94
     * @throws Exception
95
     */
96 1
    protected function now(): string
97
    {
98 1
        $format = $this->getSchemaManager()->getDatabasePlatform()->getDateTimeFormatString();
99 1
        $now    = (new DateTimeImmutable())->format($format);
100
101 1
        return $now;
102
    }
103
104
    /**
105
     * @param string   $tableName
106
     * @param null|int $limit
107
     *
108
     * @return array
109
     */
110 1
    protected function readTableData(string $tableName, int $limit = null): array
111
    {
112 1
        assert($limit === null || $limit > 0);
113
114 1
        $builder = $this->getConnection()->createQueryBuilder();
115
        $builder
116 1
            ->select('*')
117 1
            ->from($tableName);
118
119 1
        $limit === null ?: $builder->setMaxResults($limit);
120
121 1
        $result = $builder->execute()->fetchAll(PDO::FETCH_ASSOC);
122
123 1
        return $result;
124
    }
125
126
    /**
127
     * @param string   $modelClass
128
     * @param null|int $limit
129
     *
130
     * @return array
131
     */
132 1
    protected function readModelsData(string $modelClass, int $limit = null): array
133
    {
134 1
        return $this->readTableData($this->getModelSchemas()->getTable($modelClass), $limit);
135
    }
136
137
    /**
138
     * @param int     $records
139
     * @param string  $tableName
140
     * @param Closure $dataClosure
141
     * @param array   $columnTypes
142
     *
143
     * @return void
144
     *
145
     * @throws DBALException
146
     */
147 1
    protected function seedTableData(int $records, $tableName, Closure $dataClosure, array $columnTypes = []): void
148
    {
149 1
        $attributeTypeGetter = $this->createAttributeTypeGetter($columnTypes);
150
151 1
        $connection = $this->getConnection();
152 1
        for ($i = 0; $i !== $records; $i++) {
153 1
            $this->insertRow($tableName, $connection, $dataClosure($this->getContainer()), $attributeTypeGetter);
154
        }
155
    }
156
157
    /**
158
     * @param int     $records
159
     * @param string  $modelClass
160
     * @param Closure $dataClosure
161
     *
162
     * @return void
163
     *
164
     * @throws DBALException
165
     */
166 1
    protected function seedModelsData(int $records, string $modelClass, Closure $dataClosure): void
167
    {
168 1
        $attributeTypes = $this->getModelSchemas()->getAttributeTypes($modelClass);
169
170 1
        $this->seedTableData($records, $this->getModelSchemas()->getTable($modelClass), $dataClosure, $attributeTypes);
171
    }
172
173
    /**
174
     * @param string $tableName
175
     * @param array  $data
176
     * @param array  $columnTypes
177
     *
178
     * @return void
179
     *
180
     * @throws DBALException
181
     */
182 1
    protected function seedRowData(string $tableName, array $data, array $columnTypes = []): void
183
    {
184 1
        $attributeTypeGetter = $this->createAttributeTypeGetter($columnTypes);
185
186 1
        $this->insertRow($tableName, $this->getConnection(), $data, $attributeTypeGetter);
187
    }
188
189
    /**
190
     * @param string $modelClass
191
     * @param array  $data
192
     *
193
     * @return void
194
     *
195
     * @throws DBALException
196
     */
197 1
    protected function seedModelData(string $modelClass, array $data): void
198
    {
199 1
        $attributeTypes = $this->getModelSchemas()->getAttributeTypes($modelClass);
200
201 1
        $this->seedRowData($this->getModelSchemas()->getTable($modelClass), $data, $attributeTypes);
202
    }
203
204
    /**
205
     * @return string
206
     */
207 1
    protected function getLastInsertId(): string
208
    {
209 1
        return $this->getConnection()->lastInsertId();
210
    }
211
212
    /**
213
     * @param string     $tableName
214
     * @param Connection $connection
215
     * @param array      $data
216
     * @param Closure    $getColumnType
217
     *
218
     * @return void
219
     *
220
     * @throws DBALException
221
     */
222 1
    private function insertRow($tableName, Connection $connection, array $data, Closure $getColumnType): void
223
    {
224 1
        $types        = [];
225 1
        $quotedFields = [];
226 1
        foreach ($data as $column => $value) {
227 1
            $name                = $connection->quoteIdentifier($column);
228 1
            $quotedFields[$name] = $value;
229 1
            $types[$name]        = $getColumnType($column);
230
        }
231
232
        try {
233 1
            $result = $connection->insert($tableName, $quotedFields, $types);
234 1
            assert($result !== false, 'Insert failed');
235 1
        } /** @noinspection PhpRedundantCatchClauseInspection */ catch (UniqueConstraintViolationException $e) {
236
            // ignore non-unique records
237
        }
238
    }
239
240
    /**
241
     * @param array $attributeTypes
242
     *
243
     * @return Closure
244
     */
245 1
    private function createAttributeTypeGetter(array $attributeTypes): Closure
246
    {
247
        return function (string $attributeType) use ($attributeTypes) : string {
248 1
            return array_key_exists($attributeType, $attributeTypes) === true ?
249 1
                $attributeTypes[$attributeType] : Type::STRING;
250 1
        };
251
    }
252
}
253