[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/classes/message/ -> manager.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * New messaging manager class.
  19   *
  20   * @package   core_message
  21   * @since     Moodle 2.8
  22   * @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
  23   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   * @author    Petr Skoda <petr.skoda@totaralms.com>
  25   */
  26  
  27  namespace core\message;
  28  
  29  defined('MOODLE_INTERNAL') || die();
  30  
  31  /**
  32   * Class used for various messaging related stuff.
  33   *
  34   * Note: Do NOT use directly in your code, it is intended to be used from core code only.
  35   *
  36   * @access private
  37   *
  38   * @package   core_message
  39   * @since     Moodle 2.8
  40   * @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
  41   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   * @author    Petr Skoda <petr.skoda@totaralms.com>
  43   */
  44  class manager {
  45      /** @var array buffer of pending messages */
  46      protected static $buffer = array();
  47  
  48      /**
  49       * Do the message sending.
  50       *
  51       * NOTE: to be used from message_send() only.
  52       *
  53       * @param \stdClass|\core\message\message $eventdata fully prepared event data for processors
  54       * @param \stdClass $savemessage the message saved in 'message' table
  55       * @param array $processorlist list of processors for target user
  56       * @return int $messageid the id from 'message' or 'message_read' table (false is not returned)
  57       */
  58      public static function send_message($eventdata, \stdClass $savemessage, array $processorlist) {
  59          global $CFG;
  60  
  61          if (!($eventdata instanceof \stdClass) && !($eventdata instanceof message)) {
  62              // Not a valid object.
  63              throw new \coding_exception('Message should be of type stdClass or \core\message\message');
  64          }
  65  
  66          require_once($CFG->dirroot.'/message/lib.php'); // This is most probably already included from messagelib.php file.
  67  
  68          if (empty($processorlist)) {
  69              // Trigger event for sending a message - we need to do this before marking as read!
  70              \core\event\message_sent::create_from_ids($eventdata->userfrom->id, $eventdata->userto->id, $savemessage->id)->trigger();
  71  
  72              if ($savemessage->notification or empty($CFG->messaging)) {
  73                  // If they have deselected all processors and its a notification mark it read. The user doesn't want to be bothered.
  74                  // The same goes if the messaging is completely disabled.
  75                  // We cannot insert directly to the message_read table because we want to get all events in proper order!
  76                  $messageid = message_mark_message_read($savemessage, time(), true);
  77  
  78              } else {
  79                  // Just add it to the list of unread messages, there is no way it could be delivered to them,
  80                  // but they can read it via the messaging UI later.
  81                  $messageid = $savemessage->id;
  82              }
  83  
  84              return $messageid;
  85          }
  86  
  87          // Let the manager do the sending or buffering when db transaction in progress.
  88          return self::send_message_to_processors($eventdata, $savemessage, $processorlist);
  89      }
  90  
  91      /**
  92       * Send message to message processors.
  93       *
  94       * @param \stdClass|\core\message\message $eventdata
  95       * @param \stdClass $savemessage
  96       * @param array $processorlist
  97       * @return int $messageid
  98       */
  99      protected static function send_message_to_processors($eventdata, \stdClass $savemessage, array
 100      $processorlist) {
 101          global $CFG, $DB;
 102  
 103          // We cannot communicate with external systems in DB transactions,
 104          // buffer the messages if necessary.
 105  
 106          if ($DB->is_transaction_started()) {
 107              // We need to clone all objects so that devs may not modify it from outside later.
 108              $eventdata = clone($eventdata);
 109              $eventdata->userto = clone($eventdata->userto);
 110              $eventdata->userfrom = clone($eventdata->userfrom);
 111  
 112              // Conserve some memory the same was as $USER setup does.
 113              unset($eventdata->userto->description);
 114              unset($eventdata->userfrom->description);
 115  
 116              self::$buffer[] = array($eventdata, $savemessage, $processorlist);
 117              return $savemessage->id;
 118          }
 119  
 120          $processors = get_message_processors(true);
 121  
 122          $failed = false;
 123          foreach ($processorlist as $procname) {
 124              // Let new messaging class add custom content based on the processor.
 125              $proceventdata = ($eventdata instanceof message) ? $eventdata->get_eventobject_for_processor($procname) : $eventdata;
 126              if (!$processors[$procname]->object->send_message($proceventdata)) {
 127                  debugging('Error calling message processor ' . $procname);
 128                  $failed = true;
 129                  // Previously the $messageid = false here was overridden
 130                  // by other processors and message_mark_message_read() below.
 131              }
 132          }
 133  
 134          // Trigger event for sending a message - must be done before marking as read.
 135          \core\event\message_sent::create_from_ids($eventdata->userfrom->id, $eventdata->userto->id, $savemessage->id)->trigger();
 136  
 137          if (empty($CFG->messaging)) {
 138              // If messaging is disabled and they previously had forum notifications handled by the popup processor
 139              // or any processor that puts a row in message_working then the notification will remain forever
 140              // unread. To prevent this mark the message read if messaging is disabled.
 141              $messageid = message_mark_message_read($savemessage, time());
 142  
 143          } else if ($failed) {
 144              // Something failed, better keep it as unread then.
 145              $messageid = $savemessage->id;
 146  
 147          } else if ($DB->count_records('message_working', array('unreadmessageid' => $savemessage->id)) == 0) {
 148              // If there is no more processors that want to process this we can move message to message_read.
 149              $messageid = message_mark_message_read($savemessage, time(), true);
 150  
 151          } else {
 152              // Some processor is still working on the data, let's keep it unread.
 153              $messageid = $savemessage->id;
 154          }
 155  
 156          return $messageid;
 157      }
 158  
 159      /**
 160       * Notification from DML layer.
 161       *
 162       * Note: to be used from DML layer only.
 163       */
 164      public static function database_transaction_commited() {
 165          if (!self::$buffer) {
 166              return;
 167          }
 168          self::process_buffer();
 169      }
 170  
 171      /**
 172       * Notification from DML layer.
 173       *
 174       * Note: to be used from DML layer only.
 175       */
 176      public static function database_transaction_rolledback() {
 177          self::$buffer = array();
 178      }
 179  
 180      /**
 181       * Sent out any buffered messages if necessary.
 182       */
 183      protected static function process_buffer() {
 184          // Reset the buffer first in case we get exception from processor.
 185          $messages = self::$buffer;
 186          self::$buffer = array();
 187  
 188          foreach ($messages as $message) {
 189              list($eventdata, $savemessage, $processorlist) = $message;
 190              self::send_message_to_processors($eventdata, $savemessage, $processorlist);
 191          }
 192      }
 193  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1