‪TYPO3CMS  ‪main
AdministrationController.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Http\Message\ResponseInterface;
21 use Psr\Http\Message\ServerRequestInterface;
24 use TYPO3\CMS\Backend\Utility\BackendUtility;
30 use TYPO3\CMS\Core\Imaging\IconSize;
39 
46 {
47  protected int ‪$pageUid = 0;
48  protected array ‪$indexerConfig = [];
49 
50  public function ‪__construct(
51  protected readonly ‪ModuleTemplateFactory $moduleTemplateFactory,
52  protected readonly ‪AdministrationRepository $administrationRepository,
53  protected readonly ‪Indexer $indexer,
54  protected readonly ‪IconFactory $iconFactory,
55  protected readonly ‪ExtensionConfiguration $extensionConfiguration,
56  protected readonly ‪ConnectionPool $connectionPool,
57  ) {}
58 
62  protected function ‪initializeModuleTemplate(ServerRequestInterface ‪$request): ‪ModuleTemplate
63  {
64  $menuItems = [
65  'statistic' => [
66  'controller' => 'Administration',
67  'action' => 'statistic',
68  'label' => $this->‪getLanguageService()->sL('LLL:EXT:indexed_search/Resources/Private/Language/locallang.xlf:administration.menu.statistic'),
69  ],
70  'pages' => [
71  'controller' => 'Administration',
72  'action' => 'pages',
73  'label' => $this->‪getLanguageService()->sL('LLL:EXT:indexed_search/Resources/Private/Language/locallang.xlf:administration.menu.pages'),
74  ],
75  'externalDocuments' => [
76  'controller' => 'Administration',
77  'action' => 'externalDocuments',
78  'label' => $this->‪getLanguageService()->sL('LLL:EXT:indexed_search/Resources/Private/Language/locallang.xlf:administration.menu.externalDocuments'),
79  ],
80  'index' => [
81  'controller' => 'Administration',
82  'action' => 'index',
83  'label' => $this->‪getLanguageService()->sL('LLL:EXT:indexed_search/Resources/Private/Language/locallang.xlf:administration.menu.general'),
84  ],
85  ];
86 
87  ‪$view = $this->moduleTemplateFactory->create(‪$request);
88 
89  $menu = ‪$view->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
90  $menu->setIdentifier('IndexedSearchModuleMenu');
91 
92  $context = '';
93  foreach ($menuItems as $menuItemConfig) {
94  $isActive = $this->request->getControllerActionName() === $menuItemConfig['action'];
95  $menuItem = $menu->makeMenuItem()
96  ->setTitle($menuItemConfig['label'])
97  ->setHref($this->uriBuilder->reset()->uriFor($menuItemConfig['action'], [], $menuItemConfig['controller']))
98  ->setActive($isActive);
99  $menu->addMenuItem($menuItem);
100  if ($isActive) {
101  $context = $menuItemConfig['label'];
102  }
103  }
104 
105  ‪$view->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu);
106  ‪$view->setTitle(
107  $this->‪getLanguageService()->sL('LLL:EXT:indexed_search/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'),
108  $context
109  );
110 
111  $permissionClause = $this->‪getBackendUserAuthentication()->getPagePermsClause(‪Permission::PAGE_SHOW);
112  $pageRecord = BackendUtility::readPageAccess($this->pageUid, $permissionClause);
113  if ($pageRecord) {
114  ‪$view->getDocHeaderComponent()->setMetaInformation($pageRecord);
115  }
116  ‪$view->setFlashMessageQueue($this->‪getFlashMessageQueue());
117 
118  return ‪$view;
119  }
120 
124  protected function ‪initializeAction()
125  {
126  $this->pageUid = (int)($this->request->getQueryParams()['id'] ?? 0);
127  $this->indexerConfig = $this->extensionConfiguration->get('indexed_search') ?? [];
128  parent::initializeAction();
129  }
130 
134  public function ‪processRequest(‪RequestInterface ‪$request): ResponseInterface
135  {
137  $beUser = $this->‪getBackendUserAuthentication();
138 
139  if (is_array(‪$arguments) && isset(‪$arguments['action']) && method_exists($this, ‪$arguments['action'] . 'Action')) {
140  $action = ‪$arguments['action'];
141  switch ($action) {
142  case 'saveStopwordsKeywords':
143  $action = 'statisticDetails';
144  break;
145  case 'deleteIndexedItem':
146  $action = 'statistic';
147  break;
148  }
149  $beUser->uc['indexed_search']['action'] = $action;
150  $beUser->uc['indexed_search']['arguments'] = ‪$arguments;
151  $beUser->writeUC();
152  } elseif (isset($beUser->uc['indexed_search']['action'])) {
153  ‪$request = ‪$request->‪withControllerActionName((string)$beUser->uc['indexed_search']['action']);
154  if (isset($beUser->uc['indexed_search']['arguments'])) {
155  ‪$request = ‪$request->‪withArguments($beUser->uc['indexed_search']['arguments']);
156  }
157  }
158 
159  return parent::processRequest(‪$request);
160  }
161 
165  protected function ‪indexAction(): ResponseInterface
166  {
167  ‪$view = $this->‪initializeModuleTemplate($this->request);
168  ‪$view->assignMultiple([
169  'records' => $this->administrationRepository->getRecordsNumbers(),
170  'phash' => $this->administrationRepository->getPageHashTypes(),
171  ]);
172  if ($this->pageUid) {
173  $expressionBuilder = $this->connectionPool->getQueryBuilderForTable('index_stat_word')->expr();
174  $last24hours = $expressionBuilder->gt('tstamp', ‪$GLOBALS['EXEC_TIME'] - 86400);
175  $last30days = $expressionBuilder->gt('tstamp', ‪$GLOBALS['EXEC_TIME'] - 30 * 86400);
176  ‪$view->assignMultiple([
177  'extensionConfiguration' => $this->indexerConfig,
178  'pageUid' => $this->pageUid,
179  'all' => $this->administrationRepository->getGeneralSearchStatistic('', $this->pageUid),
180  'last24hours' => $this->administrationRepository->getGeneralSearchStatistic($last24hours, $this->pageUid),
181  'last30days' => $this->administrationRepository->getGeneralSearchStatistic($last30days, $this->pageUid),
182  ]);
183  }
184  return ‪$view->renderResponse('Administration/Index');
185  }
186 
190  protected function ‪pagesAction(): ResponseInterface
191  {
192  ‪$view = $this->‪initializeModuleTemplate($this->request);
193  ‪$view->assignMultiple([
194  'extensionConfiguration' => $this->indexerConfig,
195  'records' => $this->administrationRepository->getPageStatistic(),
196  ]);
197  return ‪$view->renderResponse('Administration/Pages');
198  }
199 
203  protected function ‪externalDocumentsAction(): ResponseInterface
204  {
205  ‪$view = $this->‪initializeModuleTemplate($this->request);
206  ‪$view->assignMultiple([
207  'extensionConfiguration' => $this->indexerConfig,
208  'records' => $this->administrationRepository->getExternalDocumentsStatistic(),
209  ]);
210  return ‪$view->renderResponse('Administration/ExternalDocuments');
211  }
212 
218  protected function ‪statisticDetailsAction($pageHash = 0): ResponseInterface
219  {
220  ‪$view = $this->‪initializeModuleTemplate($this->request);
221  $buttonBar = ‪$view->getDocHeaderComponent()->getButtonBar();
222  $pageHash = (int)$pageHash;
223 
224  // Set back button
225  $backButton = $buttonBar
226  ->makeLinkButton()
227  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:indexed_search/Resources/Private/Language/locallang.xlf:administration.back'))
228  ->setIcon($this->iconFactory->getIcon('actions-view-go-up', IconSize::SMALL))
229  ->setHref($this->uriBuilder->reset()->uriFor('statistic', [], 'Administration'));
230  $buttonBar->addButton($backButton);
231 
232  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('index_phash');
233  $pageHashRow = $queryBuilder
234  ->select('*')
235  ->from('index_phash')
236  ->where(
237  $queryBuilder->expr()->eq(
238  'phash',
239  $queryBuilder->createNamedParameter($pageHash, ‪Connection::PARAM_INT)
240  )
241  )
242  ->executeQuery()
243  ->fetchAssociative();
244 
245  if (!is_array($pageHashRow)) {
246  return $this->‪redirect('statistic');
247  }
248 
249  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('index_debug');
250  $debugRow = $queryBuilder
251  ->select('debuginfo')
252  ->from('index_debug')
253  ->where(
254  $queryBuilder->expr()->eq(
255  'phash',
256  $queryBuilder->createNamedParameter($pageHash, ‪Connection::PARAM_INT)
257  )
258  )
259  ->executeQuery()
260  ->fetchAssociative();
261  $debugInfo = [];
262  $lexer = '';
263  if (is_array($debugRow)) {
264  $debugInfo = json_decode($debugRow['debuginfo'], true);
265  $lexer = $debugInfo['lexer'];
266  unset($debugInfo['lexer']);
267  }
268  $pageRecord = BackendUtility::getRecord('pages', $pageHashRow['data_page_id']);
269  $keywords = is_array($pageRecord) ? array_flip(GeneralUtility::trimExplode(',', (string)$pageRecord['keywords'], true)) : [];
270 
271  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('index_words');
272  $wordRecords = $queryBuilder
273  ->select('index_words.*', 'index_rel.*')
274  ->from('index_words')
275  ->from('index_rel')
276  ->where(
277  $queryBuilder->expr()->eq(
278  'index_rel.phash',
279  $queryBuilder->createNamedParameter($pageHash, ‪Connection::PARAM_INT)
280  ),
281  $queryBuilder->expr()->eq(
282  'index_words.wid',
283  $queryBuilder->quoteIdentifier('index_rel.wid')
284  )
285  )
286  ->orderBy('index_words.baseword')
287  ->executeQuery()
288  ->fetchAllAssociative();
289  foreach ($wordRecords as $id => $row) {
290  if (isset($keywords[$row['baseword']])) {
291  $wordRecords[$id]['is_keyword'] = true;
292  }
293  }
294  $metaphoneRows = $metaphone = [];
295  $enableMetaphoneSearch = (bool)($this->indexerConfig['enableMetaphoneSearch'] ?? false);
296  if ($enableMetaphoneSearch && is_array($wordRecords)) {
297  // Group metaphone hash
298  foreach ($wordRecords as $row) {
299  $metaphoneRows[$row['metaphone']][] = $row['baseword'];
300  }
301 
302  foreach ($metaphoneRows as $hash => $words) {
303  if (count($words) > 1) {
304  $metaphone[] = [
305  'metaphone' => $this->indexer->metaphone($words[0], true), $hash,
306  'words' => $words,
307  'hash' => $hash,
308  ];
309  }
310  }
311  }
312 
313  // sections
314  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('index_section');
315  $sections = $queryBuilder
316  ->select('*')
317  ->from('index_section')
318  ->where(
319  $queryBuilder->expr()->eq(
320  'phash',
321  $queryBuilder->createNamedParameter($pageHash, ‪Connection::PARAM_INT)
322  )
323  )
324  ->executeQuery()
325  ->fetchAllAssociative();
326 
327  // top words
328  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('index_words');
329  $topCountWords = $queryBuilder
330  ->select('index_words.baseword', 'index_words.metaphone', 'index_rel.*')
331  ->from('index_words')
332  ->from('index_rel')
333  ->setMaxResults(20)
334  ->where(
335  $queryBuilder->expr()->eq(
336  'index_rel.phash',
337  $queryBuilder->createNamedParameter($pageHash, ‪Connection::PARAM_INT)
338  ),
339  $queryBuilder->expr()->eq(
340  'index_words.is_stopword',
341  $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)
342  ),
343  $queryBuilder->expr()->eq(
344  'index_words.wid',
345  $queryBuilder->quoteIdentifier('index_rel.wid')
346  )
347  )
348  ->orderBy('index_rel.count', 'DESC')
349  ->executeQuery()
350  ->fetchAllAssociative();
351 
352  // top frequency
353  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('index_words');
354  $topFrequency = $queryBuilder
355  ->select('index_words.baseword', 'index_words.metaphone', 'index_rel.*')
356  ->from('index_words')
357  ->from('index_rel')
358  ->setMaxResults(20)
359  ->where(
360  $queryBuilder->expr()->eq(
361  'index_rel.phash',
362  $queryBuilder->createNamedParameter($pageHash, ‪Connection::PARAM_INT)
363  ),
364  $queryBuilder->expr()->eq(
365  'index_words.is_stopword',
366  $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)
367  ),
368  $queryBuilder->expr()->eq(
369  'index_words.wid',
370  $queryBuilder->quoteIdentifier('index_rel.wid')
371  )
372  )
373  ->orderBy('index_rel.freq', 'DESC')
374  ->executeQuery()
375  ->fetchAllAssociative();
376 
377  ‪$view->assignMultiple([
378  'extensionConfiguration' => $this->indexerConfig,
379  'phash' => (int)$pageHash,
380  'phashRow' => $pageHashRow,
381  'words' => $wordRecords,
382  'sections' => $sections,
383  'topCount' => $topCountWords,
384  'topFrequency' => $topFrequency,
385  'debug' => $debugInfo,
386  'lexer' => $lexer,
387  'metaphone' => $metaphone,
388  'page' => $pageRecord,
389  'keywords' => $keywords,
390  ]);
391 
392  return ‪$view->renderResponse('Administration/StatisticDetails');
393  }
394 
403  protected function ‪saveStopwordsKeywordsAction($pageHash, $pageId, $stopwords = [], $keywords = []): ResponseInterface
404  {
405  if ($this->‪getBackendUserAuthentication()->isAdmin()) {
406  if (is_array($stopwords) && !empty($stopwords)) {
407  $this->administrationRepository->saveStopWords($stopwords);
408  }
409  if (is_array($keywords) && !empty($keywords)) {
410  $this->administrationRepository->saveKeywords($keywords, $pageId);
411  }
412  }
413  return $this->‪redirect('statisticDetails', null, null, ['pageHash' => $pageHash]);
414  }
415 
422  protected function ‪wordDetailAction($id = 0, $pageHash = 0): ResponseInterface
423  {
424  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('index_phash');
425  $rows = $queryBuilder
426  ->select('index_phash.*', 'index_section.*', 'index_rel.*')
427  ->from('index_rel')
428  ->from('index_section')
429  ->from('index_phash')
430  ->where(
431  $queryBuilder->expr()->eq(
432  'index_rel.wid',
433  $queryBuilder->createNamedParameter($id, ‪Connection::PARAM_INT)
434  ),
435  $queryBuilder->expr()->eq(
436  'index_rel.phash',
437  $queryBuilder->quoteIdentifier('index_section.phash')
438  ),
439  $queryBuilder->expr()->eq(
440  'index_section.phash',
441  $queryBuilder->quoteIdentifier('index_phash.phash')
442  )
443  )
444  ->orderBy('index_rel.freq', 'desc')
445  ->executeQuery()
446  ->fetchAllAssociative();
447 
448  ‪$view = $this->‪initializeModuleTemplate($this->request);
449  ‪$view->assignMultiple([
450  'extensionConfiguration' => $this->indexerConfig,
451  'rows' => $rows,
452  'phash' => $pageHash,
453  ]);
454  return ‪$view->renderResponse('Administration/WordDetail');
455  }
456 
463  protected function ‪statisticAction($depth = 1, $mode = 'overview'): ResponseInterface
464  {
465  $externalParsers = [];
466  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['external_parsers'] ?? [] as $extension => $className) {
468  $fileContentParser = GeneralUtility::makeInstance($className);
469  if ($fileContentParser->softInit($extension)) {
470  $externalParsers[$extension] = $fileContentParser;
471  }
472  }
473  $this->administrationRepository->external_parsers = $externalParsers;
474  $allLines = $this->administrationRepository->getTree($this->pageUid, $depth, $mode);
475  ‪$view = $this->‪initializeModuleTemplate($this->request);
476  ‪$view->assignMultiple([
477  'extensionConfiguration' => $this->indexerConfig,
478  'levelTranslations' => explode('|', $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enterSearchLevels')),
479  'tree' => $allLines,
480  'pageUid' => $this->pageUid,
481  'mode' => $mode,
482  'depth' => $depth,
483  ]);
484  return ‪$view->renderResponse('Administration/Statistic');
485  }
486 
494  protected function ‪deleteIndexedItemAction($itemId, $depth = 1, $mode = 'overview'): ResponseInterface
495  {
496  $this->administrationRepository->removeIndexedPhashRow($itemId, $this->pageUid, $depth);
497  return $this->‪redirect('statistic', null, null, ['depth' => $depth, 'mode' => $mode]);
498  }
499 
501  {
502  return ‪$GLOBALS['BE_USER'];
503  }
504 
506  {
507  return ‪$GLOBALS['LANG'];
508  }
509 }
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\redirect
‪redirect($actionName, $controllerName=null, $extensionName=null, array $arguments=null, $pageUid=null, $_=null, $statusCode=303)
Definition: ActionController.php:717
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\initializeModuleTemplate
‪initializeModuleTemplate(ServerRequestInterface $request)
Definition: AdministrationController.php:62
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:50
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\getLanguageService
‪getLanguageService()
Definition: AdministrationController.php:505
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\$request
‪RequestInterface $request
Definition: ActionController.php:122
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\$arguments
‪TYPO3 CMS Extbase Mvc Controller Arguments $arguments
Definition: ActionController.php:141
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\pagesAction
‪pagesAction()
Definition: AdministrationController.php:190
‪TYPO3\CMS\Core\Configuration\ExtensionConfiguration
Definition: ExtensionConfiguration.php:47
‪TYPO3\CMS\Backend\Template\ModuleTemplateFactory
Definition: ModuleTemplateFactory.php:33
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\initializeAction
‪initializeAction()
Definition: AdministrationController.php:124
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\$view
‪ViewInterface $view
Definition: ActionController.php:89
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\deleteIndexedItemAction
‪deleteIndexedItemAction($itemId, $depth=1, $mode='overview')
Definition: AdministrationController.php:494
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\statisticDetailsAction
‪statisticDetailsAction($pageHash=0)
Definition: AdministrationController.php:218
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\wordDetailAction
‪wordDetailAction($id=0, $pageHash=0)
Definition: AdministrationController.php:422
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\getBackendUserAuthentication
‪getBackendUserAuthentication()
Definition: AdministrationController.php:500
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\$indexerConfig
‪array $indexerConfig
Definition: AdministrationController.php:48
‪TYPO3\CMS\Backend\Template\ModuleTemplate
Definition: ModuleTemplate.php:46
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:26
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController
Definition: AdministrationController.php:46
‪TYPO3\CMS\IndexedSearch\Domain\Repository\AdministrationRepository
Definition: AdministrationRepository.php:39
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\statisticAction
‪statisticAction($depth=1, $mode='overview')
Definition: AdministrationController.php:463
‪TYPO3\CMS\IndexedSearch\Controller
Definition: AdministrationController.php:18
‪TYPO3\CMS\Extbase\Mvc\RequestInterface\withControllerActionName
‪withControllerActionName(string $actionName)
‪TYPO3\CMS\IndexedSearch\FileContentParser
Definition: FileContentParser.php:33
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:60
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:35
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:39
‪TYPO3\CMS\Extbase\Mvc\RequestInterface\withArguments
‪withArguments(array $arguments)
‪TYPO3\CMS\Extbase\Mvc\RequestInterface
Definition: RequestInterface.php:24
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\$pageUid
‪int $pageUid
Definition: AdministrationController.php:47
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\saveStopwordsKeywordsAction
‪saveStopwordsKeywordsAction($pageHash, $pageId, $stopwords=[], $keywords=[])
Definition: AdministrationController.php:403
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController
Definition: ActionController.php:61
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\getFlashMessageQueue
‪getFlashMessageQueue(string $identifier=null)
Definition: ActionController.php:691
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\processRequest
‪processRequest(RequestInterface $request)
Definition: AdministrationController.php:134
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\indexAction
‪indexAction()
Definition: AdministrationController.php:165
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:48
‪TYPO3\CMS\IndexedSearch\Indexer
Definition: Indexer.php:39
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\__construct
‪__construct(protected readonly ModuleTemplateFactory $moduleTemplateFactory, protected readonly AdministrationRepository $administrationRepository, protected readonly Indexer $indexer, protected readonly IconFactory $iconFactory, protected readonly ExtensionConfiguration $extensionConfiguration, protected readonly ConnectionPool $connectionPool,)
Definition: AdministrationController.php:50
‪TYPO3\CMS\Extbase\Mvc\RequestInterface\getArguments
‪getArguments()
‪TYPO3\CMS\IndexedSearch\Controller\AdministrationController\externalDocumentsAction
‪externalDocumentsAction()
Definition: AdministrationController.php:203