Passed
Pull Request — master (#123)
by
unknown
04:26
created

SearchInDocument::process()   B

Complexity

Conditions 8
Paths 4

Size

Total Lines 66
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 38
c 0
b 0
f 0
nc 4
nop 2
dl 0
loc 66
rs 8.0675

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
5
 *
6
 * This file is part of the Kitodo and TYPO3 projects.
7
 *
8
 * @license GNU General Public License version 3 or later.
9
 * For the full copyright and license information, please read the
10
 * LICENSE.txt file that was distributed with this source code.
11
 */
12
13
namespace Kitodo\Dlf\Middleware;
14
15
use Kitodo\Dlf\Common\Helper;
16
use Kitodo\Dlf\Common\Solr\Solr;
17
use Kitodo\Dlf\Common\Solr\SearchResult\ResultDocument;
18
use Psr\Http\Message\ResponseInterface;
19
use Psr\Http\Message\ServerRequestInterface;
20
use Psr\Http\Server\MiddlewareInterface;
21
use Psr\Http\Server\RequestHandlerInterface;
22
use TYPO3\CMS\Core\Http\Response;
23
use TYPO3\CMS\Core\Site\SiteFinder;
24
use TYPO3\CMS\Core\Utility\GeneralUtility;
25
26
/**
27
 * Search in document Middleware for plugin 'Search' of the 'dlf' extension
28
 *
29
 * @package TYPO3
30
 * @subpackage dlf
31
 *
32
 * @access public
33
 */
34
class SearchInDocument implements MiddlewareInterface
35
{
36
    /**
37
     * This holds the solr instance
38
     *
39
     * @var \Kitodo\Dlf\Common\Solr\Solr
40
     * @access private
41
     */
42
    private $solr;
43
44
    /**
45
     * This holds the solr fields
46
     *
47
     * @var array
48
     * @access private
49
     */
50
    private $fields;
51
52
    /**
53
     * The process method of the middleware.
54
     *
55
     * @access public
56
     *
57
     * @param ServerRequestInterface $request
58
     * @param RequestHandlerInterface $handler
59
     *
60
     * @return ResponseInterface JSON response of search suggestions
61
     */
62
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
63
    {
64
        $response = $handler->handle($request);
65
        // Get input parameters and decrypt core name.
66
        $parameters = $request->getParsedBody();
67
        // Return if not this middleware
68
        if (!isset($parameters['middleware']) || ($parameters['middleware'] != 'dlf/search-in-document')) {
69
            return $response;
70
        }
71
72
        $encrypted = (string) $parameters['encrypted'];
73
        if (empty($encrypted)) {
74
            throw new \InvalidArgumentException('No valid parameter passed: ' . $parameters['middleware'] . '  ' . $parameters['encrypted'] . '!', 1580585079);
75
        }
76
77
        $output = [
78
            'documents' => [],
79
            'numFound' => 0
80
        ];
81
82
        $core = Helper::decrypt($encrypted);
83
84
        // Perform Solr query.
85
        $this->solr = Solr::getInstance($core);
86
        $this->fields = Solr::getFields();
87
88
        if ($this->solr->ready) {
89
            $result = $this->executeSolrQuery($parameters);
0 ignored issues
show
Bug introduced by
It seems like $parameters can also be of type object; however, parameter $parameters of Kitodo\Dlf\Middleware\Se...ent::executeSolrQuery() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

89
            $result = $this->executeSolrQuery(/** @scrutinizer ignore-type */ $parameters);
Loading history...
90
            /** @scrutinizer ignore-call */
91
            $output['numFound'] = $result->getNumFound(); // @phpstan-ignore-line
92
            $data = $result->getData();
93
            $highlighting = $data['ocrHighlighting'];
94
95
            $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
96
            $site = $siteFinder->getSiteByPageId($parameters['pid']);
97
98
            // @phpstan-ignore-next-line
99
            foreach ($result as $record) {
100
                $resultDocument = new ResultDocument($record, $highlighting, $this->fields);
101
102
                $url = (string) $site->getRouter()->generateUri(
103
                    $parameters['pid'],
104
                    [
105
                        'tx_dlf[id]' => !empty($resultDocument->getUid()) ? $resultDocument->getUid() : $parameters['uid'],
106
                        'tx_dlf[page]' => $resultDocument->getPage(),
107
                        'tx_dlf[highlight_word]' => $parameters['q']
108
                    ]
109
                );
110
111
                $document = [
112
                    'id' => $resultDocument->getId(),
113
                    'uid' => !empty($resultDocument->getUid()) ? $resultDocument->getUid() : $parameters['uid'],
114
                    'page' => $resultDocument->getPage(),
115
                    'snippet' => $resultDocument->getSnippets(),
116
                    'highlight' => $resultDocument->getHighlightsIds(),
117
                    'url' => $url
118
                ];
119
                $output['documents'][] = $document;
120
            }
121
        }
122
123
        // Create response object.
124
        /** @var Response $response */
125
        $response = GeneralUtility::makeInstance(Response::class);
126
        $response->getBody()->write(json_encode($output));
127
        return $response;
128
    }
129
130
    /**
131
     * Execute SOLR query.
132
     *
133
     * @access private
134
     *
135
     * @param array $parameters array of query parameters
136
     *
137
     * @return \Solarium\Core\Query\Result\ResultInterface result
138
     */
139
    private function executeSolrQuery($parameters)
140
    {
141
        $query = $this->solr->service->createSelect();
142
        $query->setFields([$this->fields['id'], $this->fields['uid'], $this->fields['page']]);
143
        $query->setQuery($this->getQuery($parameters));
144
        $query->setStart(intval($parameters['start']))->setRows(20);
145
        $query->addSort($this->fields['page'], $query::SORT_ASC);
146
        $query->getHighlighting();
147
        $solrRequest = $this->solr->service->createRequest($query);
148
149
        // it is necessary to add the custom parameters to the request
150
        // because query object doesn't allow custom parameters
151
152
        // field for which highlighting is going to be performed,
153
        // is required if you want to have OCR highlighting
154
        $solrRequest->addParam('hl.ocr.fl', $this->fields['fulltext']);
155
         // return the coordinates of highlighted search as absolute coordinates
156
        $solrRequest->addParam('hl.ocr.absoluteHighlights', 'on');
157
        // max amount of snippets for a single page
158
        $solrRequest->addParam('hl.snippets', '40');
159
        // we store the fulltext on page level and can disable this option
160
        $solrRequest->addParam('hl.ocr.trackPages', 'off');
161
162
        $response = $this->solr->service->executeRequest($solrRequest);
163
        return $this->solr->service->createResult($query, $response);
164
    }
165
166
    /**
167
     * Build SOLR query for given fields and parameters.
168
     *
169
     * @access private
170
     *
171
     * @param array $parameters parsed from request body
172
     *
173
     * @return string SOLR query
174
     */
175
    private function getQuery(array $parameters): string
176
    {
177
        return $this->fields['fulltext'] . ':(' . Solr::escapeQuery((string) $parameters['q']) . ') AND ' . $this->fields['uid'] . ':' . $this->getUid($parameters['uid']);
178
    }
179
180
    /**
181
     * Check if uid is number, if yes convert it to int,
182
     * otherwise leave uid not changed.
183
     *
184
     * @access private
185
     *
186
     * @param string $uid of the document
187
     *
188
     * @return int|string uid of the document
189
     */
190
    private function getUid(string $uid)
191
    {
192
        return is_numeric($uid) ? intval($uid) : $uid;
193
    }
194
}
195