PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.21
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.21
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
fluent-boards / app / Services / Intergrations / FluentFormIntegration / Bootstrap.php

Bootstrap.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 1.21, at app/Services/Intergrations/FluentFormIntegration/Bootstrap.php

470 lines 17.2 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\Services\Intergrations\FluentFormIntegration;
4
5 use FluentBoards\App\Models\Label;
6 use FluentBoards\App\Models\Stage;
7 use FluentBoards\App\Models\User;
8 use FluentBoards\App\Services\Constant;
9 use FluentBoards\App\Services\NotificationService;
10 use FluentBoards\App\Services\TaskService;
11 use FluentForm\App\Http\Controllers\IntegrationManagerController;
12 use FluentBoards\Framework\Support\Arr;
13 use FluentBoards\App\Models\Board;
14 use FluentBoards\App\Models\Task;
15 use FluentBoards\App\Services\Helper;
16 use FluentCrm\App\Models\Subscriber;
17 use FluentBoards\App\App;
18
19
20 class Bootstrap extends IntegrationManagerController
21 {
22 public $disableGlobalSettings = 'yes';
23
24 public function __construct($app)
25 {
26 parent::__construct(
27 $app,
28 'Fluent Boards',
29 'fluent_boards',
30 '_fluentform_fluent_boards_settings',
31 'fluentform_fluent_boards_feed',
32 30
33 );
34
35 $fluentBoards = App::getInstance();
36 $this->logo = $fluentBoards['url.assets'] . 'images/icon.png';
37
38 $this->description = 'Connect Fluent Boards with WP Fluent Forms and create a task when a form is submitted.';
39
40 $this->registerAdminHooks();
41
42 add_action('wp_ajax_fluentform_fluent_board_config', array($this, 'getBoardConfigOptions'));
43 // add_filter('fluentform/notifying_async_fluent_boards', '__return_false');
44 }
45
46 public function addGlobalMenu($setting)
47 {
48 return $setting;
49 }
50
51 public function pushIntegration($integrations, $formId)
52 {
53 $integrations[$this->integrationKey] = [
54 'title' => $this->title . ' Integration',
55 'logo' => $this->logo,
56 'disable_global_settings' => 'yes',
57 'category' => '',
58 'is_active' => $this->isConfigured()
59 ];
60
61 return $integrations;
62 }
63
64 public function isConfigured()
65 {
66 return true;
67 }
68
69 public function getIntegrationDefaults($settings, $formId)
70 {
71 return [
72 'name' => '',
73 'list_id' => '',
74 'board_config' => [
75 'board_id' => '',
76 'stage_id' => '',
77 'board_label_id' => [],
78 'member_ids' => [],
79 'crm_contact_id' => '',
80 'priority' => ''
81 ],
82 'task_title' => '',
83 'submitter_name' => '',
84 'submitter_email' => '',
85 'priority' => '',
86 'description' => '',
87 'position' => 'bottom',
88 'due_at_days' => '',
89 'create_crm_contact' => false,
90 'conditionals' => [
91 'conditions' => [],
92 'status' => false,
93 'type' => 'all'
94 ],
95
96
97 'enabled' => true
98 ];
99 }
100
101 public function getSettingsFields($settings, $formId)
102 {
103 $data = [
104 'fields' => [
105 [
106 'key' => 'board_config',
107 'label' => 'Fluent Boards Configuration',
108 'required' => true,
109 'component' => 'chained_select',
110 'primary_key' => 'board_id',
111 'fields_options' => [
112 'board_id' => [],
113 'stage_id' => [],
114 'board_label_id' => [],
115 'member_ids' => [],
116 'priority' => []
117 ],
118 'options_labels' => [
119 'board_id' => [
120 'label' => 'Select Board',
121 'type' => 'select',
122 'placeholder' => 'Select Board'
123 ],
124 'stage_id' => [
125 'label' => 'Select Stage',
126 'type' => 'select',
127 'placeholder' => 'Select Stage'
128 ],
129 'board_label_id' => [
130 'label' => 'Select Labels',
131 'type' => 'multi-select',
132 'placeholder' => 'Select Labels'
133 ],
134 'member_ids' => [
135 'label' => 'Select Assignees',
136 'type' => 'multi-select',
137 'placeholder' => 'Select Assignees'
138 ],
139 'priority' => [
140 'label' => 'Select Priority',
141 'type' => 'select',
142 'placeholder' => 'Priority'
143 ]
144 ],
145 'remote_url' => admin_url('admin-ajax.php?action=fluentform_fluent_board_config')
146 ],
147 [
148 'key' => 'task_title',
149 'label' => 'Task Title',
150 'required' => true,
151 'placeholder' => 'Task Title',
152 'component' => 'value_text'
153 ],
154 [
155 'key' => 'description',
156 'label' => 'Description',
157 'required' => false,
158 'placeholder' => 'Describe your task',
159 'component' => 'wp_editor',
160 ],
161
162 [
163 'key' => 'submitter_name',
164 'label' => 'Submitter Name',
165 'required' => true,
166 'placeholder' => 'Submitter Name',
167 'component' => 'value_text'
168 ],
169 [
170 'key' => 'submitter_email',
171 'label' => 'Submitter Email',
172 'required' => true,
173 'placeholder' => 'Submitter Email',
174 'component' => 'value_text'
175 ],
176 [
177 'key' => 'position',
178 'label' => 'Task Position',
179 'required' => true,
180 'placeholder' => 'Position',
181 'component' => 'radio_choice',
182 'options' => [
183 'bottom' => 'Bottom',
184 'top' => 'Top'
185 ]
186 ],
187 [
188 'key' => 'due_at_days',
189 'label' => 'Due Date',
190 'tips' => 'Days after form submission, values less than zero will set due date to null.',
191 'component' => 'number'
192 ],
193 [
194 'key' => 'conditionals',
195 'label' => 'Conditional Logics',
196 'tips' => 'Allow integration conditionally based on your submission values',
197 'component' => 'conditional_block'
198 ],
199 [
200 'key' => 'enabled',
201 'label' => 'Status',
202 'component' => 'checkbox-single',
203 'checkbox_label' => 'Enable This feed'
204 ]
205 ],
206 'button_require_list' => false,
207 'integration_title' => $this->title
208 ];
209 if (function_exists('fluentCrm')) {
210 $addToCrmField = [
211 'key' => 'create_crm_contact',
212 'label' => 'FluentCRM',
213 'tips' => "This will create a FluentCRM Contact, if submitter email doesn't exists",
214 'component' => 'checkbox-single',
215 'checkbox_label' => 'Create FluentCRM Contact',
216 ];
217 array_splice($data['fields'], 7, 0, [$addToCrmField]);
218 }
219 return $data;
220 }
221
222
223 public function getBoardConfigOptions()
224 {
225 $requestInfo = $this->app->request->get('settings');
226 $boardConfig = Arr::get($requestInfo, 'board_config');
227
228 $boardId = Arr::get($boardConfig, 'board_id');
229
230 $data = [
231 'board_id' => $this->getBoards(),
232 'stage_id' => [],
233 'board_label_id' => [],
234 'member_ids' => [],
235 'priority' => [
236 'low' => 'Low',
237 'medium' => 'Medium',
238 'high' => 'High'
239 ]
240 ];
241
242 if ($boardId) {
243 $data['stage_id'] = $this->getStages($boardId);
244 $data['board_label_id'] = $this->getBoardLabels($boardId);
245 $data['member_ids'] = $this->getBoardMembers($boardId);
246 }
247
248 wp_send_json_success([
249 'fields_options' => $data
250 ], 200);
251 }
252
253 private function getBoards()
254 {
255 $boards = Board::query()->whereNull('archived_at')->get()->toArray();
256
257 $formattedBoards = [];
258 foreach ($boards as $board) {
259 if (is_array($board)) {
260 $formattedBoards[$board['id']] = $board['title'];
261 }
262 }
263
264 return $formattedBoards;
265 }
266
267 private function getStages($boardId)
268 {
269 $stages = Stage::where('board_id', $boardId)->whereNull('archived_at')->get()->toArray();
270
271 $formattedStages = [];
272 foreach ($stages as $stage) {
273 if (is_array($stage)) {
274 $formattedStages[$stage['id']] = $stage['title'];
275 }
276 }
277
278 return $formattedStages;
279 }
280
281
282 /**
283 * Prepare Fluent Boards forms for feed field.
284 *
285 * @return array
286 */
287
288 /*
289 * Submission Broadcast Handler
290 */
291
292 public function notify($feed, $formData, $entry, $form)
293 {
294 if (function_exists('fluentBoards')) {
295 $feedData = $feed['processedValues'];
296 $taskName = trim(Arr::get($feedData, 'task_title'));
297 $boardId = Arr::get($feedData, 'board_config.board_id');
298 $stageId = Arr::get($feedData, 'board_config.stage_id');
299 $boardLabels = Arr::get($feedData, 'board_config.board_label_id');
300 $assignees = Arr::get($feedData, 'board_config.member_ids');
301 $priority = Arr::get($feedData, 'board_config.priority');
302 $description = Arr::get($feedData, 'description');
303 $position = Arr::get($feedData, 'position');
304 $crmContactId = Arr::get($feedData, 'board_config.crm_contact_id');
305 $submitterName = trim(Arr::get($feedData, 'submitter_name'));
306 $submitterEmail = Arr::get($feedData, 'submitter_email');
307 $due_at_days = Arr::get($feedData, 'due_at_days');
308 $watcher = Arr::get($feedData, 'watcher_id');
309 $crateCRMContact = Arr::get($feedData, 'create_crm_contact');
310
311 if (!$boardId) {
312 do_action('fluentform/integration_action_result', $feed, 'failed', 'Board is required');
313 return;
314 }
315 $board = Board::find($boardId)->toArray();
316 if (!$board) {
317 do_action('fluentform/integration_action_result', $feed, 'failed', "Board doesn't exist");
318 return;
319 }
320 if (!$stageId) {
321 do_action('fluentform/integration_action_result', $feed, 'failed', "Stage is required");
322 return;
323 }
324 $stage = Stage::find($stageId)->toArray();
325 if (!$stage) {
326 do_action('fluentform/integration_action_result', $feed, 'failed', "Stage doesn't exist");
327 return;
328 }
329 if (!$taskName) {
330 do_action('fluentform/integration_action_result', $feed, 'failed', "Task title is required");
331 return;
332 } else if (!is_string($taskName)) {
333 do_action('fluentform/integration_action_result', $feed, 'failed', "Invalid Task title is required");
334 return;
335 }
336
337 $data = [
338 'title' => $taskName,
339 'board_id' => $boardId,
340 'stage_id' => $stageId,
341 'priority' => $priority,
342 'description' => $description,
343 'crm_contact_id' => $crmContactId,
344 'position' => $this->getLastPositionOfStageTask($boardId, $stageId),
345 'due_at' => $this->dueDateConvertion($due_at_days, 'day'),
346 'source' => 'FluentForm'
347
348 ];
349
350 $formSubmitter = User::where('user_email', $submitterEmail)->first();
351 if (isset($formSubmitter['ID'])) {
352 $data['created_by'] = $formSubmitter->ID;
353 } else {
354 $data['settings']['author'] = [
355 'name' => sanitize_text_field($submitterName),
356 'email' => sanitize_email($submitterEmail),
357 'cover' => [
358 'backgroundColor' => ''
359 ],
360 'subtask_count' => 0
361 ];
362 }
363
364 if (function_exists('fluentCrm')) {
365 $crmConatct = Subscriber::where('email', $submitterEmail)->first();
366 if ($crmConatct) {
367 $data['crm_contact_id'] = $crmConatct->id;
368 } else {
369 if ($crateCRMContact) {
370 // create crm contact
371 }
372 }
373 }
374
375 $data = Helper::sanitizeTask($data);
376 $task = (new Task())->createTask($data);
377
378 if ($task->id) {
379 do_action('fluent_boards/task_added_from_fluent_form', $task);
380 if ($position == 'top') {
381 $task->moveToNewPosition(1);
382 }
383
384 if ($assignees) {
385 foreach ($assignees as $assignee) {
386 $operation = $task->addOrRemoveAssignee($assignee);
387 $task->load('assignees');
388 $task->updated_at = current_time('mysql');
389
390 $task->save();
391
392 if ($operation == 'added') {
393 if ((new NotificationService())->checkIfEmailEnable($assignee, Constant::BOARD_EMAIL_TASK_ASSIGN, $task->board_id)) {
394 (new TaskService())->sendMailAfterTaskModify('add_assignee', $assignee, $task->id);
395 }
396 do_action('fluent_boards/task_assignee_changed', $task, $assignee, $operation);
397 }
398 }
399 }
400
401 if ($boardLabels) {
402 foreach ($boardLabels as $label) {
403 $task->labels()->syncWithoutDetaching([$label => ['object_type' => Constant::OBJECT_TYPE_TASK_LABEL]]);
404 }
405 }
406
407 $successMessage = __('Fluent Boards feed has been successfully initialized and data has been pushed.', 'fluent-boards');
408 do_action('fluentform/integration_action_result', $feed, 'success', $successMessage);
409 } else {
410 $error = __('Error when submitting data to Fluent Board server.', 'fluent-boards');
411 do_action('fluentform/integration_action_result', $feed, 'failed', $error);
412 }
413 } else {
414 do_action('fluentform/integration_action_result', $feed, 'failed', "Fluent Board doesn't exists.");
415 }
416 }
417
418 public function getMergeFields($list, $listId, $formId)
419 {
420 return false;
421 }
422
423 private function getLastPositionOfStageTask($board_id, $stage_id)
424 {
425 $lastPosition = Task::query()
426 ->where('board_id', $board_id)
427 ->where('parent_id', null)
428 ->where('stage_id', $stage_id)
429 ->whereNull('archived_at')
430 ->orderBy('position', 'desc')
431 ->pluck('position')
432 ->first();
433
434 return $lastPosition + 1;
435 }
436
437 private function getBoardLabels($boardId)
438 {
439 $labels = Label::where('board_id', $boardId)->whereNull('archived_at')->orderBy('position', 'asc')->get();
440
441 $formattedLabels = [];
442 foreach ($labels as $label) {
443 $formattedLabels[$label['id']] = $label['title'] ?? $label['slug'];
444 }
445
446 return $formattedLabels;
447 }
448
449 private function getBoardMembers($boardId)
450 {
451 $board = Board::findOrFail($boardId);
452 $boardUsers = $board->users;
453 $formattedBoardUsers = [];
454 foreach ($boardUsers as $boardUser) {
455 $formattedBoardUsers[$boardUser['ID']] = $boardUser['user_login'] . " (" . $boardUser['user_email'] . ")";
456 }
457 return $formattedBoardUsers;
458 }
459
460 private function dueDateConvertion($due_time, $unit)
461 {
462 if ($due_time > 0) {
463 $currentTime = current_time('mysql');
464 $readyString = '+' . $due_time . ' ' . $unit;
465 return date('Y-m-d H:i:s', strtotime($readyString, strtotime($currentTime)));
466 }
467 return null;
468 }
469 }
470