1
0
mirror of https://github.com/freescout-helpdesk/freescout.git synced 2024-11-24 11:22:42 +01:00
freescout/app/Folder.php

354 lines
11 KiB
PHP
Raw Normal View History

2018-07-14 03:23:37 +02:00
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Folder extends Model
{
/**
2018-07-24 08:34:28 +02:00
* Folders types (ids from HelpScout interface).
2018-07-14 03:23:37 +02:00
*/
const TYPE_UNASSIGNED = 1;
// User specific
const TYPE_MINE = 20;
2018-07-14 14:17:11 +02:00
// User specific
const TYPE_STARRED = 25;
2018-07-14 03:23:37 +02:00
const TYPE_DRAFTS = 30;
const TYPE_ASSIGNED = 40;
const TYPE_CLOSED = 60;
const TYPE_SPAM = 80;
const TYPE_DELETED = 110;
public static $types = [
self::TYPE_UNASSIGNED => 'Unassigned',
2018-07-24 08:34:28 +02:00
self::TYPE_MINE => 'Mine',
self::TYPE_DRAFTS => 'Drafts',
self::TYPE_ASSIGNED => 'Assigned',
self::TYPE_CLOSED => 'Closed',
self::TYPE_SPAM => 'Spam',
self::TYPE_DELETED => 'Deleted',
self::TYPE_STARRED => 'Starred',
2018-07-14 03:23:37 +02:00
];
2018-07-14 14:17:11 +02:00
/**
2018-07-24 08:34:28 +02:00
* https://glyphicons.bootstrapcheatsheets.com/.
2018-07-14 14:17:11 +02:00
*/
public static $type_icons = [
self::TYPE_UNASSIGNED => 'folder-open',
2018-07-24 08:34:28 +02:00
self::TYPE_MINE => 'hand-right',
self::TYPE_DRAFTS => 'duplicate',
self::TYPE_ASSIGNED => 'user',
self::TYPE_CLOSED => 'lock', // lock
self::TYPE_SPAM => 'ban-circle',
self::TYPE_DELETED => 'trash',
self::TYPE_STARRED => 'star',
2018-07-14 14:17:11 +02:00
];
// Public non-user specific mailbox types
public static $public_types = [
2018-07-14 03:23:37 +02:00
self::TYPE_UNASSIGNED,
self::TYPE_DRAFTS,
self::TYPE_ASSIGNED,
self::TYPE_CLOSED,
self::TYPE_SPAM,
self::TYPE_DELETED,
];
2018-09-14 10:24:04 +02:00
// Folder types which belong to specific user.
// These folders has user_id specified.
2018-07-14 03:23:37 +02:00
public static $personal_types = [
self::TYPE_MINE,
self::TYPE_STARRED,
];
2018-09-14 10:24:04 +02:00
// Folder types to which conversations are added via conversation_folder table.
public static $indirect_types = [
self::TYPE_DRAFTS,
self::TYPE_STARRED,
];
2019-12-20 10:41:06 +01:00
// Counter mode.
const COUNTER_ACTIVE = 1;
const COUNTER_TOTAL = 2;
2018-07-14 03:23:37 +02:00
public $timestamps = false;
2019-12-20 08:06:34 +01:00
protected $casts = [
'meta' => 'array',
];
2018-07-14 03:23:37 +02:00
/**
2018-07-24 08:34:28 +02:00
* Get the mailbox to which folder belongs.
2018-07-14 03:23:37 +02:00
*/
public function mailbox()
{
return $this->belongsTo('App\Mailbox');
}
/**
2018-07-24 08:34:28 +02:00
* Get the user to which folder belongs.
2018-07-14 03:23:37 +02:00
*/
public function user()
{
return $this->belongsTo('App\User');
}
/**
2018-07-24 08:34:28 +02:00
* Get starred conversations.
2018-07-14 03:23:37 +02:00
*/
public function conversations()
{
2018-07-14 14:17:11 +02:00
return $this->hasMany('App\Conversation');
2018-07-14 03:23:37 +02:00
}
public function getTypeName()
{
2018-12-05 13:33:05 +01:00
// To make name translatable.
switch ($this->type) {
case self::TYPE_UNASSIGNED:
return __('Unassigned');
case self::TYPE_MINE:
return __('Mine');
case self::TYPE_DRAFTS:
return __('Drafts');
case self::TYPE_ASSIGNED:
return __('Assigned');
case self::TYPE_CLOSED:
return __('Closed');
case self::TYPE_SPAM:
return __('Spam');
case self::TYPE_DELETED:
return __('Deleted');
case self::TYPE_STARRED:
return __('Starred');
2018-12-05 13:33:05 +01:00
default:
2019-12-20 08:06:34 +01:00
return __(\Eventy::filter('folder.type_name', self::$types[$this->type] ?? '', $this));
2018-12-05 13:33:05 +01:00
}
2018-07-14 03:23:37 +02:00
}
2018-07-14 14:17:11 +02:00
public function getTypeIcon()
{
2019-12-20 08:06:34 +01:00
return \Eventy::filter('folder.type_icon', self::$type_icons[$this->type] ?? '', $this);
2018-07-14 14:17:11 +02:00
}
2018-07-25 16:09:20 +02:00
/**
* Get order by array.
2018-07-25 16:15:35 +02:00
*
2018-07-25 16:09:20 +02:00
* @return array
*/
public function getOrderByArray()
{
$order_by = [];
switch ($this->type) {
case self::TYPE_UNASSIGNED:
case self::TYPE_MINE:
case self::TYPE_ASSIGNED:
$order_by[] = ['status' => 'asc'];
$order_by[] = ['last_reply_at' => 'desc'];
break;
2018-07-25 16:15:35 +02:00
2018-07-25 16:09:20 +02:00
case self::TYPE_STARRED:
2018-09-14 16:52:16 +02:00
$order_by[] = ['status' => 'asc'];
$order_by[] = ['last_reply_at' => 'desc'];
//$order_by = [['conversation_folder.id' => 'desc']];
2018-07-25 16:09:20 +02:00
break;
case self::TYPE_DRAFTS:
$order_by = [['updated_at' => 'desc']];
break;
case self::TYPE_CLOSED:
$order_by = [['closed_at' => 'desc']];
2018-07-25 16:15:35 +02:00
2018-07-25 16:09:20 +02:00
case self::TYPE_SPAM:
$order_by = [['last_reply_at' => 'desc']];
break;
case self::TYPE_DELETED:
$order_by = [['user_updated_at' => 'desc']];
break;
default:
$order_by = \Eventy::filter('folder.conversations_order_by', $order_by, $this->type);
break;
2018-07-25 16:15:35 +02:00
}
2018-07-25 16:09:20 +02:00
return $order_by;
}
/**
* Add order by to the query.
*/
public function queryAddOrderBy($query)
{
$order_bys = $this->getOrderByArray();
foreach ($order_bys as $order_by) {
foreach ($order_by as $field => $sort_order) {
$query->orderBy($field, $sort_order);
}
}
2018-07-25 16:15:35 +02:00
2018-07-25 16:09:20 +02:00
return $query;
}
2018-09-14 10:24:04 +02:00
/**
* Is this folder accumulates conversations via conversation_folder table.
*/
public function isIndirect()
{
2018-11-12 10:12:57 +01:00
return in_array($this->type, self::$indirect_types);
2018-09-14 10:24:04 +02:00
}
2018-09-14 16:52:16 +02:00
public function updateCounters()
{
2019-12-20 10:41:06 +01:00
if (\Eventy::filter('folder.update_counters', false, $this)) {
return;
}
2018-11-12 10:12:57 +01:00
if ($this->type == self::TYPE_MINE && $this->user_id) {
2018-09-20 16:34:34 +02:00
$this->active_count = Conversation::where('user_id', $this->user_id)
->where('mailbox_id', $this->mailbox_id)
->where('status', Conversation::STATUS_ACTIVE)
2018-09-18 08:25:15 +02:00
->where('state', Conversation::STATE_PUBLISHED)
2018-09-14 16:52:16 +02:00
->count();
$this->total_count = Conversation::where('user_id', $this->user_id)
2018-09-20 16:34:34 +02:00
->where('mailbox_id', $this->mailbox_id)
2018-09-18 08:25:15 +02:00
->where('state', Conversation::STATE_PUBLISHED)
2018-09-14 16:52:16 +02:00
->count();
2018-11-12 10:12:57 +01:00
} elseif ($this->type == self::TYPE_STARRED) {
2018-09-14 16:52:16 +02:00
$this->active_count = count(Conversation::getUserStarredConversationIds($this->mailbox_id, $this->user_id));
$this->total_count = $this->active_count;
2018-11-12 10:12:57 +01:00
} elseif ($this->type == self::TYPE_DELETED) {
2018-09-20 16:34:34 +02:00
$this->active_count = $this->conversations()->where('state', Conversation::STATE_DELETED)
->count();
2018-09-18 08:25:15 +02:00
$this->total_count = $this->active_count;
2018-09-14 16:52:16 +02:00
} elseif ($this->isIndirect()) {
// Conversation are connected to folder via conversation_folder table.
// Drafts.
2018-11-24 11:10:12 +01:00
$this->active_count = ConversationFolder::where('conversation_folder.folder_id', $this->id)
->join('conversations', 'conversations.id', '=', 'conversation_folder.conversation_id')
//->where('state', Conversation::STATE_PUBLISHED)
2018-11-24 11:10:12 +01:00
->count();
2018-09-14 16:52:16 +02:00
$this->total_count = $this->active_count;
} else {
$this->active_count = $this->conversations()
2018-09-18 08:25:15 +02:00
->where('state', Conversation::STATE_PUBLISHED)
2018-09-14 16:52:16 +02:00
->where('status', Conversation::STATUS_ACTIVE)
->count();
2018-09-20 16:34:34 +02:00
$this->total_count = $this->conversations()
->where('state', Conversation::STATE_PUBLISHED)
->count();
2018-09-14 16:52:16 +02:00
}
$this->save();
}
2018-09-20 16:34:34 +02:00
/**
* Get count to display in folders list.
2018-12-13 10:11:15 +01:00
*
* @param array $folders [description]
*
* @return [type] [description]
*/
public function getCount($folders = [])
{
2020-07-20 09:57:51 +02:00
$counter = \Eventy::filter('folder.counter', self::COUNTER_ACTIVE, $this, $folders);
$count = \Eventy::filter('folder.count', false, $this, $counter, $folders);
if ($count !== false) {
return $count;
}
if ($counter == self::COUNTER_TOTAL || $this->type == self::TYPE_STARRED || $this->type == self::TYPE_DRAFTS) {
return $this->total_count;
} else {
return $this->getActiveCount($folders);
}
}
2018-09-20 16:34:34 +02:00
/**
* Get calculated number of active conversations.
*/
public function getActiveCount($folders = [])
{
$active_count = $this->active_count;
2018-11-12 10:12:57 +01:00
if ($this->type == self::TYPE_ASSIGNED) {
2018-09-20 16:34:34 +02:00
if ($folders) {
2018-11-12 10:12:57 +01:00
$mine_folder = $folders->firstWhere('type', self::TYPE_MINE);
2018-09-20 16:34:34 +02:00
} else {
2018-11-12 10:12:57 +01:00
$mine_folder = $this->mailbox->folders()->where('type', self::TYPE_MINE)->first();
2018-09-20 16:34:34 +02:00
}
2018-11-12 10:12:57 +01:00
2018-09-20 16:34:34 +02:00
if ($mine_folder) {
$active_count = $active_count - $mine_folder->active_count;
if ($active_count < 0) {
$active_count = 0;
}
}
}
return $active_count;
}
2018-12-05 13:33:05 +01:00
2019-12-20 10:41:06 +01:00
/**
* Query for waiting since.
*/
public function getWaitingSinceQuery()
2018-12-05 13:33:05 +01:00
{
2019-12-20 10:41:06 +01:00
$query = null;
2018-12-05 13:33:05 +01:00
if ($this->type == self::TYPE_MINE) {
// Assigned to user.
2019-12-20 10:41:06 +01:00
$query = Conversation::where('user_id', $this->user_id)
2018-12-05 13:33:05 +01:00
->where('mailbox_id', $this->mailbox_id);
} elseif ($this->isIndirect()) {
// Via intermediate table.
2019-12-20 10:41:06 +01:00
$query = Conversation::join('conversation_folder', 'conversations.id', '=', 'conversation_folder.conversation_id')
2018-12-05 13:33:05 +01:00
->where('conversation_folder.folder_id', $this->id);
} else {
// All other conversations.
2019-12-20 10:41:06 +01:00
$query = $this->conversations();
2018-12-05 13:33:05 +01:00
}
2019-12-20 10:41:06 +01:00
return \Eventy::filter('folder.waiting_since_query', $query, $this);
2018-12-05 13:33:05 +01:00
}
/**
* Works for main folder only for now.
2018-12-13 10:11:15 +01:00
*
2018-12-05 13:33:05 +01:00
* @return [type] [description]
*/
public function getWaitingSince()
{
// Get oldest active conversation.
2019-12-20 10:41:06 +01:00
$conversation = $this->getWaitingSinceQuery()
2018-12-05 13:33:05 +01:00
->where('state', Conversation::STATE_PUBLISHED)
->where('status', Conversation::STATUS_ACTIVE)
->orderBy($this->getWaitingSinceField(), 'asc')
->first();
if ($conversation) {
return $conversation->getWaitingSince($this);
} else {
return '';
}
}
/**
* Get conversation field used to detect waiting since time.
2018-12-13 10:11:15 +01:00
*
2018-12-05 13:33:05 +01:00
* @return [type] [description]
*/
public function getWaitingSinceField()
{
if ($this->type == \App\Folder::TYPE_CLOSED) {
return 'closed_at';
} elseif ($this->type == \App\Folder::TYPE_DRAFTS) {
return 'updated_at';
} elseif ($this->type == \App\Folder::TYPE_DELETED) {
return 'user_updated_at';
} else {
return'last_reply_at';
}
}
2018-07-14 03:23:37 +02:00
}