PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.6.01
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.6.01
2.11.0 2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 All 78 releases
fluent-community / Modules / Migrations / Helpers / BPMigratorHelper.php

BPMigratorHelper.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 2.6.01, at Modules/Migrations/Helpers/BPMigratorHelper.php

808 lines 27.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCommunity\Modules\Migrations\Helpers;
4
5 use FluentCommunity\App\Functions\Utility;
6 use FluentCommunity\App\Models\BaseSpace;
7 use FluentCommunity\App\Models\Comment;
8 use FluentCommunity\App\Models\Feed;
9 use FluentCommunity\App\Models\Media;
10 use FluentCommunity\App\Models\Reaction;
11 use FluentCommunity\App\Models\Space;
12 use FluentCommunity\App\Models\SpaceGroup;
13 use FluentCommunity\App\Models\User;
14 use FluentCommunity\App\Services\Helper;
15 use FluentCommunity\Framework\Support\Arr;
16
17 class BPMigratorHelper
18 {
19 public static function getBbDataStats()
20 {
21 return [
22 'groups' => fluentCommunityApp('db')->table('bp_groups')->count(),
23 'total_posts' => fluentCommunityApp('db')->table('bp_activity')->where('type', 'activity_update')->count(),
24 'total_comments' => fluentCommunityApp('db')->table('bp_activity')->where('type', 'activity_comment')->count(),
25 'total_reactions' => class_exists('\BB_Reaction') ? fluentCommunityApp('db')->table('bb_user_reactions')->whereIn('item_type', ['activity_comment', 'activity'])->count() : 0,
26 'total_community_users' => User::count(),
27 ];
28 }
29
30 public static function migratePost($post, $spaceId = null)
31 {
32 return (new PostMigrator($post))->migrate();
33 }
34
35 public static function syncComments($activityId, Feed $feed)
36 {
37 // Let's manage the comments
38 $comments = fluentCommunityApp('db')->table('bp_activity')
39 ->where('type', 'activity_comment')
40 ->where('item_id', $activityId)
41 ->orderBy('id', 'ASC')
42 ->get();
43
44 $comments = self::buildCommentsTree($comments);
45 $commentMaps = [];
46
47 foreach ($comments as $comment) {
48 $newComment = self::insertBBComment($comment, $feed);
49 $commentMaps[$comment['id']] = $newComment->id;
50 if ($comment['children']) {
51 foreach ($comment['children'] as $child) {
52 $childComment = self::insertBBComment($child, $feed, $newComment->id);
53 $commentMaps[$child['id']] = $childComment->id;
54 }
55 }
56 }
57
58 return $commentMaps;
59 }
60
61 public static function insertBBComment($comment, $feed, $parentId = null)
62 {
63 $comemntData = [
64 'user_id' => $comment['user_id'],
65 'post_id' => $feed->id,
66 'message' => self::toMarkdown($comment['content']),
67 'message_rendered' => $comment['content'],
68 'type' => 'comment'
69 ];
70
71 $media = self::getActivityMediaPreview($comment['id']);
72
73 if ($media) {
74 $comemntData['meta'] = $media;
75 }
76
77 if ($parentId) {
78 $comemntData['parent_id'] = $parentId;
79 }
80
81 $newComment = new Comment();
82 $newComment->fill($comemntData);
83 $newComment->created_at = $comment['date_recorded'];
84 $newComment->updated_at = $comment['date_recorded'];
85 $newComment->save();
86
87 return $newComment;
88 }
89
90 public static function buildCommentsTree($comments)
91 {
92 $commentTree = [];
93 $commentMap = [];
94
95 // First pass: create a map of all comments
96 foreach ($comments as $comment) {
97 $commentMap[$comment->id] = [
98 'id' => $comment->id,
99 'content' => self::cleanUpContent($comment->content),
100 'user_id' => $comment->user_id,
101 'date_recorded' => $comment->date_recorded,
102 'mptt_left' => $comment->mptt_left,
103 'mptt_right' => $comment->mptt_right,
104 'children' => []
105 ];
106 }
107
108 // Second pass: build the tree structure
109 foreach ($comments as $comment) {
110 $parentId = $comment->secondary_item_id;
111
112 if ($parentId == $comment->item_id) {
113 // This is a top-level comment
114 $commentTree[] = &$commentMap[$comment->id];
115 } else {
116 // This is a reply to another comment
117 $commentMap[$parentId]['children'][] = &$commentMap[$comment->id];
118 }
119 }
120
121 // Sort the tree based on mptt_left values
122 usort($commentTree, function ($a, $b) {
123 return $a['mptt_left'] - $b['mptt_left'];
124 });
125
126 // Recursive function to sort children
127 $sortChildren = function (&$node) use (&$sortChildren) {
128 usort($node['children'], function ($a, $b) {
129 return $a['mptt_left'] - $b['mptt_left'];
130 });
131
132 foreach ($node['children'] as &$child) {
133 $sortChildren($child);
134 }
135 };
136
137 // Sort children for each top-level comment
138 foreach ($commentTree as &$topLevelComment) {
139 $sortChildren($topLevelComment);
140 }
141
142 foreach ($commentTree as &$comment) {
143 foreach ($comment['children'] as &$child) {
144 $childComments = $child['children'];
145 if ($childComments) {
146 $comment['children'] = array_merge($comment['children'], $childComments);
147 unset($child['children']);
148 }
149 }
150
151 // short the children
152 usort($comment['children'], function ($a, $b) {
153 return $a['id'] - $b['id'];
154 });
155 }
156
157 return $commentTree;
158 }
159
160 public static function cleanUpContent($content)
161 {
162 $pattern = '/<a class=\'bp-suggestions-mention\'[^>]*>(@[\w-]+)<\/a>/is';
163 $replacement = '$1';
164 $content = preg_replace($pattern, $replacement, $content);
165
166 // replace \" or \' with " or '
167 $content = str_replace(['\"', "\'"], ['"', "'"], $content);
168
169 // Shortcut: decode all HTML entities (including hex and decimal) to their UTF-8 characters, including emoji
170 $content = html_entity_decode($content, ENT_QUOTES | ENT_HTML5, 'UTF-8');
171
172 return trim($content);
173 }
174
175 public static function toMarkdown($html)
176 {
177 // Replace header tags
178 $html = preg_replace('/<h1>(.*?)<\/h1>/', '# $1', $html);
179 $html = preg_replace('/<h2>(.*?)<\/h2>/', '## $1', $html);
180 $html = preg_replace('/<h3>(.*?)<\/h3>/', '### $1', $html);
181 $html = preg_replace('/<h4>(.*?)<\/h4>/', '#### $1', $html);
182 $html = preg_replace('/<h5>(.*?)<\/h5>/', '##### $1', $html);
183 $html = preg_replace('/<h6>(.*?)<\/h6>/', '###### $1', $html);
184
185 // Replace bold and italic tags
186 $html = preg_replace('/<strong>(.*?)<\/strong>/', '**$1**', $html);
187 $html = preg_replace('/<b>(.*?)<\/b>/', '**$1**', $html);
188 $html = preg_replace('/<em>(.*?)<\/em>/', '*$1*', $html);
189 $html = preg_replace('/<i>(.*?)<\/i>/', '*$1*', $html);
190
191 // Replace unordered lists
192 $html = preg_replace('/<ul>(.*?)<\/ul>/', "\n$0\n", $html);
193 $html = preg_replace('/<li>(.*?)<\/li>/', "- $1\n", $html);
194
195 // Replace ordered lists
196 $html = preg_replace('/<ol>(.*?)<\/ol>/', "\n$0\n", $html);
197 $html = preg_replace('/<li>(.*?)<\/li>/', "1. $1\n", $html);
198
199 // Replace links
200 $html = preg_replace('/<a href="(.*?)".*?>(.*?)<\/a>/', '[$2]($1)', $html);
201
202 // Replace images
203 $html = preg_replace('/<img src="(.*?)".*?\/?>/', '![](=$1)', $html);
204
205 // Replace blockquotes
206 $html = preg_replace('/<blockquote>(.*?)<\/blockquote>/', "> $1\n", $html);
207
208 // Replace horizontal rules
209 $html = preg_replace('/<hr\/>/', "---\n", $html);
210
211 // Replace pre and code tags
212 $html = preg_replace('/<pre><code>(.*?)<\/code><\/pre>/', "```\n\$1\n```", $html);
213 $html = preg_replace('/<code>(.*?)<\/code>/', "`$1`", $html);
214
215 return trim($html);
216 }
217
218 public static function getActivityMediaPreview($activityId)
219 {
220 return self::getMediaItems($activityId);
221 }
222
223 private static function getMediaItems($activityId)
224 {
225 $mediaPreviews = [];
226 $mediaMetas = fluentCommunityApp('db')->table('bp_activity_meta')
227 ->select(['meta_value', 'meta_key'])
228 ->where('activity_id', $activityId)
229 ->whereIn('meta_key', ['bp_media_ids', '_gif_raw_data'])
230 ->get()
231 ->keyBy('meta_key')
232 ->toArray();
233
234 if (!$mediaMetas) {
235 return null;
236 }
237
238 if (!empty($mediaMetas['bp_media_ids']) && !empty($mediaMetas['bp_media_ids']->meta_value)) {
239 $mediaMeta = $mediaMetas['bp_media_ids'];
240 $mediaIds = explode(',', $mediaMeta->meta_value);
241
242 $mediaItems = fluentCommunityApp('db')->table('bp_media')
243 ->select(['attachment_id'])
244 ->whereIn('id', $mediaIds)
245 ->get()
246 ->pluck('attachment_id')
247 ->toArray();
248
249 $mediaPosts = fluentCommunityApp('db')->table('posts')
250 ->whereIn('id', $mediaItems)
251 ->where('post_type', 'attachment')
252 ->get();
253
254 foreach ($mediaPosts as $mediaPost) {
255 if (strpos($mediaPost->post_mime_type, 'image/') === false) {
256 continue;
257 }
258 $meta = (array)get_post_meta($mediaPost->ID, '_wp_attachment_metadata', true);
259 $mediaPreviews[] = [
260 'media_id' => NULL,
261 'url' => $mediaPost->guid,
262 'type' => 'image',
263 'width' => Arr::get($meta, 'width'),
264 'height' => Arr::get($meta, 'height'),
265 'provider' => 'external'
266 ];
267 }
268 } else if (!empty($mediaMetas['_gif_raw_data'])) {
269 $giphyMeta = Utility::safeUnserialize($mediaMetas['_gif_raw_data']->meta_value);
270 $giphyMedia = Arr::get($giphyMeta, 'images.downsized_medium', []);
271 if (!$giphyMedia || empty($giphyMedia['url'])) {
272 return null;
273 }
274
275 return [
276 'media_preview' => array_filter([
277 'image' => sanitize_url($giphyMedia['url']),
278 'type' => 'image',
279 'provider' => 'giphy',
280 'height' => (int)Arr::get($giphyMedia, 'height', 0),
281 'width' => (int)Arr::get($giphyMedia, 'width', 0),
282 ])
283 ];
284 }
285
286 if (!$mediaPreviews) {
287 return null;
288 }
289
290 if (count($mediaPreviews) == 1) {
291 $media = $mediaPreviews[0];
292 $media['image'] = $media['url'];
293 unset($media['url']);
294 return [
295 'media_preview' => $media
296 ];
297 }
298
299 return [
300 'media_items' => $mediaPreviews
301 ];
302 }
303
304 public static function isBuddyBoss()
305 {
306 return defined('BP_PLATFORM_VERSION');
307 }
308
309 private static function syncPostReactions($postsId, $feedId)
310 {
311 if (!self::isBuddyBoss()) {
312 return;
313 }
314
315 // feed likes
316 $reactions = fluentCommunityApp('db')->table('bb_user_reactions')
317 ->select(['user_id', 'date_created', 'item_id'])
318 ->where('item_id', $postsId)
319 ->where('item_type', 'activity')
320 ->get();
321
322 $likesArray = [];
323 foreach ($reactions as $reaction) {
324 $likesArray[] = [
325 'user_id' => $reaction->user_id,
326 'object_id' => $feedId,
327 'object_type' => 'feed',
328 'type' => 'like',
329 'created_at' => $reaction->date_created,
330 'updated_at' => $reaction->date_created
331 ];
332 }
333
334 if ($likesArray) {
335 Reaction::insert($likesArray);
336 }
337 }
338
339 private static function syncCommentsReactions($commentIdMaps, $feedId)
340 {
341 if (!self::isBuddyBoss()) {
342 return;
343 }
344
345 $bbCommentIds = array_keys($commentIdMaps);
346
347 if (!$bbCommentIds) {
348 return false;
349 }
350
351 $reactions = fluentCommunityApp('db')->table('bb_user_reactions')
352 ->select(['user_id', 'date_created', 'item_id'])
353 ->whereIn('item_id', $bbCommentIds)
354 ->where('item_type', 'activity_comment')
355 ->get();
356
357 $likesArray = [];
358 $likesCount = [];
359 foreach ($reactions as $reaction) {
360 $commentId = (int)Arr::get($commentIdMaps, $reaction->item_id);
361 if ($commentId) {
362 if (empty($likesCount[$commentId])) {
363 $likesCount[$commentId] = 0;
364 }
365 $likesCount[$commentId] = $likesCount[$commentId] + 1;
366 $likesArray[] = [
367 'user_id' => $reaction->user_id,
368 'object_id' => $commentId,
369 'object_type' => 'comment',
370 'parent_id' => $feedId,
371 'type' => 'like',
372 'created_at' => $reaction->date_created,
373 'updated_at' => $reaction->date_created
374 ];
375 }
376 }
377
378 if ($likesArray) {
379 Reaction::insert($likesArray);
380 foreach ($likesCount as $commentId => $count) {
381 Comment::where('id', $commentId)->update(['reactions_count' => $count]);
382 }
383 }
384 }
385
386 public static function syncUser(User $user)
387 {
388 $syncedXprofile = $user->syncXProfile();
389 if (!$syncedXprofile) {
390 return false;
391 }
392
393 $xprofile = $user->xprofile;
394 // Let's sync the cover photo and avatar
395 if (!$xprofile->hasCustomAvatar()) {
396 $avatar = get_avatar_url($user->ID, 'full', true);
397
398 $coverPhoto = bp_attachments_get_attachment(
399 'url',
400 array(
401 'object_dir' => 'members',
402 'item_id' => $user->ID,
403 )
404 );
405
406 $hasChange = false;
407 if ($coverPhoto) {
408 $path = self::getFilePathFromUrl($coverPhoto);
409 if ($path) {
410 $media = self::createMediaFromPath($path, [
411 'object_source' => 'user_cover_photo',
412 'user_id' => $user->ID
413 ]);
414 if ($media) {
415 $meta = $xprofile->meta;
416 $meta['cover_photo'] = $coverPhoto;
417 $xprofile->meta = $meta;
418 $hasChange = true;
419 }
420 }
421 }
422
423 if ($avatar && !strpos($avatar, 'gravatar.com')) {
424 $path = self::getFilePathFromUrl($avatar);
425 if ($path) {
426 $media = self::createMediaFromPath($path, [
427 'object_source' => 'user_photo',
428 'user_id' => $user->ID
429 ]);
430 if ($media) {
431 $avatar = $media->media_url;
432 $xprofile->avatar = $avatar;
433 $hasChange = true;
434 }
435 }
436 }
437
438 if ($hasChange) {
439 $xprofile->save();
440 }
441 }
442
443 if (!self::isBuddyBoss()) {
444 $favIds = get_user_meta($user->ID, 'bp_favorite_activities', true);
445 if ($favIds) {
446 $favFeedIds = fluentCommunityApp('db')->table('bp_activity_meta')
447 ->whereIn('activity_id', $favIds)
448 ->select(['meta_value'])
449 ->where('meta_key', '_fcom_feed_id')
450 ->get()
451 ->pluck('meta_value')
452 ->toArray();
453
454 if ($favFeedIds) {
455 $favPosts = Feed::whereIn('id', $favFeedIds)->get();
456 foreach ($favPosts as $favPost) {
457 $exist = Reaction::where('user_id', $user->ID)
458 ->where('object_id', $favPost->id)
459 ->where('type', 'like')
460 ->objectType('feed')
461 ->exists();
462
463 if (!$exist) {
464 Reaction::create([
465 'user_id' => get_current_user_id(),
466 'object_id' => $favPost->id,
467 'type' => 'like',
468 'object_type' => 'feed'
469 ]);
470
471 $favPost->reactions_count = (int)$favPost->reactions_count + 1;
472 $favPost->save();
473 }
474 }
475 }
476 }
477 }
478
479 return true;
480 }
481
482 public static function migrateGroupData($group, $force = true)
483 {
484 $exitMeta = fluentCommunityApp('db')->table('bp_groups_groupmeta')
485 ->where('group_id', $group->id)
486 ->where('meta_key', '_fcom_space_id')
487 ->first();
488
489 $existingSpace = null;
490 if ($exitMeta) {
491 $existingSpace = Space::find($exitMeta->meta_value);
492 if ($existingSpace && !$force) {
493 return $existingSpace;
494 }
495 }
496
497 // Create a new space group
498 $spaceGroup = null;
499 if (!empty($group->space_menu_id)) {
500 $spaceGroup = SpaceGroup::find($group->space_menu_id);
501 }
502
503 $serial = BaseSpace::when($spaceGroup, function ($q) use ($spaceGroup) {
504 $q->where('parent_id', $spaceGroup->id);
505 })->max('serial') + 1;
506
507 $privacy = $group->status;
508
509 if ($privacy == 'hidden') {
510 $privacy = 'secret';
511 } else if (!in_array($privacy, ['public', 'private'])) {
512 $privacy = 'private';
513 }
514
515 $postBy = fluentCommunityApp('db')->table('bp_groups_groupmeta')
516 ->where('group_id', $group->id)
517 ->where('meta_key', 'activity_feed_status')
518 ->first();
519
520 $restrictedPostOnly = 'no';
521 if ($postBy && $postBy->meta_value != 'members') {
522 $restrictedPostOnly = 'yes';
523 }
524
525 $settings = [
526 'restricted_post_only' => $restrictedPostOnly
527 ];
528
529 $documentStatus = fluentCommunityApp('db')->table('bp_groups_groupmeta')
530 ->where('group_id', $group->id)
531 ->where('meta_key', 'document_status')
532 ->first();
533
534 if ($documentStatus) {
535 $settings = wp_parse_args($settings, [
536 'document_library' => 'yes',
537 'document_access' => 'members_only',
538 'document_upload' => $documentStatus === 'mods' ? 'admin_only' : 'members_only'
539 ]);
540 }
541
542 $groupData = [
543 'title' => sanitize_text_field($group->name),
544 'slug' => Utility::slugify($group->slug),
545 'privacy' => $privacy,
546 'description' => wp_kses_post(wp_unslash($group->description)),
547 'settings' => $settings,
548 'parent_id' => $spaceGroup ? $spaceGroup->id : null,
549 'serial' => $serial ?: 1
550 ];
551
552 if ($existingSpace) {
553 $existingSpace->fill($groupData);
554 $existingSpace->save();
555 } else {
556 $exist = BaseSpace::where('slug', $groupData['slug'])
557 ->exists();
558
559 if ($exist) {
560 $groupData['slug'] = $groupData['slug'] . '-' . time();
561 }
562
563 $existingSpace = Space::create($groupData);
564
565 fluentCommunityApp('db')->table('bp_groups_groupmeta')
566 ->insert([
567 'group_id' => $group->id,
568 'meta_key' => '_fcom_space_id', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
569 'meta_value' => $existingSpace->id // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
570 ]);
571 }
572
573 $groupLogo = bp_core_fetch_avatar(
574 array(
575 'item_id' => $group->id,
576 'avatar_dir' => 'group-avatars',
577 'object' => 'group',
578 'type' => 'full',
579 'html' => false,
580 )
581 );
582 if ($groupLogo) {
583 $filePath = self::getFilePathFromUrl($groupLogo);
584 if ($filePath) {
585 $media = self::createMediaFromPath($filePath, [
586 'object_source' => 'space_logo',
587 'sub_object_id' => $existingSpace->id
588 ]);
589 if ($media) {
590 $existingSpace->logo = $media->media_url;
591 }
592 }
593 }
594
595 $group_cover_image = bp_attachments_get_attachment(
596 'url',
597 array(
598 'object_dir' => 'groups',
599 'item_id' => $group->id,
600 )
601 );
602 if ($group_cover_image) {
603 if ($groupLogo) {
604 $filePath = self::getFilePathFromUrl($group_cover_image);
605 if ($filePath) {
606 $media = self::createMediaFromPath($filePath, [
607 'object_source' => 'space_cover_photo',
608 'sub_object_id' => $existingSpace->id
609 ]);
610 if ($media) {
611 $existingSpace->cover_photo = $media->media_url;
612 }
613 }
614 }
615 }
616
617 $existingSpace->save();
618
619 return $existingSpace;
620 }
621
622 public static function deleteCurrentData()
623 {
624 // delete the folder in uploads folder fluent-community with php please
625 $uploadDir = wp_upload_dir();
626 $fcomDir = $uploadDir['basedir'] . '/fluent-community';
627 if (is_dir($fcomDir)) {
628 // delete the directory and all its content
629 self::deleteDirectory($fcomDir);
630 }
631
632 // reset fluent community data
633 \FluentCommunity\App\Models\Feed::truncate();
634 \FluentCommunity\App\Models\Comment::truncate();
635 \FluentCommunity\App\Models\Reaction::truncate();
636 \FluentCommunity\App\Models\Media::truncate();
637 \FluentCommunity\App\Models\Activity::truncate();
638 \FluentCommunity\App\Models\XProfile::truncate();
639 \FluentCommunity\App\Models\Space::where('type', 'community')->delete();
640
641 // reset buddypress meta data
642 fluentCommunityApp('db')->table('bp_groups_groupmeta')->where('meta_key', '_fcom_space_id')->delete();
643 fluentCommunityApp('db')->table('bp_activity_meta')->where('meta_key', '_fcom_feed_id')->delete();
644
645 delete_option('_bp_fcom_group_maps');
646 delete_option('_bp_fcom_last_post_id');
647 delete_option('_bp_fcom_last_user_id');
648 delete_option('_bp_fcom_last_migrated_member_id');
649 }
650
651 public static function getFcomSpaceIdByGroupId($bbGroupId)
652 {
653 if (!$bbGroupId) {
654 return null;
655 }
656
657 static $groupMaps;
658
659 if (!$groupMaps) {
660 $groupMaps = get_option('_bp_fcom_group_maps', []);
661 }
662
663 return isset($groupMaps[$bbGroupId]) ? $groupMaps[$bbGroupId] : null;
664
665 }
666
667 private static function deleteDirectory($dir)
668 {
669 // Include WordPress filesystem API
670 if (!function_exists('WP_Filesystem')) {
671 require_once ABSPATH . 'wp-admin/includes/file.php';
672 }
673
674 // Initialize the WP_Filesystem
675 global $wp_filesystem;
676 if (!WP_Filesystem()) {
677 return false; // Filesystem initialization failed
678 }
679
680 // Sanitize the directory path
681 $dir = trailingslashit($dir);
682
683 // Check if directory exists
684 if (!$wp_filesystem->is_dir($dir)) {
685 return false; // Directory doesn't exist
686 }
687
688 // Delete directory and its contents recursively
689 $result = $wp_filesystem->rmdir($dir, true);
690
691 return $result;
692 }
693
694 private static function getFilePathFromUrl($url)
695 {
696 // Parse the URL to get its components
697 $parsed_url = wp_parse_url($url);
698 // Get the path from the URL
699 $url_path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
700
701 // Remove the site URL part to get the relative path
702
703 // handle http / https both
704 $site_url = site_url(''); // e.g., https://example.com
705 if (strpos($url, $site_url) === false) {
706 $site_url = str_replace('https://', 'http://', $site_url);
707 }
708 if (strpos($url, $site_url) === false) {
709 $site_url = str_replace('http://', 'https://', $site_url);
710 }
711
712 $relative_path = str_replace($site_url, '', $url);
713
714 // Combine with ABSPATH to get the full file path
715 $file_path = ABSPATH . ltrim($relative_path, '/');
716
717 // Check if the file exists
718 if (file_exists($file_path)) {
719 return $file_path;
720 }
721
722 return false; // Return false if the file doesn't exist
723 }
724
725 public static function createMediaFromPath($path, $mediaArgs = [])
726 {
727 $defaults = [
728 'media_key' => md5(wp_generate_uuid4()),
729 'is_active' => 1,
730 'driver' => 'local',
731 'media_path' => '',
732 'media_url' => '',
733 'settings' => [],
734 'object_source' => ''
735 ];
736
737 $mediaArgs = wp_parse_args($mediaArgs, $defaults);
738
739
740 if (empty($mediaArgs['object_source'])) {
741 return null;
742 }
743
744 $fileName = basename($path);
745
746 $mediaArgs['settings']['original_name'] = $fileName;
747
748 // copy the file to uploads/fluent-community
749 $uploadDir = wp_upload_dir();
750 $fcomDir = $uploadDir['basedir'] . '/fluent-community';
751 if (!is_dir($fcomDir)) {
752 wp_mkdir_p($fcomDir);
753 }
754
755 $newFilePath = $fcomDir . '/fluentcom-' . md5(wp_generate_uuid4()) . '-fluentcom-' . $fileName;
756
757
758 if (!copy($path, $newFilePath)) {
759 return null;
760 }
761
762 $fileUrl = str_replace($fcomDir, wp_upload_dir()['baseurl'] . '/fluent-community', $newFilePath);
763
764 $mediaArgs['media_path'] = $newFilePath;
765 $mediaArgs['media_url'] = $fileUrl;
766
767 $mediaArgs['media_type '] = mime_content_type($newFilePath);
768
769 $imageSizes = wp_getimagesize($newFilePath);
770
771
772 if ($imageSizes && count($imageSizes) >= 2) {
773 $mediaArgs['settings']['width'] = $imageSizes[0];
774 $mediaArgs['settings']['height'] = $imageSizes[1];
775 }
776
777 return Media::create($mediaArgs);
778 }
779
780 public static function recalculateUserPoints($userId)
781 {
782 // SUM of all the points of the Comment Model
783 $commentPoints = Comment::where('user_id', $userId)
784 ->sum('reactions_count');
785
786 $postsPoints = Feed::where('user_id', $userId)
787 ->sum('reactions_count');
788
789 return $commentPoints + $postsPoints;
790 }
791
792 public static function maybeEnableFollowersModule()
793 {
794 if (!defined('FLUENT_COMMUNITY_PRO')) {
795 return;
796 }
797
798 $isEnabled = Helper::isFeatureEnabled('followers_module');
799 if ($isEnabled) {
800 return;
801 }
802
803 if (fluentCommunityApp('db')->table('bp_friends')->exists()) {
804 \FluentCommunityPro\App\Modules\Followers\FollowerHelper::updateSettings(['is_enabled' => 'yes']);
805 }
806 }
807 }
808