PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 2.0.15
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v2.0.15
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 / FluentCRM / Automations / TaskCreateAction.php

TaskCreateAction.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 2.0.15, at app/Services/Intergrations/FluentCRM/Automations/TaskCreateAction.php

318 lines 11.9 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\FluentCRM\Automations;
4
5 use FluentBoards\App\Models\Task;
6 use FluentBoards\App\Services\Constant;
7 use FluentBoards\App\Services\TaskService;
8 use FluentCrm\App\Services\Funnel\BaseAction;
9 use FluentCrm\App\Services\Funnel\FunnelHelper;
10 use FluentCrm\Framework\Support\Arr;
11 use FluentBoards\App\Services\Helper;
12
13 class TaskCreateAction extends BaseAction
14 {
15 public function __construct()
16 {
17 $this->actionName = 'add_task_to_board';
18 $this->priority = 20;
19 parent::__construct();
20 }
21
22 public function getBlock()
23 {
24 return [
25 'category' => __('FluentBoards', 'fluent-boards'),
26 'title' => __('Create Task', 'fluent-boards'),
27 'description' => __('Create Task to the selected Board', 'fluent-boards'),
28 'icon' => 'fc-icon-apply_list',
29 'settings' => [
30 'stage' => [],
31 'create_task_type' => 'new',
32 'title' => 'Task from automation of {{contact.email}}',
33 'created_by' => get_current_user_id(),
34 'assignees' => [],
35 ]
36 ];
37 }
38
39 public function getBlockFields()
40 {
41 return [
42 'title' => __('Create Task', 'fluent-boards'),
43 'sub_title' => __('Select which Board & Stage where task will be created', 'fluent-boards'),
44 'fields' => [
45 'stage' => [
46 'type' => 'grouped-select',
47 'is_multiple' => false,
48 'label' => __('Select Board & It\'s stage', 'fluent-boards'),
49 'placeholder' => __('Select Board & It\'s stage', 'fluent-boards'),
50 'options' => Helper::getStagesByBoardGroup()
51 ],
52
53 'created_by' => [
54 'type' => 'rest_selector',
55 'option_key' => 'board_members',
56 'is_multiple' => false,
57 'label' => __('Created by', 'fluent-boards'),
58 'placeholder' => __('Select a task creator', 'fluent-boards'),
59 ],
60
61 'assignees' => [
62 'type' => 'rest_selector',
63 'option_key' => 'board_members',
64 'is_multiple' => true,
65 'label' => __('Assign to', 'fluent-boards'),
66 'placeholder' => __('Select task assignees', 'fluent-boards'),
67 ],
68
69 'create_task_type' => [
70 'type' => 'radio',
71 'wrapper_class' => 'fc_half_field',
72 'label' => __('Task Create Type', 'fluent-boards'),
73 'options' => [
74 [
75 'id' => 'new',
76 'title' => __('Create from stratch', 'fluent-boards')
77 ],
78 [
79 'id' => 'template',
80 'title' => __('Create from template', 'fluent-boards')
81 ]
82 ]
83 ],
84
85 'task_template' => [
86 'type' => 'rest_selector',
87 'option_key' => 'task_templates',
88 'is_multiple' => false,
89 'label' => __('Select Task Template', 'fluent-boards'),
90 'placeholder' => __('Select Template', 'fluent-boards'),
91 'dependency' => [
92 'depends_on' => 'create_task_type',
93 'operator' => '=',
94 'value' => 'template'
95 ]
96 ],
97
98 'title_template' => [
99 'type' => 'input-text-popper',
100 'field_type' => 'text',
101 'label' => __('Task Title', 'fluent-boards'),
102 'placeholder' => __('Task Title', 'fluent-boards'),
103 'inline_help' => __('Leaving it blank will make the title the same as the template task title.', 'fluent-boards'),
104 'dependency' => [
105 'depends_on' => 'create_task_type',
106 'operator' => '=',
107 'value' => 'template'
108 ]
109 ],
110
111 'title' => [
112 'type' => 'input-text-popper',
113 'field_type' => 'text',
114 'label' => __('Task Title', 'fluent-boards'),
115 'placeholder' => __('Task Title', 'fluent-boards'),
116 'dependency' => [
117 'depends_on' => 'create_task_type',
118 'operator' => '=',
119 'value' => 'new'
120 ]
121 ],
122
123 'due_day' => [
124 'label' => __('Due Date', 'fluent-boards'),
125 'type' => 'input-number',
126 'inline_help' => __('Set to your_input days after task creation, values less than zero will set due date to null', 'fluent-boards'),
127 'dependency' => [
128 'depends_on' => 'create_task_type',
129 'operator' => '=',
130 'value' => 'new'
131 ]
132 ],
133
134 'description' => [
135 'type' => 'html_editor',
136 'smart_codes' => 'yes',
137 'context_codes' => 'yes',
138 'label' => __('Description', 'fluent-boards'),
139 'dependency' => [
140 'depends_on' => 'create_task_type',
141 'operator' => '=',
142 'value' => 'new'
143 ]
144 ],
145
146 'priority' => [
147 'type' => 'select',
148 'label' => __('Select Priority', 'fluent-boards'),
149 'options' => Helper::getPriorityOptions(),
150 'inline_help' => __('Keeping it blank will create the task with no priority', 'fluent-boards'),
151 'dependency' => [
152 'depends_on' => 'create_task_type',
153 'operator' => '=',
154 'value' => 'new'
155 ]
156 ]
157 ]
158 ];
159 }
160
161 public function handle( $subscriber, $sequence, $funnelSubscriberId, $funnelMetric )
162 {
163 $data = $sequence->settings;
164
165 $createType = Arr::get($data, 'create_task_type');
166 $stage = Arr::get($data, 'stage'); // this is a string of the pipeline stage id
167 $creatorId = $this->resolveCreatorId($data, $sequence);
168 $configuredAssignees = Arr::get($data, 'assignees', []);
169 $hasConfiguredAssignees = !empty($configuredAssignees);
170 $assigneeIds = $this->resolveAssigneeIds($configuredAssignees);
171
172 if ( empty($stage) ) {
173 FunnelHelper::changeFunnelSubSequenceStatus( $funnelSubscriberId, $sequence->id, 'skipped' );
174 return;
175 }
176
177 $stageId = (int) $stage;
178 if ($stageId <= 0) {
179 return;
180 }
181
182 $board = Helper::getBoardByStageId( $stageId );
183
184 if ($createType === 'template') {
185 $templateTaskId = Arr::get($data, 'task_template');
186 if (!$templateTaskId) {
187 FunnelHelper::changeFunnelSubSequenceStatus($funnelSubscriberId, $sequence->id, 'skipped');
188 return;
189 }
190
191 $title = Arr::get($data, 'title_template');
192
193 $templateTask = Task::find($templateTaskId);
194
195 $taskData = array();
196 $taskData['board_id'] = $board->id;
197 $taskData['stage_id'] = $stageId;
198 $taskData['assignee'] = true;
199 $taskData['label'] = true;
200
201 $taskService = new TaskService();
202
203 $task = new Task();
204
205 $task->fill($templateTask->toArray());
206
207 if (!empty($title)) {
208 $task['title'] = $title;
209 }
210
211 $task['board_id'] = $taskData['board_id'];
212 $task['stage_id'] = $taskData['stage_id'];
213 $task['created_by'] = $creatorId;
214 $task['comments_count'] = 0;
215 $task->moveToNewPosition(1);
216 $task->save();
217
218 if ($hasConfiguredAssignees) {
219 foreach ($assigneeIds as $assigneeId) {
220 $taskService->updateAssignee($assigneeId, $task);
221 }
222 } else {
223 $templateTask->load('assignees');
224 foreach ($templateTask->assignees as $assignee) {
225 $taskService->updateAssignee($assignee->ID, $task);
226 }
227 }
228 if (isset($taskData['label']) && $taskData['label'] == 'true') {
229 $templateTask->load('labels');
230 foreach ($templateTask->labels as $label) {
231 $task->labels()->syncWithoutDetaching([$label->id => ['object_type' => Constant::OBJECT_TYPE_TASK_LABEL]]);
232 }
233 }
234 } else {
235 $title = Arr::get( $data, 'title');
236 $priority = Arr::get( $data, 'priority');
237 $due_day = Arr::get( $data, 'due_day');
238
239 if(isset($due_day)) {
240 $due_date = Helper::dueDateConversion($due_day, 'day');
241 }
242
243 $description = Arr::get( $data, 'description');
244
245 $description = apply_filters('fluent_crm/parse_campaign_email_text', $description, $subscriber);
246 $title = apply_filters('fluent_crm/parse_campaign_email_text', $title, $subscriber);
247
248 (new Task())->createTask([
249 'title' => $title,
250 'board_id' => $board->id,
251 'crm_contact_id' => $subscriber->id,
252 'type' => 'task',
253 'status' => 'open',
254 'stage_id' => $stageId,
255 'source' => 'funnel',
256 'description' => $description,
257 'priority' => $priority ?? '',
258 'due_at' => $due_date ?? null,
259 'position' => (new TaskService())->getLastPositionOfTasks($stageId),
260 'created_by' => $creatorId,
261 'assignees' => $assigneeIds,
262 ]);
263 }
264
265 FunnelHelper::changeFunnelSubSequenceStatus($funnelSubscriberId, $sequence->id, 'completed');
266
267 }
268
269 /**
270 * Resolve a valid WordPress user to own tasks created by the automation.
271 */
272 private function resolveCreatorId($data, $sequence): int
273 {
274 $candidateIds = [
275 Arr::get($data, 'created_by'),
276 $sequence->created_by ?? 0,
277 get_current_user_id(),
278 ];
279 $existingIds = $this->getExistingUserIds($candidateIds);
280
281 return $existingIds[0] ?? 0;
282 }
283
284 /**
285 * Normalize configured task assignees to existing WordPress user IDs.
286 */
287 private function resolveAssigneeIds($assignees): array
288 {
289 return $this->getExistingUserIds((array) $assignees);
290 }
291
292 /**
293 * Keep positive, unique IDs that still belong to WordPress users.
294 */
295 private function getExistingUserIds($userIds): array
296 {
297 $userIds = array_values(array_unique(array_filter(array_map('absint', (array) $userIds))));
298
299 if (!$userIds) {
300 return [];
301 }
302
303 $users = get_users([
304 'include' => $userIds,
305 'fields' => 'ID',
306 ]);
307 $existingIds = array_map(function ($user) {
308 return absint(is_object($user) ? $user->ID : $user);
309 }, $users);
310 $existingLookup = array_flip($existingIds);
311
312 return array_values(array_filter($userIds, function ($userId) use ($existingLookup) {
313 return isset($existingLookup[$userId]);
314 }));
315 }
316
317 }
318