|
@@ -8,11 +8,13 @@ use ApiPlatform\State\Pagination\Pagination;
|
|
|
use ApiPlatform\State\ProviderInterface;
|
|
use ApiPlatform\State\ProviderInterface;
|
|
|
use Illuminate\Pagination\LengthAwarePaginator as LaravelPaginator;
|
|
use Illuminate\Pagination\LengthAwarePaginator as LaravelPaginator;
|
|
|
use Webkul\BagistoApi\Models\Product;
|
|
use Webkul\BagistoApi\Models\Product;
|
|
|
|
|
+use Webkul\Product\Repositories\ElasticSearchRepository;
|
|
|
|
|
|
|
|
class ProductGraphQLProvider implements ProviderInterface
|
|
class ProductGraphQLProvider implements ProviderInterface
|
|
|
{
|
|
{
|
|
|
public function __construct(
|
|
public function __construct(
|
|
|
- private readonly Pagination $pagination
|
|
|
|
|
|
|
+ private readonly Pagination $pagination,
|
|
|
|
|
+ private readonly ElasticSearchRepository $elasticSearchRepository
|
|
|
) {}
|
|
) {}
|
|
|
|
|
|
|
|
private ?array $attributeTypeCache = null;
|
|
private ?array $attributeTypeCache = null;
|
|
@@ -33,6 +35,8 @@ class ProductGraphQLProvider implements ProviderInterface
|
|
|
|
|
|
|
|
$args = $context['args'] ?? [];
|
|
$args = $context['args'] ?? [];
|
|
|
|
|
|
|
|
|
|
+ request()->attributes->remove('bagistoapi.search_metadata');
|
|
|
|
|
+
|
|
|
$query = Product::query();
|
|
$query = Product::query();
|
|
|
|
|
|
|
|
$query->whereHas('attribute_values', function ($q) {
|
|
$query->whereHas('attribute_values', function ($q) {
|
|
@@ -45,7 +49,28 @@ class ProductGraphQLProvider implements ProviderInterface
|
|
|
->where('boolean_value', 1);
|
|
->where('boolean_value', 1);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- if (! empty($args['query'])) {
|
|
|
|
|
|
|
+ $elasticSearchIds = null;
|
|
|
|
|
+ $suggest = filter_var($args['suggest'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
|
|
|
|
+
|
|
|
|
|
+ if (
|
|
|
|
|
+ ! empty($args['query'])
|
|
|
|
|
+ && core()->getConfigData('catalog.products.search.engine') === 'elastic'
|
|
|
|
|
+ && core()->getConfigData('catalog.products.search.storefront_mode') === 'elastic'
|
|
|
|
|
+ ) {
|
|
|
|
|
+ $searchResult = $this->elasticSearchRepository->searchForApi($args['query'], $suggest);
|
|
|
|
|
+ $elasticSearchIds = $searchResult['ids'];
|
|
|
|
|
+
|
|
|
|
|
+ if ($searchResult['query'] !== $args['query']) {
|
|
|
|
|
+ request()->attributes->set('bagistoapi.search_metadata', [
|
|
|
|
|
+ 'originalQuery' => $args['query'],
|
|
|
|
|
+ 'effectiveQuery' => $searchResult['query'],
|
|
|
|
|
+ 'resultMessage' => 'These are results for: '.$searchResult['query'],
|
|
|
|
|
+ 'searchInsteadMessage' => 'Search instead for '.$args['query'],
|
|
|
|
|
+ ]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $query->whereIn('products.id', $elasticSearchIds);
|
|
|
|
|
+ } elseif (! empty($args['query'])) {
|
|
|
$searchTerm = $args['query'];
|
|
$searchTerm = $args['query'];
|
|
|
|
|
|
|
|
$query->where(function ($q) use ($searchTerm) {
|
|
$query->where(function ($q) use ($searchTerm) {
|
|
@@ -63,66 +88,70 @@ class ProductGraphQLProvider implements ProviderInterface
|
|
|
$locale = $args['locale'] ?? request()->attributes->get('bagisto_locale');
|
|
$locale = $args['locale'] ?? request()->attributes->get('bagisto_locale');
|
|
|
$channel = $args['channel'] ?? request()->attributes->get('bagisto_channel');
|
|
$channel = $args['channel'] ?? request()->attributes->get('bagisto_channel');
|
|
|
|
|
|
|
|
- switch ($sortKey) {
|
|
|
|
|
- case 'TITLE':
|
|
|
|
|
- case 'NAME':
|
|
|
|
|
- $prefix = \DB::getTablePrefix();
|
|
|
|
|
-
|
|
|
|
|
- // Join for requested locale/channel
|
|
|
|
|
- $query->leftJoin('product_attribute_values as pav_name_locale', function ($join) use ($locale, $channel) {
|
|
|
|
|
- $join->on('products.id', '=', 'pav_name_locale.product_id')
|
|
|
|
|
- ->where('pav_name_locale.attribute_id', 2);
|
|
|
|
|
-
|
|
|
|
|
- if ($locale) {
|
|
|
|
|
- $join->where('pav_name_locale.locale', $locale);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if ($channel) {
|
|
|
|
|
- $join->where('pav_name_locale.channel', $channel);
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ if (! empty($elasticSearchIds) && ! isset($args['sortKey'])) {
|
|
|
|
|
+ $query->orderByRaw('FIELD(products.id, '.implode(',', $elasticSearchIds).')');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ switch ($sortKey) {
|
|
|
|
|
+ case 'TITLE':
|
|
|
|
|
+ case 'NAME':
|
|
|
|
|
+ $prefix = \DB::getTablePrefix();
|
|
|
|
|
+
|
|
|
|
|
+ // Join for requested locale/channel
|
|
|
|
|
+ $query->leftJoin('product_attribute_values as pav_name_locale', function ($join) use ($locale, $channel) {
|
|
|
|
|
+ $join->on('products.id', '=', 'pav_name_locale.product_id')
|
|
|
|
|
+ ->where('pav_name_locale.attribute_id', 2);
|
|
|
|
|
+
|
|
|
|
|
+ if ($locale) {
|
|
|
|
|
+ $join->where('pav_name_locale.locale', $locale);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ($channel) {
|
|
|
|
|
+ $join->where('pav_name_locale.channel', $channel);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- // Fallback join for null locale/channel (default values)
|
|
|
|
|
- $query->leftJoin('product_attribute_values as pav_name_fallback', function ($join) {
|
|
|
|
|
- $join->on('products.id', '=', 'pav_name_fallback.product_id')
|
|
|
|
|
- ->where('pav_name_fallback.attribute_id', 2)
|
|
|
|
|
- ->whereNull('pav_name_fallback.locale')
|
|
|
|
|
- ->whereNull('pav_name_fallback.channel');
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ // Fallback join for null locale/channel (default values)
|
|
|
|
|
+ $query->leftJoin('product_attribute_values as pav_name_fallback', function ($join) {
|
|
|
|
|
+ $join->on('products.id', '=', 'pav_name_fallback.product_id')
|
|
|
|
|
+ ->where('pav_name_fallback.attribute_id', 2)
|
|
|
|
|
+ ->whereNull('pav_name_fallback.locale')
|
|
|
|
|
+ ->whereNull('pav_name_fallback.channel');
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- $query->orderBy(\DB::raw("COALESCE({$prefix}pav_name_locale.text_value, {$prefix}pav_name_fallback.text_value)"), $direction)
|
|
|
|
|
- ->orderBy('products.id', $direction)
|
|
|
|
|
- ->select('products.*');
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'CREATED_AT':
|
|
|
|
|
- $query->orderBy('products.created_at', $direction)
|
|
|
|
|
- ->orderBy('products.id', $direction);
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'UPDATED_AT':
|
|
|
|
|
- $query->orderBy('products.updated_at', $direction)
|
|
|
|
|
- ->orderBy('products.id', $direction);
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'PRICE':
|
|
|
|
|
- $user = auth()->user();
|
|
|
|
|
- $customerGroup = $user?->getDefaultGroup()
|
|
|
|
|
- ?? app(\Webkul\Customer\Repositories\CustomerGroupRepository::class)
|
|
|
|
|
- ->findOneByField('code', 'guest');
|
|
|
|
|
-
|
|
|
|
|
- $query->leftJoin('product_price_indices', function ($join) use ($customerGroup) {
|
|
|
|
|
- $join->on('products.id', '=', 'product_price_indices.product_id')
|
|
|
|
|
- ->where('product_price_indices.customer_group_id', $customerGroup->id);
|
|
|
|
|
- })
|
|
|
|
|
- ->orderBy('product_price_indices.min_price', $direction)
|
|
|
|
|
- ->orderBy('products.id', $direction)
|
|
|
|
|
- ->select('products.*');
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'ID':
|
|
|
|
|
- default:
|
|
|
|
|
- $query->orderBy('products.id', $direction);
|
|
|
|
|
|
|
+ $query->orderBy(\DB::raw("COALESCE({$prefix}pav_name_locale.text_value, {$prefix}pav_name_fallback.text_value)"), $direction)
|
|
|
|
|
+ ->orderBy('products.id', $direction)
|
|
|
|
|
+ ->select('products.*');
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case 'CREATED_AT':
|
|
|
|
|
+ $query->orderBy('products.created_at', $direction)
|
|
|
|
|
+ ->orderBy('products.id', $direction);
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case 'UPDATED_AT':
|
|
|
|
|
+ $query->orderBy('products.updated_at', $direction)
|
|
|
|
|
+ ->orderBy('products.id', $direction);
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case 'PRICE':
|
|
|
|
|
+ $user = auth()->user();
|
|
|
|
|
+ $customerGroup = $user?->getDefaultGroup()
|
|
|
|
|
+ ?? app(\Webkul\Customer\Repositories\CustomerGroupRepository::class)
|
|
|
|
|
+ ->findOneByField('code', 'guest');
|
|
|
|
|
+
|
|
|
|
|
+ $query->leftJoin('product_price_indices', function ($join) use ($customerGroup) {
|
|
|
|
|
+ $join->on('products.id', '=', 'product_price_indices.product_id')
|
|
|
|
|
+ ->where('product_price_indices.customer_group_id', $customerGroup->id);
|
|
|
|
|
+ })
|
|
|
|
|
+ ->orderBy('product_price_indices.min_price', $direction)
|
|
|
|
|
+ ->orderBy('products.id', $direction)
|
|
|
|
|
+ ->select('products.*');
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case 'ID':
|
|
|
|
|
+ default:
|
|
|
|
|
+ $query->orderBy('products.id', $direction);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
$filters = [];
|
|
$filters = [];
|