You are here

class Messaging_Message in Messaging 6.4

Same name and namespace in other branches
  1. 6.3 classes/messaging_message.class.inc \Messaging_Message
  2. 7 messaging.message.inc \Messaging_Message

Message class

This is a message with all the information, ready for sending

Hierarchy

Expanded class hierarchy of Messaging_Message

2 string references to 'Messaging_Message'
messaging_message_build in ./messaging.module
Build message object from object or array
messaging_token_values in ./messaging.module
Implementation of hook_token_values()

File

includes/messaging_message.class.inc, line 26
Drupal Messaging Framework - Message class file

View source
class Messaging_Message extends Messaging_User_Object {

  // Value for destination when there are more destinations
  const MULTIPLE_DESTINATION = 'multiple';

  // Unique id
  public $mqid = 0;

  // Message type: outgoing, incoming
  public $type;

  // Sending method key: 'mail', 'sms', etc...
  public $method;

  // Don't forget inherited properties
  // Message destination, user uid
  // public $uid;
  // Message language
  // public $language;
  // Message source, mixed data
  public $source;

  // Sending method specific params
  public $params;

  // Real address for this message's method for single destination and destination object
  public $destination;

  // Destination id and destination object
  public $mdid;
  protected $_destination;

  // Array of multiple addresses, used when sending to multiple destinations.
  // In this case destination will be MULTIPLE_DESTINATION
  public $destinations;

  // Rendered message parts
  public $subject;
  public $body;

  // Files linked to this message, object array indexed by 'fid'
  public $files;

  // Not rendered subject and body parts
  public $parts;

  // Sender user id, will default to 0 (system) and user object
  public $sender;
  protected $_sender;

  // Sender name, will default to site name
  public $sender_name;

  // Sender address, depends on sending method, may be site address or sender address
  public $sender_address;

  // Optional sender user account, when sender is a system user. Internal storage only
  protected $sender_account;

  // Timestamps
  public $created;
  public $sent = 0;

  // Processing flags. They are 1 if the message is:
  public $queue = 0;

  // To be queued
  public $send = 0;

  // To be sent
  public $cron = 0;

  // To be processed on cron (queued)
  public $log = 0;

  // To be stored as log
  // Message priority. If > 0 it won't be queued.
  public $priority = 0;

  // Log when we've got an error, enabled as default
  public $log_error = TRUE;

  // Error code, error text
  public $error = 0;
  public $error_msg;

  // Message status. These should be persistent and handled by the storage method.
  public $built = FALSE;
  public $prepared = FALSE;
  public $rendered = FALSE;
  public $queued = FALSE;
  public $logged = FALSE;

  // Temporary processing variables. These are not stored
  public $processed = FALSE;

  // Preprocessed and ready for action (send, queue)
  public $process = TRUE;

  // Keep on processing
  public $result = TRUE;
  public $discard = FALSE;

  // Marked to be discarded
  public $redirect = FALSE;

  // Redirect to a different sending method
  public $retry = FALSE;

  // Retry sending
  public $success = TRUE;

  // Result of last operation
  public $deleted = FALSE;

  // The message has been deleted, though it's still around for whatever use
  public $updated = FALSE;

  // The message has been updated after being saved, needs to be saved again
  // Test message, not really for sending
  public $test = FALSE;

  // Serialized data for db_storage and unpack()
  public $data;

  /**
   * Constructor, with predefined array of data
   */
  function __construct($data = array()) {
    parent::__construct($data);
  }

  /**
   * Get list of persistent fields to store or serialize.
   *
   * @see _sleep()
   *
   * All these must be public properties so it can be handled by storage mechanisms.
   */
  public function data_fields() {
    return array(
      'mqid',
      'type',
      'method',
      'uid',
      'language',
      'source',
      'params',
      'mdid',
      'destination',
      'destinations',
      'subject',
      'body',
      'files',
      'parts',
      'sender',
      'sender_name',
      'sender_address',
      'created',
      'sent',
      'queue',
      'send',
      'log',
      'cron',
      'built',
      'prepared',
      'rendered',
      'queued',
      'logged',
      'priority',
      'log_error',
      'error',
      'error_msg',
    );
  }

