*/ protected array $with = []; /** * Product repository */ public function __construct(Request $request) { $this->queryBuilder = Product::query(); $this->request = $request; } /** * Create new class via static method "make" */ public static function make(Request $request): self { return new self($request); } /** * Update query builder with resource relationship */ public function queryAsFromResource($resource): self { $this->queryBuilder = $resource->products(); return $this; } /** * Attach relationships to eager load */ public function attachEagerLoadingRelationship(array $relationships): self { $this->with = array_merge($this->with, $relationships); return $this; } /** * Load relationships */ public function eagerLoadRelationships(): self { $this->queryBuilder->with($this->with); return $this; } /** * Apply Basic queries */ public function applyBasicQueries(): self { $this->attachEagerLoadingRelationship([ 'brand', 'reviews', 'media' => function ($query) { $query->orderBy('order_column', 'asc'); }, ]); $this->queryBuilder ->where('products.is_visible', true) ->where('products.parent_id', null) ->where('products.stock', '>', 0); return $this; } /** * Apply filters */ public function applyFilters(): self { $this->queryBuilder = ProductFilterer::make($this->queryBuilder, $this->request)->filter(); return $this; } /** * Apply search queries */ public function applySearchQueries(): self { if (request()->filled('q')) { $searcQuery = str_replace([ '\\', '(', ')', '[', ']', ], '', request('q')); // Search by name $this->queryBuilder->where('products.name', '~*', $searcQuery); } return $this; } public function applyMultiLevelFilter(Category $category): self { $categoryId = $category->id; $categoryIds = collect(DB::select(' WITH RECURSIVE category_tree AS ( SELECT id FROM categories WHERE id = ? UNION SELECT c.id FROM categories c JOIN category_tree ct ON c.parent_id = ct.id ) SELECT id FROM category_tree ', [$categoryId]))->pluck('id'); $products = DB::table('products') ->join('product_has_relations', 'products.id', '=', 'product_has_relations.product_id') ->whereIn('product_has_relations.productable_id', $categoryIds) ->where('product_has_relations.productable_type', '=', 'category') ->select('products.id') ->distinct() ->pluck('id') ->toArray(); $this->queryBuilder->whereIntegerInRaw('products.id', $products); return $this; } /** * Apply sorting */ public function applySorting(): self { $this->queryBuilder = ProductSorter::make($this->queryBuilder, $this->request)->sort(); return $this; } /** * "Where IN" clouse */ public function whereIn(string $attribute, array $value): self { $this->queryBuilder->whereIn($attribute, $value); return $this; } /** * "where integer in raw" clouse */ public function whereIntegerInRaw(string $attribute, array $value): self { $this->queryBuilder->whereIn($attribute, $value); return $this; } /** * Simple pagination */ public function simplePaginate(): Paginator { $this->eagerLoadRelationships(); return $this->queryBuilder->simplePaginate( perPage: $this->defaultPaginationPerPage(), page: $this->paginationPage(), ); } /** * Get the results */ public function get() { $this->eagerLoadRelationships(); return $this->queryBuilder->get(); } /** * Default Pagination Per Page */ public function defaultPaginationPerPage(): int { return intval(request('perPage')) ?: self::PERPAGE; } /** * Pagination page */ public function paginationPage(): int { return intval($this->request->page) ?: 1; } /** * Path to manage products on panel */ public static function panelPath(): string { return sprintf('%s/resources/products', config('nova.path')); } /** * Calculate price */ public static function calculatePrice(int|float $price, int $tax): float { return round_up(($price / (100 - $tax)) * 100); } /** * Shipping attributes */ public static function shippingAttributes(): array { return [ 'back_order' => false, 'weight_value' => null, 'weight_unit' => null, 'height_value' => null, 'height_unit' => null, 'width_value' => null, 'width_unit' => null, 'depth_value' => null, 'depth_unit' => null, 'volume_value' => null, 'volume_unit' => null, ]; } /** * Nova repository */ public static function nova(): NovaProductRepository { return new NovaProductRepository(); } /** * Sanatize File Name */ public static function sanitizeFileName(string $filename): string { return strtolower(str_replace(['#', '/', '\\', ' ', ','], '-', $filename)); } /** * Ajax paginate */ public static function ajaxPaginate($products): JsonResponse { return response()->json([ 'pagination' => $products, 'products' => view('web.themes.trendyol.components.products.collection.just-render', [ 'products' => $products, ])->render(), ]); } }