# Listings Page

# How do I extend the listings page query?

You can extend the listings page query by extending the `\Aero\Store\Pipelines\ListingsPageQuery` pipeline.

For example, you can add functionality to have products that only certain customer groups can view and buy.

First, add a product setting to control this behaviour:

```php
\Aero\Catalog\Models\Product::settings('customer_groups', function (\Aero\Common\Settings\ModelSettingGroup $group) {
    $group->eloquent('allowed_customer_groups', \Aero\Account\Models\CustomerGroup::class)
        ->hint('Leave blank to allow any customer group to view/buy this product')
        ->multiple()
        ->dontLoadModels();
});
```

Then add this data to the `\Aero\Search\Elastic\Documents\ListingDocument`:

```php
\Aero\Search\Elastic\Documents\ListingDocument::add('search-data', function (\Aero\Search\Elastic\Documents\ListingDocument $document) {
    $product = optional($document->getModel())->product ?? null;

    $allowedGroups = optional($product)->setting('customer_groups.allowed_customer_groups') ?? [];

    return [
        'customer_groups' => $allowedGroups,
        'does_not_require_customer_group' => empty($allowedGroups),
    ];
});
```

<p class="callout warning">You must run `php artisan aero:search:reindex --type=listing` for these document changes to be applied to existing listings.</p>

Then extend the query to use factor this in when resolving what listings to show on the listings page:

```php
\Aero\Store\Pipelines\ListingsPageQuery::extend(function (\Aero\Store\Pipelines\ListingsPageQuery $builder) {
    $bool = new \Elastica\Query\BoolQuery();

    // Always show products that don't require a customer group
    $bool->addShould(
        new \Elastica\Query\Term([
            'search-data.does_not_require_customer_group' => true,
        ]),
    );

    // When a customer is in a group, also show products that require that group
    if ($group = optional($builder->builder->request->user())->customer_group_id) {
        $bool->addShould(
            new \Elastica\Query\Terms('search-data.customer_groups', [$group]),
        );
    }

    // At least one of the above conditions must be met
    $bool->setMinimumShouldMatch(1);

    $builder->query->getQuery()->addMust($bool);
});
```

Finally extend the product page to prevent people viewing products when they lack the required customer group:

```php
\Aero\Store\Http\Responses\ProductPage::extend(function (\Aero\Store\Http\Responses\ProductPage $page, \Closure $next) {
    $allowedGroups = $page->product->setting('customer_groups.allowed_customer_groups');

    if (empty($allowedGroups)) {
        return $next($page);
    }

    $customer = $page->request->user();

    $customerGroupId = optional($customer)->customer_group_id ?? null;

    abort_unless(in_array($customerGroupId, $allowedGroups), 404);

    return $next($page);
});
```