  /**
   * Load from db
   */
  public static function load($mqid) {
    return messaging_store()
      ->message_load($mqid);
  }

  /**
   * Check parameters and go for alter hook
   */
  public function build() {
    if (empty($this->built)) {
      $this
        ->set_destination();

      // If message priority > 0 this is not to be queued
      if ($this->priority > 0) {
        $this->queue = 0;
      }

      // Provides a hook for other modules to modify the message before sending
      drupal_alter('messaging_message', $this);
      $this->built = TRUE;
    }
    return $this->built && !$this->discard;
  }

  /**
   * Prepare for sending through given method
   *
   * At this stage, message can be redirected to a different method
   */
  public function prepare() {
    if (empty($this->prepared)) {
      if ($this
        ->build()) {
        $this
          ->set_destination();

        // Prepare invoking one or more sending methods
        $this->prepared = $this
          ->process_method('message_prepare');
        messaging_debug("Prepared for send method.");
      }
      else {

        // Message building failed, we don't do anything else
        $this->prepared = FALSE;
        $this
          ->message_log("Failed message build.");
      }
    }
    return $this->prepared;
  }

  /**
   * Render through sending method
   */
  public function render() {
    $this
      ->prepare();
    if (empty($this->rendered)) {
      $this
        ->send_method()
        ->message_render($this);
      $this->rendered = time();
    }
  }

  /**
   * Send message through sending method.
   *
   * The message may need to be processed and it can be queued or discarded yet.
   */
  public function send($destination = NULL) {
    if (isset($destination)) {
      $this
        ->set_destination($destination);
    }
    if (!$this->processed) {
      return $this
        ->process();
    }
    else {

      // The message has been processed and it is for sending
      $this
        ->message_log('Sending message.');
      return $this
        ->send_method()
        ->message_send($this);
    }
  }

  /**
   * Send to multiple destinations, same method.
   *
   * The message may need to be processed and it can be queued or discarded yet.
   */
  function send_multiple($addresses = NULL, $method = NULL) {

    // Set parameters if needed, if not go with current ones
    if (isset($method)) {
      $this->method = $method;
    }
    if ($addresses) {
      $this
        ->set_multiple($addresses);
    }
    else {

      // Make sure it is marked as multiple destinations
      $this
        ->set_destination(self::MULTIPLE_DESTINATION);
    }
    if (!$this->processed) {
      return $this
        ->process();
    }
    else {
      $this
        ->message_log('Sending to multiple destinations.', array(
        'destinations' => $this->destinations,
      ));
      $this->success = $this
        ->send_method()
        ->message_multisend($this);
      return $this->success;
    }
  }

  /**
   * Queue message using the messaging store.
   *
   * This should happen only once per message, we check it hasn't been queued before.
   */
  public function queue() {
    $this->queue = 1;
    if (!$this->processed) {
      return $this
        ->process();
    }
    elseif (!$this->queued) {
      $this->queued = $this
        ->send_method()
        ->message_queue($this);
      $this
        ->send_method()
        ->message_afterqueue($this);
    }
    return $this->queued;
  }

  /**
   * Get send method object
   */
  public function send_method() {
    return !empty($this->method) ? messaging_send_method($this->method) : NULL;
  }

