Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 15 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,19 @@ jobs:

strategy:
matrix:
php: ['8.0', 8.1, 8.2]
lib:
- { laravel: ^11.0 }
- { laravel: ^10.0 }
- { laravel: ^9.0 }
php: [8.2, 8.3, 8.4]
laravel:
- ^13.0.x-dev
- ^12.0
- ^11.0
exclude:
- { php: 8.0, lib: { laravel: ^10.0 } }
- { php: 8.0, lib: { laravel: ^11.0 } }
- { php: 8.1, lib: { laravel: ^11.0 } }
- php: 8.2
laravel: ^13.0.x-dev
include:
- { lib: { laravel: ^9.0 }, phpstan: 1 }
- { lib: { laravel: ^10.0 }, phpstan: 1 }
- laravel: ^11.0
larastan: 1
- laravel: ^12.0
larastan: 1

steps:
- uses: actions/checkout@v3
Expand All @@ -47,20 +48,17 @@ jobs:
coverage: xdebug

- name: Remove impossible dependencies
if: ${{ matrix.phpstan != 1 }}
if: ${{ matrix.larastan != 1 }}
run: composer remove nunomaduro/larastan --dev --no-update

- name: Adjust Package Versions
run: |
composer require "laravel/framework:${{ matrix.lib.laravel }}" --dev
composer require "laravel/framework:${{ matrix.laravel }}" --dev

- name: PHPStan
if: ${{ matrix.phpstan == 1 }}
if: ${{ matrix.larastan == 1 }}
run: composer phpstan

- name: Clean up Larastan broken cache (Dirty hack for bugs)
run: rm -f vendor/orchestra/testbench-core/laravel/vendor vendor/orchestra/testbench-core/laravel/bootstrap/cache/*.php

- run: mkdir -p build/logs
- run: vendor/bin/phpunit --coverage-clover build/logs/clover.xml

Expand All @@ -69,7 +67,7 @@ jobs:
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_PARALLEL: 'true'
COVERALLS_FLAG_NAME: 'laravel:${{ matrix.lib.laravel }}'
COVERALLS_FLAG_NAME: 'laravel:${{ matrix.laravel }}'
with:
timeout_minutes: 1
max_attempts: 3
Expand Down
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ Temporarily enable/disable PDO prepared statement emulation.

## Requirements

| Package | Version | Mandatory |
|:--------|:-----------------------------------------------------------------------------------------|:---------:|
| PHP | <code>^8.0</code> | ✅ |
| Laravel | <code>^9.0 &#124;&#124; ^10.0</code> | ✅ |
| PHPStan | <code>&gt;=1.1</code> | |
| Package | Version | Mandatory |
|:--------|:--------------------------------------|:---------:|
| PHP | <code>^8.2</code> | ✅ |
| Laravel | <code>^11.0 &#124;&#124; ^12.0</code> | ✅ |
| PHPStan | <code>&gt;=2.0</code> | |

> [!NOTE]
> Older versions have outdated dependency requirements. If you cannot prepare the latest environment, please refer to past releases.

## Installing

Expand Down
20 changes: 10 additions & 10 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@
}
},
"require": {
"php": "^8.0",
"php": "^8.2",
"ext-pdo": "*",
"illuminate/database": "^9.0 || ^10.0 || ^11.0",
"illuminate/support": "^9.0 || ^10.0 || ^11.0",
"mpyw/unclosure": "^3.0"
"illuminate/database": "^11.0 || ^12.0 || ^13.0",
"illuminate/support": "^11.0 || ^12.0 || ^13.0",
"mpyw/unclosure": "^3.1"
},
"require-dev": {
"orchestra/testbench": "*",
"orchestra/testbench-core": ">=7.0",
"mockery/mockery": "^1.3.3 || ^1.4.2",
"phpunit/phpunit": ">=9.5",
"phpstan/phpstan": ">=1.1",
"phpstan/extension-installer": ">=1.1",
"nunomaduro/larastan": ">=1.0"
"orchestra/testbench-core": ">=9.0",
"mockery/mockery": "^1.6.12",
"phpunit/phpunit": ">=11.0",
"phpstan/phpstan": ">=2.0",
"phpstan/extension-installer": ">=1.4",
"nunomaduro/larastan": ">=3.1"
},
"scripts": {
"test": "vendor/bin/phpunit",
Expand Down
4 changes: 2 additions & 2 deletions phpstan/CallableParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
final class CallableParameter implements ParameterReflection
{
/**
* @var CallableArgumentParameter[]
* @var list<CallableArgumentParameter>
*/
private array $argumentParameters;

