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.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 1.40 All 43 releases
← All changes | app/Services/Intergrations/FluentCRM/DeepIntegration.php +180 -2 1.21 → 2.2.0 View file →
@@ -1,16 +1,26 @@
1 1 <?php
2 2
3 3 namespace FluentBoards\App\Services\Intergrations\FluentCRM;
4 4
5 -
6 5 use FluentBoards\App\Models\Board;
6 +use FluentBoards\App\Models\Task;
7 +use FluentBoards\App\Models\TaskMeta;
8 +use FluentBoards\App\Models\User;
9 +use FluentBoards\App\Services\PermissionManager;
10 +use FluentBoards\Framework\Database\Orm\Builder;
7 11
8 12 class DeepIntegration
9 13 {
14 + private const USER_TEMPLATE_OPTION_LIMIT = 50;
15 +
10 16 public function init()
11 17 {
12 18 add_filter('fluentcrm_ajax_options_boards', [$this, 'getBoards'], 10, 3);
19 + add_filter('fluentcrm_ajax_options_task_templates', [$this, 'getTaskTemplates'], 10, 3);
20 + add_filter('fluentcrm_ajax_options_board_default_templates', [$this, 'getDefaultBoardTemplates'], 10, 3);
21 + add_filter('fluentcrm_ajax_options_board_user_templates', [$this, 'getUserBoardTemplates'], 10, 3);
22 + add_filter('fluentcrm_ajax_options_board_members', [$this, 'getBoardMembers'], 10, 3);
13 23 }
14 24
15 25 public function getBoards($records, $search, $includeIds)
16 26 {
@@ -35,5 +45,173 @@
35 45 ];
36 46 }
37 47 return $formattedBoards;
38 48 }
39 -}
49 +
50 + public function getTaskTemplates($records, $search, $includeIds)
51 + {
52 + if (!defined('FLUENT_BOARDS_PRO')) {
53 + return [];
54 + }
55 +
56 + $userId = get_current_user_id();
57 + $currentUser = User::find($userId);
58 +
59 + $relatedBoardsQuery = Board::query();
60 +
61 + if (!PermissionManager::isAdmin($userId)) {
62 + $relatedBoardsQuery->whereIn('id', $currentUser->whichBoards->pluck('id'));
63 + }
64 +
65 + $templateTaskIds = TaskMeta::where('key', 'is_template')->where('value', 'yes')->pluck('task_id');
66 + $query = Task::whereIn('id', $templateTaskIds)
67 + ->where('archived_at', null)
68 + ->whereIn('board_id', $relatedBoardsQuery->pluck('id'))
69 + ->with('assignees', 'labels');
70 +
71 +
72 + if (!empty($search)) {
73 + $query->where('title', 'like', "%$search%");
74 + }
75 +
76 + $templateTasks = $query->orderBy('title', 'ASC')->get();
77 +
78 + $formattedTemplateTasks = [];
79 + foreach ($templateTasks as $task) {
80 + $formattedTemplateTasks[] = [
81 + 'id' => strval($task->id),
82 + 'title' => $task->title
83 + ];
84 + }
85 + return $formattedTemplateTasks;
86 + }
87 +
88 + public function getDefaultBoardTemplates($records, $search, $includeIds)
89 + {
90 + // Built-in board templates are coming soon. Keep this selector empty so
91 + // FluentCRM option lookups do not request the external default-template API.
92 + return [];
93 + }
94 +
95 + /**
96 + * Return bounded user-template options for the FluentCRM selector.
97 + *
98 + * @param array $records
99 + * @param string $search
100 + * @param array $includeIds
101 + * @return array
102 + */
103 + public function getUserBoardTemplates($records, $search, $includeIds)
104 + {
105 + if (!defined('FLUENT_BOARDS_PRO')) {
106 + return [];
107 + }
108 +
109 + global $wpdb;
110 +
111 + $search = is_scalar($search) ? sanitize_text_field((string) $search) : '';
112 + $includeIds = array_slice(array_values(array_unique(array_filter(
113 + array_map('absint', (array) $includeIds)
114 + ))), 0, self::USER_TEMPLATE_OPTION_LIMIT);
115 +
116 + $query = $this->newUserTemplateOptionsQuery();
117 +
118 + if ($search !== '') {
119 + $query->where('title', 'like', '%' . $wpdb->esc_like($search) . '%');
120 + }
121 +
122 + $templates = $query->orderBy('title', 'ASC')
123 + ->limit(self::USER_TEMPLATE_OPTION_LIMIT)
124 + ->get();
125 + $options = $this->formatUserTemplateOptions($templates);
126 +
127 + // Preserve saved selections even when they fall outside the current result page.
128 + $missingIds = array_diff($includeIds, array_keys($options));
129 + if ($missingIds) {
130 + $selectedTemplates = $this->newUserTemplateOptionsQuery()
131 + ->whereIn('id', $missingIds)
132 + ->get();
133 + $options += $this->formatUserTemplateOptions($selectedTemplates);
134 + }
135 +
136 + $selectedOptions = array_intersect_key($options, array_flip($includeIds));
137 + $regularOptions = array_diff_key($options, $selectedOptions);
138 + $options = array_merge(
139 + array_values($selectedOptions),
140 + array_slice(
141 + array_values($regularOptions),
142 + 0,
143 + max(0, self::USER_TEMPLATE_OPTION_LIMIT - count($selectedOptions))
144 + )
145 + );
146 +
147 + usort($options, function ($first, $second) {
148 + return strcasecmp($first['title'], $second['title']);
149 + });
150 +
151 + return $options;
152 + }
153 +
154 + /**
155 + * Create a fresh query for lightweight user-template selector options.
156 + *
157 + * @return Builder
158 + */
159 + private function newUserTemplateOptionsQuery()
160 + {
161 + return Board::select(['id', 'title'])
162 + ->whereIn('type', ['to-do', 'roadmap'])
163 + ->onlyTemplates();
164 + }
165 +
166 + /**
167 + * Format template models as selector options keyed by integer ID.
168 + *
169 + * @param iterable $templates
170 + * @return array
171 + */
172 + private function formatUserTemplateOptions($templates)
173 + {
174 + $options = [];
175 +
176 + foreach ($templates as $template) {
177 + $options[(int) $template->id] = [
178 + 'id' => (int) $template->id,
179 + 'title' => $template->title,
180 + ];
181 + }
182 +
183 + return $options;
184 + }
185 +
186 + public function getBoardMembers($records, $search, $includeIds)
187 + {
188 + // Get all WordPress users
189 + $args = [
190 + 'orderby' => 'display_name',
191 + 'order' => 'ASC',
192 + ];
193 +
194 + // Add search filter if provided
195 + if (!empty($search)) {
196 + $args['search'] = '*' . $search . '*';
197 + $args['search_columns'] = ['user_login', 'user_email', 'display_name'];
198 + }
199 +
200 + // Include specific IDs if provided
201 + if (!empty($includeIds)) {
202 + $args['include'] = $includeIds;
203 + }
204 +
205 + $users = get_users($args);
206 +
207 + $formattedMembers = [];
208 + foreach ($users as $user) {
209 + $formattedMembers[] = [
210 + 'id' => strval($user->ID),
211 + 'title' => $user->display_name . ' (' . $user->user_email . ')'
212 + ];
213 + }
214 +
215 + return $formattedMembers;
216 + }
217 +}