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
fluent-boards / app / Hooks / actions.php

actions.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 2.1.0, at app/Hooks/actions.php

244 lines 14.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 //if accessed directly exit
3 if (!defined('ABSPATH')) exit;
4
5 use FluentBoards\App\Services\Helper;
6
7 /**
8 * All registered action's handlers should be in app\Hooks\Handlers,
9 * addAction is similar to add_action and addCustomAction is just a
10 * wrapper over add_action which will add a prefix to the hook name
11 * using the plugin slug to make it unique in all WordPress plugins,
12 * ex: $app->addCustomAction('foo', ['FooHandler', 'handleFoo']) is
13 * equivalent to add_action('slug-foo', ['FooHandler', 'handleFoo']).
14 */
15
16 /**
17 * @var $app FluentBoards\Framework\Foundation\Application
18 */
19
20 (new \FluentBoards\App\Hooks\Handlers\AdminMenuHandler())->register();
21
22 /*
23 * Add custom CSS for fbs_notice.
24 */
25 add_action('admin_head', function () {
26 echo '<style>
27 .fbs_notice {
28 background: var(--fbs-primary-bg, #ffffff);
29 border: 1px solid var(--fbs-primary-border, #E1E4EA);
30 border-left: 3px solid #FB3748;
31 padding: 10px 12px !important;
32 border-radius: 8px;
33 margin-bottom: 5px;
34 }
35 </style>';
36 });
37
38 //$app->addCustomAction('task_prop_changed', 'ActivityHandler@logActivity', 10, 3);
39 $app->addCustomAction('task_board_changed', 'ActivityHandler@logMoveTaskToAnotherBoardActivity', 10, 2); //will call from service after board change code merged
40 $app->addCustomAction('task_due_date_changed', 'ActivityHandler@logDueDateActivity', 10, 2);
41 $app->addCustomAction('task_due_date_removed', 'ActivityHandler@logDueDateRemoveActivity', 10, 1);
42 $app->addCustomAction('task_start_date_changed', 'ActivityHandler@logStartDateActivity', 10, 2);
43
44 $app->addCustomAction('task_priority_changed', 'ActivityHandler@logPriorityChangeActivity', 10, 2);
45 $app->addCustomAction('comment_created', 'ActivityHandler@logCommentCreateActivity', 10, 1);
46 $app->addCustomAction('comment_updated', 'ActivityHandler@logCommentUpdateActivity', 10, 2);
47 $app->addCustomAction('comment_deleted', 'ActivityHandler@logCommentDeleteActivity', 10, 1);
48 $app->addCustomAction('subtask_added', 'ActivityHandler@logSubtaskAddedActivity', 10, 2);
49 $app->addCustomAction('subtask_cloned', 'ActivityHandler@logSubtaskCloneActivity', 10, 2);
50 $app->addCustomAction('subtask_group_created', 'ActivityHandler@logSubtaskGroupAddedActivity', 10, 2);
51 $app->addCustomAction('subtask_deleted_activity', 'ActivityHandler@logSubtaskDeletedActivity', 10, 2);
52 $app->addCustomAction('subtask_group_deleted_activity', 'ActivityHandler@logSubtaskGroupDeletedActivity', 10, 2);
53 $app->addCustomAction('subtask_group_title_updated', 'ActivityHandler@logSubtaskGroupTitleUpdatedActivity', 10, 2);
54 $app->addCustomAction('task_completed_activity', 'ActivityHandler@logTaskCompletedOrReopenActivity', 10, 2);
55 $app->addCustomAction('task_stage_updated', 'ActivityHandler@logTaskStageUpdatedActivity', 10, 3);
56 $app->addCustomAction('task_assignee_added', 'ActivityHandler@logAssigneeAddedActivity', 10, 2);
57 $app->addCustomAction('task_assignee_removed', 'ActivityHandler@logAssigneeRemovedActivity', 10, 2);
58 $app->addCustomAction('task_added_from_fluent_form', 'ActivityHandler@taskAddedFromFluentForms', 10, 1);
59 $app->addCustomAction('repeat_task_created', 'ActivityHandler@logRepeatTaskCreatedActivity', 10, 2);
60 $app->addCustomAction('repeat_task_set', 'ActivityHandler@logRepeatTaskSet', 10, 1);
61 $app->addCustomAction('repeat_task_updated', 'ActivityHandler@logRepeatTaskUpdated', 10, 1);
62 $app->addCustomAction('task_created', 'ActivityHandler@logTaskCreationActivity', 10, 1);
63 $app->addCustomAction('task_content_updated', 'ActivityHandler@logTaskContentUpdatedActivity', 10, 3);
64 $app->addCustomAction('task_deleted', 'TaskHandler@taskDeleted', 10, 1);
65 $app->addCustomAction('task_archived', 'ActivityHandler@taskArchived', 10, 1);
66 //$app->addCustomAction('task_custom_field_changed', 'ActivityHandler@logCustomFieldActivity', 10, 5); // commented for now, will implement later
67
68 $app->addCustomAction('board_created', 'BoardHandler@boardCreated', 10, 1);
69 $app->addCustomAction('board_created_from_automation', 'BoardHandler@boardCreatedFromAutomation', 10, 1);
70 $app->addCustomAction('before_board_deleted', 'BoardHandler@beforeBoardDeleted', 10, 2);
71 $app->addCustomAction('board_updated', 'BoardHandler@boardUpdated', 10, 2);
72 $app->addCustomAction('stage_updated', 'BoardHandler@boardStageUpdated', 10, 3);
73 $app->addCustomAction('board_stage_moved', 'BoardHandler@boardStageMoved', 10, 2);
74 $app->addCustomAction('board_stage_added', 'BoardHandler@boardStageAdded', 10, 2);
75 $app->addCustomAction('stage_deleted', 'BoardHandler@boardStageDeleted', 10, 2);
76 $app->addCustomAction('stage_archived', 'BoardHandler@boardStageArchived', 10, 2);
77 $app->addCustomAction('board_stage_restored', 'BoardHandler@boardArchivedStageRestore', 10, 2);
78 $app->addCustomAction('task_created', 'BoardHandler@taskCreatedOnBoard', 10, 1);
79 $app->addCustomAction('before_task_deleted', 'BoardHandler@beforeTaskDeleted', 10, 2);
80 $app->addCustomAction('task_deleted', 'BoardHandler@taskdeleted', 10, 1);
81 $app->addCustomAction('task_moved_from_board', 'BoardHandler@taskMovedFromBoard', 10, 3);
82 $app->addCustomAction('task_moved_from_board', 'ActivityHandler@taskMovedFromBoard', 10, 3);
83 $app->addCustomAction('task_archived', 'BoardHandler@taskArchivedOnBoard', 10, 1);
84 $app->addCustomAction('tasks_moved_between_stages', 'BoardHandler@tasksMovedBetweenStages', 10, 4);
85 $app->addCustomAction('board_member_added', 'BoardHandler@boardMemberAdded', 10, 2);
86 $app->addCustomAction('board_viewer_added', 'BoardHandler@boardViewerAdded', 10, 2);
87 $app->addCustomAction('board_member_removed', 'BoardHandler@boardMemberRemoved', 10, 2);
88 $app->addCustomAction('board_admin_added', 'BoardHandler@boardAdminAdded', 10, 2);
89 $app->addCustomAction('board_admin_removed', 'BoardHandler@boardAdminRemoved', 10, 2);
90 $app->addCustomAction('associate_user_add_change_remove_activity', 'ActivityHandler@associateUserAddChangeRemoveActivity', 10, 3);
91 $app->addCustomAction('task_assignee_leave', 'ActivityHandler@taskAssigneeLeave', 10, 1);
92 $app->addCustomAction('task_assignee_join', 'ActivityHandler@taskAssigneeJoin', 10, 1);
93 $app->addCustomAction('task_label', 'ActivityHandler@taskLabelActivity', 10, 3);
94 $app->addCustomAction('label_manage_for_task_activity', 'ActivityHandler@labelManageForTaskActivity', 10, 2);
95 $app->addCustomAction('board_label_created', 'BoardHandler@boardLabelCreatedActivity', 10, 1);
96 $app->addCustomAction('board_label_updated', 'BoardHandler@boardLabelUpdatedActivity', 10, 1);
97 $app->addCustomAction('board_label_deleted', 'BoardHandler@boardLabelDeletedActivity', 10, 1);
98 $app->addCustomAction('board_stages_reordered', 'BoardHandler@boardStagesReOrdered', 10, 2);
99 $app->addCustomAction('default_assignees_updated', 'BoardHandler@defaultAssigneesUpdated', 10, 2);
100
101 $app->addCustomAction('comment_created', 'NotificationHandler@addCommentNotification', 10, 1);
102 $app->addCustomAction('mention_comment_notification', 'NotificationHandler@mentionInCommentNotification', 10, 2);
103 $app->addCustomAction('subtask_added', 'NotificationHandler@addSubtaskNotification', 10, 2);
104 $app->addCustomAction('task_due_date_changed', 'NotificationHandler@changeDueDateNotification', 10, 2);
105 $app->addCustomAction('task_start_date_changed', 'NotificationHandler@changeStartDateNotification', 10, 2);
106 $app->addCustomAction('task_stage_updated', 'NotificationHandler@changeStageNotification', 10, 2);
107 $app->addCustomAction('task_priority_changed', 'NotificationHandler@changePriorityNotification', 10, 2);
108 $app->addCustomAction('task_archived', 'NotificationHandler@taskArchiveNotification', 10, 1);
109 $app->addCustomAction('task_content_updated', 'NotificationHandler@changeTitleNotification', 10, 3);
110 //$app->addCustomAction('description_changed_notification', 'NotificationHandler@changeDescriptionNotification', 10, 1);
111 $app->addCustomAction('board_changed_notification', 'NotificationHandler@changeBoardNotification', 10, 2);
112 $app->addCustomAction('task_assignee_added', 'NotificationHandler@assigneeAddedNotification', 10, 2);
113 $app->addCustomAction('task_assignee_removed', 'NotificationHandler@assigneeRemovedNotification', 10, 2);
114
115 $app->addCustomAction('one_time_schedule_send_email_for_comment', 'ScheduleHandler@sendEmailForComment', 10, 3);
116 $app->addCustomAction('one_time_schedule_send_email_for_mention', 'ScheduleHandler@sendEmailForMention', 10, 3);
117 $app->addCustomAction('one_time_schedule_send_email_for_add_assignee', 'ScheduleHandler@sendEmailForAddAssignee', 10, 3);
118 $app->addCustomAction('one_time_schedule_send_email_for_remove_assignee', 'ScheduleHandler@sendEmailForRemoveAssignee', 10, 3);
119 $app->addCustomAction('one_time_schedule_send_email_for_stage_change', 'ScheduleHandler@sendEmailForChangeStage', 10, 3);
120
121 //Todo:: update handler
122 $app->addCustomAction('one_time_schedule_send_email_for_due_date_update', 'ScheduleHandler@sendEmailForDueDateUpdate', 10, 3);
123 $app->addCustomAction('one_time_schedule_send_email_for_task_archived', 'ScheduleHandler@sendEmailForArchivedTask', 10, 3);
124 $app->addCustomAction('one_time_schedule_send_email_for_removed_from_task', 'ScheduleHandler@sendEmailForChangeStage', 10, 3);
125
126 $app->addCustomAction('task_attachment_added', 'ActivityHandler@taskAttachmentAdded', 10, 1);
127 $app->addCustomAction('task_attachment_deleted', 'ActivityHandler@taskAttachmentDeleted', 10, 1);
128 $app->addCustomAction('task_attachment_deleted', 'TaskHandler@taskAttachmentDeleted', 10, 2);
129 // Removed: direct call is made from Comment::deleting to TaskHandler@commentImageDeleted
130 $app->addAction('deleted_user', 'BoardHandler@deleteUserRelatedData', 10, 3);
131
132 $app->addCustomAction('task_created', 'TaskHandler@onTaskCreated', 10, 1);
133 $app->addCustomAction('comment_created', 'TaskHandler@onCommentCreated', 10, 1);
134 $app->addCustomAction('assign_another_user', 'TaskHandler@onAssignAnotherUser', 10, 2);
135 $app->addCustomAction('board_background_updated', 'BoardHandler@backgroundUpdated', 10, 2);
136 $app->addCustomAction('task_cloned', 'TaskHandler@taskCloned', 10, 2);
137 $app->addCustomAction('task_cloned_activity', 'ActivityHandler@taskCloned', 10, 2);
138
139 if (defined('WP_CLI') && WP_CLI) {
140 \WP_CLI::add_command('fluent_boards', '\FluentBoards\App\Hooks\Cli\Commands');
141 }
142
143
144 add_action('init', function () {
145 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public routing parameter check, no data modification
146 if (!isset($_REQUEST['fbs'])) {
147 return;
148 }
149 });
150
151 /*
152 * IMPORTANT
153 * External Pages Handler
154 * Each Request must have fbs=1 as a query parameter, then the plugin will handle the request.
155 */
156 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public routing logic, security validated in individual handlers
157 if(isset($_GET['fbs']) && $_GET['fbs'] == 1) {
158
159 // For viewing attachment
160 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public routing logic, security validated in handler
161 if(isset($_GET['route']) && ($_GET['route'] == 'task')) {
162 add_action('init', function() {
163 (new \FluentBoardsPro\App\Hooks\Handlers\ExternalPages())->handleTaskWebhook();
164 });
165 }
166
167 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public file serving endpoint, security validated by hash in handler
168 if(isset($_GET['fbs_comment_image'])) {
169 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public routing check, security validated in handler
170 if(isset($_GET['fbs_type']) && $_GET['fbs_type'] == 'public_url') {
171 add_action('init', function() {
172 (new \FluentBoards\App\Hooks\Handlers\ExternalPages())->view_uploaded_comment_image();
173 });
174 } else {
175 add_action('init', function() {
176 (new \FluentBoards\App\Hooks\Handlers\ExternalPages())->view_comment_image();
177 });
178 }
179
180 }
181
182 }
183
184 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public redirect endpoint, no sensitive operations
185 if(isset($_GET['redirect']) && $_GET['redirect'] == 'to_task') {
186 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public redirect endpoint, validation performed in handler
187 if (isset($_GET['taskId'])) {
188 add_action('init', function() {
189 (new \FluentBoards\App\Hooks\Handlers\ExternalPages())->redirectToPage();
190 });
191 }
192 }
193 // Stage Archive Handler - Archive tasks when stage is archived, restore when stage is restored
194 $app->addAction('fluent_boards/stage_archived_with_tasks', 'StageArchiveHandler@onStageArchived', 10, 2);
195 $app->addAction('fluent_boards/stage_restored_with_tasks', 'StageArchiveHandler@onStageRestored', 10, 2);
196
197 /*
198 * MCP - Register Fluent Boards abilities for the WordPress Abilities API.
199 *
200 * This mirrors FluentCRM's MCP architecture: on WordPress installs without the
201 * Abilities API / WP MCP Adapter, `wp_register_ability` is undefined and the
202 * integration skips silently. Admins can opt out with the `mcp_enabled` option.
203 */
204 add_filter('fluent_kit/mcp_products', [\FluentBoards\App\Modules\MCP\MCPInit::class, 'registerToolkitProduct'], 10, 2);
205 add_filter('fluent_kit/mcp_toggle_handlers', function ($handlers) {
206 $handlers['fluent-boards'] = [
207 'get_enabled' => function () {
208 return fluent_boards_get_option('mcp_enabled', 'yes') === 'yes';
209 },
210 'set_enabled' => function ($enabled) {
211 fluent_boards_update_option('mcp_enabled', $enabled ? 'yes' : 'no');
212 },
213 ];
214
215 return $handlers;
216 });
217
218 add_action('init', function () {
219 if (!function_exists('wp_register_ability')) {
220 return;
221 }
222
223 if (fluent_boards_get_option('mcp_enabled', 'yes') !== 'yes') {
224 return;
225 }
226
227 (new \FluentBoards\App\Modules\MCP\MCPInit())->init();
228 }, 5);
229
230 $invalidateMcpContext = [\FluentBoards\App\Modules\MCP\Tools\ContextTools::class, 'invalidateCache'];
231 foreach ([
232 'fluent_boards/board_created',
233 'fluent_boards/board_updated',
234 'fluent_boards/before_board_deleted',
235 'fluent_boards/board_stage_added',
236 'fluent_boards/stage_updated',
237 'fluent_boards/stage_deleted',
238 'fluent_boards/board_label_created',
239 'fluent_boards/board_label_updated',
240 'fluent_boards/board_label_deleted',
241 ] as $mcpContextHook) {
242 add_action($mcpContextHook, $invalidateMcpContext);
243 }
244