2017-05-09 17:49:56 +03:00
< ? php
/**
* @ copyright Copyright ( c ) 2017 , Joas Schilling < coding @ schilljs . com >
*
* @ author Joas Schilling < coding @ schilljs . com >
2019-12-03 21:57:53 +03:00
* @ author Morris Jobke < hey @ morrisjobke . de >
2017-05-09 17:49:56 +03:00
*
* @ license GNU AGPL version 3 or any later version
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
2019-12-03 21:57:53 +03:00
* along with this program . If not , see < http :// www . gnu . org / licenses />.
2017-05-09 17:49:56 +03:00
*
*/
namespace OC\App\CodeChecker ;
class DatabaseSchemaChecker {
/**
* @ param string $appId
* @ return array
*/
public function analyse ( $appId ) {
$appPath = \OC_App :: getAppPath ( $appId );
if ( $appPath === false ) {
throw new \RuntimeException ( " No app with given id < $appId > known. " );
}
if ( ! file_exists ( $appPath . '/appinfo/database.xml' )) {
return [ 'errors' => [], 'warnings' => []];
}
libxml_use_internal_errors ( true );
$loadEntities = libxml_disable_entity_loader ( false );
$xml = simplexml_load_file ( $appPath . '/appinfo/database.xml' );
libxml_disable_entity_loader ( $loadEntities );
$errors = $warnings = [];
foreach ( $xml -> table as $table ) {
// Table names
2018-01-13 01:37:40 +03:00
if ( strpos (( string ) $table -> name , '*dbprefix*' ) !== 0 ) {
$errors [] = 'Database schema error: name of table ' . ( string ) $table -> name . ' does not start with *dbprefix*' ;
2017-05-09 17:49:56 +03:00
}
2018-01-13 01:37:40 +03:00
$tableName = substr (( string ) $table -> name , strlen ( '*dbprefix*' ));
2017-05-09 17:49:56 +03:00
if ( strpos ( $tableName , '*dbprefix*' ) !== false ) {
2018-01-13 01:37:40 +03:00
$warnings [] = 'Database schema warning: *dbprefix* should only appear once in name of table ' . ( string ) $table -> name ;
2017-05-09 17:49:56 +03:00
}
if ( strlen ( $tableName ) > 27 ) {
2018-01-13 01:37:40 +03:00
$errors [] = 'Database schema error: Name of table ' . ( string ) $table -> name . ' is too long (' . strlen ( $tableName ) . '), max. 27 characters (21 characters for tables with autoincrement) + *dbprefix* allowed' ;
2017-05-09 17:49:56 +03:00
}
$hasAutoIncrement = false ;
// Column names
foreach ( $table -> declaration -> field as $column ) {
2018-01-13 01:37:40 +03:00
if ( strpos (( string ) $column -> name , '*dbprefix*' ) !== false ) {
$warnings [] = 'Database schema warning: *dbprefix* should not appear in name of column ' . ( string ) $column -> name . ' on table ' . ( string ) $table -> name ;
2017-05-09 17:49:56 +03:00
}
2018-01-13 01:37:40 +03:00
if ( strlen (( string ) $column -> name ) > 30 ) {
$errors [] = 'Database schema error: Name of column ' . ( string ) $column -> name . ' on table ' . ( string ) $table -> name . ' is too long (' . strlen ( $tableName ) . '), max. 30 characters allowed' ;
2017-05-09 17:49:56 +03:00
}
if ( $column -> autoincrement ) {
if ( $hasAutoIncrement ) {
2018-01-13 01:37:40 +03:00
$errors [] = 'Database schema error: Table ' . ( string ) $table -> name . ' has multiple autoincrement columns' ;
2017-05-09 17:49:56 +03:00
}
if ( strlen ( $tableName ) > 21 ) {
2018-01-13 01:37:40 +03:00
$errors [] = 'Database schema error: Name of table ' . ( string ) $table -> name . ' is too long (' . strlen ( $tableName ) . '), max. 27 characters (21 characters for tables with autoincrement) + *dbprefix* allowed' ;
2017-05-09 17:49:56 +03:00
}
$hasAutoIncrement = true ;
}
}
// Index names
foreach ( $table -> declaration -> index as $index ) {
2018-01-13 01:37:40 +03:00
$hasPrefix = strpos (( string ) $index -> name , '*dbprefix*' );
2017-05-10 13:35:14 +03:00
if ( $hasPrefix !== false && $hasPrefix !== 0 ) {
2018-01-13 01:37:40 +03:00
$warnings [] = 'Database schema warning: *dbprefix* should only appear at the beginning in name of index ' . ( string ) $index -> name . ' on table ' . ( string ) $table -> name ;
2017-05-09 17:49:56 +03:00
}
2018-01-13 01:37:40 +03:00
$indexName = $hasPrefix === 0 ? substr (( string ) $index -> name , strlen ( '*dbprefix*' )) : ( string ) $index -> name ;
2017-05-09 17:49:56 +03:00
if ( strlen ( $indexName ) > 27 ) {
2018-01-13 01:37:40 +03:00
$errors [] = 'Database schema error: Name of index ' . ( string ) $index -> name . ' on table ' . ( string ) $table -> name . ' is too long (' . strlen ( $tableName ) . '), max. 27 characters + *dbprefix* allowed' ;
2017-05-09 17:49:56 +03:00
}
}
}
return [ 'errors' => $errors , 'warnings' => $warnings ];
}
}