From b1792fd37562eecbf1df84d9f3abfe7c3bedfc8c Mon Sep 17 00:00:00 2001
From: Stephen Mustgrave <38930-smustgrave@users.noreply.drupalcode.org>
Date: Thu, 1 Aug 2024 01:05:13 +0000
Subject: [PATCH] Resolve #3464111 "Convert annotations to"

---
 .../QuizQuestion/QuizDirectionsQuestion.php   | 16 ++++----
 .../quiz/QuizQuestion/LongAnswerQuestion.php  | 15 ++++---
 .../quiz/QuizQuestion/MatchingQuestion.php    | 15 ++++---
 .../quiz/QuizQuestion/MultichoiceQuestion.php | 15 ++++---
 .../quiz/QuizQuestion/QuizPageQuestion.php    | 20 ++++-----
 .../quiz/QuizQuestion/ShortAnswerQuestion.php | 15 ++++---
 .../quiz/QuizQuestion/TrueFalseQuestion.php   | 15 ++++---
 quiz.api.php                                  |  6 +--
 quiz.module                                   |  4 +-
 quiz.rules_defaults.inc                       |  2 +-
 src/Attribute/QuizQuestion.php                | 41 +++++++++++++++++++
 src/Entity/QuizFeedbackType.php               |  2 +-
 src/Entity/QuizQuestion.php                   |  9 +++-
 src/Entity/QuizQuestionBroken.php             |  7 ----
 src/Entity/QuizResultAnswer.php               | 18 +++++++-
 src/Entity/QuizResultAnswerEntityTrait.php    |  1 -
 src/Entity/QuizViewsData.php                  |  2 +-
 src/Plugin/QuizQuestionPluginManager.php      |  5 +--
 src/{Entity => }/QuizResultListBuilder.php    |  7 ++--
 tests/src/Functional/QuizEvaluationTest.php   |  2 +-
 tests/src/Functional/QuizTestBase.php         |  4 +-
 21 files changed, 132 insertions(+), 89 deletions(-)
 create mode 100644 src/Attribute/QuizQuestion.php
 rename src/{Entity => }/QuizResultListBuilder.php (86%)

diff --git a/modules/quiz_directions/src/Plugin/quiz/QuizQuestion/QuizDirectionsQuestion.php b/modules/quiz_directions/src/Plugin/quiz/QuizQuestion/QuizDirectionsQuestion.php
index af5b7039..cca479ca 100644
--- a/modules/quiz_directions/src/Plugin/quiz/QuizQuestion/QuizDirectionsQuestion.php
+++ b/modules/quiz_directions/src/Plugin/quiz/QuizQuestion/QuizDirectionsQuestion.php
@@ -3,11 +3,12 @@
 namespace Drupal\quiz_directions\Plugin\quiz\QuizQuestion;
 
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\quiz\Attribute\QuizQuestion as QuizQuestionAttribute;
 use Drupal\quiz\Entity\QuizQuestion;
 use Drupal\quiz\Entity\QuizResultAnswer;
 
 /**
- * @file
  * Quiz_directions classes.
  *
  * This module uses the question interface to define something which is
@@ -20,15 +21,12 @@ use Drupal\quiz\Entity\QuizResultAnswer;
  *     please..." (Won't work if the question order is randomized);
  *   - Final confirmation, e.g. "You have answered all questions. Click submit
  *     to submit this quiz.";
- *
- * @QuizQuestion (
- *   id = "directions",
- *   label = @Translation("Directions question"),
- *   handlers = {
- *     "response" = "\Drupal\quiz_directions\Plugin\quiz\QuizQuestion\QuizDirectionsResponse"
- *   }
- * )
  */
