Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 194
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
Location
0.00% covered (danger)
0.00%
0 / 194
0.00% covered (danger)
0.00%
0 / 8
1482
0.00% covered (danger)
0.00%
0 / 1
 fetchId
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 fetchList
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
20
 fetchFromCsv
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
6
 searchAll
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 1
56
 readSearchResultList
0.00% covered (danger)
0.00%
0 / 44
0.00% covered (danger)
0.00%
0 / 1
56
 fetchGeoJsonLocations
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
12
 fetchGeoJson
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
72
 fetchLocationsForCompilation
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3/**
4 * @package ClientDldb
5 * @copyright BerlinOnline Stadtportal GmbH & Co. KG
6 **/
7
8namespace BO\Zmsdldb\Elastic;
9
10use BO\Zmsdldb\Entity\Location as Entity;
11use BO\Zmsdldb\Collection\Locations as Collection;
12use BO\Zmsdldb\File\Location as Base;
13
14/**
15 * @SuppressWarnings(Coupling)
16 */
17class Location extends Base
18{
19    /**
20     *
21     * @return Entity|false
22     */
23    #[\Override]
24    public function fetchId($itemId)
25    {
26        if ($itemId) {
27            $query = Helper::boolFilteredQuery();
28            $query->getFilter()->addMust(Helper::idsFilter($this->locale . $itemId));
29            $result = $this->access()
30                ->getIndex()
31                ->getType('location')
32                ->search($query, 1);
33
34            if ($result->count() == 1) {
35                $locationList = $result->getResults();
36                return new Entity($locationList[0]->getData());
37            }
38        }
39        return false;
40    }
41
42    /**
43     *
44     * @return Collection
45     */
46    #[\Override]
47    public function fetchList($service_csv = '')
48    {
49        $query = Helper::boolFilteredQuery();
50        $limit = 10000;
51        $query->getFilter()->addMust(Helper::localeFilter($this->locale));
52        if ($service_csv) {
53            foreach (explode(',', $service_csv) as $service_id) {
54                $filter = new \Elastica\Filter\Term(array(
55                    'services.service' => $service_id
56                ));
57                $query->getFilter()->addMust($filter);
58            }
59        }
60        $resultList = $this->access()
61            ->getIndex()
62            ->getType('location')
63            ->search($query, $limit);
64
65        $locationList = new Collection();
66        foreach ($resultList as $result) {
67            $location = new Entity($result->getData());
68            $locationList[$location['id']] = $location;
69        }
70        return $locationList;
71    }
72
73    /**
74     *
75     * @return Collection
76     */
77    #[\Override]
78    public function fetchFromCsv($location_csv)
79    {
80        $query = Helper::boolFilteredQuery();
81        $filter = new \Elastica\Filter\Ids();
82        $ids = explode(',', $location_csv);
83        $ids = array_map(function ($value) {
84            return $this->locale . $value;
85        }, $ids);
86        $filter->setIds($ids);
87        $query->getFilter()->addMust($filter);
88        $resultList = $this->access()
89            ->getIndex()
90            ->getType('location')
91            ->search($query, 10000);
92        $locationList = new Collection();
93        foreach ($resultList as $result) {
94            $location = new Entity($result->getData());
95            $locationList[$location['id']] = $location;
96        }
97        return $locationList;
98    }
99
100    /**
101     *
102     * @return \BO\Zmsdldb\Collection\Authorities
103     * @psalm-api
104     */
105    public function searchAll($querystring, $service_csv = '')
106    {
107        $query = Helper::boolFilteredQuery();
108        $mainquery = new \Elastica\Query();
109        $limit = 1000;
110        $searchquery = new \Elastica\Query\QueryString();
111        if ($querystring > 10000 && $querystring < 15000) {
112            // if it is a postal code, sort by distance and limit results
113            $coordinates = \BO\Zmsdldb\Plz\Coordinates::zip2LatLon($querystring);
114            if (false !== $coordinates) {
115                $searchquery->setQuery('*');
116                $mainquery->addSort([
117                    "_geo_distance" => [
118                        "geo" => [
119                            "lat" => $coordinates['lat'],
120                            "lon" => $coordinates['lon']
121                        ],
122                        "order" => "asc",
123                        "unit" => "km"
124                    ]
125                ]);
126                $limit = 5;
127            }
128        } elseif ('' === trim($querystring)) {
129            // if empty, find all and trust in the filter
130            $searchquery->setQuery('*');
131        } else {
132            $searchquery->setQuery($querystring);
133        }
134        $searchquery->setFields([
135            'name^9',
136            'authority.name^5',
137            'address.street',
138            'address.postal_code^9'
139        ]);
140        $query->getQuery()->addShould($searchquery);
141        if ($service_csv) {
142            foreach (explode(',', $service_csv) as $service_id) {
143                $filter = new \Elastica\Filter\Term(array(
144                    'services.service' => $service_id
145                ));
146                $query->getFilter()->addMust($filter);
147            }
148        }
149        $mainquery->setQuery($query);
150        $resultList = $this->access()
151            ->getIndex()
152            ->getType('location')
153            ->search($mainquery, $limit);
154        return $this->access()
155            ->fromAuthority()
156            ->fromLocationResults($resultList);
157    }
158
159    /**
160     * search locations
161     * this function is similar to self::searchAll() but it might get different boosts in the future
162     *
163     * @return Collection
164     */
165    #[\Override]
166    public function readSearchResultList($query, $service_csv = '')
167    {
168        $boolquery = Helper::boolFilteredQuery();
169        $boolquery->getFilter()->addMust(Helper::localeFilter($this->locale));
170        $mainquery = new \Elastica\Query();
171        $limit = 1000;
172        //$sort = true;
173        $searchquery = new \Elastica\Query\QueryString();
174        if ($query > 10000 && $query < 15000) {
175            // if it is a postal code, sort by distance and limit results
176            $coordinates = \BO\Zmsdldb\Plz\Coordinates::zip2LatLon($query);
177            if (false !== $coordinates) {
178                $searchquery->setQuery('*');
179                $mainquery->addSort([
180                    "_geo_distance" => [
181                        "geo" => [
182                            "lat" => $coordinates['lat'],
183                            "lon" => $coordinates['lon']
184                        ],
185                        "order" => "asc",
186                        "unit" => "km"
187                    ]
188                ]);
189                $limit = 5;
190                //$sort = false;
191            }
192        } elseif ('' === trim($query)) {
193            // if empty, find all and trust in the filter
194            $searchquery->setQuery('*');
195        } else {
196            $searchquery->setQuery($query);
197        }
198        $searchquery->setFields([
199            'name^9',
200            'authority.name^5',
201            'address.street',
202            'address.postal_code^9'
203        ]);
204        $boolquery->getQuery()->addShould($searchquery);
205        if ($service_csv) {
206            foreach (explode(',', $service_csv) as $service_id) {
207                $filter = new \Elastica\Filter\Term(array(
208                    'services.service' => $service_id
209                ));
210                $boolquery->getFilter()->addMust($filter);
211            }
212        }
213        $mainquery->setQuery($boolquery);
214        $resultList = $this->access()
215            ->getIndex()
216            ->getType('location')
217            ->search($mainquery, $limit);
218        return $this->access()
219            ->fromAuthority()
220            ->fromLocationResults($resultList);
221    }
222
223    protected function fetchGeoJsonLocations($category, $getAll)
224    {
225        $query = new \Elastica\Query();
226        $query->setSource(['id', 'name', 'address.*', 'geo.*', 'meta.*', 'category.*']);
227
228        $filter =  new \Elastica\Query\MatchAll();
229
230        if (!empty($category) && false === $getAll) {
231            $filter = new \Elastica\Query\BoolQuery();
232            $termFilter = new \Elastica\Query\Term(['category.identifier' => $category]);
233            $filter->addMust($termFilter);
234        }
235        $query->setQuery($filter);
236        $query->addSort(['office' => ['order' => 'asc']]);
237        $query->addSort(['name' => ['order' => 'asc']]);
238        $resultList = $this->access()
239            ->getIndex()
240            ->getType('location')
241            ->search($query, 1000)
242        ;
243        return $resultList;
244    }
245
246    /**
247     * @todo Refactoring required, functions in this class should return entities, not JSON data
248     *
249     * @psalm-api
250     *
251     * @return ((string|string[])[]|bool|mixed|string)[][]
252     *
253     */
254    public function fetchGeoJson($category = null, $getAll = false)
255    {
256        $resultList = $this->fetchGeoJsonLocations($category, $getAll);
257        $geoJson = [];
258        // TODO check refactoring: the following lines were ineffective cause the line $geoJson=[] happened afterwards
259        //if (!empty($category) && false === $getAll) {
260        //    $geoJson['category'] = $category;
261        //}
262        foreach ($resultList as $result) {
263            $location = new Entity($result->getData());
264            if (empty($location['category']['identifier'])) {
265                continue;
266            }
267            if (!isset($geoJson[$location['category']['identifier']])) {
268                $geoJson[$location['category']['identifier']] = [
269                    'name' => $location['category']['name'],
270                    'type' => 'cluster',
271                    'active' => (
272                        !empty($category)
273                        && $category == $location['category']['identifier'] ? true : (
274                            !empty($category) && $category != $location['category']['identifier'] ? false : true
275                        )
276                    ),
277                    'data' => ['type' => 'FeatureCollection', 'features' => []]
278                ];
279            }
280            $geoJson[$location['category']['identifier']]['data']['features'][] = $location->getGeoJson();
281        }
282
283        return $geoJson;
284    }
285
286    /**
287     * @psalm-api
288     *
289     * @return Collection
290     */
291    public function fetchLocationsForCompilation($authoritys = [], $locations = [])
292    {
293        $limit = 1000;
294
295        $localeFilter = new \Elastica\Query\Term(array(
296            'meta.locale' => $this->locale
297        ));
298
299        $boolquery = new \Elastica\Query\BoolQuery();
300        $boolquery->addMust($localeFilter);
301
302        if (!empty($authoritys)) {
303            $authorityFilter = new \Elastica\Query\Terms('authority.id', $authoritys);
304            $boolquery->addMust($authorityFilter);
305        }
306        if (!empty($locations)) {
307            $locationFilter = new \Elastica\Query\Terms('id', $locations);
308            $boolquery->addMust($locationFilter);
309        }
310
311        $query = \Elastica\Query::create($boolquery);
312        $query->addSort(['sort' => 'asc']);
313        #print_r(json_encode($query->toArray()));exit;
314        $resultList = $this
315            ->access()
316            ->getIndex()
317            ->getType('location')
318            ->search($query, $limit)
319        ;
320
321        $locationList = new Collection();
322        foreach ($resultList as $result) {
323            $location = new Entity($result->getData());
324            $locationList[$location['id']] = $location;
325        }
326        return $locationList;
327    }
328}