2626use Manufacturer ;
2727use PrestaShop \PrestaShop \Adapter \Presenter \Product \ProductLazyArray ;
2828use PrestaShop \PrestaShop \Adapter \Presenter \Product \ProductListingLazyArray ;
29- use Product ;
3029use Shop ;
3130
3231class ProductWrapper
3332{
3433 private $ context ;
34+ private $ categories = [];
35+ private $ homeCategory = 0 ;
3536
3637 public function __construct (Context $ context )
3738 {
@@ -55,6 +56,17 @@ public function prepareItemListFromProductList($productList, $useProvidedQuantit
5556 return [];
5657 }
5758
59+ // Preload categories for the whole list
60+ $ productIds = [];
61+ foreach ($ productList as $ product ) {
62+ if (!empty ($ product ['id_product ' ])) {
63+ $ productIds [] = $ product ['id_product ' ];
64+ } elseif (!empty ($ product ['id ' ])) {
65+ $ productIds [] = $ product ['id ' ];
66+ }
67+ }
68+ $ this ->loadCategories ($ productIds );
69+
5870 // Prepare each item and override the counter
5971 $ counter = 0 ;
6072 foreach ($ productList as $ product ) {
@@ -67,6 +79,42 @@ public function prepareItemListFromProductList($productList, $useProvidedQuantit
6779 return $ items ;
6880 }
6981
82+ /**
83+ * Loads all product categories for provided product IDs
84+ *
85+ * @param array $productIds
86+ */
87+ private function loadCategories ($ productIds ) {
88+ if (empty ($ productIds )) {
89+ return ;
90+ }
91+
92+ // Initialize home category
93+ $ this ->homeCategory = (int ) Configuration::get ('PS_HOME_CATEGORY ' );
94+
95+ // Initialize our cache
96+ $ this ->categories = [];
97+ foreach ($ productIds as $ id ) {
98+ $ this ->categories [(int ) $ id ] = [];
99+ }
100+
101+ // Load categories for all products
102+ $ result = Db::getInstance (_PS_USE_SQL_SLAVE_ )->executeS (
103+ '
104+ SELECT cp.`id_category`, cp.`id_product`, cl.`name` FROM ` ' . _DB_PREFIX_ . 'category_product` cp
105+ LEFT JOIN ` ' . _DB_PREFIX_ . 'category` c ON (c.id_category = cp.id_category)
106+ LEFT JOIN ` ' . _DB_PREFIX_ . 'category_lang` cl ON (cp.`id_category` = cl.`id_category` ' . Shop::addSqlRestrictionOnLang ('cl ' ) . ')
107+ ' . Shop::addSqlAssociation ('category ' , 'c ' ) . '
108+ WHERE cp.`id_product` IN ( ' . implode (', ' , $ productIds ) . ') AND cl.`id_lang` = ' . (int ) $ this ->context ->language ->id . '
109+ ORDER BY c.`level_depth` DESC '
110+ );
111+
112+ // Store it by product ID
113+ foreach ($ result as $ row ) {
114+ $ this ->categories [(int ) $ row ['id_product ' ]][] = $ row ;
115+ }
116+ }
117+
70118 /**
71119 * Takes provided (lazy) array and converts it to a format that GA4 requires. It can handle:
72120 * - ProductLazyArray from product page
@@ -137,25 +185,34 @@ public function prepareItemFromProduct($product, $useProvidedQuantity = false)
137185 $ item ['quantity ' ] = $ product ['quantity ' ];
138186 }
139187
140- // Prepare category information, put default category as the main one
141- $ productCategories1 = [];
142- $ productCategories2 = [];
143- foreach (Product::getProductCategoriesFull ((int ) $ product ['id ' ]) as $ productCategory ) {
144- if ($ productCategory ['id_category ' ] == $ product ['id_category_default ' ]) {
145- $ productCategories1 [] = $ productCategory ;
146- } else {
147- $ productCategories2 [] = $ productCategory ;
148- }
188+ // Prepare category information, if not loaded before, we will fetch it
189+ if (!isset ($ this ->categories [(int ) $ product_id ])) {
190+ $ this ->loadCategories ([(int ) $ product_id ]);
149191 }
150- $ productCategories = array_merge ($ productCategories1 , $ productCategories2 );
151192
152- // Limit categories to 5
153- $ productCategories = array_slice ($ productCategories , 0 , 5 , true );
193+ $ productCategories = $ this ->categories [(int ) $ product_id ];
194+
195+ // If the category is our default one, we will move it to the beginning of that list
196+ foreach ($ productCategories as $ key => $ category ) {
197+ if ($ category ['id_category ' ] == $ product ['id_category_default ' ]) {
198+ $ productCategories = [$ key => $ category ] + $ productCategories ;
199+ break ;
200+ }
201+ }
154202
155203 // Add it to our item
156204 $ counter = 1 ;
157205 foreach ($ productCategories as $ productCategory ) {
206+ // Skip home category if we have more than 1 category
207+ if (count ($ productCategories ) > 1 && $ productCategory ['id_category ' ] == $ this ->homeCategory ) {
208+ continue ;
209+ }
210+
211+ // Add it with proper key
158212 $ item [$ counter == 1 ? 'item_category ' : 'item_category ' . $ counter ] = $ productCategory ['name ' ];
213+ if ($ counter == 5 ) {
214+ break ;
215+ }
159216 ++$ counter ;
160217 }
161218
0 commit comments