+#[QuizQuestionAttribute(
+  id: 'directions',
+  label: new TranslatableMarkup('Directions question'),
+  handlers: ['response' => QuizDirectionsResponse::class],
+)]
 class QuizDirectionsQuestion extends QuizQuestion {
 
   /**
diff --git a/modules/quiz_long_answer/src/Plugin/quiz/QuizQuestion/LongAnswerQuestion.php b/modules/quiz_long_answer/src/Plugin/quiz/QuizQuestion/LongAnswerQuestion.php
index 670769dc..8648c3e3 100644
--- a/modules/quiz_long_answer/src/Plugin/quiz/QuizQuestion/LongAnswerQuestion.php
+++ b/modules/quiz_long_answer/src/Plugin/quiz/QuizQuestion/LongAnswerQuestion.php
@@ -4,21 +4,20 @@ namespace Drupal\quiz_long_answer\Plugin\quiz\QuizQuestion;
 
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\quiz\Attribute\QuizQuestion as QuizQuestionAttribute;
 use Drupal\quiz\Entity\QuizQuestion;
 use Drupal\quiz\Entity\QuizResultAnswer;
 use function filter_default_format;
 
 /**
  * Long Answer Quiz Question.
- *
- * @QuizQuestion (
- *   id = "long_answer",
- *   label = @Translation("Long answer question"),
- *   handlers = {
- *     "response" = "\Drupal\quiz_long_answer\Plugin\quiz\QuizQuestion\LongAnswerResponse"
- *   }
- * )
  */
+#[QuizQuestionAttribute(
+  id: 'Translation',
+  label: new TranslatableMarkup('Long answer question'),
+  handlers: ['response' => LongAnswerResponse::class],
+)]
 class LongAnswerQuestion extends QuizQuestion {
 
   use StringTranslationTrait;
diff --git a/modules/quiz_matching/src/Plugin/quiz/QuizQuestion/MatchingQuestion.php b/modules/quiz_matching/src/Plugin/quiz/QuizQuestion/MatchingQuestion.php
index 841de577..36938825 100644
--- a/modules/quiz_matching/src/Plugin/quiz/QuizQuestion/MatchingQuestion.php
+++ b/modules/quiz_matching/src/Plugin/quiz/QuizQuestion/MatchingQuestion.php
@@ -4,6 +4,8 @@ namespace Drupal\quiz_matching\Plugin\quiz\QuizQuestion;
 
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\quiz\Attribute\QuizQuestion as QuizQuestionAttribute;
 use Drupal\quiz\Entity\QuizQuestion;
 use Drupal\quiz\Entity\QuizResultAnswer;
 
@@ -14,15 +16,12 @@ use Drupal\quiz\Entity\QuizResultAnswer;
  *
  * A Matching node defines a series of questions and answers and requires the
  * userto associate each answer with a question.
- *
- * @QuizQuestion (
- *   id = "matching",
- *   label = @Translation("Matching question"),
- *   handlers = {
- *     "response" = "\Drupal\quiz_matching\Plugin\quiz\QuizQuestion\MatchingResponse"
- *   }
- * )
  */
+#[QuizQuestionAttribute(
+  id: 'matching',
+  label: new TranslatableMarkup('Matching question'),
+  handlers: ['response' => MatchingResponse::class],
+)]
 class MatchingQuestion extends QuizQuestion {
 
   use StringTranslationTrait;
diff --git a/modules/quiz_multichoice/src/Plugin/quiz/QuizQuestion/MultichoiceQuestion.php b/modules/quiz_multichoice/src/Plugin/quiz/QuizQuestion/MultichoiceQuestion.php
index 54d81e29..d8bbe070 100644
--- a/modules/quiz_multichoice/src/Plugin/quiz/QuizQuestion/MultichoiceQuestion.php
+++ b/modules/quiz_multichoice/src/Plugin/quiz/QuizQuestion/MultichoiceQuestion.php
@@ -4,22 +4,21 @@ namespace Drupal\quiz_multichoice\Plugin\quiz\QuizQuestion;
 
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\Core\Url;
+use Drupal\quiz\Attribute\QuizQuestion as QuizQuestionAttribute;
 use Drupal\quiz\Entity\QuizQuestion;
 use Drupal\quiz\Entity\QuizResultAnswer;
 use function check_markup;
 
 /**
  * Multichoice Question.
- *
- * @QuizQuestion (
- *   id = "multichoice",
- *   label = @Translation("Multiple choice question"),
- *   handlers = {
- *     "response" = "\Drupal\quiz_multichoice\Plugin\quiz\QuizQuestion\MultichoiceResponse"
- *   }
- * )
  */
+#[QuizQuestionAttribute(
+  id: 'multichoice',
+  label: new TranslatableMarkup('Multiple choice question'),
+  handlers: ['response' => MultichoiceResponse::class],
+)]
 class MultichoiceQuestion extends QuizQuestion {
 
   use StringTranslationTrait;
diff --git a/modules/quiz_page/src/Plugin/quiz/QuizQuestion/QuizPageQuestion.php b/modules/quiz_page/src/Plugin/quiz/QuizQuestion/QuizPageQuestion.php
index abc49bc6..021a5ac0 100644
--- a/modules/quiz_page/src/Plugin/quiz/QuizQuestion/QuizPageQuestion.php
+++ b/modules/quiz_page/src/Plugin/quiz/QuizQuestion/QuizPageQuestion.php
@@ -3,6 +3,8 @@
 namespace Drupal\quiz_page\Plugin\quiz\QuizQuestion;
 
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\quiz\Attribute\QuizQuestion as QuizQuestionAttribute;
 use Drupal\quiz\Entity\QuizQuestion;
 use Drupal\quiz\Entity\QuizResultAnswer;
 
@@ -14,25 +16,21 @@ use Drupal\quiz\Entity\QuizResultAnswer;
  *
  * A Quiz page node is a placeholder for presenting multiple questions
  * on the same page.
- *
- * @QuizQuestion (
- *   id = "page",
- *   label = @Translation("Quiz page"),
- *   handlers = {
- *     "response" = "\Drupal\quiz_page\Plugin\quiz\QuizQuestion\QuizPageResponse"
- *   }
- * )
  */
+#[QuizQuestionAttribute(
+  id: 'page',
+  label: new TranslatableMarkup('Quiz page'),
+  handlers: ['response' => QuizPageResponse::class],
+)]
 class QuizPageQuestion extends QuizQuestion {
 
   /**
    * {@inheritdoc}
    */
   public function getAnsweringForm(FormStateInterface $form_state, QuizResultAnswer $quizQuestionResultAnswer): array {
-    $element = [
+    return [
       '#type' => 'hidden',
     ];
-    return $element;
   }
 
   /**
@@ -40,7 +38,7 @@ class QuizPageQuestion extends QuizQuestion {
    *
    * @see QuizQuestion::getCreationForm()
    */
-  public function getCreationForm(array &$form_state = NULL) {
+  public function getCreationForm(array &$form_state = NULL): array {
     return [];
   }
 
diff --git a/modules/quiz_short_answer/src/Plugin/quiz/QuizQuestion/ShortAnswerQuestion.php b/modules/quiz_short_answer/src/Plugin/quiz/QuizQuestion/ShortAnswerQuestion.php
index 1cfc8b1f..b4384041 100644
--- a/modules/quiz_short_answer/src/Plugin/quiz/QuizQuestion/ShortAnswerQuestion.php
+++ b/modules/quiz_short_answer/src/Plugin/quiz/QuizQuestion/ShortAnswerQuestion.php
@@ -4,20 +4,19 @@ namespace Drupal\quiz_short_answer\Plugin\quiz\QuizQuestion;
 
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\quiz\Attribute\QuizQuestion as QuizQuestionAttribute;
 use Drupal\quiz\Entity\QuizQuestion;
 use Drupal\quiz\Entity\QuizResultAnswer;
 
 /**
  * Short answer question plugin.
- *
- * @QuizQuestion (
- *   id = "short_answer",
- *   label = @Translation("Short answer question"),
- *   handlers = {
- *     "response" = "\Drupal\quiz_short_answer\Plugin\quiz\QuizQuestion\ShortAnswerResponse"
- *   }
- * )
  */
+#[QuizQuestionAttribute(
+  id: 'short_answer',
+  label: new TranslatableMarkup('Short answer question'),
+  handlers: ['response' => ShortAnswerResponse::class],
+)]
 class ShortAnswerQuestion extends QuizQuestion {
 
   use StringTranslationTrait;
diff --git a/modules/quiz_truefalse/src/Plugin/quiz/QuizQuestion/TrueFalseQuestion.php b/modules/quiz_truefalse/src/Plugin/quiz/QuizQuestion/TrueFalseQuestion.php
index 2ba7fd3b..0c784af3 100644
--- a/modules/quiz_truefalse/src/Plugin/quiz/QuizQuestion/TrueFalseQuestion.php
+++ b/modules/quiz_truefalse/src/Plugin/quiz/QuizQuestion/TrueFalseQuestion.php
@@ -4,20 +4,19 @@ namespace Drupal\quiz_truefalse\Plugin\quiz\QuizQuestion;
 
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\quiz\Attribute\QuizQuestion as QuizQuestionAttribute;
 use Drupal\quiz\Entity\QuizQuestion;
 use Drupal\quiz\Entity\QuizResultAnswer;
 
 /**
  * The true/false question plugin.
- *
- * @QuizQuestion (
- *   id = "truefalse",
- *   label = @Translation("True/false question"),
- *   handlers = {
- *     "response" = "\Drupal\quiz_truefalse\Plugin\quiz\QuizQuestion\TrueFalseResponse"
- *   }
- * )
  */
+#[QuizQuestionAttribute(
+  id: 'truefalse',
+  label: new TranslatableMarkup('True/false question'),
+  handlers: ['response' => TrueFalseResponse::class],
+)]
 class TrueFalseQuestion extends QuizQuestion {
 
   use StringTranslationTrait;
diff --git a/quiz.api.php b/quiz.api.php
index 450a8bb2..ee41b509 100644
--- a/quiz.api.php
+++ b/quiz.api.php
@@ -9,9 +9,6 @@ use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Session\AccountInterface;
 
 /**
- * @file quiz.api.php
- * Hooks provided by Quiz module.
- *
  * These entity types provided by Quiz also have entity API hooks. There are a
  * few additional Quiz specific hooks defined in this file.
  *
@@ -25,7 +22,8 @@ use Drupal\Core\Session\AccountInterface;
  *
  * hook_quiz_result_presave(QuizResult $quiz_result)
  *   - Runs before a result is saved to the DB.
- * hook_quiz_question_relationship_insert(QuizQuestionRelationship $quiz_question_relationship)
+ * hook_quiz_question_relationship_insert(
+ * QuizQuestionRelationship $quiz_question_relationship)
  *   - Runs when a new question is added to a quiz.
  *
  * You can also use Rules to build conditional actions based off of these
diff --git a/quiz.module b/quiz.module
index 8c5c7bef..d68ed063 100644
--- a/quiz.module
+++ b/quiz.module
@@ -519,9 +519,9 @@ function quiz_get_feedback_options(): array {
   $feedback_options = Drupal::moduleHandler()->invokeAll('quiz_feedback_options');
 
   $view_modes = Drupal::service('entity_display.repository')->getViewModes('quiz_question');
-  $feedback_options["quiz_question_view_full"] = t('Question' . ': ' . 'Full');
+  $feedback_options["quiz_question_view_full"] = t('Question: Full');
   foreach ($view_modes as $view_mode => $info) {
-    $feedback_options["quiz_question_view_" . $view_mode] = t('Question' . ': ' . $info['label']);
+    $feedback_options["quiz_question_view_" . $view_mode] = t('Question: @label', ['@label' => $info['label']]);
   }
 
   $feedback_options += [
diff --git a/quiz.rules_defaults.inc b/quiz.rules_defaults.inc
index 5d61297a..e9f2ec7a 100644
--- a/quiz.rules_defaults.inc
+++ b/quiz.rules_defaults.inc
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Used for interaction with rules module
+ * Used for interaction with rules module.
  *
  * @todo not entirely sure?
  */
diff --git a/src/Attribute/QuizQuestion.php b/src/Attribute/QuizQuestion.php
new file mode 100644
index 00000000..c3e58fbd
--- /dev/null
+++ b/src/Attribute/QuizQuestion.php
@@ -0,0 +1,41 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\quiz\Attribute;
+
+use Drupal\Component\Plugin\Attribute\Plugin;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
+/**
+ * Defines a Plugin attribute class for quiz questions.
+ *
+ * @see QuizQuestionPluginManager
+ * @see plugin_api
+ *
+ * @ingroup quiz
+ */
+#[\Attribute(\Attribute::TARGET_CLASS)]
+class QuizQuestion extends Plugin {
+
+  /**
+   * Constructs a QuizQuestion attribute.
+   *
+   * @param string $id
+   *   The plugin ID.
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $label
+   *   The label of the plugin.
+   * @param array $handlers
+   *   Array handlers for the question.
+   * @param class-string|null $deriver
+   *   (optional) The deriver class.
+   */
+  public function __construct(
+    public readonly string $id,
+    public readonly ?TranslatableMarkup $label = NULL,
+    protected readonly array $handlers = [],
+    public readonly ?string $deriver = NULL,
+  ) {
+  }
+
+}
diff --git a/src/Entity/QuizFeedbackType.php b/src/Entity/QuizFeedbackType.php
index 77931b90..1e0039ae 100644
--- a/src/Entity/QuizFeedbackType.php
+++ b/src/Entity/QuizFeedbackType.php
@@ -54,7 +54,7 @@ class QuizFeedbackType extends ConfigEntityBase implements RulesUiComponentProvi
   /**
    * {@inheritdoc}
    */
-  public function getComponent() {
+  public function getComponent(): RulesComponent {
     if (empty($this->component)) {
       // Provide a default for now.
       // @todo make expression configurable.
diff --git a/src/Entity/QuizQuestion.php b/src/Entity/QuizQuestion.php
index 62406362..9056f6a7 100644
--- a/src/Entity/QuizQuestion.php
+++ b/src/Entity/QuizQuestion.php
@@ -69,7 +69,7 @@ use Drupal\user\EntityOwnerTrait;
  *   }
  * )
  */
-abstract class QuizQuestion extends EditorialContentEntityBase implements QuizQuestionInterface, EntityOwnerInterface {
+class QuizQuestion extends EditorialContentEntityBase implements QuizQuestionInterface, EntityOwnerInterface {
 
   /**
    * Define question statuses...
@@ -141,4 +141,11 @@ abstract class QuizQuestion extends EditorialContentEntityBase implements QuizQu
     return parent::save();
   }
 
+  /**
+   * @return int
+   */
+  public function getMaximumScore(): int {
+    return 0;
+  }
+
 }
diff --git a/src/Entity/QuizQuestionBroken.php b/src/Entity/QuizQuestionBroken.php
index e3a8efed..dd73182b 100644
--- a/src/Entity/QuizQuestionBroken.php
+++ b/src/Entity/QuizQuestionBroken.php
@@ -7,11 +7,4 @@ namespace Drupal\quiz\Entity;
  */
 class QuizQuestionBroken extends QuizQuestion {
 
-  /**
-   *
-   */
-  public function getMaximumScore(): int {
-    return 0;
-  }
-
 }
diff --git a/src/Entity/QuizResultAnswer.php b/src/Entity/QuizResultAnswer.php
index 27b7dded..34f75ead 100644
--- a/src/Entity/QuizResultAnswer.php
+++ b/src/Entity/QuizResultAnswer.php
@@ -50,7 +50,7 @@ use Drupal\quiz\QuizAnswerInterface;
  *   }
  * )
  */
-abstract class QuizResultAnswer extends ContentEntityBase implements QuizAnswerInterface {
+class QuizResultAnswer extends ContentEntityBase implements QuizAnswerInterface {
 
   use QuizResultAnswerEntityTrait;
 
@@ -158,7 +158,7 @@ abstract class QuizResultAnswer extends ContentEntityBase implements QuizAnswerI
   /**
    * {@inheritdoc}
    *
-   * Quiz result answers are never viewed outside of a Quiz result, so we
+   * Quiz result answers are never viewed outside a Quiz result, so we
    * enforce that a Quiz result route parameter is added.
    */
   public function toUrl($rel = 'canonical', array $options = []) {
@@ -168,4 +168,18 @@ abstract class QuizResultAnswer extends ContentEntityBase implements QuizAnswerI
     return $url;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function score(array $values): ?int {
+    return NULL;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getResponse() {
+    return NULL;
+  }
+
 }
diff --git a/src/Entity/QuizResultAnswerEntityTrait.php b/src/Entity/QuizResultAnswerEntityTrait.php
index 39574b41..f61ae712 100644
--- a/src/Entity/QuizResultAnswerEntityTrait.php
+++ b/src/Entity/QuizResultAnswerEntityTrait.php
@@ -93,7 +93,6 @@ trait QuizResultAnswerEntityTrait {
     if ($quiz->get('randomization')->getString() == 3) {
       /** @var Drupal\paragraphs\Entity\Paragraph[] $terms */
       $terms = $quiz->get('quiz_terms')->referencedEntities();
-      $total_questions = [];
       foreach ($terms as $term) {
         if ($term->get('quiz_question_tid')->getString() == $this->get('tid')->getString()) {
           return $term->get('quiz_question_max_score')->getString();
diff --git a/src/Entity/QuizViewsData.php b/src/Entity/QuizViewsData.php
index d80c4bfd..d1fb7337 100644
--- a/src/Entity/QuizViewsData.php
+++ b/src/Entity/QuizViewsData.php
@@ -17,7 +17,7 @@ class QuizViewsData extends EntityViewsData {
    *
    * @todo Cleanup once https://www.drupal.org/node/2489476 lands.
    */
-  public function getViewsData() {
+  public function getViewsData(): array {
     $data = parent::getViewsData();
 
     foreach (['quiz', 'quiz_revision'] as $table) {
diff --git a/src/Plugin/QuizQuestionPluginManager.php b/src/Plugin/QuizQuestionPluginManager.php
index aee2858d..9a06c56b 100644
--- a/src/Plugin/QuizQuestionPluginManager.php
+++ b/src/Plugin/QuizQuestionPluginManager.php
@@ -5,8 +5,7 @@ namespace Drupal\quiz\Plugin;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Plugin\DefaultPluginManager;
-use Drupal\quiz\Annotation\QuizQuestion;
-
+use Drupal\quiz\Attribute\QuizQuestion;
 /**
  * Provides the Quiz Question plugin manager.
  */
@@ -24,7 +23,7 @@ class QuizQuestionPluginManager extends DefaultPluginManager {
    *   The module handler to invoke the alter hook with.
    */
   public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
-    parent::__construct('Plugin/quiz', $namespaces, $module_handler, QuizQuestionInterface::class, QuizQuestion::class);
+    parent::__construct('Plugin/quiz', $namespaces, $module_handler, QuizQuestionInterface::class,  QuizQuestion::class, 'Drupal\quiz\Annotation\QuizQuestion');
 
     $this->alterInfo('quiz_question_info');
     $this->setCacheBackend($cache_backend, 'quiz_question_plugins');
diff --git a/src/Entity/QuizResultListBuilder.php b/src/QuizResultListBuilder.php
similarity index 86%
rename from src/Entity/QuizResultListBuilder.php
rename to src/QuizResultListBuilder.php
index 59993c6c..65be8cc2 100644
--- a/src/Entity/QuizResultListBuilder.php
+++ b/src/QuizResultListBuilder.php
@@ -1,9 +1,10 @@
 <?php
 
-namespace Drupal\quiz\Entity;
+namespace Drupal\quiz;
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityListBuilder;
+use Drupal\quiz\Entity\QuizResult;
 
 /**
  * Defines the list builder for quiz results.
@@ -13,7 +14,7 @@ class QuizResultListBuilder extends EntityListBuilder {
   /**
    * {@inheritdoc}
    */
-  public function render() {
+  public function render(): array {
     $build = parent::render();
     $build['table']['#caption'] = t('Quiz results.');
     return $build;
@@ -22,7 +23,7 @@ class QuizResultListBuilder extends EntityListBuilder {
   /**
    * {@inheritdoc}
    */
-  public function buildHeader() {
+  public function buildHeader(): array {
     $header['quiz'] = $this->t('Quiz');
     $header['user'] = $this->t('User');
     return $header + parent::buildHeader();
diff --git a/tests/src/Functional/QuizEvaluationTest.php b/tests/src/Functional/QuizEvaluationTest.php
index 15c88809..0ee34621 100644
--- a/tests/src/Functional/QuizEvaluationTest.php
+++ b/tests/src/Functional/QuizEvaluationTest.php
@@ -24,7 +24,7 @@ class QuizEvaluationTest extends QuizTestBase {
   /**
    * Test that a quiz result is marked as evaluated.
    */
-  public function testQuizEvaluation() {
+  public function testQuizEvaluation(): void {
     $this->drupalLogin($this->admin);
 
     $quiz_node = $this->createQuiz();
diff --git a/tests/src/Functional/QuizTestBase.php b/tests/src/Functional/QuizTestBase.php
index cb428b1f..3afd36ea 100644
--- a/tests/src/Functional/QuizTestBase.php
+++ b/tests/src/Functional/QuizTestBase.php
@@ -114,7 +114,7 @@ abstract class QuizTestBase extends BrowserTestBase {
    * @return \Drupal\quiz\Entity\Quiz
    *   The newly created Quiz object.
    */
-  public function createQuiz($settings = []) {
+  public function createQuiz($settings = []): Quiz {
     $settings += [
       'title' => 'Quiz',
       'body' => 'Quiz description',
@@ -136,7 +136,7 @@ abstract class QuizTestBase extends BrowserTestBase {
    * @return \Drupal\quiz\Entity\QuizQuestion
    *   The newly created Quiz Question object.
    */
-  public function createQuestion($settings = []) {
+  public function createQuestion(array $settings = []): QuizQuestion {
     $question = QuizQuestion::create($settings);
     $question->save();
     return $question;
-- 
GitLab