From 519dc8de58fc677d24c79a692edf661880191e57 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Wed, 27 Mar 2024 12:38:32 +0000
Subject: [PATCH] Issue #3353918 by Spokje, longwave, rpayanm, mondrake: Fix
 PHPStan L1 errors "Variable $foo might not be defined." caused by
 non-exhaustive switch statements

---
 core/.phpstan-baseline.php                    | 55 -------------------
 .../FieldWidget/DateTimeDatelistWidget.php    | 35 ++++--------
 .../src/Form/EntityDisplayFormBase.php        | 27 ++++-----
 core/modules/jsonapi/src/Query/Filter.php     | 13 ++---
 .../Form/FormTestTableSelectJsSelectForm.php  | 23 ++------
 .../taxonomy/src/Form/OverviewTerms.php       | 36 ++++--------
 .../views/argument/ArgumentPluginBase.php     | 38 +++++--------
 .../Core/Entity/EntitySchemaTest.php          | 40 +++++---------
 .../KernelTests/Core/Image/ToolkitGdTest.php  | 28 +++-------
 9 files changed, 75 insertions(+), 220 deletions(-)

diff --git a/core/.phpstan-baseline.php b/core/.phpstan-baseline.php
index 8114207bce70..927f28eff427 100644
--- a/core/.phpstan-baseline.php
+++ b/core/.phpstan-baseline.php
@@ -751,11 +751,6 @@
 	'count' => 1,
 	'path' => __DIR__ . '/modules/datetime/src/Plugin/Field/FieldType/DateTimeItem.php',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Variable \\$date_part_order might not be defined\\.$#',
-	'count' => 3,
-	'path' => __DIR__ . '/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDatelistWidget.php',
-];
 $ignoreErrors[] = [
 	'message' => '#^Variable \\$item in isset\\(\\) always exists and is not nullable\\.$#',
 	'count' => 1,
@@ -811,16 +806,6 @@
 	'count' => 1,
 	'path' => __DIR__ . '/modules/field_ui/src/FieldUI.php',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Variable \\$updated_columns might not be defined\\.$#',
-	'count' => 1,
-	'path' => __DIR__ . '/modules/field_ui/src/Form/EntityDisplayFormBase.php',
-];
-$ignoreErrors[] = [
-	'message' => '#^Variable \\$updated_rows might not be defined\\.$#',
-	'count' => 2,
-	'path' => __DIR__ . '/modules/field_ui/src/Form/EntityDisplayFormBase.php',
-];
 $ignoreErrors[] = [
 	'message' => '#^Method Drupal\\\\field_ui\\\\Form\\\\EntityDisplayModeFormBase\\:\\:save\\(\\) should return int but return statement is missing\\.$#',
 	'count' => 1,
@@ -956,11 +941,6 @@
 	'count' => 1,
 	'path' => __DIR__ . '/modules/jsonapi/src/Normalizer/EntityAccessDeniedHttpExceptionNormalizer.php',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Variable \\$group might not be defined\\.$#',
-	'count' => 5,
-	'path' => __DIR__ . '/modules/jsonapi/src/Query/Filter.php',
-];
 $ignoreErrors[] = [
 	'message' => '#^Method Drupal\\\\jsonapi\\\\Revisions\\\\VersionNegotiator\\:\\:getRevision\\(\\) should return Drupal\\\\Core\\\\Entity\\\\EntityInterface but return statement is missing\\.$#',
 	'count' => 1,
@@ -1493,11 +1473,6 @@
 	'count' => 1,
 	'path' => __DIR__ . '/modules/system/tests/modules/deprecation_test/src/DeprecatedController.php',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Variable \\$options might not be defined\\.$#',
-	'count' => 1,
-	'path' => __DIR__ . '/modules/system/tests/modules/form_test/src/Form/FormTestTableSelectJsSelectForm.php',
-];
 $ignoreErrors[] = [
 	'message' => '#^Constructor of class Drupal\\\\lazy_route_provider_install_test\\\\PluginManager has an unused parameter \\$cache_backend\\.$#',
 	'count' => 1,
@@ -1558,11 +1533,6 @@
 	'count' => 2,
 	'path' => __DIR__ . '/modules/system/tests/src/Functional/Theme/ThemeUiTest.php',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Variable \\$help_message might not be defined\\.$#',
-	'count' => 1,
-	'path' => __DIR__ . '/modules/taxonomy/src/Form/OverviewTerms.php',
-];
 $ignoreErrors[] = [
 	'message' => '#^Method Drupal\\\\taxonomy\\\\Plugin\\\\migrate\\\\source\\\\d7\\\\TermTranslation\\:\\:prepareRow\\(\\) should return bool but return statement is missing\\.$#',
 	'count' => 1,
@@ -1720,16 +1690,6 @@
 	'count' => 1,
 	'path' => __DIR__ . '/modules/views/src/Plugin/views/area/HTTPStatusCode.php',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Variable \\$options_name might not be defined\\.$#',
-	'count' => 1,
-	'path' => __DIR__ . '/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php',
-];
-$ignoreErrors[] = [
-	'message' => '#^Variable \\$plugin_name might not be defined\\.$#',
-	'count' => 2,
-	'path' => __DIR__ . '/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php',
-];
 $ignoreErrors[] = [
 	'message' => '#^Variable \\$validate_types might not be defined\\.$#',
 	'count' => 1,
@@ -2097,11 +2057,6 @@
 	'count' => 2,
 	'path' => __DIR__ . '/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Variable \\$field might not be defined\\.$#',
-	'count' => 9,
-	'path' => __DIR__ . '/tests/Drupal/KernelTests/Core/Entity/EntitySchemaTest.php',
-];
 $ignoreErrors[] = [
 	'message' => '#^Variable \\$e might not be defined\\.$#',
 	'count' => 1,
@@ -2112,16 +2067,6 @@
 	'count' => 1,
 	'path' => __DIR__ . '/tests/Drupal/KernelTests/Core/Entity/FieldableEntityDefinitionUpdateTest.php',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Variable \\$x might not be defined\\.$#',
-	'count' => 1,
-	'path' => __DIR__ . '/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php',
-];
-$ignoreErrors[] = [
-	'message' => '#^Variable \\$y might not be defined\\.$#',
-	'count' => 1,
-	'path' => __DIR__ . '/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php',
-];
 $ignoreErrors[] = [
 	'message' => '#^Variable \\$value in isset\\(\\) always exists and is not nullable\\.$#',
 	'count' => 1,
diff --git a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDatelistWidget.php b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDatelistWidget.php
index e7c27825595a..e7999309d4fb 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDatelistWidget.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDatelistWidget.php
@@ -49,31 +49,16 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
     }
 
     // Set up the date part order array.
