social_event_invite_flow-1.0.0-beta3/src/Service/EventInviteFlowService.php
src/Service/EventInviteFlowService.php
<?php
namespace Drupal\social_event_invite_flow\Service;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\node\NodeInterface;
use Drupal\user\UserInterface;
use Drupal\Component\Utility\Crypt;
use Drupal\social_event_invite_flow\EventInviteSettingsInterface;
use Drupal\social_event_invite_flow\EventInviteMessageInterface;
use Drupal\social_event\EventEnrollmentInterface;
use Drupal\Core\Mail\MailManagerInterface;
use Drupal\Component\Utility\EmailValidatorInterface;
use Drupal\Core\Utility\Token;
use Drupal\Component\Render\PlainTextOutput;
use Drupal\Core\Render\Markup;
use Drupal\Core\Url;
use Drupal\Core\Link;
use Drupal\webform\WebformInterface;
use Drupal\social_event_invite_flow\EventInviteFlowLogInterface;
/**
* Service description.
*/
class EventInviteFlowService {
use StringTranslationTrait;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The current route match.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $account;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
/**
* The mail manager.
*
* @var \Drupal\Core\Mail\MailManagerInterface
*/
protected $mailManager;
/**
* The Email validator service.
*
* @var \Drupal\Component\Utility\EmailValidatorInterface
*/
protected $emailValidator;
/**
* The Token service.
*
* @var \Drupal\Core\Utility\Token
*/
protected $token;
/**
* Constructs a Common object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
*/
public function __construct(
EntityTypeManagerInterface $entity_type_manager,
ConfigFactoryInterface $config_factory,
RouteMatchInterface $route_match,
AccountInterface $account,
LanguageManagerInterface $language_manager,
MailManagerInterface $mail_manager,
EmailValidatorInterface $email_validator,
Token $token) {
$this->entityTypeManager = $entity_type_manager;
$this->configFactory = $config_factory;
$this->routeMatch = $route_match;
$this->account = $account;
$this->languageManager = $language_manager;
$this->mailManager = $mail_manager;
$this->emailValidator = $email_validator;
$this->token = $token;
}
/**
* Gets the default invite messages
*
* @return array
* An array of configuration object names.
*/
public function getEventInviteMessagesDefault() {
return $this->configFactory->get('social_event_invite_flow.settings');
}
public function getEventInviteDefaultMessages() {
$defaults = FALSE;
$config = $this->configFactory->get('social_event_invite_flow.settings');
if ($config) {
$defaults = [
'reply_to' => $config->get('reply_to'),
'guests_invite_subject' => $config->get('guests_invite_subject'),
'guests_invite_message' => ['value' => $config->get('guests_invite_message')],
'new_accounts_invite_subject' => $config->get('new_accounts_invite_subject'),
'new_accounts_invite_message' => ['value' => $config->get('new_accounts_invite_message')],
'existing_accounts_invite_subject' => $config->get('existing_accounts_invite_subject'),
'existing_accounts_invite_message' => ['value' => $config->get('existing_accounts_invite_message')],
];
}
return $defaults;
}
public function getEventInviteSettings(int $nid) {
$entity = FALSE;
$node = $this->entityTypeManager->getStorage('node')->load($nid);
$storage = $this->entityTypeManager->getStorage('event_invite_settings');
$event_invite_settings = $storage->loadByProperties(['node' => $node->id()]);
if ($event_invite_setting = reset($event_invite_settings)) {
$entity = $event_invite_setting;
}
return $entity;
}
public function isInviteFlowSettingsPresent() {
$present = FALSE;
$config = $this->configFactory->get('social_event_invite_flow.settings');
$invite_mode_existing_accounts = $config->get('invite_mode_existing_accounts');
$invite_mode_new_accounts = $config->get('invite_mode_new_accounts');
$webforms_existing_accounts = $config->get('webforms_existing_accounts');
$webforms_new_accounts = $config->get('webforms_new_accounts');
if (isset($invite_mode_existing_accounts) &&
isset($invite_mode_new_accounts) &&
isset($webforms_existing_accounts) &&
isset($webforms_new_accounts)
) {
$present = TRUE;
}
return $present;
}
public function getInviteSettingsDefaultData() {
$data = [];
$config = $this->configFactory->get('social_event_invite_flow.settings');
/** @var \Drupal\node\Entity\Node $node */
$node = $this->routeMatch->getParameter('node');
if (isset($node) && !$node instanceof NodeInterface) {
$storage = $this->entityTypeManager->getStorage('node');
$node = $storage->loadByProperties(['node' => $node]);
}
// Per default we need to have our config data available.
$data = [
'invite_mode_existing_accounts' => $config->get('invite_mode_existing_accounts'),
'invite_mode_new_accounts' => $config->get('invite_mode_new_accounts'),
'selected_webform_existing_accounts' => '',
'selected_webform_new_accounts' => ''
];
if ($node instanceof NodeInterface) {
$storage = $this->entityTypeManager->getStorage('event_invite_settings');
$event_invite_settings = $storage->loadByProperties(['node' => $node->id()]);
if ($event_invite_setting = reset($event_invite_settings)) {
$invite_mode_existing_accounts = $event_invite_setting->getInviteModeExistingAccounts();
$invite_mode_new_accounts = $event_invite_setting->getInviteModeNewAccounts();
$selected_webform_existing_accounts = $event_invite_setting->getSelectedWebformExistingAccounts();
$selected_webform_new_accounts = $event_invite_setting->getSelectedWebformNewAccounts();
$enable_shareable_link = $event_invite_setting->getEnableShareableLink();
if (isset($invite_mode_existing_accounts)) {
$data['invite_mode_existing_accounts'] = $invite_mode_existing_accounts;
}
if (isset($selected_webform_existing_accounts)) {
$data['selected_webform_existing_accounts'] = $selected_webform_existing_accounts;
}
if (isset($invite_mode_new_accounts)) {
$data['invite_mode_new_accounts'] = $invite_mode_new_accounts;
}
if (isset($selected_webform_new_accounts)) {
$data['selected_webform_new_accounts'] = $selected_webform_new_accounts;
}
if (isset($enable_shareable_link)) {
$data['enable_shareable_link'] = $enable_shareable_link;
}
}
}
return $data;
}
public function saveEventInviteSettings($node, $fields = NULL) {
if (!$node instanceof NodeInterface) {
$storage = $this->entityTypeManager->getStorage('node');
$node = $storage->loadByProperties(['node' => $node]);
}
$storage = $this->entityTypeManager->getStorage('event_invite_settings');
$event_invite_settings = $storage->loadByProperties(['node' => $node->id()]);
if ($event_invite_setting = reset($event_invite_settings)) {
if (isset($fields)) {
if (isset($fields['invite_mode_existing_accounts'])) {
$event_invite_setting->setInviteModeExistingAccounts($fields['invite_mode_existing_accounts']);
}
if (isset($fields['invite_mode_new_accounts'])) {
$event_invite_setting->setInviteModeNewAccounts($fields['invite_mode_new_accounts']);
}
if (isset($fields['selected_webform_existing_accounts'])) {
$event_invite_setting->setSelectedWebformExistingAccounts($fields['selected_webform_existing_accounts']);
}
if (isset($fields['selected_webform_new_accounts'])) {
$event_invite_setting->setSelectedWebformNewAccounts($fields['selected_webform_new_accounts']);
}
if (isset($fields['enable_shareable_link'])) {
$event_invite_setting->setEnableShareableLink($fields['enable_shareable_link']);
}
}
$event_invite_setting->save();
}
else {
// When creating new entity, we need to add the
// id field, access token and node field, which are only needed
// when creating new entities.
$fields['id'] = $node->bundle() . '_' . $node->uuid();
$fields['access_token'] = $this->generateAccessToken();
$fields['node'] = $node->id();
$new_entity = $storage->create($fields);
$new_entity->save();
}
}
protected function getInviteMessagesData() {
$data = [];
$config = $this->configFactory->get('social_event_invite_flow.settings');
/** @var \Drupal\node\Entity\Node $node */
$node = $this->routeMatch->getParameter('node');
if (isset($node) && !$node instanceof NodeInterface) {
$storage = $this->entityTypeManager->getStorage('node');
$node = $storage->loadByProperties(['node' => $node]);
}
if ($node instanceof NodeInterface) {
$storage = $this->entityTypeManager->getStorage('event_invite_message');
$event_invite_messages = $storage->loadByProperties(['node' => $node->id()]);
if ($event_invite_message = reset($event_invite_messages)) {
$data = [
'guests_invite_subject' => $event_invite_message->getGuestsInviteSubject(),
'guests_invite_message' => $event_invite_message->getGuestsInviteMessage(),
'new_accounts_invite_subject' => $event_invite_message->getNewAccountsInviteSubject(),
'new_accounts_invite_message' => $event_invite_message->getNewAccountsInviteMessage(),
'existing_accounts_invite_subject' => $event_invite_message->getExistingAccountsInviteSubject(),
'existing_accounts_invite_message' => $event_invite_message->getExistingAccountsInviteMessage(),
];
}
else {
$data = [
'guests_invite_subject' => $config->get('guests_invite_subject'),
'guests_invite_message' => $config->get('guests_invite_message'),
'new_accounts_invite_subject' => $config->get('new_accounts_invite_subject'),
'new_accounts_invite_message' => $config->get('new_accounts_invite_message'),
'existing_accounts_invite_subject' => $config->get('existing_accounts_invite_subject'),
'existing_accounts_invite_message' => $config->get('existing_accounts_invite_message'),
];
}
}
return $data;
}
public function getEventInviteMessageFormElements() {
$elements = [
'guests_invite_subject' => [
'type' => 'textfield',
'title' => $this->t('Subject for guests'),
'required' => TRUE,
'default_value' => $this->getInviteMessagesData()['guests_invite_subject']
],
'guests_invite_message' => [
'type' => 'text_format',
'title' => $this->t('Message for guests'),
'required' => TRUE,
'default_value' => $this->getInviteMessagesData()['guests_invite_message']
],
'new_accounts_invite_subject' => [
'type' => 'textfield',
'title' => $this->t('Subject for new accounts'),
'required' => TRUE,
'default_value' => $this->getInviteMessagesData()['new_accounts_invite_subject']
],
'new_accounts_invite_message' => [
'type' => 'text_format',
'title' => $this->t('Message for new accounts'),
'required' => TRUE,
'default_value' => $this->getInviteMessagesData()['new_accounts_invite_message']
],
'existing_accounts_invite_subject' => [
'type' => 'textfield',
'title' => $this->t('Subject for existing accounts'),
'required' => TRUE,
'default_value' => $this->getInviteMessagesData()['existing_accounts_invite_subject']
],
'existing_accounts_invite_message' => [
'type' => 'text_format',
'title' => $this->t('Message for existing accounts'),
'required' => TRUE,
'default_value' => $this->getInviteMessagesData()['existing_accounts_invite_message']
],
];
return $elements;
}
/**
* Gets an event invite message based on
* the given route.
*/
public function getEventInviteMessages() {
$entity = FALSE;
/** @var \Drupal\node\Entity\Node $node */
$node = $this->routeMatch->getParameter('node');
if (isset($node) && !$node instanceof NodeInterface) {
$node = $this->entityTypeManager->getStorage('node')->load($node);
}
if ($node instanceof NodeInterface) {
$storage = $this->entityTypeManager->getStorage('event_invite_message');
$event_invite_messages = $storage->loadByProperties(['node' => $node->id()]);
if ($event_invite_message = reset($event_invite_messages)) {
$entity = $event_invite_message;
}
}
return $entity;
}
public function createEventInviteMessages(array $fields) {
$entity = FALSE;
$storage = $this->entityTypeManager->getStorage('event_invite_message');
$storage->create($fields);
$entity = $storage->save();
return $entity;
}
public function getAllWebforms() {
$webforms = [];
// Get webforms
$webform_ids = \Drupal::entityQuery('webform')
->accessCheck(TRUE)
->execute();
/** @var \Drupal\webform\Entity\Webform $webform */
foreach ($webform_ids as $webform) {
$storage = $this->entityTypeManager->getStorage('webform');
$loaded_webform = $storage->load($webform);
if ($loaded_webform instanceof WebformInterface) {
$webform_machine_name = $loaded_webform->id();
$webform_label = $loaded_webform->label();
$webforms[$webform_machine_name] = $webform_label;
}
}
return $webforms;
}
public function getWebformsExistingAccountsOptions() {
$webforms = [];
$social_event_invite_flow = $this->configFactory->get('social_event_invite_flow.settings');
$webform_ids = $social_event_invite_flow->get('webforms_existing_accounts');
/** @var \Drupal\webform\Entity\Webform $webform */
foreach ($webform_ids as $webform) {
$storage = $this->entityTypeManager->getStorage('webform');
$loaded_webform = $storage->load($webform);
if ($loaded_webform instanceof WebformInterface) {
$webform_machine_name = $loaded_webform->id();
$webform_label = $loaded_webform->label();
$webforms[$webform_machine_name] = $webform_label;
}
}
return $webforms;
}
public function getWebformsNewAccountsOptions() {
$webforms = [];
$social_event_invite_flow = $this->configFactory->get('social_event_invite_flow.settings');
$webform_ids = $social_event_invite_flow->get('webforms_new_accounts');
/** @var \Drupal\webform\Entity\Webform $webform */
foreach ($webform_ids as $webform) {
$storage = $this->entityTypeManager->getStorage('webform');
$loaded_webform = $storage->load($webform);
if ($loaded_webform instanceof WebformInterface) {
$webform_machine_name = $loaded_webform->id();
$webform_label = $loaded_webform->label();
$webforms[$webform_machine_name] = $webform_label;
}
}
return $webforms;
}
public function getAvailableFields() {
$node_field_definitions = [];
$available_fields = [];
$node_bundles = [];
$profile_bundles = [];
$user_bundles = ['user'];
$forbidden_node_fields = [
'type',
'field_group_allowed_join_method',
'field_group_allowed_visibility'
];
$forbidden_profile_fields = [
'type'
];
$forbidden_user_fields = [
'init',
'name'
];
$default_tokens = [
'[node:title]' => '[node:title]',
'[current-user:display-name]' => '[current-user:display-name]',
'[user:display-name]' => '[user:display-name]',
'[site:name]' => '[site:name]'
];
$available_node_fields = $this->getFields('node', ['event'], $forbidden_node_fields);
// Get profile bundles
$profile_bundles = $this->getBundle('profile');
// Default Tokens for user profiles
$default_tokens_user_profile = $this->getUserProfileBundleTokens($profile_bundles);
if (isset($profile_bundles) && !empty($profile_bundles)) {
$available_profile_fields = $this->getFields('profile',$profile_bundles,$forbidden_profile_fields);
}
$available_user_fields = $this->getFields('user',$user_bundles,$forbidden_user_fields);
$available_fields = array_merge($default_tokens,
$default_tokens_user_profile,
$available_node_fields,
$available_profile_fields,
$available_user_fields);
// Get user field definitions
return $available_fields;
}
protected function getUserProfileBundleTokens($profile_bundles) {
$token_fields = [];
foreach ($profile_bundles as $bundle_key => $bundle) {
$token_fields['[user:' . $bundle_key .']'] = '[user:' . $bundle_key . ']';
}
return $token_fields;
}
protected function getFields(string $entity_type, array $bundles, array $forbidden_fields) {
$field_definitions = [];
$available_fields = [];
foreach ($bundles as $bundle_key => $bundle) {
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($entity_type, $bundle_key);
foreach ($field_definitions as $field_key => $field_value) {
$field_token_key = strtolower($field_definitions[$field_key]->getName());
$field_token_key = str_replace(' ','_',$field_token_key);
if ($field_definitions[$field_key]->isRequired() && !in_array($field_key, $forbidden_fields)) {
if ($entity_type == 'profile') {
$available_fields['[user:' . $bundle_key . ':' . $field_token_key . ']'] = '[user:' . $bundle_key . ':' . $field_token_key . ']';
}
$available_fields['[' . $entity_type . ':' . $field_token_key . ']'] = '[' . $entity_type . ':' . $field_token_key . ']';
}
}
}
return $available_fields;
}
protected function getBundle($entity_type) {
$bundles = \Drupal::service('entity_type.bundle.info')->getBundleInfo($entity_type);
return $bundles;
}
public function getInviteModeExistingAccountsOptions() {
return [
EventInviteSettingsInterface::InviteModeExistingAccountsDefaultEnrollment => $this->t('Default Enrollment'),
EventInviteSettingsInterface::InviteModeExistingAccountsWebformEnrollment => $this->t('Webform Enrollment')
];
}
public function getInviteModeNewAccountsOptions() {
return [
EventInviteSettingsInterface::InviteModeNewAccountsGuestEnrollment => $this->t('Guest Enrollment'),
EventInviteSettingsInterface::InviteModeNewAccountsWebformEnrollment => $this->t('Webform Enrollment')
];
}
public function generateAccessToken() {
$access_token = Crypt::randomBytesBase64();
return $access_token;
}
protected function enrollmentExists($user, $nid) {
$enrollment_exists = FALSE;
$conditions = [
'field_account' => $user->id(),
'field_event' => $nid,
];
$storage = $this->entityTypeManager->getStorage('event_enrollment');
$event_enrollment = $storage->loadByProperties($conditions);
if (!empty($event_enrollment)) {
$enrollment_exists = TRUE;
}
return $enrollment_exists;
}
public function enrollmentExistsBySID($sid, $nid) {
$enrollment = FALSE;
$conditions = [
'field_token' => $sid,
'field_event' => $nid,
];
$storage = $this->entityTypeManager->getStorage('event_enrollment');
$event_enrollments = $storage->loadByProperties($conditions);
if ($event_enrollment = reset($event_enrollments)) {
$enrollment = $event_enrollment;
}
return $enrollment;
}
protected function enrollmentExistsByEmail($email, $nid) {
$enrollment_exists = FALSE;
$conditions = [
'field_email' => $email,
'field_event' => $nid,
];
$storage = $this->entityTypeManager->getStorage('event_enrollment');
$event_enrollment = $storage->loadByProperties($conditions);
if (!empty($event_enrollment)) {
$enrollment_exists = TRUE;
}
return $enrollment_exists;
}
public function enrollExistingAccount($user, $nid) {
$invite_flow = FALSE;
// First we need to know which flow we are using
$storage = $this->entityTypeManager->getStorage('event_invite_settings');
$event_invite_settings = $storage->loadByProperties(['node' => $nid]);
if ($event_invite_setting = reset($event_invite_settings)) {
$invite_flow = $event_invite_setting->getInviteModeExistingAccounts();
}
$event = $this->entityTypeManager->getStorage('node')->load($nid);
if ($invite_flow === EventInviteSettingsInterface::InviteModeExistingAccountsDefaultEnrollment) {
if (!$this->enrollmentExists($user, $nid)) {
$fields = [
//'name' => $user->getDisplayName() . ' @ ' . $event->getTitle(),
'field_event' => $nid,
'field_enrollment_status' => '1',
'user_id' => $user->id(),
'field_account' => $user->id(),
];
$storage = $this->entityTypeManager->getStorage('event_enrollment');
$new_enrollment = $storage->create($fields);
$new_enrollment->save();
$has_enrolled = $new_enrollment;
// Send emails for enrolled users only
if ($has_enrolled instanceof EventEnrollmentInterface) {
$this->sendInviteEmails(
EventInviteSettingsInterface::InviteModeExistingAccountsDefaultEnrollment,
$user,
$nid,
$has_enrolled
);
}
}
}
if ($invite_flow === EventInviteSettingsInterface::InviteModeExistingAccountsWebformEnrollment) {
// Here we just send out the emails the rest will be done
// by the webform.
$this->sendInviteEmails(
EventInviteSettingsInterface::InviteModeExistingAccountsWebformEnrollment,
$user,
$nid
);
}
}
public function enrollNewAccount($email, $nid) {
$invite_flow = FALSE;
$invite_access_token = FALSE;
$enable_shareable_link = FALSE;
$storage = $this->entityTypeManager->getStorage('event_invite_settings');
$event_invite_settings = $storage->loadByProperties(['node' => $nid]);
if ($event_invite_setting = reset($event_invite_settings)) {
$invite_flow = $event_invite_setting->getInviteModeNewAccounts();
$enable_shareable_link = $event_invite_setting->getEnableShareableLink();
$invite_access_token = $event_invite_setting->getAccessToken();
}
$event = $this->entityTypeManager->getStorage('node')->load($nid);
if ($invite_flow === EventInviteSettingsInterface::InviteModeNewAccountsGuestEnrollment) {
if ($enable_shareable_link) {
// Here we just send out the emails the rest will be done
// by the user himself (Auto enrollment).
$this->sendInviteEmails(
EventInviteSettingsInterface::InviteModeNewAccountsGuestEnrollment,
$email,
$nid
);
}
else {
// Here we need to enroll the user first
if(!$this->enrollmentExistsByEmail($email, $nid)) {
$storage = $this->entityTypeManager->getStorage('event_enrollment');
$generated_token = Crypt::randomBytesBase64();
$fields = [
//'name' => 'anonymous' . ' @ ' . $event->getTitle(),
'field_request_or_invite_status' => EventEnrollmentInterface::INVITE_PENDING_REPLY,
'field_event' => $nid,
'field_enrollment_status' => '0',
'field_email' => $email,
'field_token' => $generated_token,
'field_account' => 0,
'user_id' => 0
];
$new_enrollment = $storage->create($fields);
$new_enrollment->save();
$has_enrolled = $new_enrollment;
if ($has_enrolled instanceof EventEnrollmentInterface) {
$token = $has_enrolled->field_token->value;
}
}
else {
$existing_enrollments = $storage->loadByProperties([
'field_event' => $nid,
'field_email' => $email
]);
if ($has_enrolled = reset($existing_enrollments)) {
$token = $has_enrolled->field_token->value;
}
}
if ($token) {
$this->sendInviteEmails(
EventInviteSettingsInterface::InviteModeNewAccountsGuestEnrollment,
$email,
$nid,
$has_enrolled,
$token
);
}
}
}
if ($invite_flow === EventInviteSettingsInterface::InviteModeNewAccountsWebformEnrollment) {
$token = FALSE;
$storage = $this->entityTypeManager->getStorage('event_enrollment');
// Create guest enrollment and send emails with token
if(!$this->enrollmentExistsByEmail($email, $nid)) {
$generated_token = Crypt::randomBytesBase64();
$fields = [
//'name' => 'Anonymous' . ' @ ' . $event->getTitle(),
'field_event' => $nid,
'field_enrollment_status' => '0',
'field_email' => $email,
'field_token' => $generated_token,
'field_account' => 0,
'user_id' => 0
];
$new_enrollment = $storage->create($fields);
$new_enrollment->save();
$has_enrolled = $new_enrollment;
if ($has_enrolled instanceof EventEnrollmentInterface) {
$token = $has_enrolled->field_token->value;
}
}
else {
$existing_enrollments = $storage->loadByProperties([
'field_event' => $nid,
'field_token' => $token
]);
if ($has_enrolled = reset($existing_enrollments)) {
$token = $has_enrolled->field_token->value;
}
}
if ($token) {
$this->sendInviteEmails(
EventInviteSettingsInterface::InviteModeNewAccountsWebformEnrollment,
$email,
$nid,
$has_enrolled,
$token
);
}
}
}
public function convertEnrollRequestFormMessage(UserInterface $user, NodeInterface $node, $to_email, array $message) {
$email_sent = FALSE;
// Build token context
$token_context = [];
$token_context['node'] = $node;
$token_context['user'] = $user;
$langcode = $user->getPreferredLangcode();
$subject = PlainTextOutput::renderFromHtml($this->token->replace($message['subject'], $token_context));
$message = $this->token->replace($message['message'], $token_context);
$context = [
'subject' => $subject,
'message' => $message,
];
// Sending Email
$delivered = $this->mailManager->mail('system', 'action_send_email', $to_email, $langcode, ['context' => $context]);
if ($delivered) {
\Drupal::messenger()->addStatus($this->t('Message sent successfully!'));
}
}
public function sendInviteEmails(string $invite_flow, $attendee, int $nid, $event_enrollment = NULL, $token = FALSE ) {
$email_sent = FALSE;
// Get event invite message for specific invite flow
$event_invite_message = $this->getInviteMessageFromNid($nid, $invite_flow);
// Load the node
$node = $this->entityTypeManager->getStorage('node')->load($nid);
// Build token context
$token_context = [];
if ($node instanceof NodeInterface) {
$token_context['node'] = $node;
}
if ($attendee instanceof UserInterface) {
$user_mail = $attendee->getEmail();
$token_context['user'] = $this->account;
$langcode = $attendee->getPreferredLangcode();
}
else {
$token_context['user'] = $this->account;
$user_mail = $attendee;
$langcode = $this->languageManager->getCurrentLanguage()->getId();
}
// Get our event settings
$event_invite_setting = $this->getEventInviteSettings($nid);
// Shareable link or not
$enable_shareable_link = $event_invite_setting->getEnableShareableLink();
$log_data['shareable_link'] = $enable_shareable_link;
$log_data['invite_flow'] = $invite_flow;
$log_data['invitee_email'] = $user_mail;
$log_data['event'] = $node;
if ($event_enrollment instanceof EventEnrollmentInterface) {
$log_data['event_enrollment'] = $event_enrollment;
}
if (!$event_invite_message) {
return;
}
$subject = PlainTextOutput::renderFromHtml($this->token->replace($event_invite_message['subject'], $token_context));
$message = $this->token->replace($event_invite_message['message'], $token_context);
// As we have our action buttons pre-defined we attach it here
$action_links = [
'#theme' => 'social_event_invite_flow__actions',
'#links' => $this->getInviteActionsFromNid($nid, $invite_flow, $user_mail, $token),
];
$actions = \Drupal::service('renderer')->render($action_links);
$message = Markup::create($message);
// Attach actions to message
$message .= $message . $actions;
$reply_to = $event_invite_message['reply_to'];
$context = [
'subject' => $subject,
'message' => $message,
];
// Sending Email
$delivered = $this->mailManager->mail('system', 'action_send_email', $user_mail, $langcode, ['context' => $context], $reply_to);
if ($delivered) {
$email_sent = TRUE;
// Log
$this->createInviteFlowLogEntry('invitation_sent', $log_data);
}
return $email_sent;
}
protected function getInviteActionsFromNid(int $nid, string $invite_flow, string $email, $token = FALSE) {
$links = [];
// Get decoded invitee email
$invitee_email = $this->getEncodedEmailString($email);
// Get our event settings
$event_invite_setting = $this->getEventInviteSettings($nid);
// Shareable link or not
$enable_shareable_link = $event_invite_setting->getEnableShareableLink();
// First we need to get our token
$access_token = $event_invite_setting->getAccessToken();
// Define link attributes
$link_options = [
'absolute' => TRUE,
'attributes' => [
'class' => [
'btn-link', 'btn-link-bg', 'btn-link-one'
]
]
];
// Get the site name from config
$config = $this->configFactory->get('system.site');
$site_name = $config->get('name');
// Get site url
$site_url = Url::fromRoute('<front>');
$site_url->setOptions($link_options);
$site_link_title = $this->t('About') . ' ' . $site_name;
$site_link = Link::fromTextAndUrl($site_link_title, $site_url);
if ($invite_flow === EventInviteSettingsInterface::InviteModeExistingAccountsDefaultEnrollment) {
// Add link to event
if ($enable_shareable_link) {
// For shareable links we do not want any button styling
unset($link_options['attributes']['class']);
$link_options['query'] = [
'access_token' => $access_token,
//'invitee' => $invitee_email
];
}
$event_url = Url::fromRoute('social_event_invite_flow.event_guest_access', ['node' => $nid]);
$event_url->setOptions($link_options);
if ($enable_shareable_link) {
$event_link = Link::fromTextAndUrl($event_url->toString(), $event_url);
}
else {
$event_link = Link::fromTextAndUrl($this->t('See event'), $event_url);
}
$links['event'] = $event_link->toRenderable();
}
if ($invite_flow === EventInviteSettingsInterface::InviteModeNewAccountsGuestEnrollment) {
// Add link to event
$event_url = Url::fromRoute('social_event_invite_flow.event_guest_access', ['node' => $nid]);
if ($enable_shareable_link) {
// Attach the access token to the url
$link_options['query'] = [
'access_token' => $access_token,
//'invitee' => $invitee_email
];
}
else {
if (isset($token)) {
$link_options['query'] = [
'token' => $token,
'invitee' => $invitee_email
];
}
}
$event_url->setOptions($link_options);
$event_link = Link::fromTextAndUrl($this->t('See event'), $event_url);
$links['event'] = $event_link->toRenderable();
}
if ($invite_flow === EventInviteSettingsInterface::InviteModeExistingAccountsWebformEnrollment) {
// First we need to get the webfrom
$webform_id = $event_invite_setting->getSelectedWebformExistingAccounts();
// Add link to event
$event_url = Url::fromRoute('entity.webform.canonical', ['webform' => $webform_id]);
// Add query parameter event
$link_options['query'] = [
'event' => $nid,
'webform_redirect' => '/node/' . $nid . '/join',
];
$event_url->setOptions($link_options);
$event_link = Link::fromTextAndUrl($this->t('See event'), $event_url);
$links['event'] = $event_link->toRenderable();
}
if ($invite_flow === EventInviteSettingsInterface::InviteModeNewAccountsWebformEnrollment) {
// First we need to get the webfrom
$webform_id = $event_invite_setting->getSelectedWebformNewAccounts();
$event_url = Url::fromRoute('entity.webform.canonical', ['webform' => $webform_id]);
// Add query parameter webform_redirect
$link_options['query'] = [
'webform_redirect' => '/node/' . $nid,
'token' => $token
];
$event_url->setOptions($link_options);
$event_link = Link::fromTextAndUrl($this->t('See event'), $event_url);
$links['event'] = $event_link->toRenderable();
}
// Always add the site link
//$links['site'] = $site_link->toRenderable();
return $links;
}
public function getDecodedEmailString(string $invitee_email) {
return base64_decode(str_replace(['-', '_'], ['+', '/'], $invitee_email));
}
protected function getEncodedEmailString($email) {
$invitee_email = base64_encode($email);
return $invitee_email;
}
protected function getInviteMessageFromNid(int $nid, string $invite_flow) {
$config = $this->configFactory->get('social_event_invite_flow.settings');
$message_data = [];
$message_data['reply_to'] = NULL;
$storage = $this->entityTypeManager->getStorage('event_invite_message');
$event_invite_messages = $storage->loadByProperties(['node' => $nid]);
if ($entity = reset($event_invite_messages)) {
$event_invite_message = $entity;
$data = [
'reply_to' => $event_invite_message->getReplyTo(),
'guests_invite_subject' => $event_invite_message->getGuestsInviteSubject(),
'guests_invite_message' => $event_invite_message->getGuestsInviteMessage()['value'],
'new_accounts_invite_subject' => $event_invite_message->getNewAccountsInviteSubject(),
'new_accounts_invite_message' => $event_invite_message->getNewAccountsInviteMessage()['value'],
'existing_accounts_invite_subject' => $event_invite_message->getExistingAccountsInviteSubject(),
'existing_accounts_invite_message' => $event_invite_message->getExistingAccountsInviteMessage()['value'],
];
}
else {
$data = [
'reply_to' => $config->get('reply_to'),
'guests_invite_subject' => $config->get('guests_invite_subject'),
'guests_invite_message' => $config->get('guests_invite_message'),
'new_accounts_invite_subject' => $config->get('new_accounts_invite_subject'),
'new_accounts_invite_message' => $config->get('new_accounts_invite_message'),
'existing_accounts_invite_subject' => $config->get('existing_accounts_invite_subject'),
'existing_accounts_invite_message' => $config->get('existing_accounts_invite_message'),
];
}
// We need to check the invite_flow to get proper message
if ($invite_flow === EventInviteSettingsInterface::InviteModeExistingAccountsDefaultEnrollment ||
$invite_flow === EventInviteSettingsInterface::InviteModeExistingAccountsWebformEnrollment) {
$message_data['subject'] = $data['existing_accounts_invite_subject'];
$message_data['message'] = $data['existing_accounts_invite_message'];
}
elseif ($invite_flow === EventInviteSettingsInterface::InviteModeNewAccountsGuestEnrollment) {
$message_data['subject'] = $data['guests_invite_subject'];
$message_data['message'] = $data['guests_invite_message'];
}
elseif ($invite_flow === EventInviteSettingsInterface::InviteModeNewAccountsWebformEnrollment) {
$message_data['subject'] = $data['new_accounts_invite_subject'];
$message_data['message'] = $data['new_accounts_invite_message'];
}
if (empty($message_data)) {
return FALSE;
}
// Get Reply to email or use site mail
$reply_to = $data['reply_to'];
if (!empty($reply_to)) {
$message_data['reply_to'] = $reply_to;
}
return $message_data;
}
public function addFieldTokens(array &$form) {
$tokens = [
'node_title' => '[node:title]',
'current_user_display_name' => '[current-user:display-name]',
'user_display_name' => '[user:display-name]',
'site_name' => '[site:name]'
];
$form['tokens'] = [
'#type' => 'fieldset',
'#title' => $this->t('Available Tokens'),
'#collapsed' => TRUE,
'#collapsible' => TRUE
];
foreach($tokens as $key => $token) {
$key_value = "'" . $key . "'";
$link = '<a class="btn btn-sm btn-default" onclick="myFunction(' . $key_value . ')">Copy</a>';
$form['tokens'][$key]['container'] = [
'#type' => 'container',
'#attributes' => ['class' => ['invite--flow']],
];
$form['tokens'][$key]['container']['text'] = [
'#attributes' => ['id' => $key],
'#type' => 'textfield',
'#value' => $token,
];
$form['tokens'][$key]['container']['link'] = [
'#markup' => Markup::Create($link),
'#prefix' => '<div>',
'#suffix' => '</div>'
];
}
}
protected function getPseudoEmail() {
$sid = $this->getSessionIDForUnauthenticatedUsers();
$host = \Drupal::request()->getHost();
$email = $sid . '@' . $host;
return $email;
}
protected function getEventEnrollmentTitleFromEventNode($nid) {
$node = $this->entityTypeManager->getStorage('node')->load($nid);
$event_enrollment_name = 'Anonymous' . ' @ ' . $node->getTitle();
return $event_enrollment_name;
}
public function enrollGuestInEvent($nid, $name) {
$enrolled = FALSE;
$storage = $this->entityTypeManager->getStorage('event_enrollment');
// Get Session ID for anon. user
$sid = $this->getSessionIDForUnauthenticatedUsers();
// Get our pseudo email for anon. user
$email = $this->getPseudoEmail();
// Create enrollment
if(!$this->enrollmentExistsByEmail($email, $nid)) {
$fields = [
//'name' => $this->getEventEnrollmentTitleFromEventNode($nid),
'field_event' => $nid,
'field_enrollment_status' => '1',
'field_request_or_invite_status' => EventEnrollmentInterface::INVITE_ACCEPTED_AND_JOINED,
'field_email' => $email,
'field_first_name' => $name,
'field_token' => $this->generateAccessToken(),
'field_account' => 0,
//'user_id' => 0
];
$new_enrollment = $storage->create($fields);
$new_enrollment->save();
$enrolled = $new_enrollment;
}
return $enrolled;
}
public function enrollGuestInEventWithEmail($nid, $name, $email) {
$enrollment = FALSE;
$conditions = [
'field_email' => $email,
'field_event' => $nid,
];
$storage = $this->entityTypeManager->getStorage('event_enrollment');
$event_enrollments = $storage->loadByProperties($conditions);
if ($event_enrollment = reset($event_enrollments)) {
$enrollment = $event_enrollment;
}
// We are already enrolled and need to set the enrolled status
if ($enrollment) {
$enrollment->field_first_name->value = $name;
$enrollment->field_enrollment_status->value = 1;
$enrollment->field_request_or_invite_status->value = EventEnrollmentInterface::INVITE_ACCEPTED_AND_JOINED;
$enrollment->save();
}
return $enrollment;
}
public function validateEnrollAsGuestInEvent($email, $nid) {
}
/**
* Check if an authenticated user has enrolled
*
* @param integer $nid
* The node id.
*
* @return bool $enrolled
* TRUE | FALSE
*/
public function checkIfAuthenticatedUserHasEnrolled(int $nid) {
$enrolled = FALSE;
$user = $this->account;
$uid = $user->id();
$conditions = [
'field_account' => $uid,
'field_event' => $nid,
];
$storage = $this->entityTypeManager->getStorage('event_enrollment');
$event_enrollments = $storage->loadByProperties($conditions);
if ($event_enrollment = reset($event_enrollments)) {
$enrolled = TRUE;
}
return $enrolled;
}
/**
* Check if an un-authenticated user has enrolled
*
* @param integer $nid
* The node id.
*
* @return bool $enrolled
* TRUE | FALSE
*/
public function checkIfUnauthenticatedUserHasEnrolled(int $nid, $email) {
$enrolled = FALSE;
$conditions = [
'field_email' => $email,
'field_event' => $nid,
];
$storage = $this->entityTypeManager->getStorage('event_enrollment');
$event_enrollments = $storage->loadByProperties($conditions);
if ($event_enrollment = reset($event_enrollments)) {
$enrolled = TRUE;
}
return $enrolled;
}
/**
* Check if the enetered email belongs to an authenticated user
*
* @param integer $nid
* The node id.
*
* @return bool $enrolled
* TRUE | FALSE
*/
public function checkIfEmailHasAccount($email) {
$user = user_load_by_mail($email);
return $user;
}
public function isEventShareable(int $nid) {
$enable_shareable_link = FALSE;
// First we need to know which flow we are using
$storage = $this->entityTypeManager->getStorage('event_invite_settings');
$event_invite_settings = $storage->loadByProperties(['node' => $nid]);
if ($event_invite_setting = reset($event_invite_settings)) {
$enable_shareable_link = $event_invite_setting->getEnableShareableLink();
}
return $enable_shareable_link;
}
/**
* Creates and returns a unique identifier for unauthenticated users.
*
* @return string $session_key
* Unique session key.
*/
public function getSessionIDForUnauthenticatedUsers() {
// Define session.
$session = \Drupal::request()->getSession();
// Check if we have already an unique identifier saved into session
if (!$session->has('core.tempstore.private.owner')) {
// This generates a unique identifier for the user
$session->set('core.tempstore.private.owner', Crypt::randomBytesBase64());
}
$session_key = $session->get('core.tempstore.private.owner');
return $session_key;
}
public function isHideEnrollButtonPossible() {
$hide = FALSE;
$current_user = $this->account;
if ($current_user->isAnonymous()) {
$hide = TRUE;
}
else {
$user_roles = $current_user->getRoles();
foreach ($user_roles as $role) {
if ($role === 'administrator' ||
$role === 'contentmanager' ||
$role === 'sitemanager') {
$hide = FALSE;
}
else {
$hide = TRUE;
}
}
}
return $hide;
}
public function enrollmentExistsByToken($token, $nid) {
$enrollment = FALSE;
$conditions = [
'field_token' => $token,
'field_event' => $nid,
];
$storage = $this->entityTypeManager->getStorage('event_enrollment');
$event_enrollments = $storage->loadByProperties($conditions);
if ($event_enrollment = reset($event_enrollments)) {
if ($event_enrollment instanceof EventEnrollmentInterface) {
if ($event_enrollment->field_enrollment_status->value == 1) {
$enrollment = $event_enrollment;
}
}
}
return $enrollment;
}
/**
* Get an account from uid
*
* @param integer $uid
* @return UserInterface or FALSE
*/
public function getAccountFromUserId(int $uid) {
$account = $this->entityTypeManager->getStorage('user')->load($uid);
return $account;
}
/**
* Create Invite Flow Log
*
* @param [type] $invite_flow
* @param [type] $invitee_email
* @param [type] $event
* @param boolean $invitee_joined
* @param boolean $shareable_link
* @param [type] $event_enrollment
* @return void
*/
public function createInviteFlowLogEntry($action, array $data) {
$current_time = \Drupal::time()->getCurrentTime();
if ($data['event'] instanceof NodeInterface) {
$event_id = $data['event']->id();
}
else {
$event_id = $data['event'];
}
$conditions = [
'invitee_email' => $data['invitee_email'],
'event' => $event_id,
];
$storage = $this->entityTypeManager->getStorage('event_invite_flow_log');
$event_invite_flow_logs = $storage->loadByProperties($conditions);
if ($event_invite_flow_log = reset($event_invite_flow_logs)) {
if ($event_invite_flow_log instanceof EventInviteFlowLogInterface) {
$event_invite_flow_log->setInviteFlow($data['invite_flow']);
$event_invite_flow_log->setShareableLink($data['shareable_link']);
$event_invite_flow_log->setInviteeEmail($data['invitee_email']);
$event_invite_flow_log->setEvent($data['event']);
// Log when the message has been sent out.
if ($action === 'invitation_sent') {
$event_invite_flow_log->setInvitationSent($current_time);
$event_invite_flow_log->setHasInvitationSent(TRUE);
}
// If there is an event enrollment put it into the log
if ($data['event_enrollment'] instanceof EventEnrollmentInterface) {
$event_invite_flow_log->setEventEnrollment($data['event_enrollment']);
$event_invite_flow_log->setInviteeEnrolled($current_time);
$event_invite_flow_log->setHasInviteeEnrolled(TRUE);
}
// If the invitee has joined
if ($action === 'joined') {
$event_invite_flow_log->setInviteeJoined($current_time);
$event_invite_flow_log->setHasInviteeJoined(TRUE);
}
$event_invite_flow_log->save();
}
}
else {
if ($action === 'invitation_sent') {
$data['invitation_sent'] = $current_time;
$data['has_invitation_sent'] = TRUE;
}
// If there is an event enrollment put it into the log
if ($data['event_enrollment'] instanceof EventEnrollmentInterface) {
$data['event_enrollment'] = $data['event_enrollment']->id();
$data['invitee_enrolled'] = $current_time;
$data['has_invitee_enrolled'] = TRUE;
}
// If the invitee has joined
if ($action === 'joined') {
$data['invitee_joined'] = $current_time;
$data['has_invitee_joined'] = TRUE;
}
// Create new log entry
$new_event_invite_log = $storage->create($data);
$new_event_invite_log->save();
}
}
public function deleteInviteLogRecord($conditions) {
$storage = $this->entityTypeManager->getStorage('event_invite_flow_log');
$event_invite_flow_logs = $storage->loadByProperties($conditions);
if ($event_invite_flow_log = reset($event_invite_flow_logs)) {
if ($event_invite_flow_log instanceof EventInviteFlowLogInterface) {
\Drupal::logger('debug')->debug('Delete!!!');
$event_invite_flow_log->delete();
}
}
}
}
