|
@@ -24,7 +24,6 @@ class FilterableAttributesProvider implements ProviderInterface
|
|
|
$info = $context['info'] ?? null;
|
|
$info = $context['info'] ?? null;
|
|
|
|
|
|
|
|
$categorySlug = $args['categorySlug'] ?? null;
|
|
$categorySlug = $args['categorySlug'] ?? null;
|
|
|
- $categoryId = isset($args['categoryId']) ? (int) $args['categoryId'] : null;
|
|
|
|
|
|
|
|
|
|
$first = isset($args['first']) ? (int) $args['first'] : null;
|
|
$first = isset($args['first']) ? (int) $args['first'] : null;
|
|
|
$last = isset($args['last']) ? (int) $args['last'] : null;
|
|
$last = isset($args['last']) ? (int) $args['last'] : null;
|
|
@@ -50,13 +49,9 @@ class FilterableAttributesProvider implements ProviderInterface
|
|
|
|
|
|
|
|
$query->select('attributes.*');
|
|
$query->select('attributes.*');
|
|
|
|
|
|
|
|
- if (! $categoryId && $categorySlug) {
|
|
|
|
|
- $categoryId = DB::table('category_translations')
|
|
|
|
|
- ->where('slug', $categorySlug)
|
|
|
|
|
- ->select('category_id')
|
|
|
|
|
- ->pluck('category_id')
|
|
|
|
|
- ->first();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $categoryId = $categorySlug
|
|
|
|
|
+ ? DB::table('category_translations')->where('slug', $categorySlug)->select('category_id')->pluck('category_id')->first()
|
|
|
|
|
+ : null;
|
|
|
|
|
|
|
|
if ($categoryId) {
|
|
if ($categoryId) {
|
|
|
$query
|
|
$query
|
|
@@ -97,12 +92,10 @@ class FilterableAttributesProvider implements ProviderInterface
|
|
|
->limit($perPage)
|
|
->limit($perPage)
|
|
|
->get();
|
|
->get();
|
|
|
|
|
|
|
|
- $items = $items->map(function ($item) use ($maxPrice, $categoryId) {
|
|
|
|
|
|
|
+ $items = $items->map(function ($item) use ($maxPrice) {
|
|
|
$item->maxPrice = (float) $maxPrice;
|
|
$item->maxPrice = (float) $maxPrice;
|
|
|
$item->minPrice = 0.0;
|
|
$item->minPrice = 0.0;
|
|
|
|
|
|
|
|
- $this->attachProductCounts($item, $categoryId);
|
|
|
|
|
-
|
|
|
|
|
return $item;
|
|
return $item;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -118,88 +111,4 @@ class FilterableAttributesProvider implements ProviderInterface
|
|
|
)
|
|
)
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Attach the number of visible products associated with each option of
|
|
|
|
|
- * the given attribute within the requested category context.
|
|
|
|
|
- *
|
|
|
|
|
- * Visibility mirrors ProductGraphQLProvider: a product is counted only when
|
|
|
|
|
- * it has status=1 (attribute id 8) and visible_individually=1 (attribute id 7).
|
|
|
|
|
- */
|
|
|
|
|
- private function attachProductCounts($item, ?int $categoryId): void
|
|
|
|
|
- {
|
|
|
|
|
- $options = $item->options ?? $item->options()->get();
|
|
|
|
|
-
|
|
|
|
|
- if ($options->isEmpty()) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- $attributeId = $item->id;
|
|
|
|
|
- $column = $item->type === 'select' ? 'integer_value' : 'text_value';
|
|
|
|
|
-
|
|
|
|
|
- $countQuery = DB::table('product_attribute_values as pav')
|
|
|
|
|
- ->join('product_attribute_values as pav_status', function ($join) {
|
|
|
|
|
- $join->on('pav_status.product_id', '=', 'pav.product_id')
|
|
|
|
|
- ->where('pav_status.attribute_id', 8)
|
|
|
|
|
- ->where('pav_status.boolean_value', 1);
|
|
|
|
|
- })
|
|
|
|
|
- ->join('product_attribute_values as pav_visible', function ($join) {
|
|
|
|
|
- $join->on('pav_visible.product_id', '=', 'pav.product_id')
|
|
|
|
|
- ->where('pav_visible.attribute_id', 7)
|
|
|
|
|
- ->where('pav_visible.boolean_value', 1);
|
|
|
|
|
- })
|
|
|
|
|
- ->where('pav.attribute_id', $attributeId);
|
|
|
|
|
-
|
|
|
|
|
- if ($categoryId) {
|
|
|
|
|
- $countQuery->whereIn('pav.product_id', function ($sub) use ($categoryId) {
|
|
|
|
|
- $sub->select('product_id')
|
|
|
|
|
- ->from('product_categories')
|
|
|
|
|
- ->where('category_id', $categoryId);
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- $optionIds = $options->pluck('id')->map(fn ($id) => (string) $id)->all();
|
|
|
|
|
-
|
|
|
|
|
- if ($column === 'integer_value') {
|
|
|
|
|
- $counts = (clone $countQuery)
|
|
|
|
|
- ->whereIn('pav.integer_value', $optionIds)
|
|
|
|
|
- ->selectRaw('pav.integer_value as option_id, COUNT(DISTINCT pav.product_id) as total')
|
|
|
|
|
- ->groupBy('pav.integer_value')
|
|
|
|
|
- ->pluck('total', 'option_id')
|
|
|
|
|
- ->toArray();
|
|
|
|
|
- } else {
|
|
|
|
|
- $counts = $this->countMultiSelectOptions(clone $countQuery, $optionIds);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- foreach ($options as $option) {
|
|
|
|
|
- $option->product_count = (int) ($counts[(string) $option->id] ?? 0);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Count products for multiselect/checkbox options whose values are stored
|
|
|
|
|
- * as comma-separated option ids in the text_value column.
|
|
|
|
|
- */
|
|
|
|
|
- private function countMultiSelectOptions($query, array $optionIds): array
|
|
|
|
|
- {
|
|
|
|
|
- $rows = $query
|
|
|
|
|
- ->whereNotNull('pav.text_value')
|
|
|
|
|
- ->selectRaw('pav.text_value, COUNT(DISTINCT pav.product_id) as total')
|
|
|
|
|
- ->groupBy('pav.text_value')
|
|
|
|
|
- ->get();
|
|
|
|
|
-
|
|
|
|
|
- $counts = [];
|
|
|
|
|
-
|
|
|
|
|
- foreach ($rows as $row) {
|
|
|
|
|
- $values = array_filter(array_map('trim', explode(',', (string) $row->text_value)));
|
|
|
|
|
-
|
|
|
|
|
- foreach ($values as $value) {
|
|
|
|
|
- if (in_array($value, $optionIds, true)) {
|
|
|
|
|
- $counts[$value] = ($counts[$value] ?? 0) + (int) $row->total;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return $counts;
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|