| @@ -1,13 +1,8 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | 3 | namespace FluentSupport\App\Models; |
| 4 | 4 | |
| 5 | -use Exception; | |
| 6 | -use FluentSupport\App\Models\Ticket; | |
| 7 | -use FluentSupport\App\Models\Attachment; | |
| 8 | -use FluentSupport\App\Services\Tickets\ResponseService; | |
| 9 | -use FluentSupport\App\Modules\PermissionManager; | |
| 10 | 5 | use FluentSupport\App\Services\Helper; |
| 11 | 6 | use FluentSupport\Framework\Support\Arr; |
| 12 | 7 | |
| 13 | 8 | class Conversation extends Model |
| @@ -43,8 +38,13 @@ | ||
| 43 | 38 | |
| 44 | 39 | static::deleting(function ($model) { |
| 45 | 40 | //Delete cc info |
| 46 | 41 | Meta::where('object_type', 'response')->where('object_id', $model->id)->delete(); |
| 42 | + // Delete conversation-level attachments — files first, then DB records | |
| 43 | + $class = __NAMESPACE__ . '\Attachment'; | |
| 44 | + $attachments = $class::where('conversation_id', $model->id)->get(); | |
| 45 | + $class::purgeAttachments($attachments); | |
| 46 | + $class::where('conversation_id', $model->id)->delete(); | |
| 47 | 47 | }); |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 50 | /** |
| @@ -145,221 +145,8 @@ | ||
| 145 | 145 | )->where('object_type', 'response')->where('key', 'settings'); |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | 148 | |
| 149 | - /** | |
| 150 | - * This `doBulkReplies` will handle bulk replies | |
| 151 | - * @param array $data | |
| 152 | - * @return array | |
| 153 | - * @throws Exception | |
| 154 | - */ | |
| 155 | - public function doBulkReplies ( $data ) | |
| 156 | - { | |
| 157 | - $agent = Helper::getAgentByUserId(); | |
| 158 | - $tickets = $this->getTicketsToForBulkReply( $data, $agent ); | |
| 159 | - | |
| 160 | - $responseData = [ | |
| 161 | - 'content' => wp_kses_post(Arr::get($data, 'content', '')), | |
| 162 | - 'conversation_type' => 'response', | |
| 163 | - 'close_ticket' => Arr::get($data, 'close_ticket'), | |
| 164 | - ]; | |
| 165 | - | |
| 166 | - $attachments = Arr::get($data, 'attachments', []); | |
| 167 | - $attachments = $this->getAttachsForBulkReplies( $attachments ); | |
| 168 | - | |
| 169 | - foreach ( $tickets as $ticket ) { | |
| 170 | - if ( $attachments ) { | |
| 171 | - $responseData['attachments'] = []; | |
| 172 | - foreach ( $attachments as $attachment ) { | |
| 173 | - $responseData['attachments'][] = $this->handleAttachmentOnBulkReplies ( $attachment, $ticket ); | |
| 174 | - } | |
| 175 | - } | |
| 176 | - (new ResponseService())->createResponse( $responseData, $agent, $ticket ); | |
| 177 | - } | |
| 178 | - | |
| 179 | - return [ | |
| 180 | - 'message' => __( 'Response has been added to the selected tickets', 'fluent-support' ) | |
| 181 | - ]; | |
| 182 | - } | |
| 183 | - | |
| 184 | - // This is a supporting method of `doBulkReplies` it will return all selected tickets | |
| 185 | - // Also it will check all check permission | |
| 186 | - // @param array $data | |
| 187 | - // @param object $agent | |
| 188 | - private function getTicketsToForBulkReply( $data, $agent ) | |
| 189 | - { | |
| 190 | - $ticketIds = array_filter($data['ticket_ids'], 'absint'); | |
| 191 | - | |
| 192 | - //Get logged in agent information | |
| 193 | - $hasAllPermission = PermissionManager::currentUserCan('fst_manage_other_tickets'); | |
| 194 | - $query = Ticket::whereIn('id', $ticketIds)->where('status', '!=', 'closed'); | |
| 195 | - | |
| 196 | - //If the agent does not have permission | |
| 197 | - if ( !$hasAllPermission ) { | |
| 198 | - $query->where('agent_id', $agent->id); //Filter ticket by agent_id | |
| 199 | - } | |
| 200 | - | |
| 201 | - $tickets = $query->get(); | |
| 202 | - | |
| 203 | - //if not ticket found | |
| 204 | - if ( $tickets->isEmpty() ) { | |
| 205 | - throw new \Exception( 'Sorry no tickets found based on your filter and bulk actions'); | |
| 206 | - } | |
| 207 | - | |
| 208 | - return $tickets; | |
| 209 | - } | |
| 210 | - | |
| 211 | - // This is a supporting method of `doBulkReplies` it will return it will return attachments | |
| 212 | - // if agent add attachments to bulk replies if there is no attachments then it will return false | |
| 213 | - // @param array $attachments | |
| 214 | - private function getAttachsForBulkReplies ( $attachments ) | |
| 215 | - { | |
| 216 | - if ( $attachments ) { | |
| 217 | - $attachs = Attachment::whereNull('ticket_id') | |
| 218 | - ->orderBy('id', 'asc') | |
| 219 | - ->whereIn('file_hash', $attachments) | |
| 220 | - ->get(); | |
| 221 | - return $attachs; | |
| 222 | - } | |
| 223 | - return false; | |
| 224 | - } | |
| 225 | - | |
| 226 | - // This is a supporting method of `doBulkReplies` this method will prepare the uploaded attachments | |
| 227 | - // for adding in response | |
| 228 | - // @param object $attachment | |
| 229 | - // @param object $ticket | |
| 230 | - private function handleAttachmentOnBulkReplies ( $attachment, $ticket ) | |
| 231 | - { | |
| 232 | - $attachedFile = $attachment->replicate(); | |
| 233 | - $attachedFile->ticket_id = $ticket->id; | |
| 234 | - $attachedFile->save(); | |
| 235 | - return $attachedFile->file_hash; | |
| 236 | - } | |
| 237 | - | |
| 238 | - | |
| 239 | - /** | |
| 240 | - * This `deleteResponse` is responsible for deleting response | |
| 241 | - * @param int $ticketId | |
| 242 | - * @param int $responseId | |
| 243 | - * @return array | |
| 244 | - * @throws Exception | |
| 245 | - */ | |
| 246 | - public function deleteResponse($ticketId, $responseId) | |
| 247 | - { | |
| 248 | - $ticket = Ticket::findOrFail($ticketId); | |
| 249 | - $response = static::findOrFail($responseId); | |
| 250 | - $agent = Helper::getAgentByUserId(); | |
| 251 | - | |
| 252 | - $this->checkUserTaskPermission($ticket->agent_id, $agent->id, 'delete'); | |
| 253 | - | |
| 254 | - static::where('id', $response->id)->delete(); | |
| 255 | - $response->ccinfo()->delete(); | |
| 256 | - | |
| 257 | - return [ | |
| 258 | - 'message' => __('Selected response has been deleted', 'fluent-support') | |
| 259 | - ]; | |
| 260 | - } | |
| 261 | - | |
| 262 | - /** | |
| 263 | - * Update the conversation type for a response. | |
| 264 | - * | |
| 265 | - * @param array $data | |
| 266 | - * @param int $ticketId | |
| 267 | - * @param int $responseId | |
| 268 | - * @param string $conversationType | |
| 269 | - * | |
| 270 | - * @return array | |
| 271 | - * @throws Exception | |
| 272 | - */ | |
| 273 | - public function publishDraftResponse ( $data, $ticketId, $responseId, $conversationType ) | |
| 274 | - { | |
| 275 | - $ticket = Ticket::findOrFail($ticketId); | |
| 276 | - $response = static::findOrFail($responseId); | |
| 277 | - | |
| 278 | - $content = wp_unslash(wp_kses_post($data['content'])); | |
| 279 | - $resetWaitingSince = apply_filters('fluent_support/reset_waiting_since', true, $content); | |
| 280 | - | |
| 281 | - $person = Helper::getAgentByUserId(get_current_user_id()); | |
| 282 | - | |
| 283 | - $approveDraftResponsePermission = PermissionManager::currentUserCan('fst_approve_draft_reply'); | |
| 284 | - | |
| 285 | - if ( !$approveDraftResponsePermission ) { | |
| 286 | - throw new \Exception("Sorry, You do not have permission to approve this draft response"); | |
| 287 | - } | |
| 288 | - | |
| 289 | - $response->conversation_type = $conversationType; | |
| 290 | - $response->created_at = current_time('mysql'); | |
| 291 | - $response->save(); | |
| 292 | - | |
| 293 | - if ($person->person_type == 'agent' && $ticket->status == 'new') { | |
| 294 | - $ticket->status = 'active'; | |
| 295 | - if ($ticket->created_at) { | |
| 296 | - $ticket->first_response_time = strtotime(current_time('mysql')) - strtotime($ticket->created_at); | |
| 297 | - } else { | |
| 298 | - $ticket->first_response_time = 300; | |
| 299 | - } | |
| 300 | - } | |
| 301 | - | |
| 302 | - if ($resetWaitingSince) { | |
| 303 | - $ticket->last_agent_response = current_time('mysql'); | |
| 304 | - $ticket->waiting_since = current_time('mysql'); | |
| 305 | - } | |
| 306 | - | |
| 307 | - $ticket->response_count += 1; | |
| 308 | - $ticket->save(); | |
| 309 | - | |
| 310 | - do_action('fluent_support/' . $conversationType . '_added_by_' . $person->person_type, $response, $ticket, $person); | |
| 311 | - | |
| 312 | - return [ | |
| 313 | - 'message' => __('Draft response has been successfully approved.', 'fluent-support'), | |
| 314 | - 'response' => $response, | |
| 315 | - ]; | |
| 316 | - } | |
| 317 | - | |
| 318 | - public function updateResponse($data, $ticketId, $responseId) | |
| 319 | - { | |
| 320 | - $ticket = Ticket::findOrFail($ticketId); | |
| 321 | - $response = static::findOrFail($responseId); | |
| 322 | - | |
| 323 | - $agent = Helper::getAgentByUserId(); | |
| 324 | - | |
| 325 | - $this->checkUserTaskPermission($ticket->agent_id, $agent->id, 'update'); | |
| 326 | - | |
| 327 | - $response->content = wp_unslash(wp_kses_post($data['content'])); | |
| 328 | - | |
| 329 | - if ( $response->conversation_type == 'draft_response' ) { | |
| 330 | - $this->updateDraftResponseData($response); | |
| 331 | - } | |
| 332 | - | |
| 333 | - $response->save(); | |
| 334 | - | |
| 335 | - return [ | |
| 336 | - 'message' => __('Selected response has been updated', 'fluent-support'), | |
| 337 | - 'response' => $response | |
| 338 | - ]; | |
| 339 | - } | |
| 340 | - | |
| 341 | - public function updateDraftResponseData($response) | |
| 342 | - { | |
| 343 | - $agent = Helper::getAgentByUserId(); | |
| 344 | - $approveDraftResponsePermission = PermissionManager::currentUserCan('fst_approve_draft_reply'); | |
| 345 | - | |
| 346 | - if ($response->person_id == $agent->id) { | |
| 347 | - return null; | |
| 348 | - } | |
| 349 | - | |
| 350 | - if ($approveDraftResponsePermission) { | |
| 351 | - $response->conversation_type = 'response'; | |
| 352 | - $response->save(); | |
| 353 | - return [ | |
| 354 | - 'message' => __('Selected draft response has been approved and updated', 'fluent-support'), | |
| 355 | - 'response' => $response | |
| 356 | - ]; | |
| 357 | - } else { | |
| 358 | - throw new \Exception("Sorry, You do not have permission to approve this draft response"); | |
| 359 | - } | |
| 360 | - } | |
| 361 | - | |
| 362 | 149 | public function getSettingsValue($valueKey = false, $default = false) |
| 363 | 150 | { |
| 364 | 151 | $exist = Meta::where('object_type', 'response') |
| 365 | 152 | ->where('key', 'settings') |
| @@ -420,21 +207,7 @@ | ||
| 420 | 207 | $conversations = Conversation::where('ticket_id', $ticketId)->get(); |
| 421 | 208 | foreach ($conversations as $conversation) { |
| 422 | 209 | $conversation->delete(); |
| 423 | 210 | } |
| 424 | - } | |
| 425 | - | |
| 426 | - private function checkUserTaskPermission($ticketAgentId, $agentId, $task) | |
| 427 | - { | |
| 428 | - $permissionKey = $task === 'delete' ? 'fst_delete_tickets' : 'fst_manage_other_tickets'; | |
| 429 | - | |
| 430 | - if (!PermissionManager::currentUserCan($permissionKey) && $ticketAgentId !== $agentId) { | |
| 431 | - throw new \Exception( | |
| 432 | - // translators: %s is the action being performed (e.g., "view", "edit", "delete") | |
| 433 | - esc_html(sprintf(__('Sorry, you do not have permission to %s this response.', 'fluent-support'), $task)) | |
| 434 | - ); | |
| 435 | - } | |
| 436 | - | |
| 437 | - return true; | |
| 438 | 211 | } |
| 439 | 212 | |
| 440 | 213 | } |