diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 841ff7f14bb4f98276293c1c5df1b97678eafb68..93295d4cee62697ffe14530ab6577688568f7607 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -610,7 +610,6 @@ default: '⚡️ PHPUnit Unit tests on PHP 8.5': <<: [ *default-job-settings-lint, *default-phpunit-job-settings ] - allow_failure: true variables: TESTSUITE: PHPUnit-Unit KUBERNETES_CPU_REQUEST: "4" @@ -630,7 +629,6 @@ default: '⚡️ Component unit tests on PHP 8.5': <<: [ *default-job-settings-lint, *default-component-unit-test-job-settings ] - allow_failure: true variables: KUBERNETES_CPU_REQUEST: "2" _TARGET_PHP: "8.5-ubuntu" diff --git a/core/modules/migrate/src/Plugin/migrate/process/StaticMap.php b/core/modules/migrate/src/Plugin/migrate/process/StaticMap.php index 152603098ffdb9e416457aa52098b71272a2f460..768320a63c95512f5c5507537b5ecf68dfba6fde 100644 --- a/core/modules/migrate/src/Plugin/migrate/process/StaticMap.php +++ b/core/modules/migrate/src/Plugin/migrate/process/StaticMap.php @@ -113,18 +113,6 @@ * 'TRUE': to * @endcode * - * A NULL can be mapped. If the value of the source property 'foo' is NULL then - * the value of the destination property bar will be 'to'. - * - * @code - * process: - * bar: - * plugin: static_map - * source: foo - * map: - * NULL: to - * @endcode - * * If your source data contains booleans, the boolean is treated as a numeric 0 * or 1. If the value of the source property 'foo' is TRUE then the value of the * destination property bar will be 'bar'. And if the value of the source @@ -141,6 +129,10 @@ * 1: bar * @endcode * + * Note you cannot map NULL to a value. Use the default_value or bypass setting + * instead. If you need to differentiate between NULL and empty strings, + * then use the bypass setting and a custom process plugin. + * * @see https://www.drupal.org/project/drupal/issues/2827897 * @see \Drupal\migrate\Plugin\MigrateProcessInterface */ @@ -151,6 +143,25 @@ class StaticMap extends ProcessPluginBase { * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { + if ($value === NULL) { + if (array_key_exists('', $this->configuration['map'])) { + if (array_key_exists('default_value', $this->configuration) && $this->configuration['default_value'] === $this->configuration['map']['']) { + return $this->configuration['default_value']; + } + @trigger_error('Relying on mapping NULL values via an empty string map key in ' . __CLASS__ . '::transform() is deprecated in drupal:11.3.0 and will trigger a Drupal\migrate\MigrateSkipRowException from drupal:12.0.0. Set the empty string map value as the "default_value" in the plugin configuration. See https://www.drupal.org/node/3557003', E_USER_DEPRECATED); + // Preserve the current behavior of returning the value mapped to an + // empty string for NULL. + return $this->configuration['map']['']; + } + if (array_key_exists('default_value', $this->configuration)) { + return $this->configuration['default_value']; + } + if (!empty($this->configuration['bypass'])) { + return NULL; + } + throw new MigrateSkipRowException(sprintf("No static mapping possible for NULL and no default value provided for destination '%s'.", $destination_property)); + } + $new_value = $value; if (is_array($value)) { if (!$value) { diff --git a/core/modules/migrate/tests/src/Unit/process/StaticMapTest.php b/core/modules/migrate/tests/src/Unit/process/StaticMapTest.php index 45e1f0d6511d1d4ac333e2f970ecace885806716..5a14238159b00c33a4876079bb25559acbeaf41e 100644 --- a/core/modules/migrate/tests/src/Unit/process/StaticMapTest.php +++ b/core/modules/migrate/tests/src/Unit/process/StaticMapTest.php @@ -9,6 +9,7 @@ use Drupal\migrate\MigrateSkipRowException; use Drupal\migrate\Plugin\migrate\process\StaticMap; use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; /** * Tests the static map process plugin. @@ -98,21 +99,56 @@ public function testMapWithInvalidSourceAndBypass(): void { */ public function testWithNullSourceNotInMap(): void { $this->expectException(MigrateSkipRowException::class); - $this->expectExceptionMessage("No static mapping found for 'NULL' and no default value provided for destination 'destination_property'"); + $this->expectExceptionMessage("No static mapping possible for NULL and no default value provided for destination 'destination_property'"); $this->plugin->transform(NULL, $this->migrateExecutable, $this->row, 'destination_property'); } /** - * Tests when the source is invalid but there's a default. + * Tests when the source is invalid but there's a mapping via an empty string. */ - public function testWithNullSource(): void { + #[IgnoreDeprecations] + public function testWithNullSourceWithEmptyStringMapping(): void { $configuration['map']['foo']['bar'] = 'baz'; - $configuration['map'][NULL] = 'mapped NULL'; + $configuration['map'][''] = 'mapped NULL'; $this->plugin = new StaticMap($configuration, 'map', []); + $this->expectDeprecation('Relying on mapping NULL values via an empty string map key in Drupal\migrate\Plugin\migrate\process\StaticMap::transform() is deprecated in drupal:11.3.0 and will trigger a Drupal\migrate\MigrateSkipRowException from drupal:12.0.0. Set the empty string map value as the "default_value" in the plugin configuration. See https://www.drupal.org/node/3557003'); $value = $this->plugin->transform(NULL, $this->migrateExecutable, $this->row, 'destination_property'); $this->assertSame('mapped NULL', $value); } + /** + * Tests when the source is invalid but bypass is set to TRUE. + */ + public function testWithNullSourceBypass(): void { + $configuration['map']['foo']['bar'] = 'baz'; + $configuration['bypass'] = TRUE; + $this->plugin = new StaticMap($configuration, 'map', []); + $value = $this->plugin->transform(NULL, $this->migrateExecutable, $this->row, 'destination_property'); + $this->assertNull($value); + } + + /** + * Tests when the source is invalid but default_value is set to TRUE. + */ + public function testWithNullSourceDefaultValue(): void { + $configuration['map']['foo']['bar'] = 'baz'; + $configuration['default_value'] = FALSE; + $this->plugin = new StaticMap($configuration, 'map', []); + $value = $this->plugin->transform(NULL, $this->migrateExecutable, $this->row, 'destination_property'); + $this->assertFalse($value); + } + + /** + * Tests when the source returns an empty string and it is mapped to a value. + */ + public function testWithEmptyStringMap(): void { + $configuration['map']['foo']['bar'] = 'baz'; + $configuration['map'][''] = 'mapped empty string'; + $this->plugin = new StaticMap($configuration, 'map', []); + $value = $this->plugin->transform('', $this->migrateExecutable, $this->row, 'destination_property'); + $this->assertSame('mapped empty string', $value); + } + /** * Tests when there is a dot in a map key. */