  /**
   * Check whether the message is to be sent / queued
   *
   * @return boolean
   *   True if it needs further processing
   */
  protected function process() {

    // Preprocess: Build and prepare if not done before
    if (!$this->processed) {
      if (!$this->discard && !$this->prepared) {
        $this
          ->prepare();
      }
    }

    // If everything is ok after preprocessing go for actual send/queue
    if ($this->prepared && !$this->discard && !$this->error) {

      // Mark as processed, so it is actually queued/sent
      $this->processed = TRUE;
      if ($this->test) {
        messaging_message_test($this);
        $this->success = TRUE;
      }
      elseif ($this->queue) {
        $this->success = $this
          ->queue();
        $this
          ->module_invoke('queued');
      }
      else {

        // Send to one or more destinations
        if ($this->destination == self::MULTIPLE_DESTINATION) {
          $this->success = $this
            ->send_multiple();
        }
        else {
          $this->success = $this
            ->send();
        }
        if ($this->success) {
          $message->sent = time();
        }
        $this
          ->send_method()
          ->message_aftersend($this);
        $this
          ->module_invoke('sent');
      }

      // Message done, maybe log and return
      $this
        ->done();
      return $this->success;
    }
    else {
      $this
        ->discard('Failed processing.');
      messaging_debug('Discarded message during processing.', array(
        'message' => $this,
      ));
      return FALSE;
    }
  }

  /**
   * Process through sending method
   *
   * This can go through multiple redirections, we stop it when we get to the same method again or process = FALSE
   */
  protected function process_method($operation) {
    if ($this
      ->send_method()) {
      $this->process = TRUE;
      $methods = array();

      // The send method can stop this by setting 'process' to FALSE or 'discard' to TRUE
      while ($this->process && !$this->discard && !in_array($this->method, $methods)) {
        $methods[] = $this->method;
        $this
          ->send_method()
          ->{$operation}($this);
      }
      return TRUE;
    }
    else {
      return FALSE;
    }
  }

  /**
   * Invoke hook_messaging_message() on all modules
   */
  protected function module_invoke($op) {
    return module_invoke_all('messaging_message', $op, $this);
  }

  /**
   * Discard message
   */
  function discard($reason = 'No reason.') {
    $this->success = FALSE;
    $this
      ->message_log('Message discarded during process', array(
      'reason' => $reason,
    ));
    $this
      ->delete();
  }

  /**
   * After the message has been processed
   */
  function done() {

    // Depending on parameters and what's happened so far we make the final queue/log decision
    if ($this->discard) {
      $this
        ->discard('Done processing');
    }
    if ($this->error || $this->log) {
      $this
        ->log();
    }
  }

  /**
   * Get method info
   */
  function method_info() {
    return messaging_method_info($this->method);
  }

  /**
   * Save to store if not saved yet or updated
   */
  function store() {
    if (empty($this->mqid) || $this->updated) {
      $this
        ->save();
    }
  }

  /**
   * Save to store / update
   */
  function save() {
    $result = messaging_store()
      ->message_save($this);
    if ($result) {
      $this->updated = FALSE;
    }
    else {
      $this
        ->set_error('The message cannot be saved.');
    }
  }

  /**
   * Create log for message
   */
  function log() {
    if (!$this->logged) {
      messaging_store()
        ->message_log($this);
      $this->logged = TRUE;
    }
  }

  /**
   * Set sender account and related properties
   *
   * @param $account
   *   Sender user account
   * @param $address
   *   Opational method's address for this account
   */
  function set_sender($account, $address = NULL) {
    $this->sender = $account->uid;
    $this->sender_name = $account->name;
    $this->_sender = $account;
    if (isset($address)) {
      $this->sender_address = $address;
    }
  }

