PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.7.5
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.7.5
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 1.1.0 All 77 releases
fluent-community / Modules / Migrations / Helpers / BPMigratorHelper.php

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

809 lines 27.3 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 /** @phpstan-ignore argument.type (BuddyPress overrides get_avatar_url with different signature; WP stub doesn't match BP variant) */
397 $avatar = get_avatar_url($user->ID, 'full', true);
398
399 $coverPhoto = bp_attachments_get_attachment(
400 'url',
401 array(
402 'object_dir' => 'members',
403 'item_id' => $user->ID,
404 )
405 );
406
407 $hasChange = false;
408 if ($coverPhoto) {
409 $path = self::getFilePathFromUrl($coverPhoto);
410 if ($path) {
411 $media = self::createMediaFromPath($path, [
412 'object_source' => 'user_cover_photo',
413 'user_id' => $user->ID
414 ]);
415 if ($media) {
416 $meta = $xprofile->meta;
417 $meta['cover_photo'] = $coverPhoto;
418 $xprofile->meta = $meta;
419 $hasChange = true;
420 }
421 }
422 }
423
424 if ($avatar && !strpos($avatar, 'gravatar.com')) {
425 $path = self::getFilePathFromUrl($avatar);
426 if ($path) {
427 $media = self::createMediaFromPath($path, [
428 'object_source' => 'user_photo',
429 'user_id' => $user->ID
430 ]);
431 if ($media) {
432 $avatar = $media->media_url;
433 $xprofile->avatar = $avatar;
434 $hasChange = true;
435 }
436 }
437 }
438
439 if ($hasChange) {
440 $xprofile->save();
441 }
442 }
443
444 if (!self::isBuddyBoss()) {
445 $favIds = get_user_meta($user->ID, 'bp_favorite_activities', true);
446 if ($favIds) {
447 $favFeedIds = fluentCommunityApp('db')->table('bp_activity_meta')
448 ->whereIn('activity_id', $favIds)
449 ->select(['meta_value'])
450 ->where('meta_key', '_fcom_feed_id')
451 ->get()
452 ->pluck('meta_value')
453 ->toArray();
454
455 if ($favFeedIds) {
456 $favPosts = Feed::whereIn('id', $favFeedIds)->get();
457 foreach ($favPosts as $favPost) {
458 $exist = Reaction::where('user_id', $user->ID)
459 ->where('object_id', $favPost->id)
460 ->where('type', 'like')
461 ->objectType('feed')
462 ->exists();
463
464 if (!$exist) {
465 Reaction::create([
466 'user_id' => get_current_user_id(),
467 'object_id' => $favPost->id,
468 'type' => 'like',
469 'object_type' => 'feed'
470 ]);
471
472 $favPost->reactions_count = (int)$favPost->reactions_count + 1;
473 $favPost->save();
474 }
475 }
476 }
477 }
478 }
479
480 return true;
481 }
482
483 public static function migrateGroupData($group, $force = true)
484 {
485 $exitMeta = fluentCommunityApp('db')->table('bp_groups_groupmeta')
486 ->where('group_id', $group->id)
487 ->where('meta_key', '_fcom_space_id')
488 ->first();
489
490 $existingSpace = null;
491 if ($exitMeta) {
492 $existingSpace = Space::find($exitMeta->meta_value);
493 if ($existingSpace && !$force) {
494 return $existingSpace;
495 }
496 }
497
498 // Create a new space group
499 $spaceGroup = null;
500 if (!empty($group->space_menu_id)) {
501 $spaceGroup = SpaceGroup::find($group->space_menu_id);
502 }
503
504 $serial = BaseSpace::when($spaceGroup, function ($q) use ($spaceGroup) {
505 $q->where('parent_id', $spaceGroup->id);
506 })->max('serial') + 1;
507
508 $privacy = $group->status;
509
510 if ($privacy == 'hidden') {
511 $privacy = 'secret';
512 } else if (!in_array($privacy, ['public', 'private'])) {
513 $privacy = 'private';
514 }
515
516 $postBy = fluentCommunityApp('db')->table('bp_groups_groupmeta')
517 ->where('group_id', $group->id)
518 ->where('meta_key', 'activity_feed_status')
519 ->first();
520
521 $restrictedPostOnly = 'no';
522 if ($postBy && $postBy->meta_value != 'members') {
523 $restrictedPostOnly = 'yes';
524 }
525
526 $settings = [
527 'restricted_post_only' => $restrictedPostOnly
528 ];
529
530 $documentStatus = fluentCommunityApp('db')->table('bp_groups_groupmeta')
531 ->where('group_id', $group->id)
532 ->where('meta_key', 'document_status')
533 ->first();
534
535 if ($documentStatus) {
536 $settings = wp_parse_args($settings, [
537 'document_library' => 'yes',
538 'document_access' => 'members_only',
539 'document_upload' => $documentStatus === 'mods' ? 'admin_only' : 'members_only'
540 ]);
541 }
542
543 $groupData = [
544 'title' => sanitize_text_field($group->name),
545 'slug' => Utility::slugify($group->slug),
546 'privacy' => $privacy,
547 'description' => wp_kses_post(wp_unslash($group->description)),
548 'settings' => $settings,
549 'parent_id' => $spaceGroup ? $spaceGroup->id : null,
550 'serial' => $serial ?: 1
551 ];
552
553 if ($existingSpace) {
554 $existingSpace->fill($groupData);
555 $existingSpace->save();
556 } else {
557 $exist = BaseSpace::where('slug', $groupData['slug'])
558 ->exists();
559
560 if ($exist) {
561 $groupData['slug'] = $groupData['slug'] . '-' . time();
562 }
563
564 $existingSpace = Space::create($groupData);
565
566 fluentCommunityApp('db')->table('bp_groups_groupmeta')
567 ->insert([
568 'group_id' => $group->id,
569 'meta_key' => '_fcom_space_id', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
570 'meta_value' => $existingSpace->id // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
571 ]);
572 }
573
574 $groupLogo = bp_core_fetch_avatar(
575 array(
576 'item_id' => $group->id,
577 'avatar_dir' => 'group-avatars',
578 'object' => 'group',
579 'type' => 'full',
580 'html' => false,
581 )
582 );
583 if ($groupLogo) {
584 $filePath = self::getFilePathFromUrl($groupLogo);
585 if ($filePath) {
586 $media = self::createMediaFromPath($filePath, [
587 'object_source' => 'space_logo',
588 'sub_object_id' => $existingSpace->id
589 ]);
590 if ($media) {
591 $existingSpace->logo = $media->media_url;
592 }
593 }
594 }
595
596 $group_cover_image = bp_attachments_get_attachment(
597 'url',
598 array(
599 'object_dir' => 'groups',
600 'item_id' => $group->id,
601 )
602 );
603 if ($group_cover_image) {
604 if ($groupLogo) {
605 $filePath = self::getFilePathFromUrl($group_cover_image);
606 if ($filePath) {
607 $media = self::createMediaFromPath($filePath, [
608 'object_source' => 'space_cover_photo',
609 'sub_object_id' => $existingSpace->id
610 ]);
611 if ($media) {
612 $existingSpace->cover_photo = $media->media_url;
613 }
614 }
615 }
616 }
617
618 $existingSpace->save();
619
620 return $existingSpace;
621 }
622
623 public static function deleteCurrentData()
624 {
625 // delete the folder in uploads folder fluent-community with php please
626 $uploadDir = wp_upload_dir();
627 $fcomDir = $uploadDir['basedir'] . '/fluent-community';
628 if (is_dir($fcomDir)) {
629 // delete the directory and all its content
630 self::deleteDirectory($fcomDir);
631 }
632
633 // reset fluent community data
634 \FluentCommunity\App\Models\Feed::truncate();
635 \FluentCommunity\App\Models\Comment::truncate();
636 \FluentCommunity\App\Models\Reaction::truncate();
637 \FluentCommunity\App\Models\Media::truncate();
638 \FluentCommunity\App\Models\Activity::truncate();
639 \FluentCommunity\App\Models\XProfile::truncate();
640 \FluentCommunity\App\Models\Space::where('type', 'community')->delete();
641
642 // reset buddypress meta data
643 fluentCommunityApp('db')->table('bp_groups_groupmeta')->where('meta_key', '_fcom_space_id')->delete();
644 fluentCommunityApp('db')->table('bp_activity_meta')->where('meta_key', '_fcom_feed_id')->delete();
645
646 delete_option('_bp_fcom_group_maps');
647 delete_option('_bp_fcom_last_post_id');
648 delete_option('_bp_fcom_last_user_id');
649 delete_option('_bp_fcom_last_migrated_member_id');
650 }
651
652 public static function getFcomSpaceIdByGroupId($bbGroupId)
653 {
654 if (!$bbGroupId) {
655 return null;
656 }
657
658 static $groupMaps;
659
660 if (!$groupMaps) {
661 $groupMaps = get_option('_bp_fcom_group_maps', []);
662 }
663
664 return isset($groupMaps[$bbGroupId]) ? $groupMaps[$bbGroupId] : null;
665
666 }
667
668 private static function deleteDirectory($dir)
669 {
670 // Include WordPress filesystem API
671 if (!function_exists('WP_Filesystem')) {
672 require_once ABSPATH . 'wp-admin/includes/file.php';
673 }
674
675 // Initialize the WP_Filesystem
676 global $wp_filesystem;
677 if (!WP_Filesystem()) {
678 return false; // Filesystem initialization failed
679 }
680
681 // Sanitize the directory path
682 $dir = trailingslashit($dir);
683
684 // Check if directory exists
685 if (!$wp_filesystem->is_dir($dir)) {
686 return false; // Directory doesn't exist
687 }
688
689 // Delete directory and its contents recursively
690 $result = $wp_filesystem->rmdir($dir, true);
691
692 return $result;
693 }
694
695 private static function getFilePathFromUrl($url)
696 {
697 // Parse the URL to get its components
698 $parsed_url = wp_parse_url($url);
699 // Get the path from the URL
700 $url_path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
701
702 // Remove the site URL part to get the relative path
703
704 // handle http / https both
705 $site_url = site_url(''); // e.g., https://example.com
706 if (strpos($url, $site_url) === false) {
707 $site_url = str_replace('https://', 'http://', $site_url);
708 }
709 if (strpos($url, $site_url) === false) {
710 $site_url = str_replace('http://', 'https://', $site_url);
711 }
712
713 $relative_path = str_replace($site_url, '', $url);
714
715 // Combine with ABSPATH to get the full file path
716 $file_path = ABSPATH . ltrim($relative_path, '/');
717
718 // Check if the file exists
719 if (file_exists($file_path)) {
720 return $file_path;
721 }
722
723 return false; // Return false if the file doesn't exist
724 }
725
726 public static function createMediaFromPath($path, $mediaArgs = [])
727 {
728 $defaults = [
729 'media_key' => md5(wp_generate_uuid4()),
730 'is_active' => 1,
731 'driver' => 'local',
732 'media_path' => '',
733 'media_url' => '',
734 'settings' => [],
735 'object_source' => ''
736 ];
737
738 $mediaArgs = wp_parse_args($mediaArgs, $defaults);
739
740
741 if (empty($mediaArgs['object_source'])) {
742 return null;
743 }
744
745 $fileName = basename($path);
746
747 $mediaArgs['settings']['original_name'] = $fileName;
748
749 // copy the file to uploads/fluent-community
750 $uploadDir = wp_upload_dir();
751 $fcomDir = $uploadDir['basedir'] . '/fluent-community';
752 if (!is_dir($fcomDir)) {
753 wp_mkdir_p($fcomDir);
754 }
755
756 $newFilePath = $fcomDir . '/fluentcom-' . md5(wp_generate_uuid4()) . '-fluentcom-' . $fileName;
757
758
759 if (!copy($path, $newFilePath)) {
760 return null;
761 }
762
763 $fileUrl = str_replace($fcomDir, wp_upload_dir()['baseurl'] . '/fluent-community', $newFilePath);
764
765 $mediaArgs['media_path'] = $newFilePath;
766 $mediaArgs['media_url'] = $fileUrl;
767
768 $mediaArgs['media_type '] = mime_content_type($newFilePath);
769
770 $imageSizes = wp_getimagesize($newFilePath);
771
772
773 if ($imageSizes && count($imageSizes) >= 2) {
774 $mediaArgs['settings']['width'] = $imageSizes[0];
775 $mediaArgs['settings']['height'] = $imageSizes[1];
776 }
777
778 return Media::create($mediaArgs);
779 }
780
781 public static function recalculateUserPoints($userId)
782 {
783 // SUM of all the points of the Comment Model
784 $commentPoints = Comment::where('user_id', $userId)
785 ->sum('reactions_count');
786
787 $postsPoints = Feed::where('user_id', $userId)
788 ->sum('reactions_count');
789
790 return $commentPoints + $postsPoints;
791 }
792
793 public static function maybeEnableFollowersModule()
794 {
795 if (!defined('FLUENT_COMMUNITY_PRO')) {
796 return;
797 }
798
799 $isEnabled = Helper::isFeatureEnabled('followers_module');
800 if ($isEnabled) {
801 return;
802 }
803
804 if (fluentCommunityApp('db')->table('bp_friends')->exists()) {
805 \FluentCommunityPro\App\Modules\Followers\FollowerHelper::updateSettings(['is_enabled' => 'yes']);
806 }
807 }
808 }
809