We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.
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
![]() |
|||
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((int) $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 |