77use GraphQL \Executor \Promise \Promise ;
88use GraphQL \Executor \Promise \PromiseAdapter ;
99use Shopsys \FrameworkBundle \Component \Domain \Domain ;
10- use Shopsys \FrameworkBundle \Component \Router \FriendlyUrl \FriendlyUrlFacade ;
10+ use Shopsys \FrameworkBundle \Component \Router \FriendlyUrl \Exception \FriendlyUrlNotFoundException ;
11+ use Shopsys \FrameworkBundle \Component \Router \FriendlyUrl \FriendlyUrlCacheKeyProvider ;
12+ use Shopsys \FrameworkBundle \Component \Router \FriendlyUrl \FriendlyUrlRepository ;
1113use Shopsys \FrameworkBundle \Model \CategorySeo \ReadyCategorySeoMix ;
1214use Shopsys \FrameworkBundle \Model \CategorySeo \ReadyCategorySeoMixFacade ;
1315use Shopsys \FrameworkBundle \Model \Customer \User \Role \CustomerUserRoleResolver ;
16+ use Symfony \Contracts \Cache \CacheInterface ;
1417
1518class ReadyCategorySeoMixBatchLoader
1619{
20+ protected const string ROUTE_NAME = 'front_category_seo ' ;
21+
1722 public function __construct (
1823 protected readonly PromiseAdapter $ promiseAdapter ,
1924 protected readonly ReadyCategorySeoMixFacade $ readyCategorySeoMixFacade ,
2025 protected readonly Domain $ domain ,
21- protected readonly FriendlyUrlFacade $ friendlyUrlFacade ,
26+ protected readonly FriendlyUrlRepository $ friendlyUrlRepository ,
2227 protected readonly CustomerUserRoleResolver $ customerUserRoleResolver ,
28+ protected readonly CacheInterface $ mainFriendlyUrlSlugCache ,
29+ protected readonly FriendlyUrlCacheKeyProvider $ friendlyUrlCacheKeyProvider ,
2330 ) {
2431 }
2532
@@ -32,26 +39,87 @@ public function loadByCategoryIds(array $categoryIds): Promise
3239
3340 $ canSeePrices = $ this ->customerUserRoleResolver ->canCurrentCustomerUserSeePrices ();
3441
42+ $ allSeoMixIds = [];
43+
44+ foreach ($ allReadyCategorySeoMixes as $ readyCategorySeoMixes ) {
45+ foreach ($ readyCategorySeoMixes as $ readyCategorySeoMix ) {
46+ $ allSeoMixIds [] = $ readyCategorySeoMix ->getId ();
47+ }
48+ }
49+
50+ $ slugsByEntityId = $ this ->loadSlugsWithCache ($ allSeoMixIds );
51+
3552 $ result = [];
3653
3754 foreach ($ allReadyCategorySeoMixes as $ readyCategorySeoMixes ) {
3855 $ filteredMixes = $ canSeePrices
3956 ? $ readyCategorySeoMixes
40- : array_filter ($ readyCategorySeoMixes , fn (ReadyCategorySeoMix $ mix ) => !$ mix ->hasPriceBasedOrdering ());
57+ : array_filter ($ readyCategorySeoMixes , fn (ReadyCategorySeoMix $ readyCategorySeoMix ) => !$ readyCategorySeoMix ->hasPriceBasedOrdering ());
4158
4259 $ result [] = array_map (
43- fn (ReadyCategorySeoMix $ readyCategorySeoMix ) => [
44- 'name ' => $ readyCategorySeoMix ->getH1 (),
45- 'slug ' => '/ ' . $ this ->friendlyUrlFacade ->getMainFriendlyUrlSlug (
46- $ this ->domain ->getId (),
47- 'front_category_seo ' ,
48- $ readyCategorySeoMix ->getId (),
49- ),
50- ],
60+ function (ReadyCategorySeoMix $ readyCategorySeoMix ) use ($ slugsByEntityId ) {
61+ if (!isset ($ slugsByEntityId [$ readyCategorySeoMix ->getId ()])) {
62+ throw new FriendlyUrlNotFoundException (
63+ sprintf ('Main friendly URL not found for route "front_category_seo", domain ID "%d", and entity ID "%d". ' , $ this ->domain ->getId (), $ readyCategorySeoMix ->getId ()),
64+ );
65+ }
66+
67+ return [
68+ 'name ' => $ readyCategorySeoMix ->getH1 (),
69+ 'slug ' => '/ ' . $ slugsByEntityId [$ readyCategorySeoMix ->getId ()],
70+ ];
71+ },
5172 $ filteredMixes ,
5273 );
5374 }
5475
5576 return $ this ->promiseAdapter ->all ($ result );
5677 }
78+
79+ /**
80+ * @param int[] $entityIds
81+ * @return array<int, string>
82+ */
83+ protected function loadSlugsWithCache (array $ entityIds ): array
84+ {
85+ $ domainId = $ this ->domain ->getId ();
86+ $ slugsByEntityId = [];
87+ $ missingEntityIds = [];
88+
89+ foreach ($ entityIds as $ entityId ) {
90+ $ cacheKey = $ this ->friendlyUrlCacheKeyProvider ->getMainFriendlyUrlSlugCacheKey (static ::ROUTE_NAME , $ domainId , $ entityId );
91+ $ cachedSlug = $ this ->mainFriendlyUrlSlugCache ->get ($ cacheKey , fn () => null );
92+
93+ if ($ cachedSlug !== null ) {
94+ $ slugsByEntityId [$ entityId ] = $ cachedSlug ;
95+ } else {
96+ $ missingEntityIds [] = $ entityId ;
97+ }
98+ }
99+
100+ if ($ missingEntityIds !== []) {
101+ $ friendlyUrls = $ this ->friendlyUrlRepository ->getMainFriendlyUrlsByEntitiesIndexedByEntityId (
102+ $ missingEntityIds ,
103+ static ::ROUTE_NAME ,
104+ $ domainId ,
105+ );
106+
107+ foreach ($ missingEntityIds as $ entityId ) {
108+ if (!isset ($ friendlyUrls [$ entityId ])) {
109+ throw new FriendlyUrlNotFoundException (
110+ sprintf ('Main friendly URL not found for route "%s", domain ID "%d", and entity ID "%d". ' , static ::ROUTE_NAME , $ domainId , $ entityId ),
111+ );
112+ }
113+
114+ $ slug = $ friendlyUrls [$ entityId ]->getSlug ();
115+ $ slugsByEntityId [$ entityId ] = $ slug ;
116+
117+ $ cacheKey = $ this ->friendlyUrlCacheKeyProvider ->getMainFriendlyUrlSlugCacheKey (static ::ROUTE_NAME , $ domainId , $ entityId );
118+ $ this ->mainFriendlyUrlSlugCache ->delete ($ cacheKey );
119+ $ this ->mainFriendlyUrlSlugCache ->get ($ cacheKey , fn () => $ slug );
120+ }
121+ }
122+
123+ return $ slugsByEntityId ;
124+ }
57125}
0 commit comments