PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 2.1.0
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v2.1.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 1.41 All 42 releases
← All changes | app/Services/Intergrations/FluentFormIntegration/Bootstrap.php +99 -16 1.222.1.0 View file →
@@ -1,15 +1,19 @@
1 1 <?php
2 2
3 3 namespace FluentBoards\App\Services\Intergrations\FluentFormIntegration;
4 4
5 +use FluentBoards\App\Hooks\Handlers\AdminMenuHandler;
5 6 use FluentBoards\App\Models\Label;
6 7 use FluentBoards\App\Models\Stage;
7 8 use FluentBoards\App\Models\User;
8 9 use FluentBoards\App\Services\Constant;
10 +use FluentBoards\App\Services\DescriptionMarkdownConverter;
9 11 use FluentBoards\App\Services\NotificationService;
10 12 use FluentBoards\App\Services\TaskService;
13 +use FluentBoardsPro\App\Models\TaskAttachment;
11 14 use FluentForm\App\Http\Controllers\IntegrationManagerController;
15 +use FluentForm\App\Modules\Acl\Acl;
12 16 use FluentBoards\Framework\Support\Arr;
13 17 use FluentBoards\App\Models\Board;
14 18 use FluentBoards\App\Models\Task;
15 19 use FluentBoards\App\Services\Helper;
@@ -97,8 +101,11 @@
97 101 'enabled' => true
98 102 ];
99 103 }
100 104
105 + /**
106 + * Build the Fluent Forms feed fields with a form-scoped board options URL.
107 + */
101 108 public function getSettingsFields($settings, $formId)
102 109 {
103 110 $data = [
104 111 'fields' => [
@@ -141,9 +148,12 @@
141 148 'type' => 'select',
142 149 'placeholder' => 'Priority'
143 150 ]
144 151 ],
145 - 'remote_url' => admin_url('admin-ajax.php?action=fluentform_fluent_board_config')
152 + 'remote_url' => add_query_arg([
153 + 'action' => 'fluentform_fluent_board_config',
154 + 'form_id' => absint($formId)
155 + ], admin_url('admin-ajax.php'))
146 156 ],
147 157 [
148 158 'key' => 'task_title',
149 159 'label' => 'Task Title',
@@ -215,29 +225,50 @@
215 225 'checkbox_label' => 'Create FluentCRM Contact',
216 226 ];
217 227 array_splice($data['fields'], 7, 0, [$addToCrmField]);
218 228 }
229 + if (defined('FLUENT_BOARDS_PRO_VERSION')) {
230 + $mapFilesField = [
231 + 'key' => 'map_files',
232 + 'label' => 'Files/Attachments',
233 + 'tips' => "This will map all the Files/Images from the form submission to the task.",
234 + 'component' => 'checkbox-single',
235 + 'checkbox_label' => 'Map Files/Attachments to Task',
236 + ];
237 + array_splice($data['fields'], -2, 0, [$mapFilesField]);
238 + }
219 239 return $data;
220 240 }
221 241
222 242
243 + /**
244 + * Return board configuration options to authorized Fluent Forms managers.
245 + */
223 246 public function getBoardConfigOptions()
224 247 {
225 - $requestInfo = $this->app->request->get('settings');
226 - $boardConfig = Arr::get($requestInfo, 'board_config');
248 + $formId = absint($this->app->request->get('form_id'));
249 + $nonceValid = check_ajax_referer('fluent_forms_admin_nonce', 'fluent_forms_admin_nonce', false);
227 250
228 - $boardId = Arr::get($boardConfig, 'board_id');
251 + if (!$nonceValid || !$formId || !Acl::hasPermission('fluentform_forms_manager', $formId)) {
252 + $this->sendBoardConfigForbidden();
253 + }
229 254
255 + $requestInfo = $this->app->request->get('settings', []);
256 + $boardConfig = Arr::get($requestInfo, 'board_config', []);
257 +
258 + $boardId = absint(Arr::get($boardConfig, 'board_id'));
259 + $boards = $this->getBoards();
260 +
261 + if ($boardId && !array_key_exists($boardId, $boards)) {
262 + $this->sendBoardConfigForbidden();
263 + }
264 +
230 265 $data = [
231 - 'board_id' => $this->getBoards(),
266 + 'board_id' => $boards,
232 267 'stage_id' => [],
233 268 'board_label_id' => [],
234 269 'member_ids' => [],
235 - 'priority' => [
236 - 'low' => 'Low',
237 - 'medium' => 'Medium',
238 - 'high' => 'High'
239 - ]
270 + 'priority' => apply_filters('fluent_boards/task_priorities', (new AdminMenuHandler())->getDefaultPriorities()),
240 271 ];
241 272
242 273 if ($boardId) {
243 274 $data['stage_id'] = $this->getStages($boardId);
@@ -249,11 +280,28 @@
249 280 'fields_options' => $data
250 281 ], 200);
251 282 }
252 283
284 + /**
285 + * Send a consistent forbidden response for invalid board configuration requests.
286 + */
287 + private function sendBoardConfigForbidden()
288 + {
289 + wp_send_json_error([
290 + 'message' => __('You do not have permission to configure Fluent Boards for this form.', 'fluent-boards')
291 + ], 403);
292 + }
293 +
294 + /**
295 + * Get active boards accessible to the current user.
296 + */
253 297 private function getBoards()
254 298 {
255 - $boards = Board::query()->whereNull('archived_at')->get()->toArray();
299 + $boards = Board::query()
300 + ->whereNull('archived_at')
301 + ->byAccessUser(get_current_user_id())
302 + ->get()
303 + ->toArray();
256 304
257 305 $formattedBoards = [];
258 306 foreach ($boards as $board) {
259 307 if (is_array($board)) {
@@ -298,14 +346,15 @@
298 346 $stageId = Arr::get($feedData, 'board_config.stage_id');
299 347 $boardLabels = Arr::get($feedData, 'board_config.board_label_id');
300 348 $assignees = Arr::get($feedData, 'board_config.member_ids');
301 349 $priority = Arr::get($feedData, 'board_config.priority');
302 - $description = Arr::get($feedData, 'description');
350 + $description = DescriptionMarkdownConverter::normalize(Arr::get($feedData, 'description'));
303 351 $position = Arr::get($feedData, 'position');
304 352 $crmContactId = Arr::get($feedData, 'board_config.crm_contact_id');
305 353 $submitterName = trim(Arr::get($feedData, 'submitter_name'));
306 354 $submitterEmail = Arr::get($feedData, 'submitter_email');
307 355 $due_at_days = Arr::get($feedData, 'due_at_days');
356 + $mapFiles = Arr::get($feedData, 'map_files');
308 357 $watcher = Arr::get($feedData, 'watcher_id');
309 358 $crateCRMContact = Arr::get($feedData, 'create_crm_contact');
310 359
311 360 if (!$boardId) {
@@ -311,9 +360,9 @@
311 360 if (!$boardId) {
312 361 do_action('fluentform/integration_action_result', $feed, 'failed', 'Board is required');
313 362 return;
314 363 }
315 - $board = Board::find($boardId)->toArray();
364 + $board = Board::find($boardId);
316 365 if (!$board) {
317 366 do_action('fluentform/integration_action_result', $feed, 'failed', "Board doesn't exist");
318 367 return;
319 368 }
@@ -320,9 +369,9 @@
320 369 if (!$stageId) {
321 370 do_action('fluentform/integration_action_result', $feed, 'failed', "Stage is required");
322 371 return;
323 372 }
324 - $stage = Stage::find($stageId)->toArray();
373 + $stage = Stage::find($stageId);
325 374 if (!$stage) {
326 375 do_action('fluentform/integration_action_result', $feed, 'failed', "Stage doesn't exist");
327 376 return;
328 377 }
@@ -392,9 +441,9 @@
392 441 if ($operation == 'added') {
393 442 if ((new NotificationService())->checkIfEmailEnable($assignee, Constant::BOARD_EMAIL_TASK_ASSIGN, $task->board_id)) {
394 443 (new TaskService())->sendMailAfterTaskModify('add_assignee', $assignee, $task->id);
395 444 }
396 - do_action('fluent_boards/task_assignee_changed', $task, $assignee, $operation);
445 + do_action('fluent_boards/task_assignee_added', $task, $assignee);
397 446 }
398 447 }
399 448 }
400 449
@@ -403,8 +452,41 @@
403 452 $task->labels()->syncWithoutDetaching([$label => ['object_type' => Constant::OBJECT_TYPE_TASK_LABEL]]);
404 453 }
405 454 }
406 455
456 + if ($mapFiles && defined('FLUENT_BOARDS_PRO_VERSION')) {
457 + $results = [];
458 +
459 + // Loop through the array to find keys starting with 'image-upload' or 'file-upload'
460 + foreach ($formData as $key => $value) {
461 + if (preg_match('/^(image-upload|file-upload)/', $key)) {
462 + foreach ($value as $file_url) {
463 + $results[] = $file_url;
464 + }
465 + }
466 + }
467 +
468 +
469 + foreach ($results as $attachment) {
470 + $urlMeta = [
471 + 'title' => 'Uploaded from FluentForm',
472 + 'type' => 'meta_data',
473 + 'url' => esc_url($attachment)
474 + ];
475 + $urlData['settings'] = ['meta' => $urlMeta];
476 + // creating new attachment object
477 + $attachment = new TaskAttachment();
478 + $attachment->object_id = $task->id;
479 + $attachment->object_type = \FluentBoards\App\Services\Constant::TASK_ATTACHMENT;
480 + $attachment->attachment_type = 'url';
481 + $attachment->title = 'Uploaded File from Fluent Form';
482 + $attachment->full_url = $urlMeta['url'];
483 + $attachment->settings = $urlData['settings'] ?? '';
484 + $attachment->driver = 'local';
485 + $attachment->save();
486 + }
487 + }
488 +
407 489 $successMessage = __('Fluent Boards feed has been successfully initialized and data has been pushed.', 'fluent-boards');
408 490 do_action('fluentform/integration_action_result', $feed, 'success', $successMessage);
409 491 } else {
410 492 $error = __('Error when submitting data to Fluent Board server.', 'fluent-boards');
@@ -461,9 +543,10 @@
461 543 {
462 544 if ($due_time > 0) {
463 545 $currentTime = current_time('mysql');
464 546 $readyString = '+' . $due_time . ' ' . $unit;
465 - return date('Y-m-d H:i:s', strtotime($readyString, strtotime($currentTime)));
547 + return gmdate('Y-m-d H:i:s', strtotime($readyString, strtotime($currentTime)));
466 548 }
467 549 return null;
468 550 }
551 +
469 552 }