-    switch ($date_order) {
-      case 'YMD':
-        $date_part_order = ['year', 'month', 'day'];
-        break;
-
-      case 'MDY':
-        $date_part_order = ['month', 'day', 'year'];
-        break;
-
-      case 'DMY':
-        $date_part_order = ['day', 'month', 'year'];
-        break;
-    }
-    switch ($time_type) {
-      case '24':
-        $date_part_order = array_merge($date_part_order, ['hour', 'minute']);
-        break;
-
-      case '12':
-        $date_part_order = array_merge($date_part_order, ['hour', 'minute', 'ampm']);
-        break;
-
-      case 'none':
-        break;
-    }
+    $date_part_order = match ($date_order) {
+      'YMD' => ['year', 'month', 'day'],
+      'MDY' => ['month', 'day', 'year'],
+      'DMY' => ['day', 'month', 'year'],
+    };
+    $date_part_order = match ($time_type) {
+      '24' => array_merge($date_part_order, ['hour', 'minute']),
+      '12' => array_merge($date_part_order, ['hour', 'minute', 'ampm']),
+      default => $date_part_order,
+    };
 
     $element['value'] = [
       '#type' => 'datelist',
diff --git a/core/modules/field_ui/src/Form/EntityDisplayFormBase.php b/core/modules/field_ui/src/Form/EntityDisplayFormBase.php
index a92618a728b5..38604858a2d2 100644
--- a/core/modules/field_ui/src/Form/EntityDisplayFormBase.php
+++ b/core/modules/field_ui/src/Form/EntityDisplayFormBase.php
@@ -688,23 +688,16 @@ public function multistepAjax($form, FormStateInterface $form_state) {
     $op = $trigger['#op'];
 
     // Pick the elements that need to receive the ajax-new-content effect.
-    switch ($op) {
-      case 'edit':
-        $updated_rows = [$trigger['#field_name']];
-        $updated_columns = ['plugin'];
-        break;
-
-      case 'update':
-      case 'cancel':
-        $updated_rows = [$trigger['#field_name']];
-        $updated_columns = ['plugin', 'settings_summary', 'settings_edit'];
-        break;
-
-      case 'refresh_table':
-        $updated_rows = array_values(explode(' ', $form_state->getValue('refresh_rows')));
-        $updated_columns = ['settings_summary', 'settings_edit'];
-        break;
-    }
+    $updated_rows = match ($op) {
+      'edit' => [$trigger['#field_name']],
+      'update', 'cancel' => [$trigger['#field_name']],
+      'refresh_table' => array_values(explode(' ', $form_state->getValue('refresh_rows')))
+    };
+    $updated_columns = match ($op) {
+      'edit' => ['plugin'],
+      'update', 'cancel' => ['plugin', 'settings_summary', 'settings_edit'],
+      'refresh_table' => ['settings_summary', 'settings_edit'],
+    };
 
     foreach ($updated_rows as $name) {
       foreach ($updated_columns as $key) {
diff --git a/core/modules/jsonapi/src/Query/Filter.php b/core/modules/jsonapi/src/Query/Filter.php
index ab134317c4bc..d3cc8c4d2ebc 100644
--- a/core/modules/jsonapi/src/Query/Filter.php
+++ b/core/modules/jsonapi/src/Query/Filter.php
@@ -101,15 +101,10 @@ public function queryCondition(QueryInterface $query) {
    */
   protected function buildGroup(QueryInterface $query, EntityConditionGroup $condition_group) {
     // Create a condition group using the original query.
-    switch ($condition_group->conjunction()) {
-      case 'AND':
-        $group = $query->andConditionGroup();
-        break;
-
-      case 'OR':
-        $group = $query->orConditionGroup();
-        break;
-    }
+    $group = match ($condition_group->conjunction()) {
+      'AND' => $query->andConditionGroup(),
+      'OR' => $query->orConditionGroup(),
+    };
 
     // Get all children of the group.
     $members = $condition_group->members();
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestTableSelectJsSelectForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestTableSelectJsSelectForm.php
index aec320e9e1b8..c6cb99a27236 100644
--- a/core/modules/system/tests/modules/form_test/src/Form/FormTestTableSelectJsSelectForm.php
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestTableSelectJsSelectForm.php
@@ -22,23 +22,12 @@ public function getFormId() {
    * {@inheritdoc}
    */
   public function buildForm(array $form, FormStateInterface $form_state, $test_action = NULL) {
-    switch ($test_action) {
-      case 'multiple-true-default':
-        $options = ['#multiple' => TRUE];
-        break;
-
-      case 'multiple-false-default':
-        $options = ['#multiple' => FALSE];
-        break;
-
-      case 'multiple-true-no-advanced-select':
-        $options = ['#multiple' => TRUE, '#js_select' => FALSE];
-        break;
-
-      case 'multiple-false-advanced-select':
-        $options = ['#multiple' => FALSE, '#js_select' => TRUE];
-        break;
-    }
+    $options = match ($test_action) {
+      'multiple-true-default' => ['#multiple' => TRUE],
+      'multiple-false-default' => ['#multiple' => FALSE],
+      'multiple-true-no-advanced-select' => ['#multiple' => TRUE, '#js_select' => FALSE],
+      'multiple-false-advanced-select' => ['#multiple' => FALSE, '#js_select' => TRUE],
+    };
 
     return $this->tableselectFormBuilder($form, $form_state, $options);
   }
diff --git a/core/modules/taxonomy/src/Form/OverviewTerms.php b/core/modules/taxonomy/src/Form/OverviewTerms.php
index 62fc76a6b61b..24e16c8a0b9b 100644
--- a/core/modules/taxonomy/src/Form/OverviewTerms.php
+++ b/core/modules/taxonomy/src/Form/OverviewTerms.php
@@ -264,34 +264,18 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular
       '%name' => $taxonomy_vocabulary->label(),
     ];
     if ($this->currentUser()->hasPermission('administer taxonomy') || $this->currentUser()->hasPermission('edit terms in ' . $taxonomy_vocabulary->id())) {
-      switch ($vocabulary_hierarchy) {
-        case VocabularyInterface::HIERARCHY_DISABLED:
-          $help_message = $this->t('You can reorganize the terms in %capital_name using their drag-and-drop handles, and group terms under a parent term by sliding them under and to the right of the parent.', $args);
-          break;
-
-        case VocabularyInterface::HIERARCHY_SINGLE:
-          $help_message = $this->t('%capital_name contains terms grouped under parent terms. You can reorganize the terms in %capital_name using their drag-and-drop handles.', $args);
-          break;
-
-        case VocabularyInterface::HIERARCHY_MULTIPLE:
-          $help_message = $this->t('%capital_name contains terms with multiple parents. Drag and drop of terms with multiple parents is not supported, but you can re-enable drag-and-drop support by editing each term to include only a single parent.', $args);
-          break;
-      }
+      $help_message = match ($vocabulary_hierarchy) {
+        VocabularyInterface::HIERARCHY_DISABLED => $this->t('You can reorganize the terms in %capital_name using their drag-and-drop handles, and group terms under a parent term by sliding them under and to the right of the parent.', $args),
+        VocabularyInterface::HIERARCHY_SINGLE => $this->t('%capital_name contains terms grouped under parent terms. You can reorganize the terms in %capital_name using their drag-and-drop handles.', $args),
+        VocabularyInterface::HIERARCHY_MULTIPLE => $this->t('%capital_name contains terms with multiple parents. Drag and drop of terms with multiple parents is not supported, but you can re-enable drag-and-drop support by editing each term to include only a single parent.', $args),
+      };
     }
     else {
-      switch ($vocabulary_hierarchy) {
-        case VocabularyInterface::HIERARCHY_DISABLED:
-          $help_message = $this->t('%capital_name contains the following terms.', $args);
-          break;
-
-        case VocabularyInterface::HIERARCHY_SINGLE:
-          $help_message = $this->t('%capital_name contains terms grouped under parent terms', $args);
-          break;
-
-        case VocabularyInterface::HIERARCHY_MULTIPLE:
-          $help_message = $this->t('%capital_name contains terms with multiple parents.', $args);
-          break;
-      }
+      $help_message = match ($vocabulary_hierarchy) {
+        VocabularyInterface::HIERARCHY_DISABLED =>  $this->t('%capital_name contains the following terms.', $args),
+        VocabularyInterface::HIERARCHY_SINGLE => $this->t('%capital_name contains terms grouped under parent terms', $args),
+        VocabularyInterface::HIERARCHY_MULTIPLE => $this->t('%capital_name contains terms with multiple parents.', $args),
+      };
     }
 
     // Get the IDs of the terms edited on the current page which have pending
diff --git a/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php b/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
index bbc33b438be8..c5e50c7cdfd1 100644
--- a/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
+++ b/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
@@ -1138,30 +1138,20 @@ public function getValue() {
    */
   public function getPlugin($type = 'argument_default', $name = NULL) {
     $options = [];
-    switch ($type) {
-      case 'argument_default':
-        if (!isset($this->options['default_argument_type'])) {
-          return;
-        }
-        $plugin_name = $this->options['default_argument_type'];
-        $options_name = 'default_argument_options';
-        break;
-
-      case 'argument_validator':
-        if (!isset($this->options['validate']['type'])) {
-          return;
-        }
-        $plugin_name = $this->options['validate']['type'];
-        $options_name = 'validate_options';
-        break;
-
-      case 'style':
-        if (!isset($this->options['summary']['format'])) {
-          return;
-        }
-        $plugin_name = $this->options['summary']['format'];
-        $options_name = 'summary_options';
-    }
+    $plugin_name = match ($type) {
+      'argument_default' => $this->options['default_argument_type'] ?? NULL,
+      'argument_validator' => $this->options['validate']['type'] ?? NULL,
+      'style' => $this->options['summary']['format'] ?? NULL,
+    };
+    if ($plugin_name === NULL) {
+      return NULL;
+    }
+
+    $options_name = match ($type) {
+      'argument_default' => 'default_argument_options',
+      'argument_validator' => 'validate_options',
+      'style' => 'summary_options',
+    };
 
     if (!$name) {
       $name = $plugin_name;
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntitySchemaTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntitySchemaTest.php
index b231f6d73fc0..ad4f88177a04 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntitySchemaTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntitySchemaTest.php
@@ -157,32 +157,20 @@ public function testPrimaryKeyUpdate($entity_type_id, $field_name) {
     $entity_type = $update_manager->getEntityType($entity_type_id);
 
     /* @see \Drupal\Core\Entity\ContentEntityBase::baseFieldDefinitions() */
-    switch ($field_name) {
-      case 'id':
-        $field = BaseFieldDefinition::create('integer')
-          ->setLabel('ID')
-          ->setReadOnly(TRUE)
-          ->setSetting('unsigned', TRUE);
-        break;
-
-      case 'revision_id':
-        $field = BaseFieldDefinition::create('integer')
-          ->setLabel('Revision ID')
-          ->setReadOnly(TRUE)
-          ->setSetting('unsigned', TRUE);
-        break;
-
-      case 'langcode':
-        $field = BaseFieldDefinition::create('language')
-          ->setLabel('Language');
-        if ($entity_type->isRevisionable()) {
-          $field->setRevisionable(TRUE);
-        }
-        if ($entity_type->isTranslatable()) {
-          $field->setTranslatable(TRUE);
-        }
-        break;
-    }
+    $field = match ($field_name) {
+      'id' => BaseFieldDefinition::create('integer')
+        ->setLabel('ID')
+        ->setReadOnly(TRUE)
+        ->setSetting('unsigned', TRUE),
+      'revision_id' => BaseFieldDefinition::create('integer')
+        ->setLabel('Revision ID')
+        ->setReadOnly(TRUE)
+        ->setSetting('unsigned', TRUE),
+      'langcode' => BaseFieldDefinition::create('language')
+        ->setLabel('Language')
+        ->setRevisionable($entity_type->isRevisionable())
+        ->setTranslatable($entity_type->isTranslatable()),
+    };
 
     $field
       ->setName($field_name)
diff --git a/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php b/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php
index c796a6e94a1a..932491f8f2d9 100644
--- a/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php
@@ -325,27 +325,13 @@ public function testManipulations(string $file_name, string $test_case, string $
       }
 
       // Get the location of the corner.
-      switch ($key) {
-        case 0:
-          $x = 0;
-          $y = 0;
-          break;
-
-        case 1:
-          $x = $image->getWidth() - 1;
-          $y = 0;
-          break;
-
-        case 2:
-          $x = $image->getWidth() - 1;
-          $y = $image->getHeight() - 1;
-          break;
-
-        case 3:
-          $x = 0;
-          $y = $image->getHeight() - 1;
-          break;
-      }
+      [$x, $y] = match ($key) {
+        0 => [0, 0],
+        1 => [$image->getWidth() - 1, 0],
+        2 => [$image->getWidth() - 1, $image->getHeight() - 1],
+        3 => [0, $image->getHeight() - 1],
+      };
+
       $actual_color = $this->getPixelColor($image, $x, $y);
 
       // If image cannot handle transparent colors, skip the pixel color test.
-- 
GitLab