PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 2.2.0
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v2.2.0
2.2.1 2.2.0 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 All 44 releases
← All changes | app/Hooks/Handlers/BoardHandler.php +223 -39 1.20 → 2.2.0 View file →
@@ -1,8 +1,9 @@
1 1 <?php
2 2
3 3 namespace FluentBoards\App\Hooks\Handlers;
4 4
5 +use FluentBoards\App\Models\Attachment;
5 6 use FluentBoards\App\Models\Comment;
6 7 use FluentBoards\App\Models\Meta;
7 8 use FluentBoards\App\Models\NotificationUser;
8 9 use FluentBoards\App\Models\Relation;
@@ -10,13 +11,14 @@
10 11 use FluentBoards\App\Models\Task;
11 12 use FluentBoards\App\Models\Board;
12 13 use FluentBoards\App\Models\User;
13 14 use FluentBoards\App\Services\Constant;
15 +use FluentBoards\App\Services\BoardService;
14 16 use FluentBoards\App\Services\Helper;
15 17
16 18 class BoardHandler
17 19 {
18 - public function createLogActivity($boardId, $action, $column = null, $oldValue = null, $newValue = null, $description = null, $settings = null )
20 + public function createLogActivity($boardId, $action, $column = null, $oldValue = null, $newValue = null, $description = null, $settings = null, $userId = null )
19 21 {
20 22 $data = [
21 23 'object_type' => Constant::ACTIVITY_BOARD,
22 24 'object_id' => $boardId,
@@ -26,11 +28,53 @@
26 28 'new_value' => $newValue,
27 29 'description' => $description,
28 30 'settings' => $settings
29 31 ];
32 + if($userId) {
33 + $data['created_by'] = $userId;
34 + }
30 35
31 36 Helper::createActivity($data);
32 37 }
38 + /** Record the creation of a board's custom-field definition. */
39 + public function customFieldCreated($customField)
40 + {
41 + $this->createLogActivity(
42 + $customField->board_id,
43 + Constant::ACTIVITY_ACTION_CREATED,
44 + Constant::ACTIVITY_CUSTOM_FIELD,
45 + null,
46 + $customField->title,
47 + null,
48 + ['custom_field_id' => $customField->id, 'custom_field_type' => $customField->settings['custom_field_type']]
49 + );
50 + }
51 +
52 + /** Record changed names and options using snapshots taken before the definition was saved. */
53 + public function customFieldUpdated($customField, $oldCustomField)
54 + {
55 + $settings = [
56 + 'custom_field_id' => $customField->id,
57 + 'custom_field_title' => $customField->title,
58 + 'custom_field_type' => $customField->settings['custom_field_type']
59 + ];
60 + if ($oldCustomField->title !== $customField->title) {
61 + $this->createLogActivity($customField->board_id, Constant::ACTIVITY_ACTION_UPDATED,
62 + Constant::ACTIVITY_CUSTOM_FIELD, $oldCustomField->title, $customField->title, null, $settings);
63 + }
64 +
65 + $oldOptions = $oldCustomField->settings['select_options'] ?? [];
66 + $newOptions = $customField->settings['select_options'] ?? [];
67 + if ($oldOptions !== $newOptions) {
68 + $this->createLogActivity($customField->board_id, Constant::ACTIVITY_ACTION_UPDATED,
69 + /* translators: %s is the custom field title */
70 + sprintf(__('custom field options for %s', 'fluent-boards'), $customField->title),
71 + $oldOptions ? implode(', ', $oldOptions) : __('empty', 'fluent-boards'),
72 + $newOptions ? implode(', ', $newOptions) : __('empty', 'fluent-boards'),
73 + null, $settings);
74 + }
75 + }
76 +
33 77 public function getAllBoards($sortBy = 'ASC')
34 78 {
35 79 $boards = Board::orderBy('created_at', $sortBy)->get();
36 80
@@ -38,8 +82,15 @@
38 82 'boards' => $boards,
39 83 ];
40 84 }
41 85
86 + public function attachFolderToBoard($board)
87 + {
88 + $board->folder = (new BoardService())->getBoardFolder($board->id);
89 +
90 + return $board;
91 + }
92 +
42 93 public function boardCreated($board)
43 94 {
44 95 $boardId = $board->id;
45 96 $this->createLogActivity($boardId, 'created', 'board', null, null, $board->title);
@@ -45,8 +96,40 @@
45 96 $this->createLogActivity($boardId, 'created', 'board', null, null, $board->title);
46 97 $this->updateOnboarding();
47 98 }
48 99
100 + /**
101 + * Log a system activity without allowing a non-critical log failure to fail the automation.
102 + *
103 + * @param Board $board
104 + * @return void
105 + */
106 + public function boardCreatedFromAutomation($board)
107 + {
108 + $previousUserId = get_current_user_id();
109 +
110 + try {
111 + wp_set_current_user(0);
112 +
113 + $this->createLogActivity(
114 + $board->id,
115 + 'created',
116 + 'board',
117 + null,
118 + null,
119 + null,
120 + ['source' => 'fluentcrm_automation']
121 + );
122 + } catch (\Throwable $exception) {
123 + error_log(sprintf(
124 + 'FluentBoards: Failed to log FluentCRM automation board activity: %s',
125 + sanitize_text_field($exception->getMessage())
126 + ));
127 + } finally {
128 + wp_set_current_user($previousUserId);
129 + }
130 + }
131 +
49 132 private function updateOnboarding()
50 133 {
51 134 $onboarding = Meta::where('key', Constant::FBS_ONBOARDING)->first();
52 135 if($onboarding && $onboarding->value == 'no'){
@@ -57,12 +140,12 @@
57 140
58 141 public function taskCreatedOnBoard($task)
59 142 {
60 143 $boardId = $task->board_id;
61 - $this->updateBoardTaskCount($boardId, 1);
144 + $this->updateBoardTaskCount($boardId);
62 145 $taskStage = $task->stage;
63 146 $settings = ['task_id' => $task->id];
64 - $this->createLogActivity($boardId, 'created', 'task', null, $task->title, 'on stage '.$taskStage->title, $settings);
147 + $this->createLogActivity($boardId, 'created', 'task', null, $task->title, 'on stage '.$taskStage->title, $settings, $task->created_by);
65 148 }
66 149
67 150 public function boardStagesReOrdered($boardId, $oldStageOrders)
68 151 {
@@ -78,22 +161,8 @@
78 161 {
79 162 // do something
80 163 }
81 164
82 - public function boardDeleted($board)
83 - {
84 - // do something // commented for better code
85 - $taskIdsByBoard = (array) Task::where('board_id', '=', $board->id)->pluck('id')->toArray();
86 - foreach ($taskIdsByBoard as $taskId) {
87 - $task = Task::find($taskId);
88 - $task->delete();
89 - do_action('fluent_boards/task_deleted', $task);
90 - }
91 -// TaskActivity::whereIn('task_id', $taskIdsByBoard)->delete();
92 -// TaskAssignee::whereIn('task_id', $taskIdsByBoard)->delete();
93 -// Task::destroy($taskIdsByBoard);
94 - }
95 -
96 165 public function boardUpdated($board, $oldBoard)
97 166 {
98 167 $boardId = $board->id;
99 168 $titleChanged = false;
@@ -108,19 +177,15 @@
108 177 $this->createLogActivity($boardId, 'changed', 'title', $oldBoard->title, $board->title);
109 178 }
110 179 }
111 180
112 - public function boardStageUpdated($boardId, $newStageLabel, $oldStageLabel)
181 + public function boardStageUpdated($boardId, $newStage, $oldStage)
113 182 {
183 + $newStageLabel = $newStage['title'];
184 + $oldStageLabel = $oldStage->title;
114 185 $this->createLogActivity($boardId, 'updated', 'title of stage', $oldStageLabel, $newStageLabel);
115 186 }
116 187
117 - public function boardStageDragged($stage)
118 - {
119 - $message = sprintf(__('had changed the position of <em><strong>%1s</strong></em> stage.', 'fluent-boards'), $stage->label);
120 - $this->createLogActivity($stage->board_id,'moved', 'stage', $stage->label);
121 - }
122 -
123 188 public function boardStageAdded($board, $stage)
124 189 {
125 190 $this->createLogActivity($board->id,'created', 'stage', null, $stage->title);
126 191 }
@@ -133,10 +198,11 @@
133 198 {
134 199 $this->createLogActivity($board->id,'deleted', 'stage', $stageTobeDeleted);
135 200 }
136 201
137 - public function boardStageArchived($boardId, $stageTitle)
202 + public function boardStageArchived($boardId, $stage)
138 203 {
204 + $stageTitle = $stage->title;
139 205 $this->createLogActivity($boardId,'archived', 'stage', $stageTitle);
140 206 }
141 207
142 208 public function boardArchivedStageRestore($boardId, $stageTitle)
@@ -143,13 +209,19 @@
143 209 {
144 210 $this->createLogActivity($boardId,'restored', 'stage', $stageTitle);
145 211 }
146 212
147 - public function boardMemberAdded($boardId, $memberName)
213 + public function boardMemberAdded($boardId, $boardMember)
148 214 {
149 - $this->createLogActivity($boardId,'added', 'member', $memberName, null, '');
215 + $this->createLogActivity($boardId,'added', 'member', $boardMember->dispaly_name, null, '');
150 216 }
151 217
218 + public function boardViewerAdded($boardId, $boardMember)
219 + {
220 + $this->createLogActivity($boardId,'added', 'viewer', $boardMember->dispaly_name, null, '');
221 +
222 + }
223 +
152 224 public function boardMemberRemoved($boardId, $memberName)
153 225 {
154 226 $this->createLogActivity($boardId,'removed', 'member', $memberName, 'from board');
155 227 }
@@ -182,21 +254,48 @@
182 254 $this->createLogActivity($task->board_id, 'deleted', 'task', $task->title);
183 255 }
184 256 }
185 257
186 - public function taskarchivedOnBoard($task)
258 + public function taskArchivedOnBoard($task)
187 259 {
188 260 if(!$task->archived_at){
189 261 $this->createLogActivity($task->board_id, 'restored', 'task', $task->title);
190 - $this->updateBoardTaskCount($task->board_id, 1);
262 + $this->updateBoardTaskCount($task->board_id);
191 263 }else{
192 264 $this->createLogActivity($task->board_id, 'archived', 'task', $task->title);
193 - $this->updateBoardTaskCount($task->board_id, -1);
265 + $this->updateBoardTaskCount($task->board_id);
194 266 }
195 267 }
196 268
197 - public function boardLabelActivity($label, $action)
269 + /**
270 + * Log one board activity for a stage-level bulk task move.
271 + *
272 + * @param int $boardId
273 + * @param Stage $sourceStage
274 + * @param Stage $targetStage
275 + * @param int $taskCount
276 + * @return void
277 + */
278 + public function tasksMovedBetweenStages($boardId, $sourceStage, $targetStage, $taskCount)
198 279 {
280 + $description = sprintf(
281 + /* translators: %d is the number of tasks moved */
282 + _n('%d task moved', '%d tasks moved', $taskCount, 'fluent-boards'),
283 + $taskCount
284 + );
285 +
286 + $this->createLogActivity(
287 + $boardId,
288 + 'moved',
289 + 'tasks',
290 + $sourceStage->title,
291 + $targetStage->title,
292 + $description
293 + );
294 + }
295 +
296 + public function boardLabelCreatedActivity($label)
297 + {
199 298 $column = 'label';
200 299 $settings = [
201 300 'bg_color' => $label->bg_color,
202 301 'color' => $label->color,
@@ -203,9 +302,9 @@
203 302 'title' => $label->title ?? ''
204 303 ];
205 304 $this->createLogActivity(
206 305 $label->board_id,
207 - $action,
306 + 'created',
208 307 $column,
209 308 null,
210 309 null,
211 310 null,
@@ -212,8 +311,60 @@
212 311 $settings
213 312 );
214 313 }
215 314
315 + public function boardLabelUpdatedActivity($label)
316 + {
317 + $column = 'label';
318 + $settings = [
319 + 'bg_color' => $label->bg_color,
320 + 'color' => $label->color,
321 + 'title' => $label->title ?? ''
322 + ];
323 + $this->createLogActivity(
324 + $label->board_id,
325 + 'updated',
326 + $column,
327 + null,
328 + null,
329 + null,
330 + $settings
331 + );
332 + }
333 +
334 + public function boardLabelDeletedActivity($label)
335 + {
336 + $column = 'label';
337 + $settings = [
338 + 'bg_color' => $label->bg_color,
339 + 'color' => $label->color,
340 + 'title' => $label->title ?? ''
341 + ];
342 + $this->createLogActivity(
343 + $label->board_id,
344 + 'deleted',
345 + $column,
346 + null,
347 + null,
348 + null,
349 + $settings
350 + );
351 + }
352 +
353 + public function defaultAssigneesUpdated($stage, $assignees)
354 + {
355 + $column = 'default assignees of stage';
356 +
357 + $this->createLogActivity(
358 + $stage->board_id,
359 + 'updated',
360 + $column,
361 + null,
362 + null,
363 + $stage->title
364 + );
365 + }
366 +
216 367 public static function getCurrencies()
217 368 {
218 369 return [
219 370 'AED' => 'United Arab Emirates Dirham',
@@ -355,11 +506,11 @@
355 506 }
356 507 public function taskMovedFromBoard($task, $oldBoard, $newBoard)
357 508 {
358 509 // add tasks_count in the board
359 - $this->updateBoardTaskCount($newBoard->id, 1);
510 + $this->updateBoardTaskCount($newBoard->id);
360 511 // subtract tasks_count in the board
361 - $this->updateBoardTaskCount($oldBoard->id, -1);
512 + $this->updateBoardTaskCount($oldBoard->id);
362 513
363 514 $this->createLogActivity($oldBoard->id, 'moved', 'task', $task->title . ' to ' . $newBoard->title);
364 515 $this->createLogActivity($newBoard->id, 'added', 'task', $task->title . ' from ' . $oldBoard->title);
365 516 }
@@ -367,9 +518,9 @@
367 518 public function deleteUserRelatedData($id, $reassign, $user)
368 519 {
369 520 try{
370 521 if(!$id) {
371 - throw new \Exception('Member Not deleted');
522 + throw new \Exception(esc_html__('Member Not deleted', 'fluent-boards'));
372 523 }
373 524 Meta::where('object_type', Constant::OBJECT_TYPE_USER)
374 525 ->where('object_id', $id)
375 526 ->delete();
@@ -380,16 +531,49 @@
380 531 Constant::OBJECT_TYPE_USER_TASK_WATCH,
381 532 Constant::TASK_ASSIGNEE
382 533 ])->delete();
383 534 }catch (\Exception $e){}
384 -
385 535 }
386 - private function updateBoardTaskCount($boardId, $count)
536 + public function updateBoardTaskCount($boardId)
387 537 {
388 538 $board = Board::find($boardId);
389 539 $settings = $board->settings ?? [];
390 -
391 - $settings['tasks_count'] = $board->tasks->where('parent_id', null)->count();
540 + $stageIds = Stage::where('board_id', $boardId)->whereNull('archived_at')->pluck('id')->toArray();
541 + $settings['tasks_count'] = $board->tasks->where('parent_id', null)->whereNull('archived_at')->whereIn('stage_id', $stageIds)->count();
392 542 $board->settings = $settings;
393 543 $board->save();
394 544 }
545 +
546 + /**
547 + * Delete a board-owned previous background attachment and log the change.
548 + *
549 + * @param int $boardId
550 + * @param array|string $oldBackground
551 + * @return void
552 + */
553 + public function backgroundUpdated($boardId, $oldBackground)
554 + {
555 + if (
556 + is_array($oldBackground) &&
557 + !empty($oldBackground['is_image']) &&
558 + !empty($oldBackground['image_url'])
559 + ) {
560 + // Only the target board's background attachment may be removed by this hook.
561 + if (!empty($oldBackground['id'])) {
562 + $attachment = Attachment::where('id', absint($oldBackground['id']))
563 + ->where('object_id', absint($boardId))
564 + ->where('object_type', Constant::BOARD_BACKGROUND_IMAGE)
565 + ->first();
566 +
567 + if ($attachment) {
568 + $deletedAttachment = clone $attachment;
569 + $attachment->delete();
570 + (new FileHandler())->deleteAttachmentFile($deletedAttachment, absint($boardId));
571 + }
572 + }
573 + }
574 +
575 + $this->createLogActivity($boardId, 'changed', 'board background', null, null);
576 + }
577 +
578 +
395 579 }