PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.40
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.40
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 1.45 All 41 releases
fluent-boards / app / Services / CommentService.php

CommentService.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 1.40, at app/Services/CommentService.php

324 lines 10.6 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;
4
5 use FluentBoards\App\Models\Comment;
6 use FluentBoards\App\Models\CommentImage;
7 use FluentBoards\App\Models\Task;
8 use FluentBoards\App\Models\TaskActivity;
9 use FluentBoardsPro\App\Services\AttachmentService;
10 use FluentBoardsPro\App\Services\RemoteUrlParser;
11
12 class CommentService
13 {
14 public function getComments($id, $per_page, $filter)
15 {
16 $task = Task::findOrFail($id);
17
18 $commentsQuery = $task->comments()->whereNull('parent_id')
19 ->with(['user']);
20
21 if ($filter == 'oldest') {
22 $commentsQuery = $commentsQuery->oldest();
23 } else { // latest or newest
24 $commentsQuery = $commentsQuery->latest();
25 }
26 $comments = $commentsQuery->paginate($per_page);
27
28 foreach ($comments as $comment) {
29 $comment->replies = $this->getReplies($comment);
30 $comment->replies_count = count($comment->replies);
31 $comment->load('images');
32 }
33
34 return $comments;
35 }
36
37 public function getTotal($id)
38 {
39 $task = Task::findOrFail($id);
40 $totalComment = Comment::where('task_id', $task->id)
41 ->type('comment')
42 ->count();
43 $totalReply = Comment::where('task_id', $task->id)
44 ->type('reply')
45 ->count();
46
47 return $totalComment + $totalReply;
48 }
49
50 public function getReplies($comment)
51 {
52 $replies = Comment::where('parent_id', $comment->id)->with(['user'])->get();
53 return $replies;
54 }
55
56 public function create($commentData, $id)
57 {
58 $comment = Comment::create($commentData);
59 do_action('fluent_boards/comment_created', $comment);
60 return $comment;
61 }
62
63 private function startsWithAt($word) {
64 return strpos($word, '@') === 0;
65 }
66
67 public function processMentionAndLink($commentDescription, $mentionData)
68 {
69 // Splitting a string by either a space (" ") or a new line ("\n")
70 $lines = preg_split('/\R/', $commentDescription); // \R matches any kind of line break
71
72 $mentionedUsernames = [];
73 foreach ($mentionData as $mentionedId) {
74 $user = get_userdata($mentionedId);
75 $mentionedUsernames[$user->user_login] = ['user_id' => $user->ID, 'display_name' => $user->display_name];
76 }
77
78 foreach ($lines as &$line) {
79 $words = preg_split('/[ ]+/', $line);
80 foreach ($words as $index => $word) {
81 if ($this->startsWithAt($word)) {
82 $username = substr($word, 1);
83 if (array_key_exists($username, $mentionedUsernames)) {
84 $words[$index] = '<a class="fbs_mention" href="' . fluent_boards_page_url() . 'member/' . $mentionedUsernames[$username]['user_id'] . '/tasks">' . $mentionedUsernames[$username]['display_name'] . '</a>';
85 }
86 } elseif ($this->isValidUrl(wp_kses_post($word))) {
87 $words[$index] = '<a class="fbs_link" target="_blank" href="'. esc_url($word). '">'. esc_url($word). '</a>';
88 }
89 }
90 // Rejoin the words in this line
91 $line = implode(' ', $words);
92 }
93
94 // Rejoin the lines, adding back the new line character
95 return implode("\n", $lines);
96
97 }
98
99 private function isValidUrl($url) {
100 if (filter_var($url, FILTER_VALIDATE_URL) === false) {
101 return false;
102 }
103
104 // Additional validation with a regular expression
105 $regex = "/\b(?:https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]/i";
106
107 return preg_match($regex, $url);
108 }
109
110 public function checkIfCommentHaveLinks($comment)
111 {
112 $lines = preg_split('/\R/', $comment); // Split by any kind of line break
113 $commentHasLinks = false;
114
115 foreach ($lines as &$line) {
116 $words = preg_split('/[ ]+/', $line); // Split by spaces within each line
117 foreach ($words as $index => $word) {
118 $cleanWord = wp_kses_post($word);
119 if ($this->isValidUrl($cleanWord)) {
120 $commentHasLinks = true;
121 $words[$index] = '<a class="fbs_link" target="_blank" href="' . esc_url($cleanWord) . '">' . esc_url($cleanWord) . '</a>';
122 }
123 }
124 // Rejoin words in this line
125 $line = implode(' ', $words);
126 }
127
128 if ($commentHasLinks) {
129 return implode("\n", $lines); // Rejoin lines with new lines preserved
130 } else {
131 return $comment; // Return original comment if no links were found
132 }
133 }
134
135 public function attachCommentImages($comment, $imageIds)
136 {
137
138 foreach ($imageIds as $imageId)
139 {
140 $attachmentObject = CommentImage::findOrFail($imageId);
141 if($attachmentObject) {
142 if ($attachmentObject->object_id == $comment->id && $attachmentObject->object_type == Constant::COMMENT_IMAGE) {
143 continue;
144 }
145 $attachmentObject->object_id = $comment->id;
146 $attachmentObject->object_type = Constant::COMMENT_IMAGE;
147 $attachmentObject->save();
148 }
149 }
150 //if(in_array("banana", $imageIds))
151 $commentImages = CommentImage::where('object_id', $comment->id)->where('object_type', Constant::COMMENT_IMAGE)->get();
152
153 foreach ($commentImages as $commentImage) {
154 if(!in_array($commentImage->id, $imageIds)) {
155 $commentImage->delete();
156 }
157 }
158 }
159
160 public function update($commentData, $comment_id, $mentionData)
161 {
162 $comment = Comment::findOrFail($comment_id);
163
164 if ($comment->created_by != get_current_user_id()) {
165 return false;
166 }
167
168 $allMentionedIds = array_merge($comment->settings['mentioned_id'] ?? [], $mentionData ?? []);
169
170 if ($allMentionedIds) {
171 $processedDescription = $this->processMentionAndLink($commentData['description'], $allMentionedIds);
172 } else {
173 $processedDescription = $this->checkIfCommentHaveLinks($commentData['description']);
174 }
175
176 $oldComment = $comment->settings['raw_description'] ?? $comment->description;
177 $comment->description = $processedDescription;
178
179 if($comment->settings != null)
180 {
181 $tempSettings = $comment->settings;
182 $tempSettings['raw_description'] = $commentData['description'];
183 $tempSettings['mentioned_id'] = $allMentionedIds;
184 $comment->settings = $tempSettings;
185 } else {
186 $comment->settings = [
187 'raw_description' => $commentData['raw_description'],
188 'mentioned_id' => $allMentionedIds
189 ];
190 }
191 $comment->save();
192
193 if(!$comment->parent_id) {
194 do_action('fluent_boards/comment_updated', $comment, $oldComment);
195 }
196
197 return $comment;
198 }
199
200 public function delete($comment_id)
201 {
202 $comment = Comment::findOrFail($comment_id);
203 $taskId = $comment->task_id;
204
205 if ($comment->created_by != get_current_user_id()) {
206 return false;
207 }
208
209 $deleted = $comment->delete();
210
211 if ($deleted) {
212 $this->relatedReplyDelete($comment_id);
213 $comment->images()->delete();
214 $task = Task::findOrFail($taskId);
215 $task->comments_count = $task->comments_count - 1;
216 $task->save();
217 }
218
219 do_action('fluent_boards/comment_deleted', $comment);
220 }
221
222 public function relatedReplyDelete($comment_id)
223 {
224 $replies = Comment::where('parent_id', $comment_id)
225 ->type('reply')
226 ->get();
227 foreach ($replies as $reply) {
228 $reply->delete();
229 }
230 }
231
232 public function updateReply($replyData, $id)
233 {
234 $reply = Comment::findOrFail($id);
235
236 if ($reply->created_by != get_current_user_id()) {
237 return false;
238 }
239
240 $oldReply = $reply->description;
241 $reply->description = $replyData['description'];
242 $reply->save();
243 // do_action('fluent_boards/task_comment_updated', $comment->task_id, $oldComment, $comment->description);
244
245 return $reply;
246 }
247
248 public function deleteReply($id)
249 {
250 $reply = Comment::findOrFail($id);
251 // $taskId = $reply->task_id;
252
253 if ($reply->created_by != get_current_user_id()) {
254 return false;
255 }
256
257 $reply->delete();
258
259 // do_action('fluent_boards/comment_deleted', $taskId);
260 }
261
262 /**
263 * Adds a task attachment to the specified task.
264 *
265 * @param int $taskId The ID of the task to which the attachment is added.
266 * @param string $title The title of the attachment.
267 * @param string $url The URL of the attachment.
268 *
269 * @return Attachment The updated list of task attachments.
270 * @throws \Exception
271 */
272 public function createCommentImage($data, $boardId)
273 {
274 /*
275 * I will refactor this function later- within March 2024 Last Week
276 */
277 $initialDataData = [
278 'type' => 'url',
279 'url' => '',
280 'name' => '',
281 'size' => 0,
282 ];
283
284 $attachData = array_merge($initialDataData, $data);
285 $UrlMeta = [];
286 if($attachData['type'] == 'url') {
287 $UrlMeta = RemoteUrlParser::parse($attachData['url']);
288 }
289 $attachment = new CommentImage();
290 $attachment->object_id = 0;
291 $attachment->object_type = Constant::COMMENT_IMAGE;
292 $attachment->attachment_type = $attachData['type'];
293 $attachment->title = $this->setTitle($attachData['type'], $attachData['name'], $UrlMeta);
294 $attachment->file_path = $attachData['type'] != 'url' ? $attachData['file'] : null;
295 $attachment->full_url = esc_url($attachData['url']);
296 $attachment->file_size = $attachData['size'];
297 $attachment->settings = $attachData['type'] == 'url' ? [
298 'meta' => $UrlMeta
299 ] : '';
300 $attachment->driver = 'local';
301 $attachment->save();
302
303 return $attachment;
304 }
305
306 public function createPublicUrl($attachment, $boardId)
307 {
308 return add_query_arg([
309 'fbs' => 1,
310 'fbs_type' => 'public_url',
311 'fbs_bid' => $boardId,
312 'fbs_comment_image' => $attachment->file_hash
313 ], site_url('/index.php'));
314 }
315
316 private function setTitle($type, $title, $UrlMeta)
317 {
318 if($type != 'url') {
319 return sanitize_file_name($title);
320 }
321 return $title ?? $UrlMeta['title'] ?? '';
322 }
323 }
324