[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @package Joomla.Administrator 5 * @subpackage com_messages 6 * 7 * @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org> 8 * @license GNU General Public License version 2 or later; see LICENSE.txt 9 */ 10 11 namespace Joomla\Component\Messages\Administrator\Model; 12 13 use Joomla\CMS\Access\Access; 14 use Joomla\CMS\Access\Rule; 15 use Joomla\CMS\Component\ComponentHelper; 16 use Joomla\CMS\Factory; 17 use Joomla\CMS\Language\Language; 18 use Joomla\CMS\Language\Text; 19 use Joomla\CMS\Log\Log; 20 use Joomla\CMS\Mail\Exception\MailDisabledException; 21 use Joomla\CMS\Mail\MailTemplate; 22 use Joomla\CMS\MVC\Model\AdminModel; 23 use Joomla\CMS\Router\Route; 24 use Joomla\CMS\Table\Asset; 25 use Joomla\CMS\Table\Table; 26 use Joomla\CMS\User\User; 27 use Joomla\Database\ParameterType; 28 use PHPMailer\PHPMailer\Exception as phpMailerException; 29 30 // phpcs:disable PSR1.Files.SideEffects 31 \defined('_JEXEC') or die; 32 // phpcs:enable PSR1.Files.SideEffects 33 34 /** 35 * Private Message model. 36 * 37 * @since 1.6 38 */ 39 class MessageModel extends AdminModel 40 { 41 /** 42 * Message 43 * 44 * @var \stdClass 45 */ 46 protected $item; 47 48 /** 49 * Method to auto-populate the model state. 50 * 51 * This method should only be called once per instantiation and is designed 52 * to be called on the first call to the getState() method unless the model 53 * configuration flag to ignore the request is set. 54 * 55 * Note. Calling getState in this method will result in recursion. 56 * 57 * @return void 58 * 59 * @since 1.6 60 */ 61 protected function populateState() 62 { 63 parent::populateState(); 64 65 $input = Factory::getApplication()->input; 66 67 $user = Factory::getUser(); 68 $this->setState('user.id', $user->get('id')); 69 70 $messageId = (int) $input->getInt('message_id'); 71 $this->setState('message.id', $messageId); 72 73 $replyId = (int) $input->getInt('reply_id'); 74 $this->setState('reply.id', $replyId); 75 } 76 77 /** 78 * Check that recipient user is the one trying to delete and then call parent delete method 79 * 80 * @param array &$pks An array of record primary keys. 81 * 82 * @return boolean True if successful, false if an error occurs. 83 * 84 * @since 3.1 85 */ 86 public function delete(&$pks) 87 { 88 $pks = (array) $pks; 89 $table = $this->getTable(); 90 $user = Factory::getUser(); 91 92 // Iterate the items to delete each one. 93 foreach ($pks as $i => $pk) { 94 if ($table->load($pk)) { 95 if ($table->user_id_to != $user->id) { 96 // Prune items that you can't change. 97 unset($pks[$i]); 98 99 try { 100 Log::add(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), Log::WARNING, 'jerror'); 101 } catch (\RuntimeException $exception) { 102 Factory::getApplication()->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), 'warning'); 103 } 104 105 return false; 106 } 107 } else { 108 $this->setError($table->getError()); 109 110 return false; 111 } 112 } 113 114 return parent::delete($pks); 115 } 116 117 /** 118 * Method to get a single record. 119 * 120 * @param integer $pk The id of the primary key. 121 * 122 * @return mixed Object on success, false on failure. 123 * 124 * @since 1.6 125 */ 126 public function getItem($pk = null) 127 { 128 if (!isset($this->item)) { 129 if ($this->item = parent::getItem($pk)) { 130 // Invalid message_id returns 0 131 if ($this->item->user_id_to === '0') { 132 $this->setError(Text::_('JERROR_ALERTNOAUTHOR')); 133 134 return false; 135 } 136 137 // Prime required properties. 138 if (empty($this->item->message_id)) { 139 // Prepare data for a new record. 140 if ($replyId = (int) $this->getState('reply.id')) { 141 // If replying to a message, preload some data. 142 $db = $this->getDatabase(); 143 $query = $db->getQuery(true) 144 ->select($db->quoteName(['subject', 'user_id_from', 'user_id_to'])) 145 ->from($db->quoteName('#__messages')) 146 ->where($db->quoteName('message_id') . ' = :messageid') 147 ->bind(':messageid', $replyId, ParameterType::INTEGER); 148 149 try { 150 $message = $db->setQuery($query)->loadObject(); 151 } catch (\RuntimeException $e) { 152 $this->setError($e->getMessage()); 153 154 return false; 155 } 156 157 if (!$message || $message->user_id_to != Factory::getUser()->id) { 158 $this->setError(Text::_('JERROR_ALERTNOAUTHOR')); 159 160 return false; 161 } 162 163 $this->item->set('user_id_to', $message->user_id_from); 164 $re = Text::_('COM_MESSAGES_RE'); 165 166 if (stripos($message->subject, $re) !== 0) { 167 $this->item->set('subject', $re . ' ' . $message->subject); 168 } 169 } 170 } elseif ($this->item->user_id_to != Factory::getUser()->id) { 171 $this->setError(Text::_('JERROR_ALERTNOAUTHOR')); 172 173 return false; 174 } else { 175 // Mark message read 176 $db = $this->getDatabase(); 177 $query = $db->getQuery(true) 178 ->update($db->quoteName('#__messages')) 179 ->set($db->quoteName('state') . ' = 1') 180 ->where($db->quoteName('message_id') . ' = :messageid') 181 ->bind(':messageid', $this->item->message_id, ParameterType::INTEGER); 182 $db->setQuery($query)->execute(); 183 } 184 } 185 186 // Get the user name for an existing message. 187 if ($this->item->user_id_from && $fromUser = new User($this->item->user_id_from)) { 188 $this->item->set('from_user_name', $fromUser->name); 189 } 190 } 191 192 return $this->item; 193 } 194 195 /** 196 * Method to get the record form. 197 * 198 * @param array $data Data for the form. 199 * @param boolean $loadData True if the form is to load its own data (default case), false if not. 200 * 201 * @return \Joomla\CMS\Form\Form|bool A Form object on success, false on failure 202 * 203 * @since 1.6 204 */ 205 public function getForm($data = array(), $loadData = true) 206 { 207 // Get the form. 208 $form = $this->loadForm('com_messages.message', 'message', array('control' => 'jform', 'load_data' => $loadData)); 209 210 if (empty($form)) { 211 return false; 212 } 213 214 return $form; 215 } 216 217 /** 218 * Method to get the data that should be injected in the form. 219 * 220 * @return mixed The data for the form. 221 * 222 * @since 1.6 223 */ 224 protected function loadFormData() 225 { 226 // Check the session for previously entered form data. 227 $data = Factory::getApplication()->getUserState('com_messages.edit.message.data', array()); 228 229 if (empty($data)) { 230 $data = $this->getItem(); 231 } 232 233 $this->preprocessData('com_messages.message', $data); 234 235 return $data; 236 } 237 238 /** 239 * Checks that the current user matches the message recipient and calls the parent publish method 240 * 241 * @param array &$pks A list of the primary keys to change. 242 * @param integer $value The value of the published state. 243 * 244 * @return boolean True on success. 245 * 246 * @since 3.1 247 */ 248 public function publish(&$pks, $value = 1) 249 { 250 $user = Factory::getUser(); 251 $table = $this->getTable(); 252 $pks = (array) $pks; 253 254 // Check that the recipient matches the current user 255 foreach ($pks as $i => $pk) { 256 $table->reset(); 257 258 if ($table->load($pk)) { 259 if ($table->user_id_to != $user->id) { 260 // Prune items that you can't change. 261 unset($pks[$i]); 262 263 try { 264 Log::add(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), Log::WARNING, 'jerror'); 265 } catch (\RuntimeException $exception) { 266 Factory::getApplication()->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'warning'); 267 } 268 269 return false; 270 } 271 } 272 } 273 274 return parent::publish($pks, $value); 275 } 276 277 /** 278 * Method to save the form data. 279 * 280 * @param array $data The form data. 281 * 282 * @return boolean True on success. 283 * 284 * @since 1.6 285 */ 286 public function save($data) 287 { 288 $table = $this->getTable(); 289 290 // Bind the data. 291 if (!$table->bind($data)) { 292 $this->setError($table->getError()); 293 294 return false; 295 } 296 297 // Assign empty values. 298 if (empty($table->user_id_from)) { 299 $table->user_id_from = Factory::getUser()->get('id'); 300 } 301 302 if ((int) $table->date_time == 0) { 303 $table->date_time = Factory::getDate()->toSql(); 304 } 305 306 // Check the data. 307 if (!$table->check()) { 308 $this->setError($table->getError()); 309 310 return false; 311 } 312 313 // Load the user details (already valid from table check). 314 $toUser = User::getInstance($table->user_id_to); 315 316 // Check if recipient can access com_messages. 317 if (!$toUser->authorise('core.login.admin') || !$toUser->authorise('core.manage', 'com_messages')) { 318 $this->setError(Text::_('COM_MESSAGES_ERROR_RECIPIENT_NOT_AUTHORISED')); 319 320 return false; 321 } 322 323 // Load the recipient user configuration. 324 $model = $this->bootComponent('com_messages') 325 ->getMVCFactory()->createModel('Config', 'Administrator', ['ignore_request' => true]); 326 $model->setState('user.id', $table->user_id_to); 327 $config = $model->getItem(); 328 329 if (empty($config)) { 330 $this->setError($model->getError()); 331 332 return false; 333 } 334 335 if ($config->get('lock', false)) { 336 $this->setError(Text::_('COM_MESSAGES_ERR_SEND_FAILED')); 337 338 return false; 339 } 340 341 // Store the data. 342 if (!$table->store()) { 343 $this->setError($table->getError()); 344 345 return false; 346 } 347 348 $key = $table->getKeyName(); 349 350 if (isset($table->$key)) { 351 $this->setState($this->getName() . '.id', $table->$key); 352 } 353 354 if ($config->get('mail_on_new', true)) { 355 $fromUser = User::getInstance($table->user_id_from); 356 $debug = Factory::getApplication()->get('debug_lang'); 357 $default_language = ComponentHelper::getParams('com_languages')->get('administrator'); 358 $lang = Language::getInstance($toUser->getParam('admin_language', $default_language), $debug); 359 $lang->load('com_messages', JPATH_ADMINISTRATOR); 360 361 // Build the email subject and message 362 $app = Factory::getApplication(); 363 $linkMode = $app->get('force_ssl', 0) >= 1 ? Route::TLS_FORCE : Route::TLS_IGNORE; 364 $sitename = $app->get('sitename'); 365 $fromName = $fromUser->get('name'); 366 $siteURL = Route::link( 367 'administrator', 368 'index.php?option=com_messages&view=message&message_id=' . $table->message_id, 369 false, 370 $linkMode, 371 true 372 ); 373 $subject = html_entity_decode($table->subject, ENT_COMPAT, 'UTF-8'); 374 $message = strip_tags(html_entity_decode($table->message, ENT_COMPAT, 'UTF-8')); 375 376 // Send the email 377 $mailer = new MailTemplate('com_messages.new_message', $lang->getTag()); 378 $data = [ 379 'subject' => $subject, 380 'message' => $message, 381 'fromname' => $fromName, 382 'sitename' => $sitename, 383 'siteurl' => $siteURL, 384 'fromemail' => $fromUser->email, 385 'toname' => $toUser->name, 386 'toemail' => $toUser->email 387 ]; 388 $mailer->addTemplateData($data); 389 $mailer->setReplyTo($fromUser->email, $fromUser->name); 390 $mailer->addRecipient($toUser->email, $toUser->name); 391 392 try { 393 $mailer->send(); 394 } catch (MailDisabledException | phpMailerException $exception) { 395 try { 396 Log::add(Text::_($exception->getMessage()), Log::WARNING, 'jerror'); 397 398 $this->setError(Text::_('COM_MESSAGES_ERROR_MAIL_FAILED')); 399 400 return false; 401 } catch (\RuntimeException $exception) { 402 Factory::getApplication()->enqueueMessage(Text::_($exception->errorMessage()), 'warning'); 403 404 $this->setError(Text::_('COM_MESSAGES_ERROR_MAIL_FAILED')); 405 406 return false; 407 } 408 } 409 } 410 411 return true; 412 } 413 414 /** 415 * Sends a message to the site's super users 416 * 417 * @param string $subject The message subject 418 * @param string $message The message 419 * 420 * @return boolean 421 * 422 * @since 3.9.0 423 */ 424 public function notifySuperUsers($subject, $message, $fromUser = null) 425 { 426 $db = $this->getDatabase(); 427 428 try { 429 /** @var Asset $table */ 430 $table = Table::getInstance('Asset'); 431 $rootId = $table->getRootId(); 432 433 /** @var Rule[] $rules */ 434 $rules = Access::getAssetRules($rootId)->getData(); 435 $rawGroups = $rules['core.admin']->getData(); 436 437 if (empty($rawGroups)) { 438 $this->setError(Text::_('COM_MESSAGES_ERROR_MISSING_ROOT_ASSET_GROUPS')); 439 440 return false; 441 } 442 443 $groups = array(); 444 445 foreach ($rawGroups as $g => $enabled) { 446 if ($enabled) { 447 $groups[] = $g; 448 } 449 } 450 451 if (empty($groups)) { 452 $this->setError(Text::_('COM_MESSAGES_ERROR_NO_GROUPS_SET_AS_SUPER_USER')); 453 454 return false; 455 } 456 457 $query = $db->getQuery(true) 458 ->select($db->quoteName('map.user_id')) 459 ->from($db->quoteName('#__user_usergroup_map', 'map')) 460 ->join( 461 'LEFT', 462 $db->quoteName('#__users', 'u'), 463 $db->quoteName('u.id') . ' = ' . $db->quoteName('map.user_id') 464 ) 465 ->whereIn($db->quoteName('map.group_id'), $groups) 466 ->where($db->quoteName('u.block') . ' = 0') 467 ->where($db->quoteName('u.sendEmail') . ' = 1'); 468 469 $userIDs = $db->setQuery($query)->loadColumn(0); 470 471 if (empty($userIDs)) { 472 $this->setError(Text::_('COM_MESSAGES_ERROR_NO_USERS_SET_AS_SUPER_USER')); 473 474 return false; 475 } 476 477 foreach ($userIDs as $id) { 478 /* 479 * All messages must have a valid from user, we have use cases where an unauthenticated user may trigger this 480 * so we will set the from user as the to user 481 */ 482 $data = [ 483 'user_id_from' => $id, 484 'user_id_to' => $id, 485 'subject' => $subject, 486 'message' => $message, 487 ]; 488 489 if (!$this->save($data)) { 490 return false; 491 } 492 } 493 494 return true; 495 } catch (\Exception $exception) { 496 $this->setError($exception->getMessage()); 497 498 return false; 499 } 500 } 501 }
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 |