Passed
Pull Request — master (#96)
by Ralf
04:45
created

AbstractSearchController   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 235
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 89
dl 0
loc 235
rs 9.36
c 0
b 0
f 0
wmc 38

7 Methods

Rating   Name   Duplication   Size   Complexity  
A searchFulltext() 0 17 2
C extendedSearch() 0 40 15
A getResultList() 0 7 1
C resultsFilter() 0 76 13
A escapeQuery() 0 12 1
A formatDate() 0 5 1
A convertFormDate() 0 14 5
1
<?php
2
namespace EWW\Dpf\Controller;
3
4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
 * It is free software; you can redistribute it and/or modify it under
8
 * the terms of the GNU General Public License, either version 2
9
 * of the License, or any later version.
10
 *
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
 * The TYPO3 project - inspiring people to share!
15
 */
16
17
use TYPO3\CMS\Core\Utility\GeneralUtility;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Core\Utility\GeneralUtility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use EWW\Dpf\Services\ElasticSearch;
19
20
abstract class AbstractSearchController extends \EWW\Dpf\Controller\AbstractController
21
{
22
    // search terms
23
    private static $terms   = ['_id', 'OWNER_ID', 'submitter', 'project'];
24
25
    // search matches
26
    private static $matches = ['title', 'abstract', 'author', 'language', 'tag', 'corporation', 'doctype', 'collections'];
27
28
    /**
29
     * get results from elastic search
30
     * @param  array $query elasticsearch search query
31
     * @return array        results
32
     */
33
    public function getResultList($query, $type)
34
    {
35
36
        $elasticSearch = $this->objectManager->get(ElasticSearch::class);
37
        $results = $elasticSearch->search($query, $type);
38
39
        return $results;
40
    }
41
42
    /**
43
     * prepare fulltext query
44
     * @param  string $searchString
45
     * @return array query
46
     */
47
    public function searchFulltext($searchString)
48
    {
49
        // don't return query if searchString is empty
50
        if (empty($searchString)) {
51
            return null;
52
        }
53
54
        $searchString = $this->escapeQuery(trim($searchString));
55
56
        $query['body']['query']['bool']['should'][0]['query_string']['query']                       = $searchString;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$query was never initialized. Although not strictly required by PHP, it is generally a good practice to add $query = array(); before regardless.
Loading history...
57
        $query['body']['query']['bool']['should'][1]['has_child']['query']['query_string']['query'] = $searchString;
58
        $query['body']['query']['bool']['minimum_should_match'] = "1"; // 1
59
        $query['body']['query']['bool']['should'][1]['has_child']['child_type'] = "datastream"; // 1
60
61
        $query = $this->resultsFilter($query, false);
62
63
        return $query;
64
65
    }
66
67
    /**
68
     * build array for elasticsearch
69
     * @return array Elasticsearch query array
70
     */
71
    public function extendedSearch($searchArray = array())
72
    {
73
74
        $query  = array();
75
        $filter = array();
76
        foreach ($searchArray as $key => $qry) {
77
            $qry = trim($qry);
78
79
            if (!empty($qry) && in_array($key, self::$matches)) {
80
81
                $query['body']['query']['bool']['must'][] = array('match' => array($key => $qry));
82
83
            } elseif (!empty($qry) && in_array($key, self::$terms)) {
84
85
                $query['body']['query']['bool']['must'][] = array('term' => array($key => $qry));
86
87
            } elseif (!empty($qry) && $key == 'from') {
88
89
                if ($dateTime = $this->convertFormDate($qry, false)) {
90
                    $filter['gte'] = $dateTime->format('Y-m-d');
91
                }
92
93
            } elseif (!empty($qry) && $key == 'till') {
94
95
                if ($dateTime = $this->convertFormDate($qry, true)) {
96
                    $filter['lte'] = $dateTime->format('Y-m-d');
97
                }
98
99
            }
100
        }
101
102
        if (isset($filter['gte']) || isset($filter['lte'])) {
103
104
            $query['body']['query']['bool']['must'][] = array('range' => array('distribution_date' => $filter));
105
106
        }
107
108
        $showDeleted = ($searchArray['showDeleted'] == 'true') ? true : false;
109
        $query = $this->resultsFilter($query, $showDeleted);
110
        return $query;
111
112
    }
113
114
    /**
115
     * build array for elasticsearch resultfilter
116
     * @param array Elasticsearch query array
117
     * @return array Elasticsearch queryFilter array
118
     */
119
    public function resultsFilter($query, $showDeleted = false)
120
    {
121
122
        $queryFilter = array();
123
124
        // Frontend only
125
        $searchResultsFilter = $this->settings['searchResultsFilter'];
126
        if(!empty($searchResultsFilter)) {
127
128
            // add doctypes
129
            if($searchResultsFilter['doctype']) {
130
131
                $uids = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $searchResultsFilter['doctype']);
132
                $documentTypeRepository = $this->documentTypeRepository;
133
                $documentTypes = array();
134
                foreach($uids as $uid) {
135
                    $documentType = $documentTypeRepository->findByUid($uid);
136
                    $documentTypes[] = $documentType->getName();
137
                };
138
                $searchResultsFilter['doctype'] = implode(',', $documentTypes);
139
            }
140
141
            // add date filter
142
            $dateFilter = array();
143
            if ($searchResultsFilter['from']) {
144
145
                $from     = date('d.m.Y', $searchResultsFilter['from']);
146
                $dateTime = $this->convertFormDate($from, false);
147
                $dateFilter['gte'] = $dateTime->format('Y-m-d');
148
                unset($searchResultsFilter['from']);
149
150
            }
151
152
            if ($searchResultsFilter['till']) {
153
154
                $till          = date('d.m.Y', $searchResultsFilter['till']);
155
                $dateTime = $this->convertFormDate($till, true);
156
                $dateFilter['lte'] = $dateTime->format('Y-m-d');
157
                unset($searchResultsFilter['till']);
158
159
            }
160
161
            if (isset($dateFilter['gte']) || isset($dateFilter['lte'])) {
162
163
                $queryFilter['body']['query']['bool']['must'][] = array('range' => array('distribution_date' => $dateFilter));
164
165
            }
166
167
            foreach ($searchResultsFilter as $key => $qry) {
168
169
                if(!empty($qry)) {
170
                    $queryFilter['body']['query']['bool']['must'][] = array('match' => array($key => $qry));
171
                }
172
173
            }
174
175
        }
176
177
        // document must be active
178
        if($showDeleted == false) {
179
180
            $queryFilter['body']['query']['bool']['must'][]['term']['STATE'] = 'A';
181
182
        };
183
184
        // add OWNER_ID if present
185
        $clients = $this->clientRepository->findAll();
186
        if ($clients) {
187
            $client = $clients->getFirst();
188
            if ($client) {
189
                $queryFilter['body']['query']['bool']['must'][]['term']['OWNER_ID'] = $client->getOwnerId();
190
            }
191
        }
192
193
        $queryFilter = array_merge_recursive($queryFilter, $query);
194
        return $queryFilter;
195
    }
196
197
    /**
198
     * Convert date from form input into DateTime object.
199
     *
200
     * A 4 character string is taken for a year and the returning
201
     * DateTime object is supplemented with either the 01. Jan or 31. Dec
202
     * depending on the $intervalEnd parameter. This allows querying time
203
     * intervals like `2000 to 2003`.
204
     *
205
     * @param  string    $dateString  Date literal from form
206
     * @param  bool      $intervalEnd Fills missing values with the maximum possible date if true
207
     * @return DateTime               Determined date
0 ignored issues
show
Bug introduced by
The type EWW\Dpf\Controller\DateTime was not found. Did you mean DateTime? If so, make sure to prefix the type with \.
Loading history...
208
     */
209
    public function convertFormDate($dateString, $intervalEnd = false)
210
    {
211
        try {
212
            if (strlen($dateString) == 4) {
213
                // assuming year
214
                $year  = $dateString;
215
                $month = $intervalEnd ? "12" : "01";
216
                $day   = $intervalEnd ? "31" : "01";
217
                return new \DateTime("$year-$month-$day");
0 ignored issues
show
Bug Best Practice introduced by
The expression return new DateTime($year.'-'.$month.'-'.$day) returns the type DateTime which is incompatible with the documented return type EWW\Dpf\Controller\DateTime.
Loading history...
218
            } else {
219
                return new \DateTime($dateString);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new DateTime($dateString) returns the type DateTime which is incompatible with the documented return type EWW\Dpf\Controller\DateTime.
Loading history...
220
            }
221
        } catch (\Exception $_) {
222
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type EWW\Dpf\Controller\DateTime.
Loading history...
223
        }
224
    }
225
226
    /**
227
     * escapes lucene reserved characters from string
228
     * @param $string
229
     * @return mixed
230
     */
231
    private function escapeQuery($string)
232
    {
233
        $luceneReservedCharacters = preg_quote('+-&|!(){}[]^"~?:\\');
234
        $string                   = preg_replace_callback(
235
            '/([' . $luceneReservedCharacters . '])/',
236
            function ($matches) {
237
                return '\\' . $matches[0];
238
            },
239
            $string
240
        );
241
242
        return $string;
243
    }
244
245
    /**
246
     * converts a date from dd.mm.yy to yyyy-dd-mm
247
     * @param $date
248
     * @return string
249
     */
250
    public function formatDate($date)
251
    {
252
        // convert date from dd.mm.yyy to yyyy-dd-mm
253
        $date = explode(".", $date);
254
        return $date[2] . '-' . $date[1] . '-' . $date[0];
255
    }
256
}
257