email_confirmer-8.x-1.x-dev/src/Entity/EmailConfirmation.php
src/Entity/EmailConfirmation.php
<?php
namespace Drupal\email_confirmer\Entity;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\email_confirmer\EmailConfirmationInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\email_confirmer\InvalidConfirmationStateException;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Url;
/**
* Defines the email confirmation entity class.
*
* @ContentEntityType(
* id = "email_confirmer_confirmation",
* label = @Translation("Email confirmation"),
* label_singular = @Translation("Email confirmation"),
* label_plural = @Translation("Email confirmations"),
* label_count = @PluralTranslation(
* singular = "@count email confirmation",
* plural = "@count email confirmations",
* ),
* handlers = {
* "access" = "Drupal\email_confirmer\EmailConfirmationAccessControlHandler",
* "form" = {
* "response" = "Drupal\email_confirmer\Form\EmailConfirmerResponseForm",
* },
* },
* base_table = "email_confirmer_confirmation",
* entity_keys = {
* "id" = "cid",
* "uuid" = "uuid",
* "label" = "email",
* "langcode" = "langcode",
* "uid" = "uid",
* },
* admin_permission = "administer email confirmations",
* )
*/
class EmailConfirmation extends ContentEntityBase implements EmailConfirmationInterface {
/**
* {@inheritdoc}
*/
public function label() {
return $this->get('email')->value;
}
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
/** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */
$fields = parent::baseFieldDefinitions($entity_type);
$fields['cid'] = BaseFieldDefinition::create('integer')
->setLabel(t('Email confirmation ID'))
->setDescription(t('The ID of the email confirmation.'))
->setReadOnly(TRUE);
$fields['email'] = BaseFieldDefinition::create('email')
->setLabel(t('Email'))
->setDescription(t('The email address of this confirmation.'))
->setRequired(TRUE)
->setSetting('max_length', 255)
->setDisplayOptions('view', [
'type' => 'string',
'weight' => 0,
]);
$fields['realm'] = BaseFieldDefinition::create('string')
->setLabel(t('Realm'))
->setSetting('max_length', 255)
->setDisplayOptions('view', [
'type' => 'string',
'weight' => 0,
]);
$fields['ip'] = BaseFieldDefinition::create('string')
->setLabel(t('IP address'))
->setDescription(t('Confirmation related IP address.'))
->setSetting('max_length', 45)
->setDefaultValueCallback('Drupal\email_confirmer\Entity\EmailConfirmation::getRequestIp')
->setDisplayOptions('view', [
'type' => 'string',
'weight' => 0,
]);
$fields['data'] = BaseFieldDefinition::create('map')
->setLabel(t('Data'))
->setDescription(t('Any arbitrary data to store with the confirmation.'));
$fields['confirm_url'] = BaseFieldDefinition::create('uri')
->setLabel(t('On confirmation URL'))
->setDescription(t('A URL to go after an email confirmation was done.'))
->setSetting('max_length', 255);
$fields['cancel_url'] = BaseFieldDefinition::create('uri')
->setLabel(t('On cancellation URL'))
->setDescription(t('A URL to go after an email confirmation was cancelled.'))
->setSetting('max_length', 255);
$fields['error_url'] = BaseFieldDefinition::create('uri')
->setLabel(t('On error URL'))
->setDescription(t('A URL to go on email confirmation error.'))
->setSetting('max_length', 255);
$fields['uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Authored by'))
->setDescription(t('The user ID who created the email confirmation.'))
->setSetting('target_type', 'user')
->setSetting('handler', 'default')
->setDefaultValueCallback('Drupal\email_confirmer\Entity\EmailConfirmation::getCurrentUserId')
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'author',
'weight' => 0,
])
->setDisplayConfigurable('view', TRUE);
$fields['private'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Private'))
->setDescription(t('A boolean indicating whether the email confirmation is private.'))
->setDefaultValue(EmailConfirmationInterface::IS_PUBLIC)
->setDisplayOptions('view', [
'type' => 'string',
'weight' => 0,
]);
$fields['status'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Cancelled'))
->setDescription(t('A boolean indicating whether the email confirmation is cancelled.'))
->setDefaultValue(EmailConfirmationInterface::ACTIVE)
->setDisplayOptions('view', [
'type' => 'string',
'weight' => 0,
]);
$fields['sent'] = BaseFieldDefinition::create('timestamp')
->setLabel(t('Last request sent on'))
->setDescription(t('The time the last request was sent.'))
->setDisplayOptions('view', [
'type' => 'timestamp',
'weight' => 0,
]);
$fields['confirmed'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Confirmed'))
->setDescription(t('A boolean indicating whether the email confirmation is confirmed.'))
->setDefaultValue(EmailConfirmationInterface::UNCONFIRMED)
->setDisplayOptions('view', [
'type' => 'string',
'weight' => 0,
]);
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Added on'))
->setDefaultValueCallback('Drupal\email_confirmer\Entity\EmailConfirmation::getRequestTime')
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'timestamp',
'weight' => 0,
]);
return $fields;
}
/**
* {@inheritdoc}
*/
public function isPending() {
return !$this->isExpired()
&& !$this->isCancelled()
&& !$this->isConfirmed();
}
/**
* {@inheritdoc}
*/
public function isCancelled() {
return $this->get('status')->value == EmailConfirmationInterface::CANCELLED;
}
/**
* {@inheritdoc}
*/
public function isConfirmed() {
return $this->get('confirmed')->value == EmailConfirmationInterface::CONFIRMED;
}
/**
* {@inheritdoc}
*/
public function isExpired() {
return \Drupal::time()->getRequestTime() > $this->getCreatedTime() + \Drupal::config('email_confirmer.settings')->get('hash_expiration');
}
/**
* {@inheritdoc}
*/
public function isRequestSent() {
return !$this->get('sent')->isEmpty();
}
/**
* {@inheritdoc}
*/
public function isPrivate() {
return $this->get('private')->value == EmailConfirmationInterface::IS_PRIVATE;
}
/**
* {@inheritdoc}
*/
public function setPrivate($private = TRUE) {
$this->get('private')->setValue($private ? EmailConfirmationInterface::IS_PRIVATE : EmailConfirmationInterface::IS_PUBLIC);
return $this;
}
/**
* {@inheritdoc}
*/
public function getStatus() {
if ($this->isExpired()) {
$status = 'expired';
}
elseif ($this->isCancelled()) {
$status = 'cancelled';
}
elseif ($this->isConfirmed()) {
$status = 'confirmed';
}
else {
$status = 'pending';
}
return $status;
}
/**
* {@inheritdoc}
*/
public function sendRequest() {
$status = $this->getStatus();
if ($status != 'pending') {
throw new InvalidConfirmationStateException('Unable to send request email for ' . $status . ' confirmations.');
}
// Recently sent?
if ($this->isRequestSent()
&& $this->getLastRequestDate() + intval(\Drupal::config('email_confirmer.settings')->get('resendrequest_delay')) > \Drupal::time()->getRequestTime()) {
// Add to queue for further processing.
\Drupal::queue('email_confirmer_requests')->createItem($this->id());
return TRUE;
}
// Send the confirmation request.
$message = \Drupal::service('plugin.manager.mail')->mail('email_confirmer',
'confirmation_request',
$this->getEmail(),
$this->language()->getId(),
['context' => ['email_confirmer_confirmation' => $this]]);
if ($ok = !empty($message['result'])) {
$this->setLastRequestDate(\Drupal::time()->getRequestTime());
}
return $ok;
}
/**
* {@inheritdoc}
*/
public function confirm($hash) {
$status = $this->getStatus();
if ($status != 'pending') {
throw new InvalidConfirmationStateException('Unable to confirm ' . $status . ' confirmations.');
}
if ($hash == $this->getHash()) {
$this->get('confirmed')->setValue(EmailConfirmationInterface::CONFIRMED);
// Invoke email_confirmer hook.
\Drupal::moduleHandler()->invokeAll('email_confirmer', ['confirm', $this]);
return TRUE;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function cancel() {
$status = $this->getStatus();
if ($status != 'pending') {
throw new InvalidConfirmationStateException('Unable to cancel ' . $status . ' confirmations.');
}
$this->get('status')->setValue(EmailConfirmationInterface::CANCELLED);
// Invoke email_confirmer hook.
\Drupal::moduleHandler()->invokeAll('email_confirmer', ['cancel', $this]);
}
/**
* {@inheritdoc}
*/
public function getHash() {
$data = $this->getEmail()
. $this->getCreatedTime()
. $this->getIp() ?: '';
return Crypt::hmacBase64($data, \Drupal::service('private_key')->get());
}
/**
* {@inheritdoc}
*/
public function getEmail() {
return $this->get('email')->getString();
}
/**
* {@inheritdoc}
*/
public function setEmail($email) {
$this->get('email')->setValue($email);
return $this;
}
/**
* {@inheritdoc}
*/
public function getRealm() {
return $this->get('realm')->getString();
}
/**
* {@inheritdoc}
*/
public function setRealm($realm) {
$this->get('realm')->setValue($realm);
return $this;
}
/**
* {@inheritdoc}
*/
public function getIp() {
return $this->get('ip')->isEmpty() ? FALSE : $this->get('ip')->getString();
}
/**
* {@inheritdoc}
*/
public function setIp($ip) {
if (ip2long($ip) === FALSE) {
throw new \InvalidArgumentException($ip . ' is not a valid IP address.');
}
$this->get('ip')->setValue($ip);
return $this;
}
/**
* {@inheritdoc}
*/
public function getProperty($key = NULL) {
$data_field = $this->get('data');
$values = $data_field->isEmpty() ? [] : $data_field->first()->toArray();
if ($key) {
return isset($values[$key]) ? $values[$key] : NULL;
}
return $values;
}
/**
* {@inheritdoc}
*/
public function setProperty($key, $value = NULL) {
$item = $this->get('data')->isEmpty() ? $this->get('data')->appendItem() : $this->get('data')->first();
$map = $item->getValue();
if ($value === NULL && isset($map[$key])) {
unset($map[$key]);
}
else {
$map[$key] = $value;
}
$item->setValue($map);
return $this;
}
/**
* {@inheritdoc}
*/
public function getProperties() {
$map = [];
if (!$this->get('data')->isEmpty()) {
$map = $this->get('data')->first()->getValue();
}
return $map;
}
/**
* {@inheritdoc}
*/
public function getLastRequestDate() {
return $this->get('sent')->isEmpty() ? FALSE : intval($this->get('sent')->getString());
}
/**
* {@inheritdoc}
*/
public function setLastRequestDate($timestamp) {
$this->get('sent')->setValue($timestamp);
return $this;
}
/**
* {@inheritdoc}
*/
public function getCreatedTime() {
return $this->get('created')->value;
}
/**
* {@inheritdoc}
*/
public function setCreatedTime($timestamp) {
$this->get('created')->setValue($timestamp);
return $this;
}
/**
* Default value callback for 'uid' base field definition.
*
* @see ::baseFieldDefinitions()
*
* @return array
* An array of default values.
*/
public static function getCurrentUserId() {
return [\Drupal::currentUser()->id()];
}
/**
* Default value callback for 'ip' base field definition.
*
* @see ::baseFieldDefinitions()
*
* @return array
* An array of default values.
*/
public static function getRequestIp() {
return [\Drupal::request()->getClientIp()];
}
/**
* Default value callback for 'created' base field definition.
*
* @see ::baseFieldDefinitions()
*
* @return array
* An array of default values.
*/
public static function getRequestTime() {
return [\Drupal::time()->getRequestTime()];
}
/**
* {@inheritdoc}
*/
public function setResponseUrl(Url $url, $operation = NULL) {
$operations = $operation ? [$operation] : ['confirm', 'cancel', 'error'];
foreach ($operations as $operation) {
$this->get($operation . '_url')->setValue($url->toUriString());
}
return $this;
}
/**
* {@inheritdoc}
*/
public function getResponseUrl($operation) {
$uri = $this->get($operation . '_url')->getString();
return $uri ? Url::fromUri($uri) : NULL;
}
}
