From a98fd679d1a16acbeb0d3e2e694605da801cb9d9 Mon Sep 17 00:00:00 2001 From: Michael Knappe Date: Tue, 24 Jan 2023 16:21:05 +0100 Subject: [PATCH 1/9] Fixes phpstan errors --- composer.json | 3 +- phpstan.neon | 14 +--- .../Common/Config/XmlToArrayConverter.php | 3 +- .../Archivable/ArchivableBehavior.php | 8 +- .../Generator/Builder/Util/SchemaReader.php | 23 +++--- .../Generator/Command/AbstractCommand.php | 10 +-- .../Command/ConfigConvertCommand.php | 4 +- src/Propel/Generator/Command/InitCommand.php | 10 +-- .../Generator/Command/TestPrepareCommand.php | 2 +- .../Generator/Config/ArrayToPhpConverter.php | 2 +- .../Generator/Manager/AbstractManager.php | 12 ++- .../Generator/Manager/MigrationManager.php | 79 ++++++++++++++----- src/Propel/Generator/Manager/ModelManager.php | 1 + src/Propel/Generator/Manager/SqlManager.php | 6 ++ src/Propel/Generator/Model/Behavior.php | 7 +- src/Propel/Generator/Model/Column.php | 2 +- .../Generator/Model/ColumnDefaultValue.php | 9 +-- .../Generator/Model/Diff/ColumnComparator.php | 2 +- src/Propel/Generator/Model/Domain.php | 13 ++- src/Propel/Generator/Model/NameFactory.php | 13 +-- .../Generator/Platform/DefaultPlatform.php | 18 ++--- .../Generator/Platform/OraclePlatform.php | 4 +- .../Generator/Platform/PgsqlPlatform.php | 4 +- .../Generator/Platform/SqlitePlatform.php | 12 ++- .../Generator/Reverse/MssqlSchemaParser.php | 13 +++ .../Generator/Reverse/MysqlSchemaParser.php | 33 +++++++- .../Generator/Reverse/OracleSchemaParser.php | 33 +++++--- .../Generator/Reverse/PgsqlSchemaParser.php | 14 ++-- .../Generator/Schema/Dumper/XmlDumper.php | 2 +- src/Propel/Generator/Util/BehaviorLocator.php | 8 +- src/Propel/Generator/Util/QuickBuilder.php | 10 ++- src/Propel/Generator/Util/VfsTrait.php | 9 ++- src/Propel/Runtime/ActiveQuery/Criteria.php | 26 +++--- src/Propel/Runtime/ActiveQuery/Join.php | 14 ++-- .../QueryExecutor/AbstractQueryExecutor.php | 11 ++- .../Runtime/Adapter/Pdo/PgsqlAdapter.php | 14 ++++ .../Runtime/Collection/CollectionIterator.php | 4 +- .../Runtime/Collection/ObjectCollection.php | 8 +- .../Runtime/Collection/OnDemandIterator.php | 6 +- .../Runtime/Connection/PdoConnection.php | 4 +- .../Runtime/Connection/StatementInterface.php | 2 +- .../Runtime/Connection/StatementWrapper.php | 6 +- .../AbstractFormatterWithHydration.php | 2 + .../Runtime/Formatter/OnDemandFormatter.php | 2 + src/Propel/Runtime/Map/DatabaseMap.php | 1 + .../Runtime/Util/PropelConditionalProxy.php | 4 +- 46 files changed, 318 insertions(+), 169 deletions(-) diff --git a/composer.json b/composer.json index a1c8c78417..87573f13a7 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,8 @@ "symfony/filesystem": "^4.4.0 || ^5.0.0 || ^6.0.0", "symfony/finder": "^4.4.0 || ^5.0.0 || ^6.0.0", "symfony/translation": "^4.4.0 || ^5.0.0 || ^6.0.0", - "symfony/validator": "^4.4.0 || ^5.0.0 || ^6.0.0" + "symfony/validator": "^4.4.0 || ^5.0.0 || ^6.0.0", + "ext-xml": "*" }, "require-dev": { "ext-pdo": "*", diff --git a/phpstan.neon b/phpstan.neon index 696ad141bf..6b096d58c0 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,20 +1,12 @@ includes: - phpstan-baseline.neon parameters: - level: 6 + level: 7 checkMissingIterableValueType: false reportUnmatchedIgnoredErrors: false - treatPhpDocTypesAsCertain: false paths: - '%rootDir%/../../../src/' ignoreErrors: - '#Call to an undefined method .+Collection::.+Array\(\)#' - - - message: "#^Method .+\\\\ConsoleHelper::.+\\(\\) has no return type specified#" - path: src/Propel/Generator/Command/Helper/ConsoleHelper.php - - - message: "#^Method .+\\\\ConsoleHelper::.+\\(\\) has parameter \\$messages with no type specified#" - path: src/Propel/Generator/Command/Helper/ConsoleHelper.php - - - message: "#^Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\TreeBuilder\\:\\:root\\(\\)\\.$#" - path: src/Propel/Common/Config/PropelConfiguration.php + - '#Call to an undefined method object::.+\(\)#' + diff --git a/src/Propel/Common/Config/XmlToArrayConverter.php b/src/Propel/Common/Config/XmlToArrayConverter.php index 9e08c6778a..a06accefe6 100644 --- a/src/Propel/Common/Config/XmlToArrayConverter.php +++ b/src/Propel/Common/Config/XmlToArrayConverter.php @@ -101,9 +101,10 @@ protected static function simpleXmlToArray(SimpleXMLElement $xml): array } } else { // otherwise, just add the attribute like a child element - if (is_string($child)) { + if (!is_array($child)) { $child = []; } + $child[$ak] = self::getConvertedXmlValue($av); } } diff --git a/src/Propel/Generator/Behavior/Archivable/ArchivableBehavior.php b/src/Propel/Generator/Behavior/Archivable/ArchivableBehavior.php index 42f5c55f3a..c7e2b1ddc9 100644 --- a/src/Propel/Generator/Behavior/Archivable/ArchivableBehavior.php +++ b/src/Propel/Generator/Behavior/Archivable/ArchivableBehavior.php @@ -309,7 +309,7 @@ protected function reapplyBehaviors(array $behaviors) } /** - * @psalm-param array{local_column: string, foreign_table: string, foreign_column: string, relation_only?: string} $fkParameterData + * @psalm-param array{name?: string, localColumn: string, foreignTable: string, foreignColumn: string, relationOnly?: string} $fkParameterData * * @param \Propel\Generator\Model\Table $table * @param array $fkParameterData @@ -320,14 +320,12 @@ protected function reapplyBehaviors(array $behaviors) */ protected function createForeignKeyFromParameters(Table $table, array $fkParameterData): void { - if ( - empty($fkParameterData['localColumn']) || - empty($fkParameterData['foreignColumn']) - ) { + if (empty($fkParameterData['localColumn']) || empty($fkParameterData['foreignColumn'])) { $tableName = $this->table->getName(); throw new SchemaException("Table `$tableName`: Archivable behavior misses foreign key parameters. Please supply `localColumn`, `foreignTable` and `foreignColumn` for every entry"); } + $fk = new ForeignKey($fkParameterData['name'] ?? null); $fk->addReference($fkParameterData['localColumn'], $fkParameterData['foreignColumn']); $table->addForeignKey($fk); diff --git a/src/Propel/Generator/Builder/Util/SchemaReader.php b/src/Propel/Generator/Builder/Util/SchemaReader.php index 0ef781bee3..88d2963889 100644 --- a/src/Propel/Generator/Builder/Util/SchemaReader.php +++ b/src/Propel/Generator/Builder/Util/SchemaReader.php @@ -39,9 +39,7 @@ class SchemaReader private $schema; /** - * @psalm-suppress UndefinedDocblockClass - * @phpstan-ignore-next-line - * @var \XMLParser|resource|null + * @var \XMLParser */ private $parser; @@ -158,7 +156,7 @@ public function parseFile(string $xmlFile): ?Schema return null; } - return $this->parseString(file_get_contents($xmlFile), $xmlFile); + return $this->parseString((string)file_get_contents($xmlFile), $xmlFile); } /** @@ -184,7 +182,7 @@ public function parseString(string $xmlString, ?string $xmlFile = null): ?Schema $this->currentXmlFile = $xmlFile; $parserStash = $this->parser; - /** @psalm-suppress InvalidPropertyAssignmentValue */ + $this->parser = xml_parser_create(); xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); xml_set_object($this->parser, $this); @@ -247,7 +245,7 @@ public function startElement($parser, string $tagName, array $attributes): void } if ($xmlFile[0] !== '/') { - $xmlFile = realpath(dirname($this->currentXmlFile) . DIRECTORY_SEPARATOR . $xmlFile); + $xmlFile = (string)realpath(dirname($this->currentXmlFile) . DIRECTORY_SEPARATOR . $xmlFile); if (!file_exists($xmlFile)) { throw new SchemaException(sprintf('Unknown include external `%s`', $xmlFile)); } @@ -458,15 +456,12 @@ private function throwSchemaExceptionWithLocation(string $format, ...$args): voi */ private function getLocationDescription(): string { - $location = ''; - if ($this->currentXmlFile !== null) { - $location .= sprintf('file %s,', $this->currentXmlFile); - } - + $location = ($this->currentXmlFile !== null) ? sprintf('file %s,', $this->currentXmlFile) : ''; $location .= sprintf('line %d', xml_get_current_line_number($this->parser)); - $col = xml_get_current_column_number($this->parser); - if ($col) { - $location .= sprintf(', column %d', $col); + + $currentColumnNumber = xml_get_current_column_number($this->parser); + if ($currentColumnNumber) { + $location .= sprintf(', column %d', $currentColumnNumber); } return $location; diff --git a/src/Propel/Generator/Command/AbstractCommand.php b/src/Propel/Generator/Command/AbstractCommand.php index 657978252a..2d80791613 100644 --- a/src/Propel/Generator/Command/AbstractCommand.php +++ b/src/Propel/Generator/Command/AbstractCommand.php @@ -144,12 +144,12 @@ protected function createDirectory(string $directory): void */ protected function parseConnection(string $connection): array { - $pos = strpos($connection, '='); - $name = substr($connection, 0, $pos); - $dsn = substr($connection, $pos + 1, strlen($connection)); + $length = strpos($connection, '=') ?: null; + $name = substr($connection, 0, $length); + $dsn = substr($connection, $length + 1, strlen($connection)); - $pos = strpos($dsn, ':'); - $adapter = substr($dsn, 0, $pos); + $length = strpos($dsn, ':') ?: null; + $adapter = substr($dsn, 0, $length); $extras = []; foreach (explode(';', $dsn) as $element) { diff --git a/src/Propel/Generator/Command/ConfigConvertCommand.php b/src/Propel/Generator/Command/ConfigConvertCommand.php index 2e350f66fe..8017a5e0b4 100644 --- a/src/Propel/Generator/Command/ConfigConvertCommand.php +++ b/src/Propel/Generator/Command/ConfigConvertCommand.php @@ -156,8 +156,8 @@ protected function createLoadDatabaseDummyScript(string $loaderDir, OutputInterf */ protected function getRelativePathToLoaderScript(string $loaderDir, string $outputDir): string { - $absoluteLoaderDir = realpath($loaderDir); - $absoluteOutputDir = realpath($outputDir); + $absoluteLoaderDir = (string)realpath($loaderDir); + $absoluteOutputDir = (string)realpath($outputDir); $fs = new Filesystem(); return $fs->makePathRelative($absoluteLoaderDir, $absoluteOutputDir); diff --git a/src/Propel/Generator/Command/InitCommand.php b/src/Propel/Generator/Command/InitCommand.php index 0717351fd9..5737d7b222 100644 --- a/src/Propel/Generator/Command/InitCommand.php +++ b/src/Propel/Generator/Command/InitCommand.php @@ -40,7 +40,7 @@ class InitCommand extends AbstractCommand public function __construct(?string $name = null) { parent::__construct($name); - $this->defaultSchemaDir = getcwd(); + $this->defaultSchemaDir = (string)getcwd(); $this->defaultPhpDir = $this->detectDefaultPhpDir(); } @@ -195,7 +195,7 @@ private function detectDefaultPhpDir(): string } } - return getcwd(); + return (string)getcwd(); } /** @@ -401,12 +401,12 @@ private function reverseEngineerSchema(OutputInterface $output, array $options): $input = new ArrayInput($arrInput); $result = $this->getApplication()->run($input, $output); - if ($result === 0) { - $schema = file_get_contents($outputDir . '/schema.xml'); - } else { + if ($result !== 0) { exit(1); } + $schema = (string)file_get_contents($outputDir . '/schema.xml'); + $this->getApplication()->setAutoExit(true); return $schema; diff --git a/src/Propel/Generator/Command/TestPrepareCommand.php b/src/Propel/Generator/Command/TestPrepareCommand.php index 4429fb3478..58f170951f 100644 --- a/src/Propel/Generator/Command/TestPrepareCommand.php +++ b/src/Propel/Generator/Command/TestPrepareCommand.php @@ -127,7 +127,7 @@ protected function buildFixtures(string $fixturesDir, array $connections, InputI chdir($this->root . '/' . $fixturesDir); if (is_file('propel.yaml.dist')) { - $content = file_get_contents('propel.yaml.dist'); + $content = (string)file_get_contents('propel.yaml.dist'); $content = str_replace('##DATABASE_VENDOR##', $input->getOption('vendor'), $content); $content = str_replace('##DATABASE_URL##', $input->getOption('dsn'), $content); diff --git a/src/Propel/Generator/Config/ArrayToPhpConverter.php b/src/Propel/Generator/Config/ArrayToPhpConverter.php index e73b3e0ce4..16e39817fa 100644 --- a/src/Propel/Generator/Config/ArrayToPhpConverter.php +++ b/src/Propel/Generator/Config/ArrayToPhpConverter.php @@ -60,7 +60,7 @@ public static function convert(array $c): string // set default datasource if (isset($c['defaultConnection'])) { $defaultDatasource = $c['defaultConnection']; - } elseif (isset($c['connections']) && is_array($c['connections'])) { + } elseif (is_array($c['connections'])) { // fallback to the first datasource $datasourceNames = array_keys($c['connections']); $defaultDatasource = $datasourceNames[0]; diff --git a/src/Propel/Generator/Manager/AbstractManager.php b/src/Propel/Generator/Manager/AbstractManager.php index 9a52f8cbf1..8f9a21f13a 100644 --- a/src/Propel/Generator/Manager/AbstractManager.php +++ b/src/Propel/Generator/Manager/AbstractManager.php @@ -17,6 +17,7 @@ use Propel\Generator\Exception\EngineException; use Propel\Generator\Model\Database; use Propel\Generator\Model\Schema; +use RuntimeException; use XSLTProcessor; /** @@ -292,6 +293,7 @@ public function setLoggerClosure(Closure $logger): void * class. * * @throws \Propel\Generator\Exception\EngineException + * @throws \RuntimeException * @throws \Propel\Generator\Exception\BuildException * * @return void @@ -326,6 +328,10 @@ protected function loadDataModels(): void $xsl = new XSLTProcessor(); $xsl->importStyleSheet($xslDom); $dom = $xsl->transformToDoc($dom); + + if ($dom === false) { + throw new RuntimeException('XSLTProcessor transformation to a DOMDocument failed.'); + } } } @@ -340,7 +346,7 @@ protected function loadDataModels(): void $xmlParser = new SchemaReader($defaultPlatform, $this->dbEncoding); $xmlParser->setGeneratorConfig($this->getGeneratorConfig()); - $schema = $xmlParser->parseString($dom->saveXML(), $dmFilename); + $schema = $xmlParser->parseString((string)$dom->saveXML(), $dmFilename); $nbTables = $schema->getDatabase(null, false)->countTables(); $totalNbTables += $nbTables; @@ -519,8 +525,8 @@ protected function getProperties(string $file): array continue; } - $pos = strpos($line, '='); - $properties[trim(substr($line, 0, $pos))] = trim(substr($line, $pos + 1)); + $length = strpos($line, '=') ?: null; + $properties[trim(substr($line, 0, $length))] = trim(substr($line, $length + 1)); } return $properties; diff --git a/src/Propel/Generator/Manager/MigrationManager.php b/src/Propel/Generator/Manager/MigrationManager.php index fa69923c43..a581987920 100644 --- a/src/Propel/Generator/Manager/MigrationManager.php +++ b/src/Propel/Generator/Manager/MigrationManager.php @@ -22,6 +22,7 @@ use Propel\Runtime\Adapter\AdapterFactory; use Propel\Runtime\Connection\ConnectionFactory; use Propel\Runtime\Connection\ConnectionInterface; +use RuntimeException; /** * Service class for preparing and executing migrations @@ -123,12 +124,14 @@ public function getAdapterConnection(string $datasource): ConnectionInterface */ public function getPlatform(string $datasource): PlatformInterface { - $params = $this->getConnection($datasource); - $adapter = $params['adapter']; + $connection = $this->getConnection($datasource); + $adapter = ucfirst($connection['adapter']); + $class = '\\Propel\\Generator\\Platform\\' . $adapter . 'Platform'; - $class = '\\Propel\\Generator\\Platform\\' . ucfirst($adapter) . 'Platform'; + /** @var \Propel\Generator\Platform\PlatformInterface $platform */ + $platform = new $class(); - return new $class(); + return $platform; } /** @@ -191,6 +194,8 @@ public function getAllDatabaseVersions(): array /** * @param string $datasource * + * @throws \RuntimeException + * * @return bool */ public function migrationTableExists(string $datasource): bool @@ -199,6 +204,11 @@ public function migrationTableExists(string $datasource): bool $sql = sprintf('SELECT version FROM %s', $this->getMigrationTable()); try { $stmt = $conn->prepare($sql); + + if ($stmt === false) { + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + } + $stmt->execute(); return true; @@ -255,6 +265,11 @@ public function removeMigrationTimestamp(string $datasource, int $timestamp): vo $platform->doQuoting('version'), ); $stmt = $conn->prepare($sql); + + if ($stmt === false) { + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + } + $stmt->bindParam(1, $timestamp, PDO::PARAM_INT); $stmt->execute(); }); @@ -264,6 +279,8 @@ public function removeMigrationTimestamp(string $datasource, int $timestamp): vo * @param string $datasource * @param int $timestamp * + * @throws \RuntimeException + * * @return void */ public function updateLatestMigrationTimestamp(string $datasource, int $timestamp): void @@ -283,6 +300,11 @@ public function updateLatestMigrationTimestamp(string $datasource, int $timestam $executionDatetime = date(static::EXECUTION_DATETIME_FORMAT); $stmt = $conn->prepare($sql); + + if ($stmt === false) { + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + } + $stmt->bindParam(1, $timestamp, PDO::PARAM_INT); $stmt->bindParam(2, $executionDatetime); $stmt->execute(); @@ -298,9 +320,12 @@ public function getMigrationTimestamps(): array if (is_dir($path)) { $files = scandir($path); - foreach ($files as $file) { - if (preg_match('/^PropelMigration_(\d+).*\.php$/', $file, $matches)) { - $migrationTimestamps[] = (int)$matches[1]; + + if ($files) { + foreach ($files as $file) { + if (preg_match('/^PropelMigration_(\d+).*\.php$/', $file, $matches)) { + $migrationTimestamps[] = (int)$matches[1]; + } } } } @@ -340,7 +365,7 @@ public function getNonExecutedMigrationTimestampsByVersion(?int $version = null) return $migrationTimestamps; } - return array_slice($migrationTimestamps, 0, $versionIndex + 1); + return array_slice($migrationTimestamps, 0, (int)$versionIndex + 1); } /** @@ -439,9 +464,11 @@ public function findMigrationClassNameSuffix(int $timestamp): string $path = $this->getWorkingDirectory(); if ($path && is_dir($path)) { $files = scandir($path); - foreach ($files as $file) { - if (preg_match('/^PropelMigration_' . $timestamp . '(_)?(.*)\.php$/', $file, $matches)) { - $suffix = (string)$matches[2]; + if ($files) { + foreach ($files as $file) { + if (preg_match('/^PropelMigration_' . $timestamp . '(_)?(.*)\.php$/', $file, $matches)) { + $suffix = (string)$matches[2]; + } } } } @@ -575,6 +602,8 @@ public function getOldestDatabaseVersion(): ?int /** * @param string $datasource * + * @throws \RuntimeException + * * @return void */ public function modifyMigrationTableIfOutdated(string $datasource): void @@ -593,8 +622,12 @@ public function modifyMigrationTableIfOutdated(string $datasource): void /** @phpstan-var \Propel\Generator\Platform\DefaultPlatform $platform */ $sql = $platform->getAddColumnDDL($column); - $stmt = $connection->prepare($sql); + + if ($stmt === false) { + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + } + $stmt->execute(); } @@ -611,6 +644,8 @@ public function isDatabaseVersionApplied(int $version): bool /** * @param string $connectionName * + * @throws \RuntimeException + * * @return array */ protected function getMigrationData(string $connectionName): array @@ -631,6 +666,11 @@ protected function getMigrationData(string $connectionName): array ); $stmt = $connection->prepare($sql); + + if ($stmt === false) { + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + } + $stmt->execute(); return $stmt->fetchAll(); @@ -667,18 +707,19 @@ protected function createExecutionDatetimeColumn(PlatformInterface $platform): C * @param \Propel\Runtime\Connection\ConnectionInterface $connection * @param string $columnName * + * @throws \RuntimeException + * * @return bool */ protected function columnExists(ConnectionInterface $connection, string $columnName): bool { - $sql = sprintf( - 'SELECT %s FROM %s', - $columnName, - $this->getMigrationTable(), - ); - try { - $stmt = $connection->prepare($sql); + $stmt = $connection->prepare(sprintf('SELECT %s FROM %s', $columnName, $this->getMigrationTable())); + + if ($stmt === false) { + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + } + $stmt->execute(); return true; diff --git a/src/Propel/Generator/Manager/ModelManager.php b/src/Propel/Generator/Manager/ModelManager.php index 1d087e97d3..d03bcbf632 100644 --- a/src/Propel/Generator/Manager/ModelManager.php +++ b/src/Propel/Generator/Manager/ModelManager.php @@ -130,6 +130,7 @@ public function build(): void // ---------------------------------- if ($table->hasAdditionalBuilders()) { foreach ($table->getAdditionalBuilders() as $builderClass) { + /** @var \Propel\Generator\Builder\Om\AbstractOMBuilder $builder */ $builder = new $builderClass($table); $builder->setGeneratorConfig($generatorConfig); $nbWrittenFiles += $this->doBuild($builder, $builder->overwrite ?? true); diff --git a/src/Propel/Generator/Manager/SqlManager.php b/src/Propel/Generator/Manager/SqlManager.php index a56b1836d2..26afbca8ee 100644 --- a/src/Propel/Generator/Manager/SqlManager.php +++ b/src/Propel/Generator/Manager/SqlManager.php @@ -14,6 +14,7 @@ use Propel\Runtime\Adapter\AdapterFactory; use Propel\Runtime\Connection\ConnectionFactory; use Propel\Runtime\Connection\ConnectionInterface; +use RuntimeException; /** * Service class for managing SQL. @@ -190,6 +191,11 @@ public function insertSql(?string $datasource = null): bool foreach ($sqls as $sql) { try { $stmt = $con->prepare($sql); + + if ($stmt === false) { + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + } + $stmt->execute(); } catch (Exception $e) { $message = sprintf('SQL insert failed: %s', $sql); diff --git a/src/Propel/Generator/Model/Behavior.php b/src/Propel/Generator/Model/Behavior.php index 0a13726803..b5f5c10482 100644 --- a/src/Propel/Generator/Model/Behavior.php +++ b/src/Propel/Generator/Model/Behavior.php @@ -226,7 +226,7 @@ public function getDatabase(): Database public function addParameter(array $parameter): void { $parameter = array_change_key_case($parameter, CASE_LOWER); - $this->parameters[$parameter['name']] = $parameter['value']; + $this->parameters[(string)$parameter['name']] = $parameter['value']; } /** @@ -419,8 +419,9 @@ public function renderTemplate(string $filename, array $vars = [], ?string $temp protected function getDirname(): string { if ($this->dirname === null) { - $r = new ReflectionObject($this); - $this->dirname = dirname($r->getFileName()); + $behaviorReflectionObject = new ReflectionObject($this); + $behaviorFileName = (string)$behaviorReflectionObject->getFileName(); + $this->dirname = dirname($behaviorFileName); } return $this->dirname; diff --git a/src/Propel/Generator/Model/Column.php b/src/Propel/Generator/Model/Column.php index aba5005ca2..5ca5b92265 100644 --- a/src/Propel/Generator/Model/Column.php +++ b/src/Propel/Generator/Model/Column.php @@ -1499,7 +1499,7 @@ public function getDefaultValueString(): string } if ($this->isTextType() || $this->getDefaultValue()->isExpression()) { - return sprintf("'%s'", str_replace("'", "\'", $defaultValue->getValue())); + return sprintf("'%s'", str_replace("'", "\'", (string)$defaultValue->getValue())); } if ($this->getType() === PropelTypes::BOOLEAN) { diff --git a/src/Propel/Generator/Model/ColumnDefaultValue.php b/src/Propel/Generator/Model/ColumnDefaultValue.php index b526ef172c..3edc755b2c 100644 --- a/src/Propel/Generator/Model/ColumnDefaultValue.php +++ b/src/Propel/Generator/Model/ColumnDefaultValue.php @@ -94,7 +94,7 @@ public function getValue() */ public function setValue($value): void { - $this->value = $value; + $this->value = (string)$value; } /** @@ -118,10 +118,9 @@ public function equals(ColumnDefaultValue $other): bool // special case for current timestamp $equivalents = ['CURRENT_TIMESTAMP', 'NOW()']; - if (in_array(strtoupper($this->getValue()), $equivalents) && in_array(strtoupper($other->getValue()), $equivalents)) { - return true; - } + $value = strtoupper((string)$this->getValue()); + $otherValue = strtoupper((string)$other->getValue()); - return false; // Can't help, they are different + return in_array($value, $equivalents) && in_array($otherValue, $equivalents); } } diff --git a/src/Propel/Generator/Model/Diff/ColumnComparator.php b/src/Propel/Generator/Model/Diff/ColumnComparator.php index bc80b561e1..d6310eba85 100644 --- a/src/Propel/Generator/Model/Diff/ColumnComparator.php +++ b/src/Propel/Generator/Model/Diff/ColumnComparator.php @@ -89,7 +89,7 @@ public static function compareColumns(Column $fromColumn, Column $toColumn): arr } elseif (!$fromDefaultValue && $toDefaultValue) { $changedProperties['defaultValueType'] = [null, $toDefaultValue->getType()]; $changedProperties['defaultValueValue'] = [null, $toDefaultValue->getValue()]; - } elseif ($fromDefaultValue && $toDefaultValue) { + } elseif ($fromDefaultValue) { if (!$fromDefaultValue->equals($toDefaultValue)) { if ($fromDefaultValue->getType() !== $toDefaultValue->getType()) { $changedProperties['defaultValueType'] = [$fromDefaultValue->getType(), $toDefaultValue->getType()]; diff --git a/src/Propel/Generator/Model/Domain.php b/src/Propel/Generator/Model/Domain.php index c8ec150cec..810e599743 100644 --- a/src/Propel/Generator/Model/Domain.php +++ b/src/Propel/Generator/Model/Domain.php @@ -341,10 +341,10 @@ public function getPhpDefaultValue() } if ($this->mappingType === PropelTypes::PHP_ARRAY) { - return $this->getDefaultValueForArray($this->defaultValue->getValue()); + return $this->getDefaultValueForArray((string)$this->defaultValue->getValue()); } if ($this->mappingType === PropelTypes::SET) { - return $this->getDefaultValueForSet($this->defaultValue->getValue()); + return $this->getDefaultValueForSet((string)$this->defaultValue->getValue()); } return $this->defaultValue->getValue(); @@ -462,11 +462,10 @@ public function appendXml(DOMNode $node): void $def = $this->getDefaultValue(); if ($def) { - if ($def->isExpression()) { - $domainNode->setAttribute('defaultExpr', $def->getValue()); - } else { - $domainNode->setAttribute('defaultValue', $def->getValue()); - } + $domainNode->setAttribute( + $def->isExpression() ? 'defaultExpr' : 'defaultValue', + (string)$def->getValue(), + ); } if ($this->size) { diff --git a/src/Propel/Generator/Model/NameFactory.php b/src/Propel/Generator/Model/NameFactory.php index 1661697e46..1c78426149 100644 --- a/src/Propel/Generator/Model/NameFactory.php +++ b/src/Propel/Generator/Model/NameFactory.php @@ -42,18 +42,19 @@ class NameFactory /** * Factory method which retrieves an instance of the named generator. * - * @param string $name The fully qualified class name of the name - * generation algorithm to retrieve. + * @param string $nameGeneratorClassName The fully qualified class name of the name generation algorithm to retrieve. * * @return \Propel\Generator\Model\NameGeneratorInterface */ - protected static function getAlgorithm(string $name): NameGeneratorInterface + protected static function getAlgorithm(string $nameGeneratorClassName): NameGeneratorInterface { - if (!isset(self::$algorithms[$name])) { - self::$algorithms[$name] = new $name(); + if (!isset(self::$algorithms[$nameGeneratorClassName])) { + /** @var \Propel\Generator\Model\NameGeneratorInterface $nameGenerator */ + $nameGenerator = new $nameGeneratorClassName(); + self::$algorithms[$nameGeneratorClassName] = $nameGenerator; } - return self::$algorithms[$name]; + return self::$algorithms[$nameGeneratorClassName]; } /** diff --git a/src/Propel/Generator/Platform/DefaultPlatform.php b/src/Propel/Generator/Platform/DefaultPlatform.php index 78ef3529d3..a6bd6a918f 100644 --- a/src/Propel/Generator/Platform/DefaultPlatform.php +++ b/src/Propel/Generator/Platform/DefaultPlatform.php @@ -175,11 +175,11 @@ protected function setSchemaDomainMapping(Domain $domain): void */ public function getDatabaseType(): string { - $reflClass = new ReflectionClass($this); - $clazz = $reflClass->getShortName(); - $pos = strpos($clazz, 'Platform'); + $platformReflectionClass = new ReflectionClass($this); + $platformShortName = $platformReflectionClass->getShortName(); + $length = strpos($platformShortName, 'Platform') ?: null; - return strtolower(substr($clazz, 0, $pos)); + return strtolower(substr($platformShortName, 0, $length)); } /** @@ -455,20 +455,20 @@ public function getColumnDefaultValueDDL(Column $col): string $default .= $defaultValue->getValue(); } else { if ($col->isTextType()) { - $default .= $this->quote($defaultValue->getValue()); + $default .= $this->quote((string)$defaultValue->getValue()); } elseif (in_array($col->getType(), [PropelTypes::BOOLEAN, PropelTypes::BOOLEAN_EMU])) { $default .= $this->getBooleanString($defaultValue->getValue()); } elseif ($col->getType() == PropelTypes::ENUM) { $default .= array_search($defaultValue->getValue(), $col->getValueSet()); } elseif ($col->isSetType()) { - $val = trim($defaultValue->getValue()); + $val = trim((string)$defaultValue->getValue()); $values = []; foreach (explode(',', $val) as $v) { $values[] = trim($v); } $default .= SetColumnConverter::convertToInt($values, $col->getValueSet()); } elseif ($col->isPhpArrayType()) { - $value = $this->getPhpArrayString($defaultValue->getValue()); + $value = $this->getPhpArrayString((string)$defaultValue->getValue()); if ($value === null) { $default = ''; } else { @@ -1512,7 +1512,7 @@ public function getColumnBindingPHP(Column $column, string $identifier, string $ * @param string $tab * @param string|null $phpType * - * @return array|string|null + * @return string */ public function getIdentifierPhp( string $columnValueMutator, @@ -1520,7 +1520,7 @@ public function getIdentifierPhp( string $sequenceName = '', string $tab = ' ', ?string $phpType = null - ) { + ): string { return sprintf( " %s%s = %s%s->lastInsertId(%s);", diff --git a/src/Propel/Generator/Platform/OraclePlatform.php b/src/Propel/Generator/Platform/OraclePlatform.php index 81f0af288a..eca2b41cad 100644 --- a/src/Propel/Generator/Platform/OraclePlatform.php +++ b/src/Propel/Generator/Platform/OraclePlatform.php @@ -476,7 +476,7 @@ public function getColumnBindingPHP(Column $column, string $identifier, string $ * * @throws \Propel\Generator\Exception\EngineException * - * @return array|string|null + * @return string */ public function getIdentifierPhp( string $columnValueMutator, @@ -484,7 +484,7 @@ public function getIdentifierPhp( string $sequenceName = '', string $tab = ' ', ?string $phpType = null - ) { + ): string { if (!$sequenceName) { throw new EngineException('Oracle needs a sequence name to fetch primary keys'); } diff --git a/src/Propel/Generator/Platform/PgsqlPlatform.php b/src/Propel/Generator/Platform/PgsqlPlatform.php index 486b7fcd1d..f7b6ab6fab 100755 --- a/src/Propel/Generator/Platform/PgsqlPlatform.php +++ b/src/Propel/Generator/Platform/PgsqlPlatform.php @@ -898,7 +898,7 @@ public function getDropIndexDDL(Index $index): string * * @throws \Propel\Generator\Exception\EngineException * - * @return array|string|null + * @return string */ public function getIdentifierPhp( string $columnValueMutator, @@ -906,7 +906,7 @@ public function getIdentifierPhp( string $sequenceName = '', string $tab = ' ', ?string $phpType = null - ) { + ): string { if (!$sequenceName) { throw new EngineException('PostgreSQL needs a sequence name to fetch primary keys'); } diff --git a/src/Propel/Generator/Platform/SqlitePlatform.php b/src/Propel/Generator/Platform/SqlitePlatform.php index 2d17cd5955..ca6280c2d0 100644 --- a/src/Propel/Generator/Platform/SqlitePlatform.php +++ b/src/Propel/Generator/Platform/SqlitePlatform.php @@ -21,6 +21,7 @@ use Propel\Generator\Model\Table; use Propel\Generator\Model\Unique; use Propel\Runtime\Connection\PdoConnection; +use RuntimeException; use SQLite3; /** @@ -188,7 +189,7 @@ public function getModifyTableDDL(TableDiff $tableDiff): string ['CURRENT_TIME', 'CURRENT_DATE', 'CURRENT_TIMESTAMP'], true, )) - || substr(trim($column->getDefaultValue() ? $column->getDefaultValue()->getValue() : ''), 0, 1) === '(' + || substr(trim($column->getDefaultValue() ? (string)$column->getDefaultValue()->getValue() : ''), 0, 1) === '(' //If a NOT NULL constraint is specified, then the column must have a default value other than NULL. || ($column->isNotNull() && $column->getDefaultValue()->getValue() === 'NULL'); @@ -630,6 +631,8 @@ public function supportsNativeDeleteTrigger(): bool } /** + * @throws \RuntimeException + * * @return string */ protected function getVersion(): string @@ -640,7 +643,12 @@ protected function getVersion(): string //if php_sqlite3 extension is not installed, we need to query the database $connection = new PdoConnection('sqlite::memory:'); + $pdoStatement = $connection->query('SELECT sqlite_version()'); + + if ($pdoStatement === false) { + throw new RuntimeException('query() did not return a result set as a statement object.'); + } - return (string)$connection->query('SELECT sqlite_version()')->fetch(PDO::FETCH_NUM)[0]; + return (string)$pdoStatement->fetch(PDO::FETCH_NUM)[0]; } } diff --git a/src/Propel/Generator/Reverse/MssqlSchemaParser.php b/src/Propel/Generator/Reverse/MssqlSchemaParser.php index 772c772d35..6bd84bbc33 100644 --- a/src/Propel/Generator/Reverse/MssqlSchemaParser.php +++ b/src/Propel/Generator/Reverse/MssqlSchemaParser.php @@ -18,6 +18,7 @@ use Propel\Generator\Model\PropelTypes; use Propel\Generator\Model\Table; use Propel\Generator\Model\Unique; +use RuntimeException; /** * Microsoft SQL Server database schema parser. @@ -86,12 +87,18 @@ protected function getTypeMapping(): array * @param \Propel\Generator\Model\Database $database * @param array $additionalTables * + * @throws \RuntimeException + * * @return int */ public function parse(Database $database, array $additionalTables = []): int { $dataFetcher = $this->dbh->query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME <> 'dtproperties'"); + if ($dataFetcher === false) { + throw new RuntimeException('query() did not return a result set as a statement object.'); + } + // First load the tables (important that this happens before filling out details of tables) $tables = []; foreach ($dataFetcher as $row) { @@ -267,6 +274,8 @@ protected function addIndexes(Table $table): void * * @param \Propel\Generator\Model\Table $table * + * @throws \RuntimeException + * * @return void */ protected function addPrimaryKey(Table $table): void @@ -278,6 +287,10 @@ protected function addPrimaryKey(Table $table): void WHERE (INFORMATION_SCHEMA.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'PRIMARY KEY') AND (INFORMATION_SCHEMA.TABLE_CONSTRAINTS.TABLE_NAME = '" . $table->getName() . "')"); + if ($dataFetcher === false) { + throw new RuntimeException('query() did not return a result set as a statement object.'); + } + // Loop through the returned results, grouping the same key_name together // adding each column for that key. foreach ($dataFetcher as $row) { diff --git a/src/Propel/Generator/Reverse/MysqlSchemaParser.php b/src/Propel/Generator/Reverse/MysqlSchemaParser.php index 3a306b215c..8c4f1cd6b7 100644 --- a/src/Propel/Generator/Reverse/MysqlSchemaParser.php +++ b/src/Propel/Generator/Reverse/MysqlSchemaParser.php @@ -19,6 +19,7 @@ use Propel\Generator\Model\Unique; use Propel\Generator\Platform\MysqlPlatform; use Propel\Runtime\Connection\ConnectionInterface; +use RuntimeException; /** * Mysql database schema parser. @@ -143,6 +144,8 @@ public function parse(Database $database, array $additionalTables = []): int * @param \Propel\Generator\Model\Database $database * @param \Propel\Generator\Model\Table|null $filterTable * + * @throws \RuntimeException + * * @return void */ protected function parseTables(Database $database, ?Table $filterTable = null): void @@ -165,6 +168,10 @@ protected function parseTables(Database $database, ?Table $filterTable = null): $dataFetcher = $this->dbh->query($sql); + if ($dataFetcher === false) { + throw new RuntimeException('query() did not return a result set as a statement object.'); + } + // First load the tables (important that this happens before filling out details of tables) foreach ($dataFetcher as $row) { $name = $row[0]; @@ -342,6 +349,8 @@ protected function addColumnDescriptionsToTable(Table $table): void * * @param \Propel\Generator\Model\Table $table * + * @throws \RuntimeException + * * @return string|null */ protected function loadTableDescription(Table $table): ?string @@ -354,8 +363,13 @@ protected function loadTableDescription(Table $table): ?string AND table_name=($tableName) EOT; + $dataFetcher = $this->dbh->query($query); + if ($dataFetcher === false) { + throw new RuntimeException('query() did not return a result set as a statement object.'); + } + /** @phpstan-var string|null */ - return $this->dbh->query($query)->fetchColumn(); + return $dataFetcher->fetchColumn(); } /** @@ -363,6 +377,8 @@ protected function loadTableDescription(Table $table): ?string * * @param \Propel\Generator\Model\Column $column * + * @throws \RuntimeException + * * @return string|null */ protected function loadColumnDescription(Column $column): ?string @@ -377,8 +393,13 @@ protected function loadColumnDescription(Column $column): ?string AND column_name=($columnName) EOT; + $dataFetcher = $this->dbh->query($query); + if ($dataFetcher === false) { + throw new RuntimeException('query() did not return a result set as a statement object.'); + } + /** @phpstan-var string|null */ - return $this->dbh->query($query)->fetchColumn(); + return $dataFetcher->fetchColumn(); } /** @@ -386,6 +407,8 @@ protected function loadColumnDescription(Column $column): ?string * * @param \Propel\Generator\Model\Table $table * + * @throws \RuntimeException + * * @return void */ protected function addForeignKeys(Table $table): void @@ -393,8 +416,12 @@ protected function addForeignKeys(Table $table): void $database = $table->getDatabase(); $dataFetcher = $this->dbh->query(sprintf('SHOW CREATE TABLE %s', $this->getPlatform()->doQuoting($table->getName()))); - $row = $dataFetcher->fetch(); + if ($dataFetcher === false) { + throw new RuntimeException('query() did not return a result set as a statement object.'); + } + + $row = $dataFetcher->fetch(); $foreignKeys = []; // local store to avoid duplicates // Get the information on all the foreign keys diff --git a/src/Propel/Generator/Reverse/OracleSchemaParser.php b/src/Propel/Generator/Reverse/OracleSchemaParser.php index 0800ccf02c..1dd531faab 100644 --- a/src/Propel/Generator/Reverse/OracleSchemaParser.php +++ b/src/Propel/Generator/Reverse/OracleSchemaParser.php @@ -163,7 +163,8 @@ protected function addColumns(Table $table): void $type = 'DOUBLE'; } if (strpos($type, 'TIMESTAMP(') !== false) { - $type = substr($type, 0, strpos($type, '(')); + $length = strpos($type, '(') ?: null; + $type = substr($type, 0, $length); $default = '0000-00-00 00:00:00'; $size = null; $scale = null; @@ -204,16 +205,10 @@ protected function addColumns(Table $table): void */ protected function addIndexes(Table $table): void { - /** @var \PDOStatement $stmt */ - $stmt = $this->dbh->query("SELECT INDEX_NAME, COLUMN_NAME FROM USER_IND_COLUMNS WHERE TABLE_NAME = '" . $table->getName() . "' ORDER BY COLUMN_NAME"); - - $indices = []; - while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { - $indices[$row['INDEX_NAME']][] = $row['COLUMN_NAME']; - } + $indicesIndexedByIndexName = $this->getIndiciesIndexedByIndexName($table); - foreach ($indices as $indexName => $columnNames) { - $index = new Index($indexName); + foreach ($indicesIndexedByIndexName as $indexName => $columnNames) { + $index = new Index((string)$indexName); foreach ($columnNames as $columnName) { // Oracle deals with complex indices using an internal reference, so... // let's ignore this kind of index @@ -228,6 +223,24 @@ protected function addIndexes(Table $table): void } } + /** + * @param \Propel\Generator\Model\Table $table + * + * @return array + */ + protected function getIndiciesIndexedByIndexName(Table $table): array + { + /** @var \PDOStatement $stmt */ + $stmt = $this->dbh->query("SELECT INDEX_NAME, COLUMN_NAME FROM USER_IND_COLUMNS WHERE TABLE_NAME = '" . $table->getName() . "' ORDER BY COLUMN_NAME"); + + $indicesIndexedByIndexName = []; + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + $indicesIndexedByIndexName[$row['INDEX_NAME']][] = $row['COLUMN_NAME']; + } + + return $indicesIndexedByIndexName; + } + /** * Load foreign keys for this table. * diff --git a/src/Propel/Generator/Reverse/PgsqlSchemaParser.php b/src/Propel/Generator/Reverse/PgsqlSchemaParser.php index 6edcba663d..d37116a7c4 100755 --- a/src/Propel/Generator/Reverse/PgsqlSchemaParser.php +++ b/src/Propel/Generator/Reverse/PgsqlSchemaParser.php @@ -271,7 +271,7 @@ protected function addColumns(Table $table, int $oid): void table_schema IN ($searchPath) AND table_name = ? "); if ($stmt === false) { - throw new RuntimeException('prepare() returned no statement.'); + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); } $params[] = $table->getCommonName(); @@ -411,7 +411,7 @@ protected function addForeignKeys(Table $table, int $oid): void GROUP BY conname, confupdtype, confdeltype, fktab, reftab ORDER BY conname"); if ($stmt === false) { - throw new RuntimeException('prepare() returned no statement.'); + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); } $stmt->bindValue(1, $oid); $stmt->execute(); @@ -526,7 +526,7 @@ protected function addIndexes(Table $table, int $oid): void WHERE indrelid = ? AND NOT indisprimary ORDER BY cls.relname"); if ($stmt === false) { - throw new RuntimeException('prepare() returned no statement.'); + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); } $stmt->bindValue(1, $oid); @@ -537,7 +537,7 @@ protected function addIndexes(Table $table, int $oid): void WHERE c.oid = ? AND a.attnum = ? AND NOT a.attisdropped ORDER BY a.attnum"); if ($stmt2 === false) { - throw new RuntimeException('prepare() returned no statement.'); + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); } $indexes = []; @@ -600,7 +600,7 @@ protected function addPrimaryKey(Table $table, int $oid): void WHERE indrelid = ? AND indisprimary ORDER BY cls.relname"); if ($stmt === false) { - throw new RuntimeException('prepare() returned no statement.'); + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); } $stmt->bindValue(1, $oid); $stmt->execute(); @@ -615,7 +615,7 @@ protected function addPrimaryKey(Table $table, int $oid): void WHERE c.oid = ? AND a.attnum = ? AND NOT a.attisdropped ORDER BY a.attnum"); if ($stmt2 === false) { - throw new RuntimeException('prepare() returned no statement.'); + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); } $stmt2->bindValue(1, $oid); $stmt2->bindValue(2, $intColNum); @@ -669,7 +669,7 @@ protected function addSequences(Database $database): void AND n.nspname IN ($searchPath); "); if ($stmt === false) { - throw new RuntimeException('prepare() returned no statement.'); + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); } $stmt->execute($params); diff --git a/src/Propel/Generator/Schema/Dumper/XmlDumper.php b/src/Propel/Generator/Schema/Dumper/XmlDumper.php index e14e2bac38..a8209575cf 100644 --- a/src/Propel/Generator/Schema/Dumper/XmlDumper.php +++ b/src/Propel/Generator/Schema/Dumper/XmlDumper.php @@ -424,7 +424,7 @@ private function appendColumnNode(Column $column, DOMNode $parentNode): void $defaultValue = $domain->getDefaultValue(); if ($defaultValue) { $type = $defaultValue->isExpression() ? 'defaultExpr' : 'defaultValue'; - $columnNode->setAttribute($type, $defaultValue->getValue()); + $columnNode->setAttribute($type, (string)$defaultValue->getValue()); } if ($column->isInheritance()) { diff --git a/src/Propel/Generator/Util/BehaviorLocator.php b/src/Propel/Generator/Util/BehaviorLocator.php index e64a4e8046..1418289a56 100644 --- a/src/Propel/Generator/Util/BehaviorLocator.php +++ b/src/Propel/Generator/Util/BehaviorLocator.php @@ -101,13 +101,15 @@ private function findComposerJson(): ?SplFileInfo /** * Returns the directories to search the composer lock file in * - * @return array + * @return list */ private function getSearchDirs(): array { + $workingDirectory = (string)getcwd(); + return [ - getcwd(), - getcwd() . '/../', // cwd is a subfolder + $workingDirectory, + $workingDirectory . '/../', // cwd is a subfolder __DIR__ . '/../../../../../../../', // vendor/propel/propel __DIR__ . '/../../../../', // propel development environment ]; diff --git a/src/Propel/Generator/Util/QuickBuilder.php b/src/Propel/Generator/Util/QuickBuilder.php index 6f5f181357..fd917fe34f 100644 --- a/src/Propel/Generator/Util/QuickBuilder.php +++ b/src/Propel/Generator/Util/QuickBuilder.php @@ -30,6 +30,7 @@ use Propel\Runtime\Connection\PdoConnection; use Propel\Runtime\Connection\StatementInterface; use Propel\Runtime\Propel; +use RuntimeException; class QuickBuilder { @@ -323,6 +324,7 @@ public function buildSQL(ConnectionInterface $con): int * @param \Propel\Runtime\Connection\ConnectionInterface $con * * @throws \Propel\Generator\Exception\BuildException + * @throws \RuntimeException * * @return \Propel\Generator\Model\Database|null */ @@ -342,6 +344,11 @@ public function updateDB(ConnectionInterface $con): ?Database foreach ($statements as $statement) { try { $stmt = $con->prepare($statement); + + if ($stmt === false) { + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + } + $stmt->execute(); } catch (Exception $e) { //echo $sql; //uncomment for better debugging @@ -622,7 +629,7 @@ private function buildClassesToPhysical(array $classes, array $tables): array { $includes = []; $dirName = sys_get_temp_dir() - . '/propelQuickBuild-' . Propel::VERSION . '-' . substr(sha1(getcwd()), 0, 10) . '/'; + . '/propelQuickBuild-' . Propel::VERSION . '-' . substr(sha1((string)getcwd()), 0, 10) . '/'; if (!is_dir($dirName)) { mkdir($dirName); } @@ -680,6 +687,7 @@ protected function registerTableMaps(): void $builder->setGeneratorConfig($this->config); foreach ($db->getTables() as $table) { $builder->setTable($table); + /** @phpstan-var class-string<\Propel\Runtime\Map\TableMap> $mapClass */ $mapClass = $builder->getFullyQualifiedClassName(); $dbMap->addTableFromMapClass($mapClass); } diff --git a/src/Propel/Generator/Util/VfsTrait.php b/src/Propel/Generator/Util/VfsTrait.php index 44657cf792..03cc344796 100644 --- a/src/Propel/Generator/Util/VfsTrait.php +++ b/src/Propel/Generator/Util/VfsTrait.php @@ -50,10 +50,13 @@ public function getRoot(): vfsStreamDirectory */ public function newFile(string $filename, string $content = ''): vfsStreamFile { - $path = pathinfo($filename); - $dir = $this->getDir($path['dirname']); + $pathinfo = pathinfo($filename); + $dirname = $pathinfo['dirname'] ?? ''; + $vfsStreamDirectory = $this->getDir($dirname); - return vfsStream::newFile($path['basename'])->at($dir)->setContent($content); + return vfsStream::newFile($pathinfo['basename']) + ->at($vfsStreamDirectory) + ->setContent($content); } /** diff --git a/src/Propel/Runtime/ActiveQuery/Criteria.php b/src/Propel/Runtime/ActiveQuery/Criteria.php index 26c0503f7f..42aad64005 100644 --- a/src/Propel/Runtime/ActiveQuery/Criteria.php +++ b/src/Propel/Runtime/ActiveQuery/Criteria.php @@ -748,7 +748,7 @@ public function getTablesColumns(): array { $tables = []; foreach ($this->keys() as $key) { - $tableName = substr($key, 0, strrpos($key, '.')); + $tableName = substr($key, 0, strrpos($key, '.') ?: null); $tables[$tableName][] = $key; } @@ -1047,7 +1047,7 @@ public function combine(array $criterions = [], string $operator = self::LOGICAL */ public function addJoin($left, $right, ?string $joinType = null) { - if (is_array($left)) { + if (is_array($left) && is_array($right)) { $conditions = []; foreach ($left as $key => $value) { $condition = [$value, $right[$key]]; @@ -1063,15 +1063,17 @@ public function addJoin($left, $right, ?string $joinType = null) $join->setIdentifierQuoting($this->isIdentifierQuotingEnabled()); // is the left table an alias ? - $dotpos = strrpos($left, '.'); - $leftTableAlias = substr($left, 0, $dotpos); - $leftColumnName = substr($left, $dotpos + 1); + /** @phpstan-var string $left */ + $length = strrpos($left, '.') ?: null; + $leftTableAlias = substr($left, 0, $length); + $leftColumnName = substr($left, $length + 1); [$leftTableName, $leftTableAlias] = $this->getTableNameAndAlias($leftTableAlias); // is the right table an alias ? - $dotpos = strrpos($right, '.'); - $rightTableAlias = substr($right, 0, $dotpos); - $rightColumnName = substr($right, $dotpos + 1); + /** @phpstan-var string $right */ + $length = strrpos($right, '.') ?: null; + $rightTableAlias = substr($right, 0, $length); + $rightColumnName = substr($right, $length + 1); [$rightTableName, $rightTableAlias] = $this->getTableNameAndAlias($rightTableAlias); $join->addExplicitCondition( @@ -2441,7 +2443,7 @@ public function _and() * * @param mixed $cond Casts to bool for variable evaluation * - * @return \Propel\Runtime\Util\PropelConditionalProxy|$this + * @return \Propel\Runtime\ActiveQuery\Criteria|\Propel\Runtime\Util\PropelConditionalProxy */ public function _if($cond) { @@ -2460,7 +2462,7 @@ public function _if($cond) * * @throws \Propel\Runtime\Exception\LogicException * - * @return \Propel\Runtime\Util\PropelConditionalProxy|$this + * @return \Propel\Runtime\ActiveQuery\Criteria|\Propel\Runtime\Util\PropelConditionalProxy */ public function _elseif($cond) { @@ -2479,7 +2481,7 @@ public function _elseif($cond) * * @throws \Propel\Runtime\Exception\LogicException * - * @return \Propel\Runtime\Util\PropelConditionalProxy|static + * @return \Propel\Runtime\ActiveQuery\Criteria|\Propel\Runtime\Util\PropelConditionalProxy */ public function _else() { @@ -2496,7 +2498,7 @@ public function _else() * * @throws \Propel\Runtime\Exception\LogicException * - * @return $this|\Propel\Runtime\ActiveQuery\Criteria + * @return \Propel\Runtime\ActiveQuery\Criteria|\Propel\Runtime\Util\PropelConditionalProxy */ public function _endif() { diff --git a/src/Propel/Runtime/ActiveQuery/Join.php b/src/Propel/Runtime/ActiveQuery/Join.php index 31ae0b8090..e0ff6d1e4d 100644 --- a/src/Propel/Runtime/ActiveQuery/Join.php +++ b/src/Propel/Runtime/ActiveQuery/Join.php @@ -137,14 +137,12 @@ class Join */ public function __construct($leftColumn = null, $rightColumn = null, ?string $joinType = null) { - if ($leftColumn !== null) { - if (is_array($leftColumn)) { - // join with multiple conditions - $this->addConditions($leftColumn, $rightColumn); - } else { - // simple join - $this->addCondition($leftColumn, $rightColumn); - } + if (is_array($leftColumn) && is_array($rightColumn)) { + $this->addConditions($leftColumn, $rightColumn); + } + + if (!is_array($leftColumn) && !is_array($rightColumn)) { + $this->addCondition((string)$leftColumn, (string)$rightColumn); } if ($joinType !== null) { diff --git a/src/Propel/Runtime/ActiveQuery/QueryExecutor/AbstractQueryExecutor.php b/src/Propel/Runtime/ActiveQuery/QueryExecutor/AbstractQueryExecutor.php index a0e69962f3..678cae964c 100644 --- a/src/Propel/Runtime/ActiveQuery/QueryExecutor/AbstractQueryExecutor.php +++ b/src/Propel/Runtime/ActiveQuery/QueryExecutor/AbstractQueryExecutor.php @@ -15,6 +15,7 @@ use Propel\Runtime\Connection\StatementWrapper; use Propel\Runtime\Propel; use Propel\Runtime\ServiceContainer\ServiceContainerInterface; +use RuntimeException; use Throwable; abstract class AbstractQueryExecutor @@ -86,6 +87,8 @@ protected function retrieveConnection(ServiceContainerInterface $sc, string $dbN /** * @param \Propel\Runtime\ActiveQuery\SqlBuilder\PreparedStatementDto $preparedStatementDto * + * @throws \RuntimeException + * * @return \PDOStatement|\Propel\Runtime\Connection\StatementInterface|bool|null */ protected function executeStatement(PreparedStatementDto $preparedStatementDto) @@ -96,13 +99,19 @@ protected function executeStatement(PreparedStatementDto $preparedStatementDto) $stmt = null; try { + /** @var \Propel\Runtime\Connection\StatementInterface|false $stmt */ $stmt = $this->con->prepare($sql); + + if ($stmt === false) { + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + } + if ($params) { $this->adapter->bindValues($stmt, $params, $this->dbMap); } $stmt->execute(); } catch (Throwable $e) { - $this->handleStatementException($e, $sql, $stmt); + $this->handleStatementException($e, $sql, $stmt ?: null); } return $stmt; diff --git a/src/Propel/Runtime/Adapter/Pdo/PgsqlAdapter.php b/src/Propel/Runtime/Adapter/Pdo/PgsqlAdapter.php index 1f94f7d5ed..3a1d48919d 100644 --- a/src/Propel/Runtime/Adapter/Pdo/PgsqlAdapter.php +++ b/src/Propel/Runtime/Adapter/Pdo/PgsqlAdapter.php @@ -15,6 +15,7 @@ use Propel\Runtime\Connection\ConnectionInterface; use Propel\Runtime\Exception\InvalidArgumentException; use Propel\Runtime\Propel; +use RuntimeException; /** * This is used to connect to PostgreSQL databases. @@ -95,6 +96,7 @@ protected function getIdMethod(): int * @param string|null $name * * @throws \Propel\Runtime\Exception\InvalidArgumentException + * @throws \RuntimeException * * @return int */ @@ -103,8 +105,13 @@ public function getId(ConnectionInterface $con, ?string $name = null): int if ($name === null) { throw new InvalidArgumentException('Unable to fetch next sequence ID without sequence name.'); } + $dataFetcher = $con->query(sprintf('SELECT nextval(%s)', $con->quote($name))); + if ($dataFetcher === false) { + throw new RuntimeException('query() did not return a result set as a statement object.'); + } + return $dataFetcher->fetchColumn(); } @@ -214,6 +221,8 @@ public function quoteIdentifierTable(string $table): string * @param \Propel\Runtime\Connection\ConnectionInterface $con propel connection * @param \Propel\Runtime\ActiveQuery\Criteria|string $query query the criteria or the query string * + * @throws \RuntimeException + * * @return \Propel\Runtime\Connection\StatementInterface|\PDOStatement|false A PDO statement executed using the connection, ready to be fetched */ public function doExplainPlan(ConnectionInterface $con, $query) @@ -226,8 +235,13 @@ public function doExplainPlan(ConnectionInterface $con, $query) $sql = $query; } + /** @var \Propel\Runtime\Connection\StatementInterface|false $stmt */ $stmt = $con->prepare($this->getExplainPlanQuery($sql)); + if ($stmt === false) { + throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + } + if ($query instanceof Criteria) { $this->bindValues($stmt, $params, $dbMap); } diff --git a/src/Propel/Runtime/Collection/CollectionIterator.php b/src/Propel/Runtime/Collection/CollectionIterator.php index bacf778d6f..8be141c7c1 100644 --- a/src/Propel/Runtime/Collection/CollectionIterator.php +++ b/src/Propel/Runtime/Collection/CollectionIterator.php @@ -272,7 +272,7 @@ public function ksort($flags = SORT_REGULAR): bool } /** - * @param string $callback + * @param callable $callback * * @return bool */ @@ -285,7 +285,7 @@ public function uasort($callback): bool } /** - * @param string $callback + * @param callable $callback * * @return bool */ diff --git a/src/Propel/Runtime/Collection/ObjectCollection.php b/src/Propel/Runtime/Collection/ObjectCollection.php index ad2567d8a1..6199e119c8 100644 --- a/src/Propel/Runtime/Collection/ObjectCollection.php +++ b/src/Propel/Runtime/Collection/ObjectCollection.php @@ -188,7 +188,7 @@ public function fromArray(array $arr): void * ) * * - * @return array + * @return array */ public function toArray( ?string $keyColumn = null, @@ -235,7 +235,7 @@ public function toArray( * ) * * - * @return array + * @return array */ public function getArrayCopy(?string $keyColumn = null, bool $usePrefix = false): array { @@ -265,7 +265,7 @@ public function getArrayCopy(?string $keyColumn = null, bool $usePrefix = false) * @param string $keyColumn * @param string|null $valueColumn * - * @return array + * @return array */ public function toKeyValue(string $keyColumn = 'PrimaryKey', ?string $valueColumn = null): array { @@ -295,7 +295,7 @@ public function toKeyValue(string $keyColumn = 'PrimaryKey', ?string $valueColum * * @param string $keyColumn * - * @return array + * @return array */ public function toKeyIndex(string $keyColumn = 'PrimaryKey'): array { diff --git a/src/Propel/Runtime/Collection/OnDemandIterator.php b/src/Propel/Runtime/Collection/OnDemandIterator.php index acd3da4055..83bb54632d 100644 --- a/src/Propel/Runtime/Collection/OnDemandIterator.php +++ b/src/Propel/Runtime/Collection/OnDemandIterator.php @@ -32,7 +32,7 @@ class OnDemandIterator implements IteratorInterface protected $dataFetcher; /** - * @var array|null + * @var array|bool|null */ protected $currentRow; @@ -100,6 +100,10 @@ public function count(): int #[\ReturnTypeWillChange] public function current(): ActiveRecordInterface { + if (!is_array($this->currentRow)) { + $this->currentRow = []; + } + return $this->formatter->getAllObjectsFromRow($this->currentRow); } diff --git a/src/Propel/Runtime/Connection/PdoConnection.php b/src/Propel/Runtime/Connection/PdoConnection.php index 5bf5975ede..1906795039 100644 --- a/src/Propel/Runtime/Connection/PdoConnection.php +++ b/src/Propel/Runtime/Connection/PdoConnection.php @@ -142,7 +142,7 @@ public function query(string $statement) */ public function exec($statement): int { - return $this->pdo->exec($statement); + return (int)$this->pdo->exec($statement); } /** @@ -164,7 +164,7 @@ public function getAttribute(int $attribute) /** * @param string|null $name * - * @return string|int + * @return string|false */ public function lastInsertId(?string $name = null) { diff --git a/src/Propel/Runtime/Connection/StatementInterface.php b/src/Propel/Runtime/Connection/StatementInterface.php index ded4967066..18dea50b10 100644 --- a/src/Propel/Runtime/Connection/StatementInterface.php +++ b/src/Propel/Runtime/Connection/StatementInterface.php @@ -107,7 +107,7 @@ public function fetchAll(?int $fetchStyle = PDO::FETCH_BOTH, $fetchArgument = nu /** * Fetches the next row and returns it as an object. * - * @param string $className Name of the created class. + * @param class-string $className Name of the created class. * @param array $ctorArgs Elements of this array are passed to the constructor. * * @return mixed diff --git a/src/Propel/Runtime/Connection/StatementWrapper.php b/src/Propel/Runtime/Connection/StatementWrapper.php index 1f3a2c67ea..472a98da74 100644 --- a/src/Propel/Runtime/Connection/StatementWrapper.php +++ b/src/Propel/Runtime/Connection/StatementWrapper.php @@ -93,6 +93,7 @@ public function prepare(array $options) public function query(): DataFetcherInterface { if ($this->connection->isInDebugMode()) { + /** @var callable $callback */ $callback = [$this->connection->getWrappedConnection(), 'query']; $statement = $this->connection->callUserFunctionWithLogging($callback, [$this->sql], $this->sql); } else { @@ -123,7 +124,7 @@ public function bindParam($parameter, &$variable, int $dataType = PDO::PARAM_STR if ($this->connection->isInDebugMode()) { $typestr = self::$typeMap[$dataType] ?? '(default)'; $valuestr = (int)$length > 100 ? '[Large value]' : var_export($variable, true); - $this->boundValues[$parameter] = $valuestr; + $this->boundValues[(string)$parameter] = $valuestr; $msg = sprintf('Binding %s at position %s w/ PDO type %s', $valuestr, $parameter, $typestr); $this->connection->log($msg); } @@ -147,7 +148,7 @@ public function bindValue($parameter, $value, int $dataType = PDO::PARAM_STR): b if ($this->connection->isInDebugMode()) { $typestr = self::$typeMap[$dataType] ?? '(default)'; $valuestr = $dataType == PDO::PARAM_LOB ? '[LOB value]' : var_export($value, true); - $this->boundValues[$parameter] = $valuestr; + $this->boundValues[(string)$parameter] = $valuestr; $msg = sprintf('Binding %s at position %s w/ PDO type %s', $valuestr, $parameter, $typestr); $this->connection->log($msg); } @@ -410,6 +411,7 @@ public function setFetchMode($mode, $classNameObject = null, array $ctorarfg = [ case 2: return $this->statement->setFetchMode($mode, $classNameObject); case 3: + /** @phpstan-var string $classNameObject */ return $this->statement->setFetchMode($mode, $classNameObject, $ctorarfg); default: return $this->statement->setFetchMode(...func_get_args()); diff --git a/src/Propel/Runtime/Formatter/AbstractFormatterWithHydration.php b/src/Propel/Runtime/Formatter/AbstractFormatterWithHydration.php index a8a872e1fe..436148ff47 100644 --- a/src/Propel/Runtime/Formatter/AbstractFormatterWithHydration.php +++ b/src/Propel/Runtime/Formatter/AbstractFormatterWithHydration.php @@ -78,8 +78,10 @@ protected function &hydratePropelObjectCollection(array $row): array foreach ($this->getWith() as $relAlias => $modelWith) { // determine class to use if ($modelWith->isSingleTableInheritance()) { + /** @var class-string|object $class */ $class = $modelWith->getTableMap()::getOMClass($row, $col, false); $refl = new ReflectionClass($class); + $class = $refl->getName(); if ($refl->isAbstract()) { $tableMapClass = "Map\\{$class}TableMap"; $col += $tableMapClass::NUM_COLUMNS; diff --git a/src/Propel/Runtime/Formatter/OnDemandFormatter.php b/src/Propel/Runtime/Formatter/OnDemandFormatter.php index 62fbf40397..21f3b82d70 100644 --- a/src/Propel/Runtime/Formatter/OnDemandFormatter.php +++ b/src/Propel/Runtime/Formatter/OnDemandFormatter.php @@ -121,8 +121,10 @@ public function getAllObjectsFromRow(array $row): ActiveRecordInterface // related objects using 'with' foreach ($this->getWith() as $modelWith) { if ($modelWith->isSingleTableInheritance()) { + /** @var class-string|object $class */ $class = $modelWith->getTableMap()::getOMClass($row, $col, false); $refl = new ReflectionClass($class); + $class = $refl->getName(); if ($refl->isAbstract()) { $tableMapClass = "Map\\{$class}TableMap"; $col += $tableMapClass::NUM_COLUMNS; diff --git a/src/Propel/Runtime/Map/DatabaseMap.php b/src/Propel/Runtime/Map/DatabaseMap.php index 8f5adb4206..9ab60c508a 100644 --- a/src/Propel/Runtime/Map/DatabaseMap.php +++ b/src/Propel/Runtime/Map/DatabaseMap.php @@ -310,6 +310,7 @@ public function getTableByPhpName(string $phpName): TableMap $phpName = '\\' . $phpName; } + /** @var \Propel\Runtime\Map\TableMap|class-string<\Propel\Runtime\Map\TableMap> $tableMapOrTableMapClassName */ $tableMapOrTableMapClassName = (isset($this->tablesByPhpName[$phpName])) ? $this->tablesByPhpName[$phpName] : $this->determineTableMapClassNameByPhpName($phpName); diff --git a/src/Propel/Runtime/Util/PropelConditionalProxy.php b/src/Propel/Runtime/Util/PropelConditionalProxy.php index b892816f94..519999383a 100644 --- a/src/Propel/Runtime/Util/PropelConditionalProxy.php +++ b/src/Propel/Runtime/Util/PropelConditionalProxy.php @@ -83,7 +83,7 @@ public function __construct(Criteria $criteria, $cond, ?self $proxy = null) * * @param mixed $cond Casts to bool for variable evaluation * - * @return $this|\Propel\Runtime\ActiveQuery\Criteria + * @return \Propel\Runtime\ActiveQuery\Criteria|\Propel\Runtime\Util\PropelConditionalProxy */ public function _if($cond) { @@ -120,7 +120,7 @@ public function _else() * Returns the parent object * Allows for conditional statements in a fluid interface. * - * @return $this|\Propel\Runtime\ActiveQuery\Criteria + * @return \Propel\Runtime\ActiveQuery\Criteria|\Propel\Runtime\Util\PropelConditionalProxy */ public function _endif() { From 08bc2972166a23d6b7df8ba674dec1de5fcf4778 Mon Sep 17 00:00:00 2001 From: Michael Knappe Date: Tue, 24 Jan 2023 16:53:00 +0100 Subject: [PATCH 2/9] Fixes phpstan errors --- composer.json | 4 ++-- src/Propel/Generator/Builder/Om/AbstractOMBuilder.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 87573f13a7..04ce929d84 100644 --- a/composer.json +++ b/composer.json @@ -24,12 +24,12 @@ "symfony/filesystem": "^4.4.0 || ^5.0.0 || ^6.0.0", "symfony/finder": "^4.4.0 || ^5.0.0 || ^6.0.0", "symfony/translation": "^4.4.0 || ^5.0.0 || ^6.0.0", - "symfony/validator": "^4.4.0 || ^5.0.0 || ^6.0.0", - "ext-xml": "*" + "symfony/validator": "^4.4.0 || ^5.0.0 || ^6.0.0" }, "require-dev": { "ext-pdo": "*", "ext-json": "*", + "ext-xml": "*", "monolog/monolog": "^1.3 || ^2.3 || ^3.0", "phpstan/phpstan": "^1.2", "phpunit/phpunit": "^9.5.0", diff --git a/src/Propel/Generator/Builder/Om/AbstractOMBuilder.php b/src/Propel/Generator/Builder/Om/AbstractOMBuilder.php index 841ed1a29c..e116f1a54b 100644 --- a/src/Propel/Generator/Builder/Om/AbstractOMBuilder.php +++ b/src/Propel/Generator/Builder/Om/AbstractOMBuilder.php @@ -913,7 +913,7 @@ protected static function getRelatedBySuffix(ForeignKey $fk): string $localColumnName = $localColumn->getPhpName(); $localTable = $fk->getTable(); if (!$localColumnName) { - throw new RuntimeException(sprintf('Could not fetch column: %s in table %s.', $localColumnName, $localTable->getName())); + throw new RuntimeException(sprintf('Could not fetch column of table %s.', $localTable->getName())); } $tableName = $fk->getTableName(); @@ -976,7 +976,7 @@ protected static function getRefRelatedBySuffix(ForeignKey $fk): string $localColumnName = $localColumn->getPhpName(); $localTable = $fk->getTable(); if (!$localColumnName) { - throw new RuntimeException(sprintf('Could not fetch column: %s in table %s.', $localColumnName, $localTable->getName())); + throw new RuntimeException(sprintf('Could not fetch column of table %s.', $localTable->getName())); } $tableName = $fk->getTableName(); From 7b563f11c0976455f59c12135aa596cc8ff56d33 Mon Sep 17 00:00:00 2001 From: Michael Knappe Date: Tue, 24 Jan 2023 18:11:17 +0100 Subject: [PATCH 3/9] Fixes phpstan errors --- composer.json | 4 ++-- .../Generator/Builder/Util/SchemaReader.php | 17 ++++++++++++++--- .../Generator/Reverse/OracleSchemaParser.php | 3 ++- .../Runtime/Connection/StatementInterface.php | 2 +- .../Runtime/Connection/StatementWrapper.php | 2 +- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 04ce929d84..87573f13a7 100644 --- a/composer.json +++ b/composer.json @@ -24,12 +24,12 @@ "symfony/filesystem": "^4.4.0 || ^5.0.0 || ^6.0.0", "symfony/finder": "^4.4.0 || ^5.0.0 || ^6.0.0", "symfony/translation": "^4.4.0 || ^5.0.0 || ^6.0.0", - "symfony/validator": "^4.4.0 || ^5.0.0 || ^6.0.0" + "symfony/validator": "^4.4.0 || ^5.0.0 || ^6.0.0", + "ext-xml": "*" }, "require-dev": { "ext-pdo": "*", "ext-json": "*", - "ext-xml": "*", "monolog/monolog": "^1.3 || ^2.3 || ^3.0", "phpstan/phpstan": "^1.2", "phpunit/phpunit": "^9.5.0", diff --git a/src/Propel/Generator/Builder/Util/SchemaReader.php b/src/Propel/Generator/Builder/Util/SchemaReader.php index 6ac8686293..716d1bd967 100644 --- a/src/Propel/Generator/Builder/Util/SchemaReader.php +++ b/src/Propel/Generator/Builder/Util/SchemaReader.php @@ -39,7 +39,7 @@ class SchemaReader private $schema; /** - * @var \XMLParser + * @var \XMLParser|resource */ private $parser; @@ -450,15 +450,26 @@ private function throwSchemaExceptionWithLocation(string $format, ...$args): voi } /** - * Builds a human readable description of the current location in the parser, i.e. "file schema.xml line 42, column 43" + * Builds a human-readable description of the current location in the parser, i.e. "file schema.xml line 42, column 43" * * @return string */ private function getLocationDescription(): string { + $location = ($this->currentXmlFile !== null) ? sprintf('file %s,', $this->currentXmlFile) : ''; - $location .= sprintf('line %d', xml_get_current_line_number($this->parser)); + /** + * @phpstan-ignore-next-line + */ + $currentLineNumber = xml_get_current_line_number($this->parser); + if ($currentLineNumber) { + $location .= sprintf('line %d', $currentLineNumber); + } + + /** + * @phpstan-ignore-next-line + */ $currentColumnNumber = xml_get_current_column_number($this->parser); if ($currentColumnNumber) { $location .= sprintf(', column %d', $currentColumnNumber); diff --git a/src/Propel/Generator/Reverse/OracleSchemaParser.php b/src/Propel/Generator/Reverse/OracleSchemaParser.php index 1dd531faab..4c65e5a349 100644 --- a/src/Propel/Generator/Reverse/OracleSchemaParser.php +++ b/src/Propel/Generator/Reverse/OracleSchemaParser.php @@ -209,6 +209,7 @@ protected function addIndexes(Table $table): void foreach ($indicesIndexedByIndexName as $indexName => $columnNames) { $index = new Index((string)$indexName); + /** @phpstan-var string $columnName */ foreach ($columnNames as $columnName) { // Oracle deals with complex indices using an internal reference, so... // let's ignore this kind of index @@ -226,7 +227,7 @@ protected function addIndexes(Table $table): void /** * @param \Propel\Generator\Model\Table $table * - * @return array + * @return array> */ protected function getIndiciesIndexedByIndexName(Table $table): array { diff --git a/src/Propel/Runtime/Connection/StatementInterface.php b/src/Propel/Runtime/Connection/StatementInterface.php index 18dea50b10..5b326a3c97 100644 --- a/src/Propel/Runtime/Connection/StatementInterface.php +++ b/src/Propel/Runtime/Connection/StatementInterface.php @@ -112,7 +112,7 @@ public function fetchAll(?int $fetchStyle = PDO::FETCH_BOTH, $fetchArgument = nu * * @return mixed */ - public function fetchObject(string $className = 'stdClass', array $ctorArgs = []); + public function fetchObject(string $className, array $ctorArgs = []); /** * Fetch the SQLSTATE associated with the last operation on the statement handle. diff --git a/src/Propel/Runtime/Connection/StatementWrapper.php b/src/Propel/Runtime/Connection/StatementWrapper.php index 472a98da74..5f66f68a40 100644 --- a/src/Propel/Runtime/Connection/StatementWrapper.php +++ b/src/Propel/Runtime/Connection/StatementWrapper.php @@ -355,7 +355,7 @@ public function bindColumn($column, &$param, $type = null, $maxlen = null, $driv /** * @inheritDoc */ - public function fetchObject($className = 'stdClass', array $ctorArgs = []) + public function fetchObject($className, array $ctorArgs = []) { return $this->statement->fetchObject($className, $ctorArgs); } From 5ed201d8939529b4c66c9ea871449ad73dbb1c5d Mon Sep 17 00:00:00 2001 From: Michael Knappe Date: Tue, 24 Jan 2023 18:12:48 +0100 Subject: [PATCH 4/9] Fixes phpstan errors --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 87573f13a7..04ce929d84 100644 --- a/composer.json +++ b/composer.json @@ -24,12 +24,12 @@ "symfony/filesystem": "^4.4.0 || ^5.0.0 || ^6.0.0", "symfony/finder": "^4.4.0 || ^5.0.0 || ^6.0.0", "symfony/translation": "^4.4.0 || ^5.0.0 || ^6.0.0", - "symfony/validator": "^4.4.0 || ^5.0.0 || ^6.0.0", - "ext-xml": "*" + "symfony/validator": "^4.4.0 || ^5.0.0 || ^6.0.0" }, "require-dev": { "ext-pdo": "*", "ext-json": "*", + "ext-xml": "*", "monolog/monolog": "^1.3 || ^2.3 || ^3.0", "phpstan/phpstan": "^1.2", "phpunit/phpunit": "^9.5.0", From c7661af4e266560824b51e01426f378d619285ce Mon Sep 17 00:00:00 2001 From: Michael Knappe Date: Wed, 25 Jan 2023 12:42:08 +0100 Subject: [PATCH 5/9] Fixes phpstan errors --- src/Propel/Runtime/ActiveQuery/Join.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Propel/Runtime/ActiveQuery/Join.php b/src/Propel/Runtime/ActiveQuery/Join.php index c46ccf3716..ecd38c9639 100644 --- a/src/Propel/Runtime/ActiveQuery/Join.php +++ b/src/Propel/Runtime/ActiveQuery/Join.php @@ -137,12 +137,14 @@ class Join */ public function __construct($leftColumn = null, $rightColumn = null, ?string $joinType = null) { - if (is_array($leftColumn) && is_array($rightColumn)) { - $this->addConditions($leftColumn, $rightColumn); - } - - if (!is_array($leftColumn) && !is_array($rightColumn)) { - $this->addCondition((string)$leftColumn, (string)$rightColumn); + if ($leftColumn !== null) { + if (is_array($leftColumn)) { + // join with multiple conditions + $this->addConditions($leftColumn, $rightColumn); + } else { + // simple join + $this->addCondition($leftColumn, $rightColumn); + } } if ($joinType !== null) { From 270fc7708be578c9c4ed0422387ead7e81980b35 Mon Sep 17 00:00:00 2001 From: Michael Knappe Date: Wed, 25 Jan 2023 13:02:08 +0100 Subject: [PATCH 6/9] Fixes phpstan errors --- .../Behavior/Archivable/ArchivableBehavior.php | 5 ++++- src/Propel/Generator/Manager/MigrationManager.php | 12 ++++++------ src/Propel/Generator/Manager/SqlManager.php | 2 +- src/Propel/Generator/Platform/SqlitePlatform.php | 2 +- src/Propel/Generator/Reverse/MssqlSchemaParser.php | 4 ++-- src/Propel/Generator/Reverse/MysqlSchemaParser.php | 8 ++++---- src/Propel/Generator/Reverse/PgsqlSchemaParser.php | 14 +++++++------- src/Propel/Generator/Util/QuickBuilder.php | 2 +- src/Propel/Runtime/ActiveQuery/Join.php | 8 +++++--- .../QueryExecutor/AbstractQueryExecutor.php | 2 +- src/Propel/Runtime/Adapter/Pdo/PgsqlAdapter.php | 4 ++-- 11 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/Propel/Generator/Behavior/Archivable/ArchivableBehavior.php b/src/Propel/Generator/Behavior/Archivable/ArchivableBehavior.php index c7e2b1ddc9..c34548e00b 100644 --- a/src/Propel/Generator/Behavior/Archivable/ArchivableBehavior.php +++ b/src/Propel/Generator/Behavior/Archivable/ArchivableBehavior.php @@ -320,7 +320,10 @@ protected function reapplyBehaviors(array $behaviors) */ protected function createForeignKeyFromParameters(Table $table, array $fkParameterData): void { - if (empty($fkParameterData['localColumn']) || empty($fkParameterData['foreignColumn'])) { + if ( + empty($fkParameterData['localColumn']) || + empty($fkParameterData['foreignColumn']) + ) { $tableName = $this->table->getName(); throw new SchemaException("Table `$tableName`: Archivable behavior misses foreign key parameters. Please supply `localColumn`, `foreignTable` and `foreignColumn` for every entry"); diff --git a/src/Propel/Generator/Manager/MigrationManager.php b/src/Propel/Generator/Manager/MigrationManager.php index a581987920..a4e70339c1 100644 --- a/src/Propel/Generator/Manager/MigrationManager.php +++ b/src/Propel/Generator/Manager/MigrationManager.php @@ -206,7 +206,7 @@ public function migrationTableExists(string $datasource): bool $stmt = $conn->prepare($sql); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->execute(); @@ -267,7 +267,7 @@ public function removeMigrationTimestamp(string $datasource, int $timestamp): vo $stmt = $conn->prepare($sql); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->bindParam(1, $timestamp, PDO::PARAM_INT); @@ -302,7 +302,7 @@ public function updateLatestMigrationTimestamp(string $datasource, int $timestam $stmt = $conn->prepare($sql); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->bindParam(1, $timestamp, PDO::PARAM_INT); @@ -625,7 +625,7 @@ public function modifyMigrationTableIfOutdated(string $datasource): void $stmt = $connection->prepare($sql); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->execute(); @@ -668,7 +668,7 @@ protected function getMigrationData(string $connectionName): array $stmt = $connection->prepare($sql); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->execute(); @@ -717,7 +717,7 @@ protected function columnExists(ConnectionInterface $connection, string $columnN $stmt = $connection->prepare(sprintf('SELECT %s FROM %s', $columnName, $this->getMigrationTable())); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->execute(); diff --git a/src/Propel/Generator/Manager/SqlManager.php b/src/Propel/Generator/Manager/SqlManager.php index 26afbca8ee..0d2c5e651d 100644 --- a/src/Propel/Generator/Manager/SqlManager.php +++ b/src/Propel/Generator/Manager/SqlManager.php @@ -193,7 +193,7 @@ public function insertSql(?string $datasource = null): bool $stmt = $con->prepare($sql); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->execute(); diff --git a/src/Propel/Generator/Platform/SqlitePlatform.php b/src/Propel/Generator/Platform/SqlitePlatform.php index ca6280c2d0..5484c7abdc 100644 --- a/src/Propel/Generator/Platform/SqlitePlatform.php +++ b/src/Propel/Generator/Platform/SqlitePlatform.php @@ -646,7 +646,7 @@ protected function getVersion(): string $pdoStatement = $connection->query('SELECT sqlite_version()'); if ($pdoStatement === false) { - throw new RuntimeException('query() did not return a result set as a statement object.'); + throw new RuntimeException('PdoConnection::query() did not return a result set as a statement object.'); } return (string)$pdoStatement->fetch(PDO::FETCH_NUM)[0]; diff --git a/src/Propel/Generator/Reverse/MssqlSchemaParser.php b/src/Propel/Generator/Reverse/MssqlSchemaParser.php index 6bd84bbc33..b9d5c39594 100644 --- a/src/Propel/Generator/Reverse/MssqlSchemaParser.php +++ b/src/Propel/Generator/Reverse/MssqlSchemaParser.php @@ -96,7 +96,7 @@ public function parse(Database $database, array $additionalTables = []): int $dataFetcher = $this->dbh->query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME <> 'dtproperties'"); if ($dataFetcher === false) { - throw new RuntimeException('query() did not return a result set as a statement object.'); + throw new RuntimeException('PdoConnection::query() did not return a result set as a statement object.'); } // First load the tables (important that this happens before filling out details of tables) @@ -288,7 +288,7 @@ protected function addPrimaryKey(Table $table): void (INFORMATION_SCHEMA.TABLE_CONSTRAINTS.TABLE_NAME = '" . $table->getName() . "')"); if ($dataFetcher === false) { - throw new RuntimeException('query() did not return a result set as a statement object.'); + throw new RuntimeException('PdoConnection::query() did not return a result set as a statement object.'); } // Loop through the returned results, grouping the same key_name together diff --git a/src/Propel/Generator/Reverse/MysqlSchemaParser.php b/src/Propel/Generator/Reverse/MysqlSchemaParser.php index e4ffb765a6..438dbf9528 100644 --- a/src/Propel/Generator/Reverse/MysqlSchemaParser.php +++ b/src/Propel/Generator/Reverse/MysqlSchemaParser.php @@ -169,7 +169,7 @@ protected function parseTables(Database $database, ?Table $filterTable = null): $dataFetcher = $this->dbh->query($sql); if ($dataFetcher === false) { - throw new RuntimeException('query() did not return a result set as a statement object.'); + throw new RuntimeException('PdoConnection::query() did not return a result set as a statement object.'); } // First load the tables (important that this happens before filling out details of tables) @@ -365,7 +365,7 @@ protected function loadTableDescription(Table $table): ?string $dataFetcher = $this->dbh->query($query); if ($dataFetcher === false) { - throw new RuntimeException('query() did not return a result set as a statement object.'); + throw new RuntimeException('PdoConnection::query() did not return a result set as a statement object.'); } /** @phpstan-var string|null */ @@ -395,7 +395,7 @@ protected function loadColumnDescription(Column $column): ?string $dataFetcher = $this->dbh->query($query); if ($dataFetcher === false) { - throw new RuntimeException('query() did not return a result set as a statement object.'); + throw new RuntimeException('PdoConnection::query() did not return a result set as a statement object.'); } /** @phpstan-var string|null */ @@ -418,7 +418,7 @@ protected function addForeignKeys(Table $table): void $dataFetcher = $this->dbh->query(sprintf('SHOW CREATE TABLE %s', $this->getPlatform()->doQuoting($table->getName()))); if ($dataFetcher === false) { - throw new RuntimeException('query() did not return a result set as a statement object.'); + throw new RuntimeException('PdoConnection::query() did not return a result set as a statement object.'); } $row = $dataFetcher->fetch(); diff --git a/src/Propel/Generator/Reverse/PgsqlSchemaParser.php b/src/Propel/Generator/Reverse/PgsqlSchemaParser.php index b62b7f99cb..a28e99b78d 100755 --- a/src/Propel/Generator/Reverse/PgsqlSchemaParser.php +++ b/src/Propel/Generator/Reverse/PgsqlSchemaParser.php @@ -269,7 +269,7 @@ protected function addColumns(Table $table, int $oid): void table_schema IN ($searchPath) AND table_name = ? "); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $params[] = $table->getCommonName(); @@ -409,7 +409,7 @@ protected function addForeignKeys(Table $table, int $oid): void GROUP BY conname, confupdtype, confdeltype, fktab, reftab ORDER BY conname"); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->bindValue(1, $oid); $stmt->execute(); @@ -524,7 +524,7 @@ protected function addIndexes(Table $table, int $oid): void WHERE indrelid = ? AND NOT indisprimary ORDER BY cls.relname"); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->bindValue(1, $oid); @@ -535,7 +535,7 @@ protected function addIndexes(Table $table, int $oid): void WHERE c.oid = ? AND a.attnum = ? AND NOT a.attisdropped ORDER BY a.attnum"); if ($stmt2 === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $indexes = []; @@ -598,7 +598,7 @@ protected function addPrimaryKey(Table $table, int $oid): void WHERE indrelid = ? AND indisprimary ORDER BY cls.relname"); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->bindValue(1, $oid); $stmt->execute(); @@ -613,7 +613,7 @@ protected function addPrimaryKey(Table $table, int $oid): void WHERE c.oid = ? AND a.attnum = ? AND NOT a.attisdropped ORDER BY a.attnum"); if ($stmt2 === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt2->bindValue(1, $oid); $stmt2->bindValue(2, $intColNum); @@ -667,7 +667,7 @@ protected function addSequences(Database $database): void AND n.nspname IN ($searchPath); "); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->execute($params); diff --git a/src/Propel/Generator/Util/QuickBuilder.php b/src/Propel/Generator/Util/QuickBuilder.php index f41cb467b9..8e6f827f55 100644 --- a/src/Propel/Generator/Util/QuickBuilder.php +++ b/src/Propel/Generator/Util/QuickBuilder.php @@ -346,7 +346,7 @@ public function updateDB(ConnectionInterface $con): ?Database $stmt = $con->prepare($statement); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } $stmt->execute(); diff --git a/src/Propel/Runtime/ActiveQuery/Join.php b/src/Propel/Runtime/ActiveQuery/Join.php index ecd38c9639..b498b63aeb 100644 --- a/src/Propel/Runtime/ActiveQuery/Join.php +++ b/src/Propel/Runtime/ActiveQuery/Join.php @@ -137,13 +137,15 @@ class Join */ public function __construct($leftColumn = null, $rightColumn = null, ?string $joinType = null) { - if ($leftColumn !== null) { - if (is_array($leftColumn)) { + if ($leftColumn !== null && $rightColumn !== null) { + if (is_array($leftColumn) && is_array($rightColumn)) { // join with multiple conditions $this->addConditions($leftColumn, $rightColumn); } else { // simple join - $this->addCondition($leftColumn, $rightColumn); + if (is_string($leftColumn) && is_string($rightColumn)) { + $this->addCondition($leftColumn, $rightColumn); + } } } diff --git a/src/Propel/Runtime/ActiveQuery/QueryExecutor/AbstractQueryExecutor.php b/src/Propel/Runtime/ActiveQuery/QueryExecutor/AbstractQueryExecutor.php index 678cae964c..29b88af6f9 100644 --- a/src/Propel/Runtime/ActiveQuery/QueryExecutor/AbstractQueryExecutor.php +++ b/src/Propel/Runtime/ActiveQuery/QueryExecutor/AbstractQueryExecutor.php @@ -103,7 +103,7 @@ protected function executeStatement(PreparedStatementDto $preparedStatementDto) $stmt = $this->con->prepare($sql); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } if ($params) { diff --git a/src/Propel/Runtime/Adapter/Pdo/PgsqlAdapter.php b/src/Propel/Runtime/Adapter/Pdo/PgsqlAdapter.php index 3a1d48919d..7f113fc808 100644 --- a/src/Propel/Runtime/Adapter/Pdo/PgsqlAdapter.php +++ b/src/Propel/Runtime/Adapter/Pdo/PgsqlAdapter.php @@ -109,7 +109,7 @@ public function getId(ConnectionInterface $con, ?string $name = null): int $dataFetcher = $con->query(sprintf('SELECT nextval(%s)', $con->quote($name))); if ($dataFetcher === false) { - throw new RuntimeException('query() did not return a result set as a statement object.'); + throw new RuntimeException('PdoConnection::query() did not return a result set as a statement object.'); } return $dataFetcher->fetchColumn(); @@ -239,7 +239,7 @@ public function doExplainPlan(ConnectionInterface $con, $query) $stmt = $con->prepare($this->getExplainPlanQuery($sql)); if ($stmt === false) { - throw new RuntimeException('prepare() failed and did not return statement object for execution.'); + throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); } if ($query instanceof Criteria) { From 2f24aba83105571efe77f01cd25d09a6b50f0c27 Mon Sep 17 00:00:00 2001 From: Michael Knappe Date: Wed, 25 Jan 2023 13:09:29 +0100 Subject: [PATCH 7/9] Fixes phpstan errors --- src/Propel/Generator/Reverse/OracleSchemaParser.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Propel/Generator/Reverse/OracleSchemaParser.php b/src/Propel/Generator/Reverse/OracleSchemaParser.php index 4c65e5a349..a4888a9834 100644 --- a/src/Propel/Generator/Reverse/OracleSchemaParser.php +++ b/src/Propel/Generator/Reverse/OracleSchemaParser.php @@ -205,9 +205,9 @@ protected function addColumns(Table $table): void */ protected function addIndexes(Table $table): void { - $indicesIndexedByIndexName = $this->getIndiciesIndexedByIndexName($table); + $columnNamesIndexedByIndexName = $this->getColumnNamesIndexedByIndexName($table); - foreach ($indicesIndexedByIndexName as $indexName => $columnNames) { + foreach ($columnNamesIndexedByIndexName as $indexName => $columnNames) { $index = new Index((string)$indexName); /** @phpstan-var string $columnName */ foreach ($columnNames as $columnName) { @@ -229,17 +229,17 @@ protected function addIndexes(Table $table): void * * @return array> */ - protected function getIndiciesIndexedByIndexName(Table $table): array + protected function getColumnNamesIndexedByIndexName(Table $table): array { /** @var \PDOStatement $stmt */ $stmt = $this->dbh->query("SELECT INDEX_NAME, COLUMN_NAME FROM USER_IND_COLUMNS WHERE TABLE_NAME = '" . $table->getName() . "' ORDER BY COLUMN_NAME"); - $indicesIndexedByIndexName = []; + $columnNamesIndexedByIndexName = []; while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { - $indicesIndexedByIndexName[$row['INDEX_NAME']][] = $row['COLUMN_NAME']; + $columnNamesIndexedByIndexName[$row['INDEX_NAME']][] = $row['COLUMN_NAME']; } - return $indicesIndexedByIndexName; + return $columnNamesIndexedByIndexName; } /** From bf5e1015b676a8cb0f432eaa6207f89b67cae2d2 Mon Sep 17 00:00:00 2001 From: Michael Knappe Date: Wed, 25 Jan 2023 13:19:16 +0100 Subject: [PATCH 8/9] Fixes phpstan errors --- src/Propel/Generator/Builder/Util/SchemaReader.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Propel/Generator/Builder/Util/SchemaReader.php b/src/Propel/Generator/Builder/Util/SchemaReader.php index 716d1bd967..9696d16479 100644 --- a/src/Propel/Generator/Builder/Util/SchemaReader.php +++ b/src/Propel/Generator/Builder/Util/SchemaReader.php @@ -456,7 +456,6 @@ private function throwSchemaExceptionWithLocation(string $format, ...$args): voi */ private function getLocationDescription(): string { - $location = ($this->currentXmlFile !== null) ? sprintf('file %s,', $this->currentXmlFile) : ''; /** From fc349a2c0c1b2a661c6fc52e8f68ef18ac846e1d Mon Sep 17 00:00:00 2001 From: Michael Knappe Date: Wed, 25 Jan 2023 15:04:53 +0100 Subject: [PATCH 9/9] Fixes phpstan errors --- .../Generator/Builder/Om/AbstractOMBuilder.php | 10 ++++------ src/Propel/Generator/Builder/Util/SchemaReader.php | 4 ++-- src/Propel/Generator/Manager/MigrationManager.php | 13 ++++++------- src/Propel/Generator/Model/ColumnDefaultValue.php | 6 +++--- src/Propel/Generator/Model/NameFactory.php | 4 ++-- src/Propel/Runtime/ActiveQuery/Criteria.php | 12 ++++++------ 6 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/Propel/Generator/Builder/Om/AbstractOMBuilder.php b/src/Propel/Generator/Builder/Om/AbstractOMBuilder.php index e116f1a54b..ee87b51381 100644 --- a/src/Propel/Generator/Builder/Om/AbstractOMBuilder.php +++ b/src/Propel/Generator/Builder/Om/AbstractOMBuilder.php @@ -910,10 +910,9 @@ protected static function getRelatedBySuffix(ForeignKey $fk): string foreach ($fk->getMapping() as $mapping) { [$localColumn, $foreignValueOrColumn] = $mapping; - $localColumnName = $localColumn->getPhpName(); $localTable = $fk->getTable(); - if (!$localColumnName) { - throw new RuntimeException(sprintf('Could not fetch column of table %s.', $localTable->getName())); + if (!$localColumn) { + throw new RuntimeException(sprintf('Could not resolve column of foreign key `%s` on table `%s`', $fk->getName(), $localTable->getName())); } $tableName = $fk->getTableName(); @@ -973,10 +972,9 @@ protected static function getRefRelatedBySuffix(ForeignKey $fk): string $relCol = ''; foreach ($fk->getMapping() as $mapping) { [$localColumn, $foreignValueOrColumn] = $mapping; - $localColumnName = $localColumn->getPhpName(); $localTable = $fk->getTable(); - if (!$localColumnName) { - throw new RuntimeException(sprintf('Could not fetch column of table %s.', $localTable->getName())); + if (!$localColumn) { + throw new RuntimeException(sprintf('Could not resolve column of foreign key `%s` on table `%s`', $fk->getName(), $localTable->getName())); } $tableName = $fk->getTableName(); diff --git a/src/Propel/Generator/Builder/Util/SchemaReader.php b/src/Propel/Generator/Builder/Util/SchemaReader.php index 9696d16479..4e1aa088a2 100644 --- a/src/Propel/Generator/Builder/Util/SchemaReader.php +++ b/src/Propel/Generator/Builder/Util/SchemaReader.php @@ -459,7 +459,7 @@ private function getLocationDescription(): string $location = ($this->currentXmlFile !== null) ? sprintf('file %s,', $this->currentXmlFile) : ''; /** - * @phpstan-ignore-next-line + * @phpstan-ignore-next-line PHPStan is expecting XMLParser only, while resource is valid too. */ $currentLineNumber = xml_get_current_line_number($this->parser); if ($currentLineNumber) { @@ -467,7 +467,7 @@ private function getLocationDescription(): string } /** - * @phpstan-ignore-next-line + * @phpstan-ignore-next-line PHPStan is expecting XMLParser only, while resource is valid too. */ $currentColumnNumber = xml_get_current_column_number($this->parser); if ($currentColumnNumber) { diff --git a/src/Propel/Generator/Manager/MigrationManager.php b/src/Propel/Generator/Manager/MigrationManager.php index a4e70339c1..6bec14d0fb 100644 --- a/src/Propel/Generator/Manager/MigrationManager.php +++ b/src/Propel/Generator/Manager/MigrationManager.php @@ -463,12 +463,10 @@ public function findMigrationClassNameSuffix(int $timestamp): string $suffix = ''; $path = $this->getWorkingDirectory(); if ($path && is_dir($path)) { - $files = scandir($path); - if ($files) { - foreach ($files as $file) { - if (preg_match('/^PropelMigration_' . $timestamp . '(_)?(.*)\.php$/', $file, $matches)) { - $suffix = (string)$matches[2]; - } + $files = scandir($path) ?: []; + foreach ($files as $file) { + if (preg_match('/^PropelMigration_' . $timestamp . '(_)?(.*)\.php$/', $file, $matches)) { + $suffix = (string)$matches[2]; } } } @@ -714,7 +712,8 @@ protected function createExecutionDatetimeColumn(PlatformInterface $platform): C protected function columnExists(ConnectionInterface $connection, string $columnName): bool { try { - $stmt = $connection->prepare(sprintf('SELECT %s FROM %s', $columnName, $this->getMigrationTable())); + $sql = sprintf('SELECT %s FROM %s', $columnName, $this->getMigrationTable()); + $stmt = $connection->prepare($sql); if ($stmt === false) { throw new RuntimeException('PdoConnection::prepare() failed and did not return statement object for execution.'); diff --git a/src/Propel/Generator/Model/ColumnDefaultValue.php b/src/Propel/Generator/Model/ColumnDefaultValue.php index 3edc755b2c..f1fada6030 100644 --- a/src/Propel/Generator/Model/ColumnDefaultValue.php +++ b/src/Propel/Generator/Model/ColumnDefaultValue.php @@ -27,7 +27,7 @@ class ColumnDefaultValue public const TYPE_EXPR = 'expr'; /** - * @var string|null The default value, as specified in the schema. + * @var string|int|null The default value, as specified in the schema. */ private $value; @@ -94,7 +94,7 @@ public function getValue() */ public function setValue($value): void { - $this->value = (string)$value; + $this->value = $value; } /** @@ -121,6 +121,6 @@ public function equals(ColumnDefaultValue $other): bool $value = strtoupper((string)$this->getValue()); $otherValue = strtoupper((string)$other->getValue()); - return in_array($value, $equivalents) && in_array($otherValue, $equivalents); + return in_array($value, $equivalents, true) && in_array($otherValue, $equivalents, true); } } diff --git a/src/Propel/Generator/Model/NameFactory.php b/src/Propel/Generator/Model/NameFactory.php index 1c78426149..4af650419a 100644 --- a/src/Propel/Generator/Model/NameFactory.php +++ b/src/Propel/Generator/Model/NameFactory.php @@ -42,7 +42,7 @@ class NameFactory /** * Factory method which retrieves an instance of the named generator. * - * @param string $nameGeneratorClassName The fully qualified class name of the name generation algorithm to retrieve. + * @param class-string<\Propel\Generator\Model\NameGeneratorInterface> $nameGeneratorClassName The fully qualified class name of the name generation algorithm to retrieve. * * @return \Propel\Generator\Model\NameGeneratorInterface */ @@ -61,7 +61,7 @@ protected static function getAlgorithm(string $nameGeneratorClassName): NameGene * Given a list of String objects, implements an * algorithm which produces a name. * - * @param string $algorithmName The fully qualified class name of the {@link NameGeneratorInterface} + * @param class-string<\Propel\Generator\Model\NameGeneratorInterface> $algorithmName The fully qualified class name of the {@link NameGeneratorInterface} * implementation to use to generate names. * @param array $inputs Inputs used to generate a name. * diff --git a/src/Propel/Runtime/ActiveQuery/Criteria.php b/src/Propel/Runtime/ActiveQuery/Criteria.php index 42aad64005..54b1eff125 100644 --- a/src/Propel/Runtime/ActiveQuery/Criteria.php +++ b/src/Propel/Runtime/ActiveQuery/Criteria.php @@ -1064,16 +1064,16 @@ public function addJoin($left, $right, ?string $joinType = null) // is the left table an alias ? /** @phpstan-var string $left */ - $length = strrpos($left, '.') ?: null; - $leftTableAlias = substr($left, 0, $length); - $leftColumnName = substr($left, $length + 1); + $dotpos = strrpos($left, '.') ?: null; + $leftTableAlias = substr($left, 0, $dotpos); + $leftColumnName = substr($left, $dotpos + 1); [$leftTableName, $leftTableAlias] = $this->getTableNameAndAlias($leftTableAlias); // is the right table an alias ? /** @phpstan-var string $right */ - $length = strrpos($right, '.') ?: null; - $rightTableAlias = substr($right, 0, $length); - $rightColumnName = substr($right, $length + 1); + $dotpos = strrpos($right, '.') ?: null; + $rightTableAlias = substr($right, 0, $dotpos); + $rightColumnName = substr($right, $dotpos + 1); [$rightTableName, $rightTableAlias] = $this->getTableNameAndAlias($rightTableAlias); $join->addExplicitCondition(