PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.4.5
Fluent Support – Helpdesk & Customer Support Ticket System v2.4.5
2.4.5 2.4.0 2.3.2 2.3.1 2.3.0 2.2.1 2.2.0 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.4.0 1.4.1 1.4.2 1.4.5 1.4.6 1.4.7 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 All 69 releases
fluent-support / app / Models / Attachment.php

Attachment.php in Fluent Support – Helpdesk & Customer Support Ticket System 2.4.5, at app/Models/Attachment.php

149 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentSupport\App\Models;
4
5 use FluentSupport\App\Services\Helper;
6
7 class Attachment extends Model
8 {
9 protected $table = 'fs_attachments';
10
11 protected $hidden = ['full_url', 'file_path'];
12
13 protected $appends = ['secureUrl'];
14
15 /**
16 * The attributes that are mass assignable.
17 *
18 * @var array
19 */
20 protected $fillable = [
21 'ticket_id',
22 'person_id',
23 'conversation_id',
24 'file_type',
25 'file_path',
26 'full_url',
27 'title',
28 'driver',
29 'file_size',
30 'status',
31 'settings'
32 ];
33
34 public static function boot()
35 {
36 parent::boot();
37
38 static::creating(function ($model) {
39 $uid = wp_generate_uuid4();
40 $model->file_hash = md5($uid . wp_rand(0, 1000));
41 });
42 }
43
44 /**
45 * Delete the stored files for these attachments (local, or via the remote
46 * driver hook). DB rows are left to the caller.
47 *
48 * @param \FluentSupport\Framework\Database\Orm\Collection|array $attachments
49 * @param int|null $ticketId When provided, removes the ticket_{id} upload directory.
50 */
51 public static function purgeAttachments($attachments, $ticketId = null)
52 {
53 foreach ($attachments as $attachment) {
54 if ($attachment->driver && $attachment->driver !== 'local') {
55 do_action('fluent_support/delete_remote_attachment_' . $attachment->driver, $attachment);
56 } elseif ($attachment->file_path && file_exists($attachment->file_path)) {
57 wp_delete_file($attachment->file_path);
58 }
59 }
60
61 if ($ticketId) {
62 $uploadDir = wp_upload_dir();
63 $ticketDir = $uploadDir['basedir'] . '/' . FLUENT_SUPPORT_UPLOAD_DIR . '/ticket_' . $ticketId;
64 if (is_dir($ticketDir)) {
65 if (!class_exists('\WP_Filesystem_Direct')) {
66 require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
67 require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
68 }
69 (new \WP_Filesystem_Direct(false))->rmdir($ticketDir, true);
70 }
71 }
72 }
73
74 public function setSettingsAttribute($settings)
75 {
76 $this->attributes['settings'] = \maybe_serialize($settings);
77 }
78
79 public function getSettingsAttribute($settings)
80 {
81 return Helper::safeUnserialize($settings);
82 }
83
84 /**
85 * Signed download URL.
86 *
87 * @return string
88 */
89 public function getSecureUrlAttribute()
90 {
91 return $this->signedUrl(self::signedUrlExpiry());
92 }
93
94 /**
95 * Download URL valid until $expires.
96 *
97 * @param int $expires Unix timestamp.
98 * @return string
99 */
100 public function signedUrl($expires)
101 {
102 return add_query_arg([
103 'fst_file' => $this->file_hash,
104 'expires' => (int) $expires,
105 'secure_sign' => self::signature($this->id, (int) $expires)
106 ], site_url('/index.php'));
107 }
108
109 /**
110 * Expiry for a newly signed URL. Rounded to a TTL boundary so the URL stays
111 * the same for a while (browser caching), and always at least one TTL ahead.
112 * A URL signed just before a boundary used to die within seconds.
113 *
114 * @return int Unix timestamp.
115 */
116 public static function signedUrlExpiry()
117 {
118 $ttl = max(MINUTE_IN_SECONDS * 5, (int) apply_filters('fluent_support/attachment_signed_url_ttl', HOUR_IN_SECONDS));
119
120 return (intdiv(time(), $ttl) + 2) * $ttl;
121 }
122
123 /**
124 * Signature for an expiring URL. The 'v2|' prefix keeps it apart from legacy
125 * signatures: those signed "id|YmdH", and without the prefix an old hourly
126 * signature would pass as one that expires in 2034 (2026100614 read as a timestamp).
127 *
128 * @param int $attachmentId
129 * @param int $expires Unix timestamp.
130 * @return string
131 */
132 public static function signature($attachmentId, $expires)
133 {
134 return hash_hmac('sha256', 'v2|' . $attachmentId . '|' . (int) $expires, wp_salt('secure_auth'));
135 }
136
137 /**
138 * Signature of a pre-2.4.1 URL, valid for one UTC hour.
139 *
140 * @param int $attachmentId
141 * @param string $hourWindow gmdate('YmdH')
142 * @return string
143 */
144 public static function legacySignature($attachmentId, $hourWindow)
145 {
146 return hash_hmac('sha256', $attachmentId . '|' . $hourWindow, wp_salt('secure_auth'));
147 }
148 }
149