diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index cfc53bfef5..1a2d240f6e 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -8570,31 +8570,6 @@ parameters: count: 1 path: src/Import/Ajax.php - - - message: "#^Cannot access offset 0 on mixed\\.$#" - count: 3 - path: src/Import/Import.php - - - - message: "#^Cannot access offset 1 on mixed\\.$#" - count: 1 - path: src/Import/Import.php - - - - message: "#^Cannot access offset 2 on mixed\\.$#" - count: 1 - path: src/Import/Import.php - - - - message: "#^Cannot access offset int on mixed\\.$#" - count: 3 - path: src/Import/Import.php - - - - message: "#^Cannot access offset int\\<0, max\\> on mixed\\.$#" - count: 2 - path: src/Import/Import.php - - message: "#^Cannot call method getExtension\\(\\) on mixed\\.$#" count: 1 @@ -8605,11 +8580,6 @@ parameters: count: 1 path: src/Import/Import.php - - - message: "#^Cannot cast mixed to int\\.$#" - count: 1 - path: src/Import/Import.php - - message: "#^Cannot cast mixed to string\\.$#" count: 6 diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 98ade9c49f..225fd8a6f2 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -6425,27 +6425,12 @@ - - - - - - - - - - - - - - - @@ -6460,7 +6445,6 @@ getProperties()->getExtension()]]> - @@ -8865,6 +8849,9 @@ + + + diff --git a/src/Import/ColumnType.php b/src/Import/ColumnType.php new file mode 100644 index 0000000000..bd775d4fdb --- /dev/null +++ b/src/Import/ColumnType.php @@ -0,0 +1,15 @@ += $lastCumulativeSize) { return $currSize; } @@ -581,7 +573,7 @@ class Import return $lastCumulativeSize; } - if ($lastCumulativeType === self::DECIMAL) { + if ($lastCumulativeType === ColumnType::Decimal) { /** * The last cumulative type was DECIMAL */ @@ -594,7 +586,7 @@ class Import return $oldM; } - if ($lastCumulativeType === self::BIGINT || $lastCumulativeType === self::INT) { + if ($lastCumulativeType === ColumnType::BigInt || $lastCumulativeType === ColumnType::Int) { /** * The last cumulative type was BIGINT or INT */ @@ -605,7 +597,7 @@ class Import return $lastCumulativeSize; } - if ($lastCumulativeType === null || $lastCumulativeType === self::NONE) { + if ($lastCumulativeType === null || $lastCumulativeType === ColumnType::None) { /** * This is the first row to be analyzed */ @@ -622,14 +614,14 @@ class Import return -1; } - if ($currentCellType === self::DECIMAL) { + if ($currentCellType === ColumnType::Decimal) { /** * What to do if the current cell is of type DECIMAL */ /** * The last cumulative type was VARCHAR */ - if ($lastCumulativeType === self::VARCHAR) { + if ($lastCumulativeType === ColumnType::Varchar) { /* Convert $last_cumulative_size from varchar to decimal format */ $size = $this->getDecimalSize($cell); @@ -640,7 +632,7 @@ class Import return $lastCumulativeSize; } - if ($lastCumulativeType === self::DECIMAL) { + if ($lastCumulativeType === ColumnType::Decimal) { /** * The last cumulative type was DECIMAL */ @@ -659,7 +651,7 @@ class Import return $lastCumulativeSize; } - if ($lastCumulativeType === self::BIGINT || $lastCumulativeType === self::INT) { + if ($lastCumulativeType === ColumnType::BigInt || $lastCumulativeType === ColumnType::Int) { /** * The last cumulative type was BIGINT or INT */ @@ -673,7 +665,7 @@ class Import return $lastCumulativeSize . ',' . $size[self::D]; } - if ($lastCumulativeType === null || $lastCumulativeType === self::NONE) { + if ($lastCumulativeType === null || $lastCumulativeType === ColumnType::None) { /** * This is the first row to be analyzed */ @@ -693,14 +685,14 @@ class Import return -1; } - if ($currentCellType === self::BIGINT || $currentCellType === self::INT) { + if ($currentCellType === ColumnType::BigInt || $currentCellType === ColumnType::Int) { /** * What to do if the current cell is of type BIGINT or INT */ /** * The last cumulative type was VARCHAR */ - if ($lastCumulativeType === self::VARCHAR) { + if ($lastCumulativeType === ColumnType::Varchar) { if ($currSize >= $lastCumulativeSize) { return $currSize; } @@ -708,7 +700,7 @@ class Import return $lastCumulativeSize; } - if ($lastCumulativeType === self::DECIMAL) { + if ($lastCumulativeType === ColumnType::Decimal) { /** * The last cumulative type was DECIMAL */ @@ -727,7 +719,7 @@ class Import return ($newInt + $oldD) . ',' . $oldD; } - if ($lastCumulativeType === self::BIGINT || $lastCumulativeType === self::INT) { + if ($lastCumulativeType === ColumnType::BigInt || $lastCumulativeType === ColumnType::Int) { /** * The last cumulative type was BIGINT or INT */ @@ -738,7 +730,7 @@ class Import return $lastCumulativeSize; } - if ($lastCumulativeType === null || $lastCumulativeType === self::NONE) { + if ($lastCumulativeType === null || $lastCumulativeType === ColumnType::None) { /** * This is the first row to be analyzed */ @@ -768,15 +760,15 @@ class Import /** * Determines what MySQL type a cell is * - * @param int|null $lastCumulativeType Last cumulative column type - * (VARCHAR or INT or BIGINT or DECIMAL or NONE) - * @param string|null $cell String representation of the cell for which - * a best-fit type is to be determined + * @param ColumnType|null $lastCumulativeType Last cumulative column type + * (VARCHAR or INT or BIGINT or DECIMAL or NONE) + * @param string|null $cell String representation of the cell for which + * a best-fit type is to be determined * - * @return int The MySQL type representation + * @return ColumnType The MySQL type representation * (VARCHAR or INT or BIGINT or DECIMAL or NONE) */ - public function detectType(int|null $lastCumulativeType, string|null $cell): int + public function detectType(ColumnType|null $lastCumulativeType, string|null $cell): ColumnType { /** * If numeric, determine if decimal, int or bigint @@ -784,15 +776,15 @@ class Import */ if ($cell === 'NULL') { - if ($lastCumulativeType === null || $lastCumulativeType === self::NONE) { - return self::NONE; + if ($lastCumulativeType === null || $lastCumulativeType === ColumnType::None) { + return ColumnType::None; } return $lastCumulativeType; } if (! is_numeric($cell)) { - return self::VARCHAR; + return ColumnType::Varchar; } if ( @@ -800,18 +792,18 @@ class Import && str_contains($cell, '.') && mb_substr_count($cell, '.') === 1 ) { - return self::DECIMAL; + return ColumnType::Decimal; } if (abs((int) $cell) > 2147483647) { - return self::BIGINT; + return ColumnType::BigInt; } if ($cell !== (string) (int) $cell) { - return self::VARCHAR; + return ColumnType::Varchar; } - return self::INT; + return ColumnType::Int; } /** @@ -819,26 +811,19 @@ class Import * * @link https://wiki.phpmyadmin.net/pma/Import * - * @return array{int[], (int|string)[]} array(array $types, array $sizes) + * @return array{ColumnType[], (int|string)[]} array(array $types, array $sizes) */ public function analyzeTable(ImportTable $table): array { /* Get number of rows in table */ /* Get number of columns */ $numCols = count($table->columns); - /* Current type for each column */ - $types = []; - $sizes = []; /* Initialize $sizes to all 0's */ - for ($i = 0; $i < $numCols; ++$i) { - $sizes[$i] = 0; - } + $sizes = array_fill(0, $numCols, 0); /* Initialize $types to NONE */ - for ($i = 0; $i < $numCols; ++$i) { - $types[$i] = self::NONE; - } + $types = array_fill(0, $numCols, ColumnType::None); /* Analyze each column */ for ($i = 0; $i < $numCols; ++$i) { @@ -854,23 +839,27 @@ class Import * If a type for this column has already been declared, * only alter it if it was a number and a varchar was found */ - if ($currType == self::NONE) { + if ($currType === ColumnType::None) { continue; } - if ($currType == self::VARCHAR) { - $types[$i] = self::VARCHAR; - } elseif ($currType == self::DECIMAL) { - if ($types[$i] != self::VARCHAR) { - $types[$i] = self::DECIMAL; + if ($currType === ColumnType::Varchar) { + $types[$i] = ColumnType::Varchar; + } elseif ($currType === ColumnType::Decimal) { + if ($types[$i] !== ColumnType::Varchar) { + $types[$i] = ColumnType::Decimal; } - } elseif ($currType == self::BIGINT) { - if ($types[$i] != self::VARCHAR && $types[$i] != self::DECIMAL) { - $types[$i] = self::BIGINT; + } elseif ($currType === ColumnType::BigInt) { + if ($types[$i] !== ColumnType::Varchar && $types[$i] !== ColumnType::Decimal) { + $types[$i] = ColumnType::BigInt; } - } elseif ($currType == self::INT) { - if ($types[$i] != self::VARCHAR && $types[$i] != self::DECIMAL && $types[$i] != self::BIGINT) { - $types[$i] = self::INT; + } elseif ($currType === ColumnType::Int) { + if ( + $types[$i] !== ColumnType::Varchar + && $types[$i] !== ColumnType::Decimal + && $types[$i] !== ColumnType::BigInt + ) { + $types[$i] = ColumnType::Int; } } } @@ -879,11 +868,11 @@ class Import /* Check to ensure that all types are valid */ $len = count($types); for ($n = 0; $n < $len; ++$n) { - if ((string) $types[$n] !== (string) self::NONE) { + if ($types[$n] !== ColumnType::None) { continue; } - $types[$n] = self::VARCHAR; + $types[$n] = ColumnType::Varchar; $sizes[$n] = '10'; } @@ -896,12 +885,11 @@ class Import * * @link https://wiki.phpmyadmin.net/pma/Import * - * @param string $dbName Name of the database - * @param ImportTable[] $tables Array of tables for the specified database - * @param mixed[]|null $analyses Analyses of the tables - * @param string[]|null $additionalSql Additional SQL statements to be executed - * @param mixed[]|null $options Associative array of options - * @param string[] $sqlData List of SQL statements to be executed + * @param ImportTable[] $tables + * @param array{0:ColumnType[], 1:(int|string)[], 2?:true[]}[]|null $analyses Analyses of the tables + * @param string[]|null $additionalSql Additional SQL to be executed + * @param mixed[]|null $options Associative array of options + * @param string[] $sqlData List of SQL to be executed */ public function buildSql( string $dbName, @@ -952,16 +940,7 @@ class Import } } - if ($analyses != null) { - $typeArray = [ - self::NONE => 'NULL', - self::VARCHAR => 'varchar', - self::INT => 'int', - self::DECIMAL => 'decimal', - self::BIGINT => 'bigint', - self::GEOMETRY => 'geometry', - ]; - + if ($analyses !== null) { /* TODO: Do more checking here to make sure they really are matched */ if (count($tables) !== count($analyses)) { ResponseRenderer::getInstance()->callExit(); @@ -979,8 +958,15 @@ class Import $size = 10; } - $tempSQLStr .= Util::backquote($column) . ' ' . $typeArray[$analyses[$i][self::TYPES][$j]]; - if ($analyses[$i][self::TYPES][$j] != self::GEOMETRY) { + $tempSQLStr .= Util::backquote($column) . ' ' . match ($analyses[$i][self::TYPES][$j]) { + ColumnType::None => 'NULL', + ColumnType::Varchar => 'varchar', + ColumnType::Int => 'int', + ColumnType::Decimal => 'decimal', + ColumnType::BigInt => 'bigint', + ColumnType::Geometry => 'geometry', + }; + if ($analyses[$i][self::TYPES][$j] !== ColumnType::Geometry) { $tempSQLStr .= '(' . $size . ')'; } @@ -1034,14 +1020,13 @@ class Import // If fully formatted SQL, no need to enclose // with apostrophes, add slashes etc. if ( - $analyses != null + $analyses !== null && isset($analyses[$i][self::FORMATTEDSQL][$colCount]) - && $analyses[$i][self::FORMATTEDSQL][$colCount] == true ) { $tempSQLStr .= (string) $row[$k]; } else { - if ($analyses != null) { - $isVarchar = $analyses[$i][self::TYPES][$colCount] === self::VARCHAR; + if ($analyses !== null) { + $isVarchar = $analyses[$i][self::TYPES][$colCount] === ColumnType::Varchar; } else { $isVarchar = ! is_numeric($row[$k]); } diff --git a/src/Plugins/Import/ImportShp.php b/src/Plugins/Import/ImportShp.php index e85434342a..c9ea0d4ba2 100644 --- a/src/Plugins/Import/ImportShp.php +++ b/src/Plugins/Import/ImportShp.php @@ -15,6 +15,7 @@ use PhpMyAdmin\Gis\GisMultiLineString; use PhpMyAdmin\Gis\GisMultiPoint; use PhpMyAdmin\Gis\GisPoint; use PhpMyAdmin\Gis\GisPolygon; +use PhpMyAdmin\Import\ColumnType; use PhpMyAdmin\Import\Import; use PhpMyAdmin\Import\ImportSettings; use PhpMyAdmin\Import\ImportTable; @@ -278,7 +279,7 @@ class ImportShp extends ImportPlugin // Use data from shape file to chose best-fit MySQL types for each column $analysis = $this->import->analyzeTable($table); - $analysis[Import::TYPES][0] = Import::GEOMETRY; + $analysis[Import::TYPES][0] = ColumnType::Geometry; $analysis[Import::FORMATTEDSQL][0] = true; // Set database name to the currently selected one, if applicable diff --git a/tests/unit/Import/ImportTest.php b/tests/unit/Import/ImportTest.php index c3dc84be47..8428bd037e 100644 --- a/tests/unit/Import/ImportTest.php +++ b/tests/unit/Import/ImportTest.php @@ -7,6 +7,7 @@ namespace PhpMyAdmin\Tests\Import; use PhpMyAdmin\Config; use PhpMyAdmin\Current; use PhpMyAdmin\DatabaseInterface; +use PhpMyAdmin\Import\ColumnType; use PhpMyAdmin\Import\Import; use PhpMyAdmin\Import\ImportSettings; use PhpMyAdmin\Tests\AbstractTestCase; @@ -215,14 +216,14 @@ class ImportTest extends AbstractTestCase /** * Test for detectType * - * @param int $expected Expected result of the function - * @param int|null $type Last cumulative column type (VARCHAR or INT or - * BIGINT or DECIMAL or NONE) - * @param string|null $cell String representation of the cell for which a - * best-fit type is to be determined + * @param ColumnType $expected Expected result of the function + * @param ColumnType|null $type Last cumulative column type (VARCHAR or INT or + * BIGINT or DECIMAL or NONE) + * @param string|null $cell String representation of the cell for which a + * best-fit type is to be determined */ #[DataProvider('provDetectType')] - public function testDetectType(int $expected, int|null $type, string|null $cell): void + public function testDetectType(ColumnType $expected, ColumnType|null $type, string|null $cell): void { self::assertSame($expected, $this->import->detectType($type, $cell)); } @@ -230,32 +231,32 @@ class ImportTest extends AbstractTestCase /** * Data provider for testDetectType * - * @return mixed[] + * @return array{ColumnType, ColumnType|null, string|null}[] */ public static function provDetectType(): array { $data = [ - [Import::NONE, null, 'NULL'], - [Import::NONE, Import::NONE, 'NULL'], - [Import::INT, Import::INT, 'NULL'], - [Import::VARCHAR, Import::VARCHAR, 'NULL'], - [Import::VARCHAR, null, null], - [Import::VARCHAR, Import::INT, null], - [Import::INT, Import::INT, '10'], - [Import::DECIMAL, Import::DECIMAL, '10.2'], - [Import::DECIMAL, Import::INT, '10.2'], - [Import::VARCHAR, Import::VARCHAR, 'test'], - [Import::VARCHAR, Import::INT, 'test'], + [ColumnType::None, null, 'NULL'], + [ColumnType::None, ColumnType::None, 'NULL'], + [ColumnType::Int, ColumnType::Int, 'NULL'], + [ColumnType::Varchar, ColumnType::Varchar, 'NULL'], + [ColumnType::Varchar, null, null], + [ColumnType::Varchar, ColumnType::Int, null], + [ColumnType::Int, ColumnType::Int, '10'], + [ColumnType::Decimal, ColumnType::Decimal, '10.2'], + [ColumnType::Decimal, ColumnType::Int, '10.2'], + [ColumnType::Varchar, ColumnType::Varchar, 'test'], + [ColumnType::Varchar, ColumnType::Int, 'test'], ]; if (PHP_INT_MAX > 2147483647) { - $data[] = [Import::BIGINT, Import::BIGINT, '2147483648']; - $data[] = [Import::BIGINT, Import::INT, '2147483648']; + $data[] = [ColumnType::BigInt, ColumnType::BigInt, '2147483648']; + $data[] = [ColumnType::BigInt, ColumnType::Int, '2147483648']; } else { // To be fixed ? // Can not detect a BIGINT since the value is over PHP_INT_MAX - $data[] = [Import::VARCHAR, Import::BIGINT, '2147483648']; - $data[] = [Import::VARCHAR, Import::INT, '2147483648']; + $data[] = [ColumnType::Varchar, ColumnType::BigInt, '2147483648']; + $data[] = [ColumnType::Varchar, ColumnType::Int, '2147483648']; } return $data;