[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/plugins/workflow/notification/ -> notification.php (source)

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Plugin
   5   * @subpackage  Workflow.Notification
   6   *
   7   * @copyright   (C) 2020 Open Source Matters, Inc. <https://www.joomla.org>
   8   * @license     GNU General Public License version 2 or later; see LICENSE.txt
   9  
  10   * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
  11   */
  12  
  13  use Joomla\CMS\Application\CMSApplicationInterface;
  14  use Joomla\CMS\Component\ComponentHelper;
  15  use Joomla\CMS\Event\Workflow\WorkflowTransitionEvent;
  16  use Joomla\CMS\Factory;
  17  use Joomla\CMS\Form\Form;
  18  use Joomla\CMS\Language\LanguageFactoryInterface;
  19  use Joomla\CMS\Language\Text;
  20  use Joomla\CMS\Plugin\CMSPlugin;
  21  use Joomla\CMS\User\UserFactoryInterface;
  22  use Joomla\CMS\Workflow\WorkflowPluginTrait;
  23  use Joomla\CMS\Workflow\WorkflowServiceInterface;
  24  use Joomla\Event\EventInterface;
  25  use Joomla\Event\SubscriberInterface;
  26  use Joomla\Utilities\ArrayHelper;
  27  
  28  // phpcs:disable PSR1.Files.SideEffects
  29  \defined('_JEXEC') or die;
  30  // phpcs:enable PSR1.Files.SideEffects
  31  
  32  /**
  33   * Workflow Notification Plugin
  34   *
  35   * @since  4.0.0
  36   */
  37  class PlgWorkflowNotification extends CMSPlugin implements SubscriberInterface
  38  {
  39      use WorkflowPluginTrait;
  40  
  41      /**
  42       * Load the language file on instantiation.
  43       *
  44       * @var    boolean
  45       * @since  4.0.0
  46       */
  47      protected $autoloadLanguage = true;
  48  
  49      /**
  50       * Loads the CMS Application for direct access
  51       *
  52       * @var   CMSApplicationInterface
  53       * @since 4.0.0
  54       */
  55      protected $app;
  56  
  57      /**
  58       * @var    \Joomla\Database\DatabaseDriver
  59       *
  60       * @since  3.9.0
  61       */
  62      protected $db;
  63  
  64      /**
  65       * Returns an array of events this subscriber will listen to.
  66       *
  67       * @return   array
  68       *
  69       * @since   4.0.0
  70       */
  71      public static function getSubscribedEvents(): array
  72      {
  73          return [
  74              'onContentPrepareForm'        => 'onContentPrepareForm',
  75              'onWorkflowAfterTransition'   => 'onWorkflowAfterTransition',
  76          ];
  77      }
  78  
  79      /**
  80       * The form event.
  81       *
  82       * @param   Form      $form  The form
  83       * @param   stdClass  $data  The data
  84       *
  85       * @return   boolean
  86       *
  87       * @since   4.0.0
  88       */
  89      public function onContentPrepareForm(EventInterface $event)
  90      {
  91          $form = $event->getArgument('0');
  92          $data = $event->getArgument('1');
  93  
  94          $context = $form->getName();
  95  
  96          // Extend the transition form
  97          if ($context === 'com_workflow.transition') {
  98              $this->enhanceWorkflowTransitionForm($form, $data);
  99          }
 100  
 101          return true;
 102      }
 103  
 104      /**
 105       * Send a Notification to defined users a transition is performed
 106       *
 107       * @param   string  $context  The context for the content passed to the plugin.
 108       * @param   array   $pks      A list of primary key ids of the content that has changed stage.
 109       * @param   object  $data     Object containing data about the transition
 110       *
 111       * @return   boolean
 112       *
 113       * @since   4.0.0
 114       */
 115      public function onWorkflowAfterTransition(WorkflowTransitionEvent $event)
 116      {
 117          $context       = $event->getArgument('extension');
 118          $extensionName = $event->getArgument('extensionName');
 119          $transition    = $event->getArgument('transition');
 120          $pks           = $event->getArgument('pks');
 121  
 122          if (!$this->isSupported($context)) {
 123              return;
 124          }
 125  
 126          $component = $this->app->bootComponent($extensionName);
 127  
 128          // Check if send-mail is active
 129          if (empty($transition->options['notification_send_mail'])) {
 130              return;
 131          }
 132  
 133          // ID of the items whose state has changed.
 134          $pks = ArrayHelper::toInteger($pks);
 135  
 136          if (empty($pks)) {
 137              return;
 138          }
 139  
 140          // Get UserIds of Receivers
 141          $userIds = $this->getUsersFromGroup($transition);
 142  
 143          // The active user
 144          $user = $this->app->getIdentity();
 145  
 146          // Prepare Language for messages
 147          $defaultLanguage = ComponentHelper::getParams('com_languages')->get('administrator');
 148          $debug = $this->app->get('debug_lang');
 149  
 150          $modelName = $component->getModelName($context);
 151          $model = $component->getMVCFactory()->createModel($modelName, $this->app->getName(), ['ignore_request' => true]);
 152  
 153          // Don't send the notification to the active user
 154          $key = array_search($user->id, $userIds);
 155  
 156          if (is_int($key)) {
 157              unset($userIds[$key]);
 158          }
 159  
 160          // Remove users with locked input box from the list of receivers
 161          if (!empty($userIds)) {
 162              $userIds = $this->removeLocked($userIds);
 163          }
 164  
 165          // If there are no receivers, stop here
 166          if (empty($userIds)) {
 167              $this->app->enqueueMessage(Text::_('PLG_WORKFLOW_NOTIFICATION_NO_RECEIVER'), 'error');
 168  
 169              return;
 170          }
 171  
 172          // Get the model for private messages
 173          $model_message = $this->app->bootComponent('com_messages')
 174              ->getMVCFactory()->createModel('Message', 'Administrator');
 175  
 176          // Get the title of the stage
 177          $model_stage = $this->app->bootComponent('com_workflow')
 178              ->getMVCFactory()->createModel('Stage', 'Administrator');
 179  
 180          $toStage = $model_stage->getItem($transition->to_stage_id)->title;
 181  
 182          // Get the name of the transition
 183          $model_transition = $this->app->bootComponent('com_workflow')
 184              ->getMVCFactory()->createModel('Transition', 'Administrator');
 185  
 186          $transitionName = $model_transition->getItem($transition->id)->title;
 187  
 188          $hasGetItem = method_exists($model, 'getItem');
 189          $container = Factory::getContainer();
 190  
 191          foreach ($pks as $pk) {
 192              // Get the title of the item which has changed, unknown as fallback
 193              $title = Text::_('PLG_WORKFLOW_NOTIFICATION_NO_TITLE');
 194  
 195              if ($hasGetItem) {
 196                  $item = $model->getItem($pk);
 197                  $title = !empty($item->title) ? $item->title : $title;
 198              }
 199  
 200              // Send Email to receivers
 201              foreach ($userIds as $user_id) {
 202                  $receiver = $container->get(UserFactoryInterface::class)->loadUserById($user_id);
 203  
 204                  if ($receiver->authorise('core.manage', 'com_message')) {
 205                      // Load language for messaging
 206                      $lang = $container->get(LanguageFactoryInterface::class)
 207                          ->createLanguage($user->getParam('admin_language', $defaultLanguage), $debug);
 208                      $lang->load('plg_workflow_notification');
 209                      $messageText = sprintf(
 210                          $lang->_('PLG_WORKFLOW_NOTIFICATION_ON_TRANSITION_MSG'),
 211                          $title,
 212                          $lang->_($transitionName),
 213                          $user->name,
 214                          $lang->_($toStage)
 215                      );
 216  
 217                      if (!empty($transition->options['notification_text'])) {
 218                          $messageText .= '<br>' . htmlspecialchars($lang->_($transition->options['notification_text']));
 219                      }
 220  
 221                      $message = [
 222                          'id' => 0,
 223                          'user_id_to' => $receiver->id,
 224                          'subject' => sprintf($lang->_('PLG_WORKFLOW_NOTIFICATION_ON_TRANSITION_SUBJECT'), $title),
 225                          'message' => $messageText,
 226                      ];
 227  
 228                      $model_message->save($message);
 229                  }
 230              }
 231          }
 232  
 233          $this->app->enqueueMessage(Text::_('PLG_WORKFLOW_NOTIFICATION_SENT'), 'message');
 234      }
 235  
 236      /**
 237       * Get user_ids of receivers
 238       *
 239       * @param   object  $data  Object containing data about the transition
 240       *
 241       * @return   array  $userIds  The receivers
 242       *
 243       * @since   4.0.0
 244       */
 245      private function getUsersFromGroup($data): array
 246      {
 247          $users = [];
 248  
 249          // Single userIds
 250          if (!empty($data->options['notification_receivers'])) {
 251              $users = ArrayHelper::toInteger($data->options['notification_receivers']);
 252          }
 253  
 254          // Usergroups
 255          $groups = [];
 256  
 257          if (!empty($data->options['notification_groups'])) {
 258              $groups = ArrayHelper::toInteger($data->options['notification_groups']);
 259          }
 260  
 261          $users2 = [];
 262  
 263          if (!empty($groups)) {
 264              // UserIds from usergroups
 265              $model = Factory::getApplication()->bootComponent('com_users')
 266                  ->getMVCFactory()->createModel('Users', 'Administrator', ['ignore_request' => true]);
 267  
 268              $model->setState('list.select', 'id');
 269              $model->setState('filter.groups', $groups);
 270              $model->setState('filter.state', 0);
 271  
 272              // Ids from usergroups
 273              $groupUsers = $model->getItems();
 274  
 275              $users2 = ArrayHelper::getColumn($groupUsers, 'id');
 276          }
 277  
 278          // Merge userIds from individual entries and userIDs from groups
 279          return array_unique(array_merge($users, $users2));
 280      }
 281  
 282      /**
 283       * Check if the current plugin should execute workflow related activities
 284       *
 285       * @param   string  $context
 286       *
 287       * @return   boolean
 288       *
 289       * @since   4.0.0
 290       */
 291      protected function isSupported($context)
 292      {
 293          if (!$this->checkAllowedAndForbiddenlist($context)) {
 294              return false;
 295          }
 296  
 297          $parts = explode('.', $context);
 298  
 299          // We need at least the extension + view for loading the table fields
 300          if (count($parts) < 2) {
 301              return false;
 302          }
 303  
 304          $component = $this->app->bootComponent($parts[0]);
 305  
 306          if (
 307              !$component instanceof WorkflowServiceInterface
 308              || !$component->isWorkflowActive($context)
 309          ) {
 310              return false;
 311          }
 312  
 313          return true;
 314      }
 315  
 316      /**
 317       * Remove receivers who have locked their message inputbox
 318       *
 319       * @param   array  $userIds  The userIds which must be checked
 320       *
 321       * @return   array  users with active message input box
 322       *
 323       * @since   4.0.0
 324       */
 325      private function removeLocked(array $userIds): array
 326      {
 327          if (empty($userIds)) {
 328              return [];
 329          }
 330  
 331          // Check for locked inboxes would be better to have _cdf settings in the user_object or a filter in users model
 332          $query = $this->db->getQuery(true);
 333  
 334          $query->select($this->db->quoteName('user_id'))
 335              ->from($this->db->quoteName('#__messages_cfg'))
 336              ->whereIn($this->db->quoteName('user_id'), $userIds)
 337              ->where($this->db->quoteName('cfg_name') . ' = ' . $this->db->quote('locked'))
 338              ->where($this->db->quoteName('cfg_value') . ' = 1');
 339  
 340          $locked = $this->db->setQuery($query)->loadColumn();
 341  
 342          return array_diff($userIds, $locked);
 343      }
 344  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer