diff --git a/app/Http/Controllers/api/BylawApiController.php b/app/Http/Controllers/api/BylawApiController.php index 6573926..95fd134 100644 --- a/app/Http/Controllers/api/BylawApiController.php +++ b/app/Http/Controllers/api/BylawApiController.php @@ -80,16 +80,20 @@ class BylawApiController extends Controller $perPage = min(max((int) $request->input('per_page', 15), 10), 100); $paginator = $query->paginate($perPage); - // Pre-fetch ALL nodes directly via DB facade for speed and reliability - $documentIds = collect($paginator->items())->pluck('id'); - $allNodes = DB::table('bylaw_nodes') - ->whereIn('document_id', $documentIds) - ->orderBy('sort_order', 'asc') - ->get() - ->groupBy('document_id'); + // BULLETPROOF NODE FETCHING + $documentIds = collect($paginator->items())->pluck('id')->toArray(); + $allNodes = collect(); + if (!empty($documentIds)) { + $allNodes = DB::table('bylaw_nodes') + ->whereIn('document_id', $documentIds) + ->orderBy('sort_order', 'asc') + ->get(); + } $items = collect($paginator->items())->map(function ($item) use ($allNodes) { - return $this->formatBylaw($item, $allNodes->get($item->id, collect())); + // Safely filter nodes belonging ONLY to this specific document + $itemNodes = $allNodes->where('document_id', $item->id); + return $this->formatBylaw($item, $itemNodes); }); $responseData = [ @@ -116,8 +120,12 @@ class BylawApiController extends Controller ], 404); } - // Fetch nodes using DB facade for the format function, but Eloquent for the nodes array - $rawNodes = DB::table('bylaw_nodes')->where('document_id', $bylaw->id)->orderBy('sort_order', 'asc')->get(); + // Fetch nodes using raw DB + $rawNodes = DB::table('bylaw_nodes') + ->where('document_id', $bylaw->id) + ->orderBy('sort_order', 'asc') + ->get(); + $formatted = $this->formatBylaw($bylaw, $rawNodes); if (!$formatted['is_locked']) { @@ -203,15 +211,19 @@ class BylawApiController extends Controller $perPage = min(max((int) $request->input('per_page', 15), 10), 100); $paginator = $query->paginate($perPage); - $documentIds = collect($paginator->items())->pluck('id'); - $allNodes = DB::table('bylaw_nodes') - ->whereIn('document_id', $documentIds) - ->orderBy('sort_order', 'asc') - ->get() - ->groupBy('document_id'); + // BULLETPROOF NODE FETCHING + $documentIds = collect($paginator->items())->pluck('id')->toArray(); + $allNodes = collect(); + if (!empty($documentIds)) { + $allNodes = DB::table('bylaw_nodes') + ->whereIn('document_id', $documentIds) + ->orderBy('sort_order', 'asc') + ->get(); + } $items = collect($paginator->items())->map(function ($item) use ($allNodes) { - return $this->formatBylaw($item, $allNodes->get($item->id, collect())); + $itemNodes = $allNodes->where('document_id', $item->id); + return $this->formatBylaw($item, $itemNodes); }); $responseData = [ @@ -250,15 +262,19 @@ class BylawApiController extends Controller $count = $query->count(); $items = $query->orderBy('approval_date', 'desc')->take(5)->get(); - $documentIds = $items->pluck('id'); - $allNodes = DB::table('bylaw_nodes') - ->whereIn('document_id', $documentIds) - ->orderBy('sort_order', 'asc') - ->get() - ->groupBy('document_id'); + // BULLETPROOF NODE FETCHING + $documentIds = $items->pluck('id')->toArray(); + $allNodes = collect(); + if (!empty($documentIds)) { + $allNodes = DB::table('bylaw_nodes') + ->whereIn('document_id', $documentIds) + ->orderBy('sort_order', 'asc') + ->get(); + } $formattedItems = $items->map(function ($item) use ($allNodes) { - return $this->formatBylaw($item, $allNodes->get($item->id, collect())); + $itemNodes = $allNodes->where('document_id', $item->id); + return $this->formatBylaw($item, $itemNodes); }); return $this->success([ @@ -319,15 +335,18 @@ class BylawApiController extends Controller $itemsToFormat = array_filter([$previousItem, $current, $nextItem]); - $documentIds = collect($itemsToFormat)->pluck('id'); - $allNodes = DB::table('bylaw_nodes') - ->whereIn('document_id', $documentIds) - ->orderBy('sort_order', 'asc') - ->get() - ->groupBy('document_id'); + $documentIds = collect($itemsToFormat)->pluck('id')->toArray(); + $allNodes = collect(); + if (!empty($documentIds)) { + $allNodes = DB::table('bylaw_nodes') + ->whereIn('document_id', $documentIds) + ->orderBy('sort_order', 'asc') + ->get(); + } $results = array_values(array_map(function($item) use ($allNodes) { - return $this->formatBylaw($item, $allNodes->get($item->id, collect())); + $itemNodes = $allNodes->where('document_id', $item->id); + return $this->formatBylaw($item, $itemNodes); }, $itemsToFormat)); return $this->success($results, 'Success', 'Pager Window Details'); @@ -341,30 +360,34 @@ class BylawApiController extends Controller /** * BULLETPROOF DESCRIPTION GENERATOR */ - private function formatBylaw($item, $preloadedNodes = null) + private function formatBylaw($item, $itemNodes = null) { $isLocked = $this->isLockedForCurrentUser($item); + $description = $item->description; - // 1. We ALWAYS try to build the description from the `node_content` FIRST. - $nodes = $preloadedNodes !== null - ? $preloadedNodes - : DB::table('bylaw_nodes')->where('document_id', $item->id)->orderBy('sort_order', 'asc')->get(); + // Check if description is practically empty (less than 5 chars = garbage HTML) + $cleanDesc = trim(str_replace([' ', '‌', "\r", "\n", "\t", ' '], '', strip_tags($description ?? ''))); - $nodeContents = []; - foreach ($nodes as $node) { - // We specifically ask for the node_content column here - $content = trim(strip_tags($node->node_content ?? '')); - if (!empty($content)) { - $nodeContents[] = $content; + if (strlen($cleanDesc) < 5) { + + // Absolute Safety Net: If somehow $itemNodes is still null, FORCE a direct query for this specific ID. + if ($itemNodes === null) { + $itemNodes = DB::table('bylaw_nodes') + ->where('document_id', $item->id) + ->orderBy('sort_order', 'asc') + ->get(); } - } - // Stitch them all together - $description = implode("\n\n", $nodeContents); + $nodeContents = []; + foreach ($itemNodes as $node) { + // EXPLICITLY GET node_content + $content = trim(strip_tags($node->node_content ?? '')); + if (!empty($content)) { + $nodeContents[] = $content; + } + } - // 2. If node_content is COMPLETELY EMPTY across all nodes, ONLY THEN do we fallback to the old description - if (empty(trim(strip_tags($description)))) { - $description = $item->description; + $description = implode("\n\n", $nodeContents); } return [