PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 2.0.10
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v2.0.10
2.1.0 2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 1.41 All 42 releases
fluent-boards / app / Hooks / Handlers / ActivityHandler.php

ActivityHandler.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 2.0.10, at app/Hooks/Handlers/ActivityHandler.php

467 lines 15.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBoards\App\Hooks\Handlers;
4
5 use FluentBoards\App\Models\Board;
6 use FluentBoards\App\Models\Stage;
7 use FluentBoards\App\Models\Task;
8 use FluentBoards\App\Models\User;
9 use FluentBoards\App\Services\Constant;
10 use FluentCrm\App\Models\Subscriber;
11 use FluentBoards\App\Models\Comment;
12 use FluentBoards\App\Services\Helper;
13
14 class ActivityHandler
15 {
16 public function createLogActivity($taskId, $action, $column, $oldValue = null, $newValue = null, $description = null, $settings = null )
17 {
18 $data = [
19 'object_type' => Constant::ACTIVITY_TASK,
20 'object_id' => $taskId,
21 'action' => $action, // action type: changed, updated, added, removed
22 'column' => $column,
23 'old_value' => $oldValue,
24 'new_value' => $newValue,
25 'description' => $description,
26 'settings' => $settings
27 ];
28 $userId = get_current_user_id();
29 if($userId == 0){
30 $task = Task::find($taskId);
31 $data['created_by'] = $task->created_by;
32 }
33
34 Helper::createActivity($data);
35 }
36 public function logMoveTaskToAnotherBoardActivity($task, $oldTask)
37 {
38 $old = $this->getBoardTitleById($oldTask->board_id);
39 $new = $this->getBoardTitleById($task->board_id);
40 $this->createLogActivity( $task->id,'changed', 'board', $old, $new);
41 }
42
43 public function logAssigneeAddedActivity($task, $newAssigneeId)
44 {
45 $currentUserId = get_current_user_id();
46 if($newAssigneeId == $currentUserId) {
47 $this->taskAssigneeJoin($task->id);
48 return;
49 }
50 $user = User::findOrFail($newAssigneeId);
51 $currentUserId = get_current_user_id();
52 if($currentUserId === $user->ID){
53 $this->taskAssigneeJoin($task->id);
54 } elseif ($user) {
55 $this->createLogActivity($task->id, 'added', 'assignee', null, $user->display_name);
56 }
57 }
58
59 public function logAssigneeRemovedActivity($task, $newAssigneeId)
60 {
61 $currentUserId = get_current_user_id();
62 if($newAssigneeId == $currentUserId) {
63 $this->taskAssigneeLeave($task->id);
64 return;
65 }
66 $user = User::findOrFail($newAssigneeId);
67 $currentUserId = get_current_user_id();
68 if($currentUserId === $user->ID){
69 $this->taskAssigneeLeave($task->id);
70 } else if($user) {
71 $this->createLogActivity($task->id, 'removed', 'assignee', null, $user->display_name);
72 }
73 }
74
75 public function logTaskCreationActivity($task)
76 {
77 $this->createLogActivity( $task->id,'created', 'task', null, $task->title, null );
78 }
79
80 public function logTaskContentUpdatedActivity($task, $col, $oldTask = null)
81 {
82 // Description autosaves are intentionally excluded to avoid flooding the activity feed.
83 if ($col === 'description') {
84 return;
85 }
86
87 $action = 'updated';
88 if($task->parent_id){
89 $this->createLogActivity( $task->parent_id, $action, 'subtask', $oldTask->title, $task->title );
90 }else{
91 $this->createLogActivity( $task->id, $action, $col, $oldTask->title, $task->title );
92 }
93 }
94
95 public function taskLabelActivity($task, $label, $action)
96 {
97 $column = 'label';
98 $settings = [
99 'bg_color' => $label->bg_color,
100 'color' => $label->color,
101 'title' => $label->title,
102 ];
103
104 $this->createLogActivity($task->id, $action, $column, null, null, null, $settings);
105 }
106
107 public function logDueDateActivity($task, $oldDate)
108 {
109 $column = 'Due Date';
110 $action = 'changed';
111
112 if($oldDate){
113 $new = gmdate("F j, Y, g:i a", strtotime($task->due_at));
114 $old = gmdate("F j, Y, g:i a", strtotime($oldDate));
115 if($new == $old)
116 return;
117 }
118 $newDueDate = $task->due_at;
119 $new = null;
120 if ($newDueDate) {
121 $new = gmdate("F j, Y, g:i a", strtotime($newDueDate));
122 if(str_contains($new, '12:00 am')){
123 $new = gmdate("F j, Y", strtotime($newDueDate));
124 }
125 }
126 $old = null;
127 if(!$oldDate){
128 $action = 'added';
129 }else{
130 $old = gmdate("F j, Y, g:i a", strtotime($oldDate));
131 if(str_contains($old, '12:00 am')){
132 $old = gmdate("F j, Y", strtotime($oldDate));
133 }
134 }
135
136 $this->createLogActivity($task->id, $action, $column, $old, $new);
137 }
138 public function logDueDateRemoveActivity($task)
139 {
140 $this->createLogActivity( $task->id, 'removed', 'Due Date', null);
141 }
142
143 public function logStartDateActivity($task, $oldDate)
144 {
145 $column = 'Start Date';
146 $action = 'changed';
147
148 if($oldDate){
149 $new = gmdate("F j, Y", strtotime($task->started_at));
150 $old = gmdate("F j, Y", strtotime($oldDate));
151 if($new == $old)
152 return;
153 }
154 $newStartDate = $task->started_at;
155 $new = null;
156 if ($newStartDate) {
157 $new = gmdate("F j, Y", strtotime($newStartDate));
158 }
159 $old = null;
160 if(!$oldDate){
161 $action = 'added';
162 }else{
163 $old = gmdate("F j, Y", strtotime($oldDate));
164 }
165
166 $this->createLogActivity($task->id, $action, $column, $old, $new);
167 }
168
169
170 public function logPriorityChangeActivity($task, $old)
171 {
172 $new = $task->priority;
173 $this->createLogActivity($task->id, 'changed', 'priority', $old, $new);
174 }
175
176 public function logCommentCreateActivity($comment)
177 {
178 if($comment->parent_id) {
179 // dd($comment);
180 $parent = Comment::findOrFail($comment->parent_id);
181 $parentDescription = $parent->description;
182 $this->createLogActivity($comment->task_id, 'added', 'a reply');
183 }else{
184 $commentPlainText = wp_strip_all_tags($comment->description);
185 $this->createLogActivity($comment->task_id, 'added', 'comment', null, $commentPlainText, null);
186 }
187 }
188 public function logCommentUpdateActivity($comment, $oldComment)
189 {
190 $taskId = $comment->task_id;
191 $newComment = $comment->settings['raw_description'] ?? $comment->description;
192
193 $this->createLogActivity($taskId, 'updated', 'comment', $oldComment, $newComment);
194 }
195 public function logCommentDeleteActivity($comment)
196 {
197 $commentDescription = wp_strip_all_tags($comment->settings['raw_description'] ?? $comment->description );
198 $taskId = $comment->task_id;
199
200 $this->createLogActivity($taskId, 'removed', 'comment', null, $commentDescription, null);
201 }
202
203 public function logSubtaskAddedActivity($parentTask, $subTask)
204 {
205 $this->createLogActivity($parentTask->id, 'added', 'subtask', null, $subTask->title);
206 }
207
208 public function logSubtaskCloneActivity($parentTask, $subTask)
209 {
210 $this->createLogActivity($parentTask->id, 'cloned', 'subtask', null, $subTask->title);
211 }
212 public function logSubtaskGroupAddedActivity($task_id, $subTaskGroup)
213 {
214 $this->createLogActivity($task_id, 'added', 'subtask group', null, $subTaskGroup->value);
215 }
216
217 public function logSubtaskDeletedActivity($id, $subTaskTitle)
218 {
219 $this->createLogActivity($id, 'removed', 'subtask', null, $subTaskTitle);
220 }
221
222 public function logSubtaskGroupDeletedActivity($task_id, $subTaskGroup)
223 {
224 $this->createLogActivity($task_id, 'removed', 'subtask group', null, $subTaskGroup->value);
225 }
226 public function logSubtaskGroupTitleUpdatedActivity($oldTitle, $group)
227 {
228 $this->createLogActivity($group->task_id, 'changed', 'subtask group title', $oldTitle, $group->value);
229 }
230 public function logTaskCompletedOrReopenActivity($task, $status)
231 {
232 if($status == 'closed'){
233 if($task->parent_id){
234 $this->createLogActivity($task->parent_id, 'closed', 'subtask', $task->title);
235 }else{
236 $this->createLogActivity($task->id, 'closed', 'task', $task->title);
237 }
238 }else{
239 if($task->parent_id){
240 $this->createLogActivity($task->parent_id, 'reopened', 'subtask', $task->title);
241 }else{
242 $this->createLogActivity($task->id, 'reopened', 'task', $task->title);
243 }
244 }
245 }
246
247 public function logTaskStageUpdatedActivity($task, $oldStageId)
248 {
249 $oldStage = Stage::findOrFail($oldStageId);
250 $newStage = Stage::findOrFail($task->stage_id);
251 if($oldStage && $newStage){
252 $this->createLogActivity($task->id, 'changed', 'stage', $oldStage->title, $newStage->title);
253 }
254 }
255
256 public function associateUserAddChangeRemoveActivity($oldAssociateId, $newAssociateId, $taskId)
257 {
258 $subsciber = new Subscriber();
259 $oldAssociateUser = $subsciber->find($oldAssociateId);
260 $newAssociateUser = $subsciber->find($newAssociateId);
261 $action = 'added';
262 $column = 'the associate email';
263 $old = null; $new = null;
264
265 if ($oldAssociateUser && $newAssociateUser) {
266 $old = $oldAssociateUser->email;
267 $new = $newAssociateUser->email;
268 $action = 'changed';
269 } elseif ($oldAssociateUser && !$newAssociateUser) {
270 $old = $oldAssociateUser->email;
271 $action = 'removed';
272 } else {
273 $new = $newAssociateUser->email;
274 }
275 $this->createLogActivity($taskId, $action, $column, $old, $new);
276 }
277
278 public function taskAssigneeJoin($id)
279 {
280 $this->createLogActivity($id, 'joined', 'task', null, null);
281 }
282
283 public function taskAssigneeLeave($id)
284 {
285 $this->createLogActivity($id, 'left', 'task', null, null);
286 }
287
288 public function labelManageForTaskActivity($id, $action)
289 {
290 $this->createLogActivity($id, $action, 'label', null, null);
291 }
292
293 private function getBoardTitleById($boardId)
294 {
295 return Board::findOrFail($boardId)->title; // it can be further optimized , we may limit multiple query here.
296 }
297
298 public function taskAddedFromFluentForms($task)
299 {
300 $taskActivity = [
301 'object_type' => Constant::ACTIVITY_TASK,
302 'object_id' => $task->id,
303 'action' => 'created', // action type: changed, updated, added, removed
304 'column' => 'task',
305 'old_value' => $task->title,
306 'new_value' => null,
307 'description' => " from Fluent Forms",
308 ];
309
310 $board = Board::find($task->board_id);
311 $settings = $board->settings ?? [];
312
313 if (isset($settings['tasks_count'])) {
314 if ($settings['tasks_count'] != 0) $settings['tasks_count'] += 1;
315 } else {
316 $settings['tasks_count'] = 1;
317 }
318 $board->settings = $settings;
319 $board->save();
320 $taskStage = $task->stage;
321 $settings = ['task_id' => $task->id];
322
323 $boardActivity = [
324 'object_type' => Constant::ACTIVITY_BOARD,
325 'object_id' => $task->board_id,
326 'action' => 'created', // action type: changed, updated, added, removed, created
327 'column' => 'task',
328 'old_value' => null,
329 'new_value' => $task->title,
330 'description' => 'on stage '. $taskStage->title . ' from Fluent Forms ',
331 'settings' => $settings
332 ];
333 if (intval($task->created_by) > 0) {
334 $taskActivity['created_by'] = intval($task->created_by);
335 $boardActivity['created_by'] = intval($task->created_by);
336
337 } else {
338 $taskActivity['description'] .= ' by '. $task['settings']['author']['name'] . " (" . $task['settings']['author']['email'] . ")";
339 $boardActivity['description'] .= ' by '. $task['settings']['author']['name'] . " (" . $task['settings']['author']['email'] . ")";
340 }
341 Helper::createActivity($taskActivity);
342 Helper::createActivity($boardActivity);
343
344 }
345 public function taskAttachmentAdded($attachment)
346 {
347 $this->createLogActivity($attachment->object_id , 'added', 'attachment', null, strlen($attachment->title) > 0 ? $attachment->title : $attachment->full_url);
348 }
349 public function taskAttachmentDeleted($attachment)
350 {
351 $this->createLogActivity($attachment->object_id , 'deleted', 'attachment', null, strlen($attachment->title) > 0 ? $attachment->title : $attachment->full_url);
352 }
353
354 public function taskArchived($task)
355 {
356 if(!$task->archived_at){
357 $this->createLogActivity($task->id, 'restored', 'task', $task->title);
358 }else{
359 $this->createLogActivity($task->id, 'archived', 'task', $task->title);
360 }
361 }
362
363 public function logRepeatTaskCreatedActivity($newTask, $parentTask)
364 {
365 $this->createLogActivity(
366 $newTask->id,
367 'created',
368 'repeat task',
369 $newTask->title,
370 $parentTask->title,
371 null,
372 $parentTask
373 );
374 }
375
376 public function logRepeatTaskSet($newTask)
377 {
378 $this->createLogActivity(
379 $newTask->id,
380 'set',
381 'Repeat Task',
382 null,
383 null,
384 );
385 }
386
387 public function logRepeatTaskUpdated($newTask)
388 {
389 $this->createLogActivity(
390 $newTask->id,
391 'updated',
392 'Repeat Task',
393 null,
394 null
395 );
396 }
397 public function taskMovedFromBoard($task, $oldBoard, $newBoard)
398 {
399 $this->createLogActivity($task->id, 'moved', 'board', $oldBoard->title, $newBoard->title);
400 }
401
402 public function logCustomFieldActivity($taskId, $customField, $oldValue, $newValue, $isNewCustomField)
403 {
404 // Format values for display in activity
405 $displayNewValue = $this->formatValueForDisplay($newValue, $customField->settings['custom_field_type']);
406
407 $action = 'changed';
408 $column = $customField->title;
409
410 // Ensure we have a value to display
411 if (empty($displayNewValue)) {
412 $displayNewValue = 'empty';
413 }
414
415 // Handle old value display logic
416 $displayOldValue = null;
417 if (!$isNewCustomField && $oldValue !== null && $oldValue !== '') {
418 // Format old value for display if it exists
419 $displayOldValue = $this->formatValueForDisplay($oldValue, $customField->settings['custom_field_type']);
420 }
421
422 $settings = [
423 'custom_field_id' => $customField->id,
424 'custom_field_title' => $customField->title,
425 'custom_field_type' => $customField->settings['custom_field_type']
426 ];
427
428 $this->createLogActivity($taskId, $action, $column, $displayOldValue, $displayNewValue, null, $settings);
429 }
430
431 /**
432 * Format custom field value for display in activity logs
433 */
434 private function formatValueForDisplay($value, $fieldType)
435 {
436 if ($value === null || $value === '') {
437 return 'empty';
438 }
439
440 switch ($fieldType) {
441 case 'checkbox':
442 return $value ? 'checked' : 'unchecked';
443 case 'date':
444 // If it's already formatted as Y-m-d H:i:s, convert to readable format
445 if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $value)) {
446 return gmdate('M j, Y g:i A', strtotime($value));
447 }
448 return $value;
449 case 'select':
450 case 'text':
451 case 'textarea':
452 case 'number':
453 default:
454 return (string) $value;
455 }
456 }
457 public function taskCloned($originalTask, $clonedTask)
458 {
459 $this->createLogActivity(
460 $clonedTask->id,
461 'cloned',
462 'task',
463 'from ' . $originalTask->title,
464 );
465 }
466 }
467