303 lines
6.9 KiB
PHP
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(),
|
|
]);
|
|
}
|
|
}
|