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
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((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 |