PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.12
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.12
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 1.45 All 41 releases
fluent-boards / app / Http / Controllers / BoardController.php

BoardController.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 1.12, at app/Http/Controllers/BoardController.php

901 lines 29.5 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\Http\Controllers;
4
5 use FluentBoards\App\Models\Meta;
6 use FluentBoards\App\Models\Relation;
7 use FluentBoards\App\Models\Task;
8 use FluentBoards\App\Models\User;
9 use FluentBoards\App\Models\Board;
10 use FluentBoards\App\Services\Constant;
11 use FluentBoards\App\Services\Helper;
12 use FluentBoards\App\Models\Stage;
13 use FluentBoards\App\Services\InstallService;
14 use FluentBoards\App\Services\StageService;
15 use FluentBoards\App\Services\TaskService;
16 use FluentBoards\App\Services\BoardService;
17 use FluentBoards\App\Services\UserService;
18 use FluentBoards\Framework\Http\Request\Request;
19 use FluentBoards\App\Services\PermissionManager;
20 use FluentBoards\App\Hooks\Handlers\BoardHandler;
21 use FluentBoards\App\Services\LabelService;
22 use FluentBoards\Framework\Support\Arr;
23 use FluentBoards\Framework\Support\Collection;
24 use FluentCrm\App\Models\Subscriber;
25
26 class BoardController extends Controller
27 {
28 private $boardService;
29 private $taskService;
30 private $stageService;
31 private $labelService;
32
33 public function __construct(
34 BoardService $boardService,
35 TaskService $taskService,
36 StageService $stageService,
37 LabelService $labelService
38 )
39 {
40 parent::__construct();
41 $this->boardService = $boardService;
42 $this->taskService = $taskService;
43 $this->stageService = $stageService;
44 $this->labelService = $labelService;
45 }
46
47 public function getBoards(Request $request)
48 {
49 $per_page = $request->getSafe('per_page', 'intval', 20);
50 $userId = get_current_user_id();
51 $type = $request->getSafe('type', 'sanitize_text_field', 'to-do');
52
53 $order = $request->getSafe('order', 'sanitize_text_field', 'created_at');
54 $orderBy = $request->getSafe('orderBy', 'sanitize_text_field', 'DESC');
55 $searchInput = $request->getSafe('searchInput', 'sanitize_text_field');
56
57 $relatedBoardsQuery = Board::where('type', $type)
58 ->byAccessUser($userId);
59 if (!empty($searchInput)) {
60 $relatedBoardsQuery = $relatedBoardsQuery->where('title', 'like', '%' . $searchInput . '%');
61 }
62
63 $relatedBoards = $relatedBoardsQuery->orderBy($order, $orderBy)
64 ->withCount('completedTasks')
65 ->with('stages', 'users')
66 ->paginate($per_page);
67
68 foreach ($relatedBoards as $relatedBoard) {
69 $relatedBoard->users = Helper::sanitizeUserCollections($relatedBoard->users);
70 }
71
72 return $this->sendSuccess([
73 'boards' => $relatedBoards
74 ], 200);
75 }
76
77 public function getBoardsList(Request $request)
78 {
79 try {
80 $userId = get_current_user_id();
81 $type = $request->getSafe('type', 'sanitize_text_field', 'to-do');
82
83 if (PermissionManager::isAdmin($userId)) {
84 $relatedBoardsQuery = Board::query()->where('type', $type);
85 } else {
86 $currentUser = User::find($userId);
87 $relatedBoardsQuery = $currentUser->whichBoards()->where('type', $type);
88 }
89
90 $relatedBoards = $relatedBoardsQuery->with('stages')->get();
91 $stages = Stage::whereIn('board_id', $relatedBoards->pluck('id'))->get();
92
93 return $this->sendSuccess([
94 'boards' => $relatedBoards,
95 'all_stages' => $stages,
96 ], 200);
97 } catch (\Exception $e) {
98 return $this->sendError($e->getMessage(), 404);
99 }
100 }
101
102 public function getRecentBoards()
103 {
104 $boards = $this->boardService->getRecentBoards();
105
106 if (!$boards || $boards->isEmpty()) {
107 $boards = Board::where('type', 'to-do')->byAccessUser(get_current_user_id())
108 ->limit(4)
109 ->withCount('completedTasks')
110 ->with(['stages', 'users'])
111 ->get();
112 }
113
114 foreach ($boards as $board) {
115 $board->users = Helper::sanitizeUserCollections($board->users);
116 }
117
118 return [
119 'boards' => $boards,
120 ];
121 }
122
123 public function getBoardMeta($board_id)
124 {
125 $boards = $this->boardService->fetchBoardMeta($board_id);
126
127 return $this->sendSuccess([
128 'boards' => $boards,
129 ], 200);
130 }
131
132 public function setAuthenticationPermission(Request $request, $board_id)
133 {
134 $boardData = $this->boardSanitizeAndValidate($request->only([
135 'is_auth_require_idea_submit',
136 'is_auth_require_voting_commenting',
137 'is_auth_require_reaction',
138 'is_allow_email_along_with_auth',
139 'is_allow_unauthentication_reaction_along_with_auth'
140 ]), [
141 'is_auth_require_idea_submit' => 'required',
142 'is_auth_require_voting_commenting' => 'required',
143 'is_auth_require_reaction' => 'required',
144 'is_allow_email_along_with_auth' => 'nullable',
145 'is_allow_unauthentication_reaction_along_with_auth' => 'nullable'
146 ]);
147
148 try {
149 $boards = $this->boardService->modifyAuthenticationPermission($boardData, $board_id);
150
151 return $this->sendSuccess([
152 'message' => __("Board has been updated", 'fluent-boards'),
153 'boards' => $boards,
154 ], 200);
155 } catch (\Exception $e) {
156 return $this->sendError($e->getMessage(), 404);
157 }
158 }
159
160 public function getBoardsByType($type)
161 {
162 $boards = $this->boardService->getBoardsByType($type);
163
164 return $this->sendSuccess([
165 'boards' => $boards,
166 ], 200);
167 }
168
169 public function createFirstBoard(Request $request)
170 {
171 $boardData = $this->boardSanitizeAndValidate($request->get('board'), [
172 'title' => 'required|string',
173 'description' => 'nullable',
174 'type' => 'required|string',
175 'currency' => 'nullable|string',
176 'crm_contact_id' => 'nullable|numeric',
177 ]);
178
179 $installFluentCRM = $request->get('withFluentCRM') == 'yes' ? true : false;
180
181 $postStages = $request->get('stages');
182 $stageData = array();
183 foreach ($postStages as $stage) {
184 $temp = $this->stageSanitizeAndValidate($stage, [
185 'title' => 'required|string',
186 ]);
187 $stageData[] = $temp;
188 }
189
190 $taskData = null;
191 if ($request->get('task')) {
192 $taskData = $this->taskSanitizeAndValidate($request->get('task'), [
193 'title' => 'required|string'
194 ]);
195 }
196
197 $board = $this->boardService->createBoard($boardData);
198 $this->labelService->createDefaultLabel($board->id);
199 $type = ucfirst($boardData['type']);
200 $stage = $this->stageService->createStages($board, $stageData);
201
202 if ($taskData) {
203 $taskData['board_id'] = $board->id;
204 $taskData['stage_id'] = $stage->id;
205 $this->taskService->createTask($taskData, $board->id);
206 }
207
208 do_action('fluent_boards/board_created', $board);
209
210 if ($installFluentCRM && !defined('FLUENTCRM')) {
211 InstallService::install('fluent-crm');
212 }
213
214 return [
215 'message' => __('Board has been created', 'fluent-boards'),
216 'board' => $board,
217 ];
218 }
219
220 public function create(Request $request)
221 {
222 $boardData = $this->boardSanitizeAndValidate($request->get('board'), [
223 'title' => 'required|string',
224 'description' => 'nullable',
225 'type' => 'required|string',
226 'currency' => 'nullable|string',
227 'crm_contact_id' => 'nullable|numeric',
228 ]);
229
230 try {
231 $board = $this->boardService->createBoard($boardData);
232 $this->labelService->createDefaultLabel($board->id);
233 $type = ucfirst($boardData['type']);
234
235 if (isset($boardData['is_roadmap']) && $boardData['is_roadmap'] == 'yes') {
236 $this->stageService->createRoadmapStages($board, $boardData['stages']);
237 } else {
238 $this->stageService->createDefaultStages($board);
239 }
240
241 // if board is created from crm contact
242 if (isset($boardData['crm_contact_id'])) {
243 $this->boardService->updateAssociateMember($boardData['crm_contact_id'], $board->id);
244 }
245
246 do_action('fluent_boards/board_created', $board);
247
248 $message = __('Board has been created successfully', 'fluent-boards');
249
250 return $this->sendSuccess([
251 'message' => $message,
252 'board' => $board,
253 ], 201);
254 } catch (\Exception $e) {
255 return $this->sendError($e->getMessage(), 400);
256 }
257 }
258
259 public function getArchivedStage(Request $request, $board_id)
260 {
261 try {
262 $pagination = $request->noPagination ? true : false;
263 $per_page = isset($data['per_page']) ? $data['per_page'] : 30;
264 $page = isset($data['page']) ? $data['page'] : 1;
265 if ($pagination) {
266 $stages = Stage::where('board_id', $board_id)
267 ->whereNotNull('archived_at')
268 ->orderBy('created_at', 'DESC')
269 ->get();
270 } else {
271 $stages = Stage::where('board_id', $board_id)
272 ->whereNotNull('archived_at')
273 ->orderBy('created_at', 'DESC')
274 ->paginate($per_page, ['*'], 'page', $page);
275 }
276
277 return $this->sendSuccess([
278 'stages' => $stages,
279 ], 200);
280 } catch (\Exception $e) {
281 return $this->sendError($e->getMessage(), 404);
282 }
283 }
284
285 public function find($board_id)
286 {
287 $board = Board::findOrFail($board_id);
288 $board->background = maybe_unserialize($board->background);
289 $board->createdOn = $board->created_at->format('Y-m-d');
290
291 $board->load(['users', 'stages', 'labels', 'owner']);
292 $this->boardService->updateRecentOpenedBoards($board_id);
293
294 $board->labelColor = Constant::TRELLO_COLOR_MAP;
295 $board->labelColorText = Constant::TEXT_COLOR_MAP;
296
297 $board->users = Helper::sanitizeUserCollections($board->users);
298 $board->owner = Helper::sanitizeUserCollections($board->owner);
299
300 $board = apply_filters('fluent_boards/board_find', $board);
301
302 return [
303 'board' => $board
304 ];
305 }
306
307 public function update(Request $request, $board_id)
308 {
309 $boardData = $this->boardSanitizeAndValidate($request->only(['title', 'description']), [
310 'title' => 'required|string',
311 'description' => 'nullable|string',
312 ]);
313
314 $board = Board::findOrFail($board_id);
315
316 $oldBoard = clone $board;
317 $board->fill($boardData);
318 $board->save();
319
320 do_action('fluent_boards/board_updated', $board, $oldBoard);
321
322 return [
323 'stages' => $board->stages()->get(),
324 'message' => __('Board has been updated', 'fluent-boards'),
325 'board' => $board,
326 ];
327 }
328
329 public function archiveStage($board_id, $stage_id)
330 {
331 try {
332 $stage = Stage::findOrFail($stage_id);
333 $board = Board::findOrFail($stage->board_id);
334
335 $updatedStage = $this->boardService->archiveStage($board->id, $stage);
336
337 return $this->sendSuccess([
338 'updatedStage' => $updatedStage,
339 'message' => __('Stage has been archived', 'fluent-boards'),
340 ], 200);
341 } catch (\Exception $e) {
342 return $this->sendError($e->getMessage(), 400);
343 }
344 }
345
346 public function restoreStage($board_id, $stage_id)
347 {
348 try {
349 $stage = Stage::findOrFail($stage_id);
350 $board = Board::findOrFail($board_id);
351
352 $updatedStage = $this->boardService->restoreStage($board->id, $stage);
353
354 return $this->sendSuccess([
355 'success' => true,
356 'updatedStage' => $updatedStage,
357 'message' => __('Stage has been restored', 'fluent-boards')
358 ], 200);
359 } catch (\Exception $e) {
360 return $this->sendError($e->getMessage(), 400);
361 }
362 }
363
364
365 public function changePositionOfStage(Request $request, $board_id)
366 {
367 $changeData = $this->boardSanitizeAndValidate($request->only(['fromPosition', 'toPosition']), [
368 'fromPosition' => 'required',
369 'toPosition' => 'required',
370 ]);
371
372 try {
373 $this->boardService->changePositionOfStage($board_id, $changeData);
374
375 return $this->sendSuccess([
376 'message' => __('Board stage has been updated', 'fluent-boards')
377 ], 200);
378 } catch (\Exception $e) {
379 return $this->sendError($e->getMessage(), 400);
380 }
381 }
382
383 public function rePositionStages(Request $request, $board_id)
384 {
385 $incomingList = $request->get('list');
386 try {
387 $this->boardService->rePositionStages($board_id, $incomingList);
388 return $this->sendSuccess([
389 'message' => __('Stages Reordered', 'fluent-boards'),
390 'updatedStages' => $this->stageService->getLastOneMinuteUpdatedStages($board_id)
391 ], 200);
392 } catch (\Exception $e) {
393 return $this->sendError($e->getMessage(), 400);
394 }
395 }
396
397 public function getAssigneesByBoard($board_id)
398 {
399 return $this->sendSuccess([
400 'data' => $this->boardService->getAssigneesByBoard($board_id),
401 ], 200);
402 }
403
404 public function delete($board_id)
405 {
406 try {
407 if (!PermissionManager::isAdmin()) {
408 throw new \Exception('You do not have permission to delete this board', 400);
409 }
410 $this->boardService->deleteBoard($board_id);
411
412 return $this->sendSuccess([
413 'message' => __('Board has been deleted', 'fluent-boards'),
414 ], 200);
415 } catch (\Exception $e) {
416 return $this->sendError($e->getMessage(), 400);
417 }
418 }
419
420 public function getCurrencies()
421 {
422 return BoardHandler::getCurrencies();
423 }
424
425 public function getActivities(Request $request, $board_id)
426 {
427 try {
428 $activities = $this->boardService->getActivities($board_id, $request->all());
429 return $this->sendSuccess([
430 'activities' => $activities,
431 ], 200);
432 } catch (\Exception $e) {
433 return $this->sendError($e->getMessage(), 404);
434 }
435 }
436
437 public function getBoardUsers($board_id)
438 {
439 $board = Board::findOrFail($board_id);
440
441 $boardObjects = Relation::where('object_type', 'board_user')
442 ->where('object_id', $board_id)
443 ->get()->keyBy('foreign_id');
444
445 $userIds = $boardObjects->pluck('foreign_id')->toArray();
446
447 $coreUsers = [];
448 if ($userIds) {
449 // Get the users who are in the board (members and managers
450 $coreUsers = get_users([
451 'include' => $userIds
452 ]);
453 }
454
455 $formattedUsers = [];
456
457 foreach ($coreUsers as $user) {
458 $name = trim($user->first_name . ' ' . $user->last_name);
459 if (!$name) {
460 $name = $user->display_name;
461 }
462
463 $boardRelation = $boardObjects[$user->ID] ?? null;
464
465 $formattedUsers[] = [
466 'ID' => $user->ID,
467 'display_name' => $name,
468 'email' => $user->user_email,
469 'photo' => fluent_boards_user_avatar($user->user_email, $name),
470 'role' => $boardRelation && $boardRelation->settings['is_admin'] ? 'manager' : 'member'
471 ];
472 }
473
474 // order formatted users by display_name
475 usort($formattedUsers, function ($a, $b) {
476 return strcmp($a['display_name'], $b['display_name']);
477 });
478
479 $returnData = [
480 'users' => Helper::sanitizeUsersArray($formattedUsers),
481 'global_admins' => []
482 ];
483
484 if (!PermissionManager::isAdmin(get_current_user_id())) {
485 return $returnData;
486 }
487
488 /*
489 * These are the rest of the admin users who are not in the board
490 */
491 $adminUserIds = Meta::query()->where('object_type', Constant::FLUENT_BOARD_ADMIN)
492 ->whereNotIn('object_id', $userIds)
493 ->get()
494 ->pluck('object_id')
495 ->toArray();
496
497 if ($adminUserIds) {
498 $adminUsers = get_users([
499 'include' => $adminUserIds,
500 ]);
501
502 $formattedAdminUsers = [];
503
504 foreach ($adminUsers as $user) {
505 $name = trim($user->first_name . ' ' . $user->last_name);
506 if (!$name) {
507 $name = $user->display_name;
508 }
509
510 $formattedAdminUsers[] = [
511 'ID' => $user->ID,
512 'display_name' => $name,
513 'email' => $user->user_email,
514 'photo' => fluent_boards_user_avatar($user->user_email, $name),
515 'role' => 'admin'
516 ];
517 }
518
519 // order formatted users by display_name
520 usort($formattedAdminUsers, function ($a, $b) {
521 return strcmp($a['display_name'], $b['display_name']);
522 });
523
524 $returnData['global_admins'] = Helper::sanitizeUsersArray($formattedAdminUsers);
525 }
526
527 return $this->sendSuccess($returnData, 200);
528 }
529
530
531 public function removeUserFromBoard($board_id, $userId)
532 {
533 $this->boardService->removeUserFromBoard($board_id, $userId);
534
535 if (!PermissionManager::isAdmin($userId)) {
536 $this->boardService->removeFromRecentlyOpened($board_id, $userId);
537 }
538
539 return [
540 'message' => __('Member removed successfully', 'fluent-boards'),
541 ];
542 }
543
544 public function addMembersInBoard(Request $request, $board_id)
545 {
546 $memberId = $request->getSafe('memberId');
547 $isAlreadyMember = $this->boardService->isAlreadyMember($board_id, $memberId);
548
549 if ($isAlreadyMember) {
550 return $this->sendError([
551 'message' => __('User already a member', 'fluent-boards'),
552 ], 304);
553 }
554 $member = $this->boardService->addMembersInBoard($board_id, $memberId);
555
556 return [
557 'message' => __('Member added successfully', 'fluent-boards'),
558 'member' => Helper::sanitizeUserCollections($member)
559 ];
560 }
561
562 private function boardSanitizeAndValidate($data, array $rules = [])
563 {
564 $data = Helper::sanitizeBoard($data);
565
566 return $this->validate($data, $rules);
567 }
568
569 private function stageSanitizeAndValidate($data, array $rules = [])
570 {
571 $data = Helper::sanitizeStage($data);
572
573 return $this->validate($data, $rules);
574 }
575
576 private function taskSanitizeAndValidate($data, array $rules = [])
577 {
578 $data = Helper::sanitizeTask($data);
579
580 return $this->validate($data, $rules);
581 }
582
583 public function searchBoards(Request $request)
584 {
585 $per_page = $request->get('per_page', 10);
586 $search_input = $request->searchInput . trim('');
587 $type = $request->type;
588
589 $currentUserId = get_current_user_id();
590
591 if (PermissionManager::isAdmin($currentUserId)) {
592 $boards = Board::query()->where('type', $type)
593 ->where('title', 'like', '%' . $search_input . '%')
594 ->with('stages', 'tasks', 'users')
595 ->paginate($per_page);
596
597 foreach ($boards as $board) {
598 $board->users = Helper::sanitizeUserCollections($board->users);
599 }
600
601 } else {
602 $currentUser = User::find($currentUserId);
603 $boards = $currentUser->boards()->where('type', $type)->where('title', 'like', '%' . $search_input . '%')->paginate($per_page);
604 }
605
606 return [
607 'boards' => $boards,
608 ];
609 }
610
611 public function getUsersOfBoards()
612 {
613 $userBoards = $this->boardService->getUsersOfBoards();
614
615 return $this->sendSuccess([
616 'userBoards' => $userBoards,
617 ], 200);
618 }
619
620
621
622 /**
623 * Refactor this code form me - Masiur
624 * change stage settings is_public for roadmap user and admin view
625 * @param $board_id
626 * @param $stage_id
627 * @return
628 */
629 public function changeStageView($board_id, $stage_id)
630 {
631 try {
632 $stage = Stage::findOrFail($stage_id);
633 $message = __('The stage is made public!', 'fluent-boards');
634 $settings = $stage->settings;
635
636 if (isset($settings['is_public'])) {
637 if ($settings['is_public']) {
638 $settings['is_public'] = false;
639 $message = __('The stage is made admin only!', 'fluent-boards');
640 } else {
641 $settings['is_public'] = true;
642 }
643 } else {
644 $settings['is_public'] = true;
645 }
646
647 $stage->settings = $settings;
648 $stage->save();
649 return $this->sendSuccess([
650 'message' => $message,
651 'stage' => $stage
652 ]);
653 } catch (\Exception $e) {
654 return $this->sendError($e->getMessage(), 400);
655 }
656 }
657
658
659 /**
660 * Set board background image or color
661 * @param \FluentBoards\Framework\Http\Request\Request $request
662 * @return
663 */
664 public function setBoardBackground(Request $request, $board_id)
665 {
666 // sanitize and validate image_url
667 if ($request->image_url) {
668 $backgroundData = $this->boardSanitizeAndValidate($request->all(), [
669 "id" => 'required',
670 'image_url' => 'required|string|url',
671 ]);
672 }
673
674 // sanitize and validate color
675 if ($request->color) {
676 $backgroundData = $this->boardSanitizeAndValidate($request->all(), [
677 "id" => 'required',
678 'color' => 'required',
679 ]);
680 }
681
682 try {
683 if (!$board_id) {
684 $errorMessage = __('Board id is required', 'fluent-boards');
685 throw new \Exception($errorMessage, 400);
686 }
687
688 return $this->sendSuccess([
689 'message' => __('Background updated successfully', 'fluent-boards'),
690 'background' => $this->boardService->setBoardBackground($backgroundData, $board_id),
691 ]);
692 } catch (\Exception $e) {
693 $this->sendError([$e->getMessage(), 400]);
694 }
695 }
696
697
698 /**
699 * Summary of getStageTaskAvailablePositions
700 * @param mixed $board_id
701 * @param mixed $stage_slug
702 * @return $availablePositions as an array
703 * @throws \Exception
704 */
705 public function getStageTaskAvailablePositions($board_id, $stage_id)
706 {
707 try {
708 if ($board_id && $stage_id) {
709 $availablePositions = $this->boardService->getStageTaskAvailablePositions($board_id, $stage_id);
710 return $this->sendSuccess([
711 'availablePositions' => $availablePositions
712 ], 200);
713 } else {
714 $message = '';
715 if (!$board_id) {
716 $message = 'Board id ';
717 }
718 if (!$stage_id) {
719 $message = 'Stage ';
720 }
721 throw new \Exception($message . 'is required', 400);
722 }
723 } catch (\Exception $e) {
724 $this->sendError([$e->getMessage(), 400]);
725 }
726 }
727
728 public function getAssociateCrmContacts($board_id)
729 {
730 try {
731 $contactAssociatedTasks = Task::with('board')->where('board_id', $board_id)
732 ->whereNotNull('crm_contact_id')
733 ->get();
734
735 $formattedContacts = Collection::make($contactAssociatedTasks)
736 ->groupBy('crm_contact_id')
737 ->map(function ($tasks, $contactId) {
738 $subscriber = Subscriber::find($contactId);
739 if (!$subscriber) {
740 return null; // Skip if subscriber not found
741 }
742
743 return [
744 'name' => $subscriber->first_name . ' ' . $subscriber->last_name,
745 'photo' => $subscriber->photo,
746 'email' => $subscriber->email,
747 'crm_contact_id' => $contactId,
748 'id' => $contactId,
749 'tasks' => $tasks,
750 ];
751 })
752 ->filter()->toArray();
753
754
755 return $this->sendSuccess([
756 'associatedContacts' => $formattedContacts
757 ], 200);
758 } catch (\Exception $e) {
759 return $this->sendError($e->getMessage(), 404);
760 }
761 }
762
763 public function updateAssociateCrmContact(Request $request, $board_id)
764 {
765 $value = $request->getSafe('value');
766 $this->boardService->updateAssociateMember($value, $board_id);
767
768 return $this->sendSuccess([
769 'message' => __('Associated Crm Member has been updated', 'fluent-boards'),
770 ], 200);
771 }
772
773 public function hasDataChanged($board_id)
774 {
775 return $this->boardService->hasDataChanged($board_id);
776 }
777
778 public function createStage(Request $request, $board_id)
779 {
780 $stageData = $this->stageSanitizeAndValidate($request->all(), [
781 'title' => 'required|string',
782 ]);
783
784 $board = Board::find($board_id);
785 $stage = $this->stageService->createStage($stageData, $board_id);
786
787 do_action('fluent_boards/board_stage_added', $board, $stage);
788
789 $updatedStates = (new StageService())->getLastOneMinuteUpdatedStages($board_id);
790
791 return [
792 'updatedStages' => $updatedStates,
793 'message' => __('stage has been created', 'fluent-boards'),
794 ];
795 }
796
797 public function sortStageTasks(Request $request, $board_id, $stage_id)
798 {
799 $sort = $request->getSafe('sort', 'sanitize_text_field');
800
801 $updatedTasks = $this->stageService->sortStageTasks($sort, $stage_id);
802 return [
803 'message' => __('Tasks has been sorted', 'fluent-boards'),
804 'updatedTasks' => $updatedTasks,
805 ];
806 }
807
808 public function moveAllTasks(Request $request, $board_id)
809 {
810 $oldStageId = $request->getSafe('oldStageId');
811 $newStageId = $request->getSafe('newStageId');
812
813 $updates = $this->stageService->moveAllTasks($oldStageId, $newStageId, $board_id);
814
815 return [
816 'message' => __('Tasks has been Moved', 'fluent-boards'),
817 'updatedTasks' => $updates,
818 ];
819
820 }
821
822 public function archiveAllTasksInStage($board_id, $stage_id)
823 {
824 $updates = $this->stageService->archiveAllTasksInStage($stage_id);
825 return [
826 'message' => __('Tasks has been archived', 'fluent-boards'),
827 'updatedTasks' => $updates,
828 ];
829 }
830
831 public function getAssociatedBoards(Request $request, $associated_id)
832 {
833 $associatedBoards = $this->boardService->getAssociatedBoards($associated_id);
834 return [
835 'boards' => $associatedBoards,
836 ];
837 }
838
839 public function duplicateBoard(Request $request, $board_id)
840 {
841 $boardData = $this->taskSanitizeAndValidate($request->get('board'), [
842 'title' => 'required|string'
843 ]);
844 $isWithLabels = $request->getSafe('isWithLabels');
845 $isWithTasks = $request->getSafe('isWithTasks');
846
847 try {
848 if(!PermissionManager::isAdmin()) {
849 $errorMessage = __('You do not have permission to duplicate board', 'fluent-boards');
850 throw new \Exception($errorMessage, 400);
851 }
852 //create board
853 $newBoard = $this->boardService->copyBoard($boardData);
854
855 //label copy
856 if ($isWithLabels == 'yes') {
857 $this->labelService->copyLabelsOfBoard($board_id, $newBoard);
858 }
859
860 //stage copy
861 $stageMapForCopyingTask = $this->stageService->copyStagesOfBoard($newBoard, $board_id);
862
863 //copy tasks of selected stages
864 if ($isWithTasks == 'yes') {
865 $this->taskService->copyTasks($board_id, $stageMapForCopyingTask, $newBoard);
866 }
867
868 return $this->sendSuccess([
869 'board' => $newBoard,
870 ], 200);
871 } catch (\Exception $e) {
872 return $this->sendError($e->getMessage(), 400);
873 }
874 }
875
876 public function importFromBoard(Request $request, $board_id)
877 {
878 $selectedStages = $request->getSafe('selectedStages');
879
880 try {
881 $this->stageService->importStagesFromBoard($board_id, $selectedStages);
882
883 return $this->sendSuccess([
884 'message' => __('Import successfully', 'fluent-boards'),
885 ], 200);
886
887 } catch (\Exception $e) {
888 return $this->sendError($e->getMessage(), 400);
889 }
890 }
891
892 public function getBoardDefaultBackgroundColors()
893 {
894 return [
895 'solidColors' => Constant::BOARD_BACKGROUND_DEFAULT_SOLID_COLORS,
896 'gradients' => Constant::BOARD_BACKGROUND_DEFAULT_GRADIENT_COLORS
897 ];
898 }
899
900 }
901