/**
* @param CallableArgumentParameter[] $argumentParameters
* @param list<CallableArgumentParameter> $argumentParameters
*/
public function __construct(array $argumentParameters)
{
Expand Down
2 changes: 1 addition & 1 deletion phpstan/ConnectionClassExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ final class ConnectionClassExtension implements MethodsClassReflectionExtension
public function hasMethod(ClassReflection $classReflection, string $methodName): bool
{
return \in_array($methodName, ['emulated', 'native'], true)
&& \is_a($classReflection->getName(), ConnectionInterface::class, true);
&& $classReflection->is(ConnectionInterface::class);
}

public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
Expand Down
20 changes: 15 additions & 5 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
<coverage>
<phpunit backupGlobals="false"
bootstrap="vendor/autoload.php"
colors="true"
processIsolation="false"
stopOnFailure="false"
cacheDirectory=".phpunit.cache"
backupStaticProperties="false">

<source>
<include>
<directory suffix=".php">src</directory>
<directory>./src</directory>
</include>
</coverage>
</source>

<coverage/>

<testsuites>
<testsuite name="Package Test Suite">
<directory suffix="Test.php">./tests/</directory>
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
</phpunit>
5 changes: 4 additions & 1 deletion src/EmulationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ class EmulationController
/**
* EmulationController constructor.
*
* @param null|\Closure|\PDO &...$pdos
* @param \Closure|\PDO &...$pdos
*/
// @phpstan-ignore-next-line parameterByRef.unusedType
public function __construct(&...$pdos)
{
// @phpstan-ignore arrayFilter.same
$this->pdos = array_filter($pdos);
}

Expand Down Expand Up @@ -50,6 +52,7 @@ public function native(callable $callback, ...$args)
*/
public function switchingTo(bool $bool, callable $callback, ...$args)
{
// @phpstan-ignore assign.propertyType
return Value::withEffectForEach($this->pdos, function (PDO $pdo) use ($bool) {
$original = $pdo->getAttribute(PDO::ATTR_EMULATE_PREPARES);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, $bool);
Expand Down
72 changes: 49 additions & 23 deletions tests/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Mpyw\LaravelPdoEmulationControl\ConnectionServiceProvider;
use Orchestra\Testbench\TestCase;
use PDO;
use PHPUnit\Framework\ExpectationFailedException;

class IntegrationTest extends TestCase
{
Expand Down Expand Up @@ -36,13 +37,12 @@ protected function getEnvironmentSetUp($app): void
/**
* @param string $property
* @return \Closure|\PDO
* @noinspection PhpDocMissingThrowsInspection
*/
protected function getConnectionPropertyValue(string $property)
protected function getConnectionPropertyValue(string $property): \Closure|\PDO
{
$db = DB::connection();
$rp = new \ReflectionProperty($db, $property);
$rp->setAccessible(true);
$value = $rp->getValue($db);
/** @noinspection PhpUnhandledExceptionInspection */
$value = (new \ReflectionProperty($db = DB::connection(), $property))->getValue($db);

assert($value instanceof Closure || $value instanceof PDO);

Expand Down Expand Up @@ -80,13 +80,39 @@ protected function getPackageProviders($app): array
];
}

/**
* @throws ExpectationFailedException
*
* @phpstan-assert false $condition
*/
protected function assertPdoAttrTruthy(mixed $condition, string $message = ''): void {
if (version_compare(PHP_VERSION, '8.4', '>=')) {
$this->assertTrue($condition, $message);
} else {
$this->assertSame(1, $condition, $message);
}
}

/**
* @throws ExpectationFailedException
*
* @phpstan-assert false $condition
*/
protected function assertPdoAttrFalsy(mixed $condition, string $message = ''): void {
if (version_compare(PHP_VERSION, '8.4', '>=')) {
$this->assertFalse($condition, $message);
} else {
$this->assertSame(0, $condition, $message);
}
}

public function testEagerEmulated(): void
{
$this->assertPdoNotResolved();
$this->assertReadPdoNotResolved();

$this->assertSame(0, DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertSame(0, DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrFalsy(DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrFalsy(DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));

$this->assertPdoResolved();
$this->assertReadPdoResolved();
Expand All @@ -95,8 +121,8 @@ public function testEagerEmulated(): void
$this->assertPdoResolved();
$this->assertReadPdoResolved();

$this->assertSame(1, DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertSame(1, DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrTruthy(DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrTruthy(DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));

$this->assertPdoResolved();
$this->assertReadPdoResolved();
Expand All @@ -107,8 +133,8 @@ public function testEagerEmulated(): void
$this->assertPdoResolved();
$this->assertReadPdoResolved();

$this->assertSame(0, DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertSame(0, DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrFalsy(DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrFalsy(DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));

$this->assertPdoResolved();
$this->assertReadPdoResolved();
Expand All @@ -125,8 +151,8 @@ public function testLazyEmulated(): void
$this->assertPdoNotResolved();
$this->assertReadPdoNotResolved();

$this->assertSame(1, DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertSame(1, DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrTruthy(DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrTruthy(DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));

$this->assertPdoResolved();
$this->assertReadPdoResolved();
Expand All @@ -136,8 +162,8 @@ public function testLazyEmulated(): void
$this->assertPdoResolved();
$this->assertReadPdoResolved();

$this->assertSame(0, DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertSame(0, DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrFalsy(DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrFalsy(DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));

$this->assertPdoResolved();
$this->assertReadPdoResolved();
Expand All @@ -160,8 +186,8 @@ public function testCancelEmulated(): void
$this->assertPdoNotResolved();
$this->assertReadPdoNotResolved();

$this->assertSame(0, DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertSame(0, DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrFalsy(DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrFalsy(DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));

$this->assertPdoResolved();
$this->assertReadPdoResolved();
Expand All @@ -176,8 +202,8 @@ public function testEagerNative(): void
$this->assertPdoNotResolved();
$this->assertReadPdoNotResolved();

$this->assertSame(1, DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertSame(1, DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrTruthy(DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrTruthy(DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));

$this->assertPdoResolved();
$this->assertReadPdoResolved();
Expand All @@ -186,8 +212,8 @@ public function testEagerNative(): void
$this->assertPdoResolved();
$this->assertReadPdoResolved();

$this->assertSame(0, DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertSame(0, DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrFalsy(DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrFalsy(DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));

$this->assertPdoResolved();
$this->assertReadPdoResolved();
Expand All @@ -198,8 +224,8 @@ public function testEagerNative(): void
$this->assertPdoResolved();
$this->assertReadPdoResolved();

$this->assertSame(1, DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertSame(1, DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrTruthy(DB::getReadPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));
$this->assertPdoAttrTruthy(DB::getPdo()->getAttribute(PDO::ATTR_EMULATE_PREPARES));

$this->assertPdoResolved();
$this->assertReadPdoResolved();
Expand Down