PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / trunk
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration vtrunk
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
← All changes | app/Services/BoardService.php +78 -20 2.0.10trunk View file →
@@ -2,8 +2,9 @@
2 2
3 3 namespace FluentBoards\App\Services;
4 4
5 5 use FluentBoards\App\Models\Activity;
6 +use FluentBoards\App\Models\Attachment;
6 7 use FluentBoards\App\Models\Board;
7 8 use FluentBoards\App\Models\Comment;
8 9 use FluentBoards\App\Models\Folder;
9 10 use FluentBoards\App\Models\Label;
@@ -149,9 +150,9 @@
149 150 {
150 151 $boardData = [
151 152 'title' => $boardData['title'],
152 153 'type' => $boardData['type'] ? $boardData['type'] : 'to-do',
153 - 'description' => DescriptionMarkdownConverter::normalize($boardData['description']),
154 + 'description' => DescriptionMarkdownConverter::normalize($boardData['description'] ?? ''),
154 155 'currency' => isset($boardData['currency']) ? $boardData['currency'] : 'USD',
155 156 'background' => isset($boardData['background']) ? $boardData['background'] : '',
156 157 'created_by' => isset($boardData['created_by']) ? $boardData['created_by'] : get_current_user_id()
157 158 ];
@@ -372,14 +373,29 @@
372 373
373 374 return $isAlreadyMember ?? false;
374 375 }
375 376
377 + /**
378 + * Add a WordPress user to a board.
379 + *
380 + * @return User|false|null User on success, false for an existing relation,
381 + * or null when the board/user does not exist.
382 + */
376 383 public function addMembersInBoard($boardId, $memberId, $isViewerOnly = null)
377 384 {
385 + $boardId = intval($boardId);
386 + $memberId = intval($memberId);
387 + $isViewerOnly = sanitize_text_field((string)$isViewerOnly);
388 +
389 + if ($boardId <= 0 || $memberId <= 0) {
390 + return null;
391 + }
392 +
378 393 $board = Board::find($boardId);
394 + $boardMember = User::find($memberId);
379 395
380 - if (!$board) {
381 - return false;
396 + if (!$board || !$boardMember) {
397 + return null;
382 398 }
383 399 $isAlreadyMember = $this->isAlreadyMember($boardId, $memberId);
384 400 if($isAlreadyMember) {
385 401 return false;
@@ -399,9 +415,8 @@
399 415 'settings' => maybe_serialize($settings),
400 416 'preferences' => maybe_serialize(Constant::BOARD_NOTIFICATION_TYPES)
401 417 ]
402 418 );
403 - $boardMember = User::find($memberId);
404 419 if(!$isViewerOnly) {
405 420 do_action('fluent_boards/board_member_added', $boardId, $boardMember);
406 421 } else {
407 422 do_action('fluent_boards/board_viewer_added', $boardId, $boardMember);
@@ -522,20 +537,31 @@
522 537
523 538 /**
524 539 * Change or clear the board background.
525 540 *
526 - * @param mixed $backgroundData
541 + * Image attachments must belong to the target board and use the board
542 + * background attachment type before their identifiers can be persisted.
543 + *
544 + * @param array $backgroundData
545 + * @param int $board_id
527 546 * @return array|string
547 + * @throws \Exception
528 548 */
529 549 public function setBoardBackground($backgroundData, $board_id)
530 550 {
531 - $board = Board::find($board_id);
551 + $boardId = absint($board_id);
552 + $board = Board::find($boardId);
553 +
554 + if (!$board) {
555 + throw new \Exception(esc_html__('Board not found.', 'fluent-boards'));
556 + }
557 +
532 558 $oldBackground = $board->background;
533 559
534 560 if (!empty($backgroundData['reset'])) {
535 561 $board->background = '';
536 562 $board->save();
537 - do_action('fluent_boards/board_background_updated', $board_id, $oldBackground);
563 + do_action('fluent_boards/board_background_updated', $boardId, $oldBackground);
538 564
539 565 return $board->background;
540 566 }
541 567
@@ -543,26 +569,34 @@
543 569 if (!is_array($background)) {
544 570 $background = [];
545 571 }
546 572
547 - // if board background has color
548 - if (isset($backgroundData['color'])) {
573 + // Resolve image metadata from the board-owned attachment, never from the client URL.
574 + if (isset($backgroundData['image_url'])) {
575 + $attachmentId = absint($backgroundData['id'] ?? 0);
576 + $attachment = Attachment::where('id', $attachmentId)
577 + ->where('object_id', $boardId)
578 + ->where('object_type', Constant::BOARD_BACKGROUND_IMAGE)
579 + ->first();
580 +
581 + if (!$attachment) {
582 + throw new \Exception(esc_html__('Background image not found.', 'fluent-boards'));
583 + }
584 +
585 + $background['id'] = (int) $attachment->id;
586 + $background['image_url'] = (new CommentService())->createPublicUrl($attachment, $boardId);
587 + $background['is_image'] = true;
588 + $background['color'] = null;
589 + } elseif (isset($backgroundData['color'])) {
590 + $background['id'] = $backgroundData['id'];
549 591 $background['color'] = $backgroundData['color'];
550 592 $background['image_url'] = null;
551 593 $background['is_image'] = false;
552 594 }
553 595
554 - // if board background has image
555 - if (isset($backgroundData['image_url'])) {
556 - $background['image_url'] = $backgroundData['image_url'];
557 - $background['is_image'] = true;
558 - $background['color'] = null;
559 - }
560 - $background['id'] = $backgroundData['id'];
561 -
562 596 $board->background = $background;
563 597 $board->save();
564 - do_action('fluent_boards/board_background_updated', $board_id, $oldBackground);
598 + do_action('fluent_boards/board_background_updated', $boardId, $oldBackground);
565 599
566 600 return $board->background;
567 601 }
568 602
@@ -910,11 +944,35 @@
910 944 ->where('key', Constant::BOARD_INVITATION)
911 945 ->get();
912 946 }
913 947
914 - public function deleteInvitation($invitationId)
948 + /**
949 + * Delete an invitation only when it belongs to the supplied board.
950 + *
951 + * The optional second argument lets older Pro releases receive a controlled
952 + * error instead of reporting a successful deletion that never happened.
953 + */
954 + public function deleteInvitation($boardId, $invitationId = null)
915 955 {
916 - Meta::findOrFail($invitationId)->delete();
956 + if ($invitationId === null) {
957 + throw new \Exception(
958 + __('A board ID is required to delete an invitation.', 'fluent-boards')
959 + );
960 + }
961 +
962 + $boardId = intval($boardId);
963 + $invitationId = intval($invitationId);
964 +
965 + if ($boardId <= 0 || $invitationId <= 0) {
966 + return false;
967 + }
968 +
969 + return (bool) Meta::query()
970 + ->where('id', $invitationId)
971 + ->where('object_id', $boardId)
972 + ->where('object_type', Constant::OBJECT_TYPE_BOARD)
973 + ->where('key', Constant::BOARD_INVITATION)
974 + ->delete();
917 975 }
918 976
919 977 public function hasDataChanged($boardId, $includeArchived = false, $since = null)
920 978 {