Passed
Pull Request — master (#98)
by
unknown
02:40
created

AbstractSearchController::getResultList()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
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
    protected function initializeView(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view)
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Mvc\View\ViewInterface 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...
30
    {
31
        parent::initializeView($view);
32
33
        if (TYPO3_MODE === 'BE') {
0 ignored issues
show
Bug introduced by
The constant EWW\Dpf\Controller\TYPO3_MODE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
34
            $selectedPageId = (int) \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('id');
35
            if ($selectedPageId) {
36
                $client = $this->clientRepository->findAll()->current();
37
            }
38
            if (!$client) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $client does not seem to be defined for all execution paths leading up to this point.
Loading history...
39
                $this->redirect('list','Document');
40
            } else {
41
            }
42
        }
43
    }
44
45
    /**
46
     * get results from elastic search
47
     * @param  array $query elasticsearch search query
48
     * @return array        results
49
     */
50
    public function getResultList($query, $type)
51
    {
52
53
        $elasticSearch = $this->objectManager->get(ElasticSearch::class);
54
        $results = $elasticSearch->search($query, $type);
55
56
        return $results;
57
    }
58
59
    /**
60
     * prepare fulltext query
61
     * @param  string $searchString
62
     * @return array query
63
     */
64
    public function searchFulltext($searchString)
65
    {
66
        // don't return query if searchString is empty
67
        if (empty($searchString)) {
68
            return null;
69
        }
70
71
        $searchString = $this->escapeQuery(trim($searchString));
72
73
        $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...
74
        $query['body']['query']['bool']['should'][1]['has_child']['query']['query_string']['query'] = $searchString;
75
        $query['body']['query']['bool']['minimum_should_match'] = "1"; // 1
76
        $query['body']['query']['bool']['should'][1]['has_child']['child_type'] = "datastream"; // 1
77
78
        $query = $this->resultsFilter($query, false);
79
80
        return $query;
81
82
    }
83
84
    /**
85
     * build array for elasticsearch
86
     * @return array Elasticsearch query array
87
     */
88
    public function extendedSearch($searchArray = array())
89
    {
90
91
        $query  = array();
92
        $filter = array();
93
        foreach ($searchArray as $key => $qry) {
94
            $qry = trim($qry);
95
96
            if (!empty($qry) && in_array($key, self::$matches)) {
97
98
                $query['body']['query']['bool']['must'][] = array('match' => array($key => $qry));
99
100
            } elseif (!empty($qry) && in_array($key, self::$terms)) {
101
102
                $query['body']['query']['bool']['must'][] = array('term' => array($key => $qry));
103
104
            } elseif (!empty($qry) && $key == 'from') {
105
106
                if ($dateTime = $this->convertFormDate($qry, false)) {
107
                    $filter['gte'] = $dateTime->format('Y-m-d');
108
                }
109
110
            } elseif (!empty($qry) && $key == 'till') {
111
112
                if ($dateTime = $this->convertFormDate($qry, true)) {
113
                    $filter['lte'] = $dateTime->format('Y-m-d');
114
                }
115
116
            }
117
        }
118
119
        if (isset($filter['gte']) || isset($filter['lte'])) {
120
121
            $query['body']['query']['bool']['must'][] = array('range' => array('distribution_date' => $filter));
122
123
        }
124
125
        $showDeleted = ($searchArray['showDeleted'] == 'true') ? true : false;
126
        $query = $this->resultsFilter($query, $showDeleted);
127
        return $query;
128
129
    }
130
131
    /**
132
     * build array for elasticsearch resultfilter
133
     * @param array Elasticsearch query array
134
     * @return array Elasticsearch queryFilter array
135
     */
136
    public function resultsFilter($query, $showDeleted = false)
