Changeset 7396
- Timestamp:
- 02/08/08 00:51:14 (10 months ago)
- Files:
-
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/propel/addon/sfPropelDatabaseSchema.class.php (modified) (11 diffs)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/propel/builder/SfObjectBuilder.php (modified) (1 diff)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/propel/builder/SfPeerBuilder.php (modified) (1 diff)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/task/sfPropelBaseTask.class.php (modified) (1 diff)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/test/unit/fixtures/new_schema.yml (copied) (copied from branches/1.1/lib/plugins/sfPropelPlugin/test/unit/fixtures/new_schema.yml)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/test/unit/fixtures/schema.xml (copied) (copied from branches/1.1/lib/plugins/sfPropelPlugin/test/unit/fixtures/schema.xml)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/test/unit/fixtures/schema.yml (modified) (1 diff)
- branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/test/unit/sfPropelDatabaseSchemaTest.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/propel/addon/sfPropelDatabaseSchema.class.php
r6707 r7396 3 3 /* 4 4 * This file is part of the symfony package. 5 * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com> 5 * (c) Fabien Potencier <fabien.potencier@symfony-project.com> 6 * (c) Francois Zaninotto <francois.zaninotto@symfony-project.com> 6 7 * 7 8 * For the full copyright and license information, please view the LICENSE … … 28 29 } 29 30 31 public function loadArray($schema_array) 32 { 33 $database = array(); 34 $connection_name = ''; 35 36 if (isset($schema_array['classes'])) 37 { 38 // New schema syntax 39 $schema_array = $this->convertNewToOldYaml($schema_array); 40 } 41 42 if (count($schema_array) > 1) 43 { 44 throw new sfException('A schema.yml must only contain 1 database entry.'); 45 } 46 47 $tmp = array_keys($schema_array); 48 $connection_name = array_shift($tmp); 49 50 if ($connection_name) 51 { 52 $database = $schema_array[$connection_name]; 53 } 54 55 $this->connection_name = $connection_name; 56 $this->database = $database; 57 58 $this->fixYAMLDatabase(); 59 $this->fixYAMLI18n(); 60 $this->fixYAMLColumns(); 61 } 62 30 63 public function loadYAML($file) 31 64 { 32 $schema = sfYaml::load($file); 33 34 if (count($schema) > 1) 35 { 36 throw new sfException('A schema.yml must only contain 1 database entry.'); 37 } 65 $schema_array = sfYaml::load($file); 66 67 if (!isset($schema_array['classes'])) 68 { 69 // Old schema syntax: we convert it 70 $schema_array = $this->convertOldToNewYaml($schema_array); 71 } 72 73 $this->loadArray($schema_array); 74 } 75 76 public function convertOldToNewYaml($schema) 77 { 78 $new_schema = array(); 38 79 39 80 $tmp = array_keys($schema); 40 $this->connection_name = array_shift($tmp); 41 if ($this->connection_name) 42 { 43 $this->database = $schema[$this->connection_name]; 44 45 $this->fixYAMLDatabase(); 46 $this->fixYAMLI18n(); 47 $this->fixYAMLColumns(); 48 } 81 $connection_name = array_shift($tmp); 82 $new_schema['connection'] = $connection_name; 83 84 $classes = array(); 85 foreach($schema[$connection_name] as $table => $table_params) 86 { 87 if ($table == '_attributes') 88 { 89 // Database attributes 90 $new_schema = array_merge($new_schema, $table_params); 91 } 92 else 93 { 94 // Table 95 $phpName = sfInflector::camelize($table); 96 if (isset($table_params['_attributes'])) 97 { 98 $table_attributes = $table_params['_attributes']; 99 unset($table_params['_attributes']); 100 if (isset($table_attributes['phpName'])) 101 { 102 $phpName = $table_attributes['phpName']; 103 unset($table_attributes['phpName']); 104 } 105 } 106 else 107 { 108 $table_attributes = array(); 109 } 110 $classes[$phpName] = $table_attributes; 111 $classes[$phpName]['tableName'] = $table; 112 $classes[$phpName]['columns'] = array(); 113 foreach($table_params as $column => $column_params) 114 { 115 switch($column) 116 { 117 case '_behaviors': 118 $classes[$phpName]['behaviors'] = $column_params; 119 break; 120 case '_foreignKeys': 121 $classes[$phpName]['foreignKeys'] = $column_params; 122 break; 123 case '_indexes': 124 $classes[$phpName]['indexes'] = $column_params; 125 break; 126 case '_uniques': 127 $classes[$phpName]['uniques'] = $column_params; 128 break; 129 default: 130 $classes[$phpName]['columns'][$column] = $column_params; 131 } 132 } 133 } 134 } 135 136 $new_schema['classes'] = $classes; 137 138 return $new_schema; 139 } 140 141 public function convertNewToOldYaml($schema) 142 { 143 144 if (isset($schema['connection'])) 145 { 146 $connection_name = $schema['connection']; 147 unset($schema['connection']); 148 } 149 else 150 { 151 $connection_name = 'propel'; 152 } 153 154 $database = array(); 155 156 // Tables 157 if (isset($schema['classes'])) 158 { 159 $tables = array(); 160 foreach ($schema['classes'] as $className => $classParams) 161 { 162 $tableParams = array(); 163 164 // Columns 165 if (isset($classParams['columns'])) 166 { 167 $tableParams = array_merge($classParams['columns'], $tableParams); 168 unset($classParams['columns']); 169 } 170 171 // Indexes and foreign keys 172 if (isset($classParams['indexes'])) 173 { 174 $tableParams['_indexes'] = $classParams['indexes']; 175 unset($classParams['indexes']); 176 } 177 if (isset($classParams['uniques'])) 178 { 179 $tableParams['_uniques'] = $classParams['uniques']; 180 unset($classParams['uniques']); 181 } 182 if (isset($classParams['foreignKeys'])) 183 { 184 $tableParams['_foreignKeys'] = $classParams['foreignKeys']; 185 unset($classParams['foreignKeys']); 186 } 187 188 // Behaviors 189 if (isset($classParams['behaviors'])) 190 { 191 $tableParams['_behaviors'] = $classParams['behaviors']; 192 unset($classParams['behaviors']); 193 } 194 195 // Table attributes 196 $tableAttributes = array(); 197 if (isset($classParams['tableName'])) 198 { 199 $tableName = $classParams['tableName']; 200 unset($classParams['tableName']); 201 } 202 else 203 { 204 $tableName = sfInflector::underscore($className); 205 } 206 207 if (sfInflector::camelize($tableName) != $className) 208 { 209 $tableAttributes['phpName'] = $className; 210 } 211 212 if ($tableAttributes || $classParams) 213 { 214 $tableParams['_attributes'] = array_merge($tableAttributes, $classParams); 215 } 216 217 $tables[$tableName] = $tableParams; 218 } 219 $database = array_merge($database, $tables); 220 unset($schema['classes']); 221 } 222 223 // Database attributes 224 if ($schema) 225 { 226 $database['_attributes'] = $schema; 227 } 228 229 return array($connection_name => $database); 49 230 } 50 231 … … 58 239 foreach ($this->getChildren($this->database) as $tb_name => $table) 59 240 { 60 $xml .= "\n <table name=\"$tb_name\"".$this->getAttributesFor($table).">\n"; 241 $xml .= "\n <table name=\"$tb_name\"".$this->getAttributesFor($table); 242 if (isset($table['_behaviors'])) 243 { 244 $xml .= sprintf(" behaviors=\"%s\"", htmlspecialchars(serialize($table['_behaviors']))); 245 } 246 $xml .= ">\n"; 61 247 62 248 // columns … … 227 413 'required' => true, 228 414 'primaryKey' => true, 229 'auto increment' => true415 'autoIncrement' => true 230 416 ); 231 417 $has_primary_key = true; … … 241 427 $this->database[$table][$column] = array( 242 428 'type' => 'integer', 243 'required' => true,244 429 'foreignTable' => $foreign_table, 245 'foreignReference' => 'id' ,430 'foreignReference' => 'id' 246 431 ); 247 432 } 248 433 else 249 434 { 250 throw new sfException(sprintf('Unable to resolve foreign table for column "%s" ', $column));435 throw new sfException(sprintf('Unable to resolve foreign table for column "%s".', $column)); 251 436 } 252 437 } 438 253 439 } 254 440 else … … 281 467 'required' => true, 282 468 'primaryKey' => true, 283 'auto increment' => true469 'autoIncrement' => true 284 470 ); 285 471 } … … 314 500 foreach ($this->getTables() as $tb_name => $table) 315 501 { 316 if ((isset($table['_attributes']['phpName']) && $table['_attributes']['phpName'] == sfInflector::camelize($table_name)) || ($tb_name == $table_name)) 502 if ( 503 ($tb_name == $table_name) 504 || (isset($table['_attributes']['phpName']) && 505 ( 506 $table['_attributes']['phpName'] == sfInflector::camelize($table_name) 507 || $table['_attributes']['phpName'] == $table_name 508 ) 509 || (sfInflector::underscore($table_name) == $tb_name)) 510 ) 317 511 { 318 512 $table_match = $tb_name; 513 break; 319 514 } 320 515 } … … 330 525 foreach ($column as $key => $value) 331 526 { 332 if (!in_array($key, array('foreign Table', 'foreignReference', 'onDelete', 'onUpdate', 'index', 'unique')))527 if (!in_array($key, array('foreignClass', 'foreignTable', 'foreignReference', 'onDelete', 'onUpdate', 'index', 'unique', 'sequence'))) 333 528 { 334 529 $attributes_string .= " $key=\"".htmlspecialchars($this->getCorrectValueFor($key, $value))."\""; … … 339 534 else 340 535 { 341 throw new sfException(sprintf('Incorrect settings for column %s', $col_name));536 throw new sfException(sprintf('Incorrect settings for column "%s".', $col_name)); 342 537 } 343 538 344 539 // conventions for foreign key attributes 345 if (is_array($column) && isset($column['foreignTable'])) 346 { 347 $attributes_string .= " <foreign-key foreignTable=\"$column[foreignTable]\""; 540 if (is_array($column) && (isset($column['foreignTable']) || isset($column['foreignClass']))) 541 { 542 if (isset($column['foreignTable'])) 543 { 544 $attributes_string .= " <foreign-key foreignTable=\"$column[foreignTable]\""; 545 } 546 else 547 { 548 $foreignTable = $this->findTable($column['foreignClass']); 549 if (!$foreignTable) 550 { 551 // Let's assume that the class given is from another schema 552 // We have no access to the other schema's phpNames 553 // So our last guess is to try to underscore the class name 554 $foreignTable = sfInflector::underscore($column['foreignClass']); 555 } 556 $attributes_string .= " <foreign-key foreignTable=\"".$foreignTable."\""; 557 } 558 348 559 if (isset($column['onDelete'])) 349 560 { … … 660 871 foreach ($columns as $column => $attributes) 661 872 { 662 if ($column == 'id' && !array_diff($attributes, array('type' => 'integer', 'required' => 'true', 'primaryKey' => 'true', 'auto increment' => 'true')))873 if ($column == 'id' && !array_diff($attributes, array('type' => 'integer', 'required' => 'true', 'primaryKey' => 'true', 'autoIncrement' => 'true'))) 663 874 { 664 875 // simplify primary keys … … 705 916 foreach ($hash as $attribute => $value) 706 917 { 707 $attributes[$attribute] = strval($value);918 $attributes[$attribute] = (string) $value; 708 919 } 709 920 branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/propel/builder/SfObjectBuilder.php
r6707 r7396 349 349 $script .= $tmp; 350 350 } 351 352 protected function addClassClose(&$script) 353 { 354 parent::addClassClose($script); 355 356 $behaviors = $this->getTable()->getAttribute('behaviors'); 357 if($behaviors) 358 { 359 $behavior_file_name = 'Base'.$this->getTable()->getPhpName().'Behaviors'; 360 $behavior_file_path = $this->getFilePath($this->getStubObjectBuilder()->getPackage().'.om.'.$behavior_file_name); 361 $script .= sprintf("\n\ninclude_once '%s';\n", $behavior_file_path); 362 } 363 } 351 364 } branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/propel/builder/SfPeerBuilder.php
r7200 r7396 389 389 $script .= $tmp; 390 390 } 391 392 protected function addClassClose(&$script) 393 { 394 parent::addClassClose($script); 395 396 $behavior_file_name = 'Base'.$this->getTable()->getPhpName().'Behaviors'; 397 $behavior_file_path = $this->getFilePath($this->getStubObjectBuilder()->getPackage().'.om.'.$behavior_file_name); 398 $absolute_behavior_file_path = sfConfig::get('sf_root_dir').'/'.$behavior_file_path; 399 400 if(file_exists($absolute_behavior_file_path)) 401 { 402 unlink($absolute_behavior_file_path); 403 } 404 405 $behaviors = $this->getTable()->getAttribute('behaviors'); 406 if($behaviors) 407 { 408 file_put_contents($absolute_behavior_file_path, sprintf("<?php\nsfPropelBehavior::add('%s', %s);\n", $this->getTable()->getPhpName(), var_export(unserialize($behaviors), true))); 409 $script .= sprintf("\n\ninclude_once '%s';\n", $behavior_file_path); 410 } 411 } 391 412 } branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/lib/task/sfPropelBaseTask.class.php
r7349 r7396 103 103 104 104 $dbSchema = new sfPropelDatabaseSchema(); 105 105 106 foreach ($schemas as $schema) 106 107 { 107 $dbSchema->loadYAML($schema); 108 $schemaArray = sfYaml::load($schema); 109 110 if (!isset($schema_array['classes'])) 111 { 112 // Old schema syntax: we convert it 113 $schemaArray = $dbSchema->convertOldToNewYaml($schemaArray); 114 } 115 116 $customSchemaFilename = str_replace(array(sfConfig::get('sf_root_dir').DIRECTORY_SEPARATOR, 'plugins'.DIRECTORY_SEPARATOR, 'config'.DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, 'schema.yml'), array('', '', '', '_', 'schema.custom.yml'), $schema); 117 $customSchemas = sfFinder::type('file')->name($customSchemaFilename)->in($dirs); 118 119 foreach ($customSchemas as $customSchema) 120 { 121 $this->dispatcher->notify(new sfEvent($this, 'command.log', array($this->formatter->formatSection('schema', sprintf('found custom schema %s', $customSchema))))); 122 123 $customSchemaArray = sfYaml::load($customSchema); 124 if (!isset($customSchemaArray['classes'])) 125 { 126 // Old schema syntax: we convert it 127 $customSchemaArray = $dbSchema->convertOldToNewYaml($customSchemaArray); 128 } 129 $schemaArray = sfToolkit::arrayDeepMerge($schemaArray, $customSchemaArray); 130 } 131 132 $dbSchema->loadArray($schemaArray); 108 133 109 134 $this->dispatcher->notify(new sfEvent($this, 'command.log', array($this->formatter->formatSection('schema', sprintf('converting "%s" to XML', $schema))))); branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/test/unit/fixtures/schema.yml
r5125 r7396 1 1 propel: 2 some_table: 3 _attributes: { phpName: SomeTable } 4 somechar: { type: VARCHAR, size: 255, default: "This & That" } 2 _attributes: { noXsd: false, defaultIdMethod: none, package: lib.model } 3 ab_group: 4 _attributes: { phpName: Group, package: foo.bar.lib.model } 5 id: 6 name: varchar(50) 7 8 cd_user: 9 _attributes: { phpName: User, isI18N: true, i18nTable: cd_user_i18n } 10 first_name: { type: varchar, size: 255, default: "Anonymous" } 11 last_name: varchar(50) 12 age: { type: integer, required: true, index: true } 13 ab_group_id: 14 created_at: 15 16 cd_user_i18n: 17 description: longvarchar 18 19 ef_article: 20 title: { type: longvarchar, required: true, index: unique } 21 stripped_title: { type: longvarchar, required: true, primaryKey: true, sequence: my_custom_sequence_name } 22 user_id: 23 my_group: { type: integer, foreignTable: ab_group, foreignReference: id, onDelete: setnull } 24 my_other_group: { type: integer, foreignTable: ab_group, foreignReference: id, onDelete: setnull } 25 created_at: timestamp 26 updated_at: 27 28 ij_article: 29 _attributes: { phpName: Article } 30 title: varchar(50) 31 user_id: { type: integer } 32 _foreignKeys: 33 - 34 foreignTable: cd_user 35 onDelete: cascade 36 references: 37 - { local: user_id, foreign: id } 38 created_at: 39 _indexes: 40 my_index: [title, user_id] 41 _uniques: 42 my_other_index: [created_at] 43 _behaviors: 44 paranoid: { column: deleted_at } 45 act_as_nested_set: 46 47 ab_group_i18n: 48 motto: longvarchar branches/dwhittle/1.1/lib/plugins/sfPropelPlugin/test/unit/sfPropelDatabaseSchemaTest.php
r5125 r7396 3 3 /* 4 4 * This file is part of the symfony package. 5 * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com> 6 * 5 * (c) Fabien Potencier <fabien.potencier@symfony-project.com> 6 * (c) Francois Zaninotto <francois.zaninotto@symfony-project.com> 7 * 7 8 * For the full copyright and license information, please view the LICENSE 8 9 * file that was distributed with this source code. … … 11 12 require_once(dirname(__FILE__).'/../../../../../test/bootstrap/unit.php'); 12 13 13 $t = new lime_test(1, new lime_output_color()); 14 class my_lime_test extends lime_test 15 { 16 public function is_array_explicit($test, $target, $prefix = '') 17 { 18 foreach ($test as $key => $value) 19 { 20 if (is_array($value)) 21 { 22 $this->is_array_explicit($value, $target[$key], $prefix.' '.$key); 23 } 24 else 25 { 26 $this->is($value, $target[$key], sprintf('%s %s is %s', $prefix, $key, $value)); 27 } 28 } 29 } 14 30 31 public function is_line_by_line($exp1, $exp2) 32 { 33 $array_exp1 = explode("\n", $exp1); 34 $array_exp2 = explode("\n", $exp2); 35 $nb_lines = count($array_exp1); 36 for ($i=0; $i < $nb_lines; $i++) 37 { 38 if(!$array_exp1[$i]) continue; // Skip blank lines to avoid testing nothing 39 $this->is(trim($array_exp1[$i]), trim($array_exp2[$i]), sprintf('Line %d matches %s', $i, $array_exp1[$i])); 40 } 41 } 42 } 43 44 require_once(dirname(__FILE__).'/../../../../../test/bootstrap/unit.php'); 45 require_once(dirname(__FILE__).'/../../lib/propel/addon/sfPropelDatabaseSchema.class.php'); 46 require_once(dirname(__FILE__).'/../../../../util/sfInflector.class.php'); 47 require_once(dirname(__FILE__).'/../../../../util/sfToolkit.class.php'); 48 require_once(dirname(__FILE__).'/../../../../util/sfYaml.class.php'); 49 50 $t = new my_lime_test(261, new lime_output_color()); 51 52 $t->diag('Classical YAML to XML conversion'); 15 53 $p = new sfPropelDatabaseSchema(); 16 54 $p->loadYAML(dirname(__FILE__).'/fixtures/schema.yml'); 17 $t->like($p->asXML(), '/This & That/'); 55 $target = file_get_contents(dirname(__FILE__).'/fixtures/schema.xml'); 56 $t->is_line_by_line($p->asXML(), $target); 57 58 $t->diag('New YAML to XML conversion'); 59 $p = new sfPropelDatabaseSchema(); 60 $p->loadYAML(dirname(__FILE__).'/fixtures/new_schema.yml'); 61 $target = file_get_contents(dirname(__FILE__).'/fixtures/schema.xml'); 62 $t->is_line_by_line($p->asXML(), $target); 63 64 $t->diag('New YAML to Old YAML conversion'); 65 $old_yml_target = sfYaml::load(dirname(__FILE__).'/fixtures/schema.yml'); 66 $p = new sfPropelDatabaseSchema(); 67 $new_yml_transformed = $p->convertNewToOldYaml(sfYaml::load(dirname(__FILE__).'/fixtures/new_schema.yml')); 68 $t->is_array_explicit($new_yml_transformed, $old_yml_target); 69 70 $t->diag('Old YAML to New YAML conversion'); 71 $new_yml_target = sfYaml::load(dirname(__FILE__).'/fixtures/new_schema.yml'); 72 $p = new sfPropelDatabaseSchema(); 73 $old_yml_transformed = $p->convertOldToNewYaml(sfYaml::load(dirname(__FILE__).'/fixtures/schema.yml')); 74 $t->is_array_explicit($old_yml_transformed, $new_yml_target); 75 76 77 $t->todo('XML and classical YAML internal representation'); 78 $p1 = new sfPropelDatabaseSchema(); 79 $p1->loadXML(dirname(__FILE__).'/fixtures/schema.xml'); 80 $p2 = new sfPropelDatabaseSchema(); 81 $p2->loadYAML(dirname(__FILE__).'/fixtures/schema.yml'); 82 //$t->is_array_explicit($p1->asArray(), $p2->asArray()); 83 84 $t->todo('XML and classical YAML compared as XML'); 85 //$t->is_line_by_line($p1->asXML(), $p2->asXML()); 86 87 $t->todo('XML and classical YAML compared as YAML'); 88 //$t->is_line_by_line($p1->asYAML(), $p2->asYAML());