1
0
mirror of https://github.com/freescout-helpdesk/freescout.git synced 2024-11-25 11:52:29 +01:00
freescout/app/Thread.php

847 lines
24 KiB
PHP
Raw Normal View History

2018-07-14 03:23:37 +02:00
<?php
namespace App;
2018-11-12 14:35:06 +01:00
2018-07-14 03:23:37 +02:00
use Illuminate\Database\Eloquent\Model;
class Thread extends Model
{
/**
2018-07-25 19:30:43 +02:00
* By whom action performed (source_via).
2018-07-14 03:23:37 +02:00
*/
const PERSON_CUSTOMER = 1;
const PERSON_USER = 2;
2018-07-25 19:30:43 +02:00
public static $persons = [
2018-07-14 03:23:37 +02:00
self::PERSON_CUSTOMER => 'customer',
2018-07-25 19:30:43 +02:00
self::PERSON_USER => 'user',
];
2018-07-14 03:23:37 +02:00
/**
2018-07-25 19:30:43 +02:00
* Thread types.
2018-07-14 03:23:37 +02:00
*/
// Email from customer
const TYPE_CUSTOMER = 1;
// Thead created by user
const TYPE_MESSAGE = 2;
const TYPE_NOTE = 3;
// Thread status change
const TYPE_LINEITEM = 4;
const TYPE_PHONE = 5;
// Forwarded threads
const TYPE_FORWARDPARENT = 6;
const TYPE_FORWARDCHILD = 7;
const TYPE_CHAT = 8;
public static $types = [
2018-07-20 08:19:25 +02:00
// Thread by customer
2018-07-25 19:30:43 +02:00
self::TYPE_CUSTOMER => 'customer',
2018-07-20 08:19:25 +02:00
// Thread by user
2018-07-25 19:30:43 +02:00
self::TYPE_MESSAGE => 'message',
self::TYPE_NOTE => 'note',
2018-07-20 08:19:25 +02:00
// lineitem represents a change of state on the conversation. This could include, but not limited to, the conversation was assigned, the status changed, the conversation was moved from one mailbox to another, etc. A line item wont have a body, to/cc/bcc lists, or attachments.
2018-07-25 19:30:43 +02:00
self::TYPE_LINEITEM => 'lineitem',
self::TYPE_PHONE => 'phone',
2018-07-20 08:19:25 +02:00
// When a conversation is forwarded, a new conversation is created to represent the forwarded conversation.
// forwardparent is the type set on the thread of the original conversation that initiated the forward event.
2018-07-25 19:30:43 +02:00
self::TYPE_FORWARDPARENT => 'forwardparent',
2018-07-20 08:19:25 +02:00
// forwardchild is the type set on the first thread of the new forwarded conversation.
2018-07-25 19:30:43 +02:00
self::TYPE_FORWARDCHILD => 'forwardchild',
self::TYPE_CHAT => 'chat',
2018-07-14 03:23:37 +02:00
];
/**
2018-07-27 15:19:25 +02:00
* Statuses (code must be equal to conversations statuses).
2018-07-14 03:23:37 +02:00
*/
const STATUS_ACTIVE = 1;
2018-07-27 15:19:25 +02:00
const STATUS_PENDING = 2;
const STATUS_CLOSED = 3;
const STATUS_SPAM = 4;
const STATUS_NOCHANGE = 6;
2018-07-14 03:23:37 +02:00
2018-07-25 19:30:43 +02:00
public static $statuses = [
self::STATUS_ACTIVE => 'active',
self::STATUS_CLOSED => 'closed',
self::STATUS_NOCHANGE => 'nochange',
self::STATUS_PENDING => 'pending',
self::STATUS_SPAM => 'spam',
];
2018-07-14 03:23:37 +02:00
/**
2018-07-25 19:30:43 +02:00
* States.
2018-07-14 03:23:37 +02:00
*/
const STATE_DRAFT = 1;
const STATE_PUBLISHED = 2;
const STATE_HIDDEN = 3;
2018-08-02 18:17:13 +02:00
// A state of review means the thread has been stopped by Traffic Cop and is waiting
// to be confirmed (or discarded) by the person that created the thread.
2018-07-14 03:23:37 +02:00
const STATE_REVIEW = 4;
2018-07-25 19:30:43 +02:00
public static $states = [
self::STATE_DRAFT => 'draft',
self::STATE_PUBLISHED => 'published',
self::STATE_HIDDEN => 'hidden',
self::STATE_REVIEW => 'review',
];
2018-07-14 03:23:37 +02:00
/**
2018-07-25 19:30:43 +02:00
* Action associated with the line item.
2019-06-03 07:52:37 +02:00
* It is recommended to add custom action types between 100 and 1000
2018-07-14 03:23:37 +02:00
*/
2018-07-25 19:25:00 +02:00
// Conversation's status changed
const ACTION_TYPE_STATUS_CHANGED = 1;
// Conversation's assignee changed
const ACTION_TYPE_USER_CHANGED = 2;
2018-07-14 03:23:37 +02:00
// The conversation was moved from another mailbox
2018-07-25 19:25:00 +02:00
const ACTION_TYPE_MOVED_FROM_MAILBOX = 3;
2018-07-14 03:23:37 +02:00
// Another conversation was merged with this conversation
2018-07-25 19:25:00 +02:00
const ACTION_TYPE_MERGED = 4;
2018-07-14 03:23:37 +02:00
// The conversation was imported (no email notifications were sent)
2018-07-25 19:25:00 +02:00
const ACTION_TYPE_IMPORTED = 5;
2018-07-14 03:23:37 +02:00
// A workflow was run on this conversation (either automatic or manual)
2018-07-25 19:25:00 +02:00
const ACTION_TYPE_WORKFLOW_MANUAL = 6;
const ACTION_TYPE_WORKFLOW_AUTO = 7;
2018-07-14 03:23:37 +02:00
// The ticket was imported from an external Service
2018-07-25 19:25:00 +02:00
const ACTION_TYPE_IMPORTED_EXTERNAL = 8;
2018-08-29 08:45:15 +02:00
// Conversation customer changed
const ACTION_TYPE_CUSTOMER_CHANGED = 9;
2018-07-14 03:23:37 +02:00
// The ticket was deleted
2018-07-25 19:25:00 +02:00
const ACTION_TYPE_DELETED_TICKET = 10;
2018-07-14 03:23:37 +02:00
// The ticket was restored
2018-07-25 19:25:00 +02:00
const ACTION_TYPE_RESTORE_TICKET = 11;
2018-07-14 03:23:37 +02:00
// Describes an optional action associated with the line item
// todo: values need to be checked via HelpScout API
public static $action_types = [
2018-07-25 19:30:43 +02:00
self::ACTION_TYPE_STATUS_CHANGED => 'changed-ticket-status',
self::ACTION_TYPE_USER_CHANGED => 'changed-ticket-assignee',
self::ACTION_TYPE_MOVED_FROM_MAILBOX => 'moved-from-mailbox',
self::ACTION_TYPE_MERGED => 'merged',
self::ACTION_TYPE_IMPORTED => 'imported',
self::ACTION_TYPE_WORKFLOW_MANUAL => 'manual-workflow',
self::ACTION_TYPE_WORKFLOW_AUTO => 'automatic-workflow',
self::ACTION_TYPE_IMPORTED_EXTERNAL => 'imported-external',
2018-08-29 08:45:15 +02:00
self::ACTION_TYPE_CUSTOMER_CHANGED => 'changed-ticket-customer',
2018-07-25 19:30:43 +02:00
self::ACTION_TYPE_DELETED_TICKET => 'deleted-ticket',
self::ACTION_TYPE_RESTORE_TICKET => 'restore-ticket',
2018-07-14 03:23:37 +02:00
];
2018-07-25 19:30:43 +02:00
/**
* Source types (equal to thread source types).
2018-07-14 03:23:37 +02:00
*/
const SOURCE_TYPE_EMAIL = 1;
const SOURCE_TYPE_WEB = 2;
const SOURCE_TYPE_API = 3;
2018-07-25 19:30:43 +02:00
2018-07-14 03:23:37 +02:00
public static $source_types = [
2018-07-25 19:30:43 +02:00
self::SOURCE_TYPE_EMAIL => 'email',
self::SOURCE_TYPE_WEB => 'web',
self::SOURCE_TYPE_API => 'api',
2018-07-14 03:23:37 +02:00
];
2018-11-09 15:09:42 +01:00
protected $dates = [
'opened_at',
'created_at',
'updated_at',
2018-11-12 14:35:06 +01:00
'deleted_at',
2019-06-20 12:37:43 +02:00
'edited_at',
2018-11-12 14:35:06 +01:00
];
2018-11-09 15:09:42 +01:00
2018-07-14 03:23:37 +02:00
/**
2018-07-25 19:30:43 +02:00
* The user assigned to this thread (assignedTo).
2018-07-14 03:23:37 +02:00
*/
public function user()
{
return $this->belongsTo('App\User');
}
2018-09-05 10:05:00 +02:00
/**
2018-09-07 15:08:34 +02:00
* The user assigned to this thread (cached).
2018-09-05 10:05:00 +02:00
*/
public function user_cached()
{
return $this->user()->rememberForever();
}
2018-07-14 03:23:37 +02:00
/**
2018-07-25 19:30:43 +02:00
* Get the thread customer.
2018-07-14 03:23:37 +02:00
*/
public function customer()
{
return $this->belongsTo('App\Customer');
}
2018-09-07 15:08:34 +02:00
/**
* Get the thread customer (cached).
*/
public function customer_cached()
{
return $this->customer()->rememberForever();
}
2018-07-14 03:23:37 +02:00
/**
2018-07-25 19:30:43 +02:00
* Get conversation.
2018-07-14 03:23:37 +02:00
*/
public function conversation()
{
return $this->belongsTo('App\Conversation');
}
2018-07-20 08:19:25 +02:00
2018-08-04 12:50:55 +02:00
/**
* Get thread attachmets.
*/
public function attachments()
{
2018-08-15 08:10:05 +02:00
return $this->hasMany('App\Attachment')->where('embedded', false);
//return $this->hasMany('App\Attachment');
}
/**
* Get thread embedded attachments.
*/
public function embeds()
{
return $this->hasMany('App\Attachment')->where('embedded', true);
2018-08-04 12:50:55 +02:00
}
2018-09-14 10:24:04 +02:00
/**
* All kinds of attachments including embedded.
*/
public function all_attachments()
{
return $this->hasMany('App\Attachment');
}
2018-07-20 08:19:25 +02:00
/**
2018-07-25 19:25:00 +02:00
* Get user who created the thread.
*/
public function created_by_user()
{
return $this->belongsTo('App\User');
}
2018-09-05 10:05:00 +02:00
/**
2018-11-12 10:12:57 +01:00
* Get user who created the thread (cached).
2018-09-05 10:05:00 +02:00
*/
public function created_by_user_cached()
{
2018-09-07 15:08:34 +02:00
return $this->created_by_user()->rememberForever();
2018-09-05 10:05:00 +02:00
}
2018-07-25 19:25:00 +02:00
/**
* Get customer who created the thread.
*/
public function created_by_customer()
{
return $this->belongsTo('App\Customer');
}
2018-09-14 10:24:04 +02:00
/**
2019-06-20 12:37:43 +02:00
* Get user who edited thread.
2018-09-14 10:24:04 +02:00
*/
public function edited_by_user()
{
return $this->belongsTo('App\User');
}
2019-06-20 12:37:43 +02:00
/**
* Get user who edited thread (cached).
*/
public function edited_by_user_cached()
{
return $this->edited_by_user()->rememberForever();
}
2018-07-25 19:25:00 +02:00
/**
2018-07-25 19:30:43 +02:00
* Get sanitized body HTML.
*
2018-07-20 08:19:25 +02:00
* @return string
*/
2019-06-20 12:37:43 +02:00
public function getCleanBody($body = '')
2018-07-20 08:19:25 +02:00
{
2019-06-20 12:37:43 +02:00
if (!$body) {
$body = $this->body;
}
$body = \Purifier::clean($body);
2018-08-15 08:10:05 +02:00
// Remove all kinds of spaces after tags
// https://stackoverflow.com/questions/3230623/filter-all-types-of-whitespace-in-php
$body = preg_replace("/^(.*)>[\r\n]*\s+/mu", '$1>', $body);
return $body;
2018-07-20 08:19:25 +02:00
}
2019-06-20 12:37:43 +02:00
/**
* Get sanitized body HTML.
*
* @return string
*/
public function getCleanBodyOriginal()
{
return $this->getCleanBody($this->body_original);
}
2018-07-20 08:19:25 +02:00
/**
* Get thread recipients.
2018-07-25 19:30:43 +02:00
*
2018-07-20 08:19:25 +02:00
* @return array
*/
2018-08-27 10:08:20 +02:00
public function getToArray($exclude_array = [])
2018-07-20 08:19:25 +02:00
{
2018-09-20 09:08:02 +02:00
return \App\Misc\Helper::jsonToArray($this->to, $exclude_array);
2018-07-20 08:19:25 +02:00
}
2018-09-14 10:24:04 +02:00
public function getToString($exclude_array = [])
{
return implode(', ', $this->getToArray($exclude_array));
}
/**
* Get first address from the To list.
*/
public function getToFirst()
2018-11-12 10:12:57 +01:00
{
2018-09-14 10:24:04 +02:00
$to = $this->getToArray();
2018-11-12 10:12:57 +01:00
2018-09-14 10:24:04 +02:00
return array_shift($to);
}
2018-11-12 10:12:57 +01:00
2018-08-18 14:21:14 +02:00
/**
* Get type name.
*/
public function getTypeName()
{
return self::$types[$this->type];
}
2018-07-20 08:19:25 +02:00
/**
* Get thread CC recipients.
2018-07-25 19:30:43 +02:00
*
2018-07-20 08:19:25 +02:00
* @return array
*/
2018-08-27 10:08:20 +02:00
public function getCcArray($exclude_array = [])
2018-07-20 08:19:25 +02:00
{
2018-09-20 09:08:02 +02:00
return \App\Misc\Helper::jsonToArray($this->cc, $exclude_array);
2018-07-20 08:19:25 +02:00
}
2018-09-14 10:24:04 +02:00
public function getCcString($exclude_array = [])
{
return implode(', ', $this->getCcArray($exclude_array));
}
2018-07-20 08:19:25 +02:00
/**
* Get thread BCC recipients.
2018-07-25 19:30:43 +02:00
*
2018-07-20 08:19:25 +02:00
* @return array
*/
2018-08-27 10:08:20 +02:00
public function getBccArray($exclude_array = [])
2018-07-20 08:19:25 +02:00
{
2018-09-20 09:08:02 +02:00
return \App\Misc\Helper::jsonToArray($this->bcc, $exclude_array);
2018-07-20 08:19:25 +02:00
}
2018-09-14 10:24:04 +02:00
public function getBccString($exclude_array = [])
{
return implode(', ', $this->getBccArray($exclude_array));
}
2018-07-30 17:11:35 +02:00
/**
* Set to as JSON.
*/
public function setTo($emails)
{
$emails_array = Conversation::sanitizeEmails($emails);
if ($emails_array) {
2018-08-04 17:33:45 +02:00
$emails_array = array_unique($emails_array);
2018-07-30 17:11:35 +02:00
$this->to = json_encode($emails_array);
} else {
$this->to = null;
}
}
public function setCc($emails)
{
$emails_array = Conversation::sanitizeEmails($emails);
if ($emails_array) {
2018-08-04 17:33:45 +02:00
$emails_array = array_unique($emails_array);
2018-07-30 17:11:35 +02:00
$this->cc = json_encode($emails_array);
} else {
$this->cc = null;
}
}
public function setBcc($emails)
{
$emails_array = Conversation::sanitizeEmails($emails);
if ($emails_array) {
2018-08-04 17:33:45 +02:00
$emails_array = array_unique($emails_array);
2018-07-30 17:11:35 +02:00
$this->bcc = json_encode($emails_array);
} else {
$this->bcc = null;
}
}
2018-07-20 08:19:25 +02:00
/**
2018-07-25 19:25:00 +02:00
* Get thread's status name.
2018-07-25 19:30:43 +02:00
*
2018-07-24 08:34:28 +02:00
* @return string
2018-07-20 08:19:25 +02:00
*/
2018-07-25 19:25:00 +02:00
public function getStatusName()
{
return self::statusCodeToName($this->status);
}
/**
* Get status name. Made as a function to allow status names translation.
2018-07-25 19:30:43 +02:00
*
* @param int $status
*
* @return string
2018-07-25 19:25:00 +02:00
*/
public static function statusCodeToName($status)
2018-07-20 08:19:25 +02:00
{
switch ($status) {
case self::STATUS_ACTIVE:
2018-07-25 19:30:43 +02:00
return __('Active');
2018-07-20 08:19:25 +02:00
break;
case self::STATUS_PENDING:
2018-07-25 19:30:43 +02:00
return __('Pending');
2018-07-20 08:19:25 +02:00
break;
case self::STATUS_CLOSED:
2018-07-25 19:30:43 +02:00
return __('Closed');
2018-07-20 08:19:25 +02:00
break;
case self::STATUS_SPAM:
2018-07-25 19:30:43 +02:00
return __('Spam');
2018-07-20 08:19:25 +02:00
break;
case self::STATUS_NOCHANGE:
2018-07-25 19:30:43 +02:00
return __('Not changed');
2018-07-20 08:19:25 +02:00
break;
default:
return '';
break;
}
}
2018-07-27 08:01:34 +02:00
/**
* Get text for the assignee in line item.
2018-07-27 15:30:50 +02:00
*
2018-07-27 08:01:34 +02:00
* @return string
*/
public function getAssigneeName($ucfirst = false, $by_user = null)
2018-07-27 08:01:34 +02:00
{
if (!$by_user) {
$by_user = auth()->user();
}
2018-07-27 08:01:34 +02:00
if (!$this->user_id) {
2018-08-08 09:52:53 +02:00
if ($ucfirst) {
return __('Anyone');
} else {
return __('anyone');
}
} elseif ($by_user && $this->user_id == $by_user->id) {
if ($this->created_by_user_id && $this->created_by_user_id == $this->user_id) {
$name = __('yourself');
2018-08-08 09:52:53 +02:00
} else {
$name = __('you');
}
if ($ucfirst) {
$name = ucfirst($name);
2018-08-08 09:52:53 +02:00
}
2018-11-12 10:12:57 +01:00
2018-09-10 17:24:20 +02:00
return $name;
2018-07-27 08:01:34 +02:00
} else {
2018-09-19 10:00:59 +02:00
// User may be deleted
if ($this->user) {
return $this->user->getFullName();
} else {
return '';
}
2018-07-27 08:01:34 +02:00
}
}
2018-08-02 18:17:13 +02:00
/**
* Get user or customer who created the thead.
*/
public function getCreatedBy()
{
if (!empty($this->created_by_user_id)) {
2018-11-04 20:14:26 +01:00
// User can be deleted
if ($this->created_by_user) {
return $this->created_by_user;
} else {
return \App\User::getDeletedUser();
}
2018-08-02 18:17:13 +02:00
} else {
return $this->created_by_customer;
}
}
2018-09-07 15:08:34 +02:00
/**
* Get creator of the thread.
*/
public function getPerson($cached = false)
{
2018-11-12 10:12:57 +01:00
if ($this->type == self::TYPE_CUSTOMER) {
2018-09-07 15:08:34 +02:00
if ($cached) {
return $this->customer_cached;
} else {
return $this->customer;
}
} else {
if ($cached) {
return $this->created_by_user_cached;
} else {
return $this->created_by_user;
}
}
}
/**
2019-06-03 07:52:37 +02:00
* Get action's person.
2018-09-07 15:08:34 +02:00
*/
2019-06-03 07:52:37 +02:00
public function getActionPerson($conversation_number = '')
2018-09-07 15:08:34 +02:00
{
$person = '';
2018-11-12 10:12:57 +01:00
if ($this->type == self::TYPE_CUSTOMER) {
2018-09-20 16:34:34 +02:00
$person = $this->customer_cached->getFullName(true);
2018-11-12 10:12:57 +01:00
} elseif ($this->state == self::STATE_DRAFT && !empty($this->edited_by_user_id)) {
2018-09-14 10:24:04 +02:00
// Draft
if (auth()->user() && $this->edited_by_user_id == auth()->user()->id) {
2018-11-12 10:12:57 +01:00
$person = __('you');
2018-09-14 10:24:04 +02:00
} else {
$person = $this->edited_by_user->getFullName();
}
2018-11-02 07:35:47 +01:00
} elseif ($this->created_by_user_cached) {
2018-09-10 11:50:53 +02:00
if ($this->created_by_user_id && auth()->user() && $this->created_by_user_cached->id == auth()->user()->id) {
2018-11-12 10:12:57 +01:00
$person = __('you');
2018-09-07 15:08:34 +02:00
} else {
$person = $this->created_by_user_cached->getFullName();
}
}
2019-06-03 07:52:37 +02:00
// https://github.com/tormjens/eventy/issues/19
$person = \Eventy::filter('thread.action_person', $person, $this, $conversation_number);
return $person;
}
/**
* Get action text.
*/
public function getActionText($conversation_number = '', $escape = false, $strip_tags = false, $by_user = null)
{
$did_this = '';
2018-09-07 15:08:34 +02:00
// Did this
2018-11-12 10:12:57 +01:00
if ($this->type == self::TYPE_LINEITEM) {
2019-06-03 07:52:37 +02:00
2018-11-12 10:12:57 +01:00
if ($this->action_type == self::ACTION_TYPE_STATUS_CHANGED) {
2019-06-03 07:52:37 +02:00
if ($conversation_number) {
$did_this = __('marked as :status_name conversation #:conversation_number', ['status_name' => $this->getStatusName(), 'conversation_number' => $conversation_number]);
} else {
$did_this = __("marked as :status_name", ['status_name' => $this->getStatusName()]);
}
2018-11-12 10:12:57 +01:00
} elseif ($this->action_type == self::ACTION_TYPE_USER_CHANGED) {
2019-06-03 07:52:37 +02:00
$assignee = $this->getAssigneeName(false, $by_user);
if ($escape) {
$assignee = htmlspecialchars($assignee);
}
if ($conversation_number) {
$did_this = __('assigned :assignee convsersation #:conversation_number', ['assignee' => $assignee, 'conversation_number' => $conversation_number]);
} else {
$did_this = __("assigned to :assignee", ['assignee' => $assignee]);
}
2018-11-12 10:12:57 +01:00
} elseif ($this->action_type == self::ACTION_TYPE_CUSTOMER_CHANGED) {
2019-06-03 07:52:37 +02:00
if ($conversation_number) {
$did_this = __('changed the customer to :customer in conversation #:conversation_number', ['customer' => $this->customer->getFullName(true), 'conversation_number' => $conversation_number]);
} else {
$customer_name = $this->customer->getFullName(true);
if ($escape) {
$customer_name = htmlspecialchars($customer_name);
}
$did_this = __("changed the customer to :customer", ['customer' => '<a href="'.$this->customer->url().'" title="'.$this->action_data.'" class="link-black">'.$customer_name.'</a>']);
}
} elseif ($this->action_type == self::ACTION_TYPE_DELETED_TICKET) {
$did_this = __("deleted");
} elseif ($this->action_type == self::ACTION_TYPE_RESTORE_TICKET) {
$did_this = __("restored");
2018-09-07 15:08:34 +02:00
}
2018-11-12 10:12:57 +01:00
} elseif ($this->state == self::STATE_DRAFT) {
2018-09-14 10:24:04 +02:00
if (empty($this->edited_by_user_id)) {
2018-11-12 10:12:57 +01:00
$did_this = __('created a draft');
2018-09-14 10:24:04 +02:00
} else {
$did_this = __("edited :creator's draft", ['creator' => $this->created_by_user_cached->getFirstName()]);
}
2018-11-12 10:12:57 +01:00
} else {
2018-09-07 15:08:34 +02:00
if ($this->first) {
2018-11-12 10:12:57 +01:00
$did_this = __('started a new conversation #:conversation_number', ['conversation_number' => $conversation_number]);
} elseif ($this->type == self::TYPE_NOTE) {
$did_this = __('added a note to conversation #:conversation_number', ['conversation_number' => $conversation_number]);
2018-09-07 15:08:34 +02:00
} else {
2018-11-12 10:12:57 +01:00
$did_this = __('replied to conversation #:conversation_number', ['conversation_number' => $conversation_number]);
2018-09-07 15:08:34 +02:00
}
}
2019-06-03 07:52:37 +02:00
$did_this = \Eventy::filter('thread.action_text', $did_this, $this, $conversation_number, $escape);
if ($strip_tags) {
$did_this = strip_tags($did_this);
}
return $did_this;
}
/**
* Description of what happened.
*/
public function getActionDescription($conversation_number, $escape = true)
{
// Person
$person = $this->getActionPerson($conversation_number);
$did_this = $this->getActionText($conversation_number);
2018-09-07 15:08:34 +02:00
$description = ':person_tag_start:person:person_tag_end :did_this';
if ($escape) {
$description = htmlspecialchars($description);
}
return __($description, [
2018-11-12 10:12:57 +01:00
'person' => $person,
2018-09-07 15:08:34 +02:00
'person_tag_start' => '<strong>',
2018-11-12 10:12:57 +01:00
'person_tag_end' => '</strong>',
'did_this' => $did_this,
2018-09-07 15:08:34 +02:00
]);
}
2018-09-14 10:24:04 +02:00
/**
* Get thread state name.
*/
public function getStateName()
{
return self::$states[$this->state];
}
public function deleteThread()
{
$this->deteleAttachments();
$this->delete();
}
/**
* Delete thread attachments.
*/
public function deteleAttachments()
{
Attachment::deleteByIds($this->all_attachments()->pluck('id')->toArray());
}
2018-09-16 12:52:52 +02:00
public function isDraft()
{
2018-11-12 10:12:57 +01:00
return $this->state == self::STATE_DRAFT;
2018-09-16 12:52:52 +02:00
}
2018-09-26 19:35:11 +02:00
/**
* Get original body or body.
*/
public function getBodyOriginal()
{
if (!empty($this->body_original)) {
return $this->body_original;
} else {
return $this->body;
}
}
/**
* Get name for the reply to customer.
2018-11-12 10:12:57 +01:00
*
* @param [type] $mailbox [description]
*
* @return [type] [description]
*/
public function getFromName($mailbox = null)
{
// Created by customer
if ($this->source_via == self::PERSON_CUSTOMER) {
return $this->getCreatedBy()->getFirstName(true);
}
// Created by user
if (empty($mailbox)) {
$mailbox = $this->conversation->mailbox;
}
2018-11-12 10:12:57 +01:00
// Mailbox name by default
$name = $mailbox->name;
if ($mailbox->from_name == Mailbox::FROM_NAME_CUSTOM && $mailbox->from_name_custom) {
$name = $mailbox->from_name_custom;
} elseif ($mailbox->from_name == Mailbox::FROM_NAME_USER && $this->getCreatedBy()) {
$name = $this->getCreatedBy()->getFirstName(true);
}
2018-11-12 10:12:57 +01:00
return $name;
}
/**
* Check if thread is a reply from customer or user.
2018-12-13 10:11:15 +01:00
*
* @return bool [description]
*/
public function isReply()
{
return in_array($this->type, [\App\Thread::TYPE_MESSAGE, \App\Thread::TYPE_CUSTOMER]);
}
/**
* Is this thread created from auto responder email.
2018-12-21 10:10:07 +01:00
*
* @return bool [description]
*/
public function isAutoResponder()
{
return \MailHelper::isAutoResponder($this->headers);
}
2018-12-14 10:10:43 +01:00
/**
* Is thread created from incoming bounce email.
2018-12-21 10:10:07 +01:00
*
* @return bool [description]
2018-12-14 10:10:43 +01:00
*/
public function isBounce()
{
if (!empty($this->getSendStatusData()['is_bounce'])) {
2018-12-14 10:10:43 +01:00
return true;
} else {
return false;
}
}
/**
* Send status data mayb contain the following information:
* - bounce info (status_code, action, diagnostic_code, is_bounce, bounce_for_thread, bounce_for_conversation, bounced_by_thread, bounced_by_conversation)
* - send error message
* - click date
* - unsubscribe date
2018-12-21 10:10:07 +01:00
* - complain date.
*
* @return [type] [description]
*/
public function getSendStatusData()
{
return \Helper::jsonToArray($this->send_status_data);
}
public function updateSendStatusData($new_data)
{
if ($new_data) {
$send_status_data = $this->getSendStatusData();
if ($send_status_data) {
$send_status_data = array_merge($send_status_data, $new_data);
} else {
$send_status_data = $new_data;
}
$this->send_status_data = json_encode($send_status_data);
} else {
$this->send_status_data = null;
}
}
public function isSendStatusError()
{
return in_array($this->send_status, \App\SendLog::$status_errors);
}
2018-12-31 09:22:43 +01:00
/**
* Create thread.
*
* @param [type] $conversation_id [description]
* @param [type] $text [description]
* @param array $data [description]
* @return [type] [description]
*/
public static function create($conversation, $type, $body, $data = [], $save = true)
{
$thread = new Thread();
$thread->conversation_id = $conversation->id;
$thread->type = $type;
$thread->body = $body;
$thread->status = $conversation->status;
$thread->state = Thread::STATE_PUBLISHED;
// Assigned to.
if (!empty($data['user_id'])) {
$thread->user_id = $data['user_id'];
}
if (!empty($data['message_id'])) {
$thread->message_id = $data['message_id'];
}
if (!empty($data['headers'])) {
$thread->headers = $data['headers'];
}
if (!empty($data['from'])) {
$thread->from = $data['from'];
}
if (!empty($data['to'])) {
$thread->setTo($data['to']);
}
if (!empty($data['cc'])) {
$thread->setCc($data['cc']);
}
if (!empty($data['bcc'])) {
$thread->setBcc($data['bcc']);
}
if (isset($data['first'])) {
$thread->from = $data['first'];
}
if (isset($data['source_via'])) {
$thread->source_via = $data['source_via'];
}
if (isset($data['source_type'])) {
$thread->source_type = $data['source_type'];
}
if (!empty($data['customer_id'])) {
$thread->customer_id = $data['customer_id'];
}
if (!empty($data['created_by_customer_id'])) {
$thread->created_by_customer_id = $data['created_by_customer_id'];
}
if (!empty($data['created_by_user_id'])) {
$thread->created_by_user_id = $data['created_by_user_id'];
}
if (!empty($data['action_type'])) {
$thread->action_type = $data['action_type'];
}
2018-12-31 09:22:43 +01:00
if ($save) {
$thread->save();
}
return $thread;
}
2019-06-20 12:37:43 +02:00
/**
* Get full name of the user who edited thread.
*/
public function getEditedByUserName()
{
$name = '';
if (!$this->edited_by_user_id) {
return '';
}
if (auth()->user() && $this->edited_by_user_id == auth()->user()->id) {
$name = __('you');
} else {
$name = $this->edited_by_user_cached->getFullName();
}
return $name;
}
2018-07-14 03:23:37 +02:00
}