7abfb8988dc26be0fc3773318c13373dd541618e
[Packages/TYPO3.CMS.git] / typo3 / sysext / indexed_search / Classes / Domain / Repository / AdministrationRepository.php
1 <?php
2 namespace TYPO3\CMS\IndexedSearch\Domain\Repository;
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 use TYPO3\CMS\Backend\Tree\View\PageTreeView;
17 use TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
19 use TYPO3\CMS\Core\Cache\CacheManager;
20 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
21 use TYPO3\CMS\Core\Database\Connection;
22 use TYPO3\CMS\Core\Database\ConnectionPool;
23 use TYPO3\CMS\Core\Database\Query\QueryHelper;
24 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
25 use TYPO3\CMS\Core\DataHandling\DataHandler;
26 use TYPO3\CMS\Core\Imaging\Icon;
27 use TYPO3\CMS\Core\Imaging\IconFactory;
28 use TYPO3\CMS\Core\Type\Bitmask\Permission;
29 use TYPO3\CMS\Core\Utility\GeneralUtility;
30 use TYPO3\CMS\IndexedSearch\FileContentParser;
31
32 /**
33 * Administration repository
34 */
35 class AdministrationRepository
36 {
37 /**
38 * List of fileContentParsers
39 *
40 * @var FileContentParser[]
41 */
42 public $external_parsers = [];
43
44 /**
45 * @var array
46 */
47 protected $allPhashListed = [];
48
49 /**
50 * @var array
51 */
52 protected $iconFileNameCache = [];
53
54 /**
55 * Get group list information
56 *
57 * @param int $phash
58 * @return array
59 */
60 public function getGrlistRecord($phash)
61 {
62 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('index_grlist');
63 $result = $queryBuilder
64 ->select('*')
65 ->from('index_grlist')
66 ->where(
67 $queryBuilder->expr()->eq(
68 'phash',
69 $queryBuilder->createNamedParameter($phash, \PDO::PARAM_INT)
70 )
71 )
72 ->execute();
73 $numberOfRows = $result->rowCount();
74 $allRows = [];
75 while ($row = $result->fetch()) {
76 $row['pcount'] = $numberOfRows;
77 $allRows[] = $row;
78 }
79 return $allRows;
80 }
81
82 /**
83 * Get number of fulltext records
84 *
85 * @param int $phash
86 * @return int|bool
87 */
88 public function getNumberOfFulltextRecords($phash)
89 {
90 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('index_fulltext');
91 return $queryBuilder
92 ->count('phash')
93 ->from('index_fulltext')
94 ->where(
95 $queryBuilder->expr()->eq(
96 'phash',
97 $queryBuilder->createNamedParameter($phash, \PDO::PARAM_INT)
98 )
99 )
100 ->execute()
101 ->fetchColumn(0);
102 }
103
104 /**
105 * Get number of words
106 *
107 * @param int $phash
108 * @return int|bool
109 */
110 public function getNumberOfWords($phash)
111 {
112 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('index_rel');
113 return $queryBuilder
114 ->count('*')
115 ->from('index_rel')
116 ->where(
117 $queryBuilder->expr()->eq(
118 'phash',
119 $queryBuilder->createNamedParameter($phash, \PDO::PARAM_INT)
120 )
121 )
122 ->execute()
123 ->fetchColumn(0);
124 }
125
126 /**
127 * Get statistic of external documents
128 *
129 * @return array
130 */
131 public function getExternalDocumentsStatistic()
132 {
133 $result = [];
134
135 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('index_phash');
136 $res = $queryBuilder
137 ->select('index_phash.*')
138 ->addSelectLiteral($queryBuilder->expr()->count('*', 'pcount'))
139 ->from('index_phash')
140 ->where($queryBuilder->expr()->neq('item_type', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)))
141 ->groupBy(
142 'phash_grouping',
143 'phash',
144 'cHashParams',
145 'data_filename',
146 'data_page_id',
147 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10. Remove along with database field data_page_reg1
148 'data_page_reg1',
149 'data_page_type',
150 'data_page_mp',
151 'gr_list',
152 'item_type',
153 'item_title',
154 'item_description',
155 'item_mtime',
156 'tstamp',
157 'item_size',
158 'contentHash',
159 'crdate',
160 'parsetime',
161 'sys_language_uid',
162 'item_crdate',
163 'externalUrl',
164 'recordUid',
165 'freeIndexUid',
166 'freeIndexSetId'
167 )
168 ->orderBy('item_type')
169 ->execute();
170
171 while ($row = $res->fetch()) {
172 $this->addAdditionalInformation($row);
173
174 $result[] = $row;
175
176 if ($row['pcount'] > 1) {
177 $res2 = $queryBuilder
178 ->select('*')
179 ->from('index_phash')
180 ->where(
181 $queryBuilder->expr()->eq(
182 'phash_grouping',
183 $queryBuilder->createNamedParameter($row['phash_grouping'], \PDO::PARAM_INT)
184 ),
185 $queryBuilder->expr()->neq(
186 'phash',
187 $queryBuilder->createNamedParameter($row['phash'], \PDO::PARAM_INT)
188 )
189 )
190 ->execute();
191 while ($row2 = $res2->fetch()) {
192 $this->addAdditionalInformation($row2);
193 $result[] = $row2;
194 }
195 }
196 }
197 return $result;
198 }
199
200 /**
201 * Get count of the tables used for indexed_search
202 *
203 * @return array
204 */
205 public function getRecordsNumbers()
206 {
207 $tables = [
208 'index_phash',
209 'index_words',
210 'index_rel',
211 'index_grlist',
212 'index_section',
213 'index_fulltext',
214 ];
215 $recordList = [];
216 foreach ($tables as $tableName) {
217 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($tableName);
218 $recordList[$tableName] = $queryBuilder
219 ->count('*')
220 ->from($tableName)
221 ->execute()
222 ->fetchColumn(0);
223 }
224 return $recordList;
225 }
226
227 /**
228 * Get hash types
229 *
230 * @return array
231 */
232 public function getPageHashTypes()
233 {
234 $counts = [];
235 $types = [
236 'html' => 1,
237 'htm' => 1,
238 'pdf' => 2,
239 'doc' => 3,
240 'txt' => 4
241 ];
242 $revTypes = array_flip($types);
243 $revTypes[0] = 'TYPO3 page';
244
245 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('index_phash');
246 $res = $queryBuilder
247 ->select('item_type')
248 ->addSelectLiteral($queryBuilder->expr()->count('*', 'count'))
249 ->from('index_phash')
250 ->groupBy('item_type')
251 ->orderBy('item_type')
252 ->execute();
253
254 while ($row = $res->fetch()) {
255 $itemType = $row['item_type'];
256 $counts[] = [
257 'count' => $row['count'],
258 'name' => $revTypes[$itemType],
259 'type' => $itemType,
260 'uniqueCount' => $this->countUniqueTypes($itemType),
261 ];
262 }
263 return $counts;
264 }
265
266 /**
267 * Count unique types
268 *
269 * @param string $itemType
270 * @return int
271 */
272 protected function countUniqueTypes($itemType)
273 {
274 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('index_phash');
275 $items = $queryBuilder
276 ->count('*')
277 ->from('index_phash')
278 ->where(
279 $queryBuilder->expr()->eq(
280 'item_type',
281 $queryBuilder->createNamedParameter($itemType, \PDO::PARAM_STR)
282 )
283 )
284 ->groupBy('phash_grouping')
285 ->execute()
286 ->fetchAll();
287
288 return count($items);
289 }
290
291 /**
292 * Get number of section records
293 *
294 * @param int $pageHash
295 * @return int
296 */
297 public function getNumberOfSections($pageHash)
298 {
299 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('index_section');
300 return (int)$queryBuilder
301 ->count('phash')
302 ->from('index_section')
303 ->where(
304 $queryBuilder->expr()->eq(
305 'phash',
306 $queryBuilder->createNamedParameter($pageHash, \PDO::PARAM_INT)
307 )
308 )
309 ->execute()
310 ->fetchColumn(0);
311 }
312
313 /**
314 * Get page statistic
315 *
316 * @return array
317 */
318 public function getPageStatistic()
319 {
320 $result = [];
321 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('index_phash');
322 $res = $queryBuilder
323 ->select('index_phash.*')
324 ->addSelectLiteral($queryBuilder->expr()->count('*', 'pcount'))
325 ->from('index_phash')
326 ->where($queryBuilder->expr()->neq('data_page_id', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)))
327 ->groupBy(
328 'phash_grouping',
329 'phash',
330 'cHashParams',
331 'data_filename',
332 'data_page_id',
333 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10. Remove along with database field data_page_reg1
334 'data_page_reg1',
335 'data_page_type',
336 'data_page_mp',
337 'gr_list',
338 'item_type',
339 'item_title',
340 'item_description',
341 'item_mtime',
342 'tstamp',
343 'item_size',
344 'contentHash',
345 'crdate',
346 'parsetime',
347 'sys_language_uid',
348 'item_crdate',
349 'externalUrl',
350 'recordUid',
351 'freeIndexUid',
352 'freeIndexSetId'
353 )
354 ->orderBy('data_page_id')
355 ->execute();
356
357 while ($row = $res->fetch()) {
358 $this->addAdditionalInformation($row);
359 $result[] = $row;
360
361 if ($row['pcount'] > 1) {
362 $res2 = $queryBuilder
363 ->select('*')
364 ->from('index_phash')
365 ->where(
366 $queryBuilder->expr()->eq(
367 'phash_grouping',
368 $queryBuilder->createNamedParameter($row['phash_grouping'], \PDO::PARAM_INT)
369 ),
370 $queryBuilder->expr()->neq(
371 'phash',
372 $queryBuilder->createNamedParameter($row['phash'], \PDO::PARAM_INT)
373 )
374 )
375 ->execute();
376 while ($row2 = $res2->fetch()) {
377 $this->addAdditionalInformation($row2);
378 $result[] = $row2;
379 }
380 }
381 }
382 return $result;
383 }
384
385 /**
386 * Get general statistic
387 *
388 * @param string $additionalWhere
389 * @param int $pageUid
390 * @param int $max
391 * @return array|null
392 */
393 public function getGeneralSearchStatistic($additionalWhere, $pageUid, $max = 50)
394 {
395 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
396 ->getQueryBuilderForTable('index_stat_word');
397 $queryBuilder
398 ->select('word')
399 ->from('index_stat_word')
400 ->addSelectLiteral($queryBuilder->expr()->count('*', 'c'))
401 ->where(
402 $queryBuilder->expr()->eq(
403 'pageid',
404 $queryBuilder->createNamedParameter($pageUid, \PDO::PARAM_INT)
405 )
406 )
407 ->groupBy('word')
408 ->setMaxResults((int)$max);
409
410 if (!empty($additionalWhere)) {
411 $queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($additionalWhere));
412 }
413
414 $result = $queryBuilder->execute();
415 $count = (int)$result->rowCount();
416 $result->closeCursor();
417
418 // exist several statistics for this page?
419 if ($count === 0) {
420 // Limit access to pages of the current site
421 $queryBuilder->where(
422 $queryBuilder->expr()->in(
423 'pageid',
424 $queryBuilder->createNamedParameter(
425 $this->extGetTreeList((int)$pageUid),
426 Connection::PARAM_INT_ARRAY
427 )
428 ),
429 QueryHelper::stripLogicalOperatorPrefix($additionalWhere)
430 );
431 }
432
433 return $queryBuilder->execute()->fetchAll();
434 }
435
436 /**
437 * Add additional information to the result row
438 *
439 * @param array $row
440 */
441 protected function addAdditionalInformation(array &$row)
442 {
443 $grListRec = $this->getGrlistRecord($row['phash']);
444 $unserializedCHashParams = unserialize($row['cHashParams']);
445
446 $row['numberOfWords'] = $this->getNumberOfWords($row['phash']);
447 $row['numberOfSections'] = $this->getNumberOfSections($row['phash']);
448 $row['numberOfFulltext'] = $this->getNumberOfFulltextRecords($row['phash']);
449 $row['cHashParams'] = !empty($unserializedCHashParams) ? $unserializedCHashParams : '';
450 $row['grList'] = $grListRec;
451 }
452
453 /**
454 * Get the page tree by using \TYPO3\CMS\Backend\Tree\View\PageTreeView
455 *
456 * @param int $pageId
457 * @param int $depth
458 * @param string $mode
459 * @return array
460 */
461 public function getTree($pageId, $depth = 4, $mode)
462 {
463 $allLines = [];
464 $pageRecord = BackendUtility::getRecord('pages', (int)$pageId);
465 if (!$pageRecord) {
466 return $allLines;
467 }
468 /** @var PageTreeView $tree */
469 $tree = GeneralUtility::makeInstance(PageTreeView::class);
470 $perms_clause = $this->getBackendUserAuthentication()->getPagePermsClause(Permission::PAGE_SHOW);
471 $tree->init('AND ' . $perms_clause);
472 $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
473 $HTML = '<span title="' . htmlspecialchars($pageRecord['title']) . '">' . $iconFactory->getIconForRecord('pages', $pageRecord, Icon::SIZE_SMALL)->render() . '</span>';
474 $tree->tree[] = [
475 'row' => $pageRecord,
476 'HTML' => $HTML
477 ];
478
479 if ($depth > 0) {
480 $tree->getTree((int)$pageId, $depth, '');
481 }
482
483 foreach ($tree->tree as $singleLine) {
484 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('index_phash');
485 $result = $queryBuilder->select(
486 'ISEC.phash_t3',
487 'ISEC.rl0',
488 'ISEC.rl1',
489 'ISEC.rl2',
490 'ISEC.page_id',
491 'ISEC.uniqid',
492 'IP.phash',
493 'IP.phash_grouping',
494 'IP.cHashParams',
495 'IP.data_filename',
496 'IP.data_page_id',
497 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10. Remove along with database field data_page_reg1
498 'IP.data_page_reg1',
499 'IP.data_page_type',
500 'IP.data_page_mp',
501 'IP.gr_list',
502 'IP.item_type',
503 'IP.item_title',
504 'IP.item_description',
505 'IP.item_mtime',
506 'IP.tstamp',
507 'IP.item_size',
508 'IP.contentHash',
509 'IP.crdate',
510 'IP.parsetime',
511 'IP.sys_language_uid',
512 'IP.item_crdate',
513 'IP.externalUrl',
514 'IP.recordUid',
515 'IP.freeIndexUid',
516 'IP.freeIndexSetId'
517 )
518 ->addSelectLiteral($queryBuilder->expr()->count('*', 'count_val'))
519 ->from('index_phash', 'IP')
520 ->from('index_section', 'ISEC')
521 ->where(
522 $queryBuilder->expr()->eq('IP.phash', $queryBuilder->quoteIdentifier('ISEC.phash')),
523 $queryBuilder->expr()->eq(
524 'ISEC.page_id',
525 $queryBuilder->createNamedParameter($singleLine['row']['uid'], \PDO::PARAM_INT)
526 )
527 )
528 ->groupBy(
529 'IP.phash',
530 'IP.phash_grouping',
531 'IP.cHashParams',
532 'IP.data_filename',
533 'IP.data_page_id',
534 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10. Remove along with database field data_page_reg1
535 'IP.data_page_reg1',
536 'IP.data_page_type',
537 'IP.data_page_mp',
538 'IP.gr_list',
539 'IP.item_type',
540 'IP.item_title',
541 'IP.item_description',
542 'IP.item_mtime',
543 'IP.tstamp',
544 'IP.item_size',
545 'IP.contentHash',
546 'IP.crdate',
547 'IP.parsetime',
548 'IP.sys_language_uid',
549 'IP.item_crdate',
550 'ISEC.phash',
551 'ISEC.phash_t3',
552 'ISEC.rl0',
553 'ISEC.rl1',
554 'ISEC.rl2',
555 'ISEC.page_id',
556 'ISEC.uniqid',
557 'IP.externalUrl',
558 'IP.recordUid',
559 'IP.freeIndexUid',
560 'IP.freeIndexSetId'
561 )
562 ->orderBy('IP.item_type')
563 ->addOrderBy('IP.tstamp')
564 ->setMaxResults(11)
565 ->execute();
566
567 $lines = [];
568 // Collecting phash values (to remove local indexing for)
569 // Traverse the result set of phash rows selected:
570 while ($row = $result->fetch()) {
571 $row['icon'] = $this->makeItemTypeIcon($row['item_type']);
572 $this->allPhashListed[] = $row['phash'];
573
574 // Adds a display row:
575 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
576 ->getQueryBuilderForTable('index_rel');
577 $wordCountResult = $queryBuilder->count('index_words.baseword')
578 ->from('index_rel')
579 ->from('index_words')
580 ->where(
581 $queryBuilder->expr()->eq(
582 'index_rel.phash',
583 $queryBuilder->createNamedParameter($row['phash'], \PDO::PARAM_INT)
584 ),
585 $queryBuilder->expr()->eq('index_words.wid', $queryBuilder->quoteIdentifier('index_rel.wid'))
586 )
587 ->groupBy('index_words.baseword')
588 ->execute();
589
590 $row['wordCount'] = $wordCountResult->rowCount();
591 $wordCountResult->closeCursor();
592
593 if ($mode === 'content') {
594 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
595 ->getQueryBuilderForTable('index_fulltext');
596 $row['fulltextData'] = $queryBuilder->select('*')
597 ->from('index_fulltext')
598 ->where(
599 $queryBuilder->expr()->eq(
600 'phash',
601 $queryBuilder->createNamedParameter($row['phash'], \PDO::PARAM_INT)
602 )
603 )
604 ->setMaxResults(1)
605 ->execute()
606 ->fetch();
607
608 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
609 ->getQueryBuilderForTable('index_rel');
610 $wordRecords = $queryBuilder->select('index_words.baseword')
611 ->from('index_rel')
612 ->from('index_words')
613 ->where(
614 $queryBuilder->expr()->eq(
615 'index_rel.phash',
616 $queryBuilder->createNamedParameter($row['phash'], \PDO::PARAM_INT)
617 ),
618 $queryBuilder->expr()->eq(
619 'index_words.wid',
620 $queryBuilder->quoteIdentifier('index_rel.wid')
621 )
622 )
623 ->groupBy('index_words.baseword')
624 ->orderBy('index_words.baseword')
625 ->execute()
626 ->fetchAll();
627
628 if (is_array($wordRecords)) {
629 $row['allWords'] = array_column($wordRecords, 'baseword');
630 }
631 }
632
633 $lines[] = $row;
634 }
635
636 $singleLine['lines'] = $lines;
637 $allLines[] = $singleLine;
638 }
639
640 return $allLines;
641 }
642
643 /**
644 * Generates a list of Page-uid's from $id.
645 * The only pages excluded from the list are deleted pages.
646 *
647 * @param int $id page id
648 * @return array Returns an array with all page IDs
649 */
650 protected function extGetTreeList(int $id): array
651 {
652 $pageIds = $this->getPageTreeIds($id, 100, 0);
653 $pageIds[] = $id;
654 return $pageIds;
655 }
656
657 /**
658 * Generates a list of Page-uid's from $id. List does not include $id itself
659 * The only pages excluded from the list are deleted pages.
660 *
661 * @param int $id Start page id
662 * @param int $depth Depth to traverse down the page tree.
663 * @param int $begin Determines at which level in the tree to start collecting uid's. Zero means 'start right away', 1 = 'next level and out'
664 * @return array Returns the list of pages
665 */
666 protected function getPageTreeIds(int $id, int $depth, int $begin): array
667 {
668 if (!$id || $depth <= 0) {
669 return [];
670 }
671 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
672 ->getQueryBuilderForTable('pages');
673
674 $queryBuilder->getRestrictions()
675 ->removeAll()
676 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
677 $result = $queryBuilder
678 ->select('uid', 'title')
679 ->from('pages')
680 ->where(
681 $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT))
682 )
683 ->execute();
684
685 $pageIds = [];
686 while ($row = $result->fetch()) {
687 if ($begin <= 0) {
688 $pageIds[] = (int)$row['uid'];
689 }
690 if ($depth > 1) {
691 $pageIds[] = array_merge($pageIds, $this->getPageTreeIds((int)$row['uid'], $depth - 1, $begin - 1));
692 }
693 }
694 return $pageIds;
695 }
696
697 /**
698 * Remove indexed phash row
699 *
700 * @param string $phashList
701 * @param int $pageId
702 * @param int $depth
703 */
704 public function removeIndexedPhashRow($phashList, $pageId, $depth = 4)
705 {
706 if ($phashList === 'ALL') {
707 $this->getTree($pageId, $depth, '');
708 $phashRows = $this->allPhashListed;
709 $this->allPhashListed = [];
710 } else {
711 $phashRows = GeneralUtility::trimExplode(',', $phashList, true);
712 }
713
714 foreach ($phashRows as $phash) {
715 $phash = (int)$phash;
716 if ($phash > 0) {
717 $idList = [];
718 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
719 ->getQueryBuilderForTable('index_section');
720 $res = $queryBuilder
721 ->select('page_id')
722 ->from('index_section')
723 ->where(
724 $queryBuilder->expr()->eq(
725 'phash',
726 $queryBuilder->createNamedParameter($phash, \PDO::PARAM_INT)
727 )
728 )
729 ->execute();
730 while ($row = $res->fetch()) {
731 $idList[] = (int)$row['page_id'];
732 }
733
734 if (!empty($idList)) {
735 /** @var FrontendInterface $pageCache */
736 $pageCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_pages');
737 foreach ($idList as $pageId) {
738 $pageCache->flushByTag('pageId_' . $pageId);
739 }
740 }
741
742 // Removing old registrations for all tables.
743 $tableArr = [
744 'index_phash',
745 'index_rel',
746 'index_section',
747 'index_grlist',
748 'index_fulltext',
749 'index_debug'
750 ];
751 foreach ($tableArr as $table) {
752 GeneralUtility::makeInstance(ConnectionPool::class)
753 ->getConnectionForTable($table)
754 ->delete($table, ['phash' => (int)$phash]);
755 }
756 }
757 }
758 }
759
760 /**
761 * Save stop words
762 *
763 * @param array $words stop words
764 */
765 public function saveStopWords(array $words)
766 {
767 foreach ($words as $wid => $state) {
768 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('index_words');
769 $queryBuilder
770 ->update('index_words')
771 ->set('is_stopword', (int)$state)
772 ->where(
773 $queryBuilder->expr()->eq(
774 'wid',
775 $queryBuilder->createNamedParameter($wid, \PDO::PARAM_INT)
776 )
777 )
778 ->execute();
779 }
780 }
781
782 /**
783 * Save keywords
784 *
785 * @param array $words keywords
786 * @param int $pageId page id
787 */
788 public function saveKeywords(array $words, $pageId)
789 {
790 // Get pages current keywords
791 $pageRec = BackendUtility::getRecord('pages', $pageId);
792 if (!is_array($pageRec)) {
793 return;
794 }
795 $keywords = array_flip(GeneralUtility::trimExplode(',', $pageRec['keywords'], true));
796 // Merge keywords:
797 foreach ($words as $key => $v) {
798 if ($v) {
799 $keywords[$key] = 1;
800 } else {
801 unset($keywords[$key]);
802 }
803 }
804 // Compile new list:
805 $data = [];
806 $data['pages'][$pageId]['keywords'] = implode(', ', array_keys($keywords));
807 $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
808 $dataHandler->start($data, []);
809 $dataHandler->process_datamap();
810 }
811
812 /**
813 * Collect the type icons
814 *
815 * @param string $itemType
816 * @return string
817 */
818 protected function makeItemTypeIcon($itemType)
819 {
820 if (!isset($this->iconFileNameCache[$itemType])) {
821 $icon = '';
822 if ($itemType === '0') {
823 $icon = 'EXT:indexed_search/Resources/Public/Icons/FileTypes/pages.gif';
824 } elseif ($this->external_parsers[$itemType]) {
825 $icon = $this->external_parsers[$itemType]->getIcon($itemType);
826 }
827 $this->iconFileNameCache[$itemType] = $icon;
828 }
829 return $this->iconFileNameCache[$itemType];
830 }
831
832 /**
833 * @return BackendUserAuthentication
834 */
835 protected function getBackendUserAuthentication()
836 {
837 return $GLOBALS['BE_USER'];
838 }
839 }