diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91699f08..ca7c20f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,6 @@ jobs: matrix: include: - laravel: "^12.0" - php: "8.4" steps: - name: Checkout diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ee451d20..76af44d9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,3 +49,9 @@ Use `composer phpstan` to run our phpstan suite. Create `.env` with `PROJECT_PATH=/full/path/to/this/directory`. Configure a Docker-based interpreter for tests (with exec, not run). If you want to use XDebug, use `composer docker-rebuild-with-xdebug`. + +## PHP 8.5 + +To use PHP 8.5 during development, run: +- `PHP_VERSION=8.5.0RC2 composer docker-rebuild` to build the `test` container with PHP 8.5 +- `composer php85-patch` to get rid of some deprecation errors coming from `config/database.php` from within testbench-core diff --git a/Dockerfile b/Dockerfile index fb1620cd..2123e727 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,8 @@ ARG PHP_VERSION=8.4 - FROM php:${PHP_VERSION}-cli-bookworm SHELL ["/bin/bash", "-c"] -RUN apt-get update && apt-get install -y --no-install-recommends \ - git unzip libzip-dev libicu-dev libmemcached-dev zlib1g-dev libssl-dev sqlite3 libsqlite3-dev libpq-dev mariadb-client +RUN apt-get update RUN apt-get install -y gnupg2 \ && curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg \ @@ -12,18 +10,40 @@ RUN apt-get install -y gnupg2 \ && apt-get update \ && ACCEPT_EULA=Y apt-get install -y unixodbc-dev msodbcsql18 +RUN apt-get install -y --no-install-recommends \ + git unzip libzip-dev libicu-dev libmemcached-dev zlib1g-dev libssl-dev sqlite3 libsqlite3-dev libpq-dev mariadb-client + RUN apt autoremove && apt clean RUN pecl install apcu && docker-php-ext-enable apcu RUN pecl install pcov && docker-php-ext-enable pcov -RUN pecl install redis && docker-php-ext-enable redis +RUN pecl install redis-6.3.0RC1 && docker-php-ext-enable redis RUN pecl install memcached && docker-php-ext-enable memcached -RUN pecl install pdo_sqlsrv && docker-php-ext-enable pdo_sqlsrv RUN docker-php-ext-install zip && docker-php-ext-enable zip RUN docker-php-ext-install intl && docker-php-ext-enable intl RUN docker-php-ext-install pdo_mysql && docker-php-ext-enable pdo_mysql RUN docker-php-ext-install pdo_pgsql && docker-php-ext-enable pdo_pgsql +RUN if [[ "${PHP_VERSION}" == *"8.5"* ]]; then \ + mkdir sqlsrv \ + && cd sqlsrv \ + && pecl download pdo_sqlsrv-5.12.0 \ + && tar xzf pdo_sqlsrv-5.12.0.tgz \ + && cd pdo_sqlsrv-5.12.0 \ + && sed -i 's/= dbh->error_mode;/= static_cast(dbh->error_mode);/' pdo_dbh.cpp \ + && sed -i 's/zval_ptr_dtor( &dbh->query_stmt_zval );/OBJ_RELEASE(dbh->query_stmt_obj);dbh->query_stmt_obj=NULL;/' php_pdo_sqlsrv_int.h \ + && phpize \ + && ./configure --with-php-config=$(which php-config) \ + && make -j$(nproc) \ + && cp modules/pdo_sqlsrv.so $(php -r 'echo ini_get("extension_dir");') \ + && cd / \ + && rm -rf /sqlsrv; \ +else \ + pecl install pdo_sqlsrv; \ +fi + +RUN docker-php-ext-enable pdo_sqlsrv + RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" RUN echo "apc.enable_cli=1" >> "$PHP_INI_DIR/php.ini" diff --git a/composer.json b/composer.json index 2eab8837..393d0d8a 100644 --- a/composer.json +++ b/composer.json @@ -65,13 +65,16 @@ "docker-restart": "docker compose down && docker compose up -d", "docker-rebuild": [ "Composer\\Config::disableProcessTimeout", - "PHP_VERSION=8.4 docker compose up -d --no-deps --build" + "docker compose up -d --no-deps --build" ], "docker-rebuild-with-xdebug": [ "Composer\\Config::disableProcessTimeout", - "PHP_VERSION=8.4 XDEBUG_ENABLED=true docker compose up -d --no-deps --build" + "XDEBUG_ENABLED=true docker compose up -d --no-deps --build" ], "docker-m1": "ln -s docker-compose-m1.override.yml docker-compose.override.yml", + "php85-patch": [ + "php -r '$file=\"vendor/orchestra/testbench-core/laravel/config/database.php\"; file_put_contents($file, str_replace(\"PDO::MYSQL_ATTR_SSL_CA\", \"Pdo\\\\Mysql::ATTR_SSL_CA\", file_get_contents($file)));'" + ], "testbench-unlink": "rm ./vendor/orchestra/testbench-core/laravel/vendor", "testbench-link": "ln -s /var/www/html/vendor ./vendor/orchestra/testbench-core/laravel/vendor", "testbench-repair": "mkdir -p ./vendor/orchestra/testbench-core/laravel/storage/framework/sessions && mkdir -p ./vendor/orchestra/testbench-core/laravel/storage/framework/views && mkdir -p ./vendor/orchestra/testbench-core/laravel/storage/framework/cache", diff --git a/src/Features/DisallowSqliteAttach.php b/src/Features/DisallowSqliteAttach.php index fbfa8e58..d4412984 100644 --- a/src/Features/DisallowSqliteAttach.php +++ b/src/Features/DisallowSqliteAttach.php @@ -19,7 +19,7 @@ class DisallowSqliteAttach implements Feature // Handle any already resolved connections foreach (DB::getConnections() as $connection) { if ($connection instanceof SQLiteConnection) { - if (! $this->loadExtension($connection->getPdo())) { + if (! $this->setAuthorizer($connection->getPdo())) { return; } } @@ -28,16 +28,19 @@ class DisallowSqliteAttach implements Feature // Apply the change to all sqlite connections resolved in the future DB::extend('sqlite', function ($config, $name) { $conn = app(ConnectionFactory::class)->make($config, $name); - $this->loadExtension($conn->getPdo()); + $this->setAuthorizer($conn->getPdo()); return $conn; }); } - protected function loadExtension(PDO $pdo): bool + protected function setAuthorizer(PDO $pdo): bool { - // todo@php85 In PHP 8.5, we can use setAuthorizer() instead of loading an extension. - // However, this is currently blocked on https://github.com/phpredis/phpredis/issues/2688 + if (PHP_VERSION_ID >= 80500) { + $this->setNativeAuthorizer($pdo); + return true; + } + static $loadExtensionSupported = method_exists($pdo, 'loadExtension'); if ((! $loadExtensionSupported) || @@ -64,4 +67,13 @@ class DisallowSqliteAttach implements Feature return true; } + + protected function setNativeAuthorizer(PDO $pdo): void + { + $pdo->setAuthorizer(static function (int $action): int { + return $action === 24 // SQLITE_ATTACH + ? Pdo\Sqlite::DENY + : Pdo\Sqlite::OK; + }); + } } diff --git a/tests/TenantDatabaseManagerTest.php b/tests/TenantDatabaseManagerTest.php index a9f99829..0d83e70e 100644 --- a/tests/TenantDatabaseManagerTest.php +++ b/tests/TenantDatabaseManagerTest.php @@ -245,9 +245,6 @@ test('tenant database can be created and deleted on a foreign server', function 'prefix_indexes' => true, 'strict' => true, 'engine' => null, - 'options' => extension_loaded('pdo_mysql') ? array_filter([ - PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), - ]) : [], ], ]); @@ -293,9 +290,6 @@ test('tenant database can be created on a foreign server by using the host from 'prefix_indexes' => true, 'strict' => true, 'engine' => null, - 'options' => extension_loaded('pdo_mysql') ? array_filter([ - PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), - ]) : [], ], ]); @@ -333,9 +327,6 @@ test('database credentials can be provided to PermissionControlledMySQLDatabaseM 'prefix_indexes' => true, 'strict' => true, 'engine' => null, - 'options' => extension_loaded('pdo_mysql') ? array_filter([ - PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), - ]) : [], ], ]); diff --git a/tests/TestCase.php b/tests/TestCase.php index ceee6522..cbc6f57e 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -144,9 +144,6 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase 'prefix_indexes' => true, 'strict' => true, 'engine' => null, - 'options' => extension_loaded('pdo_mysql') ? array_filter([ - PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), - ]) : [], ], 'database.connections.sqlite.database' => ':memory:', 'database.connections.mysql.charset' => 'utf8mb4',