  /**
   * Set destination object or figure out a destination if not set
   *
   * @param $destination
   *   Destination object, single address, or array of addresses
   */
  function set_destination($destination = NULL) {
    if (isset($destination)) {
      if (is_object($destination)) {
        $this->uid = $destination->uid;
        $this->destination = $destination->address;
        $this->mdid = $destination->mdid;
        $this->_destination = $destination;
      }
      else {

        // Set destination value but not destination object
        $this->destination = $destination;
        $this->mdid = 0;
        $this->_destination = FALSE;
      }
    }
    else {
      if (empty($this->method)) {

        // If we don't have a method we can get it from the user account
        $this->method = messaging_method_default($this
          ->get_user());
      }

      // If we've got a send method we can try filling the rest of the values
      if ($this
        ->send_method() && !isset($this->_destination)) {
        if (!empty($this->mdid) && ($destination = Messaging_Destination::load($this->mdid))) {
          return $this
            ->set_destination($destination);
        }
        elseif (empty($this->destination) && $this->uid && ($address = $this
          ->send_method()
          ->get_user_address($this
          ->get_user()))) {
          return $this
            ->set_destination($address);
        }
        else {
          return $this->_destination = FALSE;
        }
      }
    }
  }

  /**
   * Get destination object
   */
  function get_destination() {
    if (!isset($this->_destination)) {
      $this
        ->set_destination();
    }
    return $this->_destination;
  }

  /**
   * Set multiple sestinations
   *
   * @param $destinations
   *   Array of addresses
   */
  function set_multiple($destinations) {
    $this
      ->set_destination(self::MULTIPLE_DESTINATION);
    $this->destinations = $destinations;
  }

  /**
   * Set user object and related properties
   *
   * If not already set, method and destination will be searched for user account
   */
  function set_user($account) {
    parent::set_user($account);
    $this
      ->set_destination();

    // The send method can have some specific bits for user
    $this
      ->process_method('message_user');

    // Check we have method and address
    if (empty($this->method)) {
      $this
        ->set_error('Cannot find a suitable send method for this user.');
      return FALSE;
    }
    elseif (empty($this->destination)) {
      $this
        ->set_error('Cannot find a suitable address for this user.');
      return FALSE;
    }
    else {
      return !$this->discard;
    }
  }

  /**
   * Check we have a sending method and a destination
   *
   * @param $error
   *   Whether to mark this message as error if destination not ok
   */
  function check_destination($error = FALSE) {
    $this
      ->set_destination();
    return !empty($this->method) && !empty($this->destination);
  }

  /**
   * Add destination to the list
   *
   *
   */
  function add_destination($destination) {
    $this->destination = self::MULTIPLE_DESTINATION;

    // This will also de-dupe destinations
    $this->destinations[$destination
      ->index()] = $destination;
  }

  /**
   * Get addresses for this to be sent to
   */
  function get_addresses() {
    $this
      ->set_destination();
    $addresses = array();
    if (!empty($this->destination)) {
      if ($this->destination != self::MULTIPLE_DESTINATION) {
        $addresses[] = $this->destination;
      }
      elseif (!empty($this->destinations)) {
        foreach ($this->destinations as $destination) {
          $addresses[] = is_object($destination) ? $destination->address : $destination;
        }
      }
    }
    return $addresses;
  }

  /**
   * Get generic parameters
   */
  function get_params($key = NULL) {
    if ($key) {
      return isset($this->params[$key]) ? $this->params[$key] : array();
    }
    else {
      return isset($this->params) ? $this->params : array();
    }
  }

  /**
   * Get sending method parameters
   */
  function get_method_params($method = NULL) {
    $method = $method ? $method : $this->method;

    // First get specific parameters for this sending method
    $params = $this
      ->get_params($method);

    // Check for specific parameters for this method group
    if ($group = $this
      ->send_method()
      ->get_info('group')) {
      $params += $this
        ->get_params($group);
    }
    return $params;
  }

  /**
   * Delete if already on store
   */
  function delete() {
    if (!empty($this->mqid) && !$this->deleted) {
      $result = messaging_store()
        ->message_delete($this);
      $this->deleted = TRUE;
      return $result;
    }
  }

  /**
   * Set error condition and stop processing
   *
   * @param $text
   *   Error message to be stored
   */
  function set_error($text = 'ERROR', $code = 1) {

    // This will stop processing if we are in the middle of anything
    $this->process = FALSE;
    $this->success = FALSE;
    $this->error = $code;
    $this->error_msg = $text;
    $this
      ->message_log('Error processing message.');

    // By default, messages are set to be logged when errors happen
    if ($this->log_error) {
      $this->log = 1;
      $this->updated = TRUE;
    }
    elseif (!$this->log) {

      // Not for logging, discard
      $this->discard = TRUE;
    }
  }

  /**
   * Get sender account
   */
  function get_sender() {
    if (!isset($this->_sender)) {
      $sender = !empty($this->sender) ? messaging_load_user($this->sender) : NULL;
      $this->_sender = $sender ? $sender : FALSE;
    }
    return $this->_sender;
  }

  /**
   * Get sender name
   */
  function get_sender_name() {
    if (!empty($this->sender_name)) {
      return $this->sender_name;
    }
    elseif ($sender = $this
      ->get_sender()) {
      return check_plain($sender->name);
    }
    else {
      return variable_get('site_name', 'Drupal');
    }
  }

  /**
   * Get rendered subject
   */
  function get_subject() {
    $this
      ->render();
    return $this->subject;
  }

  /**
   * Get rendered body
   */
  function get_body() {
    $this
      ->render();
    return $this->body;
  }

  /**
   * Get message files
   */
  function get_files() {
    return !empty($this->files) ? $this->files : array();
  }

  /**
   * Build a simple text with message subject and body
   *
   * @param $glue
   *   Separator to glue subject and body together
   */
  function get_text($glue = ' ') {
    $parts = array(
      trim($this
        ->get_subject()),
      trim($this
        ->get_body()),
    );
    $parts = array_filter($parts);
    $text = $parts ? implode($glue, $parts) : '';
    return $text;
  }

  /**
   * Log message with some data
   */
  protected function message_log($text, $variables = array()) {
    messaging_log($text, $variables + array(
      'message' => (string) $this,
    ));
  }

  // Magic function, format as string
  public function __toString() {
    $subject = !empty($this->subject) ? check_plain($this->subject) : '<none>';
    $method = !empty($this->method) ? $this->method : '<none>';
    $destination = !empty($this->destination) ? $this->destination : '<none>';
    $text = "Message: method= {$method}, destination= {$destination}, subject= {$subject}";
    if (!empty($this->error)) {
      $text .= " error={$this->error}, {$this->error_msg}";
    }
    return $text;
  }

  /**
   * Magic method, set protected properties
   *
   * Warning: This also runs for unset properties
   */
  public function __set($name, $value) {
    switch ($name) {
      case 'sender_account':
        $this->_sender = $value;
        if (!isset($this->sender)) {
          $this->sender = $value ? $value->uid : 0;
        }
        break;
      case 'destination':
        if (is_array($value)) {
          $this
            ->set_multiple($value);
        }
        else {
          $this
            ->set_destination($value);
        }
        break;
      case 'user':
      case 'account':
        $this
          ->set_user($value);
        break;
      default:

        // For unset fields, though they're public, when there's a __set function it is called too
        // When creating records, serial fields are unset() by drupal_write_record
        $this->{$name} = $value;
        break;
    }
  }

  /**
   * Magic method, get protected properties
   */
  public function __get($name) {
    switch ($name) {
      case 'sender_account':
        return $this
          ->get_sender();
      case 'user':
      case 'account':
        return $this
          ->get_user();
    }
  }

  /**
   * Magic method, isset protected properties
   */
  public function __isset($name) {
    switch ($name) {
      case 'destination':
      case 'user':
        return !empty($this->{$name});
    }
  }

  // Magic function, returns the properties names that will be serialized
  public function __sleep() {
    return $this
      ->data_fields();
  }

}

Members

