1<?php
2
3namespace Elastica\Type;
4
5use Elastica\Client;
6use Elastica\Exception\InvalidException;
7use Elastica\Index;
8use Elastica\Query;
9use Elastica\ResultSet;
10use Elastica\Search;
11use Elastica\SearchableInterface;
12use Elastica\Type;
13use Elastica\Type as BaseType;
14use Elastica\Util;
15
16/**
17 * Abstract helper class to implement search indices based on models.
18 *
19 * This abstract model should help creating search index and a subtype
20 * with some easy config entries that are overloaded.
21 *
22 * The following variables have to be set:
23 *    - $_indexName
24 *    - $_typeName
25 *
26 * The following variables can be set for additional configuration
27 *    - $_mapping: Value type mapping for the given type
28 *    - $_indexParams: Parameters for the index
29 *
30 * @todo Add some settings examples to code
31 *
32 * @author Nicolas Ruflin <spam@ruflin.com>
33 */
34abstract class AbstractType implements SearchableInterface
35{
36    const MAX_DOCS_PER_REQUEST = 1000;
37
38    /**
39     * Index name.
40     *
41     * @var string Index name
42     */
43    protected $_indexName;
44
45    /**
46     * Index name.
47     *
48     * @var string Index name
49     */
50    protected $_typeName;
51
52    /**
53     * Client.
54     *
55     * @var \Elastica\Client Client object
56     */
57    protected $_client;
58
59    /**
60     * Index.
61     *
62     * @var \Elastica\Index Index object
63     */
64    protected $_index;
65
66    /**
67     * Type.
68     *
69     * @var \Elastica\Type Type object
70     */
71    protected $_type;
72
73    /**
74     * Mapping.
75     *
76     * @var array Mapping
77     */
78    protected $_mapping = [];
79
80    /**
81     * Index params.
82     *
83     * @var array Index  params
84     */
85    protected $_indexParams = [];
86
87    /**
88     * Source.
89     *
90     * @var bool Source
91     */
92    protected $_source = true;
93
94    /**
95     * Creates index object with client connection.
96     *
97     * Reads index and type name from protected vars _indexName and _typeName.
98     * Has to be set in child class
99     *
100     * @param Client $client OPTIONAL Client object
101     *
102     * @throws InvalidException
103     */
104    public function __construct(Client $client = null)
105    {
106        if (!$client) {
107            $client = new Client();
108        }
109
110        if (empty($this->_indexName)) {
111            throw new InvalidException('Index name has to be set');
112        }
113
114        if (empty($this->_typeName)) {
115            throw new InvalidException('Type name has to be set');
116        }
117
118        $this->_client = $client;
119        $this->_index = new Index($this->_client, $this->_indexName);
120        $this->_type = new BaseType($this->_index, $this->_typeName);
121    }
122
123    /**
124     * Creates the index and sets the mapping for this type.
125     *
126     * @param bool $recreate OPTIONAL Recreates the index if true (default = false)
127     */
128    public function create(bool $recreate = false)
129    {
130        $this->getIndex()->create($this->_indexParams, $recreate);
131
132        $mapping = new Mapping($this->getType());
133        $mapping->setProperties($this->_mapping);
134        $mapping->setSource(['enabled' => $this->_source]);
135        $mapping->send();
136    }
137
138    /**
139     * @param string|Query $query
140     * @param array|int    $options
141     *
142     * @return Search
143     */
144    public function createSearch($query = '', $options = null): Search
145    {
146        return $this->getType()->createSearch($query, $options);
147    }
148
149    /**
150     * Search on the type.
151     *
152     * @param string|array|Query $query   Array with all query data inside or a Elastica\Query object
153     * @param int|array          $options
154     *
155     * @return ResultSet with all results inside
156     *
157     * @see \Elastica\SearchableInterface::search
158     */
159    public function search($query = '', $options = null): ResultSet
160    {
161        return $this->getType()->search($query, $options = null);
162    }
163
164    /**
165     * Count docs in the type based on query.
166     *
167     * @param string|array|Query $query Array with all query data inside or a Elastica\Query object
168     *
169     * @return int number of documents matching the query
170     *
171     * @see \Elastica\SearchableInterface::count
172     */
173    public function count($query = ''): int
174    {
175        return $this->getType()->count($query);
176    }
177
178    /**
179     * Returns the search index.
180     *
181     * @return Index Index object
182     */
183    public function getIndex(): Index
184    {
185        return $this->_index;
186    }
187
188    /**
189     * Returns type object.
190     *
191     * @return Type Type object
192     */
193    public function getType(): Type
194    {
195        return $this->_type;
196    }
197
198    /**
199     * Converts given time to format: 1995-12-31T23:59:59Z.
200     *
201     * This is the lucene date format
202     *
203     * @param int $date Date input (could be string etc.) -> must be supported by strtotime
204     *
205     * @return string Converted date string
206     */
207    public function convertDate(int $date): string
208    {
209        return Util::convertDate($date);
210    }
211}
212