DbDef::index()   C
last analyzed

Complexity

Conditions 14
Paths 12

Size

Total Lines 41
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 22.9253

Importance

Changes 0
Metric Value
cc 14
eloc 27
nc 12
nop 3
dl 0
loc 41
ccs 18
cts 28
cp 0.6429
crap 22.9253
rs 5.0864
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @author Todd Burry <[email protected]>
4
 * @copyright 2009-2014 Vanilla Forums Inc.
5
 * @license MIT
6
 */
7
8
namespace Garden\Db;
9
10
/**
11
 * A helper class for creating database tables.
12
 */
13
class DbDef implements \JsonSerializable {
14
    /// Properties ///
15
16
    /**
17
     * @var Db The database connection to send definitions to.
18
     */
19
    protected $db;
20
21
    /**
22
     * @var array The columns that need to be set in the table.
23
     */
24
    protected $columns;
25
26
    /**
27
     * @var array Options to send to the table definitaion call.
28
     */
29
    protected $options;
30
31
    /**
32
     *
33
     * @var string The name of the currently working table.
34
     */
35
    protected $table;
36
37
    /**
38
     * @var array An array of indexes.
39
     */
40
    protected $indexes;
41
42
    /// Methods ///
43
44
    /**
45
     * Initialize an instance of the {@link DbDef} class.
46
     *
47
     * @param Db $db The database to execute against.
48
     */
49 12
    public function __construct($db) {
50 12
        $this->db = $db;
51 12
        $this->reset();
52 12
    }
53
54
    /**
55
     * Reset the internal state of this object so that it can be re-used.
56
     *
57
     * @return DbDef Returns $this for fluent calls.
58
     */
59 12
    public function reset() {
60 12
        $this->table = null;
61 12
        $this->columns = [];
62 12
        $this->indexes = [];
63 12
        $this->options = [];
64
65 12
        return $this;
66
    }
67
68
    /**
69
     * Define a column.
70
     *
71
     * @param string $name The column name.
72
     * @param string $type The column type.
73
     * @param mixed $nullDefault Whether the column is required or it's default.
74
     *
75
     * null|true
76
     * : The column is not required.
77
     * false
78
     * : The column is required.
79
     * Anything else
80
     * : The column is required and this is its default.
81
     *
82
     * @param string|array $index The index that the column participates in.
83
     * @return DbDef
84
     */
85 12
    public function column($name, $type, $nullDefault = false, $index = null) {
86 12
        $this->columns[$name] = $this->columnDef($type, $nullDefault);
87
88 12
        $index = (array)$index;
89 12
        foreach ($index as $typeStr) {
90
            if (strpos($typeStr, '.') === false) {
91
                $indexType = $typeStr;
92
                $suffix = '';
93
            } else {
94
                list($indexType, $suffix) = explode('.', $typeStr);
95
            }
96
            $this->index($name, $indexType, $suffix);
97 12
        }
98
99 12
        return $this;
100
    }
101
102
    /**
103
     * Get an array column def from a structured function call.
104
     *
105
     * @param string $type The database type of the column.
106
     * @param mixed $nullDefault Whether or not to allow null or the default value.
107
     *
108
     * null|true
109
     * : The column is not required.
110
     * false
111
     * : The column is required.
112
     * Anything else
113
     * : The column is required and this is its default.
114
     *
115
     * @return array Returns the column def as an array.
116
     */
117 12
    protected function columnDef($type, $nullDefault = false) {
118 12
        $column = ['type' => $type];
119
120 12
        if ($nullDefault === null || $nullDefault == true) {
121
            $column['required'] = false;
122
        }
123 12
        if ($nullDefault === false) {
124 12
            $column['required'] = true;
125 12
        } else {
126 8
            $column['required'] = true;
127 8
            $column['default'] = $nullDefault;
128
        }
129
130 12
        return $column;
131
    }
132
133
    /**
134
     * Define the primary key in the database.
135
     *
136
     * @param string $name The name of the column.
137
     * @param string $type The datatype for the column.
138
     * @return DbDef
139
     */
140 2
    public function primaryKey($name, $type = 'int') {
141 2
        $column = $this->columnDef($type, false);
142 2
        $column['autoincrement'] = true;
143 2
        $column['primary'] = true;
144
145 2
        $this->columns[$name] = $column;
146
147
        // Add the pk index.
148 2
        $this->index($name, Db::INDEX_PK);
149
150 2
        return $this;
151
    }
152
153
    /**
154
     * Execute the table def against the database.
155
     *
156
     * @param bool $reset Whether or not to reset the db def upon completion.
157
     * @return DbDef $this Returns $this for fluent calls.
158
     */
159 12
    public function exec($reset = true) {
160 12
        $this->db->setTableDef(
161 12
            $this->table,
162 12
            $this->jsonSerialize(),
163 12
            $this->options
164 12
        );
165
166 12
        if ($reset) {
167 10
            $this->reset();
168 10
        }
169
170 12
        return $this;
171
    }
172
173
    /**
174
     * Set the name of the table.
175
     *
176
     * @param string|null $name The name of the table.
177
     * @return DbDef|string Returns $this for fluent calls.
178
     */
179 12
    public function table($name = null) {
180 12
        if ($name !== null) {
181 12
            $this->table = $name;
182 12
            return $this;
183
        }
184
        return $this->table;
185
    }
186
187
    /**
188
     * Add or update an index.
189
     *
190
     * @param string|array $columns An array of columns or a single column name.
191
     * @param string $type One of the `Db::INDEX_*` constants.
192
     * @param string $suffix An index suffix to group columns together in an index.
193
     * @return DbDef Returns $this for fluent calls.
194
     */
195 12
    public function index($columns, $type, $suffix = '') {
196 12
        $type = strtolower($type);
197 12
        $columns = (array)$columns;
198 12
        $suffix = strtolower($suffix);
199
200
        // Look for a current index row.
201 12
        $currentIndex = null;
202 12
        foreach ($this->indexes as $i => $index) {
203 2
            if ($type !== $index['type']) {
204 2
                continue;
205
            }
206
207
            $indexSuffix = val('suffix', $index, '');
208
209
            if ($type === Db::INDEX_PK ||
210
                ($type === Db::INDEX_UNIQUE && $suffix == $indexSuffix) ||
211
                ($type === Db::INDEX_IX && $suffix && $suffix == $indexSuffix) ||
212
                ($type === Db::INDEX_IX && !$suffix && array_diff($index['columns'], $columns) == [])
213
            ) {
214
                $currentIndex =& $this->indexes[$i];
215
                break;
216
            }
217 12
        }
218
219 12
        if ($currentIndex) {
220
            $currentIndex['columns'] = array_unique(array_merge($currentIndex['columns'], $columns));
221
        } else {
222
            $indexDef = [
223 12
                'type' => $type,
224 12
                'columns' => $columns,
225
                'suffix' => $suffix
226 12
            ];
227 12
            if ($type === Db::INDEX_PK) {
228 8
                $this->indexes[Db::INDEX_PK] = $indexDef;
229 8
            } else {
230 6
                $this->indexes[] = $indexDef;
231
            }
232
        }
233
234 12
        return $this;
235
    }
236
237
    /**
238
     * Set an option that will be passed on to the final {@link Db::setTableDef()} call.
239
     *
240
     * @param string $key The option key.
241
     * @param mixed $value The option value.
242
     * @return DbDef Returns $this for fluent calls.
243
     */
244 2
    public function option($key, $value) {
245 2
        $this->options[$key] = $value;
246 2
        return $this;
247
    }
248
249
    /**
250
     * Specify data which should be serialized to JSON.
251
     *
252
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
253
     * @return mixed data which can be serialized by {@link json_encode()},
254
     * which is a value of any type other than a resource.
255
     */
256 12
    public function jsonSerialize() {
257
        return [
258 12
            'name' => $this->table,
259 12
            'columns' => $this->columns,
260 12
            'indexes' => $this->indexes
261 12
        ];
262
    }
263
264
    /**
265
     * Get the db connection to send definitions to.
266
     *
267
     * @return Db Returns the db connection.
268
     * @see DbDef::setDb()
269
     */
270 2
    public function getDb() {
271 2
        return $this->db;
272
    }
273
274
    /**
275
     * Set the db connection to send definitions to.
276
     *
277
     * @param Db $db The new database connection.
278
     * @see DbDef::getDef()
279
     */
280
    public function setDb($db) {
281
        $this->db = $db;
282
    }
283
}
284