Feat: Displaying Draft Products, only when AppDebug = true
This commit is contained in:
@@ -254,7 +254,10 @@ class ProductService
|
||||
public function random(int $limit): array
|
||||
{
|
||||
$raw = Product::search('')
|
||||
->options(['attributesToRetrieve' => ['id']])
|
||||
->options([
|
||||
'attributesToRetrieve' => ['id'],
|
||||
'filter' => $this->filterBuilder->withVisibility(),
|
||||
])
|
||||
->raw();
|
||||
|
||||
$ids = collect($raw['hits'] ?? [])->pluck('id')->shuffle()->take($limit)->values();
|
||||
@@ -287,7 +290,7 @@ class ProductService
|
||||
private function findAllWhere(string $filter, int $limit = 1000): array
|
||||
{
|
||||
$paginator = Product::search('')
|
||||
->options(['filter' => $filter])
|
||||
->options(['filter' => $this->filterBuilder->withVisibility($filter)])
|
||||
->paginateRaw(perPage: $limit, page: 1);
|
||||
|
||||
return collect($this->localizer->hitsFrom($paginator))
|
||||
|
||||
@@ -10,6 +10,13 @@ use Modules\Core\Catalog\DTOs\ProductFilters;
|
||||
* out of ProductService (where it originated, scoped to browsing/filtering
|
||||
* without a search term) so ProductSearchService can apply the exact same
|
||||
* filter semantics to a text query too, rather than reimplementing it.
|
||||
*
|
||||
* Also the single place that composes the draft-visibility clause (see
|
||||
* withVisibility()) — every Meilisearch `filter` string ProductService
|
||||
* constructs, including the handful of ad-hoc ones that don't call build()
|
||||
* at all (getById()/getBySlug()'s id lookup, random()'s id-only fetch),
|
||||
* goes through this class so none of them can silently omit it the way a
|
||||
* status filter was missing everywhere until now.
|
||||
*/
|
||||
class ProductFilterBuilder
|
||||
{
|
||||
@@ -19,10 +26,10 @@ class ProductFilterBuilder
|
||||
* ProductService::priceRange() excludes 'price' so a price slider's own
|
||||
* bounds don't shrink to whatever range is already selected on it.
|
||||
*/
|
||||
public function build(?ProductFilters $filters, array $exclude = []): ?string
|
||||
public function build(?ProductFilters $filters, array $exclude = []): string
|
||||
{
|
||||
if ($filters === null) {
|
||||
return null;
|
||||
return $this->withVisibility();
|
||||
}
|
||||
|
||||
$clauses = Collection::make([
|
||||
@@ -36,6 +43,27 @@ class ProductFilterBuilder
|
||||
'inStockOnly' => $filters->inStockOnly ? 'in_stock = true' : null,
|
||||
])->except($exclude)->filter();
|
||||
|
||||
return $clauses->isEmpty() ? null : $clauses->join(' AND ');
|
||||
return $this->withVisibility($clauses->isEmpty() ? null : $clauses->join(' AND '));
|
||||
}
|
||||
|
||||
/**
|
||||
* A draft product (status = 'draft', see Lunar\Filament\Resources\
|
||||
* ProductResource's own status Select) is only ever visible while
|
||||
* APP_DEBUG is true — a merchant/developer previewing an unfinished
|
||||
* product locally or on a staging box, never a real storefront
|
||||
* visitor. Every ProductService method that builds a Meilisearch
|
||||
* `filter` string, build() included, calls this rather than passing
|
||||
* $rawClause straight to Product::search() — the one seam that
|
||||
* guarantees none of them can omit the visibility rule.
|
||||
*
|
||||
* Always returns a non-empty string (never null) — a bare
|
||||
* 'status = "published"' is itself a complete, valid Meilisearch
|
||||
* filter on its own when $rawClause is null.
|
||||
*/
|
||||
public function withVisibility(?string $rawClause = null): string
|
||||
{
|
||||
$visibility = config('app.debug') ? null : 'status = "published"';
|
||||
|
||||
return Collection::make([$visibility, $rawClause])->filter()->join(' AND ');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user