diff --git a/src/ConnectionManager.php b/src/ConnectionManager.php index e1234da..f538d5d 100644 --- a/src/ConnectionManager.php +++ b/src/ConnectionManager.php @@ -17,6 +17,8 @@ namespace Query; use DomainException; +use PHPUnit\Framework\Attributes\CodeCoverageIgnore; +use Query\Exception\{BadDBDriverException, NonExistentConnectionException}; use stdClass; /** @@ -37,8 +39,8 @@ final class ConnectionManager /** * Private constructor to prevent multiple instances - * @codeCoverageIgnore */ + #[CodeCoverageIgnore] private function __construct() { } @@ -108,7 +110,7 @@ final class ConnectionManager } // You should actually connect before trying to get a connection... - throw new Exception\NonExistentConnectionException('The specified connection does not exist'); + throw new NonExistentConnectionException('The specified connection does not exist'); } /** @@ -118,7 +120,7 @@ final class ConnectionManager { [$dsn, $dbType, $params, $options] = $this->parseParams($params); - $dbType = ucfirst($dbType); + $dbType = ucfirst((string) $dbType); $driver = "\\Query\\Drivers\\{$dbType}\\Driver"; // Create the database connection @@ -156,14 +158,14 @@ final class ConnectionManager public function parseParams(array|object $rawParams): array { $params = (object) $rawParams; - $params->type = strtolower($params->type); + $params->type = strtolower((string) $params->type); $dbType = ($params->type === 'postgresql') ? 'pgsql' : $params->type; $dbType = ucfirst($dbType); // Make sure the class exists if ( ! class_exists("\\Query\\Drivers\\{$dbType}\\Driver")) { - throw new Exception\BadDBDriverException('Database driver does not exist, or is not supported'); + throw new BadDBDriverException('Database driver does not exist, or is not supported'); } // Set additional PDO options @@ -182,9 +184,8 @@ final class ConnectionManager /** * Create the dsn from the db type and params - * - * @codeCoverageIgnore */ + #[CodeCoverageIgnore] private function createDsn(string $dbType, stdClass $params): string { $pairs = []; diff --git a/src/Drivers/AbstractDriver.php b/src/Drivers/AbstractDriver.php index bd58197..e1e5986 100644 --- a/src/Drivers/AbstractDriver.php +++ b/src/Drivers/AbstractDriver.php @@ -19,6 +19,7 @@ namespace Query\Drivers; use InvalidArgumentException; use PDO; use PDOStatement; +use PHPUnit\Framework\Attributes\CodeCoverageIgnore; use function call_user_func_array; use function dbFilter; @@ -87,9 +88,9 @@ abstract class AbstractDriver extends PDO implements DriverInterface /** * Allow invoke to work on table object * - * @codeCoverageIgnore * @return mixed */ + #[CodeCoverageIgnore] public function __call(string $name, array $args = []) { if ( @@ -109,7 +110,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface protected function _loadSubClasses(): void { // Load the sql and util class for the driver - $thisClass = $this::class; + $thisClass = static::class; $nsArray = explode('\\', $thisClass); array_pop($nsArray); $driver = array_pop($nsArray); @@ -256,7 +257,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface { if (is_array($identifier)) { - return array_map([$this, __METHOD__], $identifier); + return array_map(__METHOD__, $identifier); } // Make all the string-handling methods happy @@ -266,7 +267,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface if (str_contains($identifier, ',')) { $parts = array_map('mb_trim', explode(',', $identifier)); - $parts = array_map([$this, __METHOD__], $parts); + $parts = array_map(__METHOD__, $parts); $identifier = implode(',', $parts); } @@ -275,7 +276,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface $hiers = array_map('mb_trim', $hiers); // Re-compile the string - $raw = implode('.', array_map([$this, '_quote'], $hiers)); + $raw = implode('.', array_map($this->_quote(...), $hiers)); // Fix functions $funcs = []; diff --git a/src/Drivers/Mysql/Driver.php b/src/Drivers/Mysql/Driver.php index 9cc111a..f4e6936 100644 --- a/src/Drivers/Mysql/Driver.php +++ b/src/Drivers/Mysql/Driver.php @@ -17,6 +17,7 @@ namespace Query\Drivers\Mysql; use PDO; +use PHPUnit\Framework\Attributes\CodeCoverageIgnore; use Query\Drivers\AbstractDriver; use function defined; @@ -37,9 +38,8 @@ class Driver extends AbstractDriver /** * Connect to MySQL Database - * - * @codeCoverageIgnore */ + #[CodeCoverageIgnore] public function __construct(string $dsn, ?string $username=NULL, ?string $password=NULL, array $options=[]) { // Set the charset to UTF-8 diff --git a/src/Drivers/Mysql/SQL.php b/src/Drivers/Mysql/SQL.php index 406f71d..e4da5fb 100644 --- a/src/Drivers/Mysql/SQL.php +++ b/src/Drivers/Mysql/SQL.php @@ -16,6 +16,7 @@ namespace Query\Drivers\Mysql; +use PHPUnit\Framework\Attributes\CodeCoverageIgnore; use Query\Drivers\AbstractSQL; /** @@ -98,9 +99,8 @@ SQL; /** * Returns sql to list triggers - * - * @codeCoverageIgnore */ + #[CodeCoverageIgnore] public function triggerList(): string { return 'SHOW TRIGGERS'; @@ -108,9 +108,8 @@ SQL; /** * Return sql to list functions - * - * @codeCoverageIgnore */ + #[CodeCoverageIgnore] public function functionList(): string { return 'SHOW FUNCTION STATUS'; @@ -118,9 +117,8 @@ SQL; /** * Return sql to list stored procedures - * - * @codeCoverageIgnore */ + #[CodeCoverageIgnore] public function procedureList(): string { return 'SHOW PROCEDURE STATUS'; diff --git a/src/Drivers/Mysql/Util.php b/src/Drivers/Mysql/Util.php index 293be3a..84900c2 100644 --- a/src/Drivers/Mysql/Util.php +++ b/src/Drivers/Mysql/Util.php @@ -108,7 +108,7 @@ class Util extends AbstractUtil $row = array_map(static fn ($r) => is_string($r) ? $driver->quote($r) : $r, $row); $row = array_map('trim', $row); - $rowString = 'INSERT INTO `' . trim($t) . '` (`' . implode('`,`', $columns) . '`) VALUES (' . implode(',', $row) . ');'; + $rowString = 'INSERT INTO `' . trim((string) $t) . '` (`' . implode('`,`', $columns) . '`) VALUES (' . implode(',', $row) . ');'; $row = NULL; diff --git a/src/Drivers/Pgsql/Driver.php b/src/Drivers/Pgsql/Driver.php index bcd0a7b..d9d8368 100644 --- a/src/Drivers/Pgsql/Driver.php +++ b/src/Drivers/Pgsql/Driver.php @@ -16,6 +16,7 @@ namespace Query\Drivers\Pgsql; +use PHPUnit\Framework\Attributes\CodeCoverageIgnore; use Query\Drivers\AbstractDriver; /** @@ -25,9 +26,8 @@ class Driver extends AbstractDriver { /** * Connect to a PosgreSQL database - * - * @codeCoverageIgnore */ + #[CodeCoverageIgnore] public function __construct(string $dsn, ?string $username=NULL, ?string $password=NULL, array $options=[]) { if ( ! str_contains($dsn, 'pgsql')) diff --git a/src/Drivers/Pgsql/Util.php b/src/Drivers/Pgsql/Util.php index 53e4c60..fb7c69a 100644 --- a/src/Drivers/Pgsql/Util.php +++ b/src/Drivers/Pgsql/Util.php @@ -51,7 +51,7 @@ class Util extends AbstractUtil // Get the data for each object foreach ($tables as $t) { - $sql = 'SELECT * FROM "' . trim($t) . '"'; + $sql = 'SELECT * FROM "' . trim((string) $t) . '"'; $res = $this->getDriver()->query($sql); $objRes = $res->fetchAll(PDO::FETCH_ASSOC); @@ -77,7 +77,7 @@ class Util extends AbstractUtil $row = array_map([$this->getDriver(), 'quote'], $row); $row = array_map('trim', $row); - $rowString = 'INSERT INTO "' . trim($t) . '" ("' . implode('","', $columns) . '") VALUES (' . implode(',', $row) . ');'; + $rowString = 'INSERT INTO "' . trim((string) $t) . '" ("' . implode('","', $columns) . '") VALUES (' . implode(',', $row) . ');'; $row = NULL; diff --git a/src/Drivers/Sqlite/Driver.php b/src/Drivers/Sqlite/Driver.php index bccbea5..b909841 100644 --- a/src/Drivers/Sqlite/Driver.php +++ b/src/Drivers/Sqlite/Driver.php @@ -17,8 +17,9 @@ namespace Query\Drivers\Sqlite; use InvalidArgumentException; - use PDO; + +use PHPUnit\Framework\Attributes\CodeCoverageIgnore; use Query\Drivers\AbstractDriver; use function is_array; @@ -89,9 +90,9 @@ class Driver extends AbstractDriver /** * Create sql for batch insert * - * @codeCoverageIgnore * @return array[]|null[]|string[] */ + #[CodeCoverageIgnore] public function insertBatch(string $table, array $data=[]): array { // If greater than version 3.7.11, supports the same syntax as diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index efdbbb1..a5c4e98 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -70,10 +70,8 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface /** * Selects the maximum value of a field from a query - * - * @param bool|string $as */ - public function selectMax(string $field, $as=FALSE): self + public function selectMax(string $field, bool|string $as=FALSE): self { // Create the select string $this->state->appendSelectString(' MAX' . $this->_select($field, $as)); @@ -83,10 +81,8 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface /** * Selects the minimum value of a field from a query - * - * @param bool|string $as */ - public function selectMin(string $field, $as=FALSE): self + public function selectMin(string $field, bool|string $as=FALSE): self { // Create the select string $this->state->appendSelectString(' MIN' . $this->_select($field, $as)); @@ -96,10 +92,8 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface /** * Selects the average value of a field from a query - * - * @param bool|string $as */ - public function selectAvg(string $field, $as=FALSE): self + public function selectAvg(string $field, bool|string $as=FALSE): self { // Create the select string $this->state->appendSelectString(' AVG' . $this->_select($field, $as)); @@ -109,10 +103,8 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface /** * Selects the sum of a field from a query - * - * @param bool|string $as */ - public function selectSum(string $field, $as=FALSE): self + public function selectSum(string $field, bool|string $as=FALSE): self { // Create the select string $this->state->appendSelectString(' SUM' . $this->_select($field, $as)); @@ -391,7 +383,7 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface // Flatten key/val pairs into an array of space-separated pairs foreach ($this->state->getOrderArray() as $k => $v) { - $orderClauses[] = $k . ' ' . strtoupper($v); + $orderClauses[] = $k . ' ' . strtoupper((string) $v); } // Set the final string @@ -558,7 +550,7 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface /** * Creates and executes a batch insertion query */ - public function insertBatch(string $table, $data=[]): ?PDOStatement + public function insertBatch(string $table, mixed $data=[]): ?PDOStatement { // Get the generated values and sql string [$sql, $data] = $this->driver->insertBatch($table, $data); diff --git a/src/QueryBuilderBase.php b/src/QueryBuilderBase.php index c18c28b..835f628 100644 --- a/src/QueryBuilderBase.php +++ b/src/QueryBuilderBase.php @@ -17,9 +17,10 @@ namespace Query; use BadMethodCallException; - use PDO; + use PDOStatement; +use PHPUnit\Framework\Attributes\CodeCoverageIgnore; use Query\Drivers\DriverInterface; use function is_string; use function regexInArray; @@ -90,19 +91,13 @@ class QueryBuilderBase // -------------------------------------------------------------------------- // ! Methods // -------------------------------------------------------------------------- - /** - * Constructor - */ public function __construct(protected ?DriverInterface $driver, protected QueryParser $parser) { // Create new State object $this->state = new State(); } - /** - * Destructor - * @codeCoverageIgnore - */ + #[CodeCoverageIgnore] public function __destruct() { $this->driver = NULL; @@ -370,7 +365,7 @@ class QueryBuilderBase { $v = (is_numeric($v)) ? $v - : htmlentities($this->driver->quote($v), ENT_NOQUOTES, 'utf-8'); + : htmlentities((string) $this->driver->quote($v), ENT_NOQUOTES, 'utf-8'); } unset($v); @@ -392,9 +387,8 @@ class QueryBuilderBase /** * Sub-method for generating sql strings - * - * @codeCoverageIgnore */ + #[CodeCoverageIgnore] protected function _compileType(QueryType $type = QueryType::SELECT, string $table = ''): string { $setArrayKeys = $this->state->getSetArrayKeys(); diff --git a/src/QueryBuilderInterface.php b/src/QueryBuilderInterface.php index bf08dbc..efe740d 100644 --- a/src/QueryBuilderInterface.php +++ b/src/QueryBuilderInterface.php @@ -70,31 +70,23 @@ interface QueryBuilderInterface /** * Selects the maximum value of a field from a query - * - * @param bool|string $as */ - public function selectMax(string $field, $as=FALSE): self; + public function selectMax(string $field, bool|string $as=FALSE): self; /** * Selects the minimum value of a field from a query - * - * @param bool|string $as */ - public function selectMin(string $field, $as=FALSE): self; + public function selectMin(string $field, bool|string $as=FALSE): self; /** * Selects the average value of a field from a query - * - * @param bool|string $as */ - public function selectAvg(string $field, $as=FALSE): self; + public function selectAvg(string $field, bool|string $as=FALSE): self; /** * Selects the sum of a field from a query - * - * @param bool|string $as */ - public function selectSum(string $field, $as=FALSE): self; + public function selectSum(string $field, bool|string $as=FALSE): self; /** * Adds the 'distinct' keyword to a query @@ -196,8 +188,6 @@ interface QueryBuilderInterface // -------------------------------------------------------------------------- /** * Sets values for inserts / updates / deletes - * - * @param mixed $values */ public function set(mixed $key, mixed $values = NULL): self; diff --git a/src/QueryParser.php b/src/QueryParser.php index 9972da1..9a175b5 100644 --- a/src/QueryParser.php +++ b/src/QueryParser.php @@ -66,7 +66,7 @@ class QueryParser preg_match_all($fullPattern, $sql, $this->matches['combined'], PREG_SET_ORDER); // Go through the matches, and get the most relevant matches - $this->matches = array_map([$this, 'filterArray'], $this->matches); + $this->matches = array_map($this->filterArray(...), $this->matches); return $this->matches; } diff --git a/src/common.php b/src/common.php index f66d72b..d7b7d08 100644 --- a/src/common.php +++ b/src/common.php @@ -13,111 +13,109 @@ * @link https://git.timshomepage.net/aviat/Query * @version 4.0.0 */ -namespace { - use Query\ConnectionManager; - use Query\QueryBuilderInterface; +use Query\{ConnectionManager, QueryBuilderInterface}; - /** - * Global functions that don't really fit anywhere else - */ - /** - * Multibyte-safe trim function - */ - function mb_trim(string $string): string +/** + * Global functions that don't really fit anywhere else + */ +/** + * Multibyte-safe trim function + */ +function mb_trim(string $string): string +{ + return preg_replace('/(^\s+)|(\s+$)/u', '', $string); +} + +/** + * Filter out db rows into one array + */ +function dbFilter(array $array, mixed $index): array +{ + $newArray = []; + + foreach ($array as $a) { - return preg_replace('/(^\s+)|(\s+$)/u', '', $string); + $newArray[] = $a[$index]; } - /** - * Filter out db rows into one array - */ - function dbFilter(array $array, mixed $index): array + return $newArray; +} + +/** + * Zip a set of arrays together on common keys + * + * The $zipperInput array is an array of arrays indexed by their place in the output + * array. + */ +function arrayZipper(array $zipperInput): array +{ + $output = []; + + foreach ($zipperInput as $appendKey => $values) { - $newArray = []; - - foreach ($array as $a) + foreach ($values as $index => $value) { - $newArray[] = $a[$index]; - } - - return $newArray; - } - - /** - * Zip a set of arrays together on common keys - * - * The $zipperInput array is an array of arrays indexed by their place in the output - * array. - */ - function arrayZipper(array $zipperInput): array - { - $output = []; - - foreach ($zipperInput as $appendKey => $values) - { - foreach ($values as $index => $value) + if ( ! isset($output[$index])) { - if ( ! isset($output[$index])) - { - $output[$index] = []; - } - $output[$index][$appendKey] = $value; + $output[$index] = []; } + $output[$index][$appendKey] = $value; } - - return $output; } - /** - * Determine whether a value in the passed array matches the pattern - * passed - */ - function regexInArray(array $array, string $pattern): bool + return $output; +} + +/** + * Determine whether a value in the passed array matches the pattern + * passed + */ +function regexInArray(array $array, string $pattern): bool +{ + if (empty($array)) { - if (empty($array)) - { - return FALSE; - } - - foreach ($array as $item) - { - if (is_scalar($item) && preg_match($pattern, (string) $item)) - { - return TRUE; - } - } - return FALSE; } - /** - * Connection function - * - * Send an array or object as connection parameters to create a connection. If - * the array or object has an 'alias' parameter, passing that string to this - * function will return that connection. Passing no parameters returns the last - * connection created. - */ - function Query(string|object|array|null $params = ''): ?QueryBuilderInterface + foreach ($array as $item) { - if ($params === NULL) + if (is_scalar($item) && preg_match($pattern, (string) $item)) { - return NULL; + return TRUE; } - - $manager = ConnectionManager::getInstance(); - - // If you are getting a previously created connection - if (is_string($params)) - { - return $manager->getConnection($params); - } - - $paramsObject = (object)$params; - - // Otherwise, return a new connection - return $manager->connect($paramsObject); } + + return FALSE; } + +/** + * Connection function + * + * Send an array or object as connection parameters to create a connection. If + * the array or object has an 'alias' parameter, passing that string to this + * function will return that connection. Passing no parameters returns the last + * connection created. + */ +function Query(string|object|array|null $params = ''): ?QueryBuilderInterface +{ + if ($params === NULL) + { + return NULL; + } + + $manager = ConnectionManager::getInstance(); + + // If you are getting a previously created connection + if (is_string($params)) + { + return $manager->getConnection($params); + } + + $paramsObject = (object) $params; + + // Otherwise, return a new connection + return $manager->connect($paramsObject); +} + // End of common.php