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 include_once( 'lib/ezdbschema/classes/ezdbschemainterface.php' );
00061
00062 class eZLintSchema extends eZDBSchemaInterface
00063 {
00064
00065
00066
00067
00068
00069
00070 function eZLintSchema( $db, $otherSchema )
00071 {
00072 $this->eZDBSchemaInterface( $db );
00073 $this->OtherSchema = $otherSchema;
00074 $this->CorrectSchema = false;
00075 $this->IsLintChecked = false;
00076 }
00077
00078
00079
00080
00081
00082 function schema( $params = array() )
00083 {
00084 if ( $this->IsLintChecked )
00085 {
00086 return $this->CorrectSchema;
00087 }
00088
00089 $params = array_merge( array( 'meta_data' => false,
00090 'format' => 'generic' ),
00091 $params );
00092
00093 $this->CorrectSchema = $this->OtherSchema->schema( $params );
00094 $this->lintCheckSchema( $this->CorrectSchema );
00095 $this->IsLintChecked = true;
00096 return $this->CorrectSchema;
00097 }
00098
00099
00100
00101
00102
00103 function validate()
00104 {
00105 return $this->lintCheckSchema( $this->CorrectSchema );
00106 }
00107
00108
00109
00110
00111 function otherSchema()
00112 {
00113 return $this->OtherSchema;
00114 }
00115
00116
00117
00118
00119 function isLintChecked()
00120 {
00121 return $this->IsLintChecked;
00122 }
00123
00124
00125
00126
00127 function shortenIdentifier( $identifier, $limit, $shortenList )
00128 {
00129 reset( $shortenList );
00130
00131
00132 while ( strlen( $identifier ) > $limit and
00133 current( $shortenList ) !== false )
00134 {
00135 $from = key( $shortenList );
00136 $to = current( $shortenList );
00137 next( $shortenList );
00138 $identifier = str_replace( $from, $to, $identifier );
00139 }
00140
00141
00142 if ( strlen( $identifier ) > $limit )
00143 {
00144 $identifier = substr( $identifier, 0, $limit );
00145 }
00146 return $identifier;
00147 }
00148
00149
00150
00151
00152
00153
00154 function lintCheckSchema( &$schema )
00155 {
00156 $status = true;
00157
00158 $ini =& eZINI::instance( 'dbschema.ini' );
00159
00160
00161
00162 $shortenList = $ini->variable( 'LintChecker', 'NameMap' );
00163
00164
00165
00166
00167 $tableNameLimit = (int)$ini->variable( 'LintChecker', 'TableLimit' );
00168 $fieldNameLimit = (int)$ini->variable( 'LintChecker', 'FieldLimit' );
00169 $indexNameLimit = (int)$ini->variable( 'LintChecker', 'IndexLimit' );
00170
00171
00172
00173
00174 $ignoredTableList = $ini->variable( 'LintChecker', 'IgnoredTables' );
00175
00176
00177
00178 $list = $ini->variable( 'LintChecker', 'IgnoredFields' );
00179 $ignoredFieldList = array();
00180 foreach ( $list as $entry )
00181 {
00182 list( $tableName, $fieldName ) = explode( '.', $entry, 2 );
00183 if ( !isset( $ignoredFieldList[$tableName] ) )
00184 $ignoredFieldList[$tableName] = array();
00185 $ignoredFieldList[$tableName][] = $fieldName;
00186 }
00187
00188
00189
00190 $list = $ini->variable( 'LintChecker', 'IgnoredFieldSyntax' );
00191 $ignoredFieldSyntaxList = array();
00192 foreach ( $list as $entry )
00193 {
00194 list( $tableName, $fieldName ) = explode( '.', $entry, 2 );
00195 if ( !isset( $ignoredFieldList[$tableName] ) )
00196 $ignoredFieldSyntaxList[$tableName] = array();
00197 $ignoredFieldSyntaxList[$tableName][] = $fieldName;
00198 }
00199
00200
00201
00202 $ignoredIndexList = $ini->variable( 'LintChecker', 'IgnoredIndexes' );
00203
00204 $badTables = array();
00205 foreach ( $schema as $tableName => $tableDef )
00206 {
00207
00208 if ( $tableName == '_info' )
00209 continue;
00210
00211 $existingTableName = $tableName;
00212 $tableComments = array();
00213
00214
00215 if ( !in_array( $tableName, $ignoredTableList ) )
00216 {
00217
00218
00219 if ( strlen( $tableName ) > $tableNameLimit )
00220 {
00221 $tableComment = "Table names must not exceed $tableNameLimit characters,\n'$tableName' is " . strlen( $tableName ) . " characters,\ndatabases like Oracle will have problems with this.";
00222 $tableName = $this->shortenIdentifier( $tableName, $tableNameLimit, $shortenList );
00223 $tableComment .= "\nNew name is '$tableName'";
00224 $tableComments[] = $tableComment;
00225 $status = false;
00226 }
00227
00228 if ( strcmp( $tableName, $existingTableName ) != 0 )
00229 {
00230 $badTables[] = array( 'from' => $existingTableName,
00231 'to' => $tableName );
00232 }
00233 }
00234
00235 if ( isset( $tableDef['fields'] ) )
00236 {
00237 $badFields = array();
00238 foreach ( $tableDef['fields'] as $fieldName => $fieldDef )
00239 {
00240 $comments = array();
00241 $existingFieldName = $fieldName;
00242
00243
00244 if ( !isset( $ignoredFieldList[$existingTableName] ) or
00245 !in_array( $fieldName, $ignoredFieldList[$existingTableName] ) )
00246 {
00247
00248
00249 if ( strlen( $fieldName ) > $fieldNameLimit )
00250 {
00251 $comment = "Field names must not exceed $fieldNameLimit characters,\n'$fieldName' in table '$existingTableName' is " . strlen( $fieldName ) . " characters,\ndatabases like Oracle will have problems with this.";
00252 $fieldName = $this->shortenIdentifier( $fieldName, $fieldNameLimit, $shortenList );
00253 $comment .= "\nNew name is '$fieldName'";
00254 $comments[] = $comment;
00255 $status = false;
00256 }
00257 }
00258
00259 if ( !isset( $ignoredFieldSyntaxList[$existingTableName] ) or
00260 !in_array( $fieldName, $ignoredFieldSyntaxList[$existingTableName] ) )
00261 {
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 }
00275
00276 if ( strcmp( $existingFieldName, $fieldName ) != 0 )
00277 {
00278 $badFields[] = array( 'from' => $existingFieldName,
00279 'to' => $fieldName );
00280 }
00281
00282 if ( count( $comments ) > 0 )
00283 {
00284 $schema[$existingTableName]['fields'][$existingFieldName]['comments'] = $comments;
00285 foreach ( $comments as $comment )
00286 {
00287 eZDebug::writeWarning( $comment, 'eZLintSchema::fieldComment' );
00288 }
00289 }
00290 }
00291
00292 foreach ( $badFields as $badField )
00293 {
00294 $schema[$existingTableName]['fields'][$badField['to']] = $schema[$existingTableName]['fields'][$badField['from']];
00295
00296 $schema[$existingTableName]['fields'][$badField['from']]['removed'] = true;
00297 }
00298 }
00299
00300 if ( isset( $tableDef['indexes'] ) )
00301 {
00302 $badIndexes = array();
00303 foreach ( $tableDef['indexes'] as $indexName => $indexDef )
00304 {
00305
00306 if ( $indexDef['type'] == 'primary' )
00307 continue;
00308
00309
00310 if ( in_array( $indexName, $ignoredIndexList ) )
00311 continue;
00312
00313 $comments = array();
00314
00315 $existingIndexName = $indexName;
00316 if ( isset( $schema[$indexName] ) )
00317 {
00318 $comment = "Index named '$indexName' has same name as an existing table,\ndatabases like PostgreSQL and Oracle will have problems with this.";
00319 $indexFieldText = '';
00320 $i = 0;
00321 foreach ( $indexDef['fields'] as $fieldDef )
00322 {
00323 if ( $i > 0 )
00324 $indexFieldText .= '_';
00325 if ( is_array( $fieldDef ) )
00326 {
00327 $indexFieldText .= $fieldDef['name'];
00328 }
00329 else
00330 {
00331 $indexFieldText .= $fieldDef;
00332 }
00333 }
00334 $indexName = $indexName . '_' . $indexFieldText . '_i';
00335 $comment .= "\nNew name is '$indexName'";
00336 $comments[] = $comment;
00337 $status = false;
00338 }
00339
00340
00341 if ( $indexDef['type'] == 'primary' and
00342 $indexName != 'PRIMARY' )
00343 {
00344 $comment = "Index named '$indexName' which is a primary key must be named PRIMARY.";
00345 $indexName = "PRIMARY";
00346 $comments[] = $comment;
00347 $status = false;
00348 }
00349
00350
00351 if ( strlen( $indexName ) > $indexNameLimit )
00352 {
00353 $comment = "Index names must not exceed $indexNameLimit characters,\n'$indexName' is " . strlen( $indexName ) . " characters,\ndatabases like Oracle will have problems with this.";
00354 $indexName = $this->shortenIdentifier( $indexName, $indexNameLimit, $shortenList );
00355 $comment .= "\nNew name is '$indexName'";
00356 $comments[] = $comment;
00357 $status = false;
00358 }
00359
00360
00361 foreach ( $indexDef['fields'] as $fieldDef )
00362 {
00363 if ( is_array( $fieldDef ) )
00364 {
00365 $fieldName = $fieldDef['name'];
00366 foreach ( $fieldDef as $fdName => $fdValue )
00367 {
00368 if ( preg_match( "#^([a-z0-9]+):#", $fdName, $matches ) )
00369 {
00370 $dbName = $matches[1];
00371 $comments[] = "Found database specific entry ($dbName) at index $existingIndexName.$fieldName";
00372 $status = false;
00373 }
00374 }
00375 }
00376 }
00377
00378 if ( strcmp( $existingIndexName, $indexName ) != 0 )
00379 {
00380 $badIndexes[] = array( 'from' => $existingIndexName,
00381 'to' => $indexName );
00382 }
00383 if ( count( $comments ) > 0 )
00384 {
00385 $schema[$existingTableName]['indexes'][$existingIndexName]['comments'] = $comments;
00386 foreach ( $comments as $comment )
00387 {
00388 eZDebug::writeWarning( $comment, 'eZLintSchema::indexComment' );
00389 }
00390 }
00391 }
00392
00393 foreach ( $badIndexes as $badIndex )
00394 {
00395 $schema[$existingTableName]['indexes'][$badIndex['to']] = $schema[$existingTableName]['indexes'][$badIndex['from']];
00396 $schema[$existingTableName]['indexes'][$badIndex['from']]['removed'] = true;
00397 }
00398 }
00399
00400 if ( count( $tableComments ) > 0 )
00401 {
00402 $schema[$existingTableName]['comments'] = $tableComments;
00403 foreach ( $tableComments as $comment )
00404 {
00405 eZDebug::writeWarning( $comment, 'eZLintSchema::tableComment' );
00406 }
00407 }
00408 }
00409 foreach ( $badTables as $badTable )
00410 {
00411 $schema[$badTable['to']] = $schema[$badTable['from']];
00412 $schema[$badTable['from']]['removed'] = true;
00413 }
00414 return $status;
00415 }
00416
00417
00418
00419
00420
00421 function data( $schema = false, $tableNameList = false )
00422 {
00423 return $this->OtherSchema->data( $schema, $tableNameList );
00424 }
00425
00426
00427
00428
00429
00430 function generateSchemaFile( $schema, $params )
00431 {
00432 return $this->OtherSchema->generateSchemaFile( $schema, $params );
00433 }
00434
00435
00436
00437
00438
00439 function generateUpgradeFile( $differences, $params )
00440 {
00441 return $this->OtherSchema->generateUpgradeFile( $differences, $params );
00442 }
00443
00444
00445
00446
00447
00448 function generateDataFile( $schema, $data, $params )
00449 {
00450 return $this->OtherSchema->generateDataFile( $schema, $data, $params );
00451 }
00452
00453
00454
00455
00456
00457 function generateTableSchema( $table, $tableDef, $params )
00458 {
00459 return $this->OtherSchema->generateTableSchema( $table, $tableDef, $params );
00460 }
00461
00462
00463
00464
00465
00466 function generateTableInsert( $tableName, $tableDef, $dataEntries, $params )
00467 {
00468 return $this->OtherSchema->generateTableInsert( $tableName, $tableDef, $dataEntries, $params );
00469 }
00470
00471
00472
00473
00474
00475 function generateDropTable( $table, $params )
00476 {
00477 return $this->OtherSchema->generateDropTable( $table, $params );
00478 }
00479
00480
00481
00482
00483
00484 function generateAddFieldSql( $table, $field_name, $added_field, $params )
00485 {
00486 return $this->OtherSchema->generateAddFieldSql( $table, $field_name, $added_field, $params );
00487 }
00488
00489
00490
00491
00492
00493 function generateAlterFieldSql( $table, $field_name, $changed_field, $params )
00494 {
00495 return $this->OtherSchema->generateAlterFieldSql( $table, $field_name, $changed_field, $params );
00496 }
00497
00498
00499
00500
00501
00502 function generateDropFieldSql( $table, $field_name, $params )
00503 {
00504 return $this->OtherSchema->generateDropFieldSql( $table, $field_name, $params );
00505 }
00506
00507
00508
00509
00510
00511 function generateAddIndexSql( $table, $index_name, $added_index, $params )
00512 {
00513 return $this->OtherSchema->generateAddIndexSql( $table, $index_name, $added_index, $params );
00514 }
00515
00516
00517
00518
00519
00520 function generateDropIndexSql( $table, $index_name, $removed_index, $params )
00521 {
00522 return $this->OtherSchema->generateDropIndexSql( $table, $index_name, $removed_index, $params );
00523 }
00524
00525
00526
00527
00528
00529 function isMultiInsertSupported()
00530 {
00531 return $this->OtherSchema->isMultiInsertSupported();
00532 }
00533
00534
00535
00536
00537
00538 function generateDataValueTextSQL( $fieldDef, $value )
00539 {
00540 return $this->OtherSchema->generateDataValueTextSQL( $fieldDef, $value );
00541 }
00542
00543
00544
00545
00546
00547 function schemaType()
00548 {
00549 return $this->OtherSchema->schemaType();
00550 }
00551
00552
00553
00554
00555
00556 function schemaName()
00557 {
00558 return $this->OtherSchema->schemaName();
00559 }
00560
00561
00562
00563 var $OtherSchema;
00564
00565 var $CorrectSchema;
00566
00567 var $IsLintChecked;
00568 }
00569
00570 ?>