Completed
Push — master ( 10f953...ab5b42 )
by Todd
9s
created

TableDef::addIndex()   C

Complexity

Conditions 7
Paths 9

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 7.0099

Importance

Changes 0
Metric Value
dl 0
loc 32
ccs 16
cts 17
cp 0.9412
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 19
nc 9
nop 2
crap 7.0099
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 TableDef implements \JsonSerializable {
14
    /// Properties ///
15
16
    /**
17
     * @var array The columns that need to be set in the table.
18
     */
19
    private $columns;
20
21
    /**
22
     *
23
     * @var string The name of the currently working table.
24
     */
25
    private $table;
26
27
    /**
28
     * @var array An array of indexes.
29
     */
30
    private $indexes;
31
32
    /// Methods ///
33
34
    /**
35
     * Initialize an instance of the {@link TableDef} class.
36
     *
37
     * @param string $name The name of the table.
38
     */
39 40
    public function __construct($name = '') {
40 40
        $this->reset();
41 40
        $this->table = $name;
42 40
    }
43
44
    /**
45
     * Reset the internal state of this object so that it can be re-used.
46
     *
47
     * @return TableDef Returns $this for fluent calls.
48
     */
49 40
    public function reset() {
50 40
        $this->table = '';
51 40
        $this->columns = [];
52 40
        $this->indexes = [];
53
//        $this->options = [];
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
54
55 40
        return $this;
56
    }
57
58
    /**
59
     * Define a column.
60
     *
61
     * @param string $name The column name.
62
     * @param string $type The column type.
63
     * @param mixed $nullDefault Whether the column is required or it's default.
64
     *
65
     * null|true
66
     * : The column is not required.
67
     * false
68
     * : The column is required.
69
     * Anything else
70
     * : The column is required and this is its default.
71
     * @return TableDef
72
     */
73 40
    public function setColumn($name, $type, $nullDefault = false) {
74 40
        $this->columns[$name] = $this->createColumnDef($type, $nullDefault);
75
76 40
        return $this;
77
    }
78
79
    /**
80
     * Get an array column def from a structured function call.
81
     *
82
     * @param string $dbtype The database type of the column.
83
     * @param mixed $nullDefault Whether or not to allow null or the default value.
84
     *
85
     * null|true
86
     * : The column is not required.
87
     * false
88
     * : The column is required.
89
     * Anything else
90
     * : The column is required and this is its default.
91
     *
92
     * @return array Returns the column def as an array.
93
     */
94 40
    private function createColumnDef($dbtype, $nullDefault = false) {
95 40
        $column = Db::typeDef($dbtype);
96
97 40
        if ($column === null) {
98
            throw new \InvalidArgumentException("Unknown type '$dbtype'.", 500);
99
        }
100
101 40
        if ($column['dbtype'] === 'bool' && in_array($nullDefault, [true, false], true)) {
102
            // Booleans have a special meaning.
103 2
            $column['allowNull'] = false;
104 2
            $column['default'] = $nullDefault;
105 40
        } elseif ($nullDefault === null || $nullDefault === true) {
106 4
            $column['allowNull'] = true;
107 38
        } elseif ($nullDefault === false) {
108 38
            $column['allowNull'] = false;
109
        } else {
110 28
            $column['allowNull'] = false;
111 28
            $column['default'] = $nullDefault;
112
        }
113
114 40
        return $column;
115
    }
116
117
    /**
118
     * Define the primary key in the database.
119
     *
120
     * @param string $name The name of the column.
121
     * @param string $type The datatype for the column.
122
     * @return TableDef
123
     */
124 20
    public function setPrimaryKey($name, $type = 'int') {
125 20
        $column = $this->createColumnDef($type, false);
126 20
        $column['autoIncrement'] = true;
127 20
        $column['primary'] = true;
128
129 20
        $this->columns[$name] = $column;
130
131
        // Add the pk index.
132 20
        $this->addIndex(Db::INDEX_PK, $name);
133
134 20
        return $this;
135
    }
136
137
    /**
138
     * Add or update an index.
139
     *
140
     * @param string $type One of the `Db::INDEX_*` constants.
141
     * @param string ...$columns The columns in the index.
142
     * @return $this
143
     */
0 ignored issues
show
Documentation introduced by
Should the type for parameter $columns not be string[]?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
144 34
    public function addIndex($type, ...$columns) {
145 34
        if (empty($columns)) {
146
            throw new \InvalidArgumentException("An index must contain at least one column.", 500);
147
        }
148
149 34
        $type = strtolower($type);
150
151
        // Look for a current index row.
152 34
        $currentIndex = null;
153 34
        foreach ($this->indexes as $i => $index) {
154 26
            if ($type !== $index['type']) {
155 20
                continue;
156
            }
157
158 6
            if ($type === Db::INDEX_PK || array_diff($index['columns'], $columns) == []) {
159 4
                $currentIndex =& $this->indexes[$i];
160 6
                break;
161
            }
162
        }
163
164 34
        if ($currentIndex) {
165 4
            $currentIndex['columns'] = $columns;
166
        } else {
167
            $indexDef = [
168 34
                'type' => $type,
169 34
                'columns' => $columns,
170
            ];
171 34
            $this->indexes[] = $indexDef;
172
        }
173
174 34
        return $this;
175
    }
176
177
    /**
178
     * Get the table.
179
     *
180
     * @return string Returns the table.
181
     */
182
    public function getTable() {
183
        return $this->table;
184
    }
185
186
    /**
187
     * Set the name of the table.
188
     *
189
     * @param string|null $name The name of the table.
190
     * @return TableDef|string Returns $this for fluent calls.
191
     */
192 8
    public function setTable($name) {
193 8
        $this->table = $name;
194 8
        return $this;
195
    }
196
197
    /**
198
     * Specify data which should be serialized to JSON.
199
     *
200
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
201
     * @return mixed data which can be serialized by {@link json_encode()},
202
     * which is a value of any type other than a resource.
203
     */
204
    public function jsonSerialize() {
205
        return $this->toArray();
206
    }
207
208
    /**
209
     * Get the array representation of the table definition.
210
     *
211
     * @return array Returns a definition array.
212
     */
213 40
    public function toArray() {
214
        return [
215 40
            'name' => $this->table,
216 40
            'columns' => $this->columns,
217 40
            'indexes' => $this->indexes
218
        ];
219
    }
220
221
    /**
222
     * Execute this table definition on a database.
223
     *
224
     * @param Db $db The database to query.
225
     * @param array $options Additional options. See {@link Db::defineTable()}.
226
     */
227 30
    public function exec(Db $db, array $options = []) {
228 30
        $db->defineTable($this->toArray(), $options);
229 30
    }
230
}
231