You are here

class Quiz in Quiz 6.x

Same name and namespace in other branches
  1. 8.6 src/Entity/Quiz.php \Drupal\quiz\Entity\Quiz
  2. 8.5 src/Entity/Quiz.php \Drupal\quiz\Entity\Quiz

Defines the Quiz entity class.

Plugin annotation


@ContentEntityType(
  id = "quiz",
  label = @Translation("Quiz"),
  label_collection = @Translation("Quiz"),
  label_singular = @Translation("quiz"),
  label_plural = @Translation("quizzes"),
  label_count = @PluralTranslation(
    singular = "@count quiz",
    plural = "@count quizzes",
  ),
  bundle_label = @Translation("Quiz type"),
  bundle_entity_type = "quiz_type",
  admin_permission = "administer quiz",
  permission_granularity = "bundle",
  base_table = "quiz",
  fieldable = TRUE,
  field_ui_base_route = "entity.quiz_type.edit_form",
  show_revision_ui = TRUE,
  revision_table = "quiz_revision",
  revision_data_table = "quiz_field_revision",
  entity_keys = {
    "id" = "qid",
    "revision" = "vid",
    "bundle" = "type",
    "label" = "title",
    "published" = "status",
    "owner" = "uid",
    "uuid" = "uuid",
  },
  revision_metadata_keys = {
    "revision_user" = "revision_user",
    "revision_created" = "revision_created",
    "revision_log_message" = "revision_log_message",
  },
  handlers = {
    "view_builder" = "Drupal\quiz\View\QuizViewBuilder",
    "list_builder" = "Drupal\quiz\Config\Entity\QuizListBuilder",
    "access" = "Drupal\quiz\Access\QuizAccessControlHandler",
    "permission_provider" = "Drupal\entity\UncacheableEntityPermissionProvider",
    "route_provider" = {
      "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",
    },
   "form" = {
      "default" = "Drupal\quiz\Form\QuizEntityForm",
      "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
    },
    "views_data" = "Drupal\entity\EntityViewsData",
    "storage" = "Drupal\quiz\Storage\QuizStorage"
  },
  links = {
    "canonical" = "/quiz/{quiz}",
    "add-page" = "/quiz/add",
    "add-form" = "/quiz/add/{quiz_type}",
    "edit-form" = "/quiz/{quiz}/edit",
    "delete-form" = "/quiz/{quiz}/delete",
    "collection" = "/admin/quiz/quizzes",
    "take" = "/quiz/{quiz}/take",
  }
)

Hierarchy

Expanded class hierarchy of Quiz

14 files declare their use of Quiz
quiz.module in ./quiz.module
Contains quiz.module
QuizController.php in src/Controller/QuizController.php
QuizEventSubscriber.php in src/EventSubscriber/QuizEventSubscriber.php
QuizQuestionController.php in src/Controller/QuizQuestionController.php
QuizQuestionsForm.php in src/Form/QuizQuestionsForm.php

... See full list

12 string references to 'Quiz'
quiz.info.yml in ./quiz.info.yml
quiz.info.yml
quiz.links.menu.yml in ./quiz.links.menu.yml
quiz.links.menu.yml
quiz.routing.yml in ./quiz.routing.yml
quiz.routing.yml
quiz.type.quiz.yml in config/install/quiz.type.quiz.yml
config/install/quiz.type.quiz.yml
QuizListBuilder::buildHeader in src/Config/Entity/QuizListBuilder.php
Builds the header row for the entity listing.

... See full list

File

src/Entity/Quiz.php, line 82

Namespace

Drupal\quiz\Entity
View source
class Quiz extends EditorialContentEntityBase implements EntityChangedInterface, EntityOwnerInterface, RevisionLogInterface, EntityPublishedInterface {