Namesort descending Modifiers Type Description Overrides
Messaging_Message::$body public property
Messaging_Message::$built public property
Messaging_Message::$created public property
Messaging_Message::$cron public property
Messaging_Message::$data public property
Messaging_Message::$deleted public property
Messaging_Message::$destination public property
Messaging_Message::$destinations public property
Messaging_Message::$discard public property
Messaging_Message::$error public property
Messaging_Message::$error_msg public property
Messaging_Message::$files public property
Messaging_Message::$log public property
Messaging_Message::$logged public property
Messaging_Message::$log_error public property
Messaging_Message::$mdid public property
Messaging_Message::$method public property
Messaging_Message::$mqid public property
Messaging_Message::$params public property
Messaging_Message::$parts public property
Messaging_Message::$prepared public property
Messaging_Message::$priority public property
Messaging_Message::$process public property
Messaging_Message::$processed public property
Messaging_Message::$queue public property
Messaging_Message::$queued public property
Messaging_Message::$redirect public property
Messaging_Message::$rendered public property
Messaging_Message::$result public property
Messaging_Message::$retry public property
Messaging_Message::$send public property
Messaging_Message::$sender public property
Messaging_Message::$sender_account protected property
Messaging_Message::$sender_address public property
Messaging_Message::$sender_name public property
Messaging_Message::$sent public property
Messaging_Message::$source public property
Messaging_Message::$subject public property
Messaging_Message::$success public property
Messaging_Message::$test public property
Messaging_Message::$type public property
Messaging_Message::$updated public property
Messaging_Message::$_destination protected property
Messaging_Message::$_sender protected property
Messaging_Message::add_destination function Add destination to the list
Messaging_Message::build public function Check parameters and go for alter hook
Messaging_Message::check_destination function Check we have a sending method and a destination
Messaging_Message::data_fields public function Get list of persistent fields to store or serialize.
Messaging_Message::delete function Delete if already on store
Messaging_Message::discard function Discard message
Messaging_Message::done function After the message has been processed
Messaging_Message::get_addresses function Get addresses for this to be sent to
Messaging_Message::get_body function Get rendered body
Messaging_Message::get_destination function Get destination object
Messaging_Message::get_files function Get message files
Messaging_Message::get_method_params function Get sending method parameters
Messaging_Message::get_params function Get generic parameters
Messaging_Message::get_sender function Get sender account
Messaging_Message::get_sender_name function Get sender name
Messaging_Message::get_subject function Get rendered subject
Messaging_Message::get_text function Build a simple text with message subject and body
Messaging_Message::load public static function Load from db
Messaging_Message::log function Create log for message
Messaging_Message::message_log protected function Log message with some data
Messaging_Message::method_info function Get method info
Messaging_Message::module_invoke protected function Invoke hook_messaging_message() on all modules
Messaging_Message::MULTIPLE_DESTINATION constant
Messaging_Message::prepare public function Prepare for sending through given method
Messaging_Message::process protected function Check whether the message is to be sent / queued
Messaging_Message::process_method protected function Process through sending method
Messaging_Message::queue public function Queue message using the messaging store.
Messaging_Message::render public function Render through sending method
Messaging_Message::save function Save to store / update
Messaging_Message::send public function Send message through sending method.
Messaging_Message::send_method public function Get send method object
Messaging_Message::send_multiple function Send to multiple destinations, same method.
Messaging_Message::set_destination function Set destination object or figure out a destination if not set
Messaging_Message::set_error function Set error condition and stop processing
Messaging_Message::set_multiple function Set multiple sestinations
Messaging_Message::set_sender function Set sender account and related properties
Messaging_Message::set_user function Set user object and related properties
Messaging_Message::store function Save to store if not saved yet or updated
Messaging_Message::__construct function Constructor, with predefined array of data
Messaging_Message::__get public function Magic method, get protected properties
Messaging_Message::__isset public function Magic method, isset protected properties
Messaging_Message::__set public function Magic method, set protected properties
Messaging_Message::__sleep public function
Messaging_Message::__toString public function