CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 1.2 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 1.2
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Classes

  • AclBase
  • AclBehavior
  • AclComponent
  • AclNode
  • AclShell
  • Aco
  • AcoAction
  • AjaxHelper
  • ApcEngine
  • ApiShell
  • App
  • AppController
  • AppHelper
  • AppModel
  • Aro
  • AuthComponent
  • BakeShell
  • BehaviorCollection
  • Cache
  • CacheEngine
  • CacheHelper
  • CakeErrorController
  • CakeLog
  • CakeSchema
  • CakeSession
  • CakeSocket
  • ClassRegistry
  • Component
  • Configure
  • ConnectionManager
  • ConsoleShell
  • ContainableBehavior
  • Controller
  • ControllerTask
  • CookieComponent
  • DataSource
  • DbAcl
  • DbAclSchema
  • DbConfigTask
  • DboAdodb
  • DboDb2
  • DboFirebird
  • DboMssql
  • DboMysql
  • DboMysqlBase
  • DboMysqli
  • DboOdbc
  • DboOracle
  • DboPostgres
  • DboSource
  • DboSqlite
  • DboSybase
  • Debugger
  • EmailComponent
  • ErrorHandler
  • ExtractTask
  • File
  • FileEngine
  • Flay
  • Folder
  • FormHelper
  • Helper
  • HtmlHelper
  • HttpSocket
  • I18n
  • I18nModel
  • i18nSchema
  • I18nShell
  • Inflector
  • IniAcl
  • JavascriptHelper
  • JsHelper
  • JsHelperObject
  • L10n
  • MagicDb
  • MagicFileResource
  • MediaView
  • MemcacheEngine
  • Model
  • ModelBehavior
  • ModelTask
  • Multibyte
  • NumberHelper
  • Object
  • Overloadable
  • Overloadable2
  • PagesController
  • PaginatorHelper
  • Permission
  • PluginTask
  • ProjectTask
  • RequestHandlerComponent
  • Router
  • RssHelper
  • Sanitize
  • Scaffold
  • ScaffoldView
  • SchemaShell
  • Security
  • SecurityComponent
  • SessionComponent
  • SessionHelper
  • SessionsSchema
  • Set
  • Shell
  • String
  • TestSuiteShell
  • TestTask
  • TextHelper
  • ThemeView
  • TimeHelper
  • TranslateBehavior
  • TreeBehavior
  • Validation
  • View
  • ViewTask
  • XcacheEngine
  • Xml
  • XmlElement
  • XmlHelper
  • XmlManager
  • XmlNode
  • XmlTextNode

