Files
backend-mm/app/Repositories/Ecommerce/Product/ProductRepository.php
2025-09-25 03:03:31 +05:00

271 lines
5.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\Product\Product;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ProductRepository
{
/**
* Product pagination count
*/
public const PERPAGE = 32;
/**
* Query builder
*
* @var \Illuminate\Database\Eloquent\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;
}
/**
* 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(),
]);
}
}