From 5ae8baeb15a1ea1dc5bb82d262925a9aa188408f Mon Sep 17 00:00:00 2001 From: Jan Skrasek Date: Wed, 22 Jul 2020 21:46:46 +0200 Subject: [PATCH] phpstan enable strict rules --- composer.json | 3 +- src/Bridges/NetteCaching/CachedPlatform.php | 8 +++--- src/Bridges/NetteDI/DbalExtension.php | 2 +- .../NetteTracy/BluescreenQueryPanel.php | 2 +- src/Bridges/NetteTracy/ConnectionPanel.php | 8 +++--- .../DataCollector/QueryDataCollector.php | 2 +- .../DependencyInjection/Configuration.php | 4 +-- src/Connection.php | 2 +- src/Drivers/Exception/QueryException.php | 8 +++--- src/Drivers/IDriver.php | 2 +- src/Drivers/Mysqli/MysqliDriver.php | 20 +++++++------ src/Drivers/Pgsql/PgsqlDriver.php | 13 +++++---- src/Drivers/Pgsql/PgsqlResultAdapter.php | 3 +- src/Drivers/Sqlsrv/SqlsrvDriver.php | 28 +++++++++---------- src/Drivers/Sqlsrv/SqlsrvResultAdapter.php | 5 ++-- src/IConnection.php | 2 +- src/Platforms/PostgreSqlPlatform.php | 2 +- src/QueryBuilder/QueryBuilder.php | 23 +++++++-------- src/Result/Result.php | 14 +++++----- src/Result/Row.php | 4 +-- src/SqlProcessor.php | 16 +++++------ src/Utils/FileImporter.php | 4 +-- src/Utils/SqlHighlighter.php | 14 ++++++++-- 23 files changed, 100 insertions(+), 89 deletions(-) diff --git a/composer.json b/composer.json index 4ca7522d..3f3aff72 100644 --- a/composer.json +++ b/composer.json @@ -22,9 +22,10 @@ "nette/utils": "~3.0", "nette/finder": "~2.5", "nette/neon": "~3.0", + "phpstan/extension-installer": "1.0.4", "phpstan/phpstan": "0.12.33", "phpstan/phpstan-deprecation-rules": "0.12.5", - "phpstan/extension-installer": "~1.0", + "phpstan/phpstan-strict-rules": "0.12.4", "symfony/config": "~4.4 || ~5.0", "symfony/dependency-injection": "~4.4 || ~5.0", "symfony/http-kernel": "~4.4 || ~5.0", diff --git a/src/Bridges/NetteCaching/CachedPlatform.php b/src/Bridges/NetteCaching/CachedPlatform.php index 485a4cff..dc41ff82 100644 --- a/src/Bridges/NetteCaching/CachedPlatform.php +++ b/src/Bridges/NetteCaching/CachedPlatform.php @@ -34,7 +34,7 @@ public function getName(): string /** @inheritDoc */ public function getTables(?string $schema = null): array { - return $this->cache->load(self::CACHE_VERSION . '.tables.' . $schema, function () use ($schema) { + return $this->cache->load(self::CACHE_VERSION . '.tables.' . $schema, function () use ($schema): array { return $this->platform->getTables($schema); }); } @@ -43,7 +43,7 @@ public function getTables(?string $schema = null): array /** @inheritDoc */ public function getColumns(string $table): array { - return $this->cache->load(self::CACHE_VERSION . '.columns.' . $table, function () use ($table) { + return $this->cache->load(self::CACHE_VERSION . '.columns.' . $table, function () use ($table): array { return $this->platform->getColumns($table); }); } @@ -52,7 +52,7 @@ public function getColumns(string $table): array /** @inheritDoc */ public function getForeignKeys(string $table): array { - return $this->cache->load(self::CACHE_VERSION . '.foreign_keys.' . $table, function () use ($table) { + return $this->cache->load(self::CACHE_VERSION . '.foreign_keys.' . $table, function () use ($table): array { return $this->platform->getForeignKeys($table); }); } @@ -60,7 +60,7 @@ public function getForeignKeys(string $table): array public function getPrimarySequenceName(string $table): ?string { - return $this->cache->load(self::CACHE_VERSION . '.sequence.' . $table, function () use ($table) { + return $this->cache->load(self::CACHE_VERSION . '.sequence.' . $table, function () use ($table): array { return [$this->platform->getPrimarySequenceName($table)]; })[0]; } diff --git a/src/Bridges/NetteDI/DbalExtension.php b/src/Bridges/NetteDI/DbalExtension.php index 34f60b6a..8b44293a 100644 --- a/src/Bridges/NetteDI/DbalExtension.php +++ b/src/Bridges/NetteDI/DbalExtension.php @@ -35,7 +35,7 @@ protected function setupConnection(array $config): void ->setAutowired(isset($config['autowired']) ? $config['autowired'] : true); if (isset($config['debugger'])) { - $debugger = $config['debugger']; + $debugger = (bool) $config['debugger']; } else { $debugger = class_exists('Tracy\Debugger', false) && Debugger::$productionMode === Debugger::DEVELOPMENT; } diff --git a/src/Bridges/NetteTracy/BluescreenQueryPanel.php b/src/Bridges/NetteTracy/BluescreenQueryPanel.php index 415f1a97..959fea1e 100644 --- a/src/Bridges/NetteTracy/BluescreenQueryPanel.php +++ b/src/Bridges/NetteTracy/BluescreenQueryPanel.php @@ -14,7 +14,7 @@ class BluescreenQueryPanel */ public static function renderBluescreenPanel(?\Throwable $exception): ?array { - if (!$exception instanceof QueryException || !($query = $exception->getSqlQuery())) { + if (!$exception instanceof QueryException || ($query = $exception->getSqlQuery()) === null) { return null; } diff --git a/src/Bridges/NetteTracy/ConnectionPanel.php b/src/Bridges/NetteTracy/ConnectionPanel.php index 678c2499..d49f22c2 100644 --- a/src/Bridges/NetteTracy/ConnectionPanel.php +++ b/src/Bridges/NetteTracy/ConnectionPanel.php @@ -75,7 +75,7 @@ public function onQuery(string $sqlQuery, float $timeTaken, ?Result $result): vo $this->connection, $sqlQuery, $timeTaken, - $result ? $result->count() : null, + $result !== null ? $result->count() : null, ]; } @@ -85,7 +85,7 @@ public function onQueryException(string $sqlQuery, float $timeTaken, ?DriverExce } - public function getTab(): ?string + public function getTab(): string { $count = $this->count; $totalTime = $this->totalTime; @@ -96,11 +96,11 @@ public function getTab(): ?string } - public function getPanel(): ?string + public function getPanel(): string { $count = $this->count; $queries = $this->queries; - $queries = array_map(function ($row) { + $queries = array_map(function ($row): array { try { $row[4] = null; if ($this->doExplain) { diff --git a/src/Bridges/SymfonyBundle/DataCollector/QueryDataCollector.php b/src/Bridges/SymfonyBundle/DataCollector/QueryDataCollector.php index 6f76ed3e..29665a1e 100644 --- a/src/Bridges/SymfonyBundle/DataCollector/QueryDataCollector.php +++ b/src/Bridges/SymfonyBundle/DataCollector/QueryDataCollector.php @@ -144,7 +144,7 @@ public function onQuery(string $sqlQuery, float $timeTaken, ?Result $result): vo $this->queries[] = [ $sqlQuery, $timeTaken, - $result ? $result->count() : null, + $result !== null ? $result->count() : null, ]; } diff --git a/src/Bridges/SymfonyBundle/DependencyInjection/Configuration.php b/src/Bridges/SymfonyBundle/DependencyInjection/Configuration.php index 2026fe52..6dd3c410 100644 --- a/src/Bridges/SymfonyBundle/DependencyInjection/Configuration.php +++ b/src/Bridges/SymfonyBundle/DependencyInjection/Configuration.php @@ -28,10 +28,10 @@ public function getConfigTreeBuilder() // @formatter:off $treeBuilder->getRootNode() ->beforeNormalization() - ->ifTrue(static function ($v) { + ->ifTrue(static function ($v): bool { return is_array($v) && !array_key_exists('connections', $v); }) - ->then(static function ($v) { + ->then(static function ($v): array { return [ 'connections' => ['default' => $v], 'default_connection' => 'default', diff --git a/src/Connection.php b/src/Connection.php index 17a206bc..b6339f05 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -342,7 +342,7 @@ private function nativeQuery(string $sql): Result private function createDriver(): IDriver { - if (empty($this->config['driver'])) { + if (!isset($this->config['driver'])) { throw new InvalidArgumentException('Undefined driver. Choose from: mysqli, pgsql, sqlsrv.'); } elseif ($this->config['driver'] instanceof IDriver) { return $this->config['driver']; diff --git a/src/Drivers/Exception/QueryException.php b/src/Drivers/Exception/QueryException.php index 38b85886..5735462c 100644 --- a/src/Drivers/Exception/QueryException.php +++ b/src/Drivers/Exception/QueryException.php @@ -8,7 +8,7 @@ class QueryException extends DriverException { - /** @var string */ + /** @var string|null */ private $sqlQuery; @@ -17,15 +17,15 @@ public function __construct( int $errorCode = 0, string $errorSqlState = '', Exception $previousException = null, - string $sqlQuery = null + ?string $sqlQuery = null ) { parent::__construct($message, $errorCode, $errorSqlState, $previousException); - $this->sqlQuery = (string) $sqlQuery; + $this->sqlQuery = $sqlQuery; } - public function getSqlQuery(): string + public function getSqlQuery(): ?string { return $this->sqlQuery; } diff --git a/src/Drivers/IDriver.php b/src/Drivers/IDriver.php index 6b7b0311..71bc0a23 100644 --- a/src/Drivers/IDriver.php +++ b/src/Drivers/IDriver.php @@ -67,7 +67,7 @@ public function query(string $query): Result; * @return mixed * @internal */ - public function getLastInsertedId(string $sequenceName = null); + public function getLastInsertedId(?string $sequenceName = null); /** diff --git a/src/Drivers/Mysqli/MysqliDriver.php b/src/Drivers/Mysqli/MysqliDriver.php index 3f638538..8501b9dd 100644 --- a/src/Drivers/Mysqli/MysqliDriver.php +++ b/src/Drivers/Mysqli/MysqliDriver.php @@ -58,9 +58,10 @@ public function connect(array $params, ILogger $logger): void $this->logger = $logger; $host = $params['host'] ?? ini_get('mysqli.default_host'); - $port = $params['port'] ?? (int) (ini_get('mysqli.default_port') ?: 3306); + $port = (int) ($params['port'] ?? ini_get('mysqli.default_port')); + $port = $port === 0 ? 3306 : $port; $dbname = $params['database'] ?? ''; - $socket = ($params['unix_socket'] ?? ini_get('mysqli.default_socket')) ?: ''; + $socket = $params['unix_socket'] ?? ini_get('mysqli.default_socket'); $flags = $params['flags'] ?? 0; $this->connection = new mysqli(); @@ -72,7 +73,8 @@ public function connect(array $params, ILogger $logger): void if (!@$this->connection->real_connect($host, $params['username'], (string) $params['password'], $dbname, $port, $socket, $flags)) { throw $this->createException( $this->connection->connect_error, - (int) $this->connection->connect_errno, + $this->connection->connect_errno, + // @phpstan-ignore-next-line - Property access is not allowed yet @$this->connection->sqlstate ?: 'HY000' ); } @@ -83,7 +85,7 @@ public function connect(array $params, ILogger $logger): void public function disconnect(): void { - if ($this->connection) { + if ($this->connection !== null) { $this->connection->close(); $this->connection = null; } @@ -130,7 +132,7 @@ public function query(string $query): Result } - public function getLastInsertedId(string $sequenceName = null) + public function getLastInsertedId(?string $sequenceName = null) { assert($this->connection !== null); return $this->connection->insert_id; @@ -261,7 +263,7 @@ protected function processInitialSettings(array $params): void if (isset($params['charset'])) { $charset = $params['charset']; - } elseif (($version = $this->getServerVersion()) && version_compare($version, '5.5.3', '>=')) { + } elseif (version_compare($this->getServerVersion(), '5.5.3', '>=')) { $charset = 'utf8mb4'; } else { $charset = 'utf8'; @@ -318,7 +320,7 @@ public function convertStringToSql(string $value): string public function convertJsonToSql($value): string { $encoded = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION); - if (json_last_error()) { + if (json_last_error() !== JSON_ERROR_NONE) { throw new InvalidArgumentException('JSON Encode Error: ' . json_last_error_msg()); } assert(is_string($encoded)); @@ -345,7 +347,7 @@ public function convertIdentifierToSql(string $value): string } - public function convertDatetimeToSql(DateTimeInterface $value): string + public function convertDateTimeToSql(DateTimeInterface $value): string { assert($value instanceof DateTime || $value instanceof DateTimeImmutable); if ($value->getTimezone()->getName() !== $this->connectionTz->getName()) { @@ -360,7 +362,7 @@ public function convertDatetimeToSql(DateTimeInterface $value): string } - public function convertDatetimeSimpleToSql(DateTimeInterface $value): string + public function convertDateTimeSimpleToSql(DateTimeInterface $value): string { return "'" . $value->format('Y-m-d H:i:s.u') . "'"; } diff --git a/src/Drivers/Pgsql/PgsqlDriver.php b/src/Drivers/Pgsql/PgsqlDriver.php index 34db490b..20d3003f 100644 --- a/src/Drivers/Pgsql/PgsqlDriver.php +++ b/src/Drivers/Pgsql/PgsqlDriver.php @@ -80,7 +80,7 @@ public function connect(array $params, ILogger $logger): void } } - set_error_handler(function ($code, $message) { + set_error_handler(function (int $code, string $message): bool { restore_error_handler(); throw $this->createException($message, $code, null); }, E_ALL); @@ -107,7 +107,7 @@ public function connect(array $params, ILogger $logger): void public function disconnect(): void { - if ($this->connection) { + if ($this->connection !== null) { pg_close($this->connection); $this->connection = null; } @@ -143,7 +143,8 @@ public function query(string $query): Result $state = pg_result_error_field($resource, PGSQL_DIAG_SQLSTATE); if (is_string($state)) { - throw $this->createException(pg_result_error($resource) ?: 'Unknown error', 0, $state, $query); + $error = pg_result_error($resource); + throw $this->createException($error !== false ? $error : 'Unknown error', 0, $state, $query); } $this->affectedRows = pg_affected_rows($resource); @@ -151,9 +152,9 @@ public function query(string $query): Result } - public function getLastInsertedId(string $sequenceName = null) + public function getLastInsertedId(?string $sequenceName = null) { - if (empty($sequenceName)) { + if ($sequenceName === null) { throw new InvalidArgumentException('PgsqlDriver requires to pass sequence name for getLastInsertedId() method.'); } assert($this->connection !== null); @@ -284,7 +285,7 @@ public function convertStringToSql(string $value): string public function convertJsonToSql($value): string { $encoded = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION); - if (json_last_error()) { + if (json_last_error() !== JSON_ERROR_NONE) { throw new InvalidArgumentException('JSON Encode Error: ' . json_last_error_msg()); } assert(is_string($encoded)); diff --git a/src/Drivers/Pgsql/PgsqlResultAdapter.php b/src/Drivers/Pgsql/PgsqlResultAdapter.php index edcacca2..a4d19c36 100644 --- a/src/Drivers/Pgsql/PgsqlResultAdapter.php +++ b/src/Drivers/Pgsql/PgsqlResultAdapter.php @@ -73,7 +73,8 @@ public function seek(int $index): void public function fetch(): ?array { - return pg_fetch_array($this->result, null, PGSQL_ASSOC) ?: null; + $row = pg_fetch_array($this->result, null, PGSQL_ASSOC); + return $row !== false ? $row : null; } diff --git a/src/Drivers/Sqlsrv/SqlsrvDriver.php b/src/Drivers/Sqlsrv/SqlsrvDriver.php index 42621030..9779b00d 100644 --- a/src/Drivers/Sqlsrv/SqlsrvDriver.php +++ b/src/Drivers/Sqlsrv/SqlsrvDriver.php @@ -82,7 +82,7 @@ public function connect(array $params, ILogger $logger): void if ($key === 'username') { $connectionOptions['UID'] = $value; } elseif ($key === 'password') { - $connectionOptions['PWD'] = $value ?: ''; + $connectionOptions['PWD'] = $value ?? ''; } elseif ($key === 'database') { $connectionOptions['Database'] = $value; } elseif ($key === 'connectionTz') { @@ -97,16 +97,17 @@ public function connect(array $params, ILogger $logger): void } $connectionOptions['ReturnDatesAsStrings'] = true; - $this->connection = sqlsrv_connect($connectionString, $connectionOptions) ?: null; - if (!$this->connection) { + $connectionResource = sqlsrv_connect($connectionString, $connectionOptions); + if ($connectionResource === false) { $this->throwErrors(); } + $this->connection = $connectionResource; } public function disconnect(): void { - if ($this->connection) { + if ($this->connection !== null) { sqlsrv_close($this->connection); $this->connection = null; } @@ -139,21 +140,20 @@ public function query(string $query): Result } $affectedRowsStatement = sqlsrv_query($this->connection, 'SELECT @@ROWCOUNT'); - if (!$affectedRowsStatement) { + if ($affectedRowsStatement === false) { $this->throwErrors(); } - assert($affectedRowsStatement !== false); - if ($affectedRowsResult = sqlsrv_fetch_array($affectedRowsStatement, SQLSRV_FETCH_NUMERIC)) { - $this->affectedRows = $affectedRowsResult[0]; - } else { + $affectedRowsResult = sqlsrv_fetch_array($affectedRowsStatement, SQLSRV_FETCH_NUMERIC); + if (!is_array($affectedRowsResult)) { $this->throwErrors(); } + $this->affectedRows = $affectedRowsResult[0]; return new Result(new SqlsrvResultAdapter($statement), $this); } - public function getLastInsertedId(string $sequenceName = null) + public function getLastInsertedId(?string $sequenceName = null) { return $this->loggedQuery('SELECT SCOPE_IDENTITY()')->fetchField(); } @@ -294,7 +294,7 @@ public function convertStringToSql(string $value): string public function convertJsonToSql($value): string { $encoded = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION); - if (json_last_error()) { + if (json_last_error() !== JSON_ERROR_NONE) { throw new InvalidArgumentException('JSON Encode Error: ' . json_last_error_msg()); } assert(is_string($encoded)); @@ -353,7 +353,7 @@ public function convertBlobToSql(string $value): string public function modifyLimitQuery(string $query, ?int $limit, ?int $offset): string { - $query .= ' OFFSET ' . ($offset ?: 0) . ' ROWS'; + $query .= ' OFFSET ' . ($offset !== null ? $offset : 0) . ' ROWS'; if ($limit !== null) { $query .= ' FETCH NEXT ' . $limit . ' ROWS ONLY'; } @@ -366,8 +366,8 @@ public function modifyLimitQuery(string $query, ?int $limit, ?int $offset): stri */ private function throwErrors(?string $query = null): void { - $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS) ?: []; - $errors = array_unique($errors, SORT_REGULAR); + $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); + $errors = $errors === null ? [] : array_unique($errors, SORT_REGULAR); $error = array_shift($errors); if ($error === null) { return; diff --git a/src/Drivers/Sqlsrv/SqlsrvResultAdapter.php b/src/Drivers/Sqlsrv/SqlsrvResultAdapter.php index b92396c4..80029b59 100644 --- a/src/Drivers/Sqlsrv/SqlsrvResultAdapter.php +++ b/src/Drivers/Sqlsrv/SqlsrvResultAdapter.php @@ -52,7 +52,7 @@ public function __destruct() public function seek(int $index): void { - if ($index !== 0 && sqlsrv_num_rows($this->statement) !== 0 && !sqlsrv_fetch($this->statement, SQLSRV_SCROLL_ABSOLUTE, $index)) { + if ($index !== 0 && sqlsrv_num_rows($this->statement) !== 0 && sqlsrv_fetch($this->statement, SQLSRV_SCROLL_ABSOLUTE, $index) !== true) { throw new InvalidArgumentException("Unable to seek in row set to {$index} index."); } $this->index = $index; @@ -81,7 +81,8 @@ public function fetch(): ?array public function getTypes(): array { $types = []; - $fields = sqlsrv_field_metadata($this->statement) ?: []; + $fields = sqlsrv_field_metadata($this->statement); + $fields = $fields === false ? [] : $fields; foreach ($fields as $field) { $nativeType = $field['Type']; $types[(string) $field['Name']] = [ diff --git a/src/IConnection.php b/src/IConnection.php index dfad6cf0..f2c4e989 100644 --- a/src/IConnection.php +++ b/src/IConnection.php @@ -56,7 +56,7 @@ public function getConfig(): array; /** * Executes a query. * @param mixed ...$args - * @phpstan-param array ...$args + * @phpstan-param mixed ...$args * @throws QueryException */ public function query(...$args): Result; diff --git a/src/Platforms/PostgreSqlPlatform.php b/src/Platforms/PostgreSqlPlatform.php index d5b6a492..7a641adc 100644 --- a/src/Platforms/PostgreSqlPlatform.php +++ b/src/Platforms/PostgreSqlPlatform.php @@ -106,7 +106,7 @@ public function getColumns(string $table): array $column->isAutoincrement = (bool) $row->is_autoincrement; $column->isUnsigned = false; $column->isNullable = (bool) $row->is_nullable; - $column->meta = !empty($row->sequence) ? ['sequence' => $row->sequence] : []; + $column->meta = isset($row->sequence) ? ['sequence' => $row->sequence] : []; $columns[$column->name] = $column; } diff --git a/src/QueryBuilder/QueryBuilder.php b/src/QueryBuilder/QueryBuilder.php index c3d735f7..9e07dd60 100644 --- a/src/QueryBuilder/QueryBuilder.php +++ b/src/QueryBuilder/QueryBuilder.php @@ -114,11 +114,11 @@ private function getSqlForSelect(): string 'SELECT ' . ($this->select !== null ? implode(', ', $this->select) : '*') . ' FROM ' . $this->getFromClauses() . ($this->where !== null ? ' WHERE ' . ($this->where) : '') - . ($this->group ? ' GROUP BY ' . implode(', ', $this->group) : '') + . ($this->group !== null ? ' GROUP BY ' . implode(', ', $this->group) : '') . ($this->having !== null ? ' HAVING ' . ($this->having) : '') - . ($this->order ? ' ORDER BY ' . implode(', ', $this->order) : ''); + . ($this->order !== null ? ' ORDER BY ' . implode(', ', $this->order) : ''); - if ($this->limit) { + if ($this->limit !== null) { $query = $this->driver->modifyLimitQuery($query, $this->limit[0], $this->limit[1]); } @@ -131,7 +131,7 @@ private function getFromClauses(): string if ($this->from === null) { throw new InvalidStateException(); } - $query = $this->from[0] . ($this->from[1] ? " AS [{$this->from[1]}]" : ''); + $query = $this->from[0] . ($this->from[1] !== null ? " AS [{$this->from[1]}]" : ''); if ($this->indexHints !== null) { $query .= ' ' . $this->indexHints; @@ -154,7 +154,7 @@ public function getClause(string $part): array throw new InvalidArgumentException("Unknown '$part' clause type."); } - return [$this->$part, $this->args[$part]]; + return [$this->$part, $this->args[$part]]; // @phpstan-ignore-line } @@ -327,9 +327,6 @@ public function select(?string $expression = null, ...$args): self */ public function addSelect(string $expression, ...$args): self { - if (!is_string($expression)) { - throw new InvalidArgumentException('Select expression has to be a string.'); - } $this->dirty(); $this->select[] = $expression; $this->pushArgs('select', $args); @@ -357,7 +354,7 @@ public function where(?string $expression = null, ...$args): self public function andWhere(string $expression, ...$args): self { $this->dirty(); - $this->where = $this->where ? '(' . $this->where . ') AND (' . $expression . ')' : $expression; + $this->where = $this->where !== null ? '(' . $this->where . ') AND (' . $expression . ')' : $expression; $this->pushArgs('where', $args); return $this; } @@ -370,7 +367,7 @@ public function andWhere(string $expression, ...$args): self public function orWhere(string $expression, ...$args): self { $this->dirty(); - $this->where = $this->where ? '(' . $this->where . ') OR (' . $expression . ')' : $expression; + $this->where = $this->where !== null ? '(' . $this->where . ') OR (' . $expression . ')' : $expression; $this->pushArgs('where', $args); return $this; } @@ -422,7 +419,7 @@ public function having(?string $expression = null, ...$args): self public function andHaving(string $expression, ...$args): self { $this->dirty(); - $this->having = $this->having ? '(' . $this->having . ') AND (' . $expression . ')' : $expression; + $this->having = $this->having !== null ? '(' . $this->having . ') AND (' . $expression . ')' : $expression; $this->pushArgs('having', $args); return $this; } @@ -435,7 +432,7 @@ public function andHaving(string $expression, ...$args): self public function orHaving(string $expression, ...$args): self { $this->dirty(); - $this->having = $this->having ? '(' . $this->having . ') OR (' . $expression . ')' : $expression; + $this->having = $this->having !== null ? '(' . $this->having . ') OR (' . $expression . ')' : $expression; $this->pushArgs('having', $args); return $this; } @@ -473,7 +470,7 @@ public function addOrderBy(string $expression, ...$args): self public function limitBy(?int $limit, ?int $offset = null): self { $this->dirty(); - $this->limit = $limit || $offset ? [$limit, $offset] : null; + $this->limit = $limit !== null || $offset !== null ? [$limit, $offset] : null; return $this; } diff --git a/src/Result/Result.php b/src/Result/Result.php index 83fb3b7c..0f8dad24 100644 --- a/src/Result/Result.php +++ b/src/Result/Result.php @@ -108,7 +108,7 @@ public function fetch(): ?Row */ public function fetchField(int $column = 0) { - if ($row = $this->fetch()) { // = intentionally + if (($row = $this->fetch()) !== null) { // = intentionally return $row->getNthField($column); } @@ -168,23 +168,23 @@ protected function initColumnConversions(): void foreach ($types as $key => $typePair) { [$type, $nativeType] = $typePair; - if ($type & IResultAdapter::TYPE_STRING) { + if (($type & IResultAdapter::TYPE_STRING) > 0) { $this->toStringColumns[] = $key; - } elseif ($type & IResultAdapter::TYPE_INT) { + } elseif (($type & IResultAdapter::TYPE_INT) > 0) { $this->toIntColumns[] = $key; - } elseif ($type & IResultAdapter::TYPE_FLOAT) { + } elseif (($type & IResultAdapter::TYPE_FLOAT) > 0) { $this->toFloatColumns[] = $key; - } elseif ($type & IResultAdapter::TYPE_BOOL) { + } elseif (($type & IResultAdapter::TYPE_BOOL) > 0) { $this->toBoolColumns[] = $key; - } elseif ($type & IResultAdapter::TYPE_DATETIME) { + } elseif (($type & IResultAdapter::TYPE_DATETIME) > 0) { $this->toDateTimeColumns[] = $key; } - if ($type & IResultAdapter::TYPE_DRIVER_SPECIFIC) { + if (($type & IResultAdapter::TYPE_DRIVER_SPECIFIC) > 0) { $this->toDriverColumns[] = [$key, $nativeType]; } } diff --git a/src/Result/Row.php b/src/Result/Row.php index f7c96445..825e89e2 100644 --- a/src/Result/Row.php +++ b/src/Result/Row.php @@ -35,7 +35,7 @@ public function toArray(): array public function __get(string $name) { $closest = Typos::getClosest($name, array_keys($this->toArray())); - throw new InvalidArgumentException("Column '$name' does not exist" . ($closest ? ", did you mean '$closest'?" : ".")); + throw new InvalidArgumentException("Column '$name' does not exist" . ($closest !== null ? ", did you mean '$closest'?" : ".")); } @@ -45,7 +45,7 @@ public function __get(string $name) public function getNthField(int $offset) { $slice = array_slice((array) $this, $offset, 1); - if (!$slice) { + if (count($slice) === 0) { throw new InvalidArgumentException("Column '$offset' does not exist."); } return current($slice); diff --git a/src/SqlProcessor.php b/src/SqlProcessor.php index d0f899b1..003f210b 100644 --- a/src/SqlProcessor.php +++ b/src/SqlProcessor.php @@ -108,7 +108,7 @@ public function process(array $args): string $i = $j; $fragments[] = preg_replace_callback( '#%(\??+\w++(?:\[\]){0,2}+)|(%%)|(\[\[)|(\]\])|\[(.+?)\]#S', // %modifier | %% | %[ | %] | [identifier] - function ($matches) use ($args, &$j, $last) { + function ($matches) use ($args, &$j, $last): string { if ($matches[1] !== '') { if ($j === $last) { throw new InvalidArgumentException("Missing query parameter for modifier $matches[0]."); @@ -162,7 +162,7 @@ public function processModifier(string $type, $value): string case 'i': case '?i': - if (!preg_match('#^-?[1-9][0-9]*+\z#', $value)) { + if (preg_match('#^-?[1-9][0-9]*+\z#', $value) !== 1) { break; } return (string) $value; @@ -439,7 +439,7 @@ protected function processSet(string $type, array $value): string */ protected function processMultiValues(string $type, array $value): string { - if (empty($value)) { + if (count($value) === 0) { throw new InvalidArgumentException('Modifier %values[] must contain at least one array element.'); } @@ -448,19 +448,19 @@ protected function processMultiValues(string $type, array $value): string $keys[] = $this->identifierToSql(explode('%', (string) $key, 2)[0]); } foreach ($value as $subValue) { - if (empty($subValue)) { + if (!is_array($subValue) || count($subValue) === 0) { $values[] = '(' . str_repeat('DEFAULT, ', max(count($keys) - 1, 0)) . 'DEFAULT)'; } else { $subValues = []; foreach ($subValue as $_key => $val) { - $key = explode('%', $_key, 2); + $key = explode('%', (string) $_key, 2); $subValues[] = $this->processModifier(isset($key[1]) ? $key[1] : 'any', $val); } $values[] = '(' . implode(', ', $subValues) . ')'; } } - return (!empty($keys) ? '(' . implode(', ', $keys) . ') ' : '') . 'VALUES ' . implode(', ', $values); + return (count($keys) > 0 ? '(' . implode(', ', $keys) . ') ' : '') . 'VALUES ' . implode(', ', $values); } @@ -469,13 +469,13 @@ protected function processMultiValues(string $type, array $value): string */ private function processValues(string $type, array $value): string { - if (empty($value)) { + if (count($value) === 0) { return 'VALUES (DEFAULT)'; } $keys = $values = []; foreach ($value as $_key => $val) { - $key = explode('%', (string) $_key, 2); + $key = explode('%', $_key, 2); $keys[] = $this->identifierToSql($key[0]); $values[] = $this->processModifier(isset($key[1]) ? $key[1] : 'any', $val); } diff --git a/src/Utils/FileImporter.php b/src/Utils/FileImporter.php index 63bdbe96..2214b042 100644 --- a/src/Utils/FileImporter.php +++ b/src/Utils/FileImporter.php @@ -48,7 +48,7 @@ public static function executeFile(IConnection $connection, string $file): int } while ($query != '') { - if (!$offset && preg_match("~^{$space}*DELIMITER\\s+(\\S+)~i", $query, $match)) { + if ($offset === 0 && preg_match("~^{$space}*DELIMITER\\s+(\\S+)~i", $query, $match) === 1) { $delimiter = $match[1]; $query = substr($query, strlen($match[0])); @@ -73,7 +73,7 @@ public static function executeFile(IConnection $connection, string $file): int $offset = 0; } else { // find matching quote or comment end - while (preg_match('(' . ($found == '/*' ? '\*/' : ($found == '[' ? ']' : (preg_match('~^-- |^#~', $found) ? "\n" : preg_quote($found) . "|\\\\."))) . '|$)s', $query, $match, PREG_OFFSET_CAPTURE, $offset)) { //! respect sql_mode NO_BACKSLASH_ESCAPES + while (preg_match('(' . ($found == '/*' ? '\*/' : ($found == '[' ? ']' : (preg_match('~^-- |^#~', $found) === 1 ? "\n" : preg_quote($found) . "|\\\\."))) . '|$)s', $query, $match, PREG_OFFSET_CAPTURE, $offset) === 1) { //! respect sql_mode NO_BACKSLASH_ESCAPES $s = $match[0][0]; /** @var int $offset */ $offset = $match[0][1] + strlen($s); diff --git a/src/Utils/SqlHighlighter.php b/src/Utils/SqlHighlighter.php index 1cb62b05..d054973c 100644 --- a/src/Utils/SqlHighlighter.php +++ b/src/Utils/SqlHighlighter.php @@ -3,6 +3,12 @@ namespace Nextras\Dbal\Utils; +use function assert; +use function htmlspecialchars; +use function preg_replace_callback; +use function trim; + + /** * @internal */ @@ -21,12 +27,14 @@ public static function highlight(string $sql): string $sql = preg_replace_callback("#(/\\*.+?\\*/)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is", function ( $matches ) { - if (!empty($matches[1])) { // comment + if (isset($matches[1])) { // comment return '' . $matches[1] . ''; - } elseif (!empty($matches[2])) { // most important keywords + } elseif (isset($matches[2])) { // most important keywords return '' . $matches[2] . ''; - } elseif (!empty($matches[3])) { // other keywords + } elseif (isset($matches[3])) { // other keywords return '' . $matches[3] . ''; + } else { + return $matches[0]; } }, $sql); assert($sql !== null);