1010use Filament \Notifications \Notification ;
1111use Filament \Pages \Page ;
1212use Illuminate \Contracts \Support \Htmlable ;
13+ use Illuminate \Database \Eloquent \Model ;
1314use SolutionForest \InspireCms \Facades \PermissionManifest ;
15+ use SolutionForest \InspireCms \Factories \ContentSegmentFactory ;
1416use SolutionForest \InspireCms \Factories \SitemapGeneratorFactory ;
1517use SolutionForest \InspireCms \Filament \Clusters \Settings ;
1618use SolutionForest \InspireCms \Filament \Concerns \ClusterSectionPageTrait ;
1921use SolutionForest \InspireCms \Helpers \AuthHelper ;
2022use SolutionForest \InspireCms \Helpers \PermissionHelper ;
2123use SolutionForest \InspireCms \InspireCmsConfig ;
24+ use SolutionForest \InspireCms \Models \Contracts \Content ;
25+ use SolutionForest \InspireCms \Support \Helpers \KeyHelper ;
26+ use SolutionForest \InspireCms \Support \Models \Contracts \NestableTree ;
2227
2328// todo: need redo the layout
2429class Health extends Page implements ClusterSectionPage, GuardPage, HasActions, HasForms
@@ -65,6 +70,7 @@ public function getStatusInfo(): array
6570 {
6671 $ permissions = $ this ->getPermissionsStatusData ();
6772 $ sitemap = $ this ->getSiteMapStatusData ();
73+ $ contentHierarchy = $ this ->getContentHierarchyStatusData ();
6874
6975 return [
7076 'permissions ' => [
@@ -77,6 +83,12 @@ public function getStatusInfo(): array
7783 ...$ sitemap ,
7884 'action ' => 'fix ' ,
7985 ],
86+ 'content_hierarchy ' => [
87+ // 'title' => __('inspirecms::pages/health.content_hierarchy.label'),
88+ 'title ' => 'Content Hierarchy ' ,
89+ ...$ contentHierarchy ,
90+ 'action ' => 'fix ' ,
91+ ],
8092 ];
8193 }
8294
@@ -101,6 +113,10 @@ public function fixAction(): Action
101113
102114 break ;
103115
116+ case 'content_hierarchy ' :
117+ $ needRefresh = $ this ->fixContentHierarchy ();
118+ break ;
119+
104120 }
105121
106122 if ($ needRefresh ) {
@@ -145,6 +161,55 @@ protected function getSiteMapStatusData(): array
145161 ];
146162 }
147163
164+ protected function getContentHierarchyStatusData (): array
165+ {
166+ $ records = InspireCmsConfig::getNestableTreeModelClass ()::scoped ([
167+ 'nestable_type ' => app (InspireCmsConfig::getContentModelClass ())->getMorphClass (),
168+ ])->with ([
169+ 'nestable.path ' ,
170+ 'nestable.ancestorsAndSelf ' ,
171+ ])->get ();
172+
173+ $ segmentProvider = ContentSegmentFactory::create ();
174+
175+ $ data = $ records
176+ ->reject (fn (NestableTree | Model $ record ) => is_null ($ record ->nestable ))
177+ ->map (fn (NestableTree | Model $ record ) => [
178+ 'id ' => $ record ->nestable ->getKey (),
179+ 'slug ' => $ record ->nestable ->slug ,
180+ 'parent_id_from_tree ' => $ record ->parent ?->nestable_id ?? KeyHelper::generateMinUuid (),
181+ 'parent_id_from_content ' => $ record ->nestable ->getParentId (),
182+ 'current_path ' => $ record ->nestable ->path ?->value,
183+ 'expected_path ' => $ segmentProvider ->getPath ($ record ->nestable ),
184+ ])
185+ ->keyBy ('id ' )
186+ ->all ();
187+
188+ $ valids = collect ($ data )->filter (function ($ item ) {
189+ return $ item ['current_path ' ] === $ item ['expected_path ' ] &&
190+ $ item ['parent_id_from_tree ' ] === $ item ['parent_id_from_content ' ];
191+ })->all ();
192+
193+ $ invalids = collect ($ data )
194+ ->where (fn ($ item , $ key ) => array_key_exists ($ key , $ valids ) === false )
195+ ->all ();
196+
197+ return [
198+ 'status ' => $ this ->formateStatusData (count ($ data ), count ($ invalids ), count ($ valids )),
199+ 'data ' => $ this ->formateStatusContent (collect ($ invalids )
200+ ->mapWithKeys (function ($ item ) {
201+ return [
202+ 'Content ID: ' . $ item ['id ' ] => [
203+ 'Current path: ' . $ item ['current_path ' ],
204+ 'Expected path: ' . $ item ['expected_path ' ],
205+ ],
206+ ];
207+ })
208+ ->all ()
209+ ),
210+ ];
211+ }
212+
148213 protected function fixPermissions (): bool
149214 {
150215 $ missing = $ this ->getMissingPermissions ($ this ->getAllPermissions ());
@@ -178,6 +243,24 @@ protected function fixSiteMap(): bool
178243 return true ;
179244 }
180245
246+ protected function fixContentHierarchy (): bool
247+ {
248+ $ records = InspireCmsConfig::getContentModelClass ()::with (['path ' , 'ancestorsAndSelf ' ])->get ();
249+ $ segmentProvider = ContentSegmentFactory::create ();
250+
251+ $ records ->each (function (Content | Model $ record ) use ($ segmentProvider ) {
252+ $ expectedPath = $ segmentProvider ->getPath ($ record );
253+
254+ if ($ record ->path ?->value !== $ expectedPath ) {
255+ $ record ->path ?->update([
256+ 'value ' => $ expectedPath ,
257+ ]);
258+ }
259+ });
260+
261+ return true ;
262+ }
263+
181264 protected function formateStatusData ($ total , $ invalid , $ valid ): array
182265 {
183266 return [
0 commit comments