PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.7.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.7.0
1.7.0 1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 All 50 releases
← All changes | app/Models/ProductVariation.php +71 -8 1.6.6 → 1.7.0 View file →
@@ -373,9 +373,15 @@
373 373 }
374 374 return false;
375 375 }
376 376
377 - public function isStock(): bool
377 + /**
378 + * @param array|null $bundleChildren Bundle child rows keyed by id, from
379 + * loadBundleChildren(), when the caller has several bundle variations
380 + * to ask about and wants one query for all their children instead of
381 + * one per variation. Null queries this variation's own children.
382 + */
383 + public function isStock($bundleChildren = null): bool
378 384 {
379 385 // Check if variation is active
380 386 if ($this->item_status !== 'active') {
381 387 return false;
@@ -387,9 +393,9 @@
387 393 // If stock management is disabled for this variation
388 394 if (!$this->manage_stock) {
389 395 // For bundle products, still check child items
390 396 if ($isBundleProduct) {
391 - return $this->isBundleChildrenInStock();
397 + return $this->isBundleChildrenInStock($bundleChildren);
392 398 }
393 399 // For regular products without stock management, check status
394 400 return $this->stock_status === Helper::IN_STOCK;
395 401 }
@@ -406,17 +412,53 @@
406 412 if (!$hasStock) {
407 413 return false;
408 414 }
409 415
410 - return $this->isBundleChildrenInStock();
416 + return $this->isBundleChildrenInStock($bundleChildren);
411 417 }
412 418
413 419 /**
420 + * The bundle children of several variations in one query, keyed by id,
421 + * for isStock($bundleChildren). Only the columns the stock check reads.
422 + *
423 + * @param iterable $variations
424 + * @return array<int, static>
425 + */
426 + public static function loadBundleChildren($variations): array
427 + {
428 + $childIds = [];
429 + foreach ($variations as $variation) {
430 + $ids = Arr::get($variation->other_info, 'bundle_child_ids', []);
431 + if (is_array($ids)) {
432 + foreach ($ids as $id) {
433 + $childIds[(int) $id] = true;
434 + }
435 + }
436 + }
437 + unset($childIds[0]);
438 +
439 + if (!$childIds) {
440 + return [];
441 + }
442 +
443 + $children = static::query()
444 + ->whereIn('id', array_keys($childIds))
445 + ->get(['id', 'manage_stock', 'available', 'stock_status', 'item_status', 'post_id', 'other_info']);
446 +
447 + $byId = [];
448 + foreach ($children as $child) {
449 + $byId[(int) $child->id] = $child;
450 + }
451 +
452 + return $byId;
453 + }
454 +
455 + /**
414 456 * Check if all bundle children are in stock
415 457 *
416 458 * @return bool
417 459 */
418 - protected function isBundleChildrenInStock(): bool
460 + protected function isBundleChildrenInStock($preloadedChildren = null): bool
419 461 {
420 462 $childIds = Arr::get($this->other_info, 'bundle_child_ids', []);
421 463
422 464 // No bundle children, consider as in stock
@@ -423,12 +465,33 @@
423 465 if (empty($childIds) || !is_array($childIds)) {
424 466 return true;
425 467 }
426 468
427 - // Get all bundle children variations
428 - $children = static::query()
429 - ->whereIn('id', $childIds)
430 - ->get(['id', 'manage_stock', 'available', 'stock_status', 'item_status', 'post_id', 'other_info']);
469 + $childIds = array_values(array_unique(array_map('intval', $childIds)));
470 +
471 + if (is_array($preloadedChildren)) {
472 + // From loadBundleChildren().
473 + $children = [];
474 + foreach ($childIds as $childId) {
475 + if (isset($preloadedChildren[$childId])) {
476 + $children[] = $preloadedChildren[$childId];
477 + }
478 + }
479 + } else {
480 + // Get all bundle children variations
481 + $children = static::query()
482 + ->whereIn('id', $childIds)
483 + ->get(['id', 'manage_stock', 'available', 'stock_status', 'item_status', 'post_id', 'other_info'])
484 + ->all();
485 + }
486 +
487 + // A child the bundle names but that no longer exists cannot be
488 + // supplied, so the bundle is not in stock. Same rule on both paths:
489 + // a row missing from the map and a row missing from the query are
490 + // the same deleted variation.
491 + if (count($children) !== count($childIds)) {
492 + return false;
493 + }
431 494
432 495 // Check each child
433 496 foreach ($children as $child) {
434 497 // Child must be active