Functions

  • __enclose
  • make_clean_css
  • mb_encode_mimeheader
  • mb_stripos
  • mb_stristr
  • mb_strlen
  • mb_strpos
  • mb_strrchr
  • mb_strrichr
  • mb_strripos
  • mb_strrpos
  • mb_strstr
  • mb_strtolower
  • mb_strtoupper
  • mb_substr
  • mb_substr_count
  • write_css_cache
  1: <?php
  2: /* SVN FILE: $Id$ */
  3: /**
  4:  * Schema database management for CakePHP.
  5:  *
  6:  * PHP versions 4 and 5
  7:  *
  8:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  9:  * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
 10:  *
 11:  * Licensed under The MIT License
 12:  * Redistributions of files must retain the above copyright notice.
 13:  *
 14:  * @copyright     Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
 15:  * @link          http://cakephp.org CakePHP(tm) Project
 16:  * @package       cake
 17:  * @subpackage    cake.cake.libs.model
 18:  * @since         CakePHP(tm) v 1.2.0.5550
 19:  * @version       $Revision$
 20:  * @modifiedby    $LastChangedBy$
 21:  * @lastmodified  $Date$
 22:  * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
 23:  */
 24: App::import('Model', 'ConnectionManager');
 25: /**
 26:  * Base Class for Schema management
 27:  *
 28:  * @package       cake
 29:  * @subpackage    cake.cake.libs.model
 30:  */
 31: class CakeSchema extends Object {
 32: /**
 33:  * Name of the App Schema
 34:  *
 35:  * @var string
 36:  * @access public
 37:  */
 38:     var $name = null;
 39: /**
 40:  * Path to write location
 41:  *
 42:  * @var string
 43:  * @access public
 44:  */
 45:     var $path = null;
 46: /**
 47:  * File to write
 48:  *
 49:  * @var string
 50:  * @access public
 51:  */
 52:     var $file = 'schema.php';
 53: /**
 54:  * Connection used for read
 55:  *
 56:  * @var string
 57:  * @access public
 58:  */
 59:     var $connection = 'default';
 60: /**
 61:  * Set of tables
 62:  *
 63:  * @var array
 64:  * @access public
 65:  */
 66:     var $tables = array();
 67: /**
 68:  * Constructor
 69:  *
 70:  * @param array $options optional load object properties
 71:  */
 72:     function __construct($options = array()) {
 73:         parent::__construct();
 74: 
 75:         if (empty($options['name'])) {
 76:             $this->name = preg_replace('/schema$/i', '', get_class($this));
 77:         }
 78: 
 79:         if (strtolower($this->name) === 'cake') {
 80:             $this->name = Inflector::camelize(Inflector::slug(Configure::read('App.dir')));
 81:         }
 82: 
 83:         if (empty($options['path'])) {
 84:             $this->path = CONFIGS . 'sql';
 85:         }
 86: 
 87:         $options = array_merge(get_object_vars($this), $options);
 88:         $this->_build($options);
 89:     }
 90: /**
 91:  * Builds schema object properties
 92:  *
 93:  * @param array $data loaded object properties
 94:  * @return void
 95:  * @access protected
 96:  */
 97:     function _build($data) {
 98:         $file = null;
 99:         foreach ($data as $key => $val) {
100:             if (!empty($val)) {
101:                 if (!in_array($key, array('name', 'path', 'file', 'connection', 'tables', '_log'))) {
102:                     $this->tables[$key] = $val;
103:                     unset($this->{$key});
104:                 } elseif ($key !== 'tables') {
105:                     if ($key === 'name' && $val !== $this->name && !isset($data['file'])) {
106:                         $file = Inflector::underscore($val) . '.php';
107:                     }
108:                     $this->{$key} = $val;
109:                 }
110:             }
111:         }
112: 
113:         if (file_exists($this->path . DS . $file) && is_file($this->path . DS . $file)) {
114:             $this->file = $file;
115:         }
116:     }
117: /**
118:  * Before callback to be implemented in subclasses
119:  *
120:  * @param array $events schema object properties
121:  * @return boolean Should process continue
122:  * @access public
123:  */
124:     function before($event = array()) {
125:         return true;
126:     }
127: /**
128:  * After callback to be implemented in subclasses
129:  *
130:  * @param array $events schema object properties
131:  * @access public
132:  */
133:     function after($event = array()) {
134:     }
135: /**
136:  * Reads database and creates schema tables
137:  *
138:  * @param array $options schema object properties
139:  * @return array Set of name and tables
140:  * @access public
141:  */
142:     function load($options = array()) {
143:         if (is_string($options)) {
144:             $options = array('path' => $options);
145:         }
146: 
147:         $this->_build($options);
148:         extract(get_object_vars($this));
149: 
150:         $class =  $name .'Schema';
151:         if (!class_exists($class)) {
152:             if (file_exists($path . DS . $file) && is_file($path . DS . $file)) {
153:                 require_once($path . DS . $file);
154:             } elseif (file_exists($path . DS . 'schema.php') && is_file($path . DS . 'schema.php')) {
155:                 require_once($path . DS . 'schema.php');
156:             }
157:         }
158: 
159:         if (class_exists($class)) {
160:             $Schema =& new $class($options);
161:             return $Schema;
162:         }
163: 
164:         return false;
165:     }
166: /**
167:  * Reads database and creates schema tables
168:  *
169:  * Options
170:  *
171:  * - 'connection' - the db connection to use
172:  * - 'name' - name of the schema
173:  * - 'models' - a list of models to use, or false to ignore models
174:  *
175:  * @param array $options schema object properties
176:  * @return array Array indexed by name and tables
177:  * @access public
178:  */
179:     function read($options = array()) {
180:         extract(array_merge(
181:             array(
182:                 'connection' => $this->connection,
183:                 'name' => $this->name,
184:                 'models' => true,
185:             ),
186:             $options
187:         ));
188:         $db =& ConnectionManager::getDataSource($connection);
189: 
190:         App::import('Model', 'AppModel');
191: 
192:         $tables = array();
193:         $currentTables = $db->listSources();
194: 
195:         $prefix = null;
196:         if (isset($db->config['prefix'])) {
197:             $prefix = $db->config['prefix'];
198:         }
199: 
200:         if (!is_array($models) && $models !== false) {
201:             $models = Configure::listObjects('model');
202:         }
203: 
204:         if (is_array($models)) {
205:             foreach ($models as $model) {
206:                 if (PHP5) {
207:                     $Object = ClassRegistry::init(array('class' => $model, 'ds' => $connection));
208:                 } else {
209:                     $Object =& ClassRegistry::init(array('class' => $model, 'ds' => $connection));
210:                 }
211: 
212:                 if (is_object($Object) && $Object->useTable !== false) {
213:                     $Object->setDataSource($connection);
214:                     $table = $db->fullTableName($Object, false);
215: 
216:                     if (in_array($table, $currentTables)) {
217:                         $key = array_search($table, $currentTables);
218:                         if (empty($tables[$Object->table])) {
219:                             $tables[$Object->table] = $this->__columns($Object);
220:                             $tables[$Object->table]['indexes'] = $db->index($Object);
221:                             unset($currentTables[$key]);
222:                         }
223:                         if (!empty($Object->hasAndBelongsToMany)) {
224:                             foreach ($Object->hasAndBelongsToMany as $Assoc => $assocData) {
225:                                 if (isset($assocData['with'])) {
226:                                     $class = $assocData['with'];
227:                                 } elseif ($assocData['_with']) {
228:                                     $class = $assocData['_with'];
229:                                 }
230:                                 if (is_object($Object->$class)) {
231:                                     $table = $db->fullTableName($Object->$class, false);
232:                                     if (in_array($table, $currentTables)) {
233:                                         $key = array_search($table, $currentTables);
234:                                         $tables[$Object->$class->table] = $this->__columns($Object->$class);
235:                                         $tables[$Object->$class->table]['indexes'] = $db->index($Object->$class);
236:                                         unset($currentTables[$key]);
237:                                     }
238:                                 }
239:                             }
240:                         }
241:                     }
242:                 }
243:             }
244:         }
245: 
246:         if (!empty($currentTables)) {
247:             foreach ($currentTables as $table) {
248:                 if ($prefix) {
249:                     if (strpos($table, $prefix) !== 0) {
250:                         continue;
251:                     }
252:                     $table = str_replace($prefix, '', $table);
253:                 }
254:                 $Object = new AppModel(array(
255:                     'name' => Inflector::classify($table), 'table' => $table, 'ds' => $connection
256:                 ));
257: 
258:                 $systemTables = array(
259:                     'aros', 'acos', 'aros_acos', Configure::read('Session.table'), 'i18n'
260:                 );
261: 
262:                 if (in_array($table, $systemTables)) {
263:                     $tables[$Object->table] = $this->__columns($Object);
264:                     $tables[$Object->table]['indexes'] = $db->index($Object);
265:                 } elseif ($models === false) {
266:                     $tables[$table] = $this->__columns($Object);
267:                     $tables[$table]['indexes'] = $db->index($Object);
268:                 } else {
269:                     $tables['missing'][$table] = $this->__columns($Object);
270:                     $tables['missing'][$table]['indexes'] = $db->index($Object);
271:                 }
272:             }
273:         }
274: 
275:         ksort($tables);
276:         return compact('name', 'tables');
277:     }
278: /**
279:  * Writes schema file from object or options
280:  *
281:  * @param mixed $object schema object or options array
282:  * @param array $options schema object properties to override object
283:  * @return mixed false or string written to file
284:  * @access public
285:  */
286:     function write($object, $options = array()) {
287:         if (is_object($object)) {
288:             $object = get_object_vars($object);
289:             $this->_build($object);
290:         }
291: 
292:         if (is_array($object)) {
293:             $options = $object;
294:             unset($object);
295:         }
296: 
297:         extract(array_merge(
298:             get_object_vars($this), $options
299:         ));
300: 
301:         $out = "class {$name}Schema extends CakeSchema {\n";
302: 
303:         $out .= "\tvar \$name = '{$name}';\n\n";
304: 
305:         if ($path !== $this->path) {
306:             $out .= "\tvar \$path = '{$path}';\n\n";
307:         }
308: 
309:         if ($file !== $this->file) {
310:             $out .= "\tvar \$file = '{$file}';\n\n";
311:         }
312: 
313:         if ($connection !== 'default') {
314:             $out .= "\tvar \$connection = '{$connection}';\n\n";
315:         }
316: 
317:         $out .= "\tfunction before(\$event = array()) {\n\t\treturn true;\n\t}\n\n\tfunction after(\$event = array()) {\n\t}\n\n";
318: 
319:         if (empty($tables)) {
320:             $this->read();
321:         }
322: 
323:         foreach ($tables as $table => $fields) {
324:             if (!is_numeric($table) && $table !== 'missing') {
325:                 $out .= "\tvar \${$table} = array(\n";
326:                 if (is_array($fields)) {
327:                     $cols = array();
328:                     foreach ($fields as $field => $value) {
329:                         if ($field != 'indexes') {
330:                             if (is_string($value)) {
331:                                 $type = $value;
332:                                 $value = array('type'=> $type);
333:                             }
334:                             $col = "\t\t'{$field}' => array('type' => '" . $value['type'] . "', ";
335:                             unset($value['type']);
336:                             $col .= implode(', ',  $this->__values($value));
337:                         } else {
338:                             $col = "\t\t'indexes' => array(";
339:                             $props = array();
340:                             foreach ((array)$value as $key => $index) {
341:                                 $props[] = "'{$key}' => array(" . implode(', ',  $this->__values($index)) . ")";
342:                             }
343:                             $col .= implode(', ', $props);
344:                         }
345:                         $col .= ")";
346:                         $cols[] = $col;
347:                     }
348:                     $out .= implode(",\n", $cols);
349:                 }
350:                 $out .= "\n\t);\n";
351:             }
352:         }
353:         $out .="}\n";
354: 
355: 
356:         $File =& new File($path . DS . $file, true);
357:         $header = '$Id';
358:         $content = "<?php \n/* SVN FILE: {$header}$ */\n/* {$name} schema generated on: " . date('Y-m-d H:m:s') . " : ". time() . "*/\n{$out}?>";
359:         $content = $File->prepare($content);
360:         if ($File->write($content)) {
361:             return $content;
362:         }
363:         return false;
364:     }
365: /**
366:  * Compares two sets of schemas
367:  *
368:  * @param mixed $old Schema object or array
369:  * @param mixed $new Schema object or array
370:  * @return array Tables (that are added, dropped, or changed)
371:  * @access public
372:  */
373:     function compare($old, $new = null) {
374:         if (empty($new)) {
375:             $new =& $this;
376:         }
377:         if (is_array($new)) {
378:             if (isset($new['tables'])) {
379:                 $new = $new['tables'];
380:             }
381:         } else {
382:             $new = $new->tables;
383:         }
384: 
385:         if (is_array($old)) {
386:             if (isset($old['tables'])) {
387:                 $old = $old['tables'];
388:             }
389:         } else {
390:             $old = $old->tables;
391:         }
392:         $tables = array();
393:         foreach ($new as $table => $fields) {
394:             if ($table == 'missing') {
395:                 continue;
396:             }
397:             if (!array_key_exists($table, $old)) {
398:                 $tables[$table]['add'] = $fields;
399:             } else {
400:                 $diff = array_diff_assoc($fields, $old[$table]);
401:                 if (!empty($diff)) {
402:                     $tables[$table]['add'] = $diff;
403:                 }
404:                 $diff = array_diff_assoc($old[$table], $fields);
405:                 if (!empty($diff)) {
406:                     $tables[$table]['drop'] = $diff;
407:                 }
408:             }
409: 
410:             foreach ($fields as $field => $value) {
411:                 if (isset($old[$table][$field])) {
412:                     $diff = array_diff_assoc($value, $old[$table][$field]);
413:                     if (!empty($diff) && $field !== 'indexes') {
414:                         $tables[$table]['change'][$field] = array_merge($old[$table][$field], $diff);
415:                     }
416:                 }
417: 
418:                 if (isset($add[$table][$field])) {
419:                     $wrapper = array_keys($fields);
420:                     if ($column = array_search($field, $wrapper)) {
421:                         if (isset($wrapper[$column - 1])) {
422:                             $tables[$table]['add'][$field]['after'] = $wrapper[$column - 1];
423:                         }
424:                     }
425:                 }
426:             }
427: 
428:             if (isset($old[$table]['indexes']) && isset($new[$table]['indexes'])) {
429:                 $diff = $this->_compareIndexes($new[$table]['indexes'], $old[$table]['indexes']);
430:                 if ($diff) {
431:                     if (!isset($tables[$table])) {
432:                         $tables[$table] = array();
433:                     }
434:                     if (isset($diff['drop'])) {
435:                         $tables[$table]['drop']['indexes'] = $diff['drop'];
436:                     }
437:                     if ($diff && isset($diff['add'])) {
438:                         $tables[$table]['add']['indexes'] = $diff['add'];
439:                     }
440:                 }
441:             }
442:         }
443:         return $tables;
444:     }
445: /**
446:  * Formats Schema columns from Model Object
447:  *
448:  * @param array $values options keys(type, null, default, key, length, extra)
449:  * @return array Formatted values
450:  * @access public
451:  */
452:     function __values($values) {
453:         $vals = array();
454:         if (is_array($values)) {
455:             foreach ($values as $key => $val) {
456:                 if (is_array($val)) {
457:                     $vals[] = "'{$key}' => array('" . implode("', '",  $val) . "')";
458:                 } else if (!is_numeric($key)) {
459:                     $val = var_export($val, true);
460:                     $vals[] = "'{$key}' => {$val}";
461:                 }
462:             }
463:         }
464:         return $vals;
465:     }
466: /**
467:  * Formats Schema columns from Model Object
468:  *
469:  * @param array $Obj model object
470:  * @return array Formatted columns
471:  * @access public
472:  */
473:     function __columns(&$Obj) {
474:         $db =& ConnectionManager::getDataSource($Obj->useDbConfig);
475:         $fields = $Obj->schema(true);
476:         $columns = $props = array();
477:         foreach ($fields as $name => $value) {
478:             if ($Obj->primaryKey == $name) {
479:                 $value['key'] = 'primary';
480:             }
481:             if (!isset($db->columns[$value['type']])) {
482:                 trigger_error('Schema generation error: invalid column type ' . $value['type'] . ' does not exist in DBO', E_USER_NOTICE);
483:                 continue;
484:             } else {
485:                 $defaultCol = $db->columns[$value['type']];
486:                 if (isset($defaultCol['limit']) && $defaultCol['limit'] == $value['length']) {
487:                     unset($value['length']);
488:                 } elseif (isset($defaultCol['length']) && $defaultCol['length'] == $value['length']) {
489:                     unset($value['length']);
490:                 }
491:                 unset($value['limit']);
492:             }
493: 
494:             if (isset($value['default']) && ($value['default'] === '' || $value['default'] === false)) {
495:                 unset($value['default']);
496:             }
497:             if (empty($value['length'])) {
498:                 unset($value['length']);
499:             }
500:             if (empty($value['key'])) {
501:                 unset($value['key']);
502:             }
503:             $columns[$name] = $value;
504:         }
505: 
506:         return $columns;
507:     }
508: /**
509:  * Compare two schema indexes
510:  *
511:  * @param array $new New indexes
512:  * @param array $old Old indexes
513:  * @return mixed false on failure or array of indexes to add and drop
514:  */
515:     function _compareIndexes($new, $old) {
516:         if (!is_array($new) || !is_array($old)) {
517:             return false;
518:         }
519: 
520:         $add = $drop = array();
521: 
522:         $diff = array_diff_assoc($new, $old);
523:         if (!empty($diff)) {
524:             $add = $diff;
525:         }
526: 
527:         $diff = array_diff_assoc($old, $new);
528:         if (!empty($diff)) {
529:             $drop = $diff;
530:         }
531: 
532:         foreach ($new as $name => $value) {
533:             if (isset($old[$name])) {
534:                 $newUnique = isset($value['unique']) ? $value['unique'] : 0;
535:                 $oldUnique = isset($old[$name]['unique']) ? $old[$name]['unique'] : 0;
536:                 $newColumn = $value['column'];
537:                 $oldColumn = $old[$name]['column'];
538: 
539:                 $diff = false;
540: 
541:                 if ($newUnique != $oldUnique) {
542:                     $diff = true;
543:                 } elseif (is_array($newColumn) && is_array($oldColumn)) {
544:                     $diff = ($newColumn !== $oldColumn);
545:                 } elseif (is_string($newColumn) && is_string($oldColumn)) {
546:                     $diff = ($newColumn != $oldColumn);
547:                 } else {
548:                     $diff = true;
549:                 }
550:                 if ($diff) {
551:                     $drop[$name] = null;
552:                     $add[$name] = $value;
553:                 }
554:             }
555:         }
556:         return array_filter(compact('add', 'drop'));
557:     }
558: }
559: ?>
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs