/**
  * generates an EE_Message using the supplied arguments and some defaults
  *
  * @param array $properties
  * @return EE_Message
  * @throws \EE_Error
  */
 protected function _generate_message($properties = array())
 {
     // a message was generated immediately but the parent class will call this again
     if ($this->_message instanceof EE_Message) {
         return $this->_message;
     }
     $message = EEM_Message::instance()->get_one_by_token($this->token);
     if (!$message instanceof EE_Message) {
         throw new EE_Error(sprintf(__('Unable to retrieve generated message from DB using given token: "%1$s"', 'event_espresso'), $this->token));
     }
     $message->set_STS_ID(EEM_Message::status_idle);
     if (!$this->_sending_messenger instanceof EE_messenger) {
         $message->set_STS_ID(EEM_Message::status_failed);
         $message->set_error_message(sprintf(__('Unable to send message because the "%1$s" messenger is not active or not installed', 'event_espresso'), $this->_sending_messenger));
     }
     //set properties
     $this->_valid = true;
     $this->_messenger = $message->messenger_object();
     $this->_message_type = $message->message_type_object();
     $this->_send_now = $message->send_now();
     return $message;
 }
 /**
  * This accepts an array of EE_Message::MSG_ID values and will use that to retrieve the objects from the database
  * and send.
  * @param array $message_ids
  */
 public function setup_messages_from_ids_and_send($message_ids)
 {
     $this->_init_queue_and_generator();
     $messages = EEM_Message::instance()->get_all(array(array('MSG_ID' => array('IN', $message_ids), 'STS_ID' => array('IN', array_merge(EEM_Message::instance()->stati_indicating_sent(), array(EEM_Message::status_retry))))));
     //set the Messages to resend.
     foreach ($messages as $message) {
         if ($message instanceof EE_Message) {
             $message->set_STS_ID(EEM_Message::status_resend);
             $this->_queue->add($message);
         }
     }
     $this->_queue->initiate_request_by_priority('send');
 }
 /**
  * Retrieve the EE_Message objects for the list table.
  *
  * @param int    $perpage The number of items per page
  * @param string $view    The view items are being retrieved for
  * @param bool   $count   Whether to just return a count or not.
  * @param bool   $all     Disregard any paging info (no limit on data returned).
  * @return int | EE_Message[]
  * @throws \EE_Error
  */
 protected function _get_messages($perpage = 10, $view = 'all', $count = false, $all = false)
 {
     $current_page = isset($this->_req_data['paged']) && !empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
     $per_page = isset($this->_req_data['perpage']) && !empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $perpage;
     $offset = ($current_page - 1) * $per_page;
     $limit = $all || $count ? null : array($offset, $per_page);
     $query_params = array('order_by' => empty($this->_req_data['orderby']) ? 'MSG_modified' : $this->_req_data['orderby'], 'order' => empty($this->_req_data['order']) ? 'DESC' : $this->_req_data['order'], 'limit' => $limit);
     /**
      * Any filters coming in from other routes?
      */
     if (isset($this->_req_data['filterby'])) {
         $query_params = array_merge($query_params, EEM_Message::instance()->filter_by_query_params());
         if (!$count) {
             $query_params['group_by'] = 'MSG_ID';
         }
     }
     //view conditionals
     if ($view !== 'all' && $count && $all) {
         $query_params[0]['AND*view_conditional'] = array('STS_ID' => strtoupper($view));
     }
     if (!$all && !empty($this->_req_data['status']) && $this->_req_data['status'] !== 'all') {
         $query_params[0]['AND*view_conditional'] = array('STS_ID' => strtoupper($this->_req_data['status']));
     }
     if (!$all && !empty($this->_req_data['s'])) {
         $search_string = '%' . $this->_req_data['s'] . '%';
         $query_params[0]['OR'] = array('MSG_to' => array('LIKE', $search_string), 'MSG_from' => array('LIKE', $search_string), 'MSG_subject' => array('LIKE', $search_string), 'MSG_content' => array('LIKE', $search_string));
     }
     //account for debug only status.  We don't show Messages with the EEM_Message::status_debug_only to clients when
     //the messages system is in debug mode.
     //Note: for backward compat with previous iterations, this is necessary because there may be EEM_Message::status_debug_only
     //messages in the database.
     if (!EEM_Message::debug()) {
         $query_params[0]['AND*debug_only_conditional'] = array('STS_ID' => array('!=', EEM_Message::status_debug_only));
     }
     //account for filters
     if (!$all && isset($this->_req_data['ee_messenger_filter_by']) && $this->_req_data['ee_messenger_filter_by'] !== 'none_selected') {
         $query_params[0]['AND*messenger_filter'] = array('MSG_messenger' => $this->_req_data['ee_messenger_filter_by']);
     }
     if (!$all && !empty($this->_req_data['ee_message_type_filter_by']) && $this->_req_data['ee_message_type_filter_by'] !== 'none_selected') {
         $query_params[0]['AND*message_type_filter'] = array('MSG_message_type' => $this->_req_data['ee_message_type_filter_by']);
     }
     if (!$all && !empty($this->_req_data['ee_context_filter_by']) && $this->_req_data['ee_context_filter_by'] !== 'none_selected') {
         $query_params[0]['AND*context_filter'] = array('MSG_context' => array('IN', explode(',', $this->_req_data['ee_context_filter_by'])));
     }
     return $count ? EEM_Message::instance()->count($query_params, null, true) : EEM_Message::instance()->get_all($query_params);
 }
 /**
  * Deletes EE_messages for IDs in the request.
  *
  * @since 4.9.0
  */
 protected function _delete_ee_messages()
 {
     $msg_ids = $this->_get_msg_ids_from_request();
     $deleted_count = 0;
     foreach ($msg_ids as $msg_id) {
         if (EEM_Message::instance()->delete_by_ID($msg_id)) {
             $deleted_count++;
         }
     }
     if ($deleted_count) {
         $this->_redirect_after_action(true, _n('message', 'messages', $deleted_count, 'event_espresso'), __('deleted', 'event_espresso'));
     } else {
         EE_Error::add_error(_n('The message was not deleted.', 'The messages were not deleted', count($msg_ids), 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         $this->_redirect_after_action(false, '', '', array(), true);
     }
 }
 /**
  *  This iterates through the provided queue and generates the EE_Message objects.
  *  When iterating through the queue, the queued item that served as the base for generating other EE_Message objects
  *  gets removed and the new EE_Message objects get added to a NEW queue.  The NEW queue is then returned for the
  *  caller to decide what to do with it.
  *
  * @param   bool    $save   Whether to save the EE_Message objects in the new queue or just return.
  *
  * @return EE_Messages_Queue  The new queue for holding generated EE_Message objects.
  */
 public function generate($save = true)
 {
     //iterate through the messages in the queue, generate, and add to new queue.
     $this->_generation_queue->get_message_repository()->rewind();
     while ($this->_generation_queue->get_message_repository()->valid()) {
         //reset "current" properties
         $this->_reset_current_properties();
         /** @type EE_Message $msg */
         $msg = $this->_generation_queue->get_message_repository()->current();
         /**
          * need to get the next object and capture it for setting manually after deletes.  The reason is that when
          * an object is removed from the repo then valid for the next object will fail.
          */
         $this->_generation_queue->get_message_repository()->next();
         $next_msg = $this->_generation_queue->get_message_repository()->current();
         //restore pointer to current item
         $this->_generation_queue->get_message_repository()->set_current($msg);
         //skip and delete if the current $msg is NOT incomplete (queued for generation)
         if ($msg->STS_ID() !== EEM_Message::status_incomplete) {
             //we keep this item in the db just remove from the repo.
             $this->_generation_queue->get_message_repository()->remove($msg);
             //next item
             $this->_generation_queue->get_message_repository()->set_current($next_msg);
             continue;
         }
         if ($this->_verify()) {
             //let's get generating!
             $this->_generate();
         }
         //don't persist debug_only messages if the messages system is not in debug mode.
         if ($msg->STS_ID() === EEM_Message::status_debug_only && !EEM_Message::debug()) {
             $this->_generation_queue->get_message_repository()->delete();
             $this->_generation_queue->get_message_repository()->set_current($next_msg);
             continue;
         }
         //if there are error messages then let's set the status and the error message.
         if ($this->_error_msg) {
             //if the status is already debug only, then let's leave it at that.
             if ($msg->STS_ID() !== EEM_Message::status_debug_only) {
                 $msg->set_STS_ID(EEM_Message::status_failed);
             }
             $msg->set_error_message(__('Message failed to generate for the following reasons: ') . "\n" . implode("\n", $this->_error_msg));
             $msg->set_modified(time());
         } else {
             //remove from db
             $this->_generation_queue->get_message_repository()->delete();
         }
         //next item
         $this->_generation_queue->get_message_repository()->set_current($next_msg);
     }
     //generation queue is ALWAYS saved to record any errors in the generation process.
     $this->_generation_queue->save();
     /**
      * save _ready_queue if flag set.
      * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method.  This
      * means if a field was added that is not a valid database column.  The EE_Message was already saved to the db
      * so a EE_Extra_Meta entry could be created and attached to the EE_Message.  In those cases the save flag is
      * irrelevant.
      */
     if ($save) {
         $this->_ready_queue->save();
     }
     //final reset of properties
     $this->_reset_current_properties();
     return $this->_ready_queue;
 }
    /**
     * Sends messages immediately for the incoming message_ids that have the status of EEM_Message::status_resend or,
     * EEM_Message::status_idle
     *
     * @since 4.9.0
     * @param $message_ids
     *
     * @return bool | EE_Messages_Queue  false if no messages sent.
     */
    public static function send_now($message_ids)
    {
        self::_load_controller();
        $messages = EEM_Message::instance()->get_all(array(0 => array('MSG_ID' => array('IN', $message_ids), 'STS_ID' => array('IN', array(EEM_Message::status_idle, EEM_Message::status_resend, EEM_Message::status_retry)))));
        $sent_queue = false;
        if ($messages) {
            $sent_queue = self::$_MSG_PROCESSOR->batch_send_from_queue($messages);
        }
        if (!$sent_queue instanceof EE_Messages_Queue) {
            EE_Error::add_error(__('The messages were not sent. This could mean there is already a batch being sent on a separate request, or because the selected messages are not sendable. Please wait a minute or two and try again.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
        } else {
            //can count how many sent by using the messages in the queue
            $sent_count = $sent_queue->count_STS_in_queue(EEM_Message::instance()->stati_indicating_sent());
            if ($sent_count > 0) {
                EE_Error::add_success(sprintf(_n('There was %d message successfully sent.', 'There were %d messages successfully sent.', $sent_count, 'event_espresso'), $sent_count));
            } else {
                EE_Error::overwrite_errors();
                EE_Error::add_error(__('No message was sent because of problems with sending. Either all the messages you selected were not a sendable message, they were ALREADY sent on a different scheduled task, or there was an error.
					If there was an error, you can look at the messages in the message activity list table for any error messages.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
            }
        }
        return $sent_queue;
    }
 /**
  * This sets any necessary error messages on the message object and its status to failed.
  * @param EE_Message $message
  * @param array      $error_messages the response from the messenger.
  */
 protected function _set_error_message(EE_Message $message, $error_messages)
 {
     $error_messages = (array) $error_messages;
     if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
         $notices = EE_Error::has_notices();
         $error_messages[] = __('Messenger and Message Type were valid and active, but the messenger send method failed.', 'event_espresso');
         if ($notices === 1) {
             $notices = EE_Error::get_vanilla_notices();
             $notices['errors'] = isset($notices['errors']) ? $notices['errors'] : array();
             $error_messages[] = implode("\n", $notices['errors']);
         }
     }
     if (count($error_messages) > 0) {
         $msg = __('Message was not executed successfully.', 'event_espresso');
         $msg = $msg . "\n" . implode("\n", $error_messages);
         $message->set_error_message($msg);
     }
 }