diff --git a/admin_content_notification.module b/admin_content_notification.module index 1f2cbef..d6174c7 100644 --- a/admin_content_notification.module +++ b/admin_content_notification.module @@ -39,13 +39,24 @@ function admin_content_notification_node_update(EntityInterface $node) { } } +/** + * Implements hook_node_delete(). + */ +function admin_content_notification_node_delete(EntityInterface $node) { + if (!empty(\Drupal::config('admin_content_notification.settings')->get('admin_content_notification_trigger_on_node_delete')) && \Drupal::service('admin_content_notification.common')->isCurrentUserRoleAllowedToSendNotification()) { + \Drupal::service('admin_content_notification.common')->sendMail($node, FALSE, TRUE); + } +} + /** * Implements hook_mail(). */ function admin_content_notification_mail($key, &$message, $params) { switch ($key) { case 'admin_content_notification_key': - $message['headers']['bcc'] = $params['bcc']; + if (isset($params['bcc'])) { + $message['headers']['bcc'] = $params['bcc']; + } $message['subject'] = $params['subject']; $message['body'][] = $params['body']; break; diff --git a/src/AdminContentNotificationService.php b/src/AdminContentNotificationService.php index 3b6cf62..a1b8689 100644 --- a/src/AdminContentNotificationService.php +++ b/src/AdminContentNotificationService.php @@ -13,6 +13,8 @@ use Drupal\Core\Utility\LinkGeneratorInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Logger\LoggerChannelTrait; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Link; +use Drupal\Core\Render\Markup; /** * AdminContentNotificationService implement helper service class. @@ -112,8 +114,9 @@ class AdminContentNotificationService { * * @param Drupal\node\NodeInterface $node * @param bool $is_new + * @param bool $is_deleted */ - public function sendMail(NodeInterface $node, $is_new = FALSE) { + public function sendMail(NodeInterface $node, $is_new = FALSE, $is_deleted = FALSE) { global $base_url; $config = $this->getConfigs(); $node_type = $node->getType(); @@ -138,12 +141,21 @@ class AdminContentNotificationService { $user_name = $user->getDisplayName(); $url = Url::fromUri($base_url . '/node/' . $node->id()); $internal_link = $this->linkGenerator->generate($this->t('@title', ['@title' => $node->label()]), $url); + $diff = $this->getDiff($node); + $editor_user = $node->getRevisionUser(); + $editor_user_name = $editor_user->getDisplayName(); $variables = [ '@user_who_posted' => $user_name, + '@user_who_edited' => $editor_user_name, '@content_link' => $internal_link, '@content_title' => $node->label(), '@content_type' => $node_type_label, '@action' => $is_new ? $this->t('posted') : $this->t('updated'), + // Source: https://www.drupal.org/project/admin_content_notification/issues/3078319#comment-13241651 + '@action' => $is_deleted ? 'törlés történt' : ($is_new ? 'jött létre' : 'módosult'), + // Case: https://atrium.macroweb.hu/oktav/node/26861#comment-133956 + '@diff' => render($diff), + '@supplement' => $this->supplement($node) ]; $subject = $this->t($config->get('admin_content_notification_email_subject'), $variables); $body = $this->t($config->get('admin_content_notification_email_body'), $variables); @@ -166,13 +178,16 @@ class AdminContentNotificationService { } $admin_email = implode(',', $emails); } - $to = \Drupal::config('system.site')->get('mail'); + $to = ($admin_email) ? $admin_email : \Drupal::config('system.site')->get('mail'); $params = [ - 'body' => $body, + 'body' => Markup::create($body), 'subject' => $subject, - 'bcc' => $admin_email, 'nid' => $node->id(), ]; + + if (!empty($admin_email)) { + $params['bcc'] = $admin_email; + } // Allow to alter $admin_email // by using hook_admin_content_notification_recipients_alter(). @@ -204,5 +219,210 @@ class AdminContentNotificationService { public function isTokenEnabled() { return $this->moduleHandler->moduleExists('token'); } + + /** + * Custom function to get diffs + */ + private function getDiff($node) { + $return = ''; + $fields = $node->toArray(); + $revisions = array_reverse(\Drupal::entityTypeManager()->getStorage('node')->revisionIds($node)); + $vid = $fields['vid'][0]['value']; + if (isset($revisions[1])) { + $last_vid = $revisions[1]; + $last_revision = \Drupal::entityTypeManager()->getStorage('node')->loadRevision($last_vid); + if ($last_revision) { + $last_fields = $last_revision->toArray(); + } + } + else { + return ''; + } + + // Excluding some fields + $exclude_fields = [ + 'nid', 'uid', 'uuid', 'vid', 'langcode', 'type', 'revision_timestamp', 'revision_uid', 'revision_log', + 'created', 'changed', 'default_langcode','revision_default', 'revision_translation_affected', + 'content_translation_source', 'content_translation_outdated', 'menu_link', 'path', + 'metatag' + ]; + foreach ($exclude_fields as $exclude_field) { + unset($fields[$exclude_field], $last_fields[$exclude_field]); + } + + $node_properties = [ + 'title' => ($node->bundle() == 'training') ? 'Megnevezés' : 'Cím', + 'status' => 'Közzétéve', + 'promote' => 'Címlapra helyezve', + 'sticky' => 'Kiemelt' + ]; + + $field_settings = []; + foreach ($fields as $field_name => $field_array) { + $field_storage_config = \Drupal::entityTypeManager()->getStorage('field_storage_config')->load('node.' . $field_name); + $cardinality = (method_exists($field_storage_config, 'get')) ? $field_storage_config->get('cardinality') : 1; + $field_instance_config = \Drupal::entityTypeManager()->getStorage('field_config')->load('node.' . $node->bundle() . '.' . $field_name); + $field_type = method_exists($field_instance_config, 'getType') ? $field_instance_config->getType() : NULL; + $field_instance_settings = method_exists($field_instance_config, 'getSettings') ? $field_instance_config->getSettings() : NULL; + $target_type = ($field_instance_settings && isset($field_instance_settings['target_type'])) ? $field_instance_settings['target_type'] : ''; + + $field_settings[$field_name] = [ + 'field_name' => $field_name, + 'cardinality' => $cardinality, + 'field_type' => $field_type, + 'field_label' => ($field_instance_config) ? $field_instance_config->getLabel() : (($node_properties[$field_name]) ? $node_properties[$field_name] : $field_name), + 'target_type' => $target_type, + 'old_values' => [], + 'new_values' => [] + ]; + foreach ($field_array as $index => $value_array) { + foreach ($value_array as $value_key => $value) { + if ($value_key != 'format') { + $field_settings[$field_name]['value_key'] = $value_key; + $field_settings[$field_name]['new_values'][] = $value; + } + } + } + foreach ($last_fields[$field_name] as $last_index => $last_value_array) { + foreach ($last_value_array as $last_value_key => $last_value) { + if ($last_value_key != 'format') { + $field_settings[$field_name]['old_values'][] = $last_value; + } + } + } + } + + $diff = []; + + foreach ($field_settings as $field_name => $field_data) { + switch ($field_data['field_type']) { + case 'entity_reference': + $target_storage = ($field_data['target_type']) ? \Drupal::entityTypeManager()->getStorage($field_data['target_type']) : NULL; + if ($field_data['cardinality'] == 1) { + if ($field_data['old_values'] != $field_data['new_values']) { + $diff[$field_name]['old_value'] = ($target_storage && isset($field_data['old_values'][0]) && method_exists($target_storage->load($field_data['old_values'][0]), 'label')) + ? $target_storage->load($field_data['old_values'][0])->label() + : $field_data['old_values']; + $diff[$field_name]['new_value'] = ($target_storage && method_exists($target_storage->load($field_data['new_values'][0]), 'label')) + ? $target_storage->load($field_data['new_values'][0])->label() + : $field_data['new_values']; + } + } + else { + if (array_diff($field_data['new_values'], $field_data['old_values']) || array_diff($field_data['old_values'], $field_data['new_values'])) { + $diff[$field_name]['new_value'] = ''; + foreach ($field_data['new_values'] as $new_value) { + $diff[$field_name]['new_value'] .= ($target_storage && $target_storage->load($new_value) && method_exists($target_storage->load($new_value), 'label')) + ? $target_storage->load($new_value)->label() . '
' + : $new_value . '
'; + } + $diff[$field_name]['old_value'] = ''; + foreach ($field_data['old_values'] as $old_value) { + $diff[$field_name]['old_value'] .= ($target_storage && $target_storage->load($old_value) && method_exists($target_storage->load($old_value), 'label')) + ? $target_storage->load($old_value)->label() . '
' + : $old_value . '
'; + } + } + } + break; + case 'string': + case 'string_long': + if ($field_data['cardinality'] == 1) { + if (isset($field_data['old_values'][0]) && !isset($field_data['new_values'][0])) { + $diff[$field_name]['old_value'] = $field_data['old_values'][0]; + $diff[$field_name]['new_value'] = ''; + } + else if (isset($field_data['new_values'][0]) && !isset($field_data['old_values'][0])) { + $diff[$field_name]['old_value'] = ''; + $diff[$field_name]['new_value'] = $field_data['new_values'][0]; + } + else if (isset($field_data['new_values'][0]) && isset($field_data['old_values'][0]) && $field_data['old_values'][0] != $field_data['new_values'][0]) { + $diff[$field_name]['old_value'] = $field_data['old_values'][0]; + $diff[$field_name]['new_value'] = $field_data['new_values'][0]; + } + } + else { + // There are no multivalue string and string_long type fields yet + } + break; + case 'text_long': + // formatted text + if (isset ($field_data['value_key']) && $field_data['value_key'] == 'value') { // we dont care about format changes + if ($field_data['cardinality'] == 1) { + if (isset($field_data['old_values'][0]) && !isset($field_data['new_values'][0])) { + $diff[$field_name]['old_value'] = $field_data['old_values'][0]; + $diff[$field_name]['new_value'] = ''; + } + else if (isset($field_data['new_values'][0]) && !isset($field_data['old_values'][0])) { + $diff[$field_name]['old_value'] = ''; + $diff[$field_name]['new_value'] = $field_data['new_values'][0]; + } + else if (isset($field_data['new_values'][0]) && isset($field_data['old_values'][0]) && $field_data['old_values'][0] != $field_data['new_values'][0]) { + $diff[$field_name]['old_value'] = $field_data['old_values'][0]; + $diff[$field_name]['new_value'] = $field_data['new_values'][0]; + } + } + else { + // There are no multivalue string, string_long and text_long type fields yet + } + } + break; + } + } + + if (empty($diff)) { + return ''; + } + else { + $rows = []; + + foreach ($diff as $field_name => $field) { + $rows []= [ + ['data' => $field_settings[$field_name]['field_label'], 'style' => ['border: 1px solid #aaa']], + ['data' => Markup::create(($field['old_value'] || !empty($field['old_value'])) ? $field['old_value'] : ' - '), 'style' => ['border: 1px solid #aaa']], + ['data' => Markup::create($field['new_value']), 'style' => ['border: 1px solid #aaa']] + ]; + } + if (!empty($rows)) { + $return = [ + 'label' => ['#markup' => $this->t('Modfications: ')], + 'table' => [ + '#type' => 'table', + '#header' => ['', $this->t('Old value'), $this->t('New value')], + '#rows' => $rows, + '#attributes' => [ + 'style' => 'border:1px solid #aaa; width: 100%; border-collapse: collapse;', + 'class' => ['modifications-table'] + ], + '#attached' => [ + 'library' => ['admin_content_notification/mail'] + ] + ], + ]; + } + } + return $return; + } + + /** + * + */ + private function supplement($node) { + $return = ''; + if ($node->bundle() == 'place') { + $return .= 'Jelen levél csak az adott helyszínen induló ezen képzés összes időpontjára KÖZÖS mezőmódosulásokat tartalmazza táblázatosan (korábbi érték, jelenlegi érték).
'; + $return .= 'Az egy-egy időpontot érintő módosulásokhoz kérjük, látogasd meg a honlapot.
'; + $return .= '(Az alábbi módosulások nincsenek részletezve a levélben, ezek a honlapon ellenőrizendők:'; + $return .= '- kezdés jellege (folyamatos vagy fix időpontos)
'; + $return .= '- indulás időpontja
'; + $return .= '- időpont aktiválása/inaktiválása
'; + $return .= '- Képzési napok
'; + $return .= '- Egyéb (Biztosan indul, Céghez kihelyezetten is stb)
'; + $return .= '- Díjak és kedvezmények
'; + $return .= '- Tanfolyamvezetők)
'; + } + + return Markup::create($return); + } } diff --git a/src/Form/AdminContentNotification.php b/src/Form/AdminContentNotification.php index 9314667..b126e83 100644 --- a/src/Form/AdminContentNotification.php +++ b/src/Form/AdminContentNotification.php @@ -73,6 +73,14 @@ class AdminContentNotification extends ConfigFormBase { '#default_value' => $trigger_node_update, '#description' => $this->t('Please check on it if you want to send notification on update action as well.'), ]; + + $trigger_node_delete = ($config->get('admin_content_notification_trigger_on_node_delete')) ?: FALSE; + $form['admin_content_notification_trigger_on_node_delete'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Enable on content delete'), + '#default_value' => $trigger_node_delete, + '#description' => $this->t('Please check on it if you want to send notification on delete action as well.'), + ]; $trigger_node_status = ($config->get('admin_content_notification_trigger_on_node_status')) ?: 0; $content_status = []; @@ -115,7 +123,7 @@ class AdminContentNotification extends ConfigFormBase { '#type' => 'textarea', '#title' => $this->t("Email Id's to whom the notification is to be sent, add comma separated emails in case of multiple recipients"), '#default_value' => isset($admin_content_notification_email) ? $admin_content_notification_email : $site_email, - '#description' => $this->t('You can add emails upto Recipients Limit (Max)'), + '#description' => $this->t('You can add emails upto Recipients Limit (Max). Leave empty to send notifications to site email address.'), ]; $form['admin_content_notification_recepient_fieldset']['admin_content_notification_email_or_markup']['#markup'] = '' . $this->t('OR') . ''; @@ -224,6 +232,7 @@ class AdminContentNotification extends ConfigFormBase { $config = $this->configFactory->getEditable('admin_content_notification.settings'); $config->set('admin_content_notification_node_types', $user_input_values['admin_content_notification_node_types']); $config->set('admin_content_notification_trigger_on_node_update', $user_input_values['admin_content_notification_trigger_on_node_update']); + $config->set('admin_content_notification_trigger_on_node_delete', $user_input_values['admin_content_notification_trigger_on_node_delete']); $config->set('admin_content_notification_trigger_on_node_status', $user_input_values['admin_content_notification_trigger_on_node_status']); $config->set('admin_content_notification_email_limit', $user_input_values['admin_content_notification_email_limit']); $config->set('admin_content_notification_allowed_roles', $user_input_values['admin_content_notification_allowed_roles']);