Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.
   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   * Variable Envelope Return Path management.
  19   *
  20   * @package    core_message
  21   * @copyright  2014 Andrew Nicols <andrew@nicols.co.uk>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace core\message\inbound;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  /**
  30   * Variable Envelope Return Path manager class.
  31   *
  32   * @copyright  2014 Andrew Nicols <andrew@nicols.co.uk>
  33   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  34   */
  35  class manager {
  36  
  37      /**
  38       * Whether the Inbound Message interface is enabled.
  39       *
  40       * @return bool
  41       */
  42      public static function is_enabled() {
  43          global $CFG;
  44  
  45          // Check whether Inbound Message is enabled at all.
  46          if (!isset($CFG->messageinbound_enabled) || !$CFG->messageinbound_enabled) {
  47              return false;
  48          }
  49  
  50          // Check whether the outgoing mailbox and domain are configured properly.
  51          if (!isset($CFG->messageinbound_mailbox) || empty($CFG->messageinbound_mailbox)) {
  52              return false;
  53          }
  54  
  55          if (!isset($CFG->messageinbound_domain) || empty($CFG->messageinbound_domain)) {
  56              return false;
  57          }
  58  
  59          return true;
  60      }
  61  
  62      /**
  63       * Update the database to create, update, and remove handlers.
  64       *
  65       * @param string $componentname - The frankenstyle component name.
  66       */
  67      public static function update_handlers_for_component($componentname) {
  68          global $DB;
  69  
  70          $componentname = \core_component::normalize_componentname($componentname);
  71          $existinghandlers = $DB->get_recordset('messageinbound_handlers', array('component' => $componentname));
  72          foreach ($existinghandlers as $handler) {
  73              if (!class_exists($handler->classname)) {
  74                  self::remove_messageinbound_handler($handler);
  75              }
  76          }
  77          $existinghandlers->close();
  78  
  79          self::create_missing_messageinbound_handlers_for_component($componentname);
  80      }
  81  
  82      /**
  83       * Load handler instances for all of the handlers defined in db/messageinbound_handlers.php for the specified component.
  84       *
  85       * @param string $componentname - The name of the component to fetch the handlers for.
  86       * @return \core\message\inbound\handler[] - List of handlers for this component.
  87       */
  88      public static function load_default_handlers_for_component($componentname) {
  89          $componentname = \core_component::normalize_componentname($componentname);
  90          $dir = \core_component::get_component_directory($componentname);
  91  
  92          if (!$dir) {
  93              return array();
  94          }
  95  
  96          $file = $dir . '/db/messageinbound_handlers.php';
  97          if (!file_exists($file)) {
  98              return array();
  99          }
 100  
 101          $handlers = null;
 102          require_once($file);
 103  
 104          if (!isset($handlers)) {
 105              return array();
 106          }
 107  
 108          $handlerinstances = array();
 109  
 110          foreach ($handlers as $handler) {
 111              $record = (object) $handler;
 112              $record->component = $componentname;
 113              if ($handlerinstance = self::handler_from_record($record)) {
 114                  $handlerinstances[] = $handlerinstance;
 115              } else {
 116                  throw new \coding_exception("Inbound Message Handler not found for '{$componentname}'.");
 117              }
 118          }
 119  
 120          return $handlerinstances;
 121      }
 122  
 123      /**
 124       * Update the database to contain a list of handlers for a component,
 125       * adding any handlers which do not exist in the database.
 126       *
 127       * @param string $componentname - The frankenstyle component name.
 128       */
 129      public static function create_missing_messageinbound_handlers_for_component($componentname) {
 130          global $DB;
 131          $componentname = \core_component::normalize_componentname($componentname);
 132  
 133          $expectedhandlers = self::load_default_handlers_for_component($componentname);
 134          foreach ($expectedhandlers as $handler) {
 135              $recordexists = $DB->record_exists('messageinbound_handlers', array(
 136                  'component' => $componentname,
 137                  'classname' => $handler->classname,
 138              ));
 139  
 140              if (!$recordexists) {
 141                  $record = self::record_from_handler($handler);
 142                  $record->component = $componentname;
 143                  $DB->insert_record('messageinbound_handlers', $record);
 144              }
 145          }
 146      }
 147  
 148      /**
 149       * Remove the specified handler.
 150       *
 151       * @param \core\message\inbound\handler $handler The handler to remove
 152       */
 153      public static function remove_messageinbound_handler($handler) {
 154          global $DB;
 155  
 156          // Delete Inbound Message datakeys.
 157          $DB->delete_records('messageinbound_datakeys', array('handler' => $handler->id));
 158  
 159          // Delete Inbound Message handlers.
 160          $DB->delete_records('messageinbound_handlers', array('id' => $handler->id));
 161      }
 162  
 163      /**
 164       * Create a flat stdClass for the handler, appropriate for inserting
 165       * into the database.
 166       *
 167       * @param \core\message\inbound\handler $handler The handler to retrieve the record for.
 168       * @return \stdClass
 169       */
 170      public static function record_from_handler($handler) {
 171          $record = new \stdClass();
 172          $record->id = $handler->id;
 173          $record->component = $handler->component;
 174          $record->classname = get_class($handler);
 175          if (strpos($record->classname, '\\') !== 0) {
 176              $record->classname = '\\' . $record->classname;
 177          }
 178          $record->defaultexpiration = $handler->defaultexpiration;
 179          $record->validateaddress = $handler->validateaddress;
 180          $record->enabled = $handler->enabled;
 181  
 182          return $record;
 183      }
 184  
 185      /**
 186       * Load the Inbound Message handler details for a given record.
 187       *
 188       * @param \stdClass $record The record to retrieve the handler for.
 189       * @return \core\message\inbound\handler or false
 190       */
 191      protected static function handler_from_record($record) {
 192          $classname = $record->classname;
 193          if (strpos($classname, '\\') !== 0) {
 194              $classname = '\\' . $classname;
 195          }
 196          if (!class_exists($classname)) {
 197              return false;
 198          }
 199  
 200          $handler = new $classname;
 201          if (isset($record->id)) {
 202              $handler->set_id($record->id);
 203          }
 204          $handler->set_component($record->component);
 205  
 206          // Overload fields which can be modified.
 207          if (isset($record->defaultexpiration)) {
 208              $handler->set_defaultexpiration($record->defaultexpiration);
 209          }
 210  
 211          if (isset($record->validateaddress)) {
 212              $handler->set_validateaddress($record->validateaddress);
 213          }
 214  
 215          if (isset($record->enabled)) {
 216              $handler->set_enabled($record->enabled);
 217          }
 218  
 219          return $handler;
 220      }
 221  
 222      /**
 223       * Load the Inbound Message handler details for a given classname.
 224       *
 225       * @param string $classname The name of the class for the handler.
 226       * @return \core\message\inbound\handler or false
 227       */
 228      public static function get_handler($classname) {
 229          global $DB;
 230  
 231          if (strpos($classname, '\\') !== 0) {
 232              $classname = '\\' . $classname;
 233          }
 234  
 235          $record = $DB->get_record('messageinbound_handlers', array('classname' => $classname), '*', IGNORE_MISSING);
 236          if (!$record) {
 237              return false;
 238          }
 239          return self::handler_from_record($record);
 240      }
 241  
 242      /**
 243       * Load the Inbound Message handler with a given ID
 244       *
 245       * @param int $id
 246       * @return \core\message\inbound\handler or false
 247       */
 248      public static function get_handler_from_id($id) {
 249          global $DB;
 250  
 251          $record = $DB->get_record('messageinbound_handlers', array('id' => $id), '*', IGNORE_MISSING);
 252          if (!$record) {
 253              return false;
 254          }
 255          return self::handler_from_record($record);
 256      }
 257  
 258  }