5
5
*/
6
6
namespace Magento \Catalog \Model \ResourceModel \Category ;
7
7
8
+ use Magento \Catalog \Model \Category ;
9
+ use Magento \Catalog \Model \Product \Visibility ;
8
10
use Magento \CatalogUrlRewrite \Model \CategoryUrlRewriteGenerator ;
9
11
use Magento \Framework \App \Config \ScopeConfigInterface ;
12
+ use Magento \Framework \DB \Select ;
10
13
use Magento \Store \Model \ScopeInterface ;
11
14
12
15
/**
@@ -68,6 +71,11 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac
68
71
*/
69
72
private $ scopeConfig ;
70
73
74
+ /**
75
+ * @var Visibility
76
+ */
77
+ private $ catalogProductVisibility ;
78
+
71
79
/**
72
80
* Constructor
73
81
* @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
@@ -96,7 +104,8 @@ public function __construct(
96
104
\Magento \Framework \Validator \UniversalFactory $ universalFactory ,
97
105
\Magento \Store \Model \StoreManagerInterface $ storeManager ,
98
106
\Magento \Framework \DB \Adapter \AdapterInterface $ connection = null ,
99
- \Magento \Framework \App \Config \ScopeConfigInterface $ scopeConfig = null
107
+ \Magento \Framework \App \Config \ScopeConfigInterface $ scopeConfig = null ,
108
+ Visibility $ catalogProductVisibility = null
100
109
) {
101
110
parent ::__construct (
102
111
$ entityFactory ,
@@ -113,6 +122,8 @@ public function __construct(
113
122
);
114
123
$ this ->scopeConfig = $ scopeConfig ?:
115
124
\Magento \Framework \App \ObjectManager::getInstance ()->get (ScopeConfigInterface::class);
125
+ $ this ->catalogProductVisibility = $ catalogProductVisibility ?:
126
+ \Magento \Framework \App \ObjectManager::getInstance ()->get (Visibility::class);
116
127
}
117
128
118
129
/**
@@ -122,7 +133,7 @@ public function __construct(
122
133
*/
123
134
protected function _construct ()
124
135
{
125
- $ this ->_init (\ Magento \ Catalog \ Model \ Category::class, \Magento \Catalog \Model \ResourceModel \Category::class);
136
+ $ this ->_init (Category::class, \Magento \Catalog \Model \ResourceModel \Category::class);
126
137
}
127
138
128
139
/**
@@ -259,6 +270,7 @@ protected function _loadProductCount()
259
270
* @return $this
260
271
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
261
272
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
273
+ * @throws \Magento\Framework\Exception\NoSuchEntityException
262
274
*/
263
275
public function loadProductCount ($ items , $ countRegular = true , $ countAnchor = true )
264
276
{
@@ -310,34 +322,14 @@ public function loadProductCount($items, $countRegular = true, $countAnchor = tr
310
322
311
323
if ($ countAnchor ) {
312
324
// Retrieve Anchor categories product counts
325
+ $ categoryIds = array_keys ($ anchor );
326
+ $ countSelect = $ this ->getProductsCountQuery ($ categoryIds , (bool )$ websiteId );
327
+ $ categoryProductsCount = $ this ->_conn ->fetchPairs ($ countSelect );
313
328
foreach ($ anchor as $ item ) {
314
- if ($ allChildren = $ item ->getAllChildren ()) {
315
- $ bind = ['entity_id ' => $ item ->getId (), 'c_path ' => $ item ->getPath () . '/% ' ];
316
- $ select = $ this ->_conn ->select ();
317
- $ select ->from (
318
- ['main_table ' => $ this ->getProductTable ()],
319
- new \Zend_Db_Expr ('COUNT(DISTINCT main_table.product_id) ' )
320
- )->joinInner (
321
- ['e ' => $ this ->getTable ('catalog_category_entity ' )],
322
- 'main_table.category_id=e.entity_id ' ,
323
- []
324
- )->where (
325
- '(e.entity_id = :entity_id OR e.path LIKE :c_path) '
326
- );
327
- if ($ websiteId ) {
328
- $ select ->join (
329
- ['w ' => $ this ->getProductWebsiteTable ()],
330
- 'main_table.product_id = w.product_id ' ,
331
- []
332
- )->where (
333
- 'w.website_id = ? ' ,
334
- $ websiteId
335
- );
336
- }
337
- $ item ->setProductCount ((int )$ this ->_conn ->fetchOne ($ select , $ bind ));
338
- } else {
339
- $ item ->setProductCount (0 );
340
- }
329
+ $ productsCount = isset ($ categoriesProductsCount [$ item ->getId ()])
330
+ ? (int )$ categoryProductsCount [$ item ->getId ()]
331
+ : $ this ->getProductsCountFromCategoryTable ($ item , $ websiteId );
332
+ $ item ->setProductCount ($ productsCount );
341
333
}
342
334
}
343
335
return $ this ;
@@ -513,4 +505,66 @@ public function getProductTable()
513
505
}
514
506
return $ this ->_productTable ;
515
507
}
508
+
509
+ /**
510
+ * @param Category $item
511
+ * @param string $websiteId
512
+ * @return int
513
+ */
514
+ private function getProductsCountFromCategoryTable (Category $ item , string $ websiteId ): int
515
+ {
516
+ $ productCount = 0 ;
517
+
518
+ if ($ item ->getAllChildren ()) {
519
+ $ bind = ['entity_id ' => $ item ->getId (), 'c_path ' => $ item ->getPath () . '/% ' ];
520
+ $ select = $ this ->_conn ->select ();
521
+ $ select ->from (
522
+ ['main_table ' => $ this ->getProductTable ()],
523
+ new \Zend_Db_Expr ('COUNT(DISTINCT main_table.product_id) ' )
524
+ )->joinInner (
525
+ ['e ' => $ this ->getTable ('catalog_category_entity ' )],
526
+ 'main_table.category_id=e.entity_id ' ,
527
+ []
528
+ )->where (
529
+ '(e.entity_id = :entity_id OR e.path LIKE :c_path) '
530
+ );
531
+ if ($ websiteId ) {
532
+ $ select ->join (
533
+ ['w ' => $ this ->getProductWebsiteTable ()],
534
+ 'main_table.product_id = w.product_id ' ,
535
+ []
536
+ )->where (
537
+ 'w.website_id = ? ' ,
538
+ $ websiteId
539
+ );
540
+ }
541
+ $ productCount = (int )$ this ->_conn ->fetchOne ($ select , $ bind );
542
+ }
543
+ return $ productCount ;
544
+ }
545
+
546
+ /**
547
+ * Get query for retrieve count of products per category
548
+ *
549
+ * @param array $categoryIds
550
+ * @return Select
551
+ */
552
+ private function getProductsCountQuery (array $ categoryIds , $ addVisibilityFilter = true ): Select
553
+ {
554
+ $ categoryTable = $ this ->getTable ('catalog_category_product_index ' );
555
+ $ select = $ this ->_conn ->select ()
556
+ ->from (
557
+ ['cat_index ' => $ categoryTable ],
558
+ ['category_id ' => 'cat_index.category_id ' , 'count ' => 'count(cat_index.product_id) ' ]
559
+ )
560
+ ->where ('cat_index.category_id in (?) ' , \array_map ('\intval ' , $ categoryIds ));
561
+ if (true === $ addVisibilityFilter ) {
562
+ $ select ->where ('cat_index.visibility in (?) ' , $ this ->catalogProductVisibility ->getVisibleInSiteIds ());
563
+ }
564
+ if (count ($ categoryIds ) > 1 ) {
565
+ $ select ->group ('cat_index.category_id ' );
566
+ }
567
+
568
+ return $ select ;
569
+ }
516
570
}
0 commit comments