IMP_Compose::replyMessage PHP Method

replyMessage() public method

Determines the reply text and headers for a message.
public replyMessage ( integer $type, IMP_Contents $contents, array $opts = [] ) : array
$type integer The reply type (self::REPLY* constant).
$contents IMP_Contents An IMP_Contents object.
$opts array Additional options: - format: (string) Force to this format. DEFAULT: Auto-determine. - to: (string) The recipient of the reply. Overrides the automatically determined value.
return array An array with the following keys: - addr: (array) Address lists (to, cc, bcc; Horde_Mail_Rfc822_List objects). - body: (string) The text of the body part. - format: (string) The format of the body message (html, text). - identity: (integer) The identity to use for the reply based on the original message's addresses. - lang: (array) Language code (keys)/language name (values) of the original sender's preferred language(s). - reply_list_id: (string) List ID label. - reply_recip: (integer) Number of recipients in reply list. - subject: (string) Formatted subject. - type: (integer) The reply type used (either self::REPLY_ALL, self::REPLY_LIST, or self::REPLY_SENDER).
    public function replyMessage($type, $contents, array $opts = array())
    {
        global $injector, $language, $prefs;
        if (!$contents instanceof IMP_Contents) {
            throw new IMP_Exception(_("Could not retrieve message data from the mail server."));
        }
        $alist = new Horde_Mail_Rfc822_List();
        $addr = array('to' => clone $alist, 'cc' => clone $alist, 'bcc' => clone $alist);
        $h = $contents->getHeader();
        $match_identity = $this->_getMatchingIdentity($h);
        $reply_type = self::REPLY_SENDER;
        if (!$this->_replytype) {
            $this->_setMetadata('indices', $contents->getIndicesOb());
            /* Set the Message-ID related headers (RFC 5322 [3.6.4]). */
            if ($tmp = $h['Message-ID']) {
                $msg_id = $tmp->getIdentificationOb();
                $msg_id = reset($msg_id->ids);
                if (strlen($msg_id)) {
                    $this->_setMetadata('in_reply_to', $msg_id);
                }
            } else {
                $msg_id = null;
            }
            if ($tmp = $h['References']) {
                $ref_ob = $tmp->getIdentificationOb();
                if (!count($ref_ob->ids) && ($tmp = $h['In-Reply-To'])) {
                    $ref_ob = $tmp->getIdentificationOb();
                    if (count($ref_ob->ids) > 1) {
                        $ref_ob->ids = array();
                    }
                }
                if (count($ref_ob->ids)) {
                    $this->_setMetadata('references', array_merge($ref_ob->ids, array_filter(array($msg_id))));
                }
            }
        }
        $subject = strlen($s = $h['Subject']) ? 'Re: ' . strval(new Horde_Imap_Client_Data_BaseSubject($s, array('keepblob' => true))) : 'Re: ';
        $force = false;
        if (in_array($type, array(self::REPLY_AUTO, self::REPLY_SENDER))) {
            if (isset($opts['to'])) {
                $addr['to']->add($opts['to']);
                $force = true;
            } elseif ($tmp = $h['reply-to']) {
                $addr['to']->add($tmp->getAddressList());
                $force = true;
            } elseif ($tmp = $h['from']) {
                $addr['to']->add($tmp->getAddressList());
            }
        } elseif ($type === self::REPLY_ALL) {
            $force = isset($h['reply-to']);
        }
        /* We might need $list_info in the reply_all section. */
        $list_info = in_array($type, array(self::REPLY_AUTO, self::REPLY_LIST)) ? $contents->getListInformation() : null;
        if (!is_null($list_info) && !empty($list_info['reply_list'])) {
            /* If To/Reply-To and List-Reply address are the same, no need
             * to handle these address separately. */
            $rlist = new Horde_Mail_Rfc822_Address($list_info['reply_list']);
            if (!$rlist->match($addr['to'])) {
                $addr['to'] = clone $alist;
                $addr['to']->add($rlist);
                $reply_type = self::REPLY_LIST;
            }
        } elseif (in_array($type, array(self::REPLY_ALL, self::REPLY_AUTO))) {
            /* Clear the To field if we are auto-determining addresses. */
            if ($type == self::REPLY_AUTO) {
                $addr['to'] = clone $alist;
            }
            /* Filter out our own address from the addresses we reply to. */
            $identity = $injector->getInstance('IMP_Identity');
            $all_addrs = $identity->getAllFromAddresses();
            /* Build the To: header. It is either:
             * 1) the Reply-To address (if not a personal address)
             * 2) the From address(es) (if it doesn't contain a personal
             * address)
             * 3) all remaining Cc addresses. */
            $to_fields = array('from', 'reply-to');
            foreach (array('reply-to', 'from', 'to', 'cc') as $val) {
                /* If either a reply-to or $to is present, we use this address
                 * INSTEAD of the from address. */
                if ($force && $val == 'from' || !($tmp = $h[$val])) {
                    continue;
                }
                $ob = $tmp->getAddressList(true);
                /* For From: need to check if at least one of the addresses is
                 * personal. */
                if ($val == 'from') {
                    foreach ($ob->raw_addresses as $addr_ob) {
                        if ($all_addrs->contains($addr_ob)) {
                            /* The from field contained a personal address.
                             * Use the 'To' header as the primary reply-to
                             * address instead. */
                            $to_fields[] = 'to';
                            /* Add other non-personal from addresses to the
                             * list of CC addresses. */
                            $ob->setIteratorFilter($ob::BASE_ELEMENTS, $all_addrs);
                            $addr['cc']->add($ob);
                            $all_addrs->add($ob);
                            continue 2;
                        }
                    }
                }
                $ob->setIteratorFilter($ob::BASE_ELEMENTS, $all_addrs);
                foreach ($ob as $hdr_ob) {
                    if ($hdr_ob instanceof Horde_Mail_Rfc822_Group) {
                        $addr['cc']->add($hdr_ob);
                        $all_addrs->add($hdr_ob->addresses);
                    } elseif ($val != 'to' || is_null($list_info) || !$force || empty($list_info['exists'])) {
                        /* Don't add as To address if this is a list that
                         * doesn't have a post address but does have a
                         * reply-to address. */
                        if (in_array($val, $to_fields)) {
                            /* If from/reply-to doesn't have personal
                             * information, check from address. */
                            if (is_null($hdr_ob->personal) && ($tmp = $h['from']) && ($to_ob = $tmp->getAddressList(true)->first()) && !is_null($to_ob->personal) && $hdr_ob->match($to_ob)) {
                                $addr['to']->add($to_ob);
                            } else {
                                $addr['to']->add($hdr_ob);
                            }
                        } else {
                            $addr['cc']->add($hdr_ob);
                        }
                        $all_addrs->add($hdr_ob);
                    }
                }
            }
            /* Build the Cc: (or possibly the To:) header. If this is a
             * reply to a message that was already replied to by the user,
             * this reply will go to the original recipients (Request
             * #8485).  */
            if (count($addr['cc'])) {
                $reply_type = self::REPLY_ALL;
            }
            if (!count($addr['to'])) {
                $addr['to'] = $addr['cc'];
                $addr['cc'] = clone $alist;
            }
            /* Build the Bcc: header. */
            if ($tmp = $h['bcc']) {
                $bcc = $tmp->getAddressList(true);
                $bcc->add($identity->getBccAddresses());
                $bcc->setIteratorFilter(0, $all_addrs);
                foreach ($bcc as $val) {
                    $addr['bcc']->add($val);
                }
            }
        }
        if (!$this->_replytype || $reply_type != $this->_replytype) {
            $this->_replytype = $reply_type;
            $this->changed = 'changed';
        }
        $ret = $this->replyMessageText($contents, array('format' => isset($opts['format']) ? $opts['format'] : null));
        if ($prefs->getValue('reply_charset') && $ret['charset'] != $this->charset) {
            $this->charset = $ret['charset'];
            $this->changed = 'changed';
        }
        unset($ret['charset']);
        if ($type == self::REPLY_AUTO) {
            switch ($reply_type) {
                case self::REPLY_ALL:
                    try {
                        $recip_list = $this->recipientList($addr);
                        $ret['reply_recip'] = count($recip_list['list']);
                    } catch (IMP_Compose_Exception $e) {
                        $ret['reply_recip'] = 0;
                    }
                    break;
                case self::REPLY_LIST:
                    if (($list_parse = $injector->getInstance('Horde_ListHeaders')->parse('list-id', strval($h['List-Id']))) && !is_null($list_parse->label)) {
                        $ret['reply_list_id'] = $list_parse->label;
                    }
                    break;
            }
        }
        if (($lang = $h['Accept-Language']) || ($lang = $h['X-Accept-Language'])) {
            $langs = array();
            foreach (explode(',', $lang->value_single) as $val) {
                if (($name = Horde_Nls::getLanguageISO($val)) !== null) {
                    $langs[trim($val)] = $name;
                }
            }
            $ret['lang'] = array_unique($langs);
            /* Don't show display if original recipient is asking for reply in
             * the user's native language. */
            if (count($ret['lang']) == 1 && reset($ret['lang']) && substr(key($ret['lang']), 0, 2) == substr($language, 0, 2)) {
                unset($ret['lang']);
            }
        }
        return array_merge(array('addr' => $addr, 'identity' => $match_identity, 'subject' => $subject, 'type' => $reply_type), $ret);
    }