137
    {
138
139
        $queryFilter = array();
140
141
        // Frontend only
142
        $searchResultsFilter = $this->settings['searchResultsFilter'];
143
        if(!empty($searchResultsFilter)) {
144
145
            // add doctypes
146
            if($searchResultsFilter['doctype']) {
147
148
                $uids = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $searchResultsFilter['doctype']);
149
                $documentTypeRepository = $this->documentTypeRepository;
150
                $documentTypes = array();
151
                foreach($uids as $uid) {
152
                    $documentType = $documentTypeRepository->findByUid($uid);
153
                    $documentTypes[] = $documentType->getName();
154
                };
155
                $searchResultsFilter['doctype'] = implode(',', $documentTypes);
156
            }
157
158
            // add date filter
159
            $dateFilter = array();
160
            if ($searchResultsFilter['from']) {
161
162
                $from     = date('d.m.Y', $searchResultsFilter['from']);
163
                $dateTime = $this->convertFormDate($from, false);
164
                $dateFilter['gte'] = $dateTime->format('Y-m-d');
165
                unset($searchResultsFilter['from']);
166
167
            }
168
169
            if ($searchResultsFilter['till']) {
170
171
                $till          = date('d.m.Y', $searchResultsFilter['till']);
172
                $dateTime = $this->convertFormDate($till, true);
173
                $dateFilter['lte'] = $dateTime->format('Y-m-d');
174
                unset($searchResultsFilter['till']);
175
176
            }
177
178
            if (isset($dateFilter['gte']) || isset($dateFilter['lte'])) {
179
180
                $queryFilter['body']['query']['bool']['must'][] = array('range' => array('distribution_date' => $dateFilter));
181
182
            }
183
184
            foreach ($searchResultsFilter as $key => $qry) {
185
186
                if(!empty($qry)) {
187
                    $queryFilter['body']['query']['bool']['must'][] = array('match' => array($key => $qry));
188
                }
189
190
            }
191
192
        }
193
194
        // document must be active
195
        if($showDeleted == false) {
196
197
            $queryFilter['body']['query']['bool']['must'][]['term']['STATE'] = 'A';
198
199
        };
200
201
        // add OWNER_ID if present
202
        $clients = $this->clientRepository->findAll();
203
        if ($clients) {
204
            $client = $clients->getFirst();
205
            if ($client) {
206
                $queryFilter['body']['query']['bool']['must'][]['term']['OWNER_ID'] = $client->getOwnerId();
207
            }
208
        }
209
210
        $queryFilter = array_merge_recursive($queryFilter, $query);
211
        return $queryFilter;
212
    }
213
214
    /**
215
     * Convert date from form input into DateTime object.
216
     *
217
     * A 4 character string is taken for a year and the returning
218
     * DateTime object is supplemented with either the 01. Jan or 31. Dec
219
     * depending on the $intervalEnd parameter. This allows querying time
220
     * intervals like `2000 to 2003`.
221
     *
222
     * @param  string    $dateString  Date literal from form
223
     * @param  bool      $intervalEnd Fills missing values with the maximum possible date if true
224
     * @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...
225
     */
226
    public function convertFormDate($dateString, $intervalEnd = false)
227
    {
228
        try {
229
            if (strlen($dateString) == 4) {
230
                // assuming year
231
                $year  = $dateString;
232
                $month = $intervalEnd ? "12" : "01";
233
                $day   = $intervalEnd ? "31" : "01";
234
                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...
235
            } else {
236
                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...
237
            }
238
        } catch (\Exception $_) {
239
            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...
240
        }
241
    }
242
243
    /**
244
     * escapes lucene reserved characters from string
245
     * @param $string
246
     * @return mixed
247
     */
248
    private function escapeQuery($string)
249
    {
250
        $luceneReservedCharacters = preg_quote('+-&|!(){}[]^"~?:\\');
251
        $string                   = preg_replace_callback(
252
            '/([' . $luceneReservedCharacters . '])/',
253
            function ($matches) {
254
                return '\\' . $matches[0];
255
            },
256
            $string
257
        );
258
259
        return $string;
260
    }
261
262
    /**
263
     * converts a date from dd.mm.yy to yyyy-dd-mm
264
     * @param $date
265
     * @return string
266
     */
267
    public function formatDate($date)
268
    {
269
        // convert date from dd.mm.yyy to yyyy-dd-mm
270
        $date = explode(".", $date);
271
        return $date[2] . '-' . $date[1] . '-' . $date[0];
272
    }
273
}
274