[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |