33namespace App \Actions ;
44
55use App \DTO \PageDTO ;
6+ use App \Enums \LocaleEnum ;
67use App \Models \Network ;
78use App \Models \News ;
89use App \Models \OpenSource ;
910use App \Models \Page ;
1011use App \Models \Product ;
1112use App \Models \Service ;
1213use App \Models \Technology ;
14+ use Illuminate \Database \Eloquent \Model ;
1315use Illuminate \Support \Carbon ;
1416use Illuminate \Support \Collection ;
1517use Illuminate \Support \Str ;
1618
1719class PageAction
1820{
21+ private string $ locale ;
22+
1923 /**
2024 * @param Collection<int, PageDTO>|null $referencePages
2125 */
2226 public function __construct (
23- private ?string $ locale = null ,
27+ ?string $ locale = null ,
2428 private ?string $ routeName = null ,
2529 private mixed $ routeParameters = [],
2630 private ?Collection $ referencePages = null ,
@@ -37,12 +41,12 @@ public function default(): ?PageDTO
3741 }
3842
3943 return new PageDTO (
40- locale: $ page ->locale ,
44+ locale: $ this ->locale ,
4145 routeKey: $ page ->key ,
42- routeName: Str::slug ($ page ->locale ).'. ' .$ this ->routeName ,
43- title: $ page ->title ,
46+ routeName: Str::slug ($ this ->locale ).'. ' .$ this ->routeName ,
47+ title: $ this -> translatedString ( $ page ->getTranslation ( ' title ' , $ this -> locale )) ,
4448 robots: $ page ->robots ,
45- description: $ page ->description ,
49+ description: $ this -> translatedString ( $ page ->getTranslation ( ' description ' , $ this -> locale )) ,
4650 image: $ page ->image ,
4751 lastModificationDate: Carbon::parse ($ page ->updated_at ?? now ()),
4852 routeParameters: $ this ->routeParameters ,
@@ -52,27 +56,31 @@ public function default(): ?PageDTO
5256
5357 public function news (News $ news , bool $ withReferences = false , ?string $ locale = null ): PageDTO
5458 {
59+ $ locale ??= $ this ->locale ;
60+
5561 return new PageDTO (
56- locale: $ locale ?? $ news -> locale -> value ,
62+ locale: $ locale ,
5763 routeKey: 'news.show ' ,
58- routeName: Str::slug (title: $ locale ?? $ news -> locale -> value ).'.news.show ' ,
59- title: $ news ->title ,
60- description: $ news ->teaser ,
64+ routeName: Str::slug (title: $ locale ).'.news.show ' ,
65+ title: $ this -> translatedString ( $ news ->getTranslation ( ' title ' , $ locale )) ,
66+ description: $ this -> translatedString ( $ news ->getTranslation ( ' teaser ' , $ locale )) ,
6167 image: $ news ->image ,
6268 lastModificationDate: Carbon::parse ($ news ->updated_at ?? now ()),
63- routeParameters: ['locale ' => $ news -> locale , 'news ' => $ news ],
64- referencePages: $ withReferences ? $ this ->newsReferencePages ($ news ) : null ,
69+ routeParameters: ['locale ' => $ locale , 'news ' => $ news ],
70+ referencePages: $ withReferences ? $ this ->alternateLocalePages ($ news, $ locale , fn ( News $ n , string $ l ) => $ this -> news ( $ n , false , $ l ) ) : null ,
6571 );
6672 }
6773
6874 public function network (Network $ network , ?string $ locale = null ): PageDTO
6975 {
76+ $ locale ??= $ this ->locale ;
77+
7078 return new PageDTO (
71- locale: $ locale ?? $ network -> locale -> value ,
79+ locale: $ locale ,
7280 routeKey: 'network.show ' ,
73- routeName: Str::slug (title: $ locale ?? $ network -> locale -> value ).'.network.show ' ,
74- title: $ network ->name ,
75- description: $ network ->excerpt ,
81+ routeName: Str::slug (title: $ locale ).'.network.show ' ,
82+ title: $ this -> translatedString ( $ network ->getTranslation ( ' name ' , $ locale )) ,
83+ description: $ this -> nullableTranslatedString ( $ network ->getTranslation ( ' excerpt ' , $ locale )) ,
7684 image: $ network ->cover_url ,
7785 lastModificationDate: Carbon::parse ($ network ->updated_at ?? now ()),
7886 routeParameters: ['slug ' => $ network ->page_slug ],
@@ -82,168 +90,102 @@ public function network(Network $network, ?string $locale = null): PageDTO
8290
8391 public function product (Product $ product , bool $ withReferences = false , ?string $ locale = null ): PageDTO
8492 {
93+ $ locale ??= $ this ->locale ;
94+
8595 return new PageDTO (
86- locale: $ locale ?? $ product -> locale -> value ,
96+ locale: $ locale ,
8797 routeKey: 'products.show ' ,
88- routeName: Str::slug (title: $ locale ?? $ product -> locale -> value ).'.products.show ' ,
89- title: $ product ->name ,
90- description: $ product ->teaser ,
98+ routeName: Str::slug (title: $ locale ).'.products.show ' ,
99+ title: $ this -> translatedString ( $ product ->getTranslation ( ' name ' , $ locale )) ,
100+ description: $ this -> translatedString ( $ product ->getTranslation ( ' teaser ' , $ locale )) ,
91101 image: $ product ->image ,
92102 lastModificationDate: Carbon::parse ($ product ->updated_at ?? now ()),
93- routeParameters: ['locale ' => $ product -> locale , 'product ' => $ product ],
94- referencePages: $ withReferences ? $ this ->productReferencePages ($ product ) : null ,
103+ routeParameters: ['locale ' => $ locale , 'product ' => $ product ],
104+ referencePages: $ withReferences ? $ this ->alternateLocalePages ($ product, $ locale , fn ( Product $ p , string $ l ) => $ this -> product ( $ p , false , $ l ) ) : null ,
95105 );
96106 }
97107
98108 public function service (Service $ service , bool $ withReferences = false , ?string $ locale = null ): PageDTO
99109 {
110+ $ locale ??= $ this ->locale ;
111+
100112 return new PageDTO (
101- locale: $ locale ?? $ service -> locale -> value ,
113+ locale: $ locale ,
102114 routeKey: 'services.show ' ,
103- routeName: Str::slug (title: $ locale ?? $ service -> locale -> value ).'.services.show ' ,
104- title: $ service ->name ,
105- description: $ service ->teaser ,
115+ routeName: Str::slug (title: $ locale ).'.services.show ' ,
116+ title: $ this -> translatedString ( $ service ->getTranslation ( ' name ' , $ locale )) ,
117+ description: $ this -> translatedString ( $ service ->getTranslation ( ' teaser ' , $ locale )) ,
106118 image: $ service ->image ,
107119 lastModificationDate: Carbon::parse ($ service ->updated_at ?? now ()),
108- routeParameters: ['locale ' => $ service -> locale , 'service ' => $ service ],
109- referencePages: $ withReferences ? $ this ->serviceReferencePages ($ service ) : null ,
120+ routeParameters: ['locale ' => $ locale , 'service ' => $ service ],
121+ referencePages: $ withReferences ? $ this ->alternateLocalePages ($ service, $ locale , fn ( Service $ s , string $ l ) => $ this -> service ( $ s , false , $ l ) ) : null ,
110122 );
111123 }
112124
113125 public function technology (Technology $ technology , bool $ withReferences = false , ?string $ locale = null ): PageDTO
114126 {
127+ $ locale ??= $ this ->locale ;
128+
115129 return new PageDTO (
116- locale: $ locale ?? $ technology -> locale -> value ,
130+ locale: $ locale ,
117131 routeKey: 'technologies.show ' ,
118- routeName: Str::slug (title: $ locale ?? $ technology -> locale -> value ).'.technologies.show ' ,
119- title: $ technology ->title ,
120- description: $ technology ->teaser ,
132+ routeName: Str::slug (title: $ locale ).'.technologies.show ' ,
133+ title: $ this -> translatedString ( $ technology ->getTranslation ( ' title ' , $ locale )) ,
134+ description: $ this -> translatedString ( $ technology ->getTranslation ( ' teaser ' , $ locale )) ,
121135 image: $ technology ->image ,
122136 lastModificationDate: Carbon::parse ($ technology ->updated_at ?? now ()),
123- routeParameters: ['locale ' => $ technology -> locale , 'technology ' => $ technology ],
124- referencePages: $ withReferences ? $ this ->technologyReferencePages ($ technology ) : null ,
137+ routeParameters: ['locale ' => $ locale , 'technology ' => $ technology ],
138+ referencePages: $ withReferences ? $ this ->alternateLocalePages ($ technology, $ locale , fn ( Technology $ t , string $ l ) => $ this -> technology ( $ t , false , $ l ) ) : null ,
125139 );
126140 }
127141
128142 public function openSource (OpenSource $ openSource , bool $ withReferences = false , ?string $ locale = null ): PageDTO
129143 {
144+ $ locale ??= $ this ->locale ;
145+
130146 return new PageDTO (
131- locale: $ locale ?? $ openSource -> locale -> value ,
147+ locale: $ locale ,
132148 routeKey: 'open-source.show ' ,
133- routeName: Str::slug (title: $ locale ?? $ openSource -> locale -> value ).'.open-source.show ' ,
134- title: $ openSource ->title ,
135- description: $ openSource ->teaser ,
149+ routeName: Str::slug (title: $ locale ).'.open-source.show ' ,
150+ title: $ this -> translatedString ( $ openSource ->getTranslation ( ' title ' , $ locale )) ,
151+ description: $ this -> translatedString ( $ openSource ->getTranslation ( ' teaser ' , $ locale )) ,
136152 image: $ openSource ->image ,
137153 lastModificationDate: Carbon::parse ($ openSource ->updated_at ?? now ()),
138- routeParameters: ['locale ' => $ openSource -> locale , 'openSource ' => $ openSource ],
139- referencePages: $ withReferences ? $ this ->openSourceReferencePages ($ openSource ) : null ,
154+ routeParameters: ['locale ' => $ locale , 'openSource ' => $ openSource ],
155+ referencePages: $ withReferences ? $ this ->alternateLocalePages ($ openSource, $ locale , fn ( OpenSource $ o , string $ l ) => $ this -> openSource ( $ o , false , $ l ) ) : null ,
140156 );
141157 }
142158
143159 /**
160+ * The same model, rendered as a PageDTO for every other configured locale —
161+ * used to build hreflang alternate-language links.
162+ *
163+ * @template T of Model
164+ *
165+ * @param T $model
166+ * @param callable(T, string): PageDTO $builder
144167 * @return Collection<int, PageDTO>
145168 */
146- private function newsReferencePages (News $ news ): Collection
147- {
148- $ pages = [];
149-
150- foreach ($ news ->references as $ reference ) {
151- $ reference ->load (['target ' ]);
152-
153- if (! $ reference ->target instanceof News) {
154- continue ;
155- }
156-
157- $ pages [] = $ this ->news (news: $ reference ->target , withReferences: false , locale: $ reference ->reference_locale );
158- }
159-
160- return collect ($ pages );
161- }
162-
163- /**
164- * @return Collection<int, PageDTO>
165- */
166- private function productReferencePages (Product $ product ): Collection
167- {
168- $ pages = [];
169-
170- foreach ($ product ->references as $ reference ) {
171- $ reference ->load (['target ' ]);
172-
173- if (! $ reference ->target instanceof Product) {
174- continue ;
175- }
176-
177- $ pages [] = $ this ->product (product: $ reference ->target , withReferences: false , locale: $ reference ->reference_locale );
178- }
179-
180- return collect ($ pages );
181- }
182-
183- /**
184- * @return Collection<int, PageDTO>
185- */
186- private function serviceReferencePages (Service $ service ): Collection
169+ private function alternateLocalePages (Model $ model , string $ locale , callable $ builder ): Collection
187170 {
188- $ pages = [];
189-
190- foreach ($ service ->references as $ reference ) {
191- $ reference ->load (['target ' ]);
192-
193- if (! $ reference ->target instanceof Service) {
194- continue ;
195- }
196-
197- $ pages [] = $ this ->service (service: $ reference ->target , withReferences: false , locale: $ reference ->reference_locale );
198- }
199-
200- return collect ($ pages );
171+ return collect (LocaleEnum::cases ())
172+ ->reject (fn (LocaleEnum $ case ): bool => $ case ->value === $ locale )
173+ ->map (fn (LocaleEnum $ case ): PageDTO => $ builder ($ model , $ case ->value ))
174+ ->values ();
201175 }
202176
203- /**
204- * @return Collection<int, PageDTO>
205- */
206- private function technologyReferencePages (Technology $ technology ): Collection
177+ private function translatedString (mixed $ value ): string
207178 {
208- $ pages = [];
209-
210- foreach ($ technology ->references as $ reference ) {
211- $ reference ->load (['target ' ]);
212-
213- if (! $ reference ->target instanceof Technology) {
214- continue ;
215- }
216-
217- $ pages [] = $ this ->technology (technology: $ reference ->target , withReferences: false , locale: $ reference ->reference_locale );
218- }
219-
220- return collect ($ pages );
179+ return is_string ($ value ) ? $ value : '' ;
221180 }
222181
223- /**
224- * @return Collection<int, PageDTO>
225- */
226- private function openSourceReferencePages (OpenSource $ openSource ): Collection
182+ private function nullableTranslatedString (mixed $ value ): ?string
227183 {
228- $ pages = [];
229-
230- foreach ($ openSource ->references as $ reference ) {
231- $ reference ->load (['target ' ]);
232-
233- if (! $ reference ->target instanceof OpenSource) {
234- continue ;
235- }
236-
237- $ pages [] = $ this ->openSource (openSource: $ reference ->target , withReferences: false , locale: $ reference ->reference_locale );
238- }
239-
240- return collect ($ pages );
184+ return is_string ($ value ) ? $ value : null ;
241185 }
242186
243187 private function findPage (): ?Page
244188 {
245- return Page::where ('locale ' , $ this ->locale )
246- ->where ('key ' , $ this ->routeName )
247- ->first ();
189+ return Page::where ('key ' , $ this ->routeName )->first ();
248190 }
249191}
0 commit comments