← All changes
|
app/Services/Intergrations/FluentFormIntegration/Bootstrap.php
+98
-15
1.32
→
2.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 | } |
| @@ -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 | } |