Files
backend-mm/app/Repositories/Ecommerce/Product/ProductRepository.php
Mekan1206 a07c764dfe WIP
2026-04-30 19:50:59 +05:00

303 lines
6.9 KiB
PHP

<?php
namespace App\Repositories\Ecommerce\Product;
use App\Helpers\Ecommerce\Product\Filter\ProductFilterer;
use App\Helpers\Ecommerce\Product\Sort\ProductSorter;
use App\Models\Ecommerce\Product\Category\Category;
use App\Models\Ecommerce\Product\Product\Product;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class ProductRepository
{
/**
* Product pagination count
*/
public const PERPAGE = 32;
/**
* Query builder
*
* @var Builder
*/
protected mixed $queryBuilder;
/**
* Application request
*/
protected Request $request;
/**
* Relationships to eager load
*
* @var array<int, string>
*/
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(),
]);
}
}