pictcode_admin / lib / Cake / Model / CakeSchema.php @ master
履歴 | 表示 | アノテート | ダウンロード (19.184 KB)
1 |
<?php
|
---|---|
2 |
/**
|
3 |
* Schema database management for CakePHP.
|
4 |
*
|
5 |
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
6 |
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
7 |
*
|
8 |
* Licensed under The MIT License
|
9 |
* For full copyright and license information, please see the LICENSE.txt
|
10 |
* Redistributions of files must retain the above copyright notice.
|
11 |
*
|
12 |
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
13 |
* @link http://cakephp.org CakePHP(tm) Project
|
14 |
* @package Cake.Model
|
15 |
* @since CakePHP(tm) v 1.2.0.5550
|
16 |
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
17 |
*/
|
18 |
|
19 |
App::uses('Model', 'Model'); |
20 |
App::uses('AppModel', 'Model'); |
21 |
App::uses('ConnectionManager', 'Model'); |
22 |
App::uses('File', 'Utility'); |
23 |
|
24 |
/**
|
25 |
* Base Class for Schema management.
|
26 |
*
|
27 |
* @package Cake.Model
|
28 |
*/
|
29 |
class CakeSchema extends Object { |
30 |
|
31 |
/**
|
32 |
* Name of the schema.
|
33 |
*
|
34 |
* @var string
|
35 |
*/
|
36 |
public $name = null; |
37 |
|
38 |
/**
|
39 |
* Path to write location.
|
40 |
*
|
41 |
* @var string
|
42 |
*/
|
43 |
public $path = null; |
44 |
|
45 |
/**
|
46 |
* File to write.
|
47 |
*
|
48 |
* @var string
|
49 |
*/
|
50 |
public $file = 'schema.php'; |
51 |
|
52 |
/**
|
53 |
* Connection used for read.
|
54 |
*
|
55 |
* @var string
|
56 |
*/
|
57 |
public $connection = 'default'; |
58 |
|
59 |
/**
|
60 |
* Plugin name.
|
61 |
*
|
62 |
* @var string
|
63 |
*/
|
64 |
public $plugin = null; |
65 |
|
66 |
/**
|
67 |
* Set of tables.
|
68 |
*
|
69 |
* @var array
|
70 |
*/
|
71 |
public $tables = array(); |
72 |
|
73 |
/**
|
74 |
* Constructor
|
75 |
*
|
76 |
* @param array $options Optional load object properties.
|
77 |
*/
|
78 |
public function __construct($options = array()) { |
79 |
parent::__construct();
|
80 |
|
81 |
if (empty($options['name'])) { |
82 |
$this->name = preg_replace('/schema$/i', '', get_class($this)); |
83 |
} |
84 |
if (!empty($options['plugin'])) { |
85 |
$this->plugin = $options['plugin']; |
86 |
} |
87 |
|
88 |
if (strtolower($this->name) === 'cake') { |
89 |
$this->name = 'App'; |
90 |
} |
91 |
|
92 |
if (empty($options['path'])) { |
93 |
$this->path = APP . 'Config' . DS . 'Schema'; |
94 |
} |
95 |
|
96 |
$options = array_merge(get_object_vars($this), $options); |
97 |
$this->build($options); |
98 |
} |
99 |
|
100 |
/**
|
101 |
* Builds schema object properties.
|
102 |
*
|
103 |
* @param array $data Loaded object properties.
|
104 |
* @return void
|
105 |
*/
|
106 |
public function build($data) { |
107 |
$file = null; |
108 |
foreach ($data as $key => $val) { |
109 |
if (!empty($val)) { |
110 |
if (!in_array($key, array('plugin', 'name', 'path', 'file', 'connection', 'tables', '_log'))) { |
111 |
if ($key[0] === '_') { |
112 |
continue;
|
113 |
} |
114 |
$this->tables[$key] = $val; |
115 |
unset($this->{$key}); |
116 |
} elseif ($key !== 'tables') { |
117 |
if ($key === 'name' && $val !== $this->name && !isset($data['file'])) { |
118 |
$file = Inflector::underscore($val) . '.php'; |
119 |
} |
120 |
$this->{$key} = $val; |
121 |
} |
122 |
} |
123 |
} |
124 |
if (file_exists($this->path . DS . $file) && is_file($this->path . DS . $file)) { |
125 |
$this->file = $file; |
126 |
} elseif (!empty($this->plugin)) { |
127 |
$this->path = CakePlugin::path($this->plugin) . 'Config' . DS . 'Schema'; |
128 |
} |
129 |
} |
130 |
|
131 |
/**
|
132 |
* Before callback to be implemented in subclasses.
|
133 |
*
|
134 |
* @param array $event Schema object properties.
|
135 |
* @return bool Should process continue.
|
136 |
*/
|
137 |
public function before($event = array()) { |
138 |
return true; |
139 |
} |
140 |
|
141 |
/**
|
142 |
* After callback to be implemented in subclasses.
|
143 |
*
|
144 |
* @param array $event Schema object properties.
|
145 |
* @return void
|
146 |
*/
|
147 |
public function after($event = array()) { |
148 |
} |
149 |
|
150 |
/**
|
151 |
* Reads database and creates schema tables.
|
152 |
*
|
153 |
* @param array $options Schema object properties.
|
154 |
* @return array Set of name and tables.
|
155 |
*/
|
156 |
public function load($options = array()) { |
157 |
if (is_string($options)) { |
158 |
$options = array('path' => $options); |
159 |
} |
160 |
|
161 |
$this->build($options); |
162 |
extract(get_object_vars($this)); |
163 |
|
164 |
$class = $name . 'Schema'; |
165 |
|
166 |
if (!class_exists($class) && !$this->_requireFile($path, $file)) { |
167 |
$class = Inflector::camelize(Inflector::slug(Configure::read('App.dir'))) . 'Schema'; |
168 |
if (!class_exists($class)) { |
169 |
$this->_requireFile($path, $file); |
170 |
} |
171 |
} |
172 |
|
173 |
if (class_exists($class)) { |
174 |
$Schema = new $class($options); |
175 |
return $Schema; |
176 |
} |
177 |
return false; |
178 |
} |
179 |
|
180 |
/**
|
181 |
* Reads database and creates schema tables.
|
182 |
*
|
183 |
* Options
|
184 |
*
|
185 |
* - 'connection' - the db connection to use
|
186 |
* - 'name' - name of the schema
|
187 |
* - 'models' - a list of models to use, or false to ignore models
|
188 |
*
|
189 |
* @param array $options Schema object properties.
|
190 |
* @return array Array indexed by name and tables.
|
191 |
*/
|
192 |
public function read($options = array()) { |
193 |
extract(array_merge( |
194 |
array(
|
195 |
'connection' => $this->connection, |
196 |
'name' => $this->name, |
197 |
'models' => true, |
198 |
), |
199 |
$options
|
200 |
)); |
201 |
$db = ConnectionManager::getDataSource($connection); |
202 |
|
203 |
if (isset($this->plugin)) { |
204 |
App::uses($this->plugin . 'AppModel', $this->plugin . '.Model'); |
205 |
} |
206 |
|
207 |
$tables = array(); |
208 |
$currentTables = (array)$db->listSources(); |
209 |
|
210 |
$prefix = null; |
211 |
if (isset($db->config['prefix'])) { |
212 |
$prefix = $db->config['prefix']; |
213 |
} |
214 |
|
215 |
if (!is_array($models) && $models !== false) { |
216 |
if (isset($this->plugin)) { |
217 |
$models = App::objects($this->plugin . '.Model', null, false); |
218 |
} else {
|
219 |
$models = App::objects('Model'); |
220 |
} |
221 |
} |
222 |
|
223 |
if (is_array($models)) { |
224 |
foreach ($models as $model) { |
225 |
$importModel = $model; |
226 |
$plugin = null; |
227 |
if ($model === 'AppModel') { |
228 |
continue;
|
229 |
} |
230 |
|
231 |
if (isset($this->plugin)) { |
232 |
if ($model === $this->plugin . 'AppModel') { |
233 |
continue;
|
234 |
} |
235 |
$importModel = $model; |
236 |
$plugin = $this->plugin . '.'; |
237 |
} |
238 |
|
239 |
App::uses($importModel, $plugin . 'Model'); |
240 |
if (!class_exists($importModel)) { |
241 |
continue;
|
242 |
} |
243 |
|
244 |
$vars = get_class_vars($model); |
245 |
if (empty($vars['useDbConfig']) || $vars['useDbConfig'] != $connection) { |
246 |
continue;
|
247 |
} |
248 |
|
249 |
try {
|
250 |
$Object = ClassRegistry::init(array('class' => $model, 'ds' => $connection)); |
251 |
} catch (CakeException $e) { |
252 |
continue;
|
253 |
} |
254 |
|
255 |
if (!is_object($Object) || $Object->useTable === false) { |
256 |
continue;
|
257 |
} |
258 |
$db = $Object->getDataSource(); |
259 |
|
260 |
$fulltable = $table = $db->fullTableName($Object, false, false); |
261 |
if ($prefix && strpos($table, $prefix) !== 0) { |
262 |
continue;
|
263 |
} |
264 |
if (!in_array($fulltable, $currentTables)) { |
265 |
continue;
|
266 |
} |
267 |
|
268 |
$table = $this->_noPrefixTable($prefix, $table); |
269 |
|
270 |
$key = array_search($fulltable, $currentTables); |
271 |
if (empty($tables[$table])) { |
272 |
$tables[$table] = $this->_columns($Object); |
273 |
$tables[$table]['indexes'] = $db->index($Object); |
274 |
$tables[$table]['tableParameters'] = $db->readTableParameters($fulltable); |
275 |
unset($currentTables[$key]); |
276 |
} |
277 |
if (empty($Object->hasAndBelongsToMany)) { |
278 |
continue;
|
279 |
} |
280 |
foreach ($Object->hasAndBelongsToMany as $assocData) { |
281 |
if (isset($assocData['with'])) { |
282 |
$class = $assocData['with']; |
283 |
} |
284 |
if (!is_object($Object->$class)) { |
285 |
continue;
|
286 |
} |
287 |
$withTable = $db->fullTableName($Object->$class, false, false); |
288 |
if ($prefix && strpos($withTable, $prefix) !== 0) { |
289 |
continue;
|
290 |
} |
291 |
if (in_array($withTable, $currentTables)) { |
292 |
$key = array_search($withTable, $currentTables); |
293 |
$noPrefixWith = $this->_noPrefixTable($prefix, $withTable); |
294 |
|
295 |
$tables[$noPrefixWith] = $this->_columns($Object->$class); |
296 |
$tables[$noPrefixWith]['indexes'] = $db->index($Object->$class); |
297 |
$tables[$noPrefixWith]['tableParameters'] = $db->readTableParameters($withTable); |
298 |
unset($currentTables[$key]); |
299 |
} |
300 |
} |
301 |
} |
302 |
} |
303 |
|
304 |
if (!empty($currentTables)) { |
305 |
foreach ($currentTables as $table) { |
306 |
if ($prefix) { |
307 |
if (strpos($table, $prefix) !== 0) { |
308 |
continue;
|
309 |
} |
310 |
$table = $this->_noPrefixTable($prefix, $table); |
311 |
} |
312 |
$Object = new AppModel(array( |
313 |
'name' => Inflector::classify($table), 'table' => $table, 'ds' => $connection |
314 |
)); |
315 |
|
316 |
$systemTables = array( |
317 |
'aros', 'acos', 'aros_acos', Configure::read('Session.table'), 'i18n' |
318 |
); |
319 |
|
320 |
$fulltable = $db->fullTableName($Object, false, false); |
321 |
|
322 |
if (in_array($table, $systemTables)) { |
323 |
$tables[$Object->table] = $this->_columns($Object); |
324 |
$tables[$Object->table]['indexes'] = $db->index($Object); |
325 |
$tables[$Object->table]['tableParameters'] = $db->readTableParameters($fulltable); |
326 |
} elseif ($models === false) { |
327 |
$tables[$table] = $this->_columns($Object); |
328 |
$tables[$table]['indexes'] = $db->index($Object); |
329 |
$tables[$table]['tableParameters'] = $db->readTableParameters($fulltable); |
330 |
} else {
|
331 |
$tables['missing'][$table] = $this->_columns($Object); |
332 |
$tables['missing'][$table]['indexes'] = $db->index($Object); |
333 |
$tables['missing'][$table]['tableParameters'] = $db->readTableParameters($fulltable); |
334 |
} |
335 |
} |
336 |
} |
337 |
|
338 |
ksort($tables); |
339 |
return compact('name', 'tables'); |
340 |
} |
341 |
|
342 |
/**
|
343 |
* Writes schema file from object or options.
|
344 |
*
|
345 |
* @param array|object $object Schema object or options array.
|
346 |
* @param array $options Schema object properties to override object.
|
347 |
* @return mixed False or string written to file.
|
348 |
*/
|
349 |
public function write($object, $options = array()) { |
350 |
if (is_object($object)) { |
351 |
$object = get_object_vars($object); |
352 |
$this->build($object); |
353 |
} |
354 |
|
355 |
if (is_array($object)) { |
356 |
$options = $object; |
357 |
unset($object); |
358 |
} |
359 |
|
360 |
extract(array_merge( |
361 |
get_object_vars($this), $options |
362 |
)); |
363 |
|
364 |
$out = "class {$name}Schema extends CakeSchema {\n\n"; |
365 |
|
366 |
if ($path !== $this->path) { |
367 |
$out .= "\tpublic \$path = '{$path}';\n\n"; |
368 |
} |
369 |
|
370 |
if ($file !== $this->file) { |
371 |
$out .= "\tpublic \$file = '{$file}';\n\n"; |
372 |
} |
373 |
|
374 |
if ($connection !== 'default') { |
375 |
$out .= "\tpublic \$connection = '{$connection}';\n\n"; |
376 |
} |
377 |
|
378 |
$out .= "\tpublic function before(\$event = array()) {\n\t\treturn true;\n\t}\n\n\tpublic function after(\$event = array()) {\n\t}\n\n"; |
379 |
|
380 |
if (empty($tables)) { |
381 |
$this->read();
|
382 |
} |
383 |
|
384 |
foreach ($tables as $table => $fields) { |
385 |
if (!is_numeric($table) && $table !== 'missing') { |
386 |
$out .= $this->generateTable($table, $fields); |
387 |
} |
388 |
} |
389 |
$out .= "}\n"; |
390 |
|
391 |
$file = new File($path . DS . $file, true); |
392 |
$content = "<?php \n{$out}"; |
393 |
if ($file->write($content)) { |
394 |
return $content; |
395 |
} |
396 |
return false; |
397 |
} |
398 |
|
399 |
/**
|
400 |
* Generate the schema code for a table.
|
401 |
*
|
402 |
* Takes a table name and $fields array and returns a completed,
|
403 |
* escaped variable declaration to be used in schema classes.
|
404 |
*
|
405 |
* @param string $table Table name you want returned.
|
406 |
* @param array $fields Array of field information to generate the table with.
|
407 |
* @return string Variable declaration for a schema class.
|
408 |
*/
|
409 |
public function generateTable($table, $fields) { |
410 |
$out = "\tpublic \${$table} = array(\n"; |
411 |
if (is_array($fields)) { |
412 |
$cols = array(); |
413 |
foreach ($fields as $field => $value) { |
414 |
if ($field !== 'indexes' && $field !== 'tableParameters') { |
415 |
if (is_string($value)) { |
416 |
$type = $value; |
417 |
$value = array('type' => $type); |
418 |
} |
419 |
$col = "\t\t'{$field}' => array('type' => '" . $value['type'] . "', "; |
420 |
unset($value['type']); |
421 |
$col .= implode(', ', $this->_values($value)); |
422 |
} elseif ($field === 'indexes') { |
423 |
$col = "\t\t'indexes' => array(\n\t\t\t"; |
424 |
$props = array(); |
425 |
foreach ((array)$value as $key => $index) { |
426 |
$props[] = "'{$key}' => array(" . implode(', ', $this->_values($index)) . ")"; |
427 |
} |
428 |
$col .= implode(",\n\t\t\t", $props) . "\n\t\t"; |
429 |
} elseif ($field === 'tableParameters') { |
430 |
$col = "\t\t'tableParameters' => array("; |
431 |
$props = $this->_values($value); |
432 |
$col .= implode(', ', $props); |
433 |
} |
434 |
$col .= ")"; |
435 |
$cols[] = $col; |
436 |
} |
437 |
$out .= implode(",\n", $cols); |
438 |
} |
439 |
$out .= "\n\t);\n\n"; |
440 |
return $out; |
441 |
} |
442 |
|
443 |
/**
|
444 |
* Compares two sets of schemas.
|
445 |
*
|
446 |
* @param array|object $old Schema object or array.
|
447 |
* @param array|object $new Schema object or array.
|
448 |
* @return array Tables (that are added, dropped, or changed.)
|
449 |
*/
|
450 |
public function compare($old, $new = null) { |
451 |
if (empty($new)) { |
452 |
$new = $this; |
453 |
} |
454 |
if (is_array($new)) { |
455 |
if (isset($new['tables'])) { |
456 |
$new = $new['tables']; |
457 |
} |
458 |
} else {
|
459 |
$new = $new->tables; |
460 |
} |
461 |
|
462 |
if (is_array($old)) { |
463 |
if (isset($old['tables'])) { |
464 |
$old = $old['tables']; |
465 |
} |
466 |
} else {
|
467 |
$old = $old->tables; |
468 |
} |
469 |
$tables = array(); |
470 |
foreach ($new as $table => $fields) { |
471 |
if ($table === 'missing') { |
472 |
continue;
|
473 |
} |
474 |
if (!array_key_exists($table, $old)) { |
475 |
$tables[$table]['create'] = $fields; |
476 |
} else {
|
477 |
$diff = $this->_arrayDiffAssoc($fields, $old[$table]); |
478 |
if (!empty($diff)) { |
479 |
$tables[$table]['add'] = $diff; |
480 |
} |
481 |
$diff = $this->_arrayDiffAssoc($old[$table], $fields); |
482 |
if (!empty($diff)) { |
483 |
$tables[$table]['drop'] = $diff; |
484 |
} |
485 |
} |
486 |
|
487 |
foreach ($fields as $field => $value) { |
488 |
if (!empty($old[$table][$field])) { |
489 |
$diff = $this->_arrayDiffAssoc($value, $old[$table][$field]); |
490 |
if (!empty($diff) && $field !== 'indexes' && $field !== 'tableParameters') { |
491 |
$tables[$table]['change'][$field] = $value; |
492 |
} |
493 |
} |
494 |
|
495 |
if (isset($tables[$table]['add'][$field]) && $field !== 'indexes' && $field !== 'tableParameters') { |
496 |
$wrapper = array_keys($fields); |
497 |
if ($column = array_search($field, $wrapper)) { |
498 |
if (isset($wrapper[$column - 1])) { |
499 |
$tables[$table]['add'][$field]['after'] = $wrapper[$column - 1]; |
500 |
} |
501 |
} |
502 |
} |
503 |
} |
504 |
|
505 |
if (isset($old[$table]['indexes']) && isset($new[$table]['indexes'])) { |
506 |
$diff = $this->_compareIndexes($new[$table]['indexes'], $old[$table]['indexes']); |
507 |
if ($diff) { |
508 |
if (!isset($tables[$table])) { |
509 |
$tables[$table] = array(); |
510 |
} |
511 |
if (isset($diff['drop'])) { |
512 |
$tables[$table]['drop']['indexes'] = $diff['drop']; |
513 |
} |
514 |
if ($diff && isset($diff['add'])) { |
515 |
$tables[$table]['add']['indexes'] = $diff['add']; |
516 |
} |
517 |
} |
518 |
} |
519 |
if (isset($old[$table]['tableParameters']) && isset($new[$table]['tableParameters'])) { |
520 |
$diff = $this->_compareTableParameters($new[$table]['tableParameters'], $old[$table]['tableParameters']); |
521 |
if ($diff) { |
522 |
$tables[$table]['change']['tableParameters'] = $diff; |
523 |
} |
524 |
} |
525 |
} |
526 |
return $tables; |
527 |
} |
528 |
|
529 |
/**
|
530 |
* Extended array_diff_assoc noticing change from/to NULL values.
|
531 |
*
|
532 |
* It behaves almost the same way as array_diff_assoc except for NULL values: if
|
533 |
* one of the values is not NULL - change is detected. It is useful in situation
|
534 |
* where one value is strval('') ant other is strval(null) - in string comparing
|
535 |
* methods this results as EQUAL, while it is not.
|
536 |
*
|
537 |
* @param array $array1 Base array.
|
538 |
* @param array $array2 Corresponding array checked for equality.
|
539 |
* @return array Difference as array with array(keys => values) from input array
|
540 |
* where match was not found.
|
541 |
*/
|
542 |
protected function _arrayDiffAssoc($array1, $array2) { |
543 |
$difference = array(); |
544 |
foreach ($array1 as $key => $value) { |
545 |
if (!array_key_exists($key, $array2)) { |
546 |
$difference[$key] = $value; |
547 |
continue;
|
548 |
} |
549 |
$correspondingValue = $array2[$key]; |
550 |
if (($value === null) !== ($correspondingValue === null)) { |
551 |
$difference[$key] = $value; |
552 |
continue;
|
553 |
} |
554 |
if (is_bool($value) !== is_bool($correspondingValue)) { |
555 |
$difference[$key] = $value; |
556 |
continue;
|
557 |
} |
558 |
if (is_array($value) && is_array($correspondingValue)) { |
559 |
continue;
|
560 |
} |
561 |
if ($value === $correspondingValue) { |
562 |
continue;
|
563 |
} |
564 |
$difference[$key] = $value; |
565 |
} |
566 |
return $difference; |
567 |
} |
568 |
|
569 |
/**
|
570 |
* Formats Schema columns from Model Object.
|
571 |
*
|
572 |
* @param array $values Options keys(type, null, default, key, length, extra).
|
573 |
* @return array Formatted values.
|
574 |
*/
|
575 |
protected function _values($values) { |
576 |
$vals = array(); |
577 |
if (is_array($values)) { |
578 |
foreach ($values as $key => $val) { |
579 |
if (is_array($val)) { |
580 |
$vals[] = "'{$key}' => array(" . implode(", ", $this->_values($val)) . ")"; |
581 |
} else {
|
582 |
$val = var_export($val, true); |
583 |
if ($val === 'NULL') { |
584 |
$val = 'null'; |
585 |
} |
586 |
if (!is_numeric($key)) { |
587 |
$vals[] = "'{$key}' => {$val}"; |
588 |
} else {
|
589 |
$vals[] = "{$val}"; |
590 |
} |
591 |
} |
592 |
} |
593 |
} |
594 |
return $vals; |
595 |
} |
596 |
|
597 |
/**
|
598 |
* Formats Schema columns from Model Object.
|
599 |
*
|
600 |
* @param array &$Obj model object.
|
601 |
* @return array Formatted columns.
|
602 |
*/
|
603 |
protected function _columns(&$Obj) { |
604 |
$db = $Obj->getDataSource(); |
605 |
$fields = $Obj->schema(true); |
606 |
|
607 |
$columns = array(); |
608 |
foreach ($fields as $name => $value) { |
609 |
if ($Obj->primaryKey === $name) { |
610 |
$value['key'] = 'primary'; |
611 |
} |
612 |
if (!isset($db->columns[$value['type']])) { |
613 |
trigger_error(__d('cake_dev', 'Schema generation error: invalid column type %s for %s.%s does not exist in DBO', $value['type'], $Obj->name, $name), E_USER_NOTICE); |
614 |
continue;
|
615 |
} else {
|
616 |
$defaultCol = $db->columns[$value['type']]; |
617 |
if (isset($defaultCol['limit']) && $defaultCol['limit'] == $value['length']) { |
618 |
unset($value['length']); |
619 |
} elseif (isset($defaultCol['length']) && $defaultCol['length'] == $value['length']) { |
620 |
unset($value['length']); |
621 |
} |
622 |
unset($value['limit']); |
623 |
} |
624 |
|
625 |
if (isset($value['default']) && ($value['default'] === '' || ($value['default'] === false && $value['type'] !== 'boolean'))) { |
626 |
unset($value['default']); |
627 |
} |
628 |
if (empty($value['length'])) { |
629 |
unset($value['length']); |
630 |
} |
631 |
if (empty($value['key'])) { |
632 |
unset($value['key']); |
633 |
} |
634 |
$columns[$name] = $value; |
635 |
} |
636 |
|
637 |
return $columns; |
638 |
} |
639 |
|
640 |
/**
|
641 |
* Compare two schema files table Parameters.
|
642 |
*
|
643 |
* @param array $new New indexes.
|
644 |
* @param array $old Old indexes.
|
645 |
* @return mixed False on failure, or an array of parameters to add & drop.
|
646 |
*/
|
647 |
protected function _compareTableParameters($new, $old) { |
648 |
if (!is_array($new) || !is_array($old)) { |
649 |
return false; |
650 |
} |
651 |
$change = $this->_arrayDiffAssoc($new, $old); |
652 |
return $change; |
653 |
} |
654 |
|
655 |
/**
|
656 |
* Compare two schema indexes.
|
657 |
*
|
658 |
* @param array $new New indexes.
|
659 |
* @param array $old Old indexes.
|
660 |
* @return mixed False on failure or array of indexes to add and drop.
|
661 |
*/
|
662 |
protected function _compareIndexes($new, $old) { |
663 |
if (!is_array($new) || !is_array($old)) { |
664 |
return false; |
665 |
} |
666 |
|
667 |
$add = $drop = array(); |
668 |
|
669 |
$diff = $this->_arrayDiffAssoc($new, $old); |
670 |
if (!empty($diff)) { |
671 |
$add = $diff; |
672 |
} |
673 |
|
674 |
$diff = $this->_arrayDiffAssoc($old, $new); |
675 |
if (!empty($diff)) { |
676 |
$drop = $diff; |
677 |
} |
678 |
|
679 |
foreach ($new as $name => $value) { |
680 |
if (isset($old[$name])) { |
681 |
$newUnique = isset($value['unique']) ? $value['unique'] : 0; |
682 |
$oldUnique = isset($old[$name]['unique']) ? $old[$name]['unique'] : 0; |
683 |
$newColumn = $value['column']; |
684 |
$oldColumn = $old[$name]['column']; |
685 |
|
686 |
$diff = false; |
687 |
|
688 |
if ($newUnique != $oldUnique) { |
689 |
$diff = true; |
690 |
} elseif (is_array($newColumn) && is_array($oldColumn)) { |
691 |
$diff = ($newColumn !== $oldColumn); |
692 |
} elseif (is_string($newColumn) && is_string($oldColumn)) { |
693 |
$diff = ($newColumn != $oldColumn); |
694 |
} else {
|
695 |
$diff = true; |
696 |
} |
697 |
if ($diff) { |
698 |
$drop[$name] = null; |
699 |
$add[$name] = $value; |
700 |
} |
701 |
} |
702 |
} |
703 |
return array_filter(compact('add', 'drop')); |
704 |
} |
705 |
|
706 |
/**
|
707 |
* Trim the table prefix from the full table name, and return the prefix-less
|
708 |
* table.
|
709 |
*
|
710 |
* @param string $prefix Table prefix.
|
711 |
* @param string $table Full table name.
|
712 |
* @return string Prefix-less table name.
|
713 |
*/
|
714 |
protected function _noPrefixTable($prefix, $table) { |
715 |
return preg_replace('/^' . preg_quote($prefix) . '/', '', $table); |
716 |
} |
717 |
|
718 |
/**
|
719 |
* Attempts to require the schema file specified.
|
720 |
*
|
721 |
* @param string $path Filesystem path to the file.
|
722 |
* @param string $file Filesystem basename of the file.
|
723 |
* @return bool True when a file was successfully included, false on failure.
|
724 |
*/
|
725 |
protected function _requireFile($path, $file) { |
726 |
if (file_exists($path . DS . $file) && is_file($path . DS . $file)) { |
727 |
require_once $path . DS . $file; |
728 |
return true; |
729 |
} elseif (file_exists($path . DS . 'schema.php') && is_file($path . DS . 'schema.php')) { |
730 |
require_once $path . DS . 'schema.php'; |
731 |
return true; |
732 |
} |
733 |
return false; |
734 |
} |
735 |
|
736 |
} |