Completed
Push — master ( 9f79cc...417289 )
by Sébastien
07:33
created

AbstractSource   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 333
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 82.76%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 14
c 4
b 0
f 0
lcom 1
cbo 2
dl 0
loc 333
ccs 24
cts 29
cp 0.8276
rs 10

15 Methods

Rating   Name   Duplication   Size   Complexity  
getUniqueKeys() 0 1 ?
getIndexesInformation() 0 1 ?
getPrimaryKey() 0 1 ?
getPrimaryKeys() 0 1 ?
getColumnsInformation() 0 1 ?
getRelations() 0 1 ?
getTablesInformation() 0 1 ?
A getColumns() 0 4 1
A getTableInformation() 0 5 1
A getTables() 0 4 1
A hasTable() 0 5 1
A validateTable() 0 8 2
A validateSchema() 0 7 3
A setDefaultSchema() 0 6 1
A checkTableArgument() 0 8 4
1
<?php
2
namespace Soluble\Schema\Source;
3
4
use Soluble\Schema\Exception;
5
6
abstract class AbstractSource
7
{
8
    /**
9
     * Default schema name
10
     * @var string
11
     */
12
    protected $schema;
13
14
15
16
    /**
17
     * Return all uniques keys defined for a table.
18
     *
19
     * By default it does not include the primary key, simply set
20
     * the $include_primary parameter to true to get it. In this case
21
     * the associative key will be 'PRIMARY'.
22
     *
23
     * If no unique keys can be found returns an empty array
24
     *
25
     * @param string $table table name
26
     * @param boolean $include_primary include primary keys in the list
27
     * 
28
     * @throws Exception\InvalidArgumentException
29
     * @throws Exception\ErrorException
30
     * @throws Exception\ExceptionInterface
31
     * @throws Exception\TableNotFoundException
32
     * @return array associative ['index_name' => ['col1', 'col2'], 'index_name_2' => ['col3']]
33
     */
34
    abstract public function getUniqueKeys($table, $include_primary = false);
35
36
37
    /**
38
     * Return indexes information on a table
39
     *
40
     * @param string $table table name
41
     * @throws Exception\InvalidArgumentException
42
     * @throws Exception\ErrorException
43
     * @throws Exception\ExceptionInterface
44
     * @throws Exception\TableNotFoundException
45
     *
46
     * @return array
47
     */
48
    abstract public function getIndexesInformation($table);
49
50
    /**
51
     * Return table primary key
52
     *
53
     * @throws Exception\InvalidArgumentException
54
     * @throws Exception\ErrorException
55
     * @throws Exception\NoPrimaryKeyException when no pk or multiple pk found
56
     * @throws Exception\MultiplePrimaryKeyException when multiple pk found 
57
     * @throws Exception\ExceptionInterface
58
     * @throws Exception\TableNotFoundException
59
     *
60
     * @param string $table
61
     * @return string primary key
62
     */
63
    abstract public function getPrimaryKey($table);
64
65
66
    /**
67
     * Return composite primary keys
68
     *
69
     * @throws Exception\InvalidArgumentException
70
     * @throws Exception\ErrorException
71
     * @throws Exception\NoPrimaryKeyException
72
     * @throws Exception\ExceptionInterface
73
     * @throws Exception\TableNotFoundException
74
     *
75
     * @param string $table
76
     * @return array primary keys ['col1', 'col3']
77
     */
78
    abstract public function getPrimaryKeys($table);
79
80
81
    /**
82
     * Retrieve full columns informations from a table
83
     *
84
     * The returned is an array looks like
85
     * <code>
86
     * [
87
     *  ["column_name_1"] => [
88
     *   ["type"]      => (string)  "Database type, i.e: 'char', 'int', 'bigint', 'decimal'...",
89
     *   ["primary"]   => (boolean) "Whether column is (part of) a primary key",
90
     *   ["nullable"]  => (boolean) "Whether column is nullable",
91
     *   ["default"]   => (string)  "Default value for column or null if none",
92
     * 
93
     *   // Specific to primary key(s) columns
94
     *   ["autoincrement"] => (boolean) "Whether the primary key is autoincremented"
95
     *
96
     *   // Specific to numeric, decimal, boolean... types
97
     *   ["unsigned"]  => (boolean) "Whether the column is unsigned",
98
     *   ["precision"] => (int)     "Number precision (or maximum length)",
99
     *
100
     *   // Specific to character oriented types as well as enum, blobs...
101
     *   ["length"]       => (int) "Maximum length",
102
     *   ["octet_length"] => (int) "Maximum length in octets (differs from length when using multibyte charsets",
103
     *
104
     *   // Columns specific ddl information
105
     *   ["options"]  => [
106
     *            "comment"          => "Column comment",
107
     *            "definition"       => "DDL definition, i.e. varchar(250)",
108
     *            "ordinal_position" => "Column position number",
109
     *            "constraint_type"  => "Type of constraint if applicable",
110
     *            "column_key"       => "",
111
     *            "charset"          => "Column charset, i.e. 'utf8'",
112
     *            "collation"        => "Column collation, i.e. 'utf8_unicode_ci'"
113
     *          ],
114
     *   ],
115
     *   ["column_name_2"] => [ 
116
     *       //... 
117
     *   ]
118
     * ]
119
     * </code>
120
     * 
121
     * @see \Soluble\Schema\Source\AbstractSource::getColumns() for only column names
122
     * 
123
     * @throws Exception\InvalidArgumentException
124
     * @throws Exception\ErrorException
125
     * @throws Exception\ExceptionInterface
126
     * @throws Exception\TableNotFoundException
127
     *
128
     * @param string $table table name
129
     * @return array associative array i.e. ['colname' => ['type' => 'char', 'primary' => false, ...]]
130
     */
131
    abstract public function getColumnsInformation($table);
132
133
134
    /**
135
     * Retrieve foreign keys / relations information
136
     *
137
     * @throws Exception\InvalidArgumentException
138
     * @throws Exception\ErrorException
139
     * @throws Exception\ExceptionInterface
140
     * @throws Exception\TableNotFoundException
141
     *
142
     * @param string $table table name
143
     *
144
     * @return array relations associative array ['col_name_1' => ['referenced_table' => 'tab1', 'referenced_column' => 'col1', 'constraint_name' => 'FK...']]
145
     */
146
    abstract public function getRelations($table);
147
148
    /**
149
     * Return full information of all tables present in schema
150
     * 
151
     * The resulting array looks like
152
     * <code>
153
     * [
154
     *  ["table_name_1"] => [
155
     *    ["name"]    => (string) 'Table name'
156
     *    ["columns"] => [ // Columns information, 
157
     *                     // @see AbstractSource::getColumnsInformation()
158
     *                     "col name_1" => ["name" => "", "type" => "", ...]',
159
     *                     "col name_2" => ["name" => "", "type" => "", ...]'
160
     *                   ]
161
     *    ["primary_keys"] => [ // Primary key column(s) or empty
162
     *                      "pk_col1", "pk_col2"
163
     *                   ],
164
     *    ["unique_keys"]  => [ // Uniques constraints or empty if none
165
     *                      "unique_index_name_1" => ["col1", "col3"],
166
     *                      "unique_index_name_2" => ["col4"]
167
     *                   ],
168
     *    ["foreign_keys"] => [ // Foreign keys columns and their references or empty if none
169
     *                       "col_1" => [
170
     *                                    "referenced_table"  => "Referenced table name",
171
     *                                    "referenced_column" => "Referenced column name",
172
     *                                    "constraint_name"   => "Constraint name i.e. 'FK_6A2CA10CBC21F742'"
173
     *                                  ],
174
     *                       "col_2" => [ // ...  
175
     *                                  ]
176
     *                      ],
177
     *    ["references"] => [ // Relations referencing this table
178
     *                       "referencing_table_name_1" => [
179
     *                          "column"            => "Colum name in this table",
180
     *                          "referenced_column" => "Column name in the referenceing table", 
181
     *                          "constraint_name"   => "Constaint name i.e. 'FK_6A2CA10CBC21F742'"
182
     *                          ],
183
     *                        "referencing_table_2" => [ //...
184
     *                          ],     
185
     *                      ]
186
     *    ["indexes"]  => [],
187
     *    ['options']  => [ // Specific table creation options
188
     *                      "comment"   => "Table comment",
189
     *                      "collation" => "Table collation, i.e. 'utf8_general_ci'",
190
     *                      "type"      => "Table type, i.e: 'BASE TABLE'",
191
     *                      "engine"    => "Engine type if applicable, i.e. 'InnoDB'",
192
     *                    ]
193
     *  ],
194
     *  ["table_name_2"] => [
195
     *     //...
196
     *  ]
197
     * ]
198
     * </code>
199
     *
200
     * @throws Exception\InvalidArgumentException
201
     * @throws Exception\ErrorException
202
     * @throws Exception\ExceptionInterface
203
     *
204
     * @return array associative array indexed by table name
205
     */
206
    abstract public function getTablesInformation();
207
208
209
    /**
210
     * Return column information
211
     *
212
     * @throws Exception\InvalidArgumentException
213
     * @throws Exception\ErrorException
214
     * @throws Exception\ExceptionInterface
215
     * @throws Exception\TableNotFoundException
216
     *
217
     * @param string $table
218
     * @return array
219
     */
220
221 1
    public function getColumns($table)
222
    {
223 1
        return array_keys($this->getColumnsInformation($table));
224
    }
225
226
227
    /**
228
     * Return information about a specific table
229
     *
230
     * @throws Exception\InvalidArgumentException
231
     * @throws Exception\ErrorException
232
     * @throws Exception\ExceptionInterface
233
     *
234
     * @param string $table table name
235
     * @return array
236
     */
237 1
    public function getTableInformation($table)
238
    {
239 1
        $infos = $this->getTablesInformation();
240 1
        return $infos[$table];
241
    }
242
243
    /**
244
     * Return a list of table names
245
     *
246
     * @throws Exception\InvalidArgumentException
247
     * @throws Exception\ErrorException
248
     * @throws Exception\ExceptionInterface
249
     *
250
     * @return array indexed array with table names: ['table1', 'table2']
251
     */
252 1
    public function getTables()
253
    {
254 1
        return array_keys($this->getTablesInformation());
255
    }
256
257
258
    /**
259
     * Check whether a table exists in the specified or current scheme
260
     *
261
     * @throws Exception\InvalidArgumentException
262
     * @throws Exception\ErrorException
263
     * @throws Exception\ExceptionInterface
264
     *
265
     * @param string $table
266
     * @return bool
267
     */
268 1
    public function hasTable($table)
269
    {
270 1
        $tables = $this->getTables();
271 1
        return in_array($table, $tables);
272
    }
273
274
    /**
275
     * Check whether a table parameter is valid and exists
276
     *
277
     * @throws Exception\InvalidArgumentException
278
     * @throws Exception\ErrorException
279
     * @throws Exception\ExceptionInterface
280
     * @throws Exception\TableNotFoundException
281
     *
282
     * @param string $table
283
     * @return AbstractSource
284
    */
285
    protected function validateTable($table)
286
    {
287
        $this->checkTableArgument($table);
288
        if (!$this->hasTable($table)) {
289
            throw new Exception\TableNotFoundException(__METHOD__ . ": Table '$table' does not exists in database '{$this->schema}'");
290
        }
291
        return $this;
292
    }
293
    
294
295
    /**
296
     * Check whether a schema parameter is valid
297
     *
298
     * @throws Exception\InvalidArgumentException
299
300
     * @param string $schema
301
     * @return AbstractSource
302
     */
303 21
    protected function validateSchema($schema)
304
    {
305 21
        if (!is_string($schema) || trim($schema) == '') {
306 2
            throw new Exception\InvalidArgumentException(__METHOD__ . ": Schema name must be a valid string or an empty string detected");
307
        }
308 21
        return $this;
309
    }
310
311
    /**
312
     * Set default schema
313
     *
314
     * @throws Exception\InvalidArgumentException
315
     * @param string $schema
316
     * @return AbstractSource
317
     */
318 21
    protected function setDefaultSchema($schema)
319
    {
320 21
        $this->validateSchema($schema);
321 21
        $this->schema = $schema;
322 21
        return $this;
323
    }
324
325
    /**
326
     *
327
     * @param string $table
328
     * @throws Exception\InvalidArgumentException
329
     */
330 15
    protected function checkTableArgument($table = null)
331
    {
332 15
        if ($table !== null) {
333 12
            if (!is_string($table) || trim($table) == '') {
334 2
                throw new Exception\InvalidArgumentException(__METHOD__ . " Table name must be a valid string or an empty string detected");
335
            }
336 10
        }
337 13
    }
338
}
339