1<?php
2
3namespace Elastica\Aggregation;
4
5use Elastica\Exception\InvalidException;
6use Elastica\Query\AbstractQuery;
7
8/**
9 * Class Filters.
10 *
11 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-filters-aggregation.html
12 */
13class Filters extends AbstractAggregation
14{
15    const NAMED_TYPE = 1;
16    const ANONYMOUS_TYPE = 2;
17
18    /**
19     * @var int Type of bucket keys - named, or anonymous
20     */
21    private $_type;
22
23    /**
24     * Add a filter.
25     *
26     * If a name is given, it will be added as a key, otherwise considered as an anonymous filter
27     *
28     * @param AbstractQuery $filter
29     * @param string        $name
30     *
31     * @return $this
32     */
33    public function addFilter(AbstractQuery $filter, string $name = null): self
34    {
35        $filterArray = [];
36
37        $type = self::NAMED_TYPE;
38
39        if (null === $name) {
40            $filterArray[] = $filter;
41            $type = self::ANONYMOUS_TYPE;
42        } else {
43            $filterArray[$name] = $filter;
44        }
45
46        if ($this->hasParam('filters')
47            && \count($this->getParam('filters'))
48            && $this->_type !== $type
49        ) {
50            throw new InvalidException('Mix named and anonymous keys are not allowed');
51        }
52
53        $this->_type = $type;
54
55        return $this->addParam('filters', $filterArray);
56    }
57
58    /**
59     * @param bool $otherBucket
60     *
61     * @return $this
62     */
63    public function setOtherBucket(bool $otherBucket): self
64    {
65        return $this->setParam('other_bucket', $otherBucket);
66    }
67
68    /**
69     * @param string $otherBucketKey
70     *
71     * @return $this
72     */
73    public function setOtherBucketKey(string $otherBucketKey): self
74    {
75        return $this->setParam('other_bucket_key', $otherBucketKey);
76    }
77
78    /**
79     * @return array
80     */
81    public function toArray(): array
82    {
83        $array = [];
84        $filters = $this->getParam('filters');
85
86        foreach ($filters as $filter) {
87            if (self::NAMED_TYPE === $this->_type) {
88                $key = \key($filter);
89                $array['filters']['filters'][$key] = \current($filter)->toArray();
90            } else {
91                $array['filters']['filters'][] = \current($filter)->toArray();
92            }
93        }
94
95        if ($this->hasParam('other_bucket')) {
96            $array['filters']['other_bucket'] = $this->getParam('other_bucket');
97        }
98
99        if ($this->hasParam('other_bucket_key')) {
100            $array['filters']['other_bucket_key'] = $this->getParam('other_bucket_key');
101        }
102
103        if ($this->_aggs) {
104            $array['aggs'] = $this->_convertArrayable($this->_aggs);
105        }
106
107        return $array;
108    }
109}
110