diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 30a530cf9ead..0892fa26d026 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -174,6 +174,24 @@ stages: _TARGET_PHP: "8.2" _TARGET_DB: "sqlite-3" +'PHP 8.3 MySQL 8': + <<: [ *default-stage, *run-daily ] + variables: + _TARGET_PHP: "8.3" + _TARGET_DB: "mysql-8" + +'PHP 8.3 PostgreSQL 16': + <<: [ *default-stage, *run-daily ] + variables: + _TARGET_PHP: "8.3" + _TARGET_DB: "pgsql-16" + +'PHP 8.3 SQLite 3': + <<: [ *default-stage, *run-daily ] + variables: + _TARGET_PHP: "8.3" + _TARGET_DB: "sqlite-3" + # Run daily, or manually. # 'PHP 8.1 MariaDB 10.3.22': # <<: [ *default-stage, *run-daily ] diff --git a/core/assets/scaffold/files/example.settings.local.php b/core/assets/scaffold/files/example.settings.local.php index 7cb0e6857735..bfe061d05651 100644 --- a/core/assets/scaffold/files/example.settings.local.php +++ b/core/assets/scaffold/files/example.settings.local.php @@ -29,11 +29,7 @@ * It is strongly recommended that you set zend.assertions=1 in the PHP.ini file * (It cannot be changed from .htaccess or runtime) on development machines and * to 0 or -1 in production. - * - * @see https://wiki.php.net/rfc/expectations */ -assert_options(ASSERT_ACTIVE, TRUE); -assert_options(ASSERT_EXCEPTION, TRUE); /** * Enable local development services. diff --git a/core/lib/Drupal/Component/Assertion/Handle.php b/core/lib/Drupal/Component/Assertion/Handle.php index fe94bbf9d059..da355aab30ce 100644 --- a/core/lib/Drupal/Component/Assertion/Handle.php +++ b/core/lib/Drupal/Component/Assertion/Handle.php @@ -21,9 +21,11 @@ class Handle { */ public static function register() { // Since we're using exceptions, turn error warnings off. + // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated assert_options(ASSERT_WARNING, FALSE); // Turn exception throwing on. + // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated assert_options(ASSERT_EXCEPTION, TRUE); } diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index c6f0b9846d94..dd67a2b5416f 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -1058,11 +1058,6 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { // the internal browser. define('DRUPAL_TEST_IN_CHILD_SITE', TRUE); - // Web tests are to be conducted with runtime assertions active. - assert_options(ASSERT_ACTIVE, TRUE); - // Force assertion failures to be thrown as exceptions. - assert_options(ASSERT_EXCEPTION, TRUE); - // Log fatal errors to the test site directory. ini_set('log_errors', 1); ini_set('error_log', $app_root . '/' . $test_db->getTestSitePath() . '/error.log'); diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php index fb77dee8c2e6..52b967425676 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php @@ -469,9 +469,12 @@ abstract class ContentEntityBase extends EntityBase implements \IteratorAggregat public function preSave(EntityStorageInterface $storage) { // An entity requiring validation should not be saved if it has not been // actually validated. - assert(!$this->validationRequired || $this->validated, 'Entity validation was skipped.'); - - $this->validated = FALSE; + if ($this->validationRequired && !$this->validated) { + throw new \LogicException('Entity validation is required, but was skipped.'); + } + else { + $this->validated = FALSE; + } parent::preSave($storage); } diff --git a/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php b/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php index a363e911d76e..0d1d0cef219c 100644 --- a/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php +++ b/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php @@ -105,16 +105,8 @@ class ResourceResponseValidator implements EventSubscriberInterface { return; } - $this->doValidateResponse($response, $event->getRequest()); - } - - /** - * Wraps validation in an assert to prevent execution in production. - * - * @see self::validateResponse - */ - public function doValidateResponse(Response $response, Request $request) { - assert($this->validateResponse($response, $request), 'A JSON:API response failed validation (see the logs for details). Report this in the issue queue on drupal.org'); + // Wraps validation in an assert to prevent execution in production. + assert($this->validateResponse($response, $event->getRequest()), 'A JSON:API response failed validation (see the logs for details). Report this in the Drupal issue queue at https://www.drupal.org/project/issues/drupal'); } /** diff --git a/core/modules/jsonapi/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php b/core/modules/jsonapi/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php index 7a34a41a6252..90b5f5f8bbd4 100644 --- a/core/modules/jsonapi/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php +++ b/core/modules/jsonapi/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php @@ -5,12 +5,10 @@ namespace Drupal\Tests\jsonapi\Unit\EventSubscriber; use Drupal\jsonapi\EventSubscriber\ResourceResponseValidator; use Drupal\jsonapi\ResourceType\ResourceType; use Drupal\jsonapi\Routing\Routes; -use JsonSchema\Validator; use Drupal\Core\Extension\Extension; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\rest\ResourceResponse; use Drupal\Tests\UnitTestCase; -use Prophecy\Argument; use Psr\Log\LoggerInterface; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; @@ -54,47 +52,6 @@ class ResourceResponseValidatorTest extends UnitTestCase { $this->subscriber = $subscriber; } - /** - * @covers ::doValidateResponse - */ - public function testDoValidateResponse() { - $request = $this->createRequest( - 'jsonapi.node--article.individual', - new ResourceType('node', 'article', NULL) - ); - - $response = $this->createResponse('{"data":null}'); - - // Capture the default assert settings. - $zend_assertions_default = ini_get('zend.assertions'); - $assert_active_default = assert_options(ASSERT_ACTIVE); - - // The validator *should* be called when asserts are active. - $validator = $this->prophesize(Validator::class); - $validator->check(Argument::any(), Argument::any())->shouldBeCalled('Validation should be run when asserts are active.'); - $validator->isValid()->willReturn(TRUE); - $this->subscriber->setValidator($validator->reveal()); - - // Ensure asset is active. - ini_set('zend.assertions', 1); - assert_options(ASSERT_ACTIVE, 1); - $this->subscriber->doValidateResponse($response, $request); - - // The validator should *not* be called when asserts are inactive. - $validator = $this->prophesize(Validator::class); - $validator->check(Argument::any(), Argument::any())->shouldNotBeCalled('Validation should not be run when asserts are not active.'); - $this->subscriber->setValidator($validator->reveal()); - - // Ensure asset is inactive. - ini_set('zend.assertions', 0); - assert_options(ASSERT_ACTIVE, 0); - $this->subscriber->doValidateResponse($response, $request); - - // Reset the original assert values. - ini_set('zend.assertions', $zend_assertions_default); - assert_options(ASSERT_ACTIVE, $assert_active_default); - } - /** * @covers ::validateResponse * @dataProvider validateResponseProvider diff --git a/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php b/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php index 4ec687aacd96..3ea354d54993 100644 --- a/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php +++ b/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php @@ -80,7 +80,7 @@ class EntityTestForm extends ContentEntityForm { $form_state->setRebuild(); } } - catch (\AssertionError $e) { + catch (\Exception $e) { \Drupal::state()->set('entity_test.form.save.exception', get_class($e) . ': ' . $e->getMessage()); } return $status ?? FALSE; diff --git a/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php b/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php index a9ce73618169..930636ac59c1 100644 --- a/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php +++ b/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php @@ -229,7 +229,7 @@ class EntityFormTest extends BrowserTestBase { $state->set('entity_test.form.validate.test', 'button-level'); $this->drupalGet('entity_test/add'); $this->submitForm([], 'Save'); - $this->assertEquals('AssertionError: Entity validation was skipped.', $state->get('entity_test.form.save.exception'), 'Button-level validation handlers behave correctly.'); + $this->assertEquals('Drupal\\Core\\Entity\\EntityStorageException: Entity validation is required, but was skipped.', $state->get('entity_test.form.save.exception'), 'Button-level validation handlers behave correctly.'); } /** diff --git a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php index 8b75f404e715..38908b9aa605 100644 --- a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php @@ -489,8 +489,8 @@ class ContentEntityBaseUnitTest extends UnitTestCase { // that trying to save a non-validated entity when validation is required // results in an exception. $this->assertTrue($this->entity->isValidationRequired()); - $this->expectException(\AssertionError::class); - $this->expectExceptionMessage('Entity validation was skipped.'); + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Entity validation is required, but was skipped.'); $this->entity->save(); } diff --git a/core/tests/Drupal/Tests/Core/Field/FieldTypePluginManagerTest.php b/core/tests/Drupal/Tests/Core/Field/FieldTypePluginManagerTest.php index ac286f245656..b0253acc06e5 100644 --- a/core/tests/Drupal/Tests/Core/Field/FieldTypePluginManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Field/FieldTypePluginManagerTest.php @@ -147,17 +147,14 @@ class FieldTypePluginManagerTest extends UnitTestCase { ]); $zend_assertions_default = ini_get('zend.assertions'); - $assert_active_default = assert_options(ASSERT_ACTIVE); // Test behavior when assertions are not enabled. ini_set('zend.assertions', 0); - assert_options(ASSERT_ACTIVE, 0); $grouped_definitions = $this->fieldTypeManager->getGroupedDefinitions(); $this->assertEquals(['General'], array_keys($grouped_definitions)); // Test behavior when assertions are enabled. ini_set('zend.assertions', 1); - assert_options(ASSERT_ACTIVE, 1); $this->expectException(\AssertionError::class); try { $this->fieldTypeManager->getGroupedDefinitions(); @@ -165,7 +162,6 @@ class FieldTypePluginManagerTest extends UnitTestCase { catch (\Exception $e) { // Reset the original assert values. ini_set('zend.assertions', $zend_assertions_default); - assert_options(ASSERT_ACTIVE, $assert_active_default); throw $e; } diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php index 295abc42659b..0ea13b0f3937 100644 --- a/core/tests/bootstrap.php +++ b/core/tests/bootstrap.php @@ -173,11 +173,6 @@ mb_language('uni'); // reduce the fragility of the testing system in general. date_default_timezone_set('Australia/Sydney'); -// Runtime assertions. PHPUnit follows the php.ini assert.active setting for -// runtime assertions. By default this setting is on. Ensure exceptions are -// thrown if an assert fails. -assert_options(ASSERT_EXCEPTION, TRUE); - // Ensure ignored deprecation patterns listed in .deprecation-ignore.txt are // considered in testing. if (getenv('SYMFONY_DEPRECATIONS_HELPER') === FALSE) { diff --git a/sites/example.settings.local.php b/sites/example.settings.local.php index 7cb0e6857735..bfe061d05651 100644 --- a/sites/example.settings.local.php +++ b/sites/example.settings.local.php @@ -29,11 +29,7 @@ * It is strongly recommended that you set zend.assertions=1 in the PHP.ini file * (It cannot be changed from .htaccess or runtime) on development machines and * to 0 or -1 in production. - * - * @see https://wiki.php.net/rfc/expectations */ -assert_options(ASSERT_ACTIVE, TRUE); -assert_options(ASSERT_EXCEPTION, TRUE); /** * Enable local development services.