Passed
Push — main ( 6a8c3e...b8efbe )
by James Ekow Abaka
09:56 queued 08:09
created

AbstractDatabaseManipulator::deleteData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 10
rs 10
c 1
b 0
f 1
1
<?php
2
3
namespace yentu\manipulators;
4
5
use clearice\io\Io;
6
use ntentan\atiaa\DriverFactory;
7
use yentu\DatabaseAssertor;
8
use yentu\SchemaDescription;
9
use yentu\exceptions\DatabaseManipulatorException;
10
use yentu\Parameters;
11
12
    abstract class AbstractDatabaseManipulator
13
{
14
15
    const CONVERT_TO_DRIVER = 'driver';
16
    const CONVERT_TO_YENTU = 'yentu';
17
18
    private $schemaDescription;
19
    private $assertor;
20
    private $connection;
21
    private $dumpQuery;
22
    private $disableQuery;
23
    protected $defaultSchema;
24
    private $io;
25
26
    /**
27
     * AbstractDatabaseManipulator constructor.
28
     * @param DriverFactory $driverFactory
29
     * @param Io $io
30
     * @throws \ntentan\atiaa\exceptions\ConnectionException
31
     */
32
    public function __construct(DriverFactory $driverFactory, Io $io)
33
    {
34
        $this->connection = $driverFactory->createDriver();
35
        $this->connection->connect();
36
        $this->io = $io;
37
    }
38
39
    public function __get($name)
40
    {
41
        if ($name === 'description') {
42
            return $this->getDescription();
43
        }
44
    }
45
46
    public function setDumpQuery($dumpQuery)
47
    {
48
        $this->dumpQuery = $dumpQuery;
49
    }
50
51
    public function setDisableQuery($disableQuery)
52
    {
53
        $this->disableQuery = $disableQuery;
54
    }
55
56
    public function __call($name, $arguments)
57
    {
58
        if (preg_match("/^(add|drop|change|executeQuery|reverseQuery)/", $name)) {
59
            $details = Parameters::wrap($arguments[0]);
60
            $this->description->$name($details);
0 ignored issues
show
Bug Best Practice introduced by
The property description does not exist on yentu\manipulators\AbstractDatabaseManipulator. Since you implemented __get, consider adding a @property annotation.
Loading history...
61
            $name = "_$name";
62
            new \ReflectionMethod($this, $name);
63
            return $this->$name($details);
64
        } else {
65
            throw new \Exception("Failed to execute method '$name'");
66
        }
67
    }
68
69
    public function query($query, $bind = false)
70
    {
71
        try {
72
            if ($this->dumpQuery) {
73
                echo "$query\n";
74
            }
75
76
            $this->io->output("\n    > Running Query [$query]", Io::OUTPUT_LEVEL_3);
77
78
            if ($this->disableQuery !== true) {
79
                return $this->connection->query($query, $bind);
80
            }
81
        } catch (\ntentan\atiaa\exceptions\DatabaseDriverException $e) {
82
            throw new DatabaseManipulatorException($e->getMessage());
83
        }
84
    }
85
86
    public function disconnect()
87
    {
88
        $this->connection->disconnect();
89
    }
90
91
    public function getDefaultSchema()
92
    {
93
        return $this->connection->getDefaultSchema();
94
    }
95
96
    public function getAssertor()
97
    {
98
        if (!is_object($this->assertor)) {
99
            $this->assertor = new DatabaseAssertor($this->description);
0 ignored issues
show
Bug Best Practice introduced by
The property description does not exist on yentu\manipulators\AbstractDatabaseManipulator. Since you implemented __get, consider adding a @property annotation.
Loading history...
100
        }
101
        return $this->assertor;
102
    }
103
    
104
    public function insertData(array $details)
105
    {
106
        $query = sprintf(
107
            "INSERT INTO %s (%s) VALUES (%s)",
108
            "{$this->quoteIdentifier($details['schema'])}.{$this->quoteIdentifier($details['table'])}",
109
            implode(", ", array_map(fn($x) => $this->quoteIdentifier($x), $details['columns'])),
110
            implode(", ", array_fill(0, count($details['columns']), "?"))                             
111
        );
112
        
113
        foreach($details['rows'] as $row) {
114
            $this->query($query, $row);
115
        }
116
    }
117
    
118
    public function deleteData(array $details)
119
    {
120
        $query = sprintf(
121
            "DELETE FROM %s WHERE %s",
122
            "{$this->quoteIdentifier($details['schema'])}.{$this->quoteIdentifier($details['table'])}",
123
            implode(" AND ", array_map(fn($x) => "{$this->quoteIdentifier($x)}=?", $details['columns']))                      
124
        );
125
        
126
        foreach($details['rows'] as $row) {
127
            $this->query($query, $row);
128
        }
129
    }
130
    
131
    abstract protected function quoteIdentifier(string $identifier): string;
132
133
    abstract protected function _addSchema($name);
134
135
    abstract protected function _dropSchema($name);
136
137
    abstract protected function _addTable($details);
138
139
    abstract protected function _dropTable($details);
140
141
    abstract protected function _changeTableName($details);
142
143
    abstract protected function _addColumn($details);
144
145
    abstract protected function _changeColumnNulls($details);
146
147
    abstract protected function _changeColumnName($details);
148
149
    abstract protected function _changeColumnDefault($details);
150
151
    abstract protected function _dropColumn($details);
152
153
    abstract protected function _addPrimaryKey($details);
154
155
    abstract protected function _dropPrimaryKey($details);
156
157
    abstract protected function _addUniqueKey($details);
158
159
    abstract protected function _dropUniqueKey($details);
160
161
    abstract protected function _addAutoPrimaryKey($details);
162
163
    abstract protected function _dropAutoPrimaryKey($details);
164
165
    abstract protected function _addForeignKey($details);
166
167
    abstract protected function _dropForeignKey($details);
168
169
    abstract protected function _addIndex($details);
170
171
    abstract protected function _dropIndex($details);
172
173
    abstract protected function _addView($details);
174
175
    abstract protected function _dropView($details);
176
177
    abstract protected function _changeViewDefinition($details);
178
179
    protected function _changeForeignKeyOnDelete($details)
180
    {
181
        $this->_dropForeignKey($details['from']);
182
        $this->_addForeignKey($details['to']);
183
    }
184
185
    protected function _changeForeignKeyOnUpdate($details)
186
    {
187
        $this->_dropForeignKey($details['from']);
188
        $this->_addForeignKey($details['to']);
189
    }
190
191
    protected function _executeQuery($details)
192
    {
193
        $this->query($details['query'], $details['bind'] ?? []);
194
    }
195
196
    protected function _reverseQuery($details)
197
    {
198
        if (isset($details['rollback_query'])) {
199
            $this->query($details['rollback_query'], $details['rollback_bind'] ?? []);   
200
        }
201
    }
202
203
    abstract public function convertTypes($type, $direction, $length);
204
205
    /**
206
     * 
207
     * @return SchemaDescription
208
     */
209
    public function getDescription()
210
    {
211
        if (!is_object($this->schemaDescription)) {
212
            $this->schemaDescription = SchemaDescription::wrap($this->connection->describe(), $this);
213
        }
214
        return $this->schemaDescription;
215
    }
216
217
    public function setVersion($version)
218
    {
219
        $this->query('INSERT INTO yentu_history(version) values (?)', array($version));
220
    }
221
222
    public function getVersion()
223
    {
224
        $version = $this->query("SELECT MAX(version) as version FROM yentu_history");
225
        return isset($version[0]) ? $version[0]['version'] : null;
226
    }
227
228
    public function getLastSession()
229
    {
230
        $session = $this->query("SELECT session FROM yentu_history ORDER BY id DESC LIMIT 1");
231
        return isset($session[0]['session']) ? $session[0]['session'] : null;
232
    }
233
234
    public function getSessionVersions($session)
235
    {
236
        $sessionVersions = array();
237
        $versions = $this->query(
238
            "SELECT DISTINCT version FROM yentu_history WHERE session = ?", array($session)
239
        );
240
241
        foreach ($versions as $version) {
242
            $sessionVersions[] = $version['version'];
243
        }
244
245
        return $sessionVersions;
246
    }
247
248
    public function createHistory()
249
    {
250
        try {
251
            $this->connection->describeTable('yentu_history');
252
        } catch (\ntentan\atiaa\exceptions\TableNotFoundException $e) {
253
            $this->io->pushOutputLevel(Io::OUTPUT_LEVEL_0);
254
            $this->addTable(array('schema' => '', 'name' => 'yentu_history'));
0 ignored issues
show
Bug introduced by
The method addTable() does not exist on yentu\manipulators\AbstractDatabaseManipulator. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

254
            $this->/** @scrutinizer ignore-call */ 
255
                   addTable(array('schema' => '', 'name' => 'yentu_history'));
Loading history...
255
256
            $this->addColumn(array('default' => null, 'schema' => '', 'nulls' => true, 'length' => null, 'table' => 'yentu_history', 'name' => 'session', 'type' => 'string'));
0 ignored issues
show
Bug introduced by
The method addColumn() does not exist on yentu\manipulators\AbstractDatabaseManipulator. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

256
            $this->/** @scrutinizer ignore-call */ 
257
                   addColumn(array('default' => null, 'schema' => '', 'nulls' => true, 'length' => null, 'table' => 'yentu_history', 'name' => 'session', 'type' => 'string'));
Loading history...
257
            $this->addColumn(array('default' => null, 'schema' => '', 'nulls' => false, 'length' => null, 'table' => 'yentu_history', 'name' => 'version', 'type' => 'string'));
258
            $this->addColumn(array('default' => null, 'schema' => '', 'nulls' => true, 'length' => null, 'table' => 'yentu_history', 'name' => 'method', 'type' => 'string'));
259
            $this->addColumn(array('default' => null, 'schema' => '', 'nulls' => true, 'length' => null, 'table' => 'yentu_history', 'name' => 'arguments', 'type' => 'text'));
260
            $this->addColumn(array('default' => null, 'schema' => '', 'nulls' => true, 'length' => null, 'table' => 'yentu_history', 'name' => 'migration', 'type' => 'string'));
261
            $this->addColumn(array('default' => null, 'schema' => '', 'nulls' => true, 'length' => null, 'table' => 'yentu_history', 'name' => 'default_schema', 'type' => 'string'));
262
            $this->addColumn(array('default' => null, 'schema' => '', 'nulls' => true, 'length' => null, 'table' => 'yentu_history', 'name' => 'id', 'type' => 'integer'));
263
            $this->addPrimaryKey(array('schema' => '', 'table' => 'yentu_history', 'name' => 'yentu_history_pk', 'columns' => array('id')));
0 ignored issues
show
Bug introduced by
The method addPrimaryKey() does not exist on yentu\manipulators\AbstractDatabaseManipulator. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

263
            $this->/** @scrutinizer ignore-call */ 
264
                   addPrimaryKey(array('schema' => '', 'table' => 'yentu_history', 'name' => 'yentu_history_pk', 'columns' => array('id')));
Loading history...
264
            $this->addAutoPrimaryKey(array('schema' => '', 'table' => 'yentu_history', 'column' => 'id'));
0 ignored issues
show
Bug introduced by
The method addAutoPrimaryKey() does not exist on yentu\manipulators\AbstractDatabaseManipulator. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

264
            $this->/** @scrutinizer ignore-call */ 
265
                   addAutoPrimaryKey(array('schema' => '', 'table' => 'yentu_history', 'column' => 'id'));
Loading history...
265
            $this->io->popOutputLevel();
266
        }
267
    }
268
269
    public function __clone()
270
    {
271
        if (is_object($this->schemaDescription)) {
272
            $this->schemaDescription = clone $this->schemaDescription;
273
        }
274
    }
275
276
}
277