Fixed api issue

This commit is contained in:
m.razaghi
2026-07-12 17:42:34 +03:30
parent 2fab528d0a
commit 375e3b166c

View File

@@ -10,6 +10,7 @@ use App\Models\BylawNode;
use App\Models\BylawCodificationLink; use App\Models\BylawCodificationLink;
use App\Traits\BaseApiResponse; use App\Traits\BaseApiResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class BylawApiController extends Controller class BylawApiController extends Controller
{ {
@@ -79,9 +80,13 @@ class BylawApiController extends Controller
$perPage = min(max((int) $request->input('per_page', 15), 10), 100); $perPage = min(max((int) $request->input('per_page', 15), 10), 100);
$paginator = $query->paginate($perPage); $paginator = $query->paginate($perPage);
// Pre-fetch ALL nodes for the current page in ONE query // Pre-fetch ALL nodes directly via DB facade for speed and reliability
$documentIds = collect($paginator->items())->pluck('id'); $documentIds = collect($paginator->items())->pluck('id');
$allNodes = BylawNode::whereIn('document_id', $documentIds)->orderBy('sort_order', 'asc')->get()->groupBy('document_id'); $allNodes = DB::table('bylaw_nodes')
->whereIn('document_id', $documentIds)
->orderBy('sort_order', 'asc')
->get()
->groupBy('document_id');
$items = collect($paginator->items())->map(function ($item) use ($allNodes) { $items = collect($paginator->items())->map(function ($item) use ($allNodes) {
return $this->formatBylaw($item, $allNodes->get($item->id, collect())); return $this->formatBylaw($item, $allNodes->get($item->id, collect()));
@@ -111,15 +116,17 @@ class BylawApiController extends Controller
], 404); ], 404);
} }
$nodes = BylawNode::with('type') // Fetch nodes using DB facade for the format function, but Eloquent for the nodes array
->where('document_id', $bylaw->id) $rawNodes = DB::table('bylaw_nodes')->where('document_id', $bylaw->id)->orderBy('sort_order', 'asc')->get();
->orderBy('sort_order', 'asc') $formatted = $this->formatBylaw($bylaw, $rawNodes);
->get();
$formatted = $this->formatBylaw($bylaw, $nodes);
if (!$formatted['is_locked']) { if (!$formatted['is_locked']) {
$formatted['nodes'] = $nodes->map(function ($node) { $eloquentNodes = BylawNode::with('type')
->where('document_id', $bylaw->id)
->orderBy('sort_order', 'asc')
->get();
$formatted['nodes'] = $eloquentNodes->map(function ($node) {
return [ return [
'id' => $node->id, 'id' => $node->id,
'parent_id' => $node->parent_id, 'parent_id' => $node->parent_id,
@@ -196,9 +203,12 @@ class BylawApiController extends Controller
$perPage = min(max((int) $request->input('per_page', 15), 10), 100); $perPage = min(max((int) $request->input('per_page', 15), 10), 100);
$paginator = $query->paginate($perPage); $paginator = $query->paginate($perPage);
// Pre-fetch ALL nodes for the current page in ONE query
$documentIds = collect($paginator->items())->pluck('id'); $documentIds = collect($paginator->items())->pluck('id');
$allNodes = BylawNode::whereIn('document_id', $documentIds)->orderBy('sort_order', 'asc')->get()->groupBy('document_id'); $allNodes = DB::table('bylaw_nodes')
->whereIn('document_id', $documentIds)
->orderBy('sort_order', 'asc')
->get()
->groupBy('document_id');
$items = collect($paginator->items())->map(function ($item) use ($allNodes) { $items = collect($paginator->items())->map(function ($item) use ($allNodes) {
return $this->formatBylaw($item, $allNodes->get($item->id, collect())); return $this->formatBylaw($item, $allNodes->get($item->id, collect()));
@@ -240,9 +250,12 @@ class BylawApiController extends Controller
$count = $query->count(); $count = $query->count();
$items = $query->orderBy('approval_date', 'desc')->take(5)->get(); $items = $query->orderBy('approval_date', 'desc')->take(5)->get();
// Pre-fetch ALL nodes for the current page in ONE query
$documentIds = $items->pluck('id'); $documentIds = $items->pluck('id');
$allNodes = BylawNode::whereIn('document_id', $documentIds)->orderBy('sort_order', 'asc')->get()->groupBy('document_id'); $allNodes = DB::table('bylaw_nodes')
->whereIn('document_id', $documentIds)
->orderBy('sort_order', 'asc')
->get()
->groupBy('document_id');
$formattedItems = $items->map(function ($item) use ($allNodes) { $formattedItems = $items->map(function ($item) use ($allNodes) {
return $this->formatBylaw($item, $allNodes->get($item->id, collect())); return $this->formatBylaw($item, $allNodes->get($item->id, collect()));
@@ -306,9 +319,12 @@ class BylawApiController extends Controller
$itemsToFormat = array_filter([$previousItem, $current, $nextItem]); $itemsToFormat = array_filter([$previousItem, $current, $nextItem]);
// Pre-fetch ALL nodes
$documentIds = collect($itemsToFormat)->pluck('id'); $documentIds = collect($itemsToFormat)->pluck('id');
$allNodes = BylawNode::whereIn('document_id', $documentIds)->orderBy('sort_order', 'asc')->get()->groupBy('document_id'); $allNodes = DB::table('bylaw_nodes')
->whereIn('document_id', $documentIds)
->orderBy('sort_order', 'asc')
->get()
->groupBy('document_id');
$results = array_values(array_map(function($item) use ($allNodes) { $results = array_values(array_map(function($item) use ($allNodes) {
return $this->formatBylaw($item, $allNodes->get($item->id, collect())); return $this->formatBylaw($item, $allNodes->get($item->id, collect()));
@@ -322,39 +338,33 @@ class BylawApiController extends Controller
return ! auth()->user()->isSubscriber() && (bool) ($item->is_locked ?? false); return ! auth()->user()->isSubscriber() && (bool) ($item->is_locked ?? false);
} }
/**
* BULLETPROOF DESCRIPTION GENERATOR
*/
private function formatBylaw($item, $preloadedNodes = null) private function formatBylaw($item, $preloadedNodes = null)
{ {
$isLocked = $this->isLockedForCurrentUser($item); $isLocked = $this->isLockedForCurrentUser($item);
$description = $item->description;
// AGGRESSIVE HTML CLEANER: Destroys hidden HTML tags,  , and whitespaces // 1. We ALWAYS try to build the description from the `node_content` FIRST.
$cleanDesc = trim(preg_replace('/\s+/', '', html_entity_decode(strip_tags($description ?? '')))); $nodes = $preloadedNodes !== null
? $preloadedNodes
: DB::table('bylaw_nodes')->where('document_id', $item->id)->orderBy('sort_order', 'asc')->get();
// If the description is genuinely empty, pull from the nodes! $nodeContents = [];
if ($cleanDesc === '' || strtolower($cleanDesc) === 'null') { foreach ($nodes as $node) {
// We specifically ask for the node_content column here
$nodes = $preloadedNodes !== null $content = trim(strip_tags($node->node_content ?? ''));
? $preloadedNodes if (!empty($content)) {
: BylawNode::where('document_id', $item->id)->orderBy('sort_order', 'asc')->get(); $nodeContents[] = $content;
$descParts = [];
foreach ($nodes as $node) {
// Grab all possible text fields
$identifier = trim(strip_tags($node->node_identifier ?? ''));
$title = trim(strip_tags($node->title ?? ''));
$content = trim(strip_tags($node->node_content ?? ''));
// Combine them neatly (e.g. "Article 1 - Definitions - This is the text...")
$combined = array_filter([$identifier, $title, $content], function($val) {
return $val !== '';
});
if (!empty($combined)) {
$descParts[] = implode(" : ", $combined);
}
} }
}
$description = implode("\n\n", $descParts); // Stitch them all together
$description = implode("\n\n", $nodeContents);
// 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;
} }
return [ return [