diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9f59395 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +/.gitattributes export-ignore +/.github export-ignore +/.gitignore export-ignore +/infection.json.dist export-ignore +/phpstan-baseline.neon export-ignore +/phpstan.neon export-ignore +/phpunit.xml.dist export-ignore +/tests export-ignore +/tools export-ignore diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 01e3dd3..c226788 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -14,27 +14,27 @@ on: jobs: run: name: Run - runs-on: ubuntu-20.04 + runs-on: ${{ matrix.operating-system }} strategy: fail-fast: false - env: - key: cache-v1 + matrix: + operating-system: [ubuntu-latest] steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP with tools uses: shivammathur/setup-php@v2 with: - php-version: '8.1' + php-version: '8.5' extensions: mbstring, intl, opcache, xdebug, xml tools: composer, cs2pr - name: Get Composer cache directory id: composer-cache-dir run: | - echo "::set-output name=dir::$(composer config cache-files-dir)" + echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Restore composer cache id: composer-cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache-dir.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} @@ -44,7 +44,5 @@ jobs: run: rm -f composer.lock - name: Setup Composer run: composer install - - name: Setup PHPStan - run: tools/.phpstan/setup - name: Run PHPStan analysis - run: tools/phpstan analyse -c phpstan-use-baseline.neon + run: ./vendor/bin/phpstan analyse -c phpstan-use-baseline.neon diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 256ff36..62a3795 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,13 +18,11 @@ jobs: strategy: fail-fast: false matrix: - operating-system: [ubuntu-20.04] - php-versions: ['5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1'] - env: - key: cache-v1 + operating-system: [ubuntu-latest] + php-versions: ['8.1', '8.2', '8.3', '8.4', 8.5] steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP with tools uses: shivammathur/setup-php@v2 with: @@ -34,7 +32,7 @@ jobs: - name: Get Composer cache directory id: composer-cache-dir run: | - echo "::set-output name=dir::$(composer config cache-files-dir)" + echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Restore composer cache id: composer-cache uses: actions/cache@v3 diff --git a/.phpstan-baseline.neon b/.phpstan-baseline.neon deleted file mode 100644 index cb6d502..0000000 --- a/.phpstan-baseline.neon +++ /dev/null @@ -1,31 +0,0 @@ -parameters: - ignoreErrors: - - - message: "#^Generic type Teto\\\\SQL\\\\PDOAggregate\\\\> in PHPDoc tag @param for parameter \\$pdo does not specify all template types of interface Teto\\\\SQL\\\\PDOAggregate\\: S, T$#" - count: 2 - path: src/AbstractStaticQuery.php - - - - message: "#^Type PDO\\|Teto\\\\SQL\\\\PDOInterface\\ in generic type Teto\\\\SQL\\\\PDOAggregate\\\\> in PHPDoc tag @param for parameter \\$pdo is not subtype of template type S of PDOStatement\\|Teto\\\\SQL\\\\PDOStatementInterface of interface Teto\\\\SQL\\\\PDOAggregate\\.$#" - count: 2 - path: src/AbstractStaticQuery.php - - - - message: "#^Method Teto\\\\SQL\\\\Processor\\\\CallbackProcessor\\:\\:processQuery\\(\\) should return string but returns mixed\\.$#" - count: 1 - path: src/Processor/CallbackProcessor.php - - - - message: "#^Property Teto\\\\SQL\\\\Processor\\\\CallbackProcessor\\:\\:\\$callback with generic interface Teto\\\\SQL\\\\PDOInterface does not specify its types\\: T$#" - count: 1 - path: src/Processor/CallbackProcessor.php - - - - message: "#^Parameter \\#2 \\$callback of function preg_replace_callback expects callable\\(array\\\\)\\: string, Closure\\(array\\)\\: int\\|string given\\.$#" - count: 1 - path: src/Processor/PregCallbackReplacer.php - - - - message: "#^Parameter \\#2 \\$matches of method Teto\\\\SQL\\\\ReplacerInterface\\:\\:replaceQuery\\(\\) expects array\\, array\\ given\\.$#" - count: 1 - path: src/Processor/PregCallbackReplacer.php diff --git a/composer.json b/composer.json index 9fbc08b..c97faf6 100644 --- a/composer.json +++ b/composer.json @@ -15,12 +15,13 @@ "sql" ], "require": { - "php": ">=5.4" + "php": ">=8.1", + "ext-pdo": "*" }, "require-dev": { "php-coveralls/php-coveralls": "^2.1 || ^1.1", - "phpunit/phpunit": "^8.5 || ^7.5 || ^4.8", - "yoast/phpunit-polyfills": "^1.0" + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^9.6 || ^12.0" }, "autoload": { "psr-4": { diff --git a/mago.toml b/mago.toml new file mode 100644 index 0000000..cdceb1c --- /dev/null +++ b/mago.toml @@ -0,0 +1,36 @@ +# Welcome to Mago! +# For full documentation, see https://mago.carthage.software/tools/overview +php-version = "8.1.0" + +[source] +workspace = "." +paths = ["src/", "tests/"] +includes = ["vendor"] +excludes = [] + +[formatter] +print-width = 120 +tab-width = 4 +use-tabs = false + +[linter] +integrations = ["phpunit"] + +[linter.rules] +ambiguous-function-call = { enabled = false } +literal-named-argument = { enabled = false } +halstead = { effort-threshold = 7000 } + +[analyzer] +find-unused-definitions = true +find-unused-expressions = false +analyze-dead-code = false +memoize-properties = true +allow-possibly-undefined-array-keys = true +check-throws = false +check-missing-override = false +find-unused-parameters = false +strict-list-index-checks = false +no-boolean-literal-comparison = false +check-missing-type-hints = false +register-super-globals = true diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index cb6d502..86f80a5 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,31 +1,97 @@ parameters: ignoreErrors: - - message: "#^Generic type Teto\\\\SQL\\\\PDOAggregate\\\\> in PHPDoc tag @param for parameter \\$pdo does not specify all template types of interface Teto\\\\SQL\\\\PDOAggregate\\: S, T$#" + rawMessage: 'Generic type Teto\SQL\PDOAggregate> in PHPDoc tag @param for parameter $pdo does not specify all template types of interface Teto\SQL\PDOAggregate: S, T' + identifier: generics.lessTypes count: 2 path: src/AbstractStaticQuery.php - - message: "#^Type PDO\\|Teto\\\\SQL\\\\PDOInterface\\ in generic type Teto\\\\SQL\\\\PDOAggregate\\\\> in PHPDoc tag @param for parameter \\$pdo is not subtype of template type S of PDOStatement\\|Teto\\\\SQL\\\\PDOStatementInterface of interface Teto\\\\SQL\\\\PDOAggregate\\.$#" + rawMessage: Type PDO|Teto\SQL\PDOInterface in generic type Teto\SQL\PDOAggregate> in PHPDoc tag @param for parameter $pdo is not subtype of template type S of PDOStatement|Teto\SQL\PDOStatementInterface of interface Teto\SQL\PDOAggregate. + identifier: generics.notSubtype count: 2 path: src/AbstractStaticQuery.php - - message: "#^Method Teto\\\\SQL\\\\Processor\\\\CallbackProcessor\\:\\:processQuery\\(\\) should return string but returns mixed\\.$#" + rawMessage: 'Interface Teto\SQL\PDOInterface has type alias teto_pdo with generic interface Teto\SQL\PDOInterface but does not specify its types: T' + identifier: missingType.generics + count: 1 + path: src/PDOInterface.php + + - + rawMessage: 'Method Teto\SQL\Processor\CallbackProcessor::processQuery() should return string but returns mixed.' + identifier: return.type count: 1 path: src/Processor/CallbackProcessor.php - - message: "#^Property Teto\\\\SQL\\\\Processor\\\\CallbackProcessor\\:\\:\\$callback with generic interface Teto\\\\SQL\\\\PDOInterface does not specify its types\\: T$#" + rawMessage: 'Property Teto\SQL\Processor\CallbackProcessor::$callback with generic interface Teto\SQL\PDOInterface does not specify its types: T' + identifier: missingType.generics count: 1 path: src/Processor/CallbackProcessor.php - - message: "#^Parameter \\#2 \\$callback of function preg_replace_callback expects callable\\(array\\\\)\\: string, Closure\\(array\\)\\: int\\|string given\\.$#" + rawMessage: 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(array): (int|string) given.' + identifier: argument.type count: 1 path: src/Processor/PregCallbackReplacer.php - - message: "#^Parameter \\#2 \\$matches of method Teto\\\\SQL\\\\ReplacerInterface\\:\\:replaceQuery\\(\\) expects array\\, array\\ given\\.$#" + rawMessage: 'Parameter #2 $matches of method Teto\SQL\ReplacerInterface::replaceQuery() expects array, array given.' + identifier: argument.type count: 1 path: src/Processor/PregCallbackReplacer.php + + - + rawMessage: Cannot use array destructuring on mixed. + identifier: offsetAccess.nonArray + count: 1 + path: src/QueryBuilder.php + + - + rawMessage: 'Parameter #3 $type of method PDOStatement::bindParam() expects int, mixed given.' + identifier: argument.type + count: 1 + path: src/QueryBuilder.php + + - + rawMessage: 'Call to function assert() with true will always evaluate to true.' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Replacer/Placeholder.php + + - + rawMessage: 'Call to function is_string() with string will always evaluate to true.' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Replacer/Placeholder.php + + - + rawMessage: Cannot cast mixed to string. + identifier: cast.string + count: 1 + path: src/Replacer/Placeholder.php + + - + rawMessage: 'Parameter &$bind_values by-ref type of method Teto\SQL\Replacer\Placeholder::replaceQuery() expects array, array given.' + identifier: parameterByRef.type + count: 1 + path: src/Replacer/Placeholder.php + + - + rawMessage: 'Strict comparison using !== between non-falsy-string and ''0'' will always evaluate to true.' + identifier: notIdentical.alwaysTrue + count: 1 + path: src/Replacer/Placeholder.php + + - + rawMessage: 'Parameter #1 $value of method Teto\SQL\Type\PgIdentifier::quote() expects string, mixed given.' + identifier: argument.type + count: 1 + path: src/Type/PgIdentifier.php + + - + rawMessage: Unreachable statement - code above always terminates. + identifier: deadCode.unreachable + count: 1 + path: src/Type/PgIdentifier.php diff --git a/phpstan-use-baseline.neon b/phpstan-use-baseline.neon index 9ba7d48..6ce75b5 100644 --- a/phpstan-use-baseline.neon +++ b/phpstan-use-baseline.neon @@ -1,3 +1,3 @@ includes: - phpstan.dist.neon - - .phpstan-baseline.neon + - phpstan-baseline.neon diff --git a/phpstan.dist.neon b/phpstan.dist.neon index 1906f65..f83685a 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -5,3 +5,5 @@ parameters: - tests/ bootstrapFiles: - vendor/autoload.php +includes: + - vendor/phpstan/phpstan/conf/bleedingEdge.neon diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 460e867..be50364 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,6 +1,6 @@ - - ./tests/ - - - - src/ - - - - - - diff --git a/src/PDOInterface.php b/src/PDOInterface.php index 5f85936..7905392 100644 --- a/src/PDOInterface.php +++ b/src/PDOInterface.php @@ -5,7 +5,7 @@ /** * Interface for PHP Data Objects (PDO) compatible class * - * @copyright 1997-2016 the PHP Documentation Group + * @copyright 1997-2026 the PHP Documentation Group * @license https://www.php.net/manual/en/copyright.php CC-BY-3.0 * @link https://www.php.net/manual/class.pdo.php * @@ -27,7 +27,7 @@ interface PDOInterface * @link https://www.php.net/manual/pdo.begintransaction.php * @return bool Returns TRUE on success or FALSE on failure. */ - public function beginTransaction(); + public function beginTransaction(): bool; /** * Commits a transaction @@ -35,7 +35,7 @@ public function beginTransaction(); * @link https://www.php.net/manual/pdo.commit.php * @return bool Returns TRUE on success or FALSE on failure. */ - public function commit(); + public function commit(): bool; /** * Fetch the SQLSTATE associated with the last operation on the database handle @@ -43,7 +43,7 @@ public function commit(); * @link https://www.php.net/manual/pdo.errorcode.php * @return string|null Returns an SQLSTATE, a five characters alphanumeric identifier defined in the ANSI SQL-92 standard. Returns NULL if no operation has been run on the database handle. */ - public function errorCode(); + public function errorCode(): ?string; /** * Fetch extended error information associated with the last operation on the database handle @@ -51,16 +51,16 @@ public function errorCode(); * @link https://www.php.net/manual/pdo.errorinfo.php * @return array Returns an array of error information about the last operation performed by this database handle. */ - public function errorInfo(); + public function errorInfo(): array; /** * Execute an SQL statement and return the number of affected rows * * @link https://www.php.net/manual/pdo.exec.php * @param string $statement The SQL statement to prepare and execute. - * @return int Returns the number of rows that were modified or deleted by the SQL statement you issued. If no rows were affected, returns 0. + * @return int|false Returns the number of rows that were modified or deleted by the SQL statement you issued. If no rows were affected, returns 0. */ - public function exec($statement); + public function exec(string $statement): int|false; /** * Retrieve a database connection attribute @@ -69,7 +69,7 @@ public function exec($statement); * @param int $attribute One of the PDO::ATTR_* constants. * @return mixed */ - public function getAttribute($attribute); + public function getAttribute(int $attribute): mixed; /** * Return an array of available PDO drivers @@ -77,7 +77,7 @@ public function getAttribute($attribute); * @link https://www.php.net/manual/pdo.getavailabledrivers.php * @return string[] */ - public static function getAvailableDrivers(); + public static function getAvailableDrivers(): array; /** * Checks if inside a transaction @@ -85,47 +85,49 @@ public static function getAvailableDrivers(); * @link https://www.php.net/manual/pdo.intransaction.php * @return bool Returns TRUE if a transaction is currently active, and FALSE if not. */ - public function inTransaction(); + public function inTransaction(): bool; /** * Returns the ID of the last inserted row or sequence value * * @link https://www.php.net/manual/pdo.lastinsertid.php - * @param string $name - * @return string + * @param string|null $name + * @return string|false */ - public function lastInsertId($name = null); + public function lastInsertId(?string $name = null): string|false; /** * Prepares a statement for execution and returns a statement object * * @link https://www.php.net/manual/pdo.prepare.php * @param string $statement This must be a valid SQL statement template for the target database server. - * @param array $driver_options This array holds one or more key=>value pairs to set attribute values for the PDOStatement object that this method returns. + * @param array $options This array holds one or more key=>value pairs to set attribute values for the PDOStatement object that this method returns. * @return \PDOStatement|PDOStatementInterface|false * @phpstan-return T|false */ - public function prepare($statement, $driver_options = []); + public function prepare(string $statement, array $options = []); /** * Executes an SQL statement, returning a result set as a PDOStatement object * * @link http://php.net/manual/pdo.query.php * @param string $statement The SQL statement to prepare and execute. + * @param int|null $mode + * @param mixed ...$fetch_mode_args * @return \PDOStatement|PDOStatementInterface|false Returns a PDOStatement object, or FALSE on failure. * @phpstan-return T|false */ - public function query($statement); + public function query(string $statement, ?int $mode = null, mixed ...$fetch_mode_args); /** * Quotes a string for use in a query * * @link https://www.php.net/manual/pdo.quote.php * @param string $string The string to be quoted. - * @param int $parameter_type Provides a data type hint for drivers that have alternate quoting styles. - * @return string Returns a quoted string that is theoretically safe to pass into an SQL statement. Returns FALSE if the driver does not support quoting in this way. + * @param int $type Provides a data type hint for drivers that have alternate quoting styles. + * @return string|false Returns a quoted string that is theoretically safe to pass into an SQL statement. Returns FALSE if the driver does not support quoting in this way. */ - public function quote($string, $parameter_type = \PDO::PARAM_STR); + public function quote(string $string, int $type = \PDO::PARAM_STR): string|false; /** * Rolls back a transaction @@ -133,7 +135,7 @@ public function quote($string, $parameter_type = \PDO::PARAM_STR); * @link https://www.php.net/manual/pdo.rollback.php * @return bool Returns TRUE on success or FALSE on failure. */ - public function rollBack(); + public function rollBack(): bool; /** * Set an attribute @@ -143,5 +145,5 @@ public function rollBack(); * @param mixed $value * @return bool Returns TRUE on success or FALSE on failure. */ - public function setAttribute($attribute, $value); + public function setAttribute(int $attribute, mixed $value): bool; } diff --git a/src/PDOStatementInterface.php b/src/PDOStatementInterface.php index c3f6619..e14620c 100644 --- a/src/PDOStatementInterface.php +++ b/src/PDOStatementInterface.php @@ -1,10 +1,13 @@ $input_parameters + * @param ?array $params An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as PDO::PARAM_STR. + * @phpstan-param array|null $params * @return bool TRUE on success or FALSE on failure. */ - public function execute($input_parameters); + public function execute(?array $params = null): bool; /** * Fetches the next row from a result set * * @link https://www.php.net/manual/en/pdostatement.fetch.php - * @param int $fetch_style Controls how the next row will be returned to the caller. This value must be one of the PDO::FETCH_* constants, defaulting to value of PDO::ATTR_DEFAULT_FETCH_MODE (which defaults to PDO::FETCH_BOTH). - * @param int $cursor_orientation For a PDOStatement object representing a scrollable cursor, this value determines which row will be returned to the caller. This value must be one of the PDO::FETCH_ORI_* constants, defaulting to PDO::FETCH_ORI_NEXT. - * @param int $cursor_offset For a PDOStatement object representing a scrollable cursor for which the cursor_orientation parameter is set to PDO::FETCH_ORI_ABS, this value specifies the absolute number of the row in the result set that shall be fetched. + * @param int $mode Controls how the next row will be returned to the caller. This value must be one of the PDO::FETCH_* constants, defaulting to value of PDO::ATTR_DEFAULT_FETCH_MODE (which defaults to PDO::FETCH_BOTH). + * @param int $cursorOrientation For a PDOStatement object representing a scrollable cursor, this value determines which row will be returned to the caller. This value must be one of the PDO::FETCH_ORI_* constants, defaulting to PDO::FETCH_ORI_NEXT. + * @param int $cursorOffset For a PDOStatement object representing a scrollable cursor for which the cursor_orientation parameter is set to PDO::FETCH_ORI_ABS, this value specifies the absolute number of the row in the result set that shall be fetched. * @return mixed|false The return value of this function on success depends on the fetch type. In all cases, FALSE is returned on failure. */ - public function fetch($fetch_style = \PDO::ATTR_DEFAULT_FETCH_MODE, $cursor_orientation = \PDO::FETCH_ORI_NEXT, $cursor_offset = 0); + public function fetch( + int $mode = \PDO::FETCH_DEFAULT, + int $cursorOrientation = \PDO::FETCH_ORI_NEXT, + int $cursorOffset = 0, + ): mixed; /** * Returns an array containing all of the result set rows * * @link https://www.php.net/manual/en/pdostatement.fetchall.php - * @param int $fetch_style Controls the contents of the returned array as documented in PDOStatement::fetch(). Defaults to value of PDO::ATTR_DEFAULT_FETCH_MODE (which defaults to PDO::FETCH_BOTH) - * @param mixed $fetch_argument This argument has a different meaning depending on the value of the fetch_style parameter: + * @param int $mode Controls the contents of the returned array as documented in PDOStatement::fetch(). Defaults to value of PDO::ATTR_DEFAULT_FETCH_MODE (which defaults to PDO::FETCH_BOTH) + * @param mixed $args This argument has a different meaning depending on the value of the fetch_style parameter: * @param array $ctor_args * @phpstan-param list $ctor_args * @return array An array containing all of the remaining rows in the result set. The array represents each row as either an array of column values or an object with properties corresponding to each column name. An empty array is returned if there are zero results to fetch, or FALSE on failure. * @phpstan-return array */ - public function fetchAll($fetch_style, $fetch_argument = null, $ctor_args = array()); + public function fetchAll(int $mode = PDO::FETCH_DEFAULT, mixed $args = null, array $ctor_args = []): array; /** * Returns a single column from the next row of a result set * * @link https://www.php.net/manual/pdostatement.fetchcolumn.php - * @param int $column_number 0-indexed number of the column you wish to retrieve from the row. If no value is supplied, PDOStatement::fetchColumn() fetches the first column. - * @return mixed + * @param int $column 0-indexed number of the column you wish to retrieve from the row. If no value is supplied, PDOStatement::fetchColumn() fetches the first column. */ - public function fetchColumn($column_number = 0); + public function fetchColumn(int $column = 0): mixed; /** * Fetches the next row and returns it as an object * * @link https://www.php.net/manual/pdostatement.fetchobject.php - * @param string $class_name Name of the created class. - * @param array $ctor_args Elements of this array are passed to the constructor. - * @param list $ctor_args + * @param ?string $class Name of the created class. + * @phpstan-param class-string $class + * @param array $constructorArgs Elements of this array are passed to the constructor. + * @phpstan-param list $constructorArgs * @return object|false An instance of the required class with property names that correspond to the column names or FALSE on failure. */ - public function fetchObject($class_name = 'stdClass', $ctor_args = array()); + public function fetchObject(?string $class = 'stdClass', array $constructorArgs = []): object|false; /** * Retrieve a statement attribute * * @link https://www.php.net/manual/pdostatement.getattribute.php - * @param int $attribute Gets an attribute of the statement. + * @param int $name Gets an attribute of the statement. * @return mixed Returns the attribute value. */ - public function getAttribute($attribute); + public function getAttribute(int $name): mixed; /** * Returns metadata for a column in a result set @@ -165,7 +184,7 @@ public function getAttribute($attribute); * @return array|false An associative array containing the following values representing the metadata for a single column: * @phpstan-return array{native_type:non-empty-string, flags:list, name:string, table:string, len:int, precision:int, pdo_type:int}|false */ - public function getColumnMeta($column); + public function getColumnMeta(int $column): array|false; /** * Advances to the next rowset in a multi-rowset statement handle @@ -173,7 +192,7 @@ public function getColumnMeta($column); * @link https://www.php.net/manual/pdostatement.nextrowset.php * @return bool TRUE on success or FALSE on failure. */ - public function nextRowset(); + public function nextRowset(): bool; /** * Returns the number of rows affected by the last SQL statement @@ -181,7 +200,7 @@ public function nextRowset(); * @link https://www.php.net/manual/pdostatement.rowcount.php * @return int The number of rows. */ - public function rowCount(); + public function rowCount(): int; /** * Set a statement attribute @@ -191,7 +210,7 @@ public function rowCount(); * @param mixed $value * @return bool TRUE on success or FALSE on failure. */ - public function setAttribute($attribute, $value); + public function setAttribute(int $attribute, mixed $value): bool; /** * Set the default fetch mode for this statement @@ -207,5 +226,5 @@ public function setAttribute($attribute, $value); * @param ?array $ctorargs * @return bool TRUE on success or FALSE on failure. */ - public function setFetchMode($mode, $colno_or_classname_or_object, array $ctorargs = null); + public function setFetchMode(int $mode, $colno_or_classname_or_object, ?array $ctorargs = null): bool; } diff --git a/tests/DummyPDO.php b/tests/DummyPDO.php index 435ee43..42876ca 100644 --- a/tests/DummyPDO.php +++ b/tests/DummyPDO.php @@ -13,93 +13,82 @@ */ final class DummyPDO implements PDOInterface { - public function beginTransaction() + public function beginTransaction(): never { throw new BadMethodCallException('Not supported'); } - public function commit() + public function commit(): never { throw new BadMethodCallException('Not supported'); } - public function errorCode() + public function errorCode(): never { throw new BadMethodCallException('Not supported'); } - public function errorInfo() + public function errorInfo(): never { throw new BadMethodCallException('Not supported'); } - public function exec($statement) + public function exec(string $statement): never { throw new BadMethodCallException('Not supported'); } - public function getAttribute($attribute) + public function getAttribute(int $attribute): never { throw new BadMethodCallException('Not supported'); } - public static function getAvailableDrivers() + public static function getAvailableDrivers(): never { throw new BadMethodCallException('Not supported'); } - public function inTransaction() + public function inTransaction(): never { throw new BadMethodCallException('Not supported'); } - public function lastInsertId($name = null) + public function lastInsertId(?string $name = null): never { throw new BadMethodCallException('Not supported'); } - public function prepare($statement, $driver_options = array()) + public function prepare(string $statement, array $options = []): DummyPDOStatement { - return new DummyPDOStatement($statement, $driver_options); + return new DummyPDOStatement($statement, $options); } - public function query($statement) + public function query(string $statement, ?int $mode = null, mixed ...$fetch_mode_args): never { throw new BadMethodCallException('Not supported'); } /** - * @param string $string - * @param int $parameter_type - * @return string * @pure */ - public function quote($string, $parameter_type = \PDO::PARAM_STR) + public function quote(string $string, int $type = \PDO::PARAM_STR): string { - if ($parameter_type === \PDO::PARAM_STR) { + if ($type === \PDO::PARAM_STR) { return '@' . strtr($string, ['@' => '@@']) . '@'; } - if ($parameter_type === \PDO::PARAM_INT) { + if ($type === \PDO::PARAM_INT) { return $string; } - throw new LogicException("{$parameter_type} is not supported type."); + throw new LogicException("{$type} is not supported type."); } - /** - * @return bool - */ - public function rollBack() + public function rollBack(): never { throw new BadMethodCallException('Not supported'); } - /** - * @param int $attribute - * @param mixed $value - * @return bool - */ - public function setAttribute($attribute, $value) + public function setAttribute(int $attribute, mixed $value): never { throw new BadMethodCallException('Not supported'); } diff --git a/tests/DummyPDOStatement.php b/tests/DummyPDOStatement.php index 5c44f13..3a888b9 100644 --- a/tests/DummyPDOStatement.php +++ b/tests/DummyPDOStatement.php @@ -11,121 +11,129 @@ */ final class DummyPDOStatement implements PDOStatementInterface { - /** @var string */ - private $queryString; + private string $queryString; /** @var array */ - private $driverOptions; + private array $driverOptions; /** * @param string $query * @param array $driver_options */ - public function __construct($query, array $driver_options = array()) + public function __construct(string $query, array $driver_options = []) { $this->queryString = $query; $this->driverOptions = $driver_options; } - /** - * @param string $name - * @return mixed - */ - public function __get($name) + public function __get(string $name): mixed { return $this->$name; } - public function bindColumn($column, &$param, $type = null, $maxlen = null, $driverdata = null) - { + public function bindColumn( + int|string $column, + mixed &$var, + int $type = \PDO::PARAM_STR, + int $maxLength = 0, + mixed $driverOptions = null, + ): never { throw new BadMethodCallException('Unexpected method call'); } - public function bindParam($parameter, &$variable, $data_type = \PDO::PARAM_STR, $length = null, $driver_options = null) - { + public function bindParam( + int|string $param, + mixed &$var, + int $type = \PDO::PARAM_STR, + int $maxLength = 0, + mixed $driverOptions = null, + ): never { throw new BadMethodCallException('Unexpected method call'); } - public function bindValue($parameter, $value, $data_type = \PDO::PARAM_STR) + public function bindValue(int|string $param, mixed $value, int $type = \PDO::PARAM_STR): never { throw new BadMethodCallException('Unexpected method call'); } - public function closeCursor() + public function closeCursor(): never { throw new BadMethodCallException('Unexpected method call'); } - public function columnCount() + public function columnCount(): never { throw new BadMethodCallException('Unexpected method call'); } - public function debugDumpParams() + public function debugDumpParams(): never { throw new BadMethodCallException('Unexpected method call'); } - public function errorCode() + public function errorCode(): never { throw new BadMethodCallException('Unexpected method call'); } - public function errorInfo() + public function errorInfo(): never { throw new BadMethodCallException('Unexpected method call'); } - public function execute($input_parameters) + public function execute(?array $params = null): never { throw new BadMethodCallException('Unexpected method call'); } - public function fetch($fetch_style = \PDO::ATTR_DEFAULT_FETCH_MODE, $cursor_orientation = \PDO::FETCH_ORI_NEXT, $cursor_offset = 0) - { + public function fetch( + int $mode = \PDO::FETCH_DEFAULT, + int $cursorOrientation = \PDO::FETCH_ORI_NEXT, + int $cursorOffset = 0, + ): never { throw new BadMethodCallException('Unexpected method call'); } - public function fetchAll($fetch_style, $fetch_argument = null, $ctor_args = array()) + public function fetchAll(int $mode = \PDO::FETCH_DEFAULT, mixed $args = null, array $ctor_args = []): never { throw new BadMethodCallException('Unexpected method call'); } - public function fetchColumn($column_number = 0) + public function fetchColumn(int $column = 0): never { throw new BadMethodCallException('Unexpected method call'); } - public function fetchObject($class_name = 'stdClass', $ctor_args = array()) + public function fetchObject(?string $class = 'stdClass', array $constructorArgs = []): never { throw new BadMethodCallException('Unexpected method call'); } - public function getAttribute($attribute) + public function getAttribute(int $name): never { throw new BadMethodCallException('Unexpected method call'); } - public function getColumnMeta($column) + public function getColumnMeta(int $column): never { throw new BadMethodCallException('Unexpected method call'); } - public function nextRowset() + public function nextRowset(): never { throw new BadMethodCallException('Unexpected method call'); } - public function rowCount() + public function rowCount(): never { throw new BadMethodCallException('Unexpected method call'); } - public function setAttribute($attribute, $value) + public function setAttribute(int $attribute, mixed $value): never { throw new BadMethodCallException('Unexpected method call'); } - public function setFetchMode($mode, $colno_or_classname_or_object, array $ctorargs = null) + public function setFetchMode(int $mode, $colno_or_classname_or_object = null, ?array $ctorargs = null): never { throw new BadMethodCallException('Unexpected method call'); } diff --git a/tests/Processor/CallbackProcessorTest.php b/tests/Processor/CallbackProcessorTest.php index d669e9b..1b93096 100644 --- a/tests/Processor/CallbackProcessorTest.php +++ b/tests/Processor/CallbackProcessorTest.php @@ -2,15 +2,12 @@ namespace Teto\SQL\Processor; +use PHPUnit\Framework\TestCase; use Teto\SQL\DummyPDO; -use Yoast\PHPUnitPolyfills\TestCases\TestCase; class CallbackProcessorTest extends TestCase { - /** - * @return void - */ - public function test() + public function test(): void { $pdo = new DummyPDO(); diff --git a/tests/Processor/IfBlockTest.php b/tests/Processor/IfBlockTest.php index b284050..8b241ed 100644 --- a/tests/Processor/IfBlockTest.php +++ b/tests/Processor/IfBlockTest.php @@ -2,11 +2,9 @@ namespace Teto\SQL\Processor; -use Teto\SQL\QueryBuilder; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\TestCase; use Teto\SQL\DummyPDO; -use Yoast\PHPUnitPolyfills\Polyfills\ExpectException; -use Yoast\PHPUnitPolyfills\Polyfills\ExpectPHPException; -use Yoast\PHPUnitPolyfills\TestCases\TestCase; /** * @author USAMI Kenta @@ -15,13 +13,9 @@ */ final class IfBlockTest extends TestCase { - use ExpectException; - use ExpectPHPException; + private IfBlock $subject; - /** @var IfBlock */ - private $subject; - - public function set_up() + public function setUp(): void { $this->subject = new IfBlock(); } @@ -31,9 +25,9 @@ public function set_up() * @param string $input * @phpstan-param array $params * @param string $expected - * @return void */ - public function test_accept($input, array $params, $expected) + #[DataProvider('acceptDataProvider')] + public function test_accept($input, array $params, $expected): void { $pdo = new DummyPDO(); @@ -47,7 +41,7 @@ public function test_accept($input, array $params, $expected) /** * @phpstan-return iterable, string}> */ - public function acceptDataProvider() + public static function acceptDataProvider() { $query_has_if = '%if :cond Then! @@ -84,10 +78,14 @@ public function acceptDataProvider() return [ [ - 'No condition', [], 'No condition', + 'No condition', + [], + 'No condition', ], [ - '"%if :cond" in literal', [], '"%if :cond" in literal', + '"%if :cond" in literal', + [], + '"%if :cond" in literal', ], [ $query_has_if, @@ -102,7 +100,7 @@ public function acceptDataProvider() [ $query_has_if_single_line, [':cond' => false], - " Rest", + ' Rest', ], [ $query_has_if_else, @@ -112,7 +110,7 @@ public function acceptDataProvider() [ $query_has_if_else_single_line, [':cond' => false], - "Else! Rest", + 'Else! Rest', ], [ implode("\n", [$query_has_if_else, $query_has_if_else]), @@ -149,7 +147,6 @@ public function acceptDataProvider() [':cond' => false], "\nRest", ], - ]; } @@ -158,9 +155,9 @@ public function acceptDataProvider() * @param string $input * @phpstan-param array $params * @param string $expected_message - * @return void */ - public function test_raise_exception($input, array $params, $expected_message) + #[DataProvider('rejeceptDataProvider')] + public function test_raise_exception($input, array $params, $expected_message): void { $pdo = new DummyPDO(); @@ -174,7 +171,7 @@ public function test_raise_exception($input, array $params, $expected_message) /** * @return iterable */ - public function rejeceptDataProvider() + public static function rejeceptDataProvider() { return [ [ diff --git a/tests/QueryTest.php b/tests/QueryTest.php index 0b3813a..1b7c84e 100644 --- a/tests/QueryTest.php +++ b/tests/QueryTest.php @@ -2,7 +2,8 @@ namespace Teto\SQL; -use Yoast\PHPUnitPolyfills\TestCases\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\TestCase; /** * @author USAMI Kenta @@ -15,10 +16,9 @@ final class QueryTest extends TestCase * @dataProvider queryProvider * @param non-empty-string $query * @param array $params - * @param string $expected - * @return void */ - public function test($query, array $params, $expected) + #[DataProvider('queryProvider')] + public function test(string $query, array $params, string $expected): void { $pdo = new DummyPDO(); $stmt = Query::build($pdo, $query, $params); @@ -29,7 +29,7 @@ public function test($query, array $params, $expected) /** * @return array, string}> */ - public function queryProvider() + public static function queryProvider() { return [ [ @@ -44,11 +44,10 @@ public function queryProvider() ], [ <<<'SQL' -SELECT foo, bar, buz -FROM hoge -WHERE id = :id@int -SQL -, + SELECT foo, bar, buz + FROM hoge + WHERE id = :id@int + SQL, [ ':id' => 12345, ], @@ -56,14 +55,13 @@ public function queryProvider() ], [ <<<'SQL' -SELECT foo, bar, buz -FROM hoge -WHERE id = :id@int -%if :order - ORDER BY id ASC -%endif -SQL -, + SELECT foo, bar, buz + FROM hoge + WHERE id = :id@int + %if :order + ORDER BY id ASC + %endif + SQL, [ ':id' => 12345, ':order' => true, @@ -72,14 +70,13 @@ public function queryProvider() ], [ <<<'SQL' -SELECT foo, bar, buz -FROM hoge -WHERE id = :id@int -%if :order - ORDER BY id ASC -%endif -SQL -, + SELECT foo, bar, buz + FROM hoge + WHERE id = :id@int + %if :order + ORDER BY id ASC + %endif + SQL, [ ':id' => 12345, ':order' => false, @@ -88,14 +85,13 @@ public function queryProvider() ], [ <<<'SQL' -SELECT foo, bar, buz -FROM hoge -WHERE id IN (:ids@int[]) -%if :order - ORDER BY id ASC -%endif -SQL -, + SELECT foo, bar, buz + FROM hoge + WHERE id IN (:ids@int[]) + %if :order + ORDER BY id ASC + %endif + SQL, [ ':ids' => [12345, 23456, 78901], ':order' => false, @@ -104,13 +100,12 @@ public function queryProvider() ], [ <<<'SQL' -INSERT INTO hoge -VALUES -%for[,] :values - (:id@int, :name@string) -%endfor -SQL -, + INSERT INTO hoge + VALUES + %for[,] :values + (:id@int, :name@string) + %endfor + SQL, [ ':id' => 12345, ':values' => [ diff --git a/tests/Replacer/ForBlockTest.php b/tests/Replacer/ForBlockTest.php index 970aff2..dcaeb76 100644 --- a/tests/Replacer/ForBlockTest.php +++ b/tests/Replacer/ForBlockTest.php @@ -4,12 +4,10 @@ use DomainException; use OutOfRangeException; -use Teto\SQL\QueryBuilder; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\TestCase; use Teto\SQL\DummyPDO; use Teto\SQL\Processor\PregCallbackReplacer; -use Yoast\PHPUnitPolyfills\Polyfills\ExpectException; -use Yoast\PHPUnitPolyfills\Polyfills\ExpectPHPException; -use Yoast\PHPUnitPolyfills\TestCases\TestCase; /** * @author USAMI Kenta @@ -18,28 +16,24 @@ */ final class ForBlockTest extends TestCase { - use ExpectException; - use ExpectPHPException; + private PregCallbackReplacer $subject; - /** @var PregCallbackReplacer */ - private $subject; - - public function set_up() + public function setUp(): void { + parent::setUp(); + $placeholder_replacer = new Placeholder(); $this->subject = new PregCallbackReplacer([ - new ForBlock([new PregCallbackReplacer([$placeholder_replacer])]) + new ForBlock([new PregCallbackReplacer([$placeholder_replacer])]), ]); } /** * @dataProvider acceptDataProvider - * @param string $input * @phpstan-param array $params - * @param string $expected - * @return void */ - public function test_accept($input, array $params, $expected) + #[DataProvider('acceptDataProvider')] + public function test_accept(string $input, array $params, string $expected): void { $pdo = new DummyPDO(); @@ -53,7 +47,7 @@ public function test_accept($input, array $params, $expected) /** * @phpstan-return iterable, string}> */ - public function acceptDataProvider() + public static function acceptDataProvider() { $query_has_if = '%for :arr Then! @@ -62,10 +56,14 @@ public function acceptDataProvider() return [ [ - 'No collection', [], 'No collection', + 'No collection', + [], + 'No collection', ], [ - '"%for :arr" in literal', [], '"%for :arr" in literal', + '"%for :arr" in literal', + [], + '"%for :arr" in literal', ], [ '%for :arr @@ -76,7 +74,7 @@ public function acceptDataProvider() [':a' => 'A1', ':b' => 'B1'], [':a' => 'A2', ':b' => 'B2'], [':a' => 'A3', ':b' => 'B3'], - ] + ], ], '@A1@ - @B1@,@A2@ - @B2@,@A3@ - @B3@', ], @@ -87,7 +85,7 @@ public function acceptDataProvider() [':a' => 'A1', ':b' => 'B1'], [':a' => 'A2', ':b' => 'B2'], [':a' => 'A3', ':b' => 'B3'], - ] + ], ], '@A1@ - @B1@,@A2@ - @B2@,@A3@ - @B3@', ], @@ -98,7 +96,7 @@ public function acceptDataProvider() [':a' => 'A1', ':b' => 'B1'], [':a' => 'A2', ':b' => 'B2'], [':a' => 'A3', ':b' => 'B3'], - ] + ], ], '@A1@ - @B1@,@A2@ - @B2@,@A3@ - @B3@', ], @@ -109,7 +107,7 @@ public function acceptDataProvider() [':a' => 'A1', ':b' => 'B1'], [':a' => 'A2', ':b' => 'B2'], [':a' => 'A3', ':b' => 'B3'], - ] + ], ], '@A1@ - @B1@,@A2@ - @B2@,@A3@ - @B3@', ], @@ -118,12 +116,11 @@ public function acceptDataProvider() /** * @dataProvider rejeceptDataProvider - * @param string $input * @phpstan-param array $params * @phpstan-param array{class: class-string<\Exception>, message: string} $expected - * @return void */ - public function test_raise_exception($input, array $params, array $expected) + #[DataProvider('rejeceptDataProvider')] + public function test_raise_exception(string $input, array $params, array $expected): void { $pdo = new DummyPDO(); @@ -131,13 +128,13 @@ public function test_raise_exception($input, array $params, array $expected) $this->expectExceptionMessage($expected['message']); $bind_values = []; - $actual = $this->subject->processQuery($pdo, $input, $params, $bind_values); + $_ = $this->subject->processQuery($pdo, $input, $params, $bind_values); } /** * @return iterable, array{class: class-string<\Exception>, message: string}}> */ - public function rejeceptDataProvider() + public static function rejeceptDataProvider() { return [ [ @@ -148,7 +145,7 @@ public function rejeceptDataProvider() [ 'class' => get_class(new DomainException()), 'message' => 'Must be assigned parameter :arr.', - ] + ], ], [ '%for :arr @@ -159,12 +156,12 @@ public function rejeceptDataProvider() [':a' => 'A1', ':b' => 'B1'], [':a' => 'A2'], [':a' => 'A3', ':b' => 'B3'], - ] + ], ], [ 'class' => get_class(new OutOfRangeException()), 'message' => 'param ":b" expected but not assigned', - ] + ], ], ]; } diff --git a/tests/Replacer/PlaceholderTest.php b/tests/Replacer/PlaceholderTest.php index f9d72b8..99e5650 100644 --- a/tests/Replacer/PlaceholderTest.php +++ b/tests/Replacer/PlaceholderTest.php @@ -2,47 +2,39 @@ namespace Teto\SQL\Replacer; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\TestCase; use Teto\SQL\DummyPDO; -use Teto\SQL\QueryBuilder; -use Yoast\PHPUnitPolyfills\Polyfills\ExpectException; -use Yoast\PHPUnitPolyfills\Polyfills\ExpectPHPException; -use Yoast\PHPUnitPolyfills\TestCases\TestCase; /** * @author USAMI Kenta * @copyright 2019 USAMI Kenta * @license https://github.com/BaguettePHP/TetoSQL/blob/master/LICENSE MPL-2.0 */ -final class ReplaceHolderTest extends TestCase +final class PlaceholderTest extends TestCase { - use ExpectException; - use ExpectPHPException; + private Placeholder $subject; - /** @var Placeholder */ - private $subject; - - public function set_up() + public function setUp(): void { - $this->subject = new Placeholder( - ':', - [ - '@dummy' => new Sample\DummyType(), - ] - ); + parent::setUp(); + + $this->subject = new Placeholder(':', [ + '@dummy' => new Sample\DummyType(), + ]); } /** * @dataProvider acceptDataProvider - * @param string $type - * @param mixed $input - * @param string|int $expected - * @return void */ - public function test_accept($type, $input, $expected) + #[DataProvider('acceptDataProvider')] + public function test_accept(string $type, mixed $input, string|int $expected): void { $pdo = new DummyPDO(); - $actual = $this->subject->replaceHolder($pdo, ':key', "@{$type}", $input, $bind_values);; + $actual = $this->subject->replaceHolder($pdo, ':key', "@{$type}", $input, $bind_values); + + ; $this->assertSame($expected, $actual); } @@ -50,7 +42,7 @@ public function test_accept($type, $input, $expected) /** * @return iterable */ - public function acceptDataProvider() + public static function acceptDataProvider() { return [ ['ascdesc', 'ASC', 'ASC'], @@ -62,7 +54,7 @@ public function acceptDataProvider() ['int', 0, 0], ['int', '0', 0], ['int', '9223372036854775807', 9223372036854775807], - ['int', '-9223372036854775808', (int)'-9223372036854775808'], + ['int', '-9223372036854775808', (int) '-9223372036854775808'], ['int[]', [0], '0'], ['int[]', ['0'], '0'], ['int[]', [0, 0], '0,0'], @@ -77,10 +69,7 @@ public function acceptDataProvider() ['int[]', ['1', '2', '0', '3'], '1,2,0,3'], ['int[]', [1, 2, 3, 0], '1,2,3,0'], ['int[]', ['1', '2', '3', '0'], '1,2,3,0'], - ['int[]', - ['9223372036854775807', '-9223372036854775808'], - '9223372036854775807,-9223372036854775808', - ], + ['int[]', ['9223372036854775807', '-9223372036854775808'], '9223372036854775807,-9223372036854775808'], ['string', 0, '@0@'], ['string', '0', '@0@'], ['string', '', '@@'], @@ -94,9 +83,9 @@ public function acceptDataProvider() * @param string $type * @param mixed $input * @param string $expected_message - * @return void */ - public function test_raise_exception($type, $input, $expected_message) + #[DataProvider('rejeceptDataProvider')] + public function test_raise_exception(string $type, mixed $input, string $expected_message): void { $pdo = new DummyPDO(); @@ -109,7 +98,7 @@ public function test_raise_exception($type, $input, $expected_message) /** * @return iterable */ - public function rejeceptDataProvider() + public static function rejeceptDataProvider() { return [ ['', null, 'type specifier for param ":key" not found'], diff --git a/tests/SQLite/QueryTest.php b/tests/SQLite/QueryTest.php index 4c16c4c..566e005 100644 --- a/tests/SQLite/QueryTest.php +++ b/tests/SQLite/QueryTest.php @@ -2,17 +2,17 @@ namespace Teto\SQL\SQLite; +use PDO; +use PHPUnit\Framework\TestCase; use Teto\SQL\Query; -use Yoast\PHPUnitPolyfills\TestCases\TestCase; final class QueryTest extends TestCase { - /** @var \PDO */ - private $pdo; + private PDO $pdo; - public function set_up() + public function setUp(): void { - parent::set_up(); + parent::setUp(); $pdo = $this->getPDO(); $pdo->exec(self::DROP_TABLE); @@ -35,7 +35,7 @@ public function set_up() */ public function getPDO() { - if ($this->pdo === null) { + if (!isset($this->pdo)) { $dsn = 'sqlite:/' . __DIR__ . '/db.sq3'; $this->pdo = new \PDO($dsn, null, null, [\PDO::ATTR_PERSISTENT => true]); } @@ -43,16 +43,13 @@ public function getPDO() return $this->pdo; } - /** - * @return void - */ - public function test() + public function test(): void { $pdo = $this->getPDO(); $img_file = dirname(__DIR__) . '/fuji36_01.jpg'; $id = Query::executeAndReturnInsertId($pdo, self::INSERT, [ - ':name' => 'Thirty-six Views of Mount Fuji', + ':name' => 'Thirty-six Views of Mount Fuji', ':cover' => fopen($img_file, 'rb'), ]); diff --git a/tests/Type/PgIdentifierTest.php b/tests/Type/PgIdentifierTest.php index 8cc1369..1ed7e3c 100644 --- a/tests/Type/PgIdentifierTest.php +++ b/tests/Type/PgIdentifierTest.php @@ -3,18 +3,17 @@ namespace Teto\SQL\Type; use DomainException; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\TestCase; use Teto\SQL\DummyPDO; -use Yoast\PHPUnitPolyfills\TestCases\TestCase; class PgIdentifierTest extends TestCase { - /** @var PgIdentifier */ - private $subject; + private PgIdentifier $subject; - public function set_up() + public function setUp(): void { - /** @noinspection PhpMultipleClassDeclarationsInspection */ - parent::set_up(); + parent::setUp(); $this->subject = new PgIdentifier([]); } @@ -22,38 +21,36 @@ public function set_up() /** * @dataProvider escapeValuesProvider * @phpstan-param string|array|bool $input - * @param string $type - * @param string $expected - * @return void */ - public function testEscapeValue($input, $type, $expected) + #[DataProvider('escapeValuesProvider')] + public function testEscapeValue(mixed $input, string $type, string $expected): void { $pdo = new DummyPDO(); $bind_values = []; - $this->assertSame($expected, $this->subject->escapeValue($pdo, ':key', $type, $input, $bind_values)); + $this->assertSame($expected, $this->subject->escapeValue($pdo, ':key', $type, $input, $bind_values)); $this->assertEquals([], $bind_values); } /** * @return array|bool,string,string}> */ - public function escapeValuesProvider() + public static function escapeValuesProvider() { return [ - ['' , '@column', '""'], - ['abc' , '@column', '"abc"'], - ['ABC' , '@column', '"ABC"'], - ['ABC\\ABC\'' , '@column', '"ABC\\ABC\'"'], - ['ABC"ABC' , '@column', '"ABC""ABC"'], - ['ABC"""ABC' , '@column', '"ABC""""""ABC"'], - [['foo'] , '@column[]', '"foo"'], - [['foo','bar'] , '@column[]', '"foo","bar"'], - [['foo' => 'bar'] , '@column[]', 'foo AS "bar"'], - [['"foo"' => 'bar'] , '@column[]', '"foo" AS "bar"'], - [['foo' => null] , '@column[]', 'foo'], - [['"foo"' => null] , '@column[]', '"foo"'], - [['foo' => null, 'bar' => 'buz'] , '@column[]', 'foo,bar AS "buz"'], - [['"foo"' => null, 'bar' => ''] , '@column[]', '"foo",bar'], + ['', '@column', '""'], + ['abc', '@column', '"abc"'], + ['ABC', '@column', '"ABC"'], + ['ABC\\ABC\'', '@column', '"ABC\\ABC\'"'], + ['ABC"ABC', '@column', '"ABC""ABC"'], + ['ABC"""ABC', '@column', '"ABC""""""ABC"'], + [['foo'], '@column[]', '"foo"'], + [['foo', 'bar'], '@column[]', '"foo","bar"'], + [['foo' => 'bar'], '@column[]', 'foo AS "bar"'], + [['"foo"' => 'bar'], '@column[]', '"foo" AS "bar"'], + [['foo' => null], '@column[]', 'foo'], + [['"foo"' => null], '@column[]', '"foo"'], + [['foo' => null, 'bar' => 'buz'], '@column[]', 'foo,bar AS "buz"'], + [['"foo"' => null, 'bar' => ''], '@column[]', '"foo",bar'], [true, '@bool', 'TRUE'], [false, '@bool', 'FALSE'], ]; @@ -62,27 +59,25 @@ public function escapeValuesProvider() /** * @dataProvider escapeValuesUnexpectedValuesProvider * @phpstan-param string|array $input - * @param string $type * @phpstan-param array{class: class-string<\Exception>, message: non-empty-string} $expected - * @return void */ - public function testEscapeValue_raiseError($input, $type, array $expected) + #[DataProvider('escapeValuesUnexpectedValuesProvider')] + public function testEscapeValue_raiseError(mixed $input, string $type, array $expected): void { $this->expectException($expected['class']); $this->expectExceptionMessage($expected['message']); $pdo = new DummyPDO(); $bind_values = []; - $_ = $this->subject->escapeValue($pdo, ':key', $type, $input, $bind_values); + $_ = $this->subject->escapeValue($pdo, ':key', $type, $input, $bind_values); } /** * @return array, message: non-empty-string}}> */ - public function escapeValuesUnexpectedValuesProvider() + public static function escapeValuesUnexpectedValuesProvider() { - /** @phpstan-var class-string $DomainException */ - $DomainException = 'DomainException'; + $DomainException = \DomainException::class; return [ [1, '@bool', ['class' => $DomainException, 'message' => 'param ":key" must be bool']], @@ -102,11 +97,9 @@ public function escapeValuesUnexpectedValuesProvider() /** * @dataProvider quoteValueProvider - * @param string $input - * @param string $expected - * @return void */ - public function testQuote($input, $expected) + #[DataProvider('quoteValueProvider')] + public function testQuote(string $input, string $expected): void { $this->assertSame($expected, $this->subject->quote($input)); } @@ -114,11 +107,11 @@ public function testQuote($input, $expected) /** * @return array */ - public function quoteValueProvider() + public static function quoteValueProvider() { return [ - ['' , '""'], - ['foo' , '"foo"'], + ['', '""'], + ['foo', '"foo"'], ]; } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 1c0b890..d94e006 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,4 +1,5 @@