diff --git a/.phpstan.neon b/.phpstan.neon new file mode 100644 index 00000000..e61e6961 --- /dev/null +++ b/.phpstan.neon @@ -0,0 +1,3 @@ +parameters: + ignoreErrors: + - '#(sqlsrv|SQLSRV).+ not found\.#i' diff --git a/.travis.yml b/.travis.yml index 71e77cc9..54d315eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ language: php php: - 7.0 - 7.1 + - 7.2 matrix: fast_finish: true @@ -21,8 +22,8 @@ before_script: # Create php.ini & databases.ini - cp ./tests/php.unix-sample.ini ./tests/php.ini - - if [ "$TRAVIS_PHP_VERSION" == "7.0" ]; then cat ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini >> ./tests/php.ini; fi - - if [ "$TRAVIS_PHP_VERSION" == "7.0" ]; then NTESTER_FLAGS="--coverage ./coverage.xml --coverage-src ./src"; else TESTER_FLAGS=""; fi + - if [ "$TRAVIS_PHP_VERSION" == "7.2" ]; then cat ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini >> ./tests/php.ini; fi + - if [ "$TRAVIS_PHP_VERSION" == "7.2" ]; then NTESTER_FLAGS="--coverage ./coverage.xml --coverage-src ./src"; else TESTER_FLAGS=""; fi - cp ./tests/databases.sample.ini ./tests/databases.ini # Create MySQL & Postgre database @@ -37,12 +38,14 @@ before_script: - phpenv config-rm xdebug.ini - travis_retry composer update --no-interaction -script: ./tests/run.sh -s $NTESTER_FLAGS ./tests/cases +script: + - ./tests/run.sh -s $NTESTER_FLAGS ./tests/cases + - if [ "$TRAVIS_PHP_VERSION" == "7.2" ]; then vendor/bin/phpstan.phar analyse -l 7 -c .phpstan.neon src; fi after_script: - - if [ "$TRAVIS_PHP_VERSION" == "7.0" ]; then - wget https://github.com/satooshi/php-coveralls/releases/download/v1.0.1/coveralls.phar - && php coveralls.phar --verbose --config tests/.coveralls.yml + - if [ "$TRAVIS_PHP_VERSION" == "7.2" ]; then + wget https://github.com/satooshi/php-coveralls/releases/download/v2.0.0/php-coveralls.phar + && php php-coveralls.phar --verbose --config tests/.coveralls.yml || true; fi diff --git a/composer.json b/composer.json index 7b521244..cd913e43 100644 --- a/composer.json +++ b/composer.json @@ -15,11 +15,12 @@ "php": ">=7.0" }, "require-dev": { - "nette/tester": "~1.7", - "nette/caching": "~2.2", "mockery/mockery": "~1.0@dev", - "tracy/tracy": "~2.3", - "nette/di": "~2.3" + "nette/tester": "~2.0.0", + "nette/caching": "~2.2", + "nette/di": "~2.3", + "phpstan/phpstan-shim": "~0.9.1", + "tracy/tracy": "~2.3" }, "autoload": { "psr-4": { "Nextras\\Dbal\\": "src/" }, diff --git a/src/Bridges/NetteTracy/ConnectionPanel.php b/src/Bridges/NetteTracy/ConnectionPanel.php index 81342230..83384ff5 100644 --- a/src/Bridges/NetteTracy/ConnectionPanel.php +++ b/src/Bridges/NetteTracy/ConnectionPanel.php @@ -84,9 +84,15 @@ public function getPanel() { $count = $this->count; $queries = $this->queries; - $queries = array_map(function($row) { + $queries = array_map(function ($row) { try { - $row[4] = $this->doExplain ? $this->connection->getDriver()->query('EXPLAIN ' . $row['1'])->fetchAll() : null; + $row[4] = null; + if ($this->doExplain) { + $explain = $this->connection->getDriver()->query('EXPLAIN ' . $row['1']); + if ($explain !== null) { + $row[4] = $explain->fetchAll(); + } + } } catch (\Throwable $e) { $row[4] = null; $row[3] = null; // rows count is also irrelevant @@ -109,8 +115,8 @@ public static function highlight($sql) static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|IGNORE|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|[RI]?LIKE|REGEXP|TRUE|FALSE'; $sql = " $sql "; - $sql = htmlSpecialChars($sql, ENT_IGNORE, 'UTF-8'); - $sql = preg_replace_callback("#(/\\*.+?\\*/)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is", function($matches) { + $sql = htmlspecialchars($sql, ENT_IGNORE, 'UTF-8'); + $sql = preg_replace_callback("#(/\\*.+?\\*/)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is", function ($matches) { if (!empty($matches[1])) { // comment return '' . $matches[1] . ''; } elseif (!empty($matches[2])) { // most important keywords diff --git a/src/Drivers/IDriver.php b/src/Drivers/IDriver.php index e220f046..da0c09a7 100644 --- a/src/Drivers/IDriver.php +++ b/src/Drivers/IDriver.php @@ -30,12 +30,14 @@ interface IDriver /** * Connects the driver to database. + * @internal */ public function connect(array $params, callable $loggedQueryCallback); /** * Disconnects from the database. + * @internal */ public function disconnect(); @@ -54,7 +56,8 @@ public function getResourceHandle(); /** - * Runs query and returns the result. Returns null if query does not select data. + * Runs query and returns a result. Returns a null if the query does not select any data. + * @internal * @return Result|null */ public function query(string $query); @@ -62,6 +65,7 @@ public function query(string $query); /** * Returns the last inserted id. + * @internal * @return mixed */ public function getLastInsertedId(string $sequenceName = null); @@ -69,6 +73,7 @@ public function getLastInsertedId(string $sequenceName = null); /** * Returns number of affected rows. + * @internal */ public function getAffectedRows(): int; @@ -93,15 +98,20 @@ public function getServerVersion(): string; /** * Pings server. + * @internal */ public function ping(): bool; + /** + * @internal + */ public function setTransactionIsolationLevel(int $level); /** * Begins a transaction. + * @internal * @throws DriverException */ public function beginTransaction(); @@ -109,6 +119,7 @@ public function beginTransaction(); /** * Commits the current transaction. + * @internal * @throws DriverException */ public function commitTransaction(); @@ -116,6 +127,7 @@ public function commitTransaction(); /** * Rollbacks the current transaction. + * @internal * @throws DriverException */ public function rollbackTransaction(); @@ -123,6 +135,7 @@ public function rollbackTransaction(); /** * Creates a savepoint. + * @internal * @throws DriverException * @return void */ @@ -131,6 +144,7 @@ public function createSavepoint(string $name); /** * Releases the savepoint. + * @internal * @throws DriverException */ public function releaseSavepoint(string $name); @@ -138,6 +152,7 @@ public function releaseSavepoint(string $name); /** * Rollbacks the savepoint. + * @internal * @throws DriverException */ public function rollbackSavepoint(string $name); diff --git a/src/Drivers/Mysqli/MysqliDriver.php b/src/Drivers/Mysqli/MysqliDriver.php index b00065c4..652716a3 100644 --- a/src/Drivers/Mysqli/MysqliDriver.php +++ b/src/Drivers/Mysqli/MysqliDriver.php @@ -28,7 +28,7 @@ class MysqliDriver implements IDriver { - /** @var mysqli */ + /** @var mysqli|null */ private $connection; /** @var DateTimeZone Timezone for database connection. */ @@ -86,7 +86,10 @@ public function isConnected(): bool } - public function getResourceHandle(): mysqli + /** + * @return mysqli|null + */ + public function getResourceHandle() { return $this->connection; } @@ -94,6 +97,8 @@ public function getResourceHandle(): mysqli public function query(string $query) { + assert($this->connection !== null); + $time = microtime(true); $result = @$this->connection->query($query); $this->timeTaken = microtime(true) - $time; @@ -117,12 +122,14 @@ public function query(string $query) public function getLastInsertedId(string $sequenceName = null) { + assert($this->connection !== null); return $this->connection->insert_id; } public function getAffectedRows(): int { + assert($this->connection !== null); return $this->connection->affected_rows; } @@ -141,6 +148,7 @@ public function createPlatform(Connection $connection): IPlatform public function getServerVersion(): string { + assert($this->connection !== null); $version = $this->connection->server_version; $majorVersion = floor($version / 10000); $minorVersion = floor(($version - $majorVersion * 10000) / 100); @@ -151,6 +159,7 @@ public function getServerVersion(): string public function ping(): bool { + assert($this->connection !== null); return $this->connection->ping(); } @@ -208,6 +217,8 @@ public function rollbackSavepoint(string $name) protected function processInitialSettings(array $params) { + assert($this->connection !== null); + if (isset($params['charset'])) { $charset = $params['charset']; } elseif (($version = $this->getServerVersion()) && version_compare($version, '5.5.3', '>=')) { @@ -259,6 +270,7 @@ public function convertToPhp(string $value, $nativeType) public function convertStringToSql(string $value): string { + assert($this->connection !== null); return "'" . $this->connection->escape_string($value) . "'"; } @@ -326,6 +338,7 @@ public function convertDateIntervalToSql(\DateInterval $value): string public function convertBlobToSql(string $value): string { + assert($this->connection !== null); return "_binary'" . $this->connection->escape_string($value) . "'"; } diff --git a/src/Drivers/Pgsql/PgsqlDriver.php b/src/Drivers/Pgsql/PgsqlDriver.php index 88f70c5a..b65bb69b 100644 --- a/src/Drivers/Pgsql/PgsqlDriver.php +++ b/src/Drivers/Pgsql/PgsqlDriver.php @@ -27,7 +27,7 @@ class PgsqlDriver implements IDriver { - /** @var resource */ + /** @var resource|null */ private $connection; /** @var DateTimeZone Timezone for database connection. */ diff --git a/src/Drivers/Sqlsrv/SqlsrvDriver.php b/src/Drivers/Sqlsrv/SqlsrvDriver.php index 6c37724b..6b9ee8c6 100644 --- a/src/Drivers/Sqlsrv/SqlsrvDriver.php +++ b/src/Drivers/Sqlsrv/SqlsrvDriver.php @@ -28,7 +28,7 @@ class SqlsrvDriver implements IDriver { - /** @var resource */ + /** @var resource|null */ private $connection; /** @var callable */ @@ -76,7 +76,7 @@ public function connect(array $params, callable $onQueryCallback) } } - if (isset($connectionInfo['ReturnDatesAsStrings'])) { + if (isset($connectionOptions['ReturnDatesAsStrings'])) { throw new NotSupportedException("SqlsrvDriver does not allow to modify 'ReturnDatesAsStrings' parameter."); } $connectionOptions['ReturnDatesAsStrings'] = true; diff --git a/src/Drivers/Sqlsrv/SqlsrvResultAdapter.php b/src/Drivers/Sqlsrv/SqlsrvResultAdapter.php index 06685b26..fb277112 100644 --- a/src/Drivers/Sqlsrv/SqlsrvResultAdapter.php +++ b/src/Drivers/Sqlsrv/SqlsrvResultAdapter.php @@ -26,7 +26,7 @@ class SqlsrvResultAdapter implements IResultAdapter SqlsrvResultTypes::TYPE_DATETIMEOFFSET => self::TYPE_DRIVER_SPECIFIC, ]; - /** @var int */ + /** @var int|null */ private $index; /** @var resource */ diff --git a/src/QueryBuilder/QueryBuilder.php b/src/QueryBuilder/QueryBuilder.php index c85bcc20..b7a42b73 100644 --- a/src/QueryBuilder/QueryBuilder.php +++ b/src/QueryBuilder/QueryBuilder.php @@ -47,13 +47,13 @@ class QueryBuilder /** @var array|null */ private $join; - /** @var array|null */ + /** @var string|null */ private $where; /** @var array|null */ private $group; - /** @var array|null */ + /** @var string|null */ private $having; /** @var array|null */ @@ -62,7 +62,7 @@ class QueryBuilder /** @var array|null */ private $limit; - /** @var string */ + /** @var string|null */ private $generatedSql; @@ -263,9 +263,6 @@ public function andWhere(string $expression, ...$args): self /** * Adds expression with OR to WHERE clause. - * @param string $expression - * @param mixed ...$arg - * @return self */ public function orWhere(string $expression, ...$args): self {