You are here

public function DataPolicyConsentManager::saveConsent in Data Policy 8

Save user consent.

Parameters

int $user_id: The user ID.

string $action: The action (submit and etc.)

array $values: Array of user consent values to process saveConsent:

  • state - required option,
  • entity_id - required option,

The one of three allowed states:

  • undecided,
  • not agree,
  • agree.

Overrides DataPolicyConsentManagerInterface::saveConsent

File

src/DataPolicyConsentManager.php, line 177

Class

DataPolicyConsentManager
Defines the Data Policy Consent Manager service.

Namespace

Drupal\data_policy

Code

public function saveConsent($user_id, $action = NULL, $values = [
  'state' => UserConsentInterface::STATE_UNDECIDED,
]) {

  // This logic determines whether we need to create a new "user_consent"
  // entity or not, depending on whether there are new and active
  // "data_policy" with which the user should agree. Previously, there
  // was a `getState` method for this, but it is not relevant since now we
  // do not have a binding to only one entity.
  // See \Drupal\data_policy\Form\DataPolicyAgreement::submitForm.
  $user_consents = $this->entityTypeManager
    ->getStorage('user_consent')
    ->loadByProperties([
    'user_id' => $user_id,
    'status' => TRUE,
  ]);

  /** @var \Drupal\data_policy\DataPolicyStorageInterface $data_policy_storage */
  $data_policy_storage = $this->entityTypeManager
    ->getStorage('data_policy');

  // Existing states for the current user.
  $existing_states = array_map(function (UserConsentInterface $user_consent) {
    return $user_consent->state->value;
  }, $user_consents);
  if ($action === 'submit') {
    $first = FALSE;
    foreach ($values as $value) {
      $state = $this
        ->getStateNumber($value['state']);
      $is_equals = TRUE;
      foreach ($existing_states as $existing_state) {
        if ($existing_state != $state) {
          $is_equals = FALSE;
          break;
        }
      }
      if (empty($existing_states)) {
        $is_equals = FALSE;
      }

      // If submitted states for user_consent entities are the same as
      // existing then we just need to do nothing.
      if ($is_equals) {
        return;
      }

      // Set an "unpublished" status for all "user_consent" entities that
      // were active before submit.
      if (!empty($user_consents) && $first === FALSE) {
        foreach ($user_consents as $user_consent) {
          $user_consent
            ->setPublished(FALSE)
            ->save();
          $first = TRUE;
        }
      }

      // Create new "user_consent" entities with active revision from
      // user consent text in the settings tab.

      /** @var \Drupal\data_policy\Entity\DataPolicyInterface $data_policy */
      $data_policy = $data_policy_storage
        ->load($value['entity_id']);
      $is_required = $this
        ->isRequiredEntity($value['entity_id']);
      $this
        ->createUserConsent($data_policy, $user_id, $state, $is_required);
    }
  }
  elseif ($action === 'visit') {
    $state = $this
      ->getStateNumber($values['state']);
    $entities = $this
      ->getEntityIdsFromConsentText();
    if (!empty($existing_states)) {

      // Existing revisions for the current user.
      $existing_revisions = array_map(function (UserConsentInterface $user_consent) {
        return $user_consent->data_policy_revision_id->value;
      }, $user_consents);
      $revisions = $this
        ->getRevisionsByEntityIds($entities);
      $revision_ids_from_consent_text = array_map(function (DataPolicyInterface $revision) {
        return $revision
          ->getRevisionId();
      }, $revisions);

      // If existing revisions for the current user are different from
      // current revisions (consent text in setting form) then we should
      // create "user_consent" entities with zero state and all entities
      // for the current user before visit the agreement page will be
      // removed from published.
      $diff = array_diff($existing_revisions, $revision_ids_from_consent_text);
      $confirmed = array_flip(array_intersect($existing_revisions, $revision_ids_from_consent_text));
      if (!empty($diff)) {

        // Remove from the publication the old consents, those that were
        // previously agreed - skip.
        foreach ($user_consents as $id => $user_consent) {
          if (in_array($id, $confirmed)) {
            continue;
          }
          $user_consent
            ->setPublished(FALSE)
            ->save();
        }

        // Create new ones, those that were previously agreed - skip.
        foreach (array_diff($revision_ids_from_consent_text, array_flip($confirmed)) as $revision_id) {

          /** @var \Drupal\data_policy\Entity\DataPolicyInterface $data_policy */
          $data_policy = $data_policy_storage
            ->loadRevision($revision_id);
          $is_required = $this
            ->isRequiredEntity($data_policy
            ->id());
          $this
            ->createUserConsent($data_policy, $user_id, $state, $is_required);
        }
      }
      $is_equals = TRUE;
      $skip = TRUE;
      foreach ($existing_states as $existing_state) {

        // If the current state for the current user more then existing in
        // the database then we need to create new entries in the database.
        if ((int) $existing_state < (int) $state) {
          $skip = FALSE;
          break;
        }

        // If existing states are not equal the current user state then we
        // need to create new entries in the database.
        if ($existing_state != $state) {
          $is_equals = FALSE;
          break;
        }
      }
      if ($is_equals || $skip) {
        return;
      }
    }
    foreach ($entities as $entity) {

      /** @var \Drupal\data_policy\Entity\DataPolicyInterface $data_policy */
      $data_policy = $data_policy_storage
        ->load($entity);
      $is_required = $this
        ->isRequiredEntity($entity);
      $this
        ->createUserConsent($data_policy, $user_id, $state, $is_required);
    }
  }
}