fluentCommunityApp('db')->table('bp_groups')->count(), 'total_posts' => fluentCommunityApp('db')->table('bp_activity')->where('type', 'activity_update')->count(), 'total_comments' => fluentCommunityApp('db')->table('bp_activity')->where('type', 'activity_comment')->count(), 'total_reactions' => class_exists('\BB_Reaction') ? fluentCommunityApp('db')->table('bb_user_reactions')->whereIn('item_type', ['activity_comment', 'activity'])->count() : 0, 'total_community_users' => User::count(), ]; } public static function migratePost($post, $spaceId = null) { return (new PostMigrator($post))->migrate(); } public static function syncComments($activityId, Feed $feed) { // Let's manage the comments $comments = fluentCommunityApp('db')->table('bp_activity') ->where('type', 'activity_comment') ->where('item_id', $activityId) ->orderBy('id', 'ASC') ->get(); $comments = self::buildCommentsTree($comments); $commentMaps = []; foreach ($comments as $comment) { $newComment = self::insertBBComment($comment, $feed); $commentMaps[$comment['id']] = $newComment->id; if ($comment['children']) { foreach ($comment['children'] as $child) { $childComment = self::insertBBComment($child, $feed, $newComment->id); $commentMaps[$child['id']] = $childComment->id; } } } return $commentMaps; } public static function insertBBComment($comment, $feed, $parentId = null) { $comemntData = [ 'user_id' => $comment['user_id'], 'post_id' => $feed->id, 'message' => self::toMarkdown($comment['content']), 'message_rendered' => $comment['content'], 'type' => 'comment' ]; $media = self::getActivityMediaPreview($comment['id']); if ($media) { $comemntData['meta'] = $media; } if ($parentId) { $comemntData['parent_id'] = $parentId; } $newComment = new Comment(); $newComment->fill($comemntData); $newComment->created_at = $comment['date_recorded']; $newComment->updated_at = $comment['date_recorded']; $newComment->save(); return $newComment; } public static function buildCommentsTree($comments) { $commentTree = []; $commentMap = []; // First pass: create a map of all comments foreach ($comments as $comment) { $commentMap[$comment->id] = [ 'id' => $comment->id, 'content' => self::cleanUpContent($comment->content), 'user_id' => $comment->user_id, 'date_recorded' => $comment->date_recorded, 'mptt_left' => $comment->mptt_left, 'mptt_right' => $comment->mptt_right, 'children' => [] ]; } // Second pass: build the tree structure foreach ($comments as $comment) { $parentId = $comment->secondary_item_id; if ($parentId == $comment->item_id) { // This is a top-level comment $commentTree[] = &$commentMap[$comment->id]; } else { // This is a reply to another comment $commentMap[$parentId]['children'][] = &$commentMap[$comment->id]; } } // Sort the tree based on mptt_left values usort($commentTree, function ($a, $b) { return $a['mptt_left'] - $b['mptt_left']; }); // Recursive function to sort children $sortChildren = function (&$node) use (&$sortChildren) { usort($node['children'], function ($a, $b) { return $a['mptt_left'] - $b['mptt_left']; }); foreach ($node['children'] as &$child) { $sortChildren($child); } }; // Sort children for each top-level comment foreach ($commentTree as &$topLevelComment) { $sortChildren($topLevelComment); } foreach ($commentTree as &$comment) { foreach ($comment['children'] as &$child) { $childComments = $child['children']; if ($childComments) { $comment['children'] = array_merge($comment['children'], $childComments); unset($child['children']); } } // short the children usort($comment['children'], function ($a, $b) { return $a['id'] - $b['id']; }); } return $commentTree; } public static function cleanUpContent($content) { $pattern = '/]*>(@[\w-]+)<\/a>/is'; $replacement = '$1'; $content = preg_replace($pattern, $replacement, $content); // replace \" or \' with " or ' $content = str_replace(['\"', "\'"], ['"', "'"], $content); // Shortcut: decode all HTML entities (including hex and decimal) to their UTF-8 characters, including emoji $content = html_entity_decode($content, ENT_QUOTES | ENT_HTML5, 'UTF-8'); return trim($content); } public static function toMarkdown($html) { // Replace header tags $html = preg_replace('/

(.*?)<\/h1>/', '# $1', $html); $html = preg_replace('/

(.*?)<\/h2>/', '## $1', $html); $html = preg_replace('/

(.*?)<\/h3>/', '### $1', $html); $html = preg_replace('/

(.*?)<\/h4>/', '#### $1', $html); $html = preg_replace('/

(.*?)<\/h5>/', '##### $1', $html); $html = preg_replace('/
(.*?)<\/h6>/', '###### $1', $html); // Replace bold and italic tags $html = preg_replace('/(.*?)<\/strong>/', '**$1**', $html); $html = preg_replace('/(.*?)<\/b>/', '**$1**', $html); $html = preg_replace('/(.*?)<\/em>/', '*$1*', $html); $html = preg_replace('/(.*?)<\/i>/', '*$1*', $html); // Replace unordered lists $html = preg_replace('/