diff --git a/README.md b/README.md index d1efc1e..97cb699 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # Icinga PHP Library - SQL abstraction layer -![Build Status](https://github.com/Icinga/ipl-sql/workflows/PHP%20Tests/badge.svg?branch=main) - The package `ipl\Sql` provides a [database connection abstraction](#sql-connection) and an [SQL query abstraction layer](#sql-queries) for building SQL queries via an OOP API. diff --git a/phpstan.neon b/phpstan.neon index f58b54c..5ee24f4 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -11,9 +11,6 @@ parameters: paths: - src - scanDirectories: - - vendor - universalObjectCratesClasses: # to ignore magic property errors - ipl\Sql\Config diff --git a/src/Adapter/BaseAdapter.php b/src/Adapter/BaseAdapter.php index f062f63..29994f3 100644 --- a/src/Adapter/BaseAdapter.php +++ b/src/Adapter/BaseAdapter.php @@ -21,13 +21,13 @@ abstract class BaseAdapter implements Adapter * * @var array */ - protected $quoteCharacter = ['"', '"']; + protected array $quoteCharacter = ['"', '"']; /** @var string Character to use for escaping quote characters */ - protected $escapeCharacter = '\\"'; + protected string $escapeCharacter = '\\"'; /** @var array Default PDO connect options */ - protected $options = [ + protected array $options = [ PDO::ATTR_CASE => PDO::CASE_NATURAL, PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, @@ -35,7 +35,7 @@ abstract class BaseAdapter implements Adapter PDO::ATTR_STRINGIFY_FETCHES => false ]; - public function getDsn(Config $config) + public function getDsn(Config $config): string { $dsn = "{$config->db}:"; @@ -50,7 +50,7 @@ public function getDsn(Config $config) return $dsn . implode(';', $parts); } - public function getOptions(Config $config) + public function getOptions(Config $config): array { if (is_array($config->options)) { return $config->options + $this->options; @@ -59,12 +59,12 @@ public function getOptions(Config $config) return $this->options; } - public function setClientTimezone(Connection $db) + public function setClientTimezone(Connection $db): static { return $this; } - public function quoteIdentifier($identifiers) + public function quoteIdentifier(array|string $identifiers): string { if (is_string($identifiers)) { $identifiers = explode('.', $identifiers); @@ -83,7 +83,7 @@ public function quoteIdentifier($identifiers) return implode('.', $identifiers); } - public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder) + public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder): static { $queryBuilder->on(QueryBuilder::ON_ASSEMBLE_SELECT, function (Select $select): void { if ($select->hasOrderBy()) { @@ -105,7 +105,7 @@ public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder) return $this; } - protected function getTimezoneOffset() + protected function getTimezoneOffset(): string { $tz = new DateTimeZone(date_default_timezone_get()); $offset = $tz->getOffset(new DateTime()); diff --git a/src/Adapter/Mssql.php b/src/Adapter/Mssql.php index c9f11ce..55d6c95 100644 --- a/src/Adapter/Mssql.php +++ b/src/Adapter/Mssql.php @@ -10,11 +10,11 @@ class Mssql extends BaseAdapter { - protected $quoteCharacter = ['[', ']']; + protected array $quoteCharacter = ['[', ']']; - protected $escapeCharacter = '[[]'; + protected string $escapeCharacter = '[[]'; - public function getDsn(Config $config) + public function getDsn(Config $config): string { $drivers = array_intersect(['sqlsrv', 'dblib', 'mssql', 'sybase'], PDO::getAvailableDrivers()); @@ -62,7 +62,7 @@ public function getDsn(Config $config) return $dsn; } - public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder) + public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder): static { parent::registerQueryBuilderCallbacks($queryBuilder); diff --git a/src/Adapter/Mysql.php b/src/Adapter/Mysql.php index 2421cae..19683b3 100644 --- a/src/Adapter/Mysql.php +++ b/src/Adapter/Mysql.php @@ -4,51 +4,57 @@ use ipl\Sql\Config; use ipl\Sql\Connection; -use PDO; class Mysql extends BaseAdapter { - protected $quoteCharacter = ['`', '`']; + protected array $quoteCharacter = ['`', '`']; - protected $escapeCharacter = '``'; + protected string $escapeCharacter = '``'; - public function setClientTimezone(Connection $db) + public function setClientTimezone(Connection $db): static { $db->exec('SET time_zone = ' . $db->quote($this->getTimezoneOffset())); return $this; } - public function getOptions(Config $config) + public function getOptions(Config $config): array { $options = parent::getOptions($config); + // In PHP 8.5+, driver-specific constants of the PDO class are deprecated, + // but the replacements are only available since php 8.4 + if (version_compare(PHP_VERSION, '8.4.0', '<')) { + $mysqlConstantPrefix = 'PDO::MYSQL_ATTR_'; + } else { + $mysqlConstantPrefix = 'Pdo\Mysql::ATTR_'; + } if (! empty($config->useSsl)) { if (! empty($config->sslKey)) { - $options[PDO::MYSQL_ATTR_SSL_KEY] = $config->sslKey; + $options[constant($mysqlConstantPrefix . 'SSL_KEY')] = $config->sslKey; } if (! empty($config->sslCert)) { - $options[PDO::MYSQL_ATTR_SSL_CERT] = $config->sslCert; + $options[constant($mysqlConstantPrefix . 'SSL_CERT')] = $config->sslCert; } if (! empty($config->sslCa)) { - $options[PDO::MYSQL_ATTR_SSL_CA] = $config->sslCa; + $options[constant($mysqlConstantPrefix . 'SSL_CA')] = $config->sslCa; } if (! empty($config->sslCapath)) { - $options[PDO::MYSQL_ATTR_SSL_CAPATH] = $config->sslCapath; + $options[constant($mysqlConstantPrefix . 'SSL_CAPATH')] = $config->sslCapath; } if (! empty($config->sslCipher)) { - $options[PDO::MYSQL_ATTR_SSL_CIPHER] = $config->sslCipher; + $options[constant($mysqlConstantPrefix . 'SSL_CIPHER')] = $config->sslCipher; } if ( - defined('PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT') + defined($mysqlConstantPrefix . 'SSL_VERIFY_SERVER_CERT') && ! empty($config->sslDoNotVerifyServerCert) ) { - $options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false; + $options[constant($mysqlConstantPrefix . 'SSL_VERIFY_SERVER_CERT')] = false; } } diff --git a/src/Adapter/Oracle.php b/src/Adapter/Oracle.php index de0aee5..a6c5aa0 100644 --- a/src/Adapter/Oracle.php +++ b/src/Adapter/Oracle.php @@ -7,7 +7,7 @@ class Oracle extends BaseAdapter { - public function getDsn(Config $config) + public function getDsn(Config $config): string { $dsn = 'oci:dbname='; @@ -30,7 +30,7 @@ public function getDsn(Config $config) return $dsn; } - public function setClientTimezone(Connection $db) + public function setClientTimezone(Connection $db): static { $db->prepexec('ALTER SESSION SET TIME_ZONE = ?', [$this->getTimezoneOffset()]); diff --git a/src/Adapter/Pgsql.php b/src/Adapter/Pgsql.php index 18bf15d..871d059 100644 --- a/src/Adapter/Pgsql.php +++ b/src/Adapter/Pgsql.php @@ -6,7 +6,7 @@ class Pgsql extends BaseAdapter { - public function setClientTimezone(Connection $db) + public function setClientTimezone(Connection $db): static { $db->exec(sprintf('SET TIME ZONE INTERVAL %s HOUR TO MINUTE', $db->quote($this->getTimezoneOffset()))); diff --git a/src/Adapter/Sqlite.php b/src/Adapter/Sqlite.php index 9f4e209..e040b6f 100644 --- a/src/Adapter/Sqlite.php +++ b/src/Adapter/Sqlite.php @@ -6,7 +6,7 @@ class Sqlite extends BaseAdapter { - public function getDsn(Config $config) + public function getDsn(Config $config): string { return "sqlite:{$config->dbname}"; } diff --git a/src/CommonTableExpression.php b/src/CommonTableExpression.php index 596ec39..5877fbf 100644 --- a/src/CommonTableExpression.php +++ b/src/CommonTableExpression.php @@ -17,21 +17,21 @@ trait CommonTableExpression * * @var array[] */ - protected $with = []; + protected array $with = []; - public function getWith() + public function getWith(): array { return $this->with; } - public function with(Select $query, $alias, $recursive = false) + public function with(Select $query, string $alias, bool $recursive = false): static { $this->with[] = [$query, $alias, $recursive]; return $this; } - public function resetWith() + public function resetWith(): static { $this->with = []; @@ -43,7 +43,7 @@ public function resetWith() * * Shall be called by using classes in their __clone() */ - protected function cloneCte() + protected function cloneCte(): void { foreach ($this->with as &$cte) { $cte[0] = clone $cte[0]; diff --git a/src/CommonTableExpressionInterface.php b/src/CommonTableExpressionInterface.php index 7e93bc8..9a528bd 100644 --- a/src/CommonTableExpressionInterface.php +++ b/src/CommonTableExpressionInterface.php @@ -17,7 +17,7 @@ interface CommonTableExpressionInterface * * @return array[] */ - public function getWith(); + public function getWith(): array; /** * Add a CTE @@ -28,12 +28,12 @@ public function getWith(); * * @return $this */ - public function with(Select $query, $alias, $recursive = false); + public function with(Select $query, string $alias, bool $recursive = false): static; /** * Reset all CTEs * * @return $this */ - public function resetWith(); + public function resetWith(): static; } diff --git a/src/Compat/FilterProcessor.php b/src/Compat/FilterProcessor.php index 1ed1c3d..457b712 100644 --- a/src/Compat/FilterProcessor.php +++ b/src/Compat/FilterProcessor.php @@ -13,7 +13,7 @@ class FilterProcessor { - public static function assembleFilter(Filter\Rule $filter, $level = 0) + public static function assembleFilter(Filter\Rule $filter, int $level = 0): ?array { $condition = null; @@ -60,7 +60,7 @@ public static function assembleFilter(Filter\Rule $filter, $level = 0) return $condition; } - public static function assemblePredicate(Filter\Condition $filter) + public static function assemblePredicate(Filter\Condition $filter): array { $column = $filter->getColumn(); $expression = $filter->getValue(); diff --git a/src/Config.php b/src/Config.php index 5fa103e..e4fdb49 100644 --- a/src/Config.php +++ b/src/Config.php @@ -2,34 +2,31 @@ namespace ipl\Sql; -use InvalidArgumentException; use ipl\Stdlib\Str; use OutOfRangeException; -use function ipl\Stdlib\get_php_type; - /** * SQL connection configuration */ class Config { - /** @var string Type of the DBMS */ - public $db; + /** @var ?string Type of the DBMS */ + public ?string $db = null; - /** @var string Database host */ - public $host; + /** @var ?string Database host */ + public ?string $host = null; - /** @var int Database port */ - public $port; + /** @var string|int|null Database port */ + public string|int|null $port = null; - /** @var string Database name */ - public $dbname; + /** @var ?string Database name */ + public ?string $dbname = null; - /** @var string Username to use for authentication */ - public $username; + /** @var ?string Username to use for authentication */ + public ?string $username = null; - /** @var string Password to use for authentication */ - public $password; + /** @var ?string Password to use for authentication */ + public ?string $password = null; /** * Character set for the connection @@ -38,7 +35,7 @@ class Config * * @var string */ - public $charset; + public string $charset = ''; /** * PDO connect options @@ -48,10 +45,10 @@ class Config * * @var array */ - public $options; + public array $options = []; /** @var array Extra settings e.g. for SQL SSL connections */ - protected $extraSettings = []; + protected array $extraSettings = []; /** * Create a new SQL connection configuration from the given configuration key-value pairs @@ -59,19 +56,9 @@ class Config * Keys will be converted to camelCase, e.g. use_ssl → useSsl. * * @param iterable $config Configuration key-value pairs - * - * @throws InvalidArgumentException If $config is not iterable */ - public function __construct($config) + public function __construct(iterable $config) { - if (! is_iterable($config)) { - throw new InvalidArgumentException(sprintf( - '%s expects parameter one to be iterable, got %s instead', - __METHOD__, - get_php_type($config) - )); - } - foreach ($config as $key => $value) { $key = Str::camel($key); $this->$key = $value; diff --git a/src/Connection.php b/src/Connection.php index 9480fe7..40b41d3 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -4,6 +4,7 @@ use BadMethodCallException; use Exception; +use Generator; use InvalidArgumentException; use ipl\Sql\Contract\Adapter; use ipl\Sql\Contract\Quoter; @@ -11,6 +12,7 @@ use LogicException; use PDO; use PDOStatement; +use Throwable; /** * Connection to a SQL database using the native PDO for database access @@ -20,27 +22,27 @@ class Connection implements Quoter use Plugins; /** @var Config */ - protected $config; + protected Config $config; /** @var ?PDO */ - protected $pdo; + protected ?PDO $pdo = null; - /** @var QueryBuilder */ - protected $queryBuilder; + /** @var ?QueryBuilder */ + protected ?QueryBuilder $queryBuilder = null; /** @var Adapter */ - protected $adapter; + protected Adapter $adapter; /** * Create a new database connection using the given config for initialising the options for the connection * * {@link init()} is called after construction. * - * @param Config|iterable $config + * @param iterable|Config $config * * @throws InvalidArgumentException If there's no adapter for the given database available */ - public function __construct($config) + public function __construct(iterable|Config $config) { $config = $config instanceof Config ? $config : new Config($config); @@ -69,7 +71,7 @@ public function __construct($config) * @throws BadMethodCallException If the called method does not exist * */ - public function __call($name, array $arguments) + public function __call(string $name, array $arguments) { $this->connect(); @@ -88,7 +90,7 @@ public function __call($name, array $arguments) * * If you have to adjust the connection after construction, override this method. */ - public function init() + public function init(): void { } @@ -97,7 +99,7 @@ public function init() * * @return Adapter */ - public function getAdapter() + public function getAdapter(): Adapter { return $this->adapter; } @@ -107,7 +109,7 @@ public function getAdapter() * * @return Config */ - public function getConfig() + public function getConfig(): Config { return $this->config; } @@ -117,7 +119,7 @@ public function getConfig() * * @return QueryBuilder */ - public function getQueryBuilder() + public function getQueryBuilder(): QueryBuilder { if ($this->queryBuilder === null) { $this->queryBuilder = new QueryBuilder($this->adapter); @@ -134,7 +136,7 @@ public function getQueryBuilder() * * @return PDO */ - protected function createPdoAdapter() + protected function createPdoAdapter(): PDO { $adapter = $this->getAdapter(); @@ -153,7 +155,7 @@ protected function createPdoAdapter() * * @return $this */ - public function connect() + public function connect(): static { if ($this->pdo !== null) { return $this; @@ -175,7 +177,7 @@ public function connect() * * @return $this */ - public function disconnect() + public function disconnect(): static { $this->pdo = null; @@ -189,11 +191,11 @@ public function disconnect() * * @return bool */ - public function ping($reconnect = true) + public function ping(bool $reconnect = true): bool { try { $this->query('SELECT 1')->closeCursor(); - } catch (Exception $e) { + } catch (Throwable) { if (! $reconnect) { return false; } @@ -210,11 +212,11 @@ public function ping($reconnect = true) * Fetch and return all result rows as sequential array * * @param Select|string $stmt The SQL statement to prepare and execute. - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * * @return array */ - public function fetchAll($stmt, array $values = null) + public function fetchAll(Select|string $stmt, ?array $values = null): array { return $this->prepexec($stmt, $values) ->fetchAll(); @@ -224,11 +226,11 @@ public function fetchAll($stmt, array $values = null) * Fetch and return the first column of all result rows as sequential array * * @param Select|string $stmt The SQL statement to prepare and execute. - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * * @return array */ - public function fetchCol($stmt, array $values = null) + public function fetchCol(Select|string $stmt, ?array $values = null): array { return $this->prepexec($stmt, $values) ->fetchAll(PDO::FETCH_COLUMN, 0); @@ -238,11 +240,11 @@ public function fetchCol($stmt, array $values = null) * Fetch and return the first row of the result rows * * @param Select|string $stmt The SQL statement to prepare and execute. - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * - * @return array + * @return mixed */ - public function fetchOne($stmt, array $values = null) + public function fetchOne(Select|string $stmt, ?array $values = null): mixed { return $this->prepexec($stmt, $values) ->fetch(); @@ -251,7 +253,7 @@ public function fetchOne($stmt, array $values = null) /** * Alias of {@link fetchOne()} */ - public function fetchRow($stmt, array $values = null) + public function fetchRow(Select|string $stmt, ?array $values = null): mixed { return $this->prepexec($stmt, $values) ->fetch(); @@ -263,11 +265,11 @@ public function fetchRow($stmt, array $values = null) * First column is the key and the second column is the value. * * @param Select|string $stmt The SQL statement to prepare and execute. - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * * @return array */ - public function fetchPairs($stmt, array $values = null) + public function fetchPairs(Select|string $stmt, ?array $values = null): array { return $this->prepexec($stmt, $values) ->fetchAll(PDO::FETCH_KEY_PAIR); @@ -277,11 +279,11 @@ public function fetchPairs($stmt, array $values = null) * Fetch and return the first column of the first result row * * @param Select|string $stmt The SQL statement to prepare and execute. - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * - * @return string + * @return mixed */ - public function fetchScalar($stmt, array $values = null) + public function fetchScalar(Select|string $stmt, ?array $values = null): mixed { return $this->prepexec($stmt, $values) ->fetchColumn(0); @@ -295,9 +297,9 @@ public function fetchScalar($stmt, array $values = null) * @param Select|string $stmt The SQL statement to prepare and execute. * @param mixed ...$args Values to bind to the statement, fetch mode for the statement, fetch mode options * - * @return \Generator + * @return Generator */ - public function yieldAll($stmt, ...$args) + public function yieldAll(Select|string $stmt, ...$args): Generator { $values = null; @@ -343,11 +345,11 @@ public function yieldAll($stmt, ...$args) * Yield the first column of each result row * * @param Select|string $stmt The SQL statement to prepare and execute - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * - * @return \Generator + * @return Generator */ - public function yieldCol($stmt, array $values = null) + public function yieldCol(Select|string $stmt, ?array $values = null): Generator { $sth = $this->prepexec($stmt, $values); @@ -362,18 +364,18 @@ public function yieldCol($stmt, array $values = null) * Yield key-value pairs with the first column as key and the second column as value for each result row * * @param Select|string $stmt The SQL statement to prepare and execute - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * - * @return \Generator + * @return Generator */ - public function yieldPairs($stmt, array $values = null) + public function yieldPairs(Select|string $stmt, ?array $values = null): Generator { $sth = $this->prepexec($stmt, $values); $sth->setFetchMode(PDO::FETCH_NUM); foreach ($sth as $row) { - list($key, $value) = $row; + [$key, $value] = $row; yield $key => $value; } @@ -382,8 +384,8 @@ public function yieldPairs($stmt, array $values = null) /** * Prepare and execute the given statement * - * @param Delete|Insert|Select|Update|string $stmt The SQL statement to prepare and execute - * @param string|array $values Values to bind to the statement, if any + * @param Delete|Insert|Select|Update|string $stmt The SQL statement to prepare and execute + * @param string|array $values Values to bind to the statement, if any * * @return PDOStatement */ @@ -394,7 +396,7 @@ public function prepexec($stmt, $values = null) } if (is_object($stmt)) { - list($stmt, $values) = $this->getQueryBuilder()->assemble($stmt); + [$stmt, $values] = $this->getQueryBuilder()->assemble($stmt); } $this->connect(); @@ -412,9 +414,9 @@ public function prepexec($stmt, $values = null) * * @return PDOStatement */ - public function select(Select $select) + public function select(Select $select): PDOStatement { - list($stmt, $values) = $this->getQueryBuilder()->assembleSelect($select); + [$stmt, $values] = $this->getQueryBuilder()->assembleSelect($select); return $this->prepexec($stmt, $values); } @@ -422,7 +424,7 @@ public function select(Select $select) /** * Insert a table row with the specified data * - * @param string $table The table to insert data into. The table specification must be in + * @param string $table The table to insert data into. The table specification must be in * one of the following formats: 'table' or 'schema.table' * @param iterable $data Row data in terms of column-value pairs * @@ -430,7 +432,7 @@ public function select(Select $select) * * @throws InvalidArgumentException If data type is invalid */ - public function insert($table, $data) + public function insert(string $table, iterable $data): PDOStatement { $insert = (new Insert()) ->into($table) @@ -461,20 +463,24 @@ public function lastInsertId(?string $name = null): false|string /** * Update table rows with the specified data, optionally based on a given condition * - * @param string|array $table The table to update. The table specification must be in one of + * @param array|string $table The table to update. The table specification must be in one of * the following formats: * 'table', 'table alias', ['alias' => 'table'] - * @param iterable $data The columns to update in terms of column-value pairs - * @param mixed $condition The WHERE condition - * @param string $operator The operator to combine multiple conditions with, + * @param iterable $data The columns to update in terms of column-value pairs + * @param array|string|null $condition The WHERE condition + * @param string $operator The operator to combine multiple conditions with, * if the condition is in the array format * * @return PDOStatement * * @throws InvalidArgumentException If data type is invalid */ - public function update($table, $data, $condition = null, $operator = Sql::ALL) - { + public function update( + array|string $table, + iterable $data, + array|string|null $condition = null, + string $operator = Sql::ALL + ): PDOStatement { $update = (new Update()) ->table($table) ->set($data); @@ -489,16 +495,19 @@ public function update($table, $data, $condition = null, $operator = Sql::ALL) /** * Delete table rows, optionally based on a given condition * - * @param string|array $table The table to delete data from. The table specification must be in one of the + * @param array|string $table The table to delete data from. The table specification must be in one of the * following formats: 'table', 'table alias', ['alias' => 'table'] - * @param mixed $condition The WHERE condition - * @param string $operator The operator to combine multiple conditions with, + * @param array|string|null $condition The WHERE condition + * @param string $operator The operator to combine multiple conditions with, * if the condition is in the array format * * @return PDOStatement */ - public function delete($table, $condition = null, $operator = Sql::ALL) - { + public function delete( + array|string $table, + array|string|null $condition = null, + string $operator = Sql::ALL + ): PDOStatement { $delete = (new Delete()) ->from($table); @@ -514,7 +523,7 @@ public function delete($table, $condition = null, $operator = Sql::ALL) * * @return bool Whether the transaction was started successfully */ - public function beginTransaction() + public function beginTransaction(): bool { $this->connect(); @@ -526,7 +535,7 @@ public function beginTransaction() * * @return bool Whether the transaction was committed successfully */ - public function commitTransaction() + public function commitTransaction(): bool { return $this->pdo->commit(); } @@ -536,7 +545,7 @@ public function commitTransaction() * * @return bool Whether the transaction was rolled back successfully */ - public function rollBackTransaction() + public function rollBackTransaction(): bool { return $this->pdo->rollBack(); } @@ -551,7 +560,7 @@ public function rollBackTransaction() * * @throws Exception If an error occurs when running the callback */ - public function transaction(callable $callback) + public function transaction(callable $callback): mixed { $this->beginTransaction(); @@ -567,8 +576,8 @@ public function transaction(callable $callback) return $result; } - public function quoteIdentifier($identifier) + public function quoteIdentifier(array|string $identifiers): string { - return $this->getAdapter()->quoteIdentifier($identifier); + return $this->getAdapter()->quoteIdentifier($identifiers); } } diff --git a/src/Contract/Adapter.php b/src/Contract/Adapter.php index 6142626..4be8ea7 100644 --- a/src/Contract/Adapter.php +++ b/src/Contract/Adapter.php @@ -15,7 +15,7 @@ interface Adapter extends Quoter * * @return string */ - public function getDsn(Config $config); + public function getDsn(Config $config): string; /** * Get the PDO connect options based on the specified connection configuration @@ -24,7 +24,7 @@ public function getDsn(Config $config); * * @return array */ - public function getOptions(Config $config); + public function getOptions(Config $config): array; /** * Set the client time zone @@ -33,7 +33,7 @@ public function getOptions(Config $config); * * @return $this */ - public function setClientTimezone(Connection $db); + public function setClientTimezone(Connection $db): static; /** * Register callbacks for query builder events @@ -42,5 +42,5 @@ public function setClientTimezone(Connection $db); * * @return $this */ - public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder); + public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder): static; } diff --git a/src/Contract/Quoter.php b/src/Contract/Quoter.php index 79c4c78..08dda06 100644 --- a/src/Contract/Quoter.php +++ b/src/Contract/Quoter.php @@ -17,5 +17,5 @@ interface Quoter * * @return string */ - public function quoteIdentifier($identifiers); + public function quoteIdentifier(array|string $identifiers): string; } diff --git a/src/Cursor.php b/src/Cursor.php index 85c5b1c..4df790a 100644 --- a/src/Cursor.php +++ b/src/Cursor.php @@ -12,13 +12,13 @@ class Cursor implements IteratorAggregate, Paginatable { /** @var Connection */ - protected $db; + protected Connection $db; /** @var Select */ - protected $select; + protected Select $select; /** @var array */ - protected $fetchModeAndArgs = []; + protected array $fetchModeAndArgs = []; /** * Create a new cursor for the given connection and query @@ -37,7 +37,7 @@ public function __construct(Connection $db, Select $select) * * @return array */ - public function getFetchMode() + public function getFetchMode(): array { return $this->fetchModeAndArgs; } @@ -45,13 +45,13 @@ public function getFetchMode() /** * Set the fetch mode * - * @param int $fetchMode Fetch mode as one of the PDO fetch mode constants. + * @param int $fetchMode Fetch mode as one of the PDO fetch mode constants. * Please see {@link https://www.php.net/manual/en/pdostatement.setfetchmode} for details * @param mixed ...$args Fetch mode arguments * * @return $this */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode(int $fetchMode, ...$args): static { array_unshift($args, $fetchMode); @@ -65,34 +65,34 @@ public function getIterator(): Traversable return $this->db->yieldAll($this->select, ...$this->getFetchMode()); } - public function hasLimit() + public function hasLimit(): bool { return $this->select->hasLimit(); } - public function getLimit() + public function getLimit(): ?int { return $this->select->getLimit(); } - public function limit($limit) + public function limit(?int $limit): static { $this->select->limit($limit); return $this; } - public function hasOffset() + public function hasOffset(): bool { return $this->select->hasOffset(); } - public function getOffset() + public function getOffset(): ?int { return $this->select->getOffset(); } - public function offset($offset) + public function offset(?int $offset): static { $this->select->offset($offset); diff --git a/src/Delete.php b/src/Delete.php index 53736b8..15fb33f 100644 --- a/src/Delete.php +++ b/src/Delete.php @@ -10,15 +10,15 @@ class Delete implements CommonTableExpressionInterface, WhereInterface use CommonTableExpression; use Where; - /** @var array|null The FROM part of the DELETE query */ - protected $from; + /** @var ?array The FROM part of the DELETE query */ + protected ?array $from = null; /** * Get the FROM part of the DELETE query * - * @return array|null + * @return ?array */ - public function getFrom() + public function getFrom(): ?array { return $this->from; } @@ -32,12 +32,12 @@ public function getFrom() * If you are using special table names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. * - * @param string|array $table The table to delete data from. The table specification must be in one of the + * @param array|string $table The table to delete data from. The table specification must be in one of the * following formats: 'table', 'table alias', ['alias' => 'table'] * * @return $this */ - public function from($table) + public function from(array|string $table): static { $this->from = ! is_array($table) ? [$table] : $table; diff --git a/src/Expression.php b/src/Expression.php index 83c10bd..6edb266 100644 --- a/src/Expression.php +++ b/src/Expression.php @@ -8,46 +8,46 @@ class Expression implements ExpressionInterface { /** @var string The statement of the expression */ - protected $statement; + protected string $statement; - /** @var array The columns used by the expression */ - protected $columns; + /** @var ?array The columns used by the expression */ + protected ?array $columns; /** @var array The values for the expression */ - protected $values; + protected array $values; /** * Create a new database expression * * @param string $statement The statement of the expression - * @param array $columns The columns used by the expression + * @param ?array $columns The columns used by the expression * @param mixed ...$values The values for the expression */ - public function __construct($statement, array $columns = null, ...$values) + public function __construct(string $statement, ?array $columns = null, ...$values) { $this->statement = $statement; $this->columns = $columns; $this->values = $values; } - public function getStatement() + public function getStatement(): string { return $this->statement; } - public function getColumns() + public function getColumns(): array { return $this->columns ?: []; } - public function setColumns(array $columns) + public function setColumns(array $columns): static { $this->columns = $columns; return $this; } - public function getValues() + public function getValues(): array { return $this->values; } diff --git a/src/ExpressionInterface.php b/src/ExpressionInterface.php index 9ebe5ee..9c994d6 100644 --- a/src/ExpressionInterface.php +++ b/src/ExpressionInterface.php @@ -12,14 +12,14 @@ interface ExpressionInterface * * @return string */ - public function getStatement(); + public function getStatement(): string; /** * Get the columns used by the expression * * @return array */ - public function getColumns(); + public function getColumns(): array; /** * Set the columns to use by the expression @@ -28,12 +28,12 @@ public function getColumns(); * * @return $this */ - public function setColumns(array $columns); + public function setColumns(array $columns): static; /** * Get the values for the expression * * @return array */ - public function getValues(); + public function getValues(): array; } diff --git a/src/Filter/In.php b/src/Filter/In.php index c126af6..2c8ce84 100644 --- a/src/Filter/In.php +++ b/src/Filter/In.php @@ -7,18 +7,14 @@ class In extends Filter\Condition { - use InAndNotInUtils; - /** * Create a new sql IN condition * * @param string[]|string $column * @param Select $select */ - public function __construct($column, Select $select) + public function __construct(array|string $column, Select $select) { - $this - ->setColumn($column) - ->setValue($select); + parent::__construct($column, $select); } } diff --git a/src/Filter/InAndNotInUtils.php b/src/Filter/InAndNotInUtils.php deleted file mode 100644 index 6f26de1..0000000 --- a/src/Filter/InAndNotInUtils.php +++ /dev/null @@ -1,62 +0,0 @@ -column; - } - - /** - * Set the columns of this condition - * - * @param string[]|string $column - * - * @return $this - */ - public function setColumn($column): self - { - $this->column = $column; - - return $this; - } - - /** - * Get the value of this condition - * - * @return Select - */ - public function getValue(): Select - { - return $this->value; - } - - /** - * Set the value of this condition - * - * @param Select $value - * - * @return $this - */ - public function setValue($value): self - { - $this->value = $value; - - return $this; - } -} diff --git a/src/Filter/NotIn.php b/src/Filter/NotIn.php index cdf6241..e42909f 100644 --- a/src/Filter/NotIn.php +++ b/src/Filter/NotIn.php @@ -7,18 +7,14 @@ class NotIn extends Filter\Condition { - use InAndNotInUtils; - /** * Create a new sql NOT IN condition * * @param string[]|string $column * @param Select $select */ - public function __construct($column, Select $select) + public function __construct(array|string $column, Select $select) { - $this - ->setColumn($column) - ->setValue($select); + parent::__construct($column, $select); } } diff --git a/src/Insert.php b/src/Insert.php index 738a842..4ee0137 100644 --- a/src/Insert.php +++ b/src/Insert.php @@ -13,24 +13,24 @@ class Insert implements CommonTableExpressionInterface { use CommonTableExpression; - /** @var string|null The table for the INSERT INTO query */ - protected $into; + /** @var ?string The table for the INSERT INTO query */ + protected ?string $into = null; - /** @var array|null The columns for which the query provides values */ - protected $columns; + /** @var ?array The columns for which the query provides values */ + protected ?array $columns = null; - /** @var array|null The values to insert */ - protected $values; + /** @var ?array $values The values to insert */ + protected ?array $values = null; - /** @var Select|null The select query for INSERT INTO ... SELECT queries */ - protected $select; + /** @var ?Select The select query for INSERT INTO ... SELECT queries */ + protected ?Select $select = null; /** * Get the table for the INSERT INTo query * - * @return string|null + * @return ?string */ - public function getInto() + public function getInto(): ?string { return $this->into; } @@ -49,7 +49,7 @@ public function getInto() * * @return $this */ - public function into($table) + public function into(string $table): static { $this->into = $table; @@ -61,7 +61,7 @@ public function into($table) * * @return array */ - public function getColumns() + public function getColumns(): array { if (! empty($this->columns)) { return array_keys($this->columns); @@ -90,7 +90,7 @@ public function getColumns() * * @return $this */ - public function columns(array $columns) + public function columns(array $columns): static { $this->columns = array_flip($columns); @@ -102,7 +102,7 @@ public function columns(array $columns) * * @return array */ - public function getValues() + public function getValues(): array { return array_values($this->values ?: []); } @@ -135,7 +135,7 @@ public function values($values) * * @return $this */ - public function select(Select $select) + public function select(Select $select): static { $this->select = $select; @@ -145,9 +145,9 @@ public function select(Select $select) /** * Get the select query for the INSERT INTO ... SELECT statement * - * @return Select|null + * @return ?Select */ - public function getSelect() + public function getSelect(): ?Select { return $this->select; } diff --git a/src/LimitOffset.php b/src/LimitOffset.php index 99c30a2..254314b 100644 --- a/src/LimitOffset.php +++ b/src/LimitOffset.php @@ -12,75 +12,61 @@ trait LimitOffset * * If unset or lower than 0, no limit will be applied. * - * @var int|null + * @var ?int */ - protected $limit; + protected ?int $limit = null; /** * Offset from where to start the result set * * If unset or lower than 0, the result set will start from the beginning. * - * @var int|null + * @var ?int */ - protected $offset; + protected ?int $offset = null; - public function hasLimit() + public function hasLimit(): bool { return $this->limit !== null; } - public function getLimit() + public function getLimit(): ?int { return $this->limit; } - public function limit($limit) + public function limit(?int $limit): static { - if ($limit !== null) { - $limit = (int) $limit; - if ($limit < 0) { - $limit = null; - } - } - - $this->limit = $limit; + $this->limit = $limit < 0 ? null : $limit; return $this; } - public function resetLimit() + public function resetLimit(): static { $this->limit = null; return $this; } - public function hasOffset() + public function hasOffset(): bool { return $this->offset !== null; } - public function getOffset() + public function getOffset(): ?int { return $this->offset; } - public function offset($offset) + public function offset(?int $offset): static { - if ($offset !== null) { - $offset = (int) $offset; - if ($offset <= 0) { - $offset = null; - } - } - - $this->offset = $offset; + $this->offset = $offset <= 0 ? null : $offset; return $this; } - public function resetOffset() + public function resetOffset(): static { $this->offset = null; diff --git a/src/LimitOffsetInterface.php b/src/LimitOffsetInterface.php index 94628c4..4dede24 100644 --- a/src/LimitOffsetInterface.php +++ b/src/LimitOffsetInterface.php @@ -12,60 +12,60 @@ interface LimitOffsetInterface * * @return bool */ - public function hasLimit(); + public function hasLimit(): bool; /** * Get the limit * - * @return int|null + * @return ?int */ - public function getLimit(); + public function getLimit(): ?int; /** * Set the limit * - * @param int|null $limit Maximum number of items to return. + * @param ?int $limit Maximum number of items to return. * If you want to disable the limit, use null or a negative value * * @return $this */ - public function limit($limit); + public function limit(?int $limit): static; /** * Reset the limit * * @return $this */ - public function resetLimit(); + public function resetLimit(): static; /** * Get whether an offset is configured * * @return bool */ - public function hasOffset(); + public function hasOffset(): bool; /** * Get the offset * - * @return int|null + * @return ?int */ - public function getOffset(); + public function getOffset(): ?int; /** * Set the offset * - * @param int|null $offset Start result set after this many rows. + * @param ?int $offset Start result set after this many rows. * If you want to disable the offset, use null, 0, or a negative value * * @return $this */ - public function offset($offset); + public function offset(?int $offset): static; /** * Reset the offset * * @return $this */ - public function resetOffset(); + public function resetOffset(): static; } diff --git a/src/OrderBy.php b/src/OrderBy.php index a19d7c5..822a8fa 100644 --- a/src/OrderBy.php +++ b/src/OrderBy.php @@ -8,19 +8,19 @@ trait OrderBy { /** @var ?array ORDER BY part of the query */ - protected $orderBy; + protected ?array $orderBy = null; - public function hasOrderBy() + public function hasOrderBy(): bool { return $this->orderBy !== null; } - public function getOrderBy() + public function getOrderBy(): ?array { return $this->orderBy; } - public function orderBy($orderBy, $direction = null) + public function orderBy($orderBy, int|string|null $direction = null): static { if (! is_array($orderBy)) { $orderBy = [$orderBy]; @@ -48,7 +48,7 @@ public function orderBy($orderBy, $direction = null) return $this; } - public function resetOrderBy() + public function resetOrderBy(): static { $this->orderBy = null; @@ -60,7 +60,7 @@ public function resetOrderBy() * * Shall be called by using classes in their __clone() */ - protected function cloneOrderBy() + protected function cloneOrderBy(): void { if ($this->orderBy !== null) { foreach ($this->orderBy as &$orderBy) { diff --git a/src/OrderByInterface.php b/src/OrderByInterface.php index 0ee0dda..37588df 100644 --- a/src/OrderByInterface.php +++ b/src/OrderByInterface.php @@ -12,14 +12,14 @@ interface OrderByInterface * * @return bool */ - public function hasOrderBy(); + public function hasOrderBy(): bool; /** * Get the ORDER BY part of the query * - * @return array|null + * @return ?array */ - public function getOrderBy(); + public function getOrderBy(): ?array; /** * Set the ORDER BY part of the query - either plain columns or expressions or scalar subqueries @@ -33,19 +33,19 @@ public function getOrderBy(); * If you are using special field names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. * - * @param string|int|array $orderBy The ORDER BY part. The items can be in any format of the following: + * @param int|array|string $orderBy The ORDER BY part. The items can be in any format of the following: * ['column', 'column' => 'DESC', 'column' => SORT_DESC, ['column', 'DESC']] - * @param string|int $direction The default direction. Can be any of the following: + * @param int|string|null $direction The default direction. Can be any of the following: * 'ASC', 'DESC', SORT_ASC, SORT_DESC * * @return $this */ - public function orderBy($orderBy, $direction = null); + public function orderBy($orderBy, int|string|null $direction = null): static; /** * Reset the ORDER BY part of the query * * @return $this */ - public function resetOrderBy(); + public function resetOrderBy(): static; } diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index 07b5e3e..24f5e6f 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -2,13 +2,10 @@ namespace ipl\Sql; -use InvalidArgumentException; use ipl\Sql\Adapter\Mssql; use ipl\Sql\Contract\Adapter; use ipl\Stdlib\Events; -use function ipl\Stdlib\get_php_type; - class QueryBuilder { use Events; @@ -141,9 +138,9 @@ class QueryBuilder public const ON_DELETE_ASSEMBLED = 'deleteAssembled'; /** @var Adapter */ - protected $adapter; + protected Adapter $adapter; - protected $separator = " "; + protected string $separator = " "; /** * Create a new query builder for the specified database adapter @@ -163,26 +160,15 @@ public function __construct(Adapter $adapter) * @param Delete|Insert|Select|Update $stmt * * @return array - * - * @throw InvalidArgumentException If statement type is invalid */ - public function assemble($stmt) + public function assemble(Select|Insert|Update|Delete $stmt): array { - switch (true) { - case $stmt instanceof Delete: - return $this->assembleDelete($stmt); - case $stmt instanceof Insert: - return $this->assembleInsert($stmt); - case $stmt instanceof Select: - return $this->assembleSelect($stmt); - case $stmt instanceof Update: - return $this->assembleUpdate($stmt); - default: - throw new InvalidArgumentException(sprintf( - __METHOD__ . ' expects instances of Delete, Insert, Select or Update. Got %s instead.', - get_php_type($stmt) - )); - } + return match (true) { + $stmt instanceof Delete => $this->assembleDelete($stmt), + $stmt instanceof Insert => $this->assembleInsert($stmt), + $stmt instanceof Select => $this->assembleSelect($stmt), + $stmt instanceof Update => $this->assembleUpdate($stmt) + }; } /** @@ -192,7 +178,7 @@ public function assemble($stmt) * * @return array */ - public function assembleDelete(Delete $delete) + public function assembleDelete(Delete $delete): array { $values = []; @@ -218,7 +204,7 @@ public function assembleDelete(Delete $delete) * * @return array */ - public function assembleInsert(Insert $insert) + public function assembleInsert(Insert $insert): array { $values = []; @@ -249,7 +235,7 @@ public function assembleInsert(Insert $insert) * * @return array */ - public function assembleSelect(Select $select, array &$values = []) + public function assembleSelect(Select $select, array &$values = []): array { $select = clone $select; @@ -271,7 +257,7 @@ public function assembleSelect(Select $select, array &$values = []) $unions = $this->buildUnions($select->getUnion(), $values); if ($unions) { - list($unionKeywords, $selects) = $unions; + [$unionKeywords, $selects] = $unions; if ($sql) { $sql = "($sql)"; @@ -307,7 +293,7 @@ public function assembleSelect(Select $select, array &$values = []) * * @return array */ - public function assembleUpdate(Update $update) + public function assembleUpdate(Update $update): array { $values = []; @@ -335,7 +321,7 @@ public function assembleUpdate(Update $update) * * @return string The WITH part of a query */ - public function buildWith(array $with, array &$values) + public function buildWith(array $with, array &$values): string { if (empty($with)) { return ''; @@ -345,8 +331,8 @@ public function buildWith(array $with, array &$values) $hasRecursive = false; foreach ($with as $cte) { - list($query, $alias, $recursive) = $cte; - list($cteSql, $cteValues) = $this->assembleSelect($query); + [$query, $alias, $recursive] = $cte; + [$cteSql, $cteValues] = $this->assembleSelect($query); $ctes[] = "$alias AS ($cteSql)"; @@ -360,11 +346,11 @@ public function buildWith(array $with, array &$values) /** * Build the DELETE FROM part of a query * - * @param array $from + * @param ?array $from * * @return string The DELETE FROM part of a query */ - public function buildDeleteFrom(array $from = null) + public function buildDeleteFrom(?array $from = null): string { if ($from === null) { return ''; @@ -393,7 +379,7 @@ public function buildDeleteFrom(array $from = null) * * @return array */ - public function unpackCondition($expression, array $values) + public function unpackCondition(string $expression, array $values): array { $placeholders = preg_match_all('/(\?)/', $expression, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); @@ -440,7 +426,7 @@ public function unpackCondition($expression, array $values) * * @return string */ - public function buildCondition(array $condition, array &$values) + public function buildCondition(array $condition, array &$values): string { $sql = []; @@ -486,12 +472,12 @@ public function buildCondition(array $condition, array &$values) /** * Build the WHERE part of a query * - * @param array $where + * @param ?array $where * @oaram array $values * * @return string The WHERE part of the query */ - public function buildWhere(array $where = null, array &$values = []) + public function buildWhere(?array $where = null, array &$values = []): string { if ($where === null) { return ''; @@ -507,7 +493,7 @@ public function buildWhere(array $where = null, array &$values = []) * * @return string The INSERT INTO part of a INSERT INTO ... statement */ - public function buildInsertInto($into) + public function buildInsertInto(?string $into): string { if (empty($into)) { return ''; @@ -525,7 +511,7 @@ public function buildInsertInto($into) * * @return string The columns and SELECT part of the INSERT INTO ... SELECT statement */ - public function buildInsertIntoSelect(array $columns, Select $select, array &$values) + public function buildInsertIntoSelect(array $columns, Select $select, array &$values): string { $sql = [ '(' . implode(',', $columns) . ')', @@ -544,7 +530,7 @@ public function buildInsertIntoSelect(array $columns, Select $select, array &$va * * @return string The columns and values part of a INSERT INTO ... statement */ - public function buildInsertColumnsAndValues(array $columns, array $insertValues, array &$values) + public function buildInsertColumnsAndValues(array $columns, array $insertValues, array &$values): string { $sql = ['(' . implode(',', $columns) . ')']; @@ -570,12 +556,12 @@ public function buildInsertColumnsAndValues(array $columns, array $insertValues, * Build the SELECT part of a query * * @param array $columns - * @param bool $distinct + * @param bool $distinct * @param array $values * * @return string The SELECT part of the query */ - public function buildSelect(array $columns, $distinct, array &$values) + public function buildSelect(array $columns, bool $distinct, array &$values): string { if (empty($columns)) { return ''; @@ -609,12 +595,12 @@ public function buildSelect(array $columns, $distinct, array &$values) /** * Build the FROM part of a query * - * @param array $from + * @param ?array $from * @param array $values * * @return string The FROM part of the query */ - public function buildFrom(array $from = null, array &$values = []) + public function buildFrom(?array $from = null, array &$values = []): string { if ($from === null) { return ''; @@ -640,12 +626,13 @@ public function buildFrom(array $from = null, array &$values = []) /** * Build the JOIN part(s) of a query * - * @param array $joins + * @param ?array $joins + * * @oaram array $values * * @return string The JOIN part(s) of the query */ - public function buildJoin($joins, array &$values) + public function buildJoin(?array $joins, array &$values): string { if ($joins === null) { return ''; @@ -653,7 +640,7 @@ public function buildJoin($joins, array &$values) $sql = []; foreach ($joins as $join) { - list($joinType, $table, $condition) = $join; + [$joinType, $table, $condition] = $join; if (is_array($table)) { $tableName = null; @@ -686,12 +673,12 @@ public function buildJoin($joins, array &$values) /** * Build the GROUP BY part of a query * - * @param array $groupBy + * @param ?array $groupBy * @param array $values * * @return string The GROUP BY part of the query */ - public function buildGroupBy(array $groupBy = null, array &$values = []) + public function buildGroupBy(?array $groupBy = null, array &$values = []): string { if ($groupBy === null) { return ''; @@ -711,12 +698,12 @@ public function buildGroupBy(array $groupBy = null, array &$values = []) /** * Build the HAVING part of a query * - * @param array $having + * @param ?array $having * @param array $values * * @return string The HAVING part of the query */ - public function buildHaving(array $having = null, array &$values = []) + public function buildHaving(?array $having = null, array &$values = []): string { if ($having === null) { return ''; @@ -728,12 +715,12 @@ public function buildHaving(array $having = null, array &$values = []) /** * Build the ORDER BY part of a query * - * @param array $orderBy + * @param ?array $orderBy * @param array $values * * @return string The ORDER BY part of the query */ - public function buildOrderBy(array $orderBy = null, array &$values = []) + public function buildOrderBy(?array $orderBy = null, array &$values = []): string { if ($orderBy === null) { return ''; @@ -742,7 +729,7 @@ public function buildOrderBy(array $orderBy = null, array &$values = []) $sql = []; foreach ($orderBy as $column) { - list($column, $direction) = $column; + [$column, $direction] = $column; if ($column instanceof ExpressionInterface) { $column = $this->buildExpression($column, $values); @@ -763,12 +750,12 @@ public function buildOrderBy(array $orderBy = null, array &$values = []) /** * Build the LIMIT and OFFSET part of a query * - * @param int $limit - * @param int $offset + * @param ?int $limit + * @param ?int $offset * * @return string The LIMIT and OFFSET part of the query */ - public function buildLimitOffset($limit = null, $offset = null) + public function buildLimitOffset(?int $limit = null, ?int $offset = null): string { $sql = []; @@ -798,12 +785,12 @@ public function buildLimitOffset($limit = null, $offset = null) /** * Build the UNION parts of a query * - * @param array $unions + * @param ?array $unions * @param array $values * - * @return array|null The UNION parts of the query + * @return ?array The UNION parts of the query */ - public function buildUnions(array $unions = null, array &$values = []) + public function buildUnions(?array $unions = null, array &$values = []): ?array { if ($unions === null) { return null; @@ -813,10 +800,10 @@ public function buildUnions(array $unions = null, array &$values = []) $selects = []; foreach ($unions as $union) { - list($select, $all) = $union; + [$select, $all] = $union; if ($select instanceof Select) { - list($select, $values) = $this->assembleSelect($select, $values); + [$select, $values] = $this->assembleSelect($select, $values); } $unionKeywords[] = ($all ? 'UNION ALL' : 'UNION'); @@ -829,11 +816,11 @@ public function buildUnions(array $unions = null, array &$values = []) /** * Build the UPDATE {table} part of a query * - * @param array $updateTable The table to UPDATE + * @param ?array $updateTable The table to UPDATE * * @return string The UPDATE {table} part of the query */ - public function buildUpdateTable(array $updateTable = null) + public function buildUpdateTable(?array $updateTable = null): string { if ($updateTable === null) { return ''; @@ -857,12 +844,12 @@ public function buildUpdateTable(array $updateTable = null) /** * Build the SET part of a UPDATE query * - * @param array $set + * @param ?array $set * @param array $values * * @return string The SET part of a UPDATE query */ - public function buildUpdateSet(array $set = null, array &$values = []) + public function buildUpdateSet(?array $set = null, array &$values = []): string { if (empty($set)) { return ''; @@ -892,7 +879,7 @@ public function buildUpdateSet(array $set = null, array &$values = []) * * @return string The expression's statement */ - public function buildExpression(ExpressionInterface $expression, array &$values = []) + public function buildExpression(ExpressionInterface $expression, array &$values = []): string { $stmt = $expression->getStatement(); $columns = $expression->getColumns(); diff --git a/src/Select.php b/src/Select.php index f56a131..ecf3a62 100644 --- a/src/Select.php +++ b/src/Select.php @@ -13,13 +13,13 @@ class Select implements CommonTableExpressionInterface, LimitOffsetInterface, Or use Where; /** @var bool Whether the query is DISTINCT */ - protected $distinct = false; + protected bool $distinct = false; - /** @var array|null The columns for the SELECT query */ - protected $columns; + /** @var ?array The columns for the SELECT query */ + protected ?array $columns = null; - /** @var array|null FROM part of the query, i.e. the table names to select data from */ - protected $from; + /** @var ?array FROM part of the query, i.e. the table names to select data from */ + protected ?array $from = null; /** * The tables to JOIN @@ -31,13 +31,13 @@ class Select implements CommonTableExpressionInterface, LimitOffsetInterface, Or * * @var ?array */ - protected $join; + protected ?array $join = null; - /** @var array|null The columns for the GROUP BY part of the query */ - protected $groupBy; + /** @var ?array The columns for the GROUP BY part of the query */ + protected ?array $groupBy = null; - /** @var array|null Internal representation for the HAVING part of the query */ - protected $having; + /** @var ?array Internal representation for the HAVING part of the query */ + protected ?array $having = null; /** * The queries to UNION @@ -49,14 +49,14 @@ class Select implements CommonTableExpressionInterface, LimitOffsetInterface, Or * * @var ?array */ - protected $union; + protected ?array $union = null; /** * Get whether to SELECT DISTINCT * * @return bool */ - public function getDistinct() + public function getDistinct(): bool { return $this->distinct; } @@ -68,7 +68,7 @@ public function getDistinct() * * @return $this */ - public function distinct($distinct = true) + public function distinct(bool $distinct = true): static { $this->distinct = $distinct; @@ -80,7 +80,7 @@ public function distinct($distinct = true) * * @return array */ - public function getColumns() + public function getColumns(): array { return $this->columns ?: []; } @@ -102,7 +102,7 @@ public function getColumns() * * @return $this */ - public function columns($columns) + public function columns($columns): static { if (! is_array($columns)) { $columns = [$columns]; @@ -116,9 +116,9 @@ public function columns($columns) /** * Get the FROM part of the query * - * @return array|null + * @return ?array */ - public function getFrom() + public function getFrom(): ?array { return $this->from; } @@ -139,7 +139,7 @@ public function getFrom() * * @return $this */ - public function from($tables) + public function from($tables): static { if (! is_array($tables)) { $tables = [$tables]; @@ -153,9 +153,9 @@ public function from($tables) /** * Get the JOIN part(s) of the query * - * @return array|null + * @return ?array */ - public function getJoin() + public function getJoin(): ?array { return $this->join; } @@ -174,7 +174,7 @@ public function getJoin() * * @return $this */ - public function join($table, $condition, $operator = Sql::ALL) + public function join($table, $condition, $operator = Sql::ALL): static { $this->join[] = ['INNER', $table, $this->buildCondition($condition, $operator)]; @@ -195,7 +195,7 @@ public function join($table, $condition, $operator = Sql::ALL) * * @return $this */ - public function joinLeft($table, $condition, $operator = Sql::ALL) + public function joinLeft($table, $condition, $operator = Sql::ALL): static { $this->join[] = ['LEFT', $table, $this->buildCondition($condition, $operator)]; @@ -216,7 +216,7 @@ public function joinLeft($table, $condition, $operator = Sql::ALL) * * @return $this */ - public function joinRight($table, $condition, $operator = Sql::ALL) + public function joinRight($table, $condition, $operator = Sql::ALL): static { $this->join[] = ['RIGHT', $table, $this->buildCondition($condition, $operator)]; @@ -226,9 +226,9 @@ public function joinRight($table, $condition, $operator = Sql::ALL) /** * Get the GROUP BY part of the query * - * @return array|null + * @return ?array */ - public function getGroupBy() + public function getGroupBy(): ?array { return $this->groupBy; } @@ -249,7 +249,7 @@ public function getGroupBy() * * @return $this */ - public function groupBy($groupBy) + public function groupBy($groupBy): static { $this->groupBy = array_merge( $this->groupBy === null ? [] : $this->groupBy, @@ -262,9 +262,9 @@ public function groupBy($groupBy) /** * Get the HAVING part of the query * - * @return array|null + * @return ?array */ - public function getHaving() + public function getHaving(): ?array { return $this->having; } @@ -291,7 +291,7 @@ public function getHaving() * * @return $this */ - public function having($condition, $operator = Sql::ALL) + public function having($condition, string $operator = Sql::ALL): static { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::ALL); @@ -309,7 +309,7 @@ public function having($condition, $operator = Sql::ALL) * * @return $this */ - public function orHaving($condition, $operator = Sql::ALL) + public function orHaving($condition, string $operator = Sql::ALL): static { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::ANY); @@ -327,7 +327,7 @@ public function orHaving($condition, $operator = Sql::ALL) * * @return $this */ - public function notHaving($condition, $operator = Sql::ALL) + public function notHaving($condition, string $operator = Sql::ALL) { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::NOT_ALL); @@ -345,7 +345,7 @@ public function notHaving($condition, $operator = Sql::ALL) * * @return $this */ - public function orNotHaving($condition, $operator = Sql::ALL) + public function orNotHaving($condition, string $operator = Sql::ALL) { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::NOT_ANY); @@ -355,9 +355,9 @@ public function orNotHaving($condition, $operator = Sql::ALL) /** * Get the UNION parts of the query * - * @return array|null + * @return ?array */ - public function getUnion() + public function getUnion(): ?array { return $this->union; } @@ -365,11 +365,11 @@ public function getUnion() /** * Combine a query with UNION * - * @param Select|string $query + * @param string|Select $query * * @return $this */ - public function union($query) + public function union(Select|string $query): static { $this->union[] = [$query, false]; @@ -379,11 +379,11 @@ public function union($query) /** * Combine a query with UNION ALL * - * @param Select|string $query + * @param string|Select $query * * @return $this */ - public function unionAll($query) + public function unionAll(Select|string $query): static { $this->union[] = [$query, true]; @@ -395,7 +395,7 @@ public function unionAll($query) * * @return $this */ - public function resetDistinct() + public function resetDistinct(): static { $this->distinct = false; @@ -407,7 +407,7 @@ public function resetDistinct() * * @return $this */ - public function resetColumns() + public function resetColumns(): static { $this->columns = null; @@ -419,7 +419,7 @@ public function resetColumns() * * @return $this */ - public function resetFrom() + public function resetFrom(): static { $this->from = null; @@ -431,7 +431,7 @@ public function resetFrom() * * @return $this */ - public function resetJoin() + public function resetJoin(): static { $this->join = null; @@ -443,7 +443,7 @@ public function resetJoin() * * @return $this */ - public function resetGroupBy() + public function resetGroupBy(): static { $this->groupBy = null; @@ -455,7 +455,7 @@ public function resetGroupBy() * * @return $this */ - public function resetHaving() + public function resetHaving(): static { $this->having = null; @@ -467,7 +467,7 @@ public function resetHaving() * * @return $this */ - public function resetUnion() + public function resetUnion(): static { $this->union = null; @@ -479,7 +479,7 @@ public function resetUnion() * * @return Select */ - public function getCountQuery() + public function getCountQuery(): Select|static { $countQuery = clone $this; diff --git a/src/Sql.php b/src/Sql.php index 000a43a..bb90bff 100644 --- a/src/Sql.php +++ b/src/Sql.php @@ -33,7 +33,7 @@ class Sql * * @return Delete */ - public static function delete() + public static function delete(): Delete { return new Delete(); } @@ -43,7 +43,7 @@ public static function delete() * * @return Insert */ - public static function insert() + public static function insert(): Insert { return new Insert(); } @@ -53,7 +53,7 @@ public static function insert() * * @return Select */ - public static function select() + public static function select(): Select { return new Select(); } @@ -63,7 +63,7 @@ public static function select() * * @return Update */ - public static function update() + public static function update(): Update { return new Update(); } diff --git a/src/Test/SqlAssertions.php b/src/Test/SqlAssertions.php index 74a04ba..62d4ab0 100644 --- a/src/Test/SqlAssertions.php +++ b/src/Test/SqlAssertions.php @@ -33,7 +33,7 @@ protected function setUpSqlAssertions(): void * * @return void */ - public function assertSql(string $sql, $statement, array $values = null, string $message = ''): void + public function assertSql(string $sql, $statement, ?array $values = null, string $message = ''): void { // Reduce whitespaces to just one space $sql = preg_replace('/\s+/', ' ', trim($sql)); diff --git a/src/Test/TestConnection.php b/src/Test/TestConnection.php index 913070f..1e149b8 100644 --- a/src/Test/TestConnection.php +++ b/src/Test/TestConnection.php @@ -14,22 +14,22 @@ public function __construct() $this->adapter = new TestAdapter(); } - public function connect() + public function connect(): static { return $this; } - public function beginTransaction() + public function beginTransaction(): bool { throw new \LogicException('Transactions are not supported by the test connection'); } - public function commitTransaction() + public function commitTransaction(): bool { throw new \LogicException('Transactions are not supported by the test connection'); } - public function rollbackTransaction() + public function rollbackTransaction(): bool { throw new \LogicException('Transactions are not supported by the test connection'); } @@ -43,7 +43,7 @@ public function getIterator(): \Iterator return new \ArrayIterator([]); } - public function setFetchMode($mode, ...$args): bool + public function setFetchMode($mode, ...$args): true { return true; } @@ -55,7 +55,7 @@ public function getIterator(): \Iterator return new \ArrayIterator([]); } - public function setFetchMode($mode, $params = null): bool + public function setFetchMode($mode, ...$params): true { return true; } diff --git a/src/Update.php b/src/Update.php index 356a610..af9ad53 100644 --- a/src/Update.php +++ b/src/Update.php @@ -14,18 +14,18 @@ class Update implements CommonTableExpressionInterface, WhereInterface use CommonTableExpression; use Where; - /** @var array|null The table for the UPDATE query */ - protected $table; + /** @var ?array The table for the UPDATE query */ + protected ?array $table = null; - /** @var array|null The columns to update in terms of column-value pairs */ - protected $set = []; + /** @var ?array The columns to update in terms of column-value pairs */ + protected ?array $set = []; /** * Get the table for the UPDATE query * - * @return array|null + * @return ?array */ - public function getTable() + public function getTable(): ?array { return $this->table; } @@ -39,12 +39,12 @@ public function getTable() * If you are using special table names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. * - * @param string|array $table The table to update. The table specification must be in one of the + * @param array|string $table The table to update. The table specification must be in one of the * following formats: 'table', 'table alias', ['alias' => 'table'] * * @return $this */ - public function table($table) + public function table(array|string $table): static { $this->table = is_array($table) ? $table : [$table]; @@ -54,9 +54,9 @@ public function table($table) /** * Get the columns to update in terms of column-value pairs * - * @return array|null + * @return ?array */ - public function getSet() + public function getSet(): ?array { return $this->set; } @@ -78,7 +78,7 @@ public function getSet() * * @throws InvalidArgumentException If set type is invalid */ - public function set($set) + public function set($set): static { $this->set = arrayval($set); diff --git a/src/Where.php b/src/Where.php index f862846..404766c 100644 --- a/src/Where.php +++ b/src/Where.php @@ -7,47 +7,47 @@ */ trait Where { - /** @var array|null Internal representation for the WHERE part of the query */ - protected $where; + /** @var ?array Internal representation for the WHERE part of the query */ + protected ?array $where = null; - public function getWhere() + public function getWhere(): ?array { return $this->where; } - public function where($condition, ...$args) + public function where($condition, ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::ALL); return $this; } - public function orWhere($condition, ...$args) + public function orWhere($condition, ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::ANY); return $this; } - public function notWhere($condition, ...$args) + public function notWhere($condition, ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::NOT_ALL); return $this; } - public function orNotWhere($condition, ...$args) + public function orNotWhere($condition, ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::NOT_ANY); return $this; } - public function resetWhere() + public function resetWhere(): static { $this->where = null; @@ -64,7 +64,7 @@ public function resetWhere() * * @return array */ - protected function buildCondition($condition, $operator) + protected function buildCondition($condition, string $operator): array { if (is_array($condition)) { if (empty($condition)) { @@ -86,7 +86,7 @@ protected function buildCondition($condition, $operator) * @param array $condition As returned by {@link buildCondition()} * @param string $operator */ - protected function mergeCondition(&$base, array $condition, $operator) + protected function mergeCondition(&$base, array $condition, string $operator): void { if ($base === null) { $base = [$operator, [$condition]]; @@ -111,7 +111,7 @@ protected function mergeCondition(&$base, array $condition, $operator) * * @return array */ - protected function prepareConditionArguments($condition, array $args) + protected function prepareConditionArguments($condition, array $args): array { // Default operator $operator = Sql::ALL; @@ -132,7 +132,7 @@ protected function prepareConditionArguments($condition, array $args) * * Shall be called by using classes in their __clone() */ - protected function cloneWhere() + protected function cloneWhere(): void { if ($this->where !== null) { $this->cloneCondition($this->where); @@ -144,7 +144,7 @@ protected function cloneWhere() * * @param array $condition As returned by {@link buildCondition()} */ - protected function cloneCondition(array &$condition) + protected function cloneCondition(array &$condition): void { foreach ($condition as &$subCondition) { if (is_array($subCondition)) { diff --git a/src/WhereInterface.php b/src/WhereInterface.php index e724465..a74a8dc 100644 --- a/src/WhereInterface.php +++ b/src/WhereInterface.php @@ -10,9 +10,9 @@ interface WhereInterface /** * Get the WHERE part of the query * - * @return array|null + * @return ?array */ - public function getWhere(); + public function getWhere(): ?array; /** * Add a WHERE part of the query @@ -37,7 +37,7 @@ public function getWhere(); * * @return $this */ - public function where($condition, ...$args); + public function where($condition, ...$args): static; /** * Add a OR part to the WHERE part of the query @@ -49,7 +49,7 @@ public function where($condition, ...$args); * * @return $this */ - public function orWhere($condition, ...$args); + public function orWhere($condition, ...$args): static; /** * Add a AND NOT part to the WHERE part of the query @@ -61,7 +61,7 @@ public function orWhere($condition, ...$args); * * @return $this */ - public function notWhere($condition, ...$args); + public function notWhere($condition, ...$args): static; /** * Add a OR NOT part to the WHERE part of the query @@ -73,12 +73,12 @@ public function notWhere($condition, ...$args); * * @return $this */ - public function orNotWhere($condition, ...$args); + public function orNotWhere($condition, ...$args): static; /** * Reset the WHERE part of the query * * @return $this */ - public function resetWhere(); + public function resetWhere(): static; } diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index 58d0324..4f3183e 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -52,7 +52,7 @@ public function testAllPropertiesCanBeSet(): void 'password' => 'test_password', 'use_ssl' => 'true', 'charset' => 'latin1', - 'options' => 'test_options', + 'options' => ['test_options'], 'ssl_key' => 'test_ssl_key', 'ssl_cert' => 'test_ssl_cert', 'ssl_ca' => 'test_ssl_ca', @@ -69,7 +69,7 @@ public function testAllPropertiesCanBeSet(): void $this->assertSame($config->password, 'test_password'); $this->assertSame($config->useSsl, 'true'); $this->assertSame($config->charset, 'latin1'); - $this->assertSame($config->options, 'test_options'); + $this->assertSame($config->options, ['test_options']); $this->assertSame($config->sslKey, 'test_ssl_key'); $this->assertSame($config->sslCert, 'test_ssl_cert'); $this->assertSame($config->sslCa, 'test_ssl_ca');