[!!!][TASK] Rewrite backend modules of indexed_search
[Packages/TYPO3.CMS.git] / typo3 / sysext / indexed_search / Classes / Controller / AdministrationController.php
1 <?php
2 namespace TYPO3\CMS\IndexedSearch\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\Authentication\BackendUserAuthentication;
18 use TYPO3\CMS\Core\Database\DatabaseConnection;
19 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
20 use TYPO3\CMS\Extbase\Mvc\Web\Request as WebRequest;
21 use TYPO3\CMS\IndexedSearch\Domain\Repository\AdministrationRepository;
22 use TYPO3\CMS\Backend\Utility\BackendUtility;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24 use TYPO3\CMS\IndexedSearch\Indexer;
25 use TYPO3\CMS\Lang\LanguageService;
26
27 /**
28 * Administration controller
29 */
30 class AdministrationController extends ActionController {
31
32 /**
33 * @var AdministrationRepository
34 */
35 protected $administrationRepository;
36
37 /**
38 * @var int Current page id
39 */
40 protected $pageUid = 0;
41
42 /**
43 * @var int Max lists per page
44 */
45 protected $maxListPerPage = 50;
46
47 /**
48 * @var array External parsers
49 */
50 protected $external_parsers = array();
51
52 /**
53 * @var array Configuration defined in the Extension Manager
54 */
55 protected $indexerConfig = array();
56
57 /**
58 * @var bool is metaphone enabled
59 */
60 protected $enableMetaphoneSearch = FALSE;
61
62 /**
63 * Indexer object
64 *
65 * @var \TYPO3\CMS\IndexedSearch\Indexer
66 */
67 protected $indexer;
68
69 /**
70 * Function will be called before every other action
71 *
72 * @return void
73 */
74 public function initializeAction() {
75 $this->pageUid = (int)GeneralUtility::_GET('id');
76 $this->maxListPerPage = GeneralUtility::_GP('listALL') ? 100000 : 100;
77 $this->indexerConfig = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['indexed_search']);
78 $this->enableMetaphoneSearch = (bool)$this->indexerConfig['enableMetaphoneSearch'];
79 $this->indexer = GeneralUtility::makeInstance(Indexer::class);
80
81 parent::initializeAction();
82 }
83
84 /**
85 * Override the action name if found in the uc of the user
86 *
87 * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request
88 * @param \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response
89 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
90 */
91 public function processRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request, \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response) {
92 $vars = GeneralUtility::_GET('tx_indexedsearch_web_indexedsearchisearch');
93
94 $beUser = $this->getBackendUserAuthentication();
95 if (is_array($vars) && isset($vars['action']) && method_exists($this, $vars['action'] . 'Action')) {
96 $action = $vars['action'];
97
98 switch($action) {
99 case 'saveStopwordsKeywords':
100 $action = 'statisticDetails';
101 break;
102 case 'deleteIndexedItem':
103 $action = 'statistic';
104 break;
105 }
106
107 $beUser->uc['indexed_search']['action'] = $action;
108 $beUser->uc['indexed_search']['arguments'] = $request->getArguments();
109 $beUser->writeUC();
110 } elseif (isset($beUser->uc['indexed_search']['action'])) {
111 if ($request instanceof WebRequest) {
112 $request->setControllerActionName($beUser->uc['indexed_search']['action']);
113 }
114 if (isset($beUser->uc['indexed_search']['arguments'])) {
115 $request->setArguments($beUser->uc['indexed_search']['arguments']);
116 }
117 }
118
119 parent::processRequest($request, $response);
120 }
121
122 /**
123 * @param \TYPO3\CMS\IndexedSearch\Domain\Repository\AdministrationRepository $administrationRepository
124 * @return void
125 */
126 public function injectAdministrationRepository(AdministrationRepository $administrationRepository) {
127 $this->administrationRepository = $administrationRepository;
128 }
129
130 /**
131 * Index action contains the most important statistics
132 *
133 * @return void
134 */
135 public function indexAction() {
136 $this->view->assignMultiple(array(
137 'records' => $this->administrationRepository->getRecordsNumbers(),
138 'phash' => $this->administrationRepository->getPageHashTypes()
139 ));
140
141 if ($this->pageUid) {
142 $last24hours = ' AND tstamp > ' . ($GLOBALS['EXEC_TIME'] - 24 * 60 * 60);
143 $last30days = ' AND tstamp > ' . ($GLOBALS['EXEC_TIME'] - 30 * 24 * 60 * 60);
144
145 $this->view->assignMultiple(array(
146 'pageUid' => $this->pageUid,
147 'all' => $this->administrationRepository->getGeneralSearchStatistic('', $this->pageUid),
148 'last24hours' => $this->administrationRepository->getGeneralSearchStatistic($last24hours, $this->pageUid),
149 'last30days' => $this->administrationRepository->getGeneralSearchStatistic($last30days, $this->pageUid),
150 ));
151 }
152 }
153
154 /**
155 * Statistics for pages
156 *
157 * @return void
158 */
159 public function pagesAction() {
160 $this->view->assign('records', $this->administrationRepository->getPageStatistic());
161 }
162
163 /**
164 * Statistics for external documents
165 *
166 * @return void
167 */
168 public function externalDocumentsAction() {
169 $this->view->assign('records', $this->administrationRepository->getExternalDocumentsStatistic());
170 }
171
172 /**
173 * Statistics for a given page hash
174 *
175 * @param int $pageHash
176 * @return void
177 */
178 public function statisticDetailsAction($pageHash = 0) {
179 $pageHash = (int)$pageHash;
180 $db = $this->getDatabaseConnection();
181 $pageHashRow = $db->exec_SELECTgetSingleRow('*', 'index_phash', 'phash = ' . (int)$pageHash);
182
183 if (!is_array($pageHashRow)) {
184 $this->redirect('statistic');
185 }
186
187 $debugRow = $db->exec_SELECTgetRows('*', 'index_debug', 'phash = ' . (int)$pageHash);
188 $debugInfo = array();
189 $lexer = '';
190 if (is_array($debugRow)) {
191 $debugInfo = unserialize($debugRow[0]['debuginfo']);
192 $lexer = $debugInfo['lexer'];
193 unset($debugInfo['lexer']);
194 }
195 $pageRecord = BackendUtility::getRecord('pages', $pageHashRow['data_page_id']);
196 $keywords = is_array($pageRecord) ? array_flip(GeneralUtility::trimExplode(',', $pageRecord['keywords'], TRUE)) : array();
197 $wordRecords = $db->exec_SELECTgetRows(
198 'index_words.*, index_rel.*',
199 'index_rel, index_words',
200 'index_rel.phash = ' . (int)$pageHash . ' AND index_words.wid = index_rel.wid',
201 '',
202 'index_words.baseword'
203 );
204 foreach($wordRecords as $id => $row) {
205 if (isset($keywords[$row['baseword']])) {
206 $wordRecords[$id]['is_keyword'] = TRUE;
207 }
208 }
209 $metaphoneRows = $metaphone = array();
210 if ($this->enableMetaphoneSearch && is_array($wordRecords)) {
211 // Group metaphone hash
212 foreach ($wordRecords as $row) {
213 $metaphoneRows[$row['metaphone']][] = $row['baseword'];
214 }
215
216 foreach ($metaphoneRows as $hash => $words) {
217 if (count($words) > 1) {
218 $metaphone[] = array(
219 'metaphone' => $this->indexer->metaphone($words[0], 1), $hash,
220 'words' => $words,
221 'hash' => $hash
222 );
223 }
224 }
225 }
226 $this->view->assignMultiple(array(
227 'phash' => $pageHash,
228 'phashRow' => $pageHashRow,
229 'words' => $wordRecords,
230 'sections' => $db->exec_SELECTgetRows(
231 '*',
232 'index_section',
233 'index_section.phash = ' . (int)$pageHash
234 ),
235 'topCount' => $db->exec_SELECTgetRows(
236 'index_words.baseword, index_words.metaphone, index_rel.*',
237 'index_rel, index_words',
238 'index_rel.phash = ' . (int)$pageHash . ' AND index_words.wid = index_rel.wid
239 AND index_words.is_stopword=0',
240 '',
241 'index_rel.count DESC',
242 '20'
243 ),
244 'topFrequency' => $db->exec_SELECTgetRows(
245 'index_words.baseword, index_words.metaphone, index_rel.*',
246 'index_rel, index_words',
247 'index_rel.phash = ' . (int)$pageHash . ' AND index_words.wid = index_rel.wid
248 AND index_words.is_stopword=0',
249 '',
250 'index_rel.freq DESC',
251 '20'
252 ),
253 'debug' => $debugInfo,
254 'lexer' => $lexer,
255 'metaphone' => $metaphone,
256 'page' => $pageRecord,
257 'keywords' => $keywords
258 ));
259 }
260
261 /**
262 * Save stop words and keywords
263 *
264 * @param string $pageHash
265 * @param int $pageId
266 * @param array $stopwords
267 * @param array $keywords
268 * @return void
269 */
270 public function saveStopwordsKeywordsAction($pageHash, $pageId, $stopwords = array(), $keywords = array()) {
271 if ($this->getBackendUserAuthentication()->isAdmin()) {
272 if (is_array($stopwords) && !empty($stopwords)) {
273 $this->administrationRepository->saveStopWords($stopwords);
274 }
275 if (is_array($keywords) && !empty($keywords)) {
276 $this->administrationRepository->saveKeywords($keywords, $pageId);
277 }
278 }
279
280 $this->redirect('statisticDetails', NULL, NULL, array('pageHash' => $pageHash));
281 }
282
283 /**
284 * Statistics for a given word id
285 *
286 * @param int $id
287 * @param int $pageHash
288 * @return void
289 */
290 public function wordDetailAction($id = 0, $pageHash = 0) {
291 $rows = $this->getDatabaseConnection()->exec_SELECTgetRows(
292 'index_phash.*, index_section.*, index_rel.*',
293 'index_rel, index_section, index_phash',
294 'index_rel.wid = ' . (int)$id . ' AND index_rel.phash = index_section.phash' . ' AND index_section.phash = index_phash.phash',
295 '',
296 'index_rel.freq DESC'
297 );
298
299 $this->view->assignMultiple(array(
300 'rows' => $rows,
301 'phash' => $pageHash
302 ));
303 }
304
305 /**
306 * General statistics
307 *
308 * @param int $depth
309 * @param string $mode
310 * @return void
311 */
312 public function statisticAction($depth = 1, $mode = 'overview') {
313 if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['external_parsers'])) {
314 foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['external_parsers'] as $extension => $_objRef) {
315 /** @var \TYPO3\CMS\IndexedSearch\FileContentParser $fileContentParser */
316 $fileContentParser = GeneralUtility::getUserObj($_objRef);
317 if ($fileContentParser->softInit($extension)) {
318 $this->external_parsers[$extension] = $fileContentParser;
319 }
320 }
321 }
322 $this->administrationRepository->external_parsers = $this->external_parsers;
323
324 $allLines = $this->administrationRepository->getTree($this->pageUid, $depth, $mode);
325
326 $this->view->assignMultiple(array(
327 'levelTranslations' => explode('|', $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.enterSearchLevels')),
328 'tree' => $allLines,
329 'pageUid' => $this->pageUid,
330 'mode' => $mode,
331 'depth' => $depth
332 ));
333 }
334
335
336 /**
337 * Remove item from index
338 *
339 * @param string $id
340 * @param int $depth
341 * @param string $mode
342 * @return void
343 */
344 public function deleteIndexedItemAction($id, $depth = 1, $mode = 'overview') {
345 $this->administrationRepository->removeIndexedPhashRow($id, $this->pageUid, $depth);
346 $this->redirect('statistic', NULL, NULL, array('depth' => $depth, 'mode' => $mode));
347 }
348
349 /**
350 * @return DatabaseConnection
351 */
352 protected function getDatabaseConnection() {
353 return $GLOBALS['TYPO3_DB'];
354 }
355
356 /**
357 * @return BackendUserAuthentication
358 */
359 protected function getBackendUserAuthentication() {
360 return $GLOBALS['BE_USER'];
361 }
362
363 /**
364 * @return LanguageService
365 */
366 protected function getLanguageService() {
367 return $GLOBALS['LANG'];
368 }
369 }