diff --git a/README.md b/README.md index f6b72f5..db9d13c 100644 --- a/README.md +++ b/README.md @@ -58,3 +58,14 @@ Navodila za konstruiranje fajlov pa so tukaj: https://www.drupal.org/docs/contri ### Endpoint za dodajanje pojmov V modulu [yufu_concept](web/modules/custom/yufu_concept/yufu_concept.info.yml "yufu_concept"). + + +### Obveščanje prek mailov + +1. Ko je dodan nov pojem ali posodobljen star pojem, obvesti o tem vse urednike. +- ob novi draft revizija se poslje mail urednikom + +2. Ko je sprejet nov pojem ali revizija, obvesti uporabnika in ga odblokiraj. +- ob novi publishani revizijami se poslje mail uporabniku, ki jo je naredil. + +Funkcionalnost se nahaja v yufu_admin modulu. diff --git a/composer.json b/composer.json index e980592..003a46b 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ "drupal/core-composer-scaffold": "^10.0", "drupal/core-project-message": "^10.0", "drupal/core-recommended": "^10.0", + "drupal/diff": "^1.1", "drupal/gin": "^3.0@RC", "drupal/gin_toolbar": "^1.0@RC", "drupal/jsonapi_menu_items": "^1.2", diff --git a/composer.lock b/composer.lock index f029d26..7c1d6be 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "185dc0d2be2be9514fc2dad73c4205d1", + "content-hash": "2ca7e5f483ed127efa757db4cb8d35ca", "packages": [ { "name": "asm89/stack-cors", @@ -62,6 +62,67 @@ }, "time": "2022-01-18T09:12:03+00:00" }, + { + "name": "caxy/php-htmldiff", + "version": "v0.1.15", + "source": { + "type": "git", + "url": "https://github.com/caxy/php-htmldiff.git", + "reference": "6342b02ddb86fd36093ad7e2db2efc21f01ab7cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/caxy/php-htmldiff/zipball/6342b02ddb86fd36093ad7e2db2efc21f01ab7cd", + "reference": "6342b02ddb86fd36093ad7e2db2efc21f01ab7cd", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "ezyang/htmlpurifier": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "doctrine/cache": "~1.0", + "phpunit/phpunit": "~9.0" + }, + "suggest": { + "doctrine/cache": "Used for caching the calculated diffs using a Doctrine Cache Provider" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "Caxy\\HtmlDiff": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0" + ], + "authors": [ + { + "name": "Josh Schroeder", + "email": "jschroeder@caxy.com", + "homepage": "http://www.caxy.com" + } + ], + "description": "A library for comparing two HTML files/snippets and highlighting the differences using simple HTML.", + "homepage": "https://github.com/caxy/php-htmldiff", + "keywords": [ + "diff", + "html" + ], + "support": { + "issues": "https://github.com/caxy/php-htmldiff/issues", + "source": "https://github.com/caxy/php-htmldiff/tree/v0.1.15" + }, + "time": "2023-11-05T23:49:04+00:00" + }, { "name": "chi-teck/drupal-code-generator", "version": "2.6.2", @@ -1718,6 +1779,97 @@ }, "time": "2023-12-06T09:22:56+00:00" }, + { + "name": "drupal/diff", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/diff.git", + "reference": "8.x-1.1" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/diff-8.x-1.1.zip", + "reference": "8.x-1.1", + "shasum": "b7558b0f431d5945289829946e0beba61bf7ae18" + }, + "require": { + "drupal/core": "^9.3 || ^10", + "mkalkbrenner/php-htmldiff-advanced": "~0.0.8" + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "8.x-1.1", + "datestamp": "1665437355", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Miro Dietiker (miro_dietiker)", + "homepage": "https://www.drupal.org/u/miro_dietiker", + "role": "Maintainer" + }, + { + "name": "Juampy NR (juampynr)", + "homepage": "https://www.drupal.org/u/juampynr", + "role": "Maintainer" + }, + { + "name": "Lucian Hangea (lhangea)", + "homepage": "https://www.drupal.org/u/lhangea", + "role": "Maintainer" + }, + { + "name": "Alan D.", + "homepage": "https://www.drupal.org/u/alan-d.", + "role": "Maintainer" + }, + { + "name": "Brian Gilbert (realityloop).", + "homepage": "https://www.drupal.org/u/realityloop", + "role": "Maintainer" + }, + { + "name": "lhangea", + "homepage": "https://www.drupal.org/user/2743803" + }, + { + "name": "miro_dietiker", + "homepage": "https://www.drupal.org/user/227761" + }, + { + "name": "phenaproxima", + "homepage": "https://www.drupal.org/user/205645" + }, + { + "name": "realityloop", + "homepage": "https://www.drupal.org/user/139189" + }, + { + "name": "rötzi", + "homepage": "https://www.drupal.org/user/73064" + }, + { + "name": "yhahn", + "homepage": "https://www.drupal.org/user/264833" + } + ], + "description": "Compares two entity revisions", + "homepage": "https://www.drupal.org/project/diff", + "support": { + "source": "http://cgit.drupalcode.org/diff", + "issues": "https://www.drupal.org/project/issues/diff" + } + }, { "name": "drupal/gin", "version": "3.0.0-rc7", @@ -2476,6 +2628,67 @@ }, "time": "2023-11-17T07:53:29+00:00" }, + { + "name": "ezyang/htmlpurifier", + "version": "v4.17.0", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/bbc513d79acf6691fa9cf10f192c90dd2957f18c", + "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c", + "shasum": "" + }, + "require": { + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" + }, + "require-dev": { + "cerdic/css-tidy": "^1.7 || ^2.0", + "simpletest/simpletest": "dev-master" + }, + "suggest": { + "cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.", + "ext-bcmath": "Used for unit conversion and imagecrash protection", + "ext-iconv": "Converts text to and from non-UTF-8 encodings", + "ext-tidy": "Used for pretty-printing HTML" + }, + "type": "library", + "autoload": { + "files": [ + "library/HTMLPurifier.composer.php" + ], + "psr-0": { + "HTMLPurifier": "library/" + }, + "exclude-from-classmap": [ + "/library/HTMLPurifier/Language/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ], + "support": { + "issues": "https://github.com/ezyang/htmlpurifier/issues", + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.17.0" + }, + "time": "2023-11-17T15:01:25+00:00" + }, { "name": "grasmash/expander", "version": "3.0.0", @@ -3051,6 +3264,47 @@ }, "time": "2023-08-12T08:29:29+00:00" }, + { + "name": "mkalkbrenner/php-htmldiff-advanced", + "version": "0.0.8", + "source": { + "type": "git", + "url": "https://github.com/mkalkbrenner/php-htmldiff.git", + "reference": "3a714b48c9c3d3730baaf6d3949691e654cd37c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mkalkbrenner/php-htmldiff/zipball/3a714b48c9c3d3730baaf6d3949691e654cd37c9", + "reference": "3a714b48c9c3d3730baaf6d3949691e654cd37c9", + "shasum": "" + }, + "require": { + "caxy/php-htmldiff": ">=0.0.6", + "php": ">=5.5.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/HtmlDiffAdvancedInterface.php", + "src/HtmlDiffAdvanced.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GNU General Public License V2" + ], + "description": "An add-on for the php-htmldiff library for comparing two HTML files/snippets and highlighting the differences using simple HTML.", + "homepage": "https://github.com/mkalkbrenner/php-htmldiff", + "keywords": [ + "diff", + "html" + ], + "support": { + "issues": "https://github.com/mkalkbrenner/php-htmldiff/issues", + "source": "https://github.com/mkalkbrenner/php-htmldiff/tree/master" + }, + "time": "2016-07-25T17:07:32+00:00" + }, { "name": "nikic/php-parser", "version": "v4.17.1", diff --git a/web/modules/custom/yufu_admin/yufu_admin.module b/web/modules/custom/yufu_admin/yufu_admin.module index 7dd23f6..7d7b030 100644 --- a/web/modules/custom/yufu_admin/yufu_admin.module +++ b/web/modules/custom/yufu_admin/yufu_admin.module @@ -7,6 +7,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Url; +use Drupal\node\NodeInterface; /** * Implements hook_entity_operation(). @@ -28,3 +29,122 @@ function yufu_admin_entity_operation(EntityInterface $entity) { } return $operations; } + +/** + * Implements hook_mail(). + */ +function yufu_admin_mail($key, &$message, $params) { + $options = ['langcode' => $message['langcode']]; + + switch ($key) { + case 'concept_drafted': + $message['from'] = \Drupal::config('system.site')->get('mail'); + $message['subject'] = t('YUFU: New concept draft: @title', ['@title' => $params['node_title']], $options); + $message['body'][] = $params['message']; + break; + case 'concept_approved': + $message['from'] = \Drupal::config('system.site')->get('mail'); + $message['subject'] = t('YUFU: Your concept (changes) were approved: @title', ['@title' => $params['node_title']], $options); + $message['body'][] = $params['message']; + break; + case 'concept_rejected': + $message['from'] = \Drupal::config('system.site')->get('mail'); + $message['subject'] = t('YUFU: Your concept (changes) were rejected: @title', ['@title' => $params['node_title']], $options); + $message['body'][] = $params['message']; + } +} + +/** + * Implements hook_ENTITY_TYPE_presave(). + */ +function yufu_admin_node_presave(EntityInterface $entity) { + if ($entity instanceOf NodeInterface && $entity->bundle() == 'concept') { + // Get transition: concept_drafted, concept_approved, concept_rejected. + if ($entity->isNew()) { + $transition = 'concept_drafted'; + } + else { + $transition = _yufu_admin_get_node_transition($entity); + } + switch ($transition) { + case 'concept_drafted': + // Send email to editors. + _yufu_admin_concept_drafted_mail($entity); + break; + case 'concept_approved': + // Send email to revision creator (user). + break; + case 'concept_rejectd': + // Send email to revision creator (user). + // This transition happens on revision delete. + // Curently it is dead. + break; + } + } +} + +/** + * Compare original node moderation state with current state. + * + * @param \Drupal\node\NodeInterface $node + * Node to check transition on. + * + * @return string|null + * Name of the transition. + */ +function _yufu_admin_get_node_transition(NodeInterface $node) { + $original = $node->original; + $moderation_state = $node->moderation_state->value; + $previous_state = $original->moderation_state->value; + if ($moderation_state == 'draft' && $previous_state == 'published') { + return 'concept_drafted'; + } + else if ($moderation_state == 'published' && $previous_state == 'draft') { + return 'concept_approved'; + } + else if ($moderation_state == 'published' && $previous_state == 'published') { + return 'stay_published'; + } + else if ($moderation_state == 'draft' && $previous_state == 'draft') { + return 'stay_draft'; + } + return NULL; +} + +function _yufu_admin_concept_drafted_mail(NodeInterface $node) { + $mailManager = \Drupal::service('plugin.manager.mail'); + $module = 'yufu_admin'; + $key = 'concept_drafted'; + // To all editors. + $to = _yufu_admin_get_all_editors_emails(); + $params['message'] = t('New concept created: @title - @url', [ + 'title' => $node->getTitle(), + 'url' => $node->toUrl()->toString(), + ]); + $params['node_title'] = $entity->label(); + $langcode = \Drupal::currentUser()->getPreferredLangcode(); + $send = true; + + $result = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send); + if ($result['result'] !== true) { + drupal_set_message(t('There was a problem sending your message and it was not sent.'), 'error'); + } + else { + drupal_set_message(t('Your message has been sent.')); + } +} + +function _yufu_admin_get_all_editors_emails() { + $user_storage = \Drupal::entityTypeManager()->getStorage('user'); + $ids = $user_storage->getQuery() + ->condition('status', 1) + ->condition('roles', 'administrator') + ->execute(); + $editors = $user_storage->loadMultiple($ids); + $emails = []; + foreach ($editors as $editor) { + /* @var \Drupal\user\UserInterface $user */ + $emails[] = $editor->getEmail(); + } + return $emails; +}