diff --git a/app/Http/Controllers/api/BylawApiController.php b/app/Http/Controllers/api/BylawApiController.php index a880a77..f77e061 100644 --- a/app/Http/Controllers/api/BylawApiController.php +++ b/app/Http/Controllers/api/BylawApiController.php @@ -80,22 +80,30 @@ class BylawApiController extends Controller $perPage = min(max((int) $request->input('per_page', 15), 10), 100); $paginator = $query->paginate($perPage); - // واکشی بهینه گره‌ها از دیتابیس + // واکشی ۱۰۰٪ قطعی گره‌ها با آرایه‌های بومی (Native PHP Arrays) $documentIds = collect($paginator->items())->pluck('id')->toArray(); - $allNodes = collect(); + $nodesDictionary = []; + if (!empty($documentIds)) { - $allNodes = DB::table('bylaw_nodes') + $nodes = DB::table('bylaw_nodes') ->whereIn('document_id', $documentIds) ->orderBy('sort_order', 'asc') + ->select('document_id', 'node_content') ->get(); + + foreach ($nodes as $node) { + $docId = $node->document_id; + if (!isset($nodesDictionary[$docId])) { + $nodesDictionary[$docId] = []; + } + if (!empty(trim((string)$node->node_content))) { + $nodesDictionary[$docId][] = trim((string)$node->node_content); + } + } } - $items = collect($paginator->items())->map(function ($item) use ($allNodes) { - // حل مشکل فیلتر سخت‌گیرانه (Strict) در کالکشن‌ها - $itemNodes = $allNodes->filter(function($node) use ($item) { - return $node->document_id == $item->id; - }); - return $this->formatBylaw($item, $itemNodes); + $items = collect($paginator->items())->map(function ($item) use ($nodesDictionary) { + return $this->formatBylaw($item, $nodesDictionary[$item->id] ?? null); }); $responseData = [ @@ -122,13 +130,7 @@ class BylawApiController extends Controller ], 404); } - // واکشی خام گره‌ها برای توضیحات کلی - $rawNodes = DB::table('bylaw_nodes') - ->where('document_id', $bylaw->id) - ->orderBy('sort_order', 'asc') - ->get(); - - $formatted = $this->formatBylaw($bylaw, $rawNodes); + $formatted = $this->formatBylaw($bylaw); if (!$formatted['is_locked']) { $eloquentNodes = BylawNode::with('type') @@ -214,19 +216,28 @@ class BylawApiController extends Controller $paginator = $query->paginate($perPage); $documentIds = collect($paginator->items())->pluck('id')->toArray(); - $allNodes = collect(); + $nodesDictionary = []; + if (!empty($documentIds)) { - $allNodes = DB::table('bylaw_nodes') + $nodes = DB::table('bylaw_nodes') ->whereIn('document_id', $documentIds) ->orderBy('sort_order', 'asc') + ->select('document_id', 'node_content') ->get(); + + foreach ($nodes as $node) { + $docId = $node->document_id; + if (!isset($nodesDictionary[$docId])) { + $nodesDictionary[$docId] = []; + } + if (!empty(trim((string)$node->node_content))) { + $nodesDictionary[$docId][] = trim((string)$node->node_content); + } + } } - $items = collect($paginator->items())->map(function ($item) use ($allNodes) { - $itemNodes = $allNodes->filter(function($node) use ($item) { - return $node->document_id == $item->id; - }); - return $this->formatBylaw($item, $itemNodes); + $items = collect($paginator->items())->map(function ($item) use ($nodesDictionary) { + return $this->formatBylaw($item, $nodesDictionary[$item->id] ?? null); }); $responseData = [ @@ -266,19 +277,28 @@ class BylawApiController extends Controller $items = $query->orderBy('approval_date', 'desc')->take(5)->get(); $documentIds = $items->pluck('id')->toArray(); - $allNodes = collect(); + $nodesDictionary = []; + if (!empty($documentIds)) { - $allNodes = DB::table('bylaw_nodes') + $nodes = DB::table('bylaw_nodes') ->whereIn('document_id', $documentIds) ->orderBy('sort_order', 'asc') + ->select('document_id', 'node_content') ->get(); + + foreach ($nodes as $node) { + $docId = $node->document_id; + if (!isset($nodesDictionary[$docId])) { + $nodesDictionary[$docId] = []; + } + if (!empty(trim((string)$node->node_content))) { + $nodesDictionary[$docId][] = trim((string)$node->node_content); + } + } } - $formattedItems = $items->map(function ($item) use ($allNodes) { - $itemNodes = $allNodes->filter(function($node) use ($item) { - return $node->document_id == $item->id; - }); - return $this->formatBylaw($item, $itemNodes); + $formattedItems = $items->map(function ($item) use ($nodesDictionary) { + return $this->formatBylaw($item, $nodesDictionary[$item->id] ?? null); }); return $this->success([ @@ -340,19 +360,28 @@ class BylawApiController extends Controller $itemsToFormat = array_filter([$previousItem, $current, $nextItem]); $documentIds = collect($itemsToFormat)->pluck('id')->toArray(); - $allNodes = collect(); + $nodesDictionary = []; + if (!empty($documentIds)) { - $allNodes = DB::table('bylaw_nodes') + $nodes = DB::table('bylaw_nodes') ->whereIn('document_id', $documentIds) ->orderBy('sort_order', 'asc') + ->select('document_id', 'node_content') ->get(); + + foreach ($nodes as $node) { + $docId = $node->document_id; + if (!isset($nodesDictionary[$docId])) { + $nodesDictionary[$docId] = []; + } + if (!empty(trim((string)$node->node_content))) { + $nodesDictionary[$docId][] = trim((string)$node->node_content); + } + } } - $results = array_values(array_map(function($item) use ($allNodes) { - $itemNodes = $allNodes->filter(function($node) use ($item) { - return $node->document_id == $item->id; - }); - return $this->formatBylaw($item, $itemNodes); + $results = array_values(array_map(function($item) use ($nodesDictionary) { + return $this->formatBylaw($item, $nodesDictionary[$item->id] ?? null); }, $itemsToFormat)); return $this->success($results, 'Success', 'Pager Window Details'); @@ -364,38 +393,38 @@ class BylawApiController extends Controller } /** - * BULLETPROOF DESCRIPTION GENERATOR + * سیستم کاملاً ضد گلوله برای استخراج Description */ - private function formatBylaw($item, $itemNodes = null) + private function formatBylaw($item, $preloadedNodes = null) { $isLocked = $this->isLockedForCurrentUser($item); + + // ۱. اولویت اول: متنی که ادمین در پنل وارد کرده است $description = $item->description; - $cleanDesc = trim(str_replace([' ', '‌', "\r", "\n", "\t", ' '], '', strip_tags($description ?? ''))); + // ۲. اولویت دوم: اگر توضیحات ادمین خالی بود، متن قانون را از گره‌ها می‌گیریم + if (empty(trim((string)$description))) { - // اگر فیلد اصلی description خالی بود (که در خزش فعلی خالی است)، به سراغ متن اصلی می‌رویم - if (strlen($cleanDesc) < 5) { + // اگر آرایه گره‌ها از قبل (در توابع index یا search) آماده شده بود: + if ($preloadedNodes !== null && is_array($preloadedNodes)) { + $description = implode("\n\n", $preloadedNodes); - // شبکه اطمینان: اگر متغیر حاوی گره‌ها به هر دلیلی خالی بود، مستقیماً از دیتابیس می‌گیریم - if ($itemNodes === null || (is_countable($itemNodes) && count($itemNodes) === 0)) { - $itemNodes = DB::table('bylaw_nodes') + // در غیر این صورت (مثلا در تابع single) مستقیماً از دیتابیس می‌گیریم + } else { + $nodes = DB::table('bylaw_nodes') ->where('document_id', $item->id) ->orderBy('sort_order', 'asc') - ->get(); - } + ->pluck('node_content') + ->toArray(); - $nodeContents = []; - foreach ($itemNodes as $node) { - // استخراج امن متن از آبجکت یا آرایه (برای جلوگیری از خطاهای احتمالی) - $contentRaw = is_array($node) ? ($node['node_content'] ?? '') : ($node->node_content ?? ''); - - $content = trim(strip_tags($contentRaw)); - if (!empty($content)) { - $nodeContents[] = $content; + $validContents = []; + foreach ($nodes as $content) { + if (!empty(trim((string)$content))) { + $validContents[] = trim((string)$content); + } } + $description = implode("\n\n", $validContents); } - - $description = implode("\n\n", $nodeContents); } return [ @@ -416,7 +445,7 @@ class BylawApiController extends Controller 'bylaw_type' => $item->bylaw_type, 'global_status' => $item->global_status, 'pdf_file_url' => $isLocked ? null : ($item->pdf_file_path ? asset('storage/' . $item->pdf_file_path) : null), - 'description' => $isLocked ? null : $description, // متن کامل از node_content اینجا قرار می‌گیرد + 'description' => $isLocked ? null : $description, 'is_locked' => $isLocked, ]; }