00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 class eZDBSchemaInterface
00084 {
00085
00086
00087
00088
00089
00090
00091
00092 function eZDBSchemaInterface( $params )
00093 {
00094 $this->DBInstance =& $params['instance'];
00095 $this->Schema = false;
00096 $this->Data = false;
00097 if ( isset( $params['schema'] ) )
00098 $this->Schema = $params['schema'];
00099 if ( isset( $params['data'] ) )
00100 $this->Data = $params['data'];
00101 }
00102
00103
00104
00105
00106
00107
00108
00109 function schema( $params = array() )
00110 {
00111 }
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 function data( $schema = false, $tableNameList = false, $params = array() )
00127 {
00128 $params = array_merge( array( 'meta_data' => false,
00129 'format' => 'generic' ),
00130 $params );
00131
00132 if ( $this->Data === false )
00133 {
00134 if ( $schema === false )
00135 $schema = $this->schema( $params );
00136
00137
00138 if ( $schema['_info']['format'] == 'generic' )
00139 $this->transformSchema( $schema, true );
00140
00141 $data = array();
00142 foreach ( $schema as $tableName => $tableInfo )
00143 {
00144
00145 if ( $tableName == '_info' )
00146 continue;
00147
00148 if ( is_array( $tableNameList ) and
00149 !in_array( $tableName, $tableNameList ) )
00150 continue;
00151
00152 $tableEntry = $this->fetchTableData( $tableInfo );
00153 if ( count( $tableEntry['rows'] ) > 0 )
00154 $data[$tableName] = $tableEntry;
00155 }
00156 $this->transformData( $data, $params['format'] == 'local' );
00157 ksort( $data );
00158 $this->Data = $data;
00159 }
00160 else
00161 {
00162 $this->transformData( $this->Data, $params['format'] == 'local' );
00163 $data = $this->Data;
00164 }
00165
00166 return $data;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176 function validate()
00177 {
00178 return false;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 function fetchTableData( $tableInfo, $offset = false, $limit = false )
00198 {
00199 if ( count( $tableInfo['fields'] ) == 0 )
00200 return false;
00201
00202 $tableName = $tableInfo['name'];
00203 $fieldText = '';
00204 $i = 0;
00205 $fields = array();
00206 foreach ( $tableInfo['fields'] as $fieldName => $field )
00207 {
00208 if ( $i > 0 )
00209 $fieldText .= ', ';
00210 $fieldText .= $fieldName;
00211 $fields[] = $fieldName;
00212 ++$i;
00213 }
00214 $rows = $this->DBInstance->arrayQuery( "SELECT $fieldText FROM $tableName" );
00215 $resultArray = array();
00216 foreach ( $rows as $row )
00217 {
00218 $rowData = array();
00219 foreach ( $tableInfo['fields'] as $fieldName => $field )
00220 {
00221 if ( $field['type'] == 'char' )
00222 {
00223 $rowData[$fieldName] = str_pad( $row[$fieldName], $field['length'], ' ' );
00224 }
00225 else
00226 {
00227 $rowData[$fieldName] = $row[$fieldName];
00228 }
00229 }
00230 $resultArray[] = array_values( $rowData );
00231 }
00232 return array( 'fields' => $fields,
00233 'rows' => $resultArray );
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243 function writeUpgradeFile( $differences, $filename, $params = array() )
00244 {
00245 $params = array_merge( array( 'schema' => true,
00246 'data' => false,
00247 'allow_multi_insert' => false,
00248 'diff_friendly' => false ),
00249 $params );
00250 $fp = @fopen( $filename, 'w' );
00251 if ( $fp )
00252 {
00253 fputs( $fp, $this->generateUpgradeFile( $differences, $params ) );
00254 fclose( $fp );
00255 return true;
00256 }
00257 else
00258 {
00259 return false;
00260 }
00261 }
00262
00263
00264
00265
00266
00267
00268 function writeSQLSchemaFile( $filename, $params = array() )
00269 {
00270 $params = array_merge( array( 'schema' => true,
00271 'data' => false,
00272 'allow_multi_insert' => false,
00273 'diff_friendly' => false ),
00274 $params );
00275 $includeSchema = $params['schema'];
00276 $includeData = $params['data'];
00277 $fp = @fopen( $filename, 'w' );
00278 if ( $fp )
00279 {
00280 $schema = $this->schema( $params );
00281 $this->transformSchema( $schema, true );
00282 if ( $includeSchema )
00283 {
00284 fputs( $fp, $this->generateSchemaFile( $schema, $params ) );
00285 }
00286 if ( $includeData )
00287 {
00288 $data = $this->data( $schema );
00289 $this->transformData( $data, true );
00290 fputs( $fp, $this->generateDataFile( $schema, $data, $params ) );
00291 }
00292 fclose( $fp );
00293 return true;
00294 }
00295 else
00296 {
00297 return false;
00298 }
00299 }
00300
00301
00302
00303
00304
00305
00306 function writeSerializedSchemaFile( $filename, $params = array() )
00307 {
00308 $params = array_merge( array( 'schema' => true,
00309 'data' => false ),
00310 $params );
00311 $includeSchema = $params['schema'];
00312 $includeData = $params['data'];
00313 $fp = @fopen( $filename, 'w' );
00314 if ( $fp )
00315 {
00316 $schema = $this->schema( $params );
00317 if ( $includeSchema and $includeData )
00318 {
00319 fputs( $fp, serialize( array( 'schema' => $schema,
00320 'data' => $this->data( $schema ) ) ) );
00321 }
00322 else if ( $includeSchema )
00323 {
00324 fputs( $fp, serialize( $schema ) );
00325 }
00326 else if ( $includeData )
00327 {
00328 fputs( $fp, serialize( $this->data( $schema ) ) );
00329 }
00330 fclose( $fp );
00331 return true;
00332 }
00333 else
00334 {
00335 return false;
00336 }
00337 }
00338
00339
00340
00341
00342
00343
00344 function writeArraySchemaFile( $filename, $params = array() )
00345 {
00346 $params = array_merge( array( 'schema' => true,
00347 'data' => false ),
00348 $params );
00349 $includeSchema = $params['schema'];
00350 $includeData = $params['data'];
00351 $fp = @fopen( $filename, 'w' );
00352 if ( $fp )
00353 {
00354 $schema = $this->schema( $params );
00355 fputs( $fp, '<?' . 'php' . "\n" );
00356 if ( $includeSchema )
00357 {
00358 fputs( $fp, "// This array contains the database schema\n" );
00359 if ( isset( $schema['_info'] ) )
00360 {
00361 $info = $schema['_info'];
00362 unset( $schema['_info'] );
00363 $schema['_info'] = $info;
00364 }
00365 fputs( $fp, '$schema = ' . var_export( $schema, true ) . ";\n" );
00366 }
00367 if ( $includeData )
00368 {
00369 $data = $this->data( $schema );
00370 fputs( $fp, "// This array contains the database data\n" );
00371 if ( isset( $data['_info'] ) )
00372 {
00373 $info = $data['_info'];
00374 unset( $data['_info'] );
00375 $data['_info'] = $info;
00376 }
00377 fputs( $fp, '$data = ' . var_export( $data, true ) . ";\n" );
00378 }
00379 fputs( $fp, "\n" . '?>' );
00380 fclose( $fp );
00381 return true;
00382 }
00383 else
00384 {
00385 return false;
00386 }
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 function insertSchema( $params = array() )
00398 {
00399 $params = array_merge( array( 'schema' => true,
00400 'data' => false ),
00401 $params );
00402
00403 if ( !is_object( $this->DBInstance ) )
00404 {
00405 eZDebug::writeError( "No database instance is available, cannot insert", 'eZDBSchemaInterface::insertSchema' );
00406 return false;
00407 }
00408
00409 $oldOutputSQL = $this->DBInstance->OutputSQL;
00410 $this->DBInstance->OutputSQL = false;
00411
00412 $includeSchema = $params['schema'];
00413 $includeData = $params['data'];
00414 $params['format'] = 'local';
00415 $schema = $this->schema( $params );
00416 if ( $includeSchema )
00417 {
00418 foreach ( $schema as $tableName => $table )
00419 {
00420
00421 if ( $tableName == '_info' )
00422 continue;
00423
00424 $sqlList = $this->generateTableSQLList( $tableName, $table, $params, false );
00425 foreach ( $sqlList as $sql )
00426 {
00427 if ( !$this->DBInstance->query( $sql ) )
00428 {
00429 eZDebug::writeError( "Failed inserting the SQL:\n$sql" );
00430 return false;
00431 }
00432 }
00433 }
00434 }
00435 if ( $includeData )
00436 {
00437 $data = $this->data( $schema, false, array( 'format' => 'local' ) );
00438 foreach ( $schema as $tableName => $table )
00439 {
00440
00441 if ( $tableName == '_info' )
00442 continue;
00443
00444 if ( !isset( $data[$tableName] ) )
00445 {
00446 continue;
00447 }
00448
00449 $sqlList = $this->generateTableInsertSQLList( $tableName, $table, $data[$tableName], $params, false );
00450 foreach ( $sqlList as $sql )
00451 {
00452 if ( !$this->DBInstance->query( $sql ) )
00453 {
00454 eZDebug::writeError( "Failed inserting the SQL:\n$sql" );
00455 return false;
00456 }
00457 }
00458 }
00459
00460
00461 if ( method_exists( $this->DBInstance, 'correctSequenceValues' ) )
00462 {
00463 $status = $this->DBInstance->correctSequenceValues();
00464 if ( !$status )
00465 return false;
00466 }
00467 }
00468 $this->DBInstance->OutputSQL = $oldOutputSQL;
00469 return true;
00470 }
00471
00472
00473
00474
00475
00476
00477 function generateDataFile( $schema, $data, $params )
00478 {
00479 $params = array_merge( array( 'allow_multi_insert' => false,
00480 'diff_friendly' => false ),
00481 $params );
00482 $sql = '';
00483
00484 $i = 0;
00485 foreach ( $schema as $tableName => $tableDef )
00486 {
00487
00488 if ( $tableName == '_info' )
00489 continue;
00490
00491 if ( !isset( $data[$tableName] ) )
00492 continue;
00493 if ( $i > 0 )
00494 $sql .= "\n\n";
00495 $dataEntries = $data[$tableName];
00496 $sql .= $this->generateTableInsert( $tableName, $tableDef, $dataEntries, $params );
00497 ++$i;
00498 }
00499
00500 return $sql;
00501 }
00502
00503
00504
00505
00506
00507
00508 function generateSchemaFile( $schema, $params = array() )
00509 {
00510 $sql = '';
00511
00512 $i = 0;
00513 foreach ( $schema as $table => $tableDef )
00514 {
00515
00516 if ( $table == '_info' )
00517 continue;
00518
00519 if ( $i > 0 )
00520 $sql .= "\n\n";
00521 $sql .= $this->generateTableSchema( $table, $tableDef, $params );
00522 ++$i;
00523 }
00524
00525 return $sql;
00526 }
00527
00528
00529
00530
00531 function generateUpgradeFile( $differences, $params = array() )
00532 {
00533 $params = array_merge( array( 'schema' => true,
00534 'data' => false,
00535 'allow_multi_insert' => false,
00536 'diff_friendly' => false ),
00537 $params );
00538 $sql = '';
00539
00540
00541 if ( isset( $differences['table_changes'] ) )
00542 {
00543 foreach ( $differences['table_changes'] as $table => $table_diff )
00544 {
00545 if ( isset ( $table_diff['added_fields'] ) )
00546 {
00547 foreach ( $table_diff['added_fields'] as $field_name => $added_field )
00548 {
00549 $this->appendSQLComments( $added_field, $sql );
00550 $sql .= $this->generateAddFieldSql( $table, $field_name, $added_field, $params );
00551 }
00552 }
00553
00554 if ( isset ( $table_diff['changed_fields'] ) )
00555 {
00556 foreach ( $table_diff['changed_fields'] as $field_name => $changed_field )
00557 {
00558 $changed_field_def =& $changed_field['field-def'];
00559 $diffPrams = array_merge( $params, array( 'different-options' => $changed_field['different-options'] ) );
00560 $this->appendSQLComments( $changed_field_def, $sql );
00561 $sql .= $this->generateAlterFieldSql( $table, $field_name, $changed_field_def, $diffPrams );
00562 unset( $diffPrams );
00563 }
00564 }
00565 if ( isset ( $table_diff['removed_fields'] ) )
00566 {
00567 foreach ( $table_diff['removed_fields'] as $field_name => $removed_field)
00568 {
00569 $this->appendSQLComments( $removed_field, $sql );
00570 $sql .= $this->generateDropFieldSql( $table, $field_name, $params );
00571 }
00572 }
00573
00574 if ( isset ( $table_diff['removed_indexes'] ) )
00575 {
00576 foreach ( $table_diff['removed_indexes'] as $index_name => $removed_index)
00577 {
00578 $this->appendSQLComments( $removed_index, $sql );
00579 $sql .= $this->generateDropIndexSql( $table, $index_name, $removed_index, $params );
00580 }
00581 }
00582 if ( isset ( $table_diff['added_indexes'] ) )
00583 {
00584 foreach ( $table_diff['added_indexes'] as $index_name => $added_index)
00585 {
00586 $this->appendSQLComments( $added_index, $sql );
00587 $sql .= $this->generateAddIndexSql( $table, $index_name, $added_index, $params );
00588 }
00589 }
00590
00591 if ( isset ( $table_diff['changed_indexes'] ) )
00592 {
00593 foreach ( $table_diff['changed_indexes'] as $index_name => $changed_index )
00594 {
00595
00596 $this->appendSQLComments( $changed_index, $sql );
00597 $sql .= $this->generateDropIndexSql( $table, $index_name, $changed_index, $params );
00598 $sql .= $this->generateAddIndexSql( $table, $index_name, $changed_index, $params );
00599
00600 }
00601 }
00602 }
00603 }
00604 if ( isset( $differences['new_tables'] ) )
00605 {
00606 foreach ( $differences['new_tables'] as $table => $table_def )
00607 {
00608 $this->appendSQLComments( $table_def, $sql );
00609 $sql .= $this->generateTableSchema( $table, $table_def, $params );
00610 }
00611 }
00612 if ( isset( $differences['removed_tables'] ) )
00613 {
00614 foreach ( $differences['removed_tables'] as $table => $table_def )
00615 {
00616 $this->appendSQLComments( $table_def, $sql );
00617 $sql .= $this->generateDropTable( $table, $params );
00618 }
00619 }
00620 return $sql;
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646 function generateTableSQLList( $tableName, $table, $params, $separateTypes )
00647 {
00648 return false;
00649 }
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662 function generateTableSchema( $tableName, $table, $params )
00663 {
00664 return false;
00665 }
00666
00667
00668
00669
00670
00671
00672
00673 function generateTableInsert( $tableName, $tableDef, $dataEntries, $params )
00674 {
00675 return join( "\n", $this->generateTableInsertSQLList( $tableName, $tableDef, $dataEntries, $params, true ) );
00676 }
00677
00678
00679
00680
00681
00682 function generateTableInsertSQLList( $tableName, $tableDef, $dataEntries, $params, $withClosure = true )
00683 {
00684 $diffFriendly = isset( $params['diff_friendly'] ) ? $params['diff_friendly'] : false;
00685 $multiInsert = ( isset( $params['allow_multi_insert'] ) and $params['allow_multi_insert'] ) ? $this->isMultiInsertSupported() : false;
00686
00687
00688 if ( count( $dataEntries['rows'] ) == 0 )
00689 return '';
00690
00691 $sqlList = array();
00692 $sql = '';
00693 $defText = '';
00694 $entryIndex = 0;
00695 foreach ( $dataEntries['fields'] as $fieldName )
00696 {
00697 if ( !isset( $tableDef['fields'][$fieldName] ) )
00698 continue;
00699 if ( $entryIndex == 0 )
00700 {
00701 if ( $diffFriendly )
00702 {
00703 $defText .= " ";
00704 }
00705 }
00706 else
00707 {
00708 if ( $diffFriendly )
00709 {
00710 $defText .= ",\n ";
00711 }
00712 else
00713 {
00714 $defText .= ", ";
00715 }
00716 }
00717 $defText .= $fieldName;
00718 ++$entryIndex;
00719 }
00720
00721 if ( $multiInsert )
00722 {
00723 if ( $diffFriendly )
00724 {
00725 $sql .= "INSERT INTO $tableName (\n $defText\n)\nVALUES\n";
00726 }
00727 else
00728 {
00729 $sql .= "INSERT INTO $tableName ($defText) VALUES ";
00730 }
00731 }
00732 $insertIndex = 0;
00733 foreach ( $dataEntries['rows'] as $row )
00734 {
00735 if ( $multiInsert and $insertIndex > 0 )
00736 {
00737 if ( $diffFriendly )
00738 $sql .= "\n,\n";
00739 else
00740 $sql .= ", ";
00741 }
00742 $dataText = '';
00743 $entryIndex = 0;
00744 foreach ( $dataEntries['fields'] as $fieldName )
00745 {
00746 if ( !isset( $tableDef['fields'][$fieldName] ) )
00747 continue;
00748 if ( $entryIndex == 0 )
00749 {
00750 if ( $diffFriendly )
00751 {
00752 $dataText .= " ";
00753 }
00754 }
00755 else
00756 {
00757 if ( $diffFriendly )
00758 {
00759 $dataText .= ",\n ";
00760 }
00761 else
00762 {
00763 $dataText .= ",";
00764 }
00765 }
00766 $dataText .= $this->generateDataValueTextSQL( $tableDef['fields'][$fieldName], $row[$entryIndex] );
00767 ++$entryIndex;
00768 }
00769 if ( $multiInsert )
00770 {
00771 if ( $diffFriendly )
00772 {
00773 $sql .= "(\n $dataText\n)";
00774 }
00775 else
00776 {
00777 $sql .= "($dataText)";
00778 }
00779 ++$insertIndex;
00780 }
00781 else
00782 {
00783 if ( $diffFriendly )
00784 {
00785 $sqlList[] = "INSERT INTO $tableName (\n$defText\n) VALUES (\n$dataText\n)" . ( $withClosure ? ";" : "" );
00786 }
00787 else
00788 {
00789 $sqlList[] = "INSERT INTO $tableName ($defText) VALUES ($dataText)" . ( $withClosure ? ";" : "" );
00790 }
00791 }
00792 }
00793 if ( $multiInsert )
00794 {
00795 if ( $withClosure )
00796 $sql .= "\n;";
00797 $sqlList[] = $sql;
00798 }
00799 return $sqlList;
00800 }
00801
00802
00803
00804
00805
00806 function generateDataValueTextSQL( $fieldDef, $value )
00807 {
00808 if ( $fieldDef['type'] == 'auto_increment' or
00809 $fieldDef['type'] == 'int' or
00810 $fieldDef['type'] == 'float' )
00811 {
00812 if ( $value === null or
00813 $value === false )
00814 return "NULL";
00815 $value = (int)$value;
00816 $value = (string)$value;
00817 return $value;
00818 }
00819 else if ( is_string( $value ) )
00820 {
00821 return "'" . $this->escapeSQLString( $value ) . "'";
00822 }
00823 else
00824 {
00825 if ( $value === null or
00826 $value === false )
00827 return "NULL";
00828 return (string)$value;
00829 }
00830 }
00831
00832
00833
00834
00835
00836
00837 function escapeSQLString( $value )
00838 {
00839 return $value;
00840 }
00841
00842
00843
00844
00845
00846 function generateAlterFieldSql( $table_name, $field_name, $def )
00847 {
00848 }
00849
00850
00851
00852
00853
00854 function generateAddFieldSql( $table_name, $field_name, $def )
00855 {
00856 }
00857
00858
00859
00860
00861 function generateDropFieldSql( $table_name, $field_name )
00862 {
00863 $sql = "ALTER TABLE $table_name DROP COLUMN $field_name";
00864
00865 return $sql . ";\n";
00866 }
00867
00868
00869
00870
00871
00872 function appendSQLComments( $def, &$sql )
00873 {
00874 if ( isset( $def['comments'] ) )
00875 {
00876 if ( count( $def['comments'] ) > 0 )
00877 $sql .= "\n";
00878 foreach ( $def['comments'] as $comment )
00879 {
00880 $commentLines = explode( "\n", $comment );
00881 foreach ( $commentLines as $commentLine )
00882 {
00883 $sql .= '-- ' . $commentLine . "\n";
00884 }
00885 }
00886 return true;
00887 }
00888 return false;
00889 }
00890
00891
00892
00893
00894
00895
00896
00897 function isMultiInsertSupported()
00898 {
00899 return false;
00900 }
00901
00902
00903
00904
00905
00906
00907
00908
00909 function schemaType()
00910 {
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920 function schemaName()
00921 {
00922 }
00923
00924
00925
00926
00927
00928
00929 function loadSchemaTransformationRules( $schemaType )
00930 {
00931 include_once( 'lib/ezutils/classes/ezini.php' );
00932 $ini =& eZINI::instance( 'dbschema.ini' );
00933
00934 if ( !$ini )
00935 {
00936 eZDebug::writeError( "Error loading $schemaType schema transformation rules" );
00937 return false;
00938 }
00939
00940 $transformationRules = array();
00941
00942 if ( $ini->hasVariable( $schemaType, 'ColumnNameTranslation' ) )
00943 $transformationRules['column-name'] = $ini->variable( $schemaType, 'ColumnNameTranslation' );
00944
00945 if ( $ini->hasVariable( $schemaType, 'ColumnTypeTranslation' ) )
00946 {
00947 $transformationRules['column-type'] = $ini->variable( $schemaType, 'ColumnTypeTranslation' );
00948
00949
00950 if ( is_array( $transformationRules['column-type'] ) )
00951 {
00952 foreach ( $transformationRules['column-type'] as $key => $val )
00953 {
00954 $types = explode( ';', $val );
00955 $transformationRules['column-type'][$key] = $types;
00956 }
00957 }
00958 }
00959
00960 $indexTranslations = array();
00961 if ( $ini->hasVariable( $schemaType, 'IndexTranslation' ) )
00962 {
00963 $translations = $ini->variable( $schemaType, 'IndexTranslation' );
00964 foreach ( $translations as $combinedName => $translation )
00965 {
00966 list( $tableName, $indexName ) = explode( '.', $combinedName );
00967 $indexTranslations[$tableName][$indexName] = array();
00968 $fields = explode( ';', $translation );
00969 foreach ( $fields as $field )
00970 {
00971 $entries = explode( '.', $field );
00972 $fieldName = $entries[0];
00973 $fieldData = array();
00974 for ( $i = 1; $i < count( $entries ); ++$i )
00975 {
00976 list( $metaName, $metaValue ) = explode( '/', $entries[$i], 2 );
00977 if ( is_numeric( $metaValue ) )
00978 $metaValue = (int)$metaValue;
00979 $fieldData[$metaName] = $metaValue;
00980 }
00981 $indexTranslations[$tableName][$indexName][$fieldName] = $fieldData;
00982 }
00983 }
00984 }
00985 $transformationRules['index-field'] = $indexTranslations;
00986
00987 $tableTranslations = array();
00988 if ( $ini->hasVariable( $schemaType, 'TableOptionTranslation' ) )
00989 {
00990 $translations = $ini->variable( $schemaType, 'TableOptionTranslation' );
00991 foreach ( $translations as $tableName => $optionTexts )
00992 {
00993 $tableTranslations[$tableName] = array();
00994 $options = explode( ';', $optionTexts );
00995 $optionData = array();
00996 foreach ( $options as $option )
00997 {
00998 list( $metaName, $metaValue ) = explode( '/', $option, 2 );
00999 if ( is_numeric( $metaValue ) )
01000 $metaValue = (int)$metaValue;
01001 $optionData[$metaName] = $metaValue;
01002 $tableTranslations[$tableName] = $optionData;
01003 }
01004 }
01005 }
01006 $transformationRules['table-option'] = $tableTranslations;
01007
01008 if ( $ini->hasVariable( $schemaType, 'IndexNameTranslation' ) )
01009 {
01010 $tmpIdxNameTranslations = $ini->variable( $schemaType, 'IndexNameTranslation' );
01011
01012 if ( is_array( $tmpIdxNameTranslations ) )
01013 {
01014 foreach ( $tmpIdxNameTranslations as $key => $val )
01015 {
01016 list( $tableName, $genericIdxName ) = explode( '.', $key );
01017 $localIdxName = $val;
01018 if ( !$tableName || !$genericIdxName || !$localIdxName )
01019 {
01020 eZDebug::writeWarning( "Malformed index name translation rule: $key => $val" );
01021 continue;
01022 }
01023 $transformationRules['index-name'][] = array( $tableName, $genericIdxName, $localIdxName );
01024
01025 }
01026 }
01027 unset( $tmpIdxNameTranslations );
01028 }
01029
01030 if ( $ini->hasVariable( $schemaType, 'ColumnOptionTranslations' ) )
01031 {
01032 $transformationRules['column-option'] = array();
01033 foreach( $ini->variable( $schemaType, 'ColumnOptionTranslations' ) as $key => $val )
01034 {
01035 list( $tableName, $colName ) = explode( '.', $key );
01036 $colOptOverride = $val;
01037 if ( !$tableName || !$colName || !$colOptOverride )
01038 {
01039 eZDebug::writeWarning( "Malformed column option translation rule: $key => $val" );
01040 continue;
01041 }
01042 $transformationRules['column-option'][] = array( $tableName, $colName, $colOptOverride );
01043 }
01044 }
01045
01046
01047 foreach ( array( 'column-name', 'column-type', 'column-option', 'index-name' ) as $rulesType )
01048 {
01049 if( !isset( $transformationRules[$rulesType] ) )
01050 $transformationRules[$rulesType] = array();
01051 }
01052
01053 return $transformationRules;
01054 }
01055
01056
01057
01058
01059
01060
01061
01062
01063 function transformSchema( &$schema, $toLocal )
01064 {
01065
01066 if ( isset( $schema['_info']['format'] ) )
01067 {
01068 if ( $schema['_info']['format'] == ( $toLocal ? 'local' : 'generic' ) )
01069 return true;
01070 }
01071
01072
01073 $schema['_info']['format'] = $toLocal ? 'local' : 'generic';
01074
01075
01076 $schemaType = $this->schemaType();
01077 $schemaTransformationRules = eZDBSchemaInterface::loadSchemaTransformationRules( $schemaType );
01078 if ( $schemaTransformationRules === false )
01079 return false;
01080
01081
01082 foreach ( $schemaTransformationRules['column-name'] as $key => $val )
01083 {
01084 list( $tableName, $genericColName ) = explode( '.', $key );
01085 $localColName = $val;
01086
01087 if ( $toLocal )
01088 {
01089 $searchColName =& $genericColName;
01090 $replacementColName =& $localColName;
01091 }
01092 else
01093 {
01094 $searchColName =& $localColName;
01095 $replacementColName =& $genericColName;
01096 }
01097
01098 if ( !isset( $schema[$tableName] ) )
01099 continue;
01100
01101
01102 $fieldsSchema =& $schema[$tableName]['fields'];
01103 if ( isset( $fieldsSchema[$searchColName] ) )
01104 {
01105 $schema[$tableName]['fields'][$replacementColName] =& $schema[$tableName]['fields'][$searchColName];
01106 unset( $schema[$tableName]['fields'][$searchColName] );
01107 ksort( $schema[$tableName]['fields'] );
01108 eZDebugSetting::writeDebug( 'lib-dbschema-transformation', '',
01109 "transformed table column name $tableName.$searchColName to $replacementColName" );
01110 }
01111
01112
01113
01114 $indexesSchema =& $schema[$tableName]['indexes'];
01115 foreach ( $indexesSchema as $indexName => $indexSchema )
01116 {
01117 if ( ( $key = array_search( $searchColName, $indexSchema['fields'] ) ) !== false )
01118 {
01119 $indexesSchema[$indexName]['fields'][$key] = $replacementColName;
01120 eZDebugSetting::writeDebug( 'lib-dbschema-transformation', '',
01121 "transformed index columnn name $indexName.$searchColName to $replacementColName" );
01122 }
01123 }
01124 }
01125
01126
01127 foreach ( $schemaTransformationRules['column-type'] as $key => $val )
01128 {
01129 list( $tableName, $colName ) = explode( '.', $key );
01130 list( $genericType, $localType ) = $val;
01131
01132 if ( !isset( $schema[$tableName] ) )
01133 continue;
01134
01135 preg_match( '/(\w+)\((\d+)\)/', $localType, $matches );
01136 $localLength = ( count($matches) == 2 ) ? $matches[2] : null;
01137 if ( count($matches) == 2 )
01138 $localType = $matches[1];
01139
01140 preg_match( '/(\w+)\((\d+)\)/', $genericType, $matches );
01141 $genericLength = ( count($matches) == 2 ) ? $matches[2] : null;
01142 if ( count($matches) == 2 )
01143 $genericType = $matches[1];
01144
01145 $fieldsSchema =& $schema[$tableName]['fields'];
01146 if ( !isset( $schema[$tableName]['fields'][$colName] ) )
01147 continue;
01148
01149 $fieldSchema =& $fieldsSchema[$colName];
01150
01151 if ( $toLocal )
01152 {
01153 $searchType =& $genericType;
01154 $searchLength =& $genericLength;
01155 $replacementType =& $localType;
01156 $replacementLength =& $localLength;
01157 }
01158 else
01159 {
01160 $searchType =& $localType;
01161 $searchLength =& $localLength;
01162 $replacementType =& $genericType;
01163 $replacementLength =& $genericLength;
01164 }
01165
01166 $fieldSchema['type'] = $replacementType;
01167 if ( $replacementLength !== null )
01168 $fieldSchema['length'] = $replacementLength;
01169 else
01170 unset( $fieldSchema['length'] );
01171
01172 eZDebugSetting::writeDebug( 'lib-dbschema-transformation', '',
01173 "transformed table column type $schemaType:$tableName.$colName from $searchType to $replacementType" );
01174 }
01175
01176
01177 foreach ( $schemaTransformationRules['index-field'] as $tableName => $indexes )
01178 {
01179 foreach ( $indexes as $indexName => $fields )
01180 {
01181 if ( !isset( $schema[$tableName]['indexes'][$indexName]['fields'] ) )
01182 continue;
01183
01184 $newFields = array();
01185 foreach ( $schema[$tableName]['indexes'][$indexName]['fields'] as $indexField )
01186 {
01187 if ( !is_array( $indexField ) )
01188 {
01189 $indexField = array( 'name' => $indexField );
01190 }
01191 $fieldName = $indexField['name'];
01192 if ( isset( $fields[$fieldName] ) )
01193 {
01194 if ( $toLocal )
01195 {
01196 $indexField = array_merge( $indexField,
01197 $fields[$fieldName] );
01198 }
01199 else
01200 {
01201 foreach ( $fields[$fieldName] as $removeName => $removeValue )
01202 {
01203 unset( $indexField[$removeName] );
01204 }
01205 }
01206 }
01207
01208
01209 if ( count( array_diff( array_keys( $indexField ), array( 'name' ) ) ) == 0 )
01210 {
01211 $indexField = $indexField['name'];
01212 }
01213 $newFields[] = $indexField;
01214 }
01215 $schema[$tableName]['indexes'][$indexName]['fields'] = $newFields;
01216 }
01217 }
01218
01219
01220 foreach ( $schemaTransformationRules['table-option'] as $tableName => $options )
01221 {
01222 if ( !isset( $schema[$tableName] ) )
01223 continue;
01224
01225 if ( !isset( $schema[$tableName]['options'] ) )
01226 {
01227 if ( $toLocal )
01228 $schema[$tableName]['options'] = $options;
01229 }
01230 else
01231 {
01232 if ( $toLocal )
01233 {
01234 $schema[$tableName]['options'] = array_merge( $schema[$tableName]['options'], $options );
01235 }
01236 else
01237 {
01238 foreach ( $options as $optionName => $optionValue )
01239 {
01240 unset( $schema[$tableName]['options'][$optionName] );
01241 }
01242 }
01243 }
01244 }
01245
01246
01247 foreach ( $schemaTransformationRules['index-name'] as $idxTransRule )
01248 {
01249 list( $tableName, $genericIdxName, $localIdxName ) = $idxTransRule;
01250
01251 if ( $toLocal )
01252 {
01253 $searchIdxName =& $genericIdxName;
01254 $replacementIdxName =& $localIdxName;
01255 }
01256 else
01257 {
01258 $searchIdxName =& $localIdxName;
01259 $replacementIdxName =& $genericIdxName;
01260 }
01261
01262 if ( !isset( $schema[$tableName] ) )
01263 continue;
01264
01265 $fieldsSchema =& $schema[$tableName]['indexes'];
01266 if ( isset( $fieldsSchema[$searchIdxName] ) )
01267 {
01268 eZDebugSetting::writeDebug( 'lib-dbschema-transformation', '',
01269 "replaced $tableName.$searchIdxName => $replacementIdxName" );
01270 $schema[$tableName]['indexes'][$replacementIdxName] =& $schema[$tableName]['indexes'][$searchIdxName];
01271 unset( $schema[$tableName]['indexes'][$searchIdxName] );
01272 ksort( $schema[$tableName]['indexes'] );
01273 }
01274
01275 }
01276
01277
01278 foreach ( $schemaTransformationRules['column-option'] as $colOptTransRule )
01279 {
01280 list( $tableName, $colName, $colOptOverride ) = $colOptTransRule;
01281
01282 if ( !isset( $schema[$tableName] ) || !isset( $schema[$tableName]['fields'][$colName] ) )
01283 continue;
01284
01285 $fieldSchema =& $schema[$tableName]['fields'][$colName];
01286
01287 switch ( $colOptOverride )
01288 {
01289 case 'null':
01290 {
01291 if ( $toLocal )
01292 {
01293
01294 unset( $fieldSchema['not_null'] );
01295 eZDebugSetting::writeDebug( 'lib-dbschema-transformation', '',
01296 "transformed table column option: $schemaType:$tableName.$colName set to NULL" );
01297 }
01298 else
01299 {
01300
01301 $fieldSchema['not_null'] = '1';
01302 eZDebugSetting::writeDebug( 'lib-dbschema-transformation', '',
01303 "transformed table column option: $schemaType:$tableName.$colName set to NOT NULL" );
01304 }
01305
01306
01307 {
01308 $tmp = $fieldSchema['default'];
01309 unset( $fieldSchema['default'] );
01310 $fieldSchema['default'] = $tmp;
01311 }
01312 } break;
01313 default:
01314 {
01315 eZDebug::writeWarning( "Column option override '$colOptOverride' is not supported" );
01316 } break;
01317 }
01318
01319
01320 }
01321
01322
01323 return true;
01324 }
01325
01326
01327
01328
01329
01330
01331
01332
01333 function transformData( &$data, $toLocal )
01334 {
01335
01336 if ( isset( $data['_info']['format'] ) )
01337 {
01338 if ( $data['_info']['format'] == ( $toLocal ? 'local' : 'generic' ) )
01339 return true;
01340 }
01341
01342
01343 $data['_info']['format'] = $toLocal ? 'local' : 'generic';
01344
01345
01346 $schemaType = $this->schemaType();
01347 $schemaTransformationRules = eZDBSchemaInterface::loadSchemaTransformationRules( $schemaType );
01348 if ( $schemaTransformationRules === false )
01349 return false;
01350
01351
01352 foreach ( $schemaTransformationRules['column-name'] as $key => $val )
01353 {
01354 list( $tableName, $genericColName ) = explode( '.', $key );
01355 $localColName = $val;
01356
01357 if ( $toLocal )
01358 {
01359 $searchColName =& $genericColName;
01360 $replacementColName =& $localColName;
01361 }
01362 else
01363 {
01364 $searchColName =& $localColName;
01365 $replacementColName =& $genericColName;
01366 }
01367
01368 if ( !isset( $data[$tableName] ) )
01369 continue;
01370
01371
01372 $fieldsData =& $data[$tableName]['fields'];
01373 foreach ( $fieldsData as $key => $fieldName )
01374 {
01375 if ( $searchColName == $fieldName )
01376 {
01377 $data[$tableName]['fields'][$key] = $replacementColName;
01378 eZDebugSetting::writeDebug( 'lib-dbschema-data-transformation', '',
01379 "transformed table column name $tableName.$searchColName to $replacementColName" );
01380 }
01381 }
01382 }
01383
01384 return true;
01385 }
01386
01387
01388 var $DBInstance;
01389 var $Schema;
01390 var $Data;
01391 }
01392
01393 ?>