Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
StockIndex.php
Go to the documentation of this file.
1 <?php
8 
11 use Magento\Catalog\Model\ProductFactory;
16 
22 {
27 
31  protected $productRepository;
32 
37 
41  protected $productType;
42 
48  protected $websites;
49 
55  protected $productTypes = [];
56 
63  public function __construct(
66  ProductWebsite $productWebsite,
68  ) {
69  $this->stockRegistryProvider = $stockRegistryProvider;
70  $this->productRepository = $productRepository;
71  $this->productWebsite = $productWebsite;
72  $this->productType = $productType;
73  }
74 
84  public function rebuild($productId = null, $scopeId = null)
85  {
86  if ($productId !== null) {
87  $this->updateProductStockStatus($productId, $scopeId);
88  } else {
89  $lastProductId = 0;
90  while (true) {
93  $productCollection = $resource->getProductCollection($lastProductId);
94  if (!$productCollection) {
95  break;
96  }
99  $this->updateProductStockStatus($productId, $scopeId);
100  }
101  }
102  }
103  return true;
104  }
105 
115  {
116  $item = $this->stockRegistryProvider->getStockItem($productId, $websiteId);
117 
118  $status = \Magento\CatalogInventory\Model\Stock\Status::STATUS_IN_STOCK;
119  $qty = 0;
120  if ($item->getItemId()) {
121  $status = $item->getIsInStock();
122  $qty = $item->getQty();
123  }
124  $this->processChildren($productId, $item->getWebsiteId(), $qty, $status);
125  $this->processParents($productId, $item->getWebsiteId());
126  }
127 
138  protected function processChildren(
139  $productId,
140  $websiteId,
141  $qty = 0,
142  $status = \Magento\CatalogInventory\Model\Stock\Status::STATUS_IN_STOCK
143  ) {
144  if ($status == \Magento\CatalogInventory\Model\Stock\Status::STATUS_OUT_OF_STOCK) {
145  $this->getStockStatusResource()->saveProductStatus($productId, $status, $qty, $websiteId);
146  return;
147  }
148 
149  $statuses = [];
150  $websitesWithStores = $this->getWebsitesWithDefaultStores($websiteId);
151 
152  foreach (array_keys($websitesWithStores) as $websiteId) {
153  /* @var $website \Magento\Store\Model\Website */
154  $statuses[$websiteId] = $status;
155  }
156 
158  $product = $this->productRepository->getById($productId);
159  $typeInstance = $product->getTypeInstance();
160 
161  $requiredChildrenIds = $typeInstance->getChildrenIds($productId, true);
162  if ($requiredChildrenIds) {
163  $childrenIds = [];
164  foreach ($requiredChildrenIds as $groupedChildrenIds) {
165  $childrenIds = array_merge($childrenIds, $groupedChildrenIds);
166  }
167  $childrenWebsites = $this->productWebsite->getWebsites($childrenIds);
168  foreach ($websitesWithStores as $websiteId => $storeId) {
169  $childrenStatus = $this->getStockStatusResource()->getProductStatus($childrenIds, $storeId);
170  $childrenStock = $this->getStockStatusResource()->getProductsStockStatuses($childrenIds, $websiteId);
171  $websiteStatus = $statuses[$websiteId];
172  foreach ($requiredChildrenIds as $groupedChildrenIds) {
173  $optionStatus = false;
174  foreach ($groupedChildrenIds as $childId) {
175  if (isset($childrenStatus[$childId])
176  && isset($childrenWebsites[$childId])
177  && in_array($websiteId, $childrenWebsites[$childId])
178  && $childrenStatus[$childId] == Status::STATUS_ENABLED
179  && isset($childrenStock[$childId])
180  && $childrenStock[$childId] == \Magento\CatalogInventory\Model\Stock\Status::STATUS_IN_STOCK
181  ) {
182  $optionStatus = true;
183  }
184  }
185  $websiteStatus = $websiteStatus && $optionStatus;
186  }
187  $statuses[$websiteId] = (int)$websiteStatus;
188  }
189  }
190  foreach ($statuses as $websiteId => $websiteStatus) {
191  $this->getStockStatusResource()->saveProductStatus($productId, $websiteStatus, $qty, $websiteId);
192  }
193  }
194 
201  protected function getWebsitesWithDefaultStores($websiteId = null)
202  {
203  if ($this->websites === null) {
206  $this->websites = $resource->getWebsiteStores();
207  }
209  if ($websiteId !== null && isset($this->websites[$websiteId])) {
210  $websites = [$websiteId => $this->websites[$websiteId]];
211  }
212  return $websites;
213  }
214 
222  protected function processParents($productId, $websiteId)
223  {
224  $parentIds = [];
225  foreach ($this->getProductTypeInstances() as $typeInstance) {
226  /* @var $typeInstance AbstractType */
227  $parentIds = array_merge($parentIds, $typeInstance->getParentIdsByChild($productId));
228  }
229 
230  if (!$parentIds) {
231  return $this;
232  }
233 
234  foreach ($parentIds as $parentId) {
235  $item = $this->stockRegistryProvider->getStockItem($parentId, $websiteId);
236  $status = \Magento\CatalogInventory\Model\Stock\Status::STATUS_IN_STOCK;
237  $qty = 0;
238  if ($item->getItemId()) {
239  $status = $item->getIsInStock();
240  $qty = $item->getQty();
241  }
242  $this->processChildren($parentId, $websiteId, $qty, $status);
243  }
244  }
245 
252  protected function getProductTypeInstances()
253  {
254  if (empty($this->productTypes)) {
255  $productEmulator = new \Magento\Framework\DataObject();
256  foreach (array_keys($this->productType->getTypes()) as $typeId) {
257  $productEmulator->setTypeId($typeId);
258  $this->productTypes[$typeId] = $this->productType->factory($productEmulator);
259  }
260  }
261  return $this->productTypes;
262  }
263 
267  protected function getStockStatusResource()
268  {
269  if (empty($this->stockStatusResource)) {
270  $this->stockStatusResource = \Magento\Framework\App\ObjectManager::getInstance()->get(
271  \Magento\CatalogInventory\Model\ResourceModel\Stock\Status::class
272  );
273  }
275  }
276 }
__construct(StockRegistryProviderInterface $stockRegistryProvider, ProductRepositoryInterface $productRepository, ProductWebsite $productWebsite, ProductType $productType)
Definition: StockIndex.php:63
$resource
Definition: bulk.php:12
updateProductStockStatus($productId, $websiteId)
Definition: StockIndex.php:114
rebuild($productId=null, $scopeId=null)
$status
Definition: order_status.php:8
$lastProductId
processParents($productId, $websiteId)
Definition: StockIndex.php:222