From 683ef6329ac93dcd62024a41f2c5db6d3f47ebd6 Mon Sep 17 00:00:00 2001 From: Devansh Date: Wed, 1 Dec 2021 12:42:18 +0530 Subject: [PATCH] Filtering Issue Fixed --- .../src/Repositories/ProductRepository.php | 262 +++++++++--------- 1 file changed, 138 insertions(+), 124 deletions(-) diff --git a/packages/Webkul/Product/src/Repositories/ProductRepository.php b/packages/Webkul/Product/src/Repositories/ProductRepository.php index d64fd490b..1c7664bd7 100755 --- a/packages/Webkul/Product/src/Repositories/ProductRepository.php +++ b/packages/Webkul/Product/src/Repositories/ProductRepository.php @@ -3,26 +3,26 @@ namespace Webkul\Product\Repositories; use Exception; -use Illuminate\Support\Str; -use Illuminate\Support\Facades\DB; -use Webkul\Checkout\Facades\Cart; -use Webkul\Product\Models\Product; -use Illuminate\Pagination\Paginator; -use Webkul\Core\Eloquent\Repository; -use Illuminate\Support\Facades\Event; -use Webkul\Attribute\Models\Attribute; -use Webkul\Product\Models\ProductFlat; -use Illuminate\Support\Facades\Storage; use Illuminate\Container\Container as App; -use Illuminate\Pagination\LengthAwarePaginator; -use Webkul\Product\Models\ProductAttributeValueProxy; -use Webkul\Attribute\Repositories\AttributeRepository; use Illuminate\Database\Eloquent\ModelNotFoundException; +use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Pagination\Paginator; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Str; +use Webkul\Attribute\Models\Attribute; +use Webkul\Attribute\Repositories\AttributeRepository; +use Webkul\Checkout\Facades\Cart; +use Webkul\Core\Eloquent\Repository; +use Webkul\Product\Models\Product; +use Webkul\Product\Models\ProductAttributeValueProxy; +use Webkul\Product\Models\ProductFlat; class ProductRepository extends Repository { /** - * AttributeRepository object + * Attribute repository instance, * * @var \Webkul\Attribute\Repositories\AttributeRepository */ @@ -39,26 +39,26 @@ class ProductRepository extends Repository public function __construct( AttributeRepository $attributeRepository, App $app - ) - { + ) { $this->attributeRepository = $attributeRepository; parent::__construct($app); } /** - * Specify Model class name + * Specify model class name. * * @return string */ - function model() + public function model() { - return 'Webkul\Product\Contracts\Product'; + return \Webkul\Product\Contracts\Product::class; } /** - * @param array $data + * Create product. * + * @param array $data * @return \Webkul\Product\Contracts\Product */ public function create(array $data) @@ -75,13 +75,14 @@ class ProductRepository extends Repository } /** - * @param array $data - * @param int $id - * @param string $attribute + * Update product. * + * @param array $data + * @param int $id + * @param string $attribute * @return \Webkul\Product\Contracts\Product */ - public function update(array $data, $id, $attribute = "id") + public function update(array $data, $id, $attribute = 'id') { Event::dispatch('catalog.product.update.before', $id); @@ -99,8 +100,9 @@ class ProductRepository extends Repository } /** - * @param int $id + * Delete product. * + * @param int $id * @return void */ public function delete($id) @@ -112,15 +114,15 @@ class ProductRepository extends Repository Event::dispatch('catalog.product.delete.after', $id); } - /** - * @param int $categoryId + /** + * Get product related to category. * + * @param int $categoryId * @return \Illuminate\Support\Collection */ public function getProductsRelatedToCategory($categoryId = null) { - $qb = $this->model - ->leftJoin('product_categories', 'products.id', '=', 'product_categories.product_id'); + $qb = $this->model->leftJoin('product_categories', 'products.id', '=', 'product_categories.product_id'); if ($categoryId) { $qb->where('product_categories.category_id', $categoryId); @@ -130,8 +132,41 @@ class ProductRepository extends Repository } /** - * @param string $categoryId + * Check out of stock items. This method needed `variants` alias in + * the `product_flat` query. * + * @param Webkul\Product\Models\ProductFlat $query + * @return Illuminate\Database\Eloquent\Builder + */ + public function checkOutOfStockItem($query) + { + return $query + ->leftJoin('products as ps', 'product_flat.product_id', '=', 'ps.id') + ->leftJoin('product_inventories as pv', 'product_flat.product_id', '=', 'pv.product_id') + ->where(function ($qb) { + return $qb + /* for grouped, downloadable, bundle and booking product */ + ->orWhereIn('ps.type', ['grouped', 'downloadable', 'bundle', 'booking']) + /* for simple and virtual product */ + ->orWhere(function ($qb) { + return $qb->whereIn('ps.type', ['simple', 'virtual'])->where('pv.qty', '>', 0); + }) + /* for configurable product */ + ->orWhere(function ($qb) { + return $qb->where('ps.type', 'configurable')->where(function ($qb) { + return $qb + ->selectRaw('SUM(' . DB::getTablePrefix() . 'product_inventories.qty)') + ->from('product_flat') + ->leftJoin('product_inventories', 'product_inventories.product_id', '=', 'product_flat.product_id'); + }, '>', 0); + }); + }); + } + + /** + * Get all products. + * + * @param string $categoryId * @return \Illuminate\Support\Collection */ public function getAll($categoryId = null) @@ -155,9 +190,8 @@ class ProductRepository extends Repository $qb = $query->distinct() ->select('product_flat.*') - ->join('product_flat as variants', 'product_flat.id', '=', DB::raw('COALESCE(' . DB::getTablePrefix() . 'variants.parent_id, ' . DB::getTablePrefix() . 'variants.id)')) ->leftJoin('product_categories', 'product_categories.product_id', '=', 'product_flat.product_id') - ->leftJoin('product_attribute_values', 'product_attribute_values.product_id', '=', 'variants.product_id') + ->leftJoin('product_attribute_values', 'product_attribute_values.product_id', '=', 'product_flat.product_id') ->where('product_flat.channel', $channel) ->where('product_flat.locale', $locale) ->whereNotNull('product_flat.url_key'); @@ -182,12 +216,10 @@ class ProductRepository extends Repository $qb->where('product_flat.name', 'like', '%' . urldecode($params['search']) . '%'); } - /* added for api as per the documentation */ if (isset($params['name'])) { $qb->where('product_flat.name', 'like', '%' . urldecode($params['name']) . '%'); } - /* added for api as per the documentation */ if (isset($params['url_key'])) { $qb->where('product_flat.url_key', 'like', '%' . urldecode($params['url_key']) . '%'); } @@ -227,25 +259,25 @@ class ProductRepository extends Repository } $qb - ->leftJoin('catalog_rule_product_prices', 'catalog_rule_product_prices.product_id', '=', 'variants.product_id') - ->leftJoin('product_customer_group_prices', 'product_customer_group_prices.product_id', '=', 'variants.product_id') + ->leftJoin('catalog_rule_product_prices', 'catalog_rule_product_prices.product_id', '=', 'product_flat.product_id') + ->leftJoin('product_customer_group_prices', 'product_customer_group_prices.product_id', '=', 'product_flat.product_id') ->where(function ($qb) use ($priceRange, $customerGroupId) { - $qb->where(function ($qb) use ($priceRange){ + $qb->where(function ($qb) use ($priceRange) { $qb - ->where('variants.min_price', '>=', core()->convertToBasePrice($priceRange[0])) - ->where('variants.min_price', '<=', core()->convertToBasePrice(end($priceRange))); + ->where('product_flat.min_price', '>=', core()->convertToBasePrice($priceRange[0])) + ->where('product_flat.min_price', '<=', core()->convertToBasePrice(end($priceRange))); }) - ->orWhere(function ($qb) use ($priceRange) { - $qb - ->where('catalog_rule_product_prices.price', '>=', core()->convertToBasePrice($priceRange[0])) - ->where('catalog_rule_product_prices.price', '<=', core()->convertToBasePrice(end($priceRange))); - }) - ->orWhere(function ($qb) use ($priceRange, $customerGroupId) { - $qb - ->where('product_customer_group_prices.value', '>=', core()->convertToBasePrice($priceRange[0])) - ->where('product_customer_group_prices.value', '<=', core()->convertToBasePrice(end($priceRange))) - ->where('product_customer_group_prices.customer_group_id', '=', $customerGroupId); - }); + ->orWhere(function ($qb) use ($priceRange) { + $qb + ->where('catalog_rule_product_prices.price', '>=', core()->convertToBasePrice($priceRange[0])) + ->where('catalog_rule_product_prices.price', '<=', core()->convertToBasePrice(end($priceRange))); + }) + ->orWhere(function ($qb) use ($priceRange, $customerGroupId) { + $qb + ->where('product_customer_group_prices.value', '>=', core()->convertToBasePrice($priceRange[0])) + ->where('product_customer_group_prices.value', '<=', core()->convertToBasePrice(end($priceRange))) + ->where('product_customer_group_prices.customer_group_id', '=', $customerGroupId); + }); }); } } @@ -291,7 +323,7 @@ class ProductRepository extends Repository # this is key! if a product has been filtered down to the same number of attributes that we filtered on, # we know that it has matched all of the requested filters. - $qb->groupBy('variants.id'); + $qb->groupBy('product_flat.id'); $qb->havingRaw('COUNT(*) = ' . count($attributeFilters)); } @@ -325,11 +357,10 @@ class ProductRepository extends Repository } /** - * Retrive product from slug - * - * @param string $slug - * @param string $columns + * Retrive product from slug. * + * @param string $slug + * @param string $columns * @return \Webkul\Product\Contracts\Product */ public function findBySlugOrFail($slug, $columns = null) @@ -350,10 +381,9 @@ class ProductRepository extends Repository } /** - * Retrieve product from slug without throwing an exception (might return null) - * - * @param string $slug + * Retrieve product from slug without throwing an exception. * + * @param string $slug * @return \Webkul\Product\Contracts\ProductFlat */ public function findBySlug($slug) @@ -366,7 +396,7 @@ class ProductRepository extends Repository } /** - * Returns newly added product + * Returns newly added product. * * @return \Illuminate\Support\Collection */ @@ -393,7 +423,7 @@ class ProductRepository extends Repository } /** - * Returns featured product + * Returns featured product. * * @return \Illuminate\Support\Collection */ @@ -420,10 +450,9 @@ class ProductRepository extends Repository } /** - * Search Product by Attribute - * - * @param string $term + * Search product by attribute. * + * @param string $term * @return \Illuminate\Support\Collection */ public function searchProductByAttribute($term) @@ -440,8 +469,8 @@ class ProductRepository extends Repository $searchDriver->setSettings([ 'attributesForFaceting' => [ - "searchable(locale)", - "searchable(channel)", + 'searchable(locale)', + 'searchable(channel)', ], ]); @@ -468,7 +497,6 @@ class ProductRepository extends Repository $query = $query->distinct() ->addSelect('product_flat.*') - ->join('product_flat as variants', 'product_flat.id', '=', DB::raw('COALESCE(' . DB::getTablePrefix() . 'variants.parent_id, ' . DB::getTablePrefix() . 'variants.id)')) ->where('product_flat.channel', $channel) ->where('product_flat.locale', $locale) ->whereNotNull('product_flat.url_key'); @@ -495,10 +523,9 @@ class ProductRepository extends Repository } /** - * Returns product's super attribute with options - * - * @param \Webkul\Product\Contracts\Product $product + * Returns product's super attribute with options. * + * @param \Webkul\Product\Contracts\Product $product * @return \Illuminate\Support\Collection */ public function getSuperAttributes($product) @@ -522,10 +549,9 @@ class ProductRepository extends Repository } /** - * Search simple products for grouped product association - * - * @param string $term + * Search simple products for grouped product association. * + * @param string $term * @return \Illuminate\Support\Collection */ public function searchSimpleProducts($term) @@ -552,7 +578,7 @@ class ProductRepository extends Repository * * Always make the copy is inactive so the admin is able to configure it before setting it live. * - * @param int $sourceProductId the id of the product that should be copied + * @param int $sourceProductId (The id of the product that should be copied.) */ public function copy(Product $originalProduct): Product { @@ -584,7 +610,7 @@ class ProductRepository extends Repository } /** - * Get default sort by option + * Get default sort by option. * * @return array */ @@ -598,12 +624,11 @@ class ProductRepository extends Repository } /** - * Check sort attribute and generate query - * - * @param object $query - * @param string $sort - * @param string $direction + * Check sort attribute and generate query. * + * @param object $query + * @param string $sort + * @param string $direction * @return object */ private function checkSortAttributeAndGenerateQuery($query, $sort, $direction) @@ -624,6 +649,12 @@ class ProductRepository extends Repository return $query; } + /** + * Fill original product. + * + * @param \Webkul\Product\Models\Product $sourceProduct + * @return void + */ private function fillOriginalProduct(Product &$sourceProduct): void { $sourceProduct @@ -635,16 +666,17 @@ class ProductRepository extends Repository } /** - * @param $originalProduct + * Persist copied product. * - * @return mixed + * @param $originalProduct + * @return \Webkul\Product\Models\Product */ private function persistCopiedProduct($originalProduct): Product { $copiedProduct = $originalProduct ->replicate() ->fill([ - // the sku and url_key needs to be unique and should be entered again newly by the admin: + // the sku and url_key needs to be unique and should be entered again newly by the admin 'sku' => 'temporary-sku-' . substr(md5(microtime()), 0, 6), ]); @@ -653,10 +685,12 @@ class ProductRepository extends Repository return $copiedProduct; } - /** * Gather the ids of the necessary product attributes. + * * Throw an Exception if one of these 'basic' attributes are missing for some reason. + * + * @return array */ private function gatherAttributeIds(): array { @@ -669,6 +703,13 @@ class ProductRepository extends Repository return $ids; } + /** + * Persist attribute values. + * + * @param \Webkul\Product\Models\Product $originalProduct + * @param \Webkul\Product\Models\Product $copiedProduct + * @return void + */ private function persistAttributeValues(Product $originalProduct, Product $copiedProduct): void { $attributeIds = $this->gatherAttributeIds(); @@ -749,8 +790,11 @@ class ProductRepository extends Repository } /** - * @param $originalProduct - * @param $copiedProduct + * Persist relations. + * + * @param $originalProduct + * @param $copiedProduct + * @return void */ private function persistRelations($originalProduct, $copiedProduct): void { @@ -822,15 +866,18 @@ class ProductRepository extends Repository } /** - * @object $data - * @object $copiedProduct - * @object $copiedProductImageVideo + * Copy product image video. + * + * @param $data + * @param $copiedProduct + * @param $copiedProductImageVideo + * @return void */ private function copyProductImageVideo($data, $copiedProduct, $copiedProductImageVideo): void { - $path = explode("/", $data->path); + $path = explode('/', $data->path); - $path = 'product/' . $copiedProduct->id .'/'. end($path); + $path = 'product/' . $copiedProduct->id . '/' . end($path); $copiedProductImageVideo->path = $path; @@ -840,37 +887,4 @@ class ProductRepository extends Repository Storage::copy($data->path, $copiedProductImageVideo->path); } - - /** - * Check out of stock items. This method needed `variants` alias in - * the `product_flat` query. - * - * @param Webkul\Product\Models\ProductFlat $query - * @return Illuminate\Database\Eloquent\Builder - */ - public function checkOutOfStockItem($query) - { - return $query - ->leftJoin('products as ps', 'product_flat.product_id', '=', 'ps.id') - ->leftJoin('product_inventories as pv', 'product_flat.product_id', '=', 'pv.product_id') - ->where(function ($qb) { - return $qb - /* for grouped, downloadable, bundle and booking product */ - ->orWhereIn('ps.type', ['grouped', 'downloadable', 'bundle', 'booking']) - /* for simple and virtual product */ - ->orWhere(function ($qb) { - return $qb->whereIn('ps.type', ['simple', 'virtual'])->where('pv.qty', '>', 0); - }) - /* for configurable product */ - ->orWhere(function ($qb) { - return $qb->where('ps.type', 'configurable')->where(function ($qb) { - return $qb - ->selectRaw('SUM(' . DB::getTablePrefix() . 'product_inventories.qty)') - ->from('product_flat') - ->leftJoin('product_inventories', 'product_inventories.product_id', '=', 'product_flat.product_id') - ->whereRaw(DB::getTablePrefix() . 'product_flat.parent_id = variants.id'); - }, '>', 0); - }); - }); - } -} \ No newline at end of file +}