sections(); if ($onlyVisible) { $query->where('visibility', true); } return $query->get(); } /** * Update an existing section. * Handles uploaded file storage and data merging. */ public function update(SectionPage $section, array $data): SectionPage { if (isset($data['data'])) { array_walk_recursive($data['data'], function (&$value) use ($section) { if ($value instanceof UploadedFile) { $value = FileStorageHelper::storeFile($section->page, $value); } }); } $section->update([ 'name' => $data['name'] ?? $section->name, 'visibility' => $data['visibility'] ?? $section->visibility, 'data' => $this->mergeData((array) json_decode(json_encode($section->data), true), $data['data'] ?? []), ]); return $section->fresh(); } /** * Merge original data with new data. * Performs a recursive merge for nested arrays. * * @param array $original Current section data * @param array $new New data to merge */ private function mergeData(array $original, array $new): array { foreach ($new as $key => $field) { if (isset($original[$key]) && is_array($original[$key]) && is_array($field)) { $original[$key] = $this->deepMerge($original[$key], $field); } else { $original[$key] = $field; } } return $original; } /** * Deep merge two arrays. * If a video is provided, clears the existing picture and vice versa. * * @param array $original Original array * @param array $new Array to merge into the original */ private function deepMerge(array $original, array $new): array { if (isset($new['video'])) { $original['picture'] = null; } elseif (isset($new['picture'])) { $original['video'] = null; } foreach ($new as $key => $field) { if (isset($original[$key]) && is_array($original[$key]) && is_array($field)) { $original[$key] = $this->deepMerge($original[$key], $field); } else { $original[$key] = $field; } } return $original; } /** * Toggle the visibility of a section. */ public function toggleVisibility(SectionPage $section): SectionPage { $section->update([ 'visibility' => ! $section->visibility, ]); return $section->fresh(); } }