PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / 1.10.7
ووسلام – همگام سازی ووکامرس و باسلام v1.10.7
1.10.19 1.10.20 1.10.18 1.10.17 1.10.15 1.10.14 1.10.13 1.10.12 1.10.10 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.2 1.9.1 1.9.0 1.8.8 1.8.5 1.8.6 All 53 releases
sync-basalam / includes / Services / TicketServiceManager.php

TicketServiceManager.php in ووسلام – همگام سازی ووکامرس و باسلام 1.10.7, at includes/Services/TicketServiceManager.php

239 lines 7.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SyncBasalam\Services;
4
5 use SyncBasalam\Admin\Settings\SettingsConfig;
6 use SyncBasalam\Services\Hamsalam\FetchHamsalamToken;
7 use SyncBasalam\Services\Hamsalam\FetchHamsalamBusinessId;
8
9 use SyncBasalam\Services\Ticket\FetchAllTickets;
10 use SyncBasalam\Services\Ticket\FetchTicket;
11 use SyncBasalam\Services\Ticket\FetchTicketSubjects;
12 use SyncBasalam\Services\Ticket\CreateTicket;
13 use SyncBasalam\Services\Ticket\CreateTicketItem;
14 use SyncBasalam\Services\Ticket\UploadTicketMedia;
15 use SyncBasalam\Services\Ticket\UpsertTicketSiteAccess;
16
17 use SyncBasalam\Jobs\Exceptions\RetryableException;
18 use SyncBasalam\Jobs\Exceptions\NonRetryableException;
19
20 class TicketServiceManager
21 {
22 private $hamsalamToken;
23 private $hamsalamBusinessId;
24 private $tokenFetcher;
25 private $businessIdFetcher;
26
27 private const MAX_RETRY_ATTEMPTS = 2;
28
29 public static function isUnauthorized($response): bool
30 {
31 return is_array($response) && isset($response['status_code']) && intval($response['status_code']) === 401;
32 }
33
34 public static function isSuccessful($response): bool
35 {
36 if (!is_array($response)) return false;
37 $statusCode = intval($response['status_code'] ?? 0);
38 return $statusCode >= 200 && $statusCode < 300;
39 }
40
41 public static function ticketStatuses(): array
42 {
43 return [
44 'pending_response' => 'در انتظار پاسخ',
45 'under_review' => 'در حال بررسی',
46 'closed' => 'بسته شده',
47 'answered' => 'پاسخ داده شده',
48 ];
49 }
50
51 public static function resolveTicketStatus(array $ticket): string
52 {
53 $status = $ticket['data']['status'] ?? $ticket['status'] ?? '';
54
55 if (is_array($status)) {
56 $status = $status['slug'] ?? $status['name'] ?? '';
57 }
58
59 return strtolower(trim((string) $status));
60 }
61
62 public static function isTicketClosed(array $ticket): bool
63 {
64 return in_array(self::resolveTicketStatus($ticket), ['closed', 'بسته شده'], true);
65 }
66
67 public function __construct()
68 {
69 $settings = (array) syncBasalamSettings()->getSettings();
70
71 $this->hamsalamToken = $settings[SettingsConfig::HAMSALAM_TOKEN] ?? null;
72 $this->hamsalamBusinessId = $settings[SettingsConfig::HAMSALAM_BUSINESS_ID] ?? null;
73 $this->tokenFetcher = new FetchHamsalamToken();
74 $this->businessIdFetcher = new FetchHamsalamBusinessId();
75 }
76
77 private function executeWithRetry(callable $callback, array $callbackArgs = []): array
78 {
79 $attempt = 0;
80
81 while ($attempt < self::MAX_RETRY_ATTEMPTS) {
82 $attempt++;
83
84 try {
85 $token = $this->getHamsalamToken();
86 if (!$this->hasValue($token)) return $this->buildErrorResponse('توکن ه�
87 سلا�
88 در دسترس نیست.', 401);
89
90 $data = call_user_func_array($callback, array_merge([$token], $callbackArgs));
91 } catch (RetryableException $e) {
92 return $this->buildErrorResponse($e->getMessage(), $e->getCode() ?: 400);
93 } catch (NonRetryableException $e) {
94 return $this->buildErrorResponse($e->getMessage(), $e->getCode() ?: 400);
95 } catch (\Exception $e) {
96 return $this->buildErrorResponse($e->getMessage(), 500);
97 }
98
99 if (!is_array($data) || !isset($data['status_code'])) {
100 return $this->buildErrorResponse('پاسخ دریافتی از سرویس نا�
101 عتبر است.', 500);
102 }
103
104 if (!self::isUnauthorized($data)) return $data;
105
106 if ($attempt >= self::MAX_RETRY_ATTEMPTS) return $data;
107
108 $this->refreshHamsalamToken();
109 }
110
111 return $this->buildErrorResponse('خطای ناشناخته در پردازش درخواست.', 500);
112 }
113
114 private function buildErrorResponse(string $message, int $statusCode = 500): array
115 {
116 return [
117 'status_code' => $statusCode,
118 'error' => true,
119 'message' => $message,
120 ];
121 }
122
123 private function getHamsalamToken()
124 {
125 if ($this->hasValue($this->hamsalamToken)) return $this->hamsalamToken;
126
127 $this->hamsalamToken = $this->tokenFetcher->fetch();
128 return $this->hamsalamToken;
129 }
130
131 private function refreshHamsalamToken(): void
132 {
133 $this->hamsalamToken = $this->tokenFetcher->fetch();
134 }
135
136 private function getHamsalamBusinessId()
137 {
138 if ($this->hasValue($this->hamsalamBusinessId)) return $this->hamsalamBusinessId;
139
140 $this->hamsalamBusinessId = $this->businessIdFetcher->fetch();
141 return $this->hamsalamBusinessId;
142 }
143
144 private function hasValue($value): bool
145 {
146 return !($value === null || $value === '');
147 }
148
149 private function isValidTicketPayload($title, $subject, $content): bool
150 {
151 if (!isset($title, $subject, $content)) return false;
152
153 $title = trim((string) $title);
154 $content = trim((string) $content);
155
156 return mb_strlen($title) >= 3
157 && mb_strlen($title) <= 255
158 && mb_strlen($content) >= 10;
159 }
160
161 public function CheckHamsalamAccess($page = 1): array
162 {
163 return $this->fetchAllTickets($page);
164 }
165
166 public function fetchTicketSubjects(): array
167 {
168 $service = new FetchTicketSubjects();
169 return $this->executeWithRetry([$service, 'execute']);
170 }
171
172 public function fetchAllTickets($page = 1): array
173 {
174 $service = new FetchAllTickets();
175 $page = max(1, intval($page));
176
177 return $this->executeWithRetry([$service, 'execute'], [$page]);
178 }
179
180 public function fetchTicket($ticket_id): array
181 {
182 $service = new FetchTicket($ticket_id);
183 return $this->executeWithRetry([$service, 'execute']);
184 }
185
186 public function uploadTicketMedia($filePath): array
187 {
188 $service = new UploadTicketMedia();
189 return $this->executeWithRetry([$service, 'execute'], [$filePath]);
190 }
191
192 public function createTicket($title, $subject, $content, $fileIds = []): array
193 {
194 if (!$this->isValidTicketPayload($title, $subject, $content)) {
195 return $this->buildErrorResponse('اطلاعات وارد شده �
196 عتبر نیست', 400);
197 }
198
199 $service = new CreateTicket();
200
201 $data = [
202 'title' => $title,
203 'subject' => $subject,
204 'content' => $content,
205 'file_ids' => is_array($fileIds) ? $fileIds : [],
206 'business_id' => $this->getHamsalamBusinessId(),
207 ];
208
209 return $this->executeWithRetry([$service, 'execute'], [$data]);
210 }
211
212 public function createTicketItem($ticket_id, $content, $fileIds = []): array
213 {
214 $service = new CreateTicketItem($ticket_id);
215
216 $data = [
217 'type' => 'content',
218 'content' => $content,
219 'file_ids' => is_array($fileIds) ? $fileIds : [],
220 ];
221
222 return $this->executeWithRetry([$service, 'execute'], [$data]);
223 }
224
225 public function upsertTicketSiteAccess($ticketId, array $accessData): array
226 {
227 $businessId = intval($this->getHamsalamBusinessId());
228 $ticketId = intval($ticketId);
229 if ($businessId <= 0 || $ticketId <= 0 || empty($accessData)) {
230 return $this->buildErrorResponse('اطلاعات دسترسی �
231 عتبر نیست.', 400);
232 }
233
234 $accessData['ticket_id'] = $ticketId;
235 $service = new UpsertTicketSiteAccess($businessId);
236 return $this->executeWithRetry([$service, 'execute'], [$accessData]);
237 }
238 }
239