  /**
   * Define options for keeping results.
   */
  const KEEP_BEST = 0;
  const KEEP_LATEST = 1;
  const KEEP_ALL = 2;
  use EntityOwnerTrait;
  use EntityChangedTrait;
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = parent::baseFieldDefinitions($entity_type);
    $fields += static::ownerBaseFieldDefinitions($entity_type);
    $fields['status']
      ->setDisplayConfigurable('form', TRUE);
    $fields['title'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Title'))
      ->setDescription(t('This is only visible to Quiz admnistrators.'))
      ->setRequired(TRUE)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setSetting('max_length', 255)
      ->setDisplayOptions('view', [
      'label' => 'hidden',
      'type' => 'string',
      'weight' => -5,
    ])
      ->setDisplayOptions('form', [
      'type' => 'string_textfield',
      'weight' => -5,
    ]);
    $fields['body'] = BaseFieldDefinition::create('text_long')
      ->setLabel(t('Description'))
      ->setSetting('weight', 0)
      ->setRequired(TRUE)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions('form', [
      'type' => 'text_textarea',
    ]);
    $fields['created'] = BaseFieldDefinition::create('created')
      ->setRevisionable(TRUE)
      ->setLabel('Created');
    $fields['changed'] = BaseFieldDefinition::create('changed')
      ->setRevisionable(TRUE)
      ->setLabel('Changed');
    $fields['number_of_random_questions'] = BaseFieldDefinition::create('integer')
      ->setRevisionable(TRUE)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayOptions('form', [
      'type' => 'number',
    ])
      ->setLabel(t('Number of random questions'));
    $fields['max_score_for_random'] = BaseFieldDefinition::create('integer')
      ->setDefaultValue(1)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'number',
    ])
      ->setLabel(t('Max score for random'));
    $fields['pass_rate'] = BaseFieldDefinition::create('integer')
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'number',
    ])
      ->setSettings([
      'min' => 0,
      'max' => 100,
    ])
      ->setDescription('Passing rate for this Quiz as a percentage score.')
      ->setLabel(t('Passing rate for Quiz (%)'));
    $fields['summary_pass'] = BaseFieldDefinition::create('text_long')
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'text_textarea',
    ])
      ->setDescription('Summary text for when the user passes the Quiz. Leave blank to not give summary text if passed, or if not using the "passing rate" field above. If not using the "passing rate" field above, this text will not be used.')
      ->setLabel(t('Result text for a passing grade.'));
    $fields['summary_default'] = BaseFieldDefinition::create('text_long')
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'text_textarea',
    ])
      ->setDescription('Summary text for when the user fails the Quiz. Leave blank to not give summary text if failed, or if not using the "passing rate" field above. If not using the "passing rate" field above, this text will not be used.')
      ->setLabel(t('Result text for any grade.'));
    $fields['randomization'] = BaseFieldDefinition::create('list_integer')
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'options_buttons',
    ])
      ->setCardinality(1)
      ->setSetting('allowed_values', [
      0 => 'No randomization',
      1 => 'Random order',
      2 => 'Random questions',
      3 => 'Categorized random questions',
    ])
      ->setDescription("<strong>Random order</strong> - all questions display in random order<br>\n<strong>Random questions</strong> - specific number of questions are drawn randomly from this Quiz's pool of questions<br>\n<strong>Categorized random questions</strong> - specific number of questions are drawn from each specified taxonomy term")
      ->setDefaultValue(0)
      ->setRequired(TRUE)
      ->setLabel(t('Randomize questions'));
    $fields['backwards_navigation'] = BaseFieldDefinition::create('boolean')
      ->setDefaultValue(1)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'boolean_checkbox',
    ])
      ->setDescription('Allow users to go back and revisit questions already answered.')
      ->setLabel(t('Backwards navigation'));
    $fields['keep_results'] = BaseFieldDefinition::create('list_integer')
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setCardinality(1)
      ->setDefaultValue(2)
      ->setRequired(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'options_buttons',
    ])
      ->setSetting('allowed_values', [
      0 => 'The best',
      1 => 'The newest',
      2 => 'All',
    ])
      ->setLabel(t('Store results'))
      ->setDescription('These results should be stored for each user.');
    $fields['repeat_until_correct'] = BaseFieldDefinition::create('boolean')
      ->setDefaultValue(0)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'boolean_checkbox',
    ])
      ->setDescription('Require the user to retry the question until answered correctly.')
      ->setLabel(t('Repeat until correct'));
    $fields['quiz_date'] = BaseFieldDefinition::create('daterange')
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'daterange_default',
    ])
      ->setDescription('The date and time during which this Quiz will be available. Leave blank to always be available.')
      ->setLabel(t('Quiz date'));
    $fields['takes'] = BaseFieldDefinition::create('integer')
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'number',
    ])
      ->setLabel(t('Allowed number of attempts'))
      ->setDescription('The number of times a user is allowed to take this Quiz. Anonymous users are only allowed to take Quiz that allow an unlimited number of attempts.');
    $fields['show_attempt_stats'] = BaseFieldDefinition::create('boolean')
      ->setDefaultValue(1)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'boolean_checkbox',
    ])
      ->setSetting('min', 0)
      ->setDescription('Display the allowed number of attempts on the starting page for this Quiz.')
      ->setLabel(t('Display allowed number of attempts'));
    $fields['time_limit'] = BaseFieldDefinition::create('integer')
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'number',
    ])
      ->setSetting('min', 0)
      ->setDescription('Set the maximum allowed time in seconds for this Quiz. Use 0 for no limit.')
      ->setLabel(t('Time limit'));
    $fields['max_score'] = BaseFieldDefinition::create('integer')
      ->setRevisionable(TRUE)
      ->setLabel(t('Calculated max score of this quiz.'));
    $fields['allow_skipping'] = BaseFieldDefinition::create('boolean')
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDefaultValue(1)
      ->setDisplayOptions('form', [
      'type' => 'boolean_checkbox',
    ])
      ->setDescription('Allow users to skip questions in this Quiz.')
      ->setLabel(t('Allow skipping'));
    $fields['allow_resume'] = BaseFieldDefinition::create('boolean')
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDefaultValue(1)
      ->setDisplayOptions('form', [
      'type' => 'boolean_checkbox',
    ])
      ->setDescription('Allow users to leave this Quiz incomplete and then resume it from where they left off.')
      ->setLabel(t('Allow resume'));
    $fields['allow_jumping'] = BaseFieldDefinition::create('boolean')
      ->setDefaultValue(0)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'boolean_checkbox',
    ])
      ->setDescription('Allow users to jump to any question using a menu or pager in this Quiz.')
      ->setLabel(t('Allow jumping'));
    $fields['allow_change'] = BaseFieldDefinition::create('boolean')
      ->setDefaultValue(1)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'boolean_checkbox',
    ])
      ->setDescription('If the user is able to visit a previous question, allow them to change the answer.')
      ->setLabel(t('Allow changing answers'));
    $fields['allow_change_blank'] = BaseFieldDefinition::create('boolean')
      ->setDefaultValue(0)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'boolean_checkbox',
    ])
      ->setDescription('Allow users to go back and revisit questions already answered.')
      ->setLabel(t('Allow changing blank answers'));
    $fields['build_on_last'] = BaseFieldDefinition::create('list_string')
      ->setLabel('Each attempt builds on the last')
      ->setDisplayConfigurable('form', TRUE)
      ->setDefaultValue('fresh')
      ->setRequired(TRUE)
      ->setCardinality(1)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'options_buttons',
    ])
      ->setSetting('allowed_values', [
      'fresh' => t('Fresh attempt every time'),
      'correct' => t('Prepopulate with correct answers from last result'),
      'all' => t('Prepopulate with all answers from last result'),
    ])
      ->setDescription('Instead of starting a fresh Quiz, users can base a new attempt on the last attempt, with correct answers prefilled. Set the default selection users will see. Selecting "fresh attempt every time" will not allow the user to choose.');
    $fields['show_passed'] = BaseFieldDefinition::create('boolean')
      ->setDefaultValue(1)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'boolean_checkbox',
    ])
      ->setDescription('Show a message if the user has previously passed the Quiz.')
      ->setLabel(t('Show passed message'));
    $fields['mark_doubtful'] = BaseFieldDefinition::create('boolean')
      ->setDefaultValue(0)
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setDisplayOptions('form', [
      'type' => 'boolean_checkbox',
    ])
      ->setDescription('Allow users to mark their answers as doubtful.')
      ->setLabel(t('Mark doubtful'));
    $fields['review_options'] = BaseFieldDefinition::create('map')
      ->setRevisionable(TRUE)
      ->setLabel(t('Review options'));
    $fields['result_type'] = BaseFieldDefinition::create('entity_reference')
      ->setSetting('target_type', 'quiz_result_type')
      ->setRequired(TRUE)
      ->setDefaultValue('quiz_result')
      ->setDisplayConfigurable('form', TRUE)
      ->setRevisionable(TRUE)
      ->setLabel(t('Result type to use'));
    $fields['result_options'] = BaseFieldDefinition::create('entity_reference_revisions')
      ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
      ->setSetting('target_type', 'paragraph')
      ->setSetting('handler_settings', [
      'target_bundles' => [
        'quiz_result_feedback' => 'quiz_result_feedback',
      ],
    ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayOptions('form', [
      'type' => 'entity_reference_paragraphs',
    ])
      ->setLabel('Result options');
    $fields['quiz_terms'] = BaseFieldDefinition::create('entity_reference_revisions')
      ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
      ->setSetting('target_type', 'paragraph')
      ->setSetting('handler_settings', [
      'target_bundles' => [
        'quiz_question_term_pool' => 'quiz_question_term_pool',
      ],
    ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayOptions('form', [
      'type' => 'entity_reference_paragraphs',
    ])
      ->setLabel('Quiz terms');
    return $fields;
  }

  /**
   * Add a question to this quiz.
   *
   * @param QuizQuestion $quiz_question
   *
   * @return \Drupal\quiz\Entity\QuizQuestionRelationship
   *   Newly created or found QuizQuestionRelationship.
   * @todo return value may change
   *
   */
  function addQuestion(QuizQuestion $quiz_question) {
    $relationships = Drupal::entityTypeManager()
      ->getStorage('quiz_question_relationship')
      ->loadByProperties([
      'quiz_vid' => $this
        ->getRevisionId(),
      'question_id' => $quiz_question
        ->id(),
      'question_vid' => $quiz_question
        ->getRevisionId(),
    ]);
    $query = Drupal::database()
      ->select('quiz_question_relationship', 'qqr')
      ->condition('quiz_vid', $this
      ->getRevisionId());
    $query
      ->addExpression('max(weight)', 'max_weight');
    $new_weight = $query
      ->execute()
      ->fetchField();
    if (empty($relationships)) {

      // Save a new relationship.
      $qqr = QuizQuestionRelationship::create([
        'quiz_id' => $this
          ->id(),
        'quiz_vid' => $this
          ->getRevisionId(),
        'question_id' => $quiz_question
          ->id(),
        'question_vid' => $quiz_question
          ->getRevisionId(),
        'weight' => $new_weight + 1,
      ]);
      $qqr
        ->save();
      return $qqr;
    }
    else {
      return reset($relationships);
    }

    // @todo update the max score of the quiz.
    // quiz_update_max_score_properties(array($quiz->vid));
  }

  /**
   * Find a resumable Quiz attempt in progress.
   *
   * @param AccountInterface $user
   *   A user.
   *
   * @return Drupal\quiz\Entity\QuizResult
   *   The Quiz result to resume, or NULL if one is not found.
   */
  function getResumeableResult(AccountInterface $user) {
    $query = Drupal::entityQuery('quiz_result')
      ->condition('qid', $this
      ->get('qid')
      ->getString())
      ->condition('uid', $user
      ->id())
      ->condition('time_end', NULL, 'IS NULL')
      ->sort('time_start', 'DESC')
      ->range(0, 1);
    if ($result = $query
      ->execute()) {
      return QuizResult::load(key($result));
    }
    return NULL;
  }

  /**
   * Delete all quiz results and question relationships when a quiz is deleted.
   *
   * @todo This should probably gather keys instead of loading all entities and
   * looping through to ensure their hooks get fired.
   *
   * {@inheritdoc}
   */
  public function delete() {
    $entities = \Drupal::entityTypeManager()
      ->getStorage('quiz_question_relationship')
      ->loadByProperties([
      'quiz_id' => $this
        ->id(),
    ]);
    foreach ($entities as $entity) {
      $entity
        ->delete();
    }
    $entities = \Drupal::entityTypeManager()
      ->getStorage('quiz_result')
      ->loadByProperties([
      'qid' => $this
        ->id(),
    ]);
    foreach ($entities as $entity) {
      $entity
        ->delete();
    }
    parent::delete();
  }

  /**
   * Retrieves a list of questions (to be taken) for a given quiz.
   *
   * If the quiz has random questions this function only returns a random
   * selection of those questions. This function should be used to decide
   * what questions a quiz taker should answer.
   *
   * This question list is stored in the user's result, and may be different
   * when called multiple times. It should only be used to generate the layout
   * for a quiz attempt and NOT used to do operations on the questions inside of
   * a quiz.
   *
   * @return array
   *   Array of question data keyed by the weight of the question. This should
   *   be used to create QuizResultAnswer entities.
   */
  function buildLayout() {
    $questions = [];
    if ($this
      ->get('randomization')
      ->getString() == 3) {
      $questions = $this
        ->buildCategorizedQuestionList();
    }
    else {

      // Get required questions first.
      $query = \Drupal::database()
        ->query('SELECT qqr.question_id as qqid, qqr.question_vid as vid, qq.type, qqr.qqr_id, qqr.qqr_pid, qq.title
    FROM {quiz_question_relationship} qqr
    JOIN {quiz_question} qq ON qqr.question_id = qq.qqid
    LEFT JOIN {quiz_question_relationship} qqr2 ON (qqr.qqr_pid = qqr2.qqr_id OR (qqr.qqr_pid IS NULL AND qqr.qqr_id = qqr2.qqr_id))
    WHERE qqr.quiz_vid = :quiz_vid
    AND qqr.question_status = :question_status
    ORDER BY qqr2.weight, qqr.weight', [
        ':quiz_vid' => $this
          ->getRevisionId(),
        ':question_status' => QuizQuestion::QUESTION_ALWAYS,
      ]);
      $i = 0;
      while ($question_node = $query
        ->fetchAssoc()) {

        // Just to make it easier on us, let's use a 1-based index.
        $i++;
        $questions[$i] = $question_node;
      }

      // Get random questions for the remainder.
      if ($this
        ->get('randomization')
        ->getString() == 2) {
        if ($this
          ->get('number_of_random_questions')
          ->getString() > 0) {
          $random_questions = $this
            ->getRandomQuestions();
          $questions = array_merge($questions, $random_questions);
          if ($this
            ->get('number_of_random_questions')
            ->getString() > count($random_questions)) {

            // Unable to find enough requested random questions.
            return FALSE;
          }
        }
      }

      // Shuffle questions if required.
      if ($this
        ->get('randomization')
        ->getString() == '1') {
        $question_to_shuffle = [];
        $mark = NULL;
        foreach ($questions as $qidx => $question) {
          if ($mark) {
            if ($question['type'] == 'page') {

              // Found another page.
              shuffle($question_to_shuffle);
              array_splice($questions, $mark, $qidx - $mark - 1, $question_to_shuffle);
              $mark = 0;
              $question_to_shuffle = [];
            }
            else {
              $question_to_shuffle[] = $question;
            }
          }
          if ($question['type'] == 'page') {
            $mark = $qidx;
          }
        }
        if ($mark) {
          shuffle($question_to_shuffle);
          array_splice($questions, $mark, $qidx - $mark, $question_to_shuffle);
        }
        elseif (is_null($mark)) {
          shuffle($questions);
        }
      }
    }
    $count = 0;
    $display_count = 0;
    $questions_out = [];
    foreach ($questions as &$question) {
      $count++;
      $display_count++;
      $question['number'] = $count;
      if ($question['type'] != 'page') {
        $question['display_number'] = $display_count;
      }
      $questions_out[$count] = $question;
    }
    return $questions_out;
  }

  /**
   * Check if this Quiz revision has attempts.
   *
   * @return bool
   *   If the version of this Quiz has attempts.
   */
  function hasAttempts() {
    $result = \Drupal::entityQuery('quiz_result')
      ->condition('qid', $this
      ->id())
      ->condition('vid', $this
      ->getRevisionId())
      ->range(0, 1)
      ->execute();
    return !empty($result);
  }

  /**
   * Build a question list for quizzes with categorized random questions.
   *
   * @return array
   *   Array of question information.
   */
  function buildCategorizedQuestionList() {

    /* @var $terms Drupal\paragraphs\Entity\Paragraph[] */
    $terms = $this
      ->get('quiz_terms')
      ->referencedEntities();
    $total_questions = [];
    foreach ($terms as $term) {

      // Get the term ID referenced on the quiz question pool.
      $tid = $term
        ->get('quiz_question_tid')
        ->referencedEntities()[0]
        ->id();
      $query = \Drupal::entityQuery('quiz_question');

      // Find all taxonomy fields on questions.
      $fields = \Drupal::service('entity_field.manager')
        ->getFieldStorageDefinitions('quiz_question');
      $or = $query
        ->orConditionGroup();
      foreach ($fields as $field_name => $field) {
        if ($field
          ->getType() == 'entity_reference' && $field
          ->getSetting('target_type') == 'taxonomy_term') {
          $or
            ->condition("{$field_name}.target_id", $tid);
        }
      }
      $query
        ->condition($or);
      $query
        ->condition('status', 1);
      $query
        ->addTag('quiz_build_categorized_questions');
      $query
        ->addTag('quiz_random');
      $query
        ->range(0, $term
        ->get('quiz_question_number')
        ->getString());
      $question_ids = $query
        ->execute();
      if (count($question_ids) != $term
        ->get('quiz_question_number')
        ->getString()) {

        // Didn't find enough questions in this category.
        return [];
      }
      $found_questions = QuizQuestion::loadMultiple($question_ids);
      foreach ($found_questions as $qqid => $question) {
        $total_questions[] = [
          'qqid' => $qqid,
          'tid' => $tid,
          'type' => $question
            ->bundle(),
          'vid' => $question
            ->getRevisionId(),
        ];
      }
    }

    // Optionally shuffle all categories together?

    //shuffle($total_questions);
    return $total_questions;
  }

  /**
   * Get the number of required questions for a quiz.
   *
   * @return int
   *   Number of required questions.
   */
  function getNumberOfRequiredQuestions() {
    $query = Drupal::entityQuery('quiz_question_relationship');
    $query
      ->condition('quiz_vid', $this
      ->getRevisionId());
    $query
      ->condition('question_status', QuizQuestion::QUESTION_ALWAYS);
    $result = $query
      ->execute();
    return count($result);
  }

  /**
   * Finds out the number of configured questions for the quiz, taking into
   * account random questions pulled from a pool
   *
   * @return int
   *   The number of quiz questions.
   */
  function getNumberOfQuestions() {
    $count = 0;
    $relationships = $this
      ->getQuestions();
    $random = $this
      ->get('randomization')
      ->getString();
    switch ($random) {
      case 2:
      case 3:
        $count = $this
          ->getNumberOfRequiredQuestions() + $this
          ->get('number_of_random_questions')->value;
        break;
      case 0:
      case 1:
      default:
        foreach ($relationships as $relationship) {
          if ($quizQuestion = $relationship
            ->getQuestion()) {
            if ($quizQuestion
              ->isGraded()) {
              $count++;
            }
          }
        }
    }
    return intval($count);
  }

  /**
   * Show the finish button?
   */
  function isLastQuestion() {

    /* @var $quiz_session \Drupal\quiz\Services\QuizSessionInterface */
    $quiz_session = \Drupal::service('quiz.session');
    $quiz_result = $quiz_session
      ->getResult($this);
    $current = $quiz_session
      ->getCurrentQuestion($this);
    $layout = $quiz_result
      ->getLayout();
    foreach ($layout as $idx => $qra) {
      if ($qra
        ->get('question_id')
        ->referencedEntities()[0]
        ->bundle() == 'page') {
        if ($current == $idx) {

          // Found a page that we are on.
          $in_page = TRUE;
          $last_page = TRUE;
        }
        else {

          // Found a quiz page that we are not on.
          $last_page = FALSE;
        }
      }
      elseif (empty($qra->qqr_pid)) {

        // A question without a parent showed up.
        $in_page = FALSE;
        $last_page = FALSE;
      }
    }
    return $last_page || !isset($layout[$current + 1]);
  }

  /**
   * Store old revision ID for copying questions.
   */
  function createDuplicate() {
    $vid = $this
      ->getRevisionId();
    $dupe = parent::createDuplicate();
    $dupe->old_vid = $vid;
    return $dupe;
  }

  /**
   * Retrieve list of published questions assigned to quiz.
   *
   * This function should be used for question browsers and similar. It
   * should not be used to decide what questions a user should answer when
   * taking a quiz. Quiz::buildLayout is written for that purpose.
   *
   * @return QuizQuestionRelationship[]
   *   An array of questions.
   */
  function getQuestions() {
    $relationships = Drupal::entityTypeManager()
      ->getStorage('quiz_question_relationship')
      ->loadByProperties([
      'quiz_vid' => $this
        ->getRevisionId(),
    ]);
    return $relationships;
  }

  /**
   * Copy questions to a new quiz revision.
   *
   * @param Quiz $old_quiz
   *   The old quiz revision.
   */
  function copyFromRevision(Quiz $old_quiz) {
    $quiz_questions = \Drupal::entityTypeManager()
      ->getStorage('quiz_question_relationship')
      ->loadByProperties([
      'quiz_vid' => $old_quiz
        ->getRevisionId(),
    ]);
    foreach ($quiz_questions as $quiz_question) {
      $new_question = $quiz_question
        ->createDuplicate();
      $new_question
        ->set('quiz_vid', $this
        ->getRevisionId());
      $new_question
        ->set('quiz_id', $this
        ->id());
      $old_id = $quiz_question
        ->id();
      $new_question
        ->save();
      $new_questions[$old_id] = $new_question;
    }
    foreach ($new_questions as $old_id => $quiz_question) {
      if (!$quiz_question
        ->get('qqr_pid')
        ->isEmpty()) {
        $quiz_question
          ->set('qqr_pid', $new_questions[$quiz_question
          ->get('qqr_pid')
          ->getString()]
          ->id());
        $quiz_question
          ->save();
      }
    }
  }

  /**
   * Get random questions for a quiz.
   *
   * @return array
   *   Array questions.
   */
  function getRandomQuestions() {
    $num_random = $this
      ->get('number_of_random_questions')
      ->getString();
    $questions = [];
    if ($num_random > 0) {

      // Select random question from assigned pool.
      $query = Drupal::entityQuery('quiz_question_relationship');
      $query
        ->condition('quiz_vid', $this
        ->getRevisionId());
      $query
        ->condition('question_status', QuizQuestion::QUESTION_RANDOM);
      $query
        ->addTag('quiz_random');
      $query
        ->range(0, $this
        ->get('number_of_random_questions')
        ->getString());
      if ($relationships = $query
        ->execute()) {

        /* @var $qqrs QuizQuestionRelationship[] */
        $qqrs = QuizQuestionRelationship::loadMultiple($relationships);
        foreach ($qqrs as $qqr) {
          $questionEntity = Drupal::entityTypeManager()
            ->getStorage('quiz_question')
            ->loadRevision($qqr
            ->get('question_vid')
            ->getString());
          $question = [
            'qqid' => $questionEntity
              ->id(),
            'vid' => $questionEntity
              ->getRevisionId(),
            'type' => $questionEntity
              ->bundle(),
            'random' => TRUE,
            'relative_max_score' => $this
              ->get('max_score_for_random')
              ->getString(),
          ];
          $questions[] = $question;
        }
        return $questions;
      }
    }
    return [];
  }

  /**
   * Check if a user passed this Quiz.
   *
   * @param AccountInterface $account
   *   The user to check.
   *
   * @return bool
   *   Returns TRUE if the user has passed the quiz at least once, and FALSE
   *   otherwise. Note that a FALSE may simply indicate that the user has not
   *   taken the quiz.
   */
  function isPassed(AccountInterface $account) {

    // @todo convert to select()
    $passed = Drupal::database()
      ->query('SELECT COUNT(result_id) AS passed_count
    FROM {quiz_result} qnrs
    INNER JOIN {quiz} USING (vid, qid)
    WHERE qnrs.vid = :vid
    AND qnrs.qid = :qid
    AND qnrs.uid = :uid
    AND score >= pass_rate', [
      ':vid' => $this
        ->getRevisionId(),
      ':qid' => $this
        ->id(),
      ':uid' => $account
        ->id(),
    ])
      ->fetchField();
    return $passed > 0;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CacheableDependencyTrait::$cacheContexts protected property Cache contexts.
CacheableDependencyTrait::$cacheMaxAge protected property Cache max-age.
CacheableDependencyTrait::$cacheTags protected property Cache tags.
CacheableDependencyTrait::setCacheability protected function Sets cacheability; useful for value object constructors.
ContentEntityBase::$activeLangcode protected property Language code identifying the entity active language.
ContentEntityBase::$defaultLangcode protected property Local cache for the default language code.
ContentEntityBase::$defaultLangcodeKey protected property The default langcode entity key.
ContentEntityBase::$enforceRevisionTranslationAffected protected property Whether the revision translation affected flag has been enforced.
ContentEntityBase::$entityKeys protected property Holds untranslatable entity keys such as the ID, bundle, and revision ID.
ContentEntityBase::$fieldDefinitions protected property Local cache for field definitions.
ContentEntityBase::$fields protected property The array of fields, each being an instance of FieldItemListInterface.
ContentEntityBase::$fieldsToSkipFromTranslationChangesCheck protected static property Local cache for fields to skip from the checking for translation changes.
ContentEntityBase::$isDefaultRevision protected property Indicates whether this is the default revision.
ContentEntityBase::$langcodeKey protected property The language entity key.
ContentEntityBase::$languages protected property Local cache for the available language objects.
ContentEntityBase::$loadedRevisionId protected property The loaded revision ID before the new revision was set.
ContentEntityBase::$newRevision protected property Boolean indicating whether a new revision should be created on save.
ContentEntityBase::$revisionTranslationAffectedKey protected property The revision translation affected entity key.
ContentEntityBase::$translatableEntityKeys protected property Holds translatable entity keys such as the label.
ContentEntityBase::$translationInitialize protected property A flag indicating whether a translation object is being initialized.
ContentEntityBase::$translations protected property An array of entity translation metadata.
ContentEntityBase::$validated protected property Whether entity validation was performed.
ContentEntityBase::$validationRequired protected property Whether entity validation is required before saving the entity.
ContentEntityBase::$values protected property The plain data values of the contained fields.
ContentEntityBase::access public function Checks data value access. Overrides EntityBase::access 1
ContentEntityBase::addTranslation public function Adds a new translation to the translatable object. Overrides TranslatableInterface::addTranslation
ContentEntityBase::bundle public function Gets the bundle of the entity. Overrides EntityBase::bundle
ContentEntityBase::bundleFieldDefinitions public static function Provides field definitions for a specific bundle. Overrides FieldableEntityInterface::bundleFieldDefinitions 4
ContentEntityBase::clearTranslationCache protected function Clear entity translation object cache to remove stale references.
ContentEntityBase::get public function Gets a field item list. Overrides FieldableEntityInterface::get
ContentEntityBase::getEntityKey protected function Gets the value of the given entity key, if defined. 1
ContentEntityBase::getFieldDefinition public function Gets the definition of a contained field. Overrides FieldableEntityInterface::getFieldDefinition
ContentEntityBase::getFieldDefinitions public function Gets an array of field definitions of all contained fields. Overrides FieldableEntityInterface::getFieldDefinitions
ContentEntityBase::getFields public function Gets an array of all field item lists. Overrides FieldableEntityInterface::getFields
ContentEntityBase::getFieldsToSkipFromTranslationChangesCheck protected function Returns an array of field names to skip in ::hasTranslationChanges. 1
ContentEntityBase::getIterator public function
ContentEntityBase::getLanguages protected function
ContentEntityBase::getLoadedRevisionId public function Gets the loaded Revision ID of the entity. Overrides RevisionableInterface::getLoadedRevisionId
ContentEntityBase::getRevisionId public function Gets the revision identifier of the entity. Overrides RevisionableInterface::getRevisionId
ContentEntityBase::getTranslatableFields public function Gets an array of field item lists for translatable fields. Overrides FieldableEntityInterface::getTranslatableFields
ContentEntityBase::getTranslatedField protected function Gets a translated field.
ContentEntityBase::getTranslation public function Gets a translation of the data. Overrides TranslatableInterface::getTranslation
ContentEntityBase::getTranslationLanguages public function Returns the languages the data is translated to. Overrides TranslatableInterface::getTranslationLanguages
ContentEntityBase::getTranslationStatus public function Returns the translation status. Overrides TranslationStatusInterface::getTranslationStatus
ContentEntityBase::getUntranslated public function Returns the translatable object referring to the original language. Overrides TranslatableInterface::getUntranslated
ContentEntityBase::hasField public function Determines whether the entity has a field with the given name. Overrides FieldableEntityInterface::hasField
ContentEntityBase::hasTranslation public function Checks there is a translation for the given language code. Overrides TranslatableInterface::hasTranslation
ContentEntityBase::hasTranslationChanges public function Determines if the current translation of the entity has unsaved changes. Overrides TranslatableInterface::hasTranslationChanges
ContentEntityBase::id public function Gets the identifier. Overrides EntityBase::id
ContentEntityBase::initializeTranslation protected function Instantiates a translation object for an existing translation.
ContentEntityBase::isDefaultRevision public function Checks if this entity is the default revision. Overrides RevisionableInterface::isDefaultRevision
ContentEntityBase::isDefaultTranslation public function Checks whether the translation is the default one. Overrides TranslatableInterface::isDefaultTranslation
ContentEntityBase::isDefaultTranslationAffectedOnly public function Checks if untranslatable fields should affect only the default translation. Overrides TranslatableRevisionableInterface::isDefaultTranslationAffectedOnly
ContentEntityBase::isLatestRevision public function Checks if this entity is the latest revision. Overrides RevisionableInterface::isLatestRevision
ContentEntityBase::isLatestTranslationAffectedRevision public function Checks whether this is the latest revision affecting this translation. Overrides TranslatableRevisionableInterface::isLatestTranslationAffectedRevision
ContentEntityBase::isNewRevision public function Determines whether a new revision should be created on save. Overrides RevisionableInterface::isNewRevision
ContentEntityBase::isNewTranslation public function Checks whether the translation is new. Overrides TranslatableInterface::isNewTranslation
ContentEntityBase::isRevisionTranslationAffected public function Checks whether the current translation is affected by the current revision. Overrides TranslatableRevisionableInterface::isRevisionTranslationAffected
ContentEntityBase::isRevisionTranslationAffectedEnforced public function Checks if the revision translation affected flag value has been enforced. Overrides TranslatableRevisionableInterface::isRevisionTranslationAffectedEnforced
ContentEntityBase::isTranslatable public function Returns the translation support status. Overrides TranslatableInterface::isTranslatable
ContentEntityBase::isValidationRequired public function Checks whether entity validation is required before saving the entity. Overrides FieldableEntityInterface::isValidationRequired
ContentEntityBase::label public function Gets the label of the entity. Overrides EntityBase::label 6
ContentEntityBase::language public function Gets the language of the entity. Overrides EntityBase::language
ContentEntityBase::onChange public function Reacts to changes to a field. Overrides FieldableEntityInterface::onChange
ContentEntityBase::postCreate public function Acts on a created entity before hooks are invoked. Overrides EntityBase::postCreate
ContentEntityBase::postSave public function Acts on a saved entity before the insert or update hook is invoked. Overrides EntityBase::postSave 9
ContentEntityBase::preSave public function Acts on an entity before the presave hook is invoked. Overrides EntityBase::preSave 8
ContentEntityBase::preSaveRevision public function Acts on a revision before it gets saved. Overrides RevisionableInterface::preSaveRevision 3
ContentEntityBase::referencedEntities public function Gets a list of entities referenced by this entity. Overrides EntityBase::referencedEntities 1
ContentEntityBase::removeTranslation public function Removes the translation identified by the given language code. Overrides TranslatableInterface::removeTranslation
ContentEntityBase::set public function Sets a field value. Overrides FieldableEntityInterface::set
ContentEntityBase::setDefaultLangcode protected function Populates the local cache for the default language code.
ContentEntityBase::setNewRevision public function Enforces an entity to be saved as a new revision. Overrides RevisionableInterface::setNewRevision
ContentEntityBase::setRevisionTranslationAffected public function Marks the current revision translation as affected. Overrides TranslatableRevisionableInterface::setRevisionTranslationAffected
ContentEntityBase::setRevisionTranslationAffectedEnforced public function Enforces the revision translation affected flag value. Overrides TranslatableRevisionableInterface::setRevisionTranslationAffectedEnforced
ContentEntityBase::setValidationRequired public function Sets whether entity validation is required before saving the entity. Overrides FieldableEntityInterface::setValidationRequired
ContentEntityBase::toArray public function Gets an array of all property values. Overrides EntityBase::toArray
ContentEntityBase::updateFieldLangcodes protected function Updates language for already instantiated fields.
ContentEntityBase::updateLoadedRevisionId public function Updates the loaded Revision ID with the revision ID. Overrides RevisionableInterface::updateLoadedRevisionId
ContentEntityBase::updateOriginalValues public function Updates the original values with the interim changes.
ContentEntityBase::uuid public function Gets the entity UUID (Universally Unique Identifier). Overrides EntityBase::uuid
ContentEntityBase::validate public function Validates the currently set values. Overrides FieldableEntityInterface::validate 1
ContentEntityBase::wasDefaultRevision public function Checks whether the entity object was a default revision when it was saved. Overrides RevisionableInterface::wasDefaultRevision
ContentEntityBase::__clone public function Magic method: Implements a deep clone.
ContentEntityBase::__construct public function Constructs an Entity object. Overrides EntityBase::__construct
ContentEntityBase::__get public function Implements the magic method for getting object properties.
ContentEntityBase::__isset public function Implements the magic method for isset().
ContentEntityBase::__set public function Implements the magic method for setting object properties.
ContentEntityBase::__sleep public function Overrides EntityBase::__sleep
ContentEntityBase::__unset public function Implements the magic method for unset().
DependencySerializationTrait::$_entityStorages protected property
DependencySerializationTrait::$_serviceIds protected property
DependencySerializationTrait::__sleep public function Aliased as: traitSleep 2
DependencySerializationTrait::__wakeup public function 2
EntityBase::$enforceIsNew protected property Boolean indicating whether the entity should be forced to be new.
EntityBase::$entityTypeId protected property The entity type.
EntityBase::$typedData protected property A typed data object wrapping this entity.
EntityBase::create public static function Constructs a new entity object, without permanently saving it. Overrides EntityInterface::create
EntityBase::enforceIsNew public function Enforces an entity to be new. Overrides EntityInterface::enforceIsNew
EntityBase::entityTypeBundleInfo protected function Gets the entity type bundle info service.
EntityBase::entityTypeManager protected function Gets the entity type manager.
EntityBase::getCacheContexts public function The cache contexts associated with this object. Overrides CacheableDependencyTrait::getCacheContexts
EntityBase::getCacheMaxAge public function The maximum age for which this object may be cached. Overrides CacheableDependencyTrait::getCacheMaxAge
EntityBase::getCacheTags public function The cache tags associated with this object. Overrides CacheableDependencyTrait::getCacheTags
EntityBase::getCacheTagsToInvalidate public function Returns the cache tags that should be used to invalidate caches. Overrides EntityInterface::getCacheTagsToInvalidate 4
EntityBase::getConfigDependencyKey public function Gets the key that is used to store configuration dependencies. Overrides EntityInterface::getConfigDependencyKey
EntityBase::getConfigDependencyName public function Gets the configuration dependency name. Overrides EntityInterface::getConfigDependencyName 1
EntityBase::getConfigTarget public function Gets the configuration target identifier for the entity. Overrides EntityInterface::getConfigTarget 1
EntityBase::getEntityTypeId public function Gets the ID of the type of the entity. Overrides EntityInterface::getEntityTypeId
EntityBase::getListCacheTagsToInvalidate protected function The list cache tags to invalidate for this entity.
EntityBase::getOriginalId public function Gets the original ID. Overrides EntityInterface::getOriginalId 1
EntityBase::getTypedData public function Gets a typed data object for this entity object. Overrides EntityInterface::getTypedData
EntityBase::hasLinkTemplate public function Indicates if a link template exists for a given key. Overrides EntityInterface::hasLinkTemplate
EntityBase::invalidateTagsOnDelete protected static function Invalidates an entity's cache tags upon delete. 1
EntityBase::invalidateTagsOnSave protected function Invalidates an entity's cache tags upon save. 1
EntityBase::isNew public function Determines whether the entity is new. Overrides EntityInterface::isNew 2
EntityBase::languageManager protected function Gets the language manager.
EntityBase::linkTemplates protected function Gets an array link templates. 1
EntityBase::load public static function Loads an entity. Overrides EntityInterface::load
EntityBase::loadMultiple public static function Loads one or more entities. Overrides EntityInterface::loadMultiple
EntityBase::postDelete public static function Acts on deleted entities before the delete hook is invoked. Overrides EntityInterface::postDelete 18
EntityBase::postLoad public static function Acts on loaded entities. Overrides EntityInterface::postLoad 2
EntityBase::preCreate public static function Changes the values of an entity before it is created. Overrides EntityInterface::preCreate 7
EntityBase::preDelete public static function Acts on entities before they are deleted and before hooks are invoked. Overrides EntityInterface::preDelete 6
EntityBase::save public function Saves an entity permanently. Overrides EntityInterface::save 3
EntityBase::setOriginalId public function Sets the original ID. Overrides EntityInterface::setOriginalId 1
EntityBase::toLink public function Generates the HTML for a link to this entity. Overrides EntityInterface::toLink
EntityBase::toUrl public function Gets the URL object for the entity. Overrides EntityInterface::toUrl 2
EntityBase::uriRelationships public function Gets a list of URI relationships supported by this entity. Overrides EntityInterface::uriRelationships
EntityBase::urlRouteParameters protected function Gets an array of placeholders for this entity. 2
EntityBase::uuidGenerator protected function Gets the UUID generator.
EntityChangedTrait::getChangedTime public function Gets the timestamp of the last entity change for the current translation.
EntityChangedTrait::getChangedTimeAcrossTranslations public function Returns the timestamp of the last entity change across all translations.
EntityChangedTrait::setChangedTime public function Sets the timestamp of the last entity change for the current translation.
EntityChangesDetectionTrait::getFieldsToSkipFromTranslationChangesCheck protected function Returns an array of field names to skip when checking for changes. Aliased as: traitGetFieldsToSkipFromTranslationChangesCheck
EntityOwnerTrait::getDefaultEntityOwner public static function Default value callback for 'owner' base field. 1
EntityOwnerTrait::getOwner public function 1
EntityOwnerTrait::getOwnerId public function
EntityOwnerTrait::ownerBaseFieldDefinitions public static function Returns an array of base field definitions for entity owners.
EntityOwnerTrait::setOwner public function
EntityOwnerTrait::setOwnerId public function
EntityPublishedTrait::isPublished public function
EntityPublishedTrait::publishedBaseFieldDefinitions public static function Returns an array of base field definitions for publishing status.
EntityPublishedTrait::setPublished public function
EntityPublishedTrait::setUnpublished public function
Quiz::addQuestion function Add a question to this quiz.
Quiz::baseFieldDefinitions public static function Provides base field definitions for an entity type. Overrides EditorialContentEntityBase::baseFieldDefinitions
Quiz::buildCategorizedQuestionList function Build a question list for quizzes with categorized random questions.
Quiz::buildLayout function Retrieves a list of questions (to be taken) for a given quiz.
Quiz::copyFromRevision function Copy questions to a new quiz revision.
Quiz::createDuplicate function Store old revision ID for copying questions. Overrides ContentEntityBase::createDuplicate
Quiz::delete public function Delete all quiz results and question relationships when a quiz is deleted. Overrides EntityBase::delete
Quiz::getNumberOfQuestions function Finds out the number of configured questions for the quiz, taking into account random questions pulled from a pool
Quiz::getNumberOfRequiredQuestions function Get the number of required questions for a quiz.
Quiz::getQuestions function Retrieve list of published questions assigned to quiz.
Quiz::getRandomQuestions function Get random questions for a quiz.
Quiz::getResumeableResult function Find a resumable Quiz attempt in progress.
Quiz::hasAttempts function Check if this Quiz revision has attempts.
Quiz::isLastQuestion function Show the finish button?
Quiz::isPassed function Check if a user passed this Quiz.
Quiz::KEEP_ALL constant
Quiz::KEEP_BEST constant Define options for keeping results.
Quiz::KEEP_LATEST constant
RefinableCacheableDependencyTrait::addCacheableDependency public function 1
RefinableCacheableDependencyTrait::addCacheContexts public function
RefinableCacheableDependencyTrait::addCacheTags public function
RefinableCacheableDependencyTrait::mergeCacheMaxAge public function
RevisionLogEntityTrait::getEntityType abstract public function Gets the entity type definition.
RevisionLogEntityTrait::getRevisionCreationTime public function Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionCreationTime(). 1
RevisionLogEntityTrait::getRevisionLogMessage public function Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionLogMessage(). 1
RevisionLogEntityTrait::getRevisionMetadataKey protected static function Gets the name of a revision metadata field.
RevisionLogEntityTrait::getRevisionUser public function Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionUser(). 1
RevisionLogEntityTrait::getRevisionUserId public function Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionUserId(). 1
RevisionLogEntityTrait::revisionLogBaseFieldDefinitions public static function Provides revision-related base field definitions for an entity type.
RevisionLogEntityTrait::setRevisionCreationTime public function Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionCreationTime(). 1
RevisionLogEntityTrait::setRevisionLogMessage public function Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionLogMessage(). 1
RevisionLogEntityTrait::setRevisionUser public function Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionUser(). 1
RevisionLogEntityTrait::setRevisionUserId public function Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionUserId(). 1
SynchronizableEntityTrait::$isSyncing protected property Whether this entity is being created, updated or deleted through a synchronization process.
SynchronizableEntityTrait::isSyncing public function
SynchronizableEntityTrait::setSyncing public function
TranslationStatusInterface::TRANSLATION_CREATED constant Status code identifying a newly created translation.
TranslationStatusInterface::TRANSLATION_EXISTING constant Status code identifying an existing translation.
TranslationStatusInterface::TRANSLATION_REMOVED constant Status code identifying a removed translation.