Table::toString()   F
last analyzed

Complexity

Conditions 15
Paths 2880

Size

Total Lines 96
Code Lines 60

Duplication

Lines 6
Ratio 6.25 %

Importance

Changes 0
Metric Value
dl 6
loc 96
rs 2
c 0
b 0
f 0
cc 15
eloc 60
nc 2880
nop 0

How to fix   Long Method    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
namespace donatj\MySqlSchema;
4
5
use donatj\MySqlSchema\Columns\AbstractColumn;
6
use donatj\MySqlSchema\Columns\Numeric\AbstractIntegerColumn;
7
use donatj\MySqlSchema\Traits\CharsetAndCollationTrait;
8
9
class Table {
10
11
	use Traits\EscapeTrait;
12
	use CharsetAndCollationTrait;
13
14
	/**
15
	 * Table constructor.
16
	 *
17
	 * @param string $name
18
	 */
19
	public function __construct( $name ) {
20
		$this->name = $name;
21
	}
22
23
	/**
24
	 * Table Name
25
	 *
26
	 * @var string
27
	 */
28
	protected $name;
29
30
	/**
31
	 * Table Comment
32
	 *
33
	 * @var string
34
	 */
35
	protected $comment = '';
36
37
	protected $engine = null;
38
39
	/**
40
	 * @return Columns\AbstractColumn[]
41
	 */
42
	public function getColumns() {
43
		return $this->columns;
44
	}
45
46
	/**
47
	 * @return string
48
	 */
49
	public function getComment() {
50
		return $this->comment;
51
	}
52
53
	/**
54
	 * @param string $comment
55
	 */
56
	public function setComment( $comment ) {
57
		$this->comment = $comment;
58
	}
59
60
	/**
61
	 * @return null
62
	 */
63
	public function getEngine() {
64
		return $this->engine;
65
	}
66
67
	/**
68
	 * @param null $engine
69
	 */
70
	public function setEngine( $engine ) {
71
		$this->engine = $engine;
72
	}
73
74
	/**
75
	 * @return string
76
	 */
77
	public function getName() {
78
		return $this->name;
79
	}
80
81
	/**
82
	 * @param string $name
83
	 */
84
	public function setName( $name ) {
85
		$this->name = $name;
86
	}
87
88
	/**
89
	 * @var AbstractIntegerColumn|null
90
	 */
91
	protected $autoIncrement = null;
92
93
	public function addAutoIncrement( AbstractIntegerColumn $column ) {
94
		$this->autoIncrement = $column;
95
96
		$this->addPrimaryKey($column);
97
	}
98
99
	/**
100
	 * @param \donatj\MySqlSchema\Columns\Numeric\AbstractIntegerColumn $column
101
	 * @return bool
102
	 */
103
	public function isAutoIncrement( AbstractIntegerColumn $column ) {
104
		return $this->autoIncrement === $column;
105
	}
106
107
	/**
108
	 * @var AbstractColumn[]
109
	 */
110
	protected $primaryKeys = [ ];
111
112
	public function addPrimaryKey( AbstractColumn $column ) {
113
		$this->primaryKeys[spl_object_hash($column)] = $column;
114
115
		$this->addColumn($column);
116
	}
117
118
	/**
119
	 * @param \donatj\MySqlSchema\Columns\AbstractColumn $column
120
	 * @return bool
121
	 */
122
	public function isPrimaryKey( AbstractColumn $column ) {
123
		return isset($this->primaryKeys[spl_object_hash($column)]);
124
	}
125
126
	protected $keys = [ ];
127
128
	public function addKeyColumn( $keyName, AbstractColumn $column, $index = null, $type = 'NORMAL', $method = '' ) {
129
		if( !isset($this->keys[$keyName]) ) {
130
			$this->keys[$keyName] = [
131
				'columns' => [ ],
132
			];
133
		}
134
135
		$this->keys[$keyName]['type']   = $type;
136
		$this->keys[$keyName]['method'] = $method;
137
138
139
		if( is_null($index) ) {
140
			$this->keys[$keyName]['columns'][] = $column;
141
		} else {
142
			$this->keys[$keyName]['columns'][$index] = $column;
143
		}
144
	}
145
146
	protected $foreignKeys = [ ];
147
148
	public function addForeignKey( AbstractColumn $local, AbstractColumn $remote ) {
149
		$this->foreignKeys[spl_object_hash($local)] = [
150
			'local'  => $local,
151
			'remote' => $remote,
152
		];
153
	}
154
155
	/**
156
	 * @var Columns\AbstractColumn[]
157
	 */
158
	protected $columns = [ ];
159
160
	public function addColumn( AbstractColumn $column ) {
161
		$this->columns[spl_object_hash($column)] = $column;
162
		$column->addTable($this);
163
	}
164
165
	public function toString() {
166
		$warnings   = [ ];
167
		$statements = [ ];
168
		foreach( $this->columns as $column ) {
169
			$statements[] = "\t" . $column->toString($this);
170
		}
171
172
		if( count($this->primaryKeys) > 0 ) {
173
			$primary = "\tPRIMARY KEY (";
174
			$primary .= implode(",", array_map(function ( AbstractColumn $column ) {
175
				return $this->mkString($column->getName());
176
			}, $this->primaryKeys));
177
			$primary .= ")";
178
			$statements[] = $primary;
179
		}
180
181
		if( !is_null($this->autoIncrement) ) {
182
			if( $this->autoIncrement->isSigned() ) {
183
				$warnings[] = $this->mkString($this->autoIncrement->getName()) . ' is a signed AUTO_INCREMENT';
184
			}
185
			if( $this->autoIncrement->isNullable() ) {
186
				$warnings[] = $this->mkString($this->autoIncrement->getName()) . ' is a nullable AUTO_INCREMENT';
187
			}
188
		}
189
190
		foreach( $this->keys as $keyName => $key ) {
191
			$keys = "\t";
192
			if( $key['type'] != 'NORMAL' ) {
193
				$keys .= $key['type'] . ' ';
194
			}
195
			$keys .= "KEY " . $this->mkString($keyName) . " (";
196
			$keys .= implode(",", array_map(function ( AbstractColumn $column ) {
197
				return $this->mkString($column->getName());
198
			}, $key['columns']));
199
			$keys .= ")";
200
			$statements[] = $keys;
201
		}
202
203
		foreach( $this->foreignKeys as $fks ) {
204
			/**
205
			 * @var $local AbstractColumn
206
			 * @var $remote AbstractColumn
207
			 */
208
			$local  = $fks['local'];
209
			$remote = $fks['remote'];
210
211
			$tables = $remote->getTables();
212
			// @todo doesn't really need to be a PK, just a key
213
			$tables = array_filter($tables, function ( Table $a ) use ( $remote ) {
214
				return $a->isPrimaryKey($remote);
215
			});
216
217
			foreach( $tables as $tbl ) {
218
				// @todo check length and perhaps other stuff
219
				if( $local->getTypeName() != $remote->getTypeName() ) {
220
					$warnings[] = $this->mkString($this->autoIncrement->getName()) . ' type does not match defined foreign key type';
221
				}
222
				$localName     = $this->mkString($local->getName());
223
				$remoteName    = $this->mkString($remote->getName());
224
				$remoteTblName = $this->mkString($tbl->getName());
225
226
				$keys = "\tFOREIGN KEY ({$localName}) REFERENCES {$remoteTblName}({$remoteName})";
227
				$statements[] = $keys;
228
			}
229
		}
230
231
		$charset   = '';
232
		$collation = '';
233 View Code Duplication
		if( $this->getCharset() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
234
			$charset = ' CHARACTER SET ' . $this->getCharset();
235
			if( $this->getCollation() ) {
236
				$collation = ' COLLATE ' . $this->getCollation();
237
			}
238
		}
239
240
241
		$comment = '';
242
		if( $this->comment ) {
243
			$comment = ' COMMENT ' . $this->mkString($this->comment, "'");
244
		}
245
246
		$name   = $this->mkString($this->name);
247
		$stmnts = implode(",\n", $statements);
248
249
		$warn = '';
250
		if( count($warnings) > 0 ) {
251
			$warn = "\n# Warning: " . implode("\n# Warning: ", $warnings);
252
		}
253
254
		return <<<EOT
255
CREATE TABLE {$name} (
256
{$stmnts}
257
){$charset}{$collation}{$comment}{$warn};
258
259
EOT;
260
	}
261
}
262