[TASK] Re-work/simplify copyright header in PHP files - Part 8
[Packages/TYPO3.CMS.git] / typo3 / sysext / indexed_search / Classes / Controller / IndexedPagesController.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\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20 /**
21 * Indexing class for TYPO3 frontend
22 *
23 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
24 */
25 class IndexedPagesController extends \TYPO3\CMS\Backend\Module\AbstractFunctionModule {
26
27 // Internal, dynamic:
28 /**
29 * @todo Define visibility
30 */
31 public $allPhashListed = array();
32
33 // phash values accumulations for link to clear all
34 /**
35 * @todo Define visibility
36 */
37 public $external_parsers = array();
38
39 // External content parsers - objects set here with file extensions as keys.
40 /**
41 * @todo Define visibility
42 */
43 public $iconFileNameCache = array();
44
45 // File extensions - icon map/cache.
46 /**
47 * @todo Define visibility
48 */
49 public $indexerConfig = array();
50
51 // Indexer configuration, coming from $GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['indexed_search']
52 /**
53 * @todo Define visibility
54 */
55 public $enableMetaphoneSearch = FALSE;
56
57 /**
58 * Indexer object
59 *
60 * @var \TYPO3\CMS\IndexedSearch\Indexer
61 * @todo Define visibility
62 */
63 public $indexerObj;
64
65 /**
66 * @int Default number of list entries per page
67 */
68 protected $maxListPerPage;
69
70 /**
71 * Default constructor loads additional locallang
72 */
73 public function __construct() {
74 $GLOBALS['LANG']->includeLLFile('EXT:indexed_search/modfunc1/locallang.xlf');
75 }
76
77 /**
78 * Initialize menu array internally
79 *
80 * @return void
81 * @todo Define visibility
82 */
83 public function modMenu() {
84 global $LANG;
85 return array(
86 'depth' => array(
87 0 => $LANG->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_0'),
88 1 => $LANG->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_1'),
89 2 => $LANG->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_2'),
90 3 => $LANG->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_3'),
91 999 => $LANG->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_infi')
92 ),
93 'type' => array(
94 0 => 'Overview',
95 1 => 'Technical Details',
96 2 => 'Words and content'
97 )
98 );
99 }
100
101 /**
102 * Produces main content of the module
103 *
104 * @return string HTML output
105 * @todo Define visibility
106 */
107 public function main() {
108 // Initializes the module. Done in this function because we may need to re-initialize if data is submitted!
109 global $LANG, $TYPO3_CONF_VARS;
110 // Return if no page id:
111 if ($this->pObj->id <= 0) {
112 return;
113 }
114 // Indexer configuration from Extension Manager interface:
115 $this->indexerConfig = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['indexed_search']);
116 // Workaround: If the extension configuration was not updated yet, the value is not existing
117 $this->enableMetaphoneSearch = isset($this->indexerConfig['enableMetaphoneSearch']) ? ($this->indexerConfig['enableMetaphoneSearch'] ? TRUE : FALSE) : TRUE;
118 // Initialize max-list items
119 $this->maxListPerPage = GeneralUtility::_GP('listALL') ? 100000 : 100;
120 // Processing deletion of phash rows:
121 if (GeneralUtility::_GP('deletePhash')) {
122 $this->removeIndexedPhashRow(GeneralUtility::_GP('deletePhash'));
123 }
124 // Processing stop-words:
125 if (GeneralUtility::_POST('_stopwords')) {
126 $this->processStopWords(GeneralUtility::_POST('stopWord'));
127 }
128 // Processing stop-words:
129 if (GeneralUtility::_POST('_pageKeywords')) {
130 $this->processPageKeywords(GeneralUtility::_POST('pageKeyword'), GeneralUtility::_POST('pageKeyword_pageUid'));
131 }
132 // Initialize external document parsers:
133 // Example configuration, see ext_localconf.php of this file!
134 if (is_array($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['external_parsers'])) {
135 foreach ($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['external_parsers'] as $extension => $_objRef) {
136 $this->external_parsers[$extension] = GeneralUtility::getUserObj($_objRef);
137 // Init parser and if it returns FALSE, unset its entry again:
138 if (!$this->external_parsers[$extension]->softInit($extension)) {
139 unset($this->external_parsers[$extension]);
140 }
141 }
142 }
143 // Initialize indexer if we need it (metaphone display does...)
144 $this->indexerObj = GeneralUtility::makeInstance('TYPO3\\CMS\\IndexedSearch\\Indexer');
145 // Set CSS styles specific for this document:
146 $this->pObj->content = str_replace('/*###POSTCSSMARKER###*/', '
147 TABLE.c-list TR TD { white-space: nowrap; vertical-align: top; }
148 ', $this->pObj->content);
149 // Check if details for a phash record should be shown:
150 if (GeneralUtility::_GET('phash')) {
151 // Show title / function menu:
152 $theOutput .= $this->pObj->doc->spacer(5);
153 $theOutput .= $this->pObj->doc->section('Details for a single result row:', $this->showDetailsForPhash(GeneralUtility::_GET('phash')), 0, 1);
154 } elseif (GeneralUtility::_GET('wid')) {
155 // Show title / function menu:
156 $theOutput .= $this->pObj->doc->spacer(5);
157 $theOutput .= $this->pObj->doc->section('Details for a word:', $this->showDetailsForWord(GeneralUtility::_GET('wid')), 0, 1);
158 } elseif ($this->enableMetaphoneSearch && GeneralUtility::_GET('metaphone')) {
159 // Show title / function menu:
160 $theOutput .= $this->pObj->doc->spacer(5);
161 $theOutput .= $this->pObj->doc->section('Details for metaphone value:', $this->showDetailsForMetaphone(GeneralUtility::_GET('metaphone')), 0, 1);
162 } elseif (GeneralUtility::_GET('reindex')) {
163 // Show title / function menu:
164 $theOutput .= $this->pObj->doc->spacer(5);
165 $theOutput .= $this->pObj->doc->section('Reindexing...', $this->reindexPhash(GeneralUtility::_GET('reindex'), GeneralUtility::_GET('reindex_id')), 0, 1);
166 } else {
167 // Detail listings:
168 // Depth function menu:
169 $h_func = BackendUtility::getFuncMenu($this->pObj->id, 'SET[type]', $this->pObj->MOD_SETTINGS['type'], $this->pObj->MOD_MENU['type']);
170 $h_func .= BackendUtility::getFuncMenu($this->pObj->id, 'SET[depth]', $this->pObj->MOD_SETTINGS['depth'], $this->pObj->MOD_MENU['depth']);
171 // Show title / function menu:
172 $theOutput .= $this->pObj->doc->header($LANG->getLL('title'));
173 $theOutput .= $this->pObj->doc->section('', $h_func, 0, 1);
174 $theOutput .= $this->drawTableOfIndexedPages();
175 }
176 return $theOutput;
177 }
178
179 /*******************************
180 *
181 * Drawing table of indexed pages
182 *
183 ******************************/
184 /**
185 * Produces a table with indexing information for each page.
186 *
187 * @return string HTML output
188 * @todo Define visibility
189 */
190 public function drawTableOfIndexedPages() {
191 global $BACK_PATH;
192 // Drawing tree:
193 $tree = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Tree\\View\\PageTreeView');
194 $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
195 $tree->init('AND ' . $perms_clause);
196 $HTML = '<img src="' . $BACK_PATH . \TYPO3\CMS\Backend\Utility\IconUtility::getIcon('pages', $this->pObj->pageinfo) . '" width="18" height="16" align="top" alt="" />';
197 $tree->tree[] = array(
198 'row' => $this->pObj->pageinfo,
199 'HTML' => $HTML
200 );
201 if ($this->pObj->MOD_SETTINGS['depth']) {
202 $tree->getTree($this->pObj->id, $this->pObj->MOD_SETTINGS['depth'], '');
203 }
204 // Traverse page tree:
205 $code = '';
206 foreach ($tree->tree as $data) {
207 $code .= $this->indexed_info($data['row'], $data['HTML'] . $this->showPageDetails(
208 BackendUtility::getRecordTitlePrep($data['row']['title']), $data['row']['uid']));
209 }
210 if ($code) {
211 $code = '<br /><br />
212 <table border="0" cellspacing="1" cellpadding="2" class="c-list">' . $this->printPhashRowHeader() . $code . '</table>';
213 // Create section to output:
214 $theOutput .= $this->pObj->doc->section('', $code, 0, 1);
215 } else {
216 $theOutput .= $this->pObj->doc->section('', '<br /><br />' . $this->pObj->doc->icons(1) . 'There were no indexed pages found in the tree.<br /><br />', 0, 1);
217 }
218 return $theOutput;
219 }
220
221 /**
222 * Create information table row for a page regarding indexing information.
223 *
224 * @param array Data array for this page
225 * @param string HTML content for first column (page tree icon etc.)
226 * @return string HTML code. (table row)
227 * @todo Define visibility
228 */
229 public function indexed_info($data, $firstColContent) {
230 // Query:
231 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('ISEC.phash_t3, ISEC.rl0, ISEC.rl1, ISEC.rl2, ISEC.page_id, ISEC.uniqid, ' . 'IP.phash, IP.phash_grouping, IP.cHashParams, IP.data_filename, IP.data_page_id, ' . 'IP.data_page_reg1, IP.data_page_type, IP.data_page_mp, IP.gr_list, IP.item_type, ' . 'IP.item_title, IP.item_description, IP.item_mtime, IP.tstamp, IP.item_size, ' . 'IP.contentHash, IP.crdate, IP.parsetime, IP.sys_language_uid, IP.item_crdate, ' . 'IP.externalUrl, IP.recordUid, IP.freeIndexUid, IP.freeIndexSetId, count(*) AS count_val', 'index_phash IP, index_section ISEC', 'IP.phash = ISEC.phash AND ISEC.page_id = ' . (int)$data['uid'], 'IP.phash,IP.phash_grouping,IP.cHashParams,IP.data_filename,IP.data_page_id,IP.data_page_reg1,IP.data_page_type,IP.data_page_mp,IP.gr_list,IP.item_type,IP.item_title,IP.item_description,IP.item_mtime,IP.tstamp,IP.item_size,IP.contentHash,IP.crdate,IP.parsetime,IP.sys_language_uid,IP.item_crdate,ISEC.phash,ISEC.phash_t3,ISEC.rl0,ISEC.rl1,ISEC.rl2,ISEC.page_id,ISEC.uniqid,IP.externalUrl,IP.recordUid,IP.freeIndexUid,IP.freeIndexSetId', 'IP.item_type, IP.tstamp', $this->maxListPerPage + 1);
232 // Initialize variables:
233 $rowCount = 0;
234 $lines = array();
235 // Collecting HTML rows here.
236 $phashAcc = array();
237 // Collecting phash values (to remove local indexing for)
238 $phashAcc[] = 0;
239 // Traverse the result set of phash rows selected:
240 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
241 if ($rowCount == $this->maxListPerPage) {
242 $rowCount++;
243 // Increase to the extra warning row will appear as well.
244 break;
245 }
246 // Adds a display row:
247 $lines[$row['phash_grouping']][] = $this->printPhashRow($row, isset($lines[$row['phash_grouping']]), $this->getGrListEntriesForPhash($row['phash'], $row['gr_list']));
248 $rowCount++;
249 $phashAcc[] = $row['phash'];
250 $this->allPhashListed[] = $row['phash'];
251 }
252 // Compile rows into the table:
253 $out = '';
254 $cellAttrib = $data['_CSSCLASS'] ? ' class="' . $data['_CSSCLASS'] . '"' : '';
255 if (count($lines)) {
256 $firstColContent = '<td rowspan="' . $rowCount . '"' . $cellAttrib . '>' . $firstColContent . '</td>';
257 foreach ($lines as $rowSet) {
258 foreach ($rowSet as $rows) {
259 $out .= '
260 <tr class="bgColor-20">' . $firstColContent . implode('', $rows) . '</tr>';
261 $firstColContent = '';
262 }
263 }
264 if ($rowCount > $this->maxListPerPage) {
265 // Now checking greater than, because we increased $rowCount before...
266 $out .= '
267 <tr class="bgColor-20">
268 <td>&nbsp;</td>
269 <td colspan="' . ($this->returnNumberOfColumns() - 1) . '">' . $this->pObj->doc->icons(3) . '<span class="">There were more than ' . $this->maxListPerPage . ' rows. <a href="' . htmlspecialchars(BackendUtility::getModuleUrl('web_info', array('id' => $this->pObj->id, 'listAll' => 1))) . '">Click here to list them ALL!</a></span></td>
270 </tr>';
271 }
272 } else {
273 $out .= '
274 <tr class="bgColor-20">
275 <td' . $cellAttrib . '>' . $firstColContent . '</td>
276 <td colspan="' . ($this->returnNumberOfColumns() - 1) . '"><em>Not indexed</em></td>
277 </tr>';
278 }
279 // Checking for phash-rows which are NOT joined with the section table:
280 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('IP.*', 'index_phash IP', 'IP.data_page_id = ' . (int)$data['uid'] . ' AND IP.phash NOT IN (' . implode(',', $phashAcc) . ')');
281 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
282 $out .= '
283 <tr class="typo3-red">
284 <td colspan="' . $this->returnNumberOfColumns() . '"><strong>Warning:</strong> phash-row "' . $row['phash'] . '" didn\'t have a representation in the index_section table!</td>
285 </tr>';
286 $this->allPhashListed[] = $row['phash'];
287 }
288 return $out;
289 }
290
291 /**
292 * Render a single row of information about a indexing entry.
293 *
294 * @param array Row from query (combined phash table with sections etc).
295 * @param boolean Set if grouped to previous result; the icon of the element is not shown again.
296 * @param array Array of index_grlist records.
297 * @return array Array of table rows.
298 * @see indexed_info()
299 * @todo Define visibility
300 */
301 public function printPhashRow($row, $grouping = 0, $extraGrListRows) {
302 $lines = array();
303 // Title cell attributes will highlight TYPO3 pages with a slightly darker color (bgColor4) than attached medias. Also IF there are more than one section record for a phash row it will be red as a warning that something is wrong!
304 $titleCellAttribs = $row['count_val'] != 1 ? ' bgcolor="red"' : ($row['item_type'] === '0' ? ' class="bgColor4"' : '');
305 if ($row['item_type']) {
306 $arr = unserialize($row['cHashParams']);
307 $page = $arr['key'] ? ' [' . $arr['key'] . ']' : '';
308 } else {
309 $page = '';
310 }
311 $elTitle = $this->linkDetails($row['item_title'] ? htmlspecialchars(GeneralUtility::fixed_lgd_cs($row['item_title'], 20) . $page) : '<em>[No Title]</em>', $row['phash']);
312 $cmdLinks = $this->printRemoveIndexed($row['phash'], 'Clear phash-row') . $this->printReindex($row, 'Re-index element');
313 switch ($this->pObj->MOD_SETTINGS['type']) {
314 case 1:
315 // Technical details:
316 // Display icon:
317 if (!$grouping) {
318 $lines[] = '<td>' . $this->makeItemTypeIcon($row['item_type'], ($row['data_filename'] ? $row['data_filename'] : $row['item_title'])) . '</td>';
319 } else {
320 $lines[] = '<td>&nbsp;</td>';
321 }
322 // Title displayed:
323 $lines[] = '<td' . $titleCellAttribs . '>' . $elTitle . '</td>';
324 // Remove-indexing-link:
325 $lines[] = '<td>' . $cmdLinks . '</td>';
326 // Various data:
327 $lines[] = '<td>' . $row['phash'] . '</td>';
328 $lines[] = '<td>' . $row['contentHash'] . '</td>';
329 if ($row['item_type'] === '0') {
330 $lines[] = '<td>' . ($row['data_page_id'] ? $row['data_page_id'] : '&nbsp;') . '</td>';
331 $lines[] = '<td>' . ($row['data_page_type'] ? $row['data_page_type'] : '&nbsp;') . '</td>';
332 $lines[] = '<td>' . ($row['sys_language_uid'] ? $row['sys_language_uid'] : '&nbsp;') . '</td>';
333 $lines[] = '<td>' . ($row['data_page_mp'] ? $row['data_page_mp'] : '&nbsp;') . '</td>';
334 } else {
335 $lines[] = '<td colspan="4">' . htmlspecialchars($row['data_filename']) . '</td>';
336 }
337 $lines[] = '<td>' . $row['gr_list'] . $this->printExtraGrListRows($extraGrListRows) . '</td>';
338 $lines[] = '<td>' . $this->printRootlineInfo($row) . '</td>';
339 $lines[] = '<td>' . ($row['page_id'] ? $row['page_id'] : '&nbsp;') . '</td>';
340 $lines[] = '<td>' . ($row['phash_t3'] != $row['phash'] ? $row['phash_t3'] : '&nbsp;') . '</td>';
341 $lines[] = '<td>' . ($row['freeIndexUid'] ? $row['freeIndexUid'] . ($row['freeIndexSetId'] ? '/' . $row['freeIndexSetId'] : '') : '&nbsp;') . '</td>';
342 $lines[] = '<td>' . ($row['recordUid'] ? $row['recordUid'] : '&nbsp;') . '</td>';
343 // cHash parameters:
344 $arr = unserialize($row['cHashParams']);
345 if (!is_array($arr)) {
346 $arr = array(
347 'cHash' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_general.xlf:LGL.error', TRUE)
348 );
349 }
350 $theCHash = $arr['cHash'];
351 unset($arr['cHash']);
352 if ($row['item_type']) {
353 // pdf...
354 $lines[] = '<td>' . ($arr['key'] ? 'Page ' . $arr['key'] : '') . '&nbsp;</td>';
355 } elseif ($row['item_type'] == 0) {
356 $lines[] = '<td>' . htmlspecialchars(GeneralUtility::implodeArrayForUrl('', $arr)) . '&nbsp;</td>';
357 } else {
358 $lines[] = '<td class="bgColor">&nbsp;</td>';
359 }
360 $lines[] = '<td>' . $theCHash . '</td>';
361 break;
362 case 2:
363 // Words and content:
364 // Display icon:
365 if (!$grouping) {
366 $lines[] = '<td>' . $this->makeItemTypeIcon($row['item_type'], ($row['data_filename'] ? $row['data_filename'] : $row['item_title'])) . '</td>';
367 } else {
368 $lines[] = '<td>&nbsp;</td>';
369 }
370 // Title displayed:
371 $lines[] = '<td' . $titleCellAttribs . '>' . $elTitle . '</td>';
372 // Remove-indexing-link:
373 $lines[] = '<td>' . $cmdLinks . '</td>';
374 // Query:
375 $ftrow = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'index_fulltext', 'phash = ' . (int)$row['phash']);
376 $lines[] = '<td style="white-space: normal;">' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($ftrow['fulltextdata'], 3000)) . '<hr/><em>Size: ' . strlen($ftrow['fulltextdata']) . '</em>' . '</td>';
377 // Query:
378 $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_words.baseword, index_rel.*', 'index_rel, index_words', 'index_rel.phash = ' . (int)$row['phash'] . ' AND index_words.wid = index_rel.wid', '', '', '', 'baseword');
379 $wordList = '';
380 if (is_array($ftrows)) {
381 $indexed_words = array_keys($ftrows);
382 sort($indexed_words);
383 $wordList = htmlspecialchars(implode(' ', $indexed_words));
384 $wordList .= '<hr/><em>Count: ' . count($indexed_words) . '</em>';
385 }
386 $lines[] = '<td style="white-space: normal;">' . $wordList . '</td>';
387 break;
388 default:
389 // Overview
390 // Display icon:
391 if (!$grouping) {
392 $lines[] = '<td>' . $this->makeItemTypeIcon($row['item_type'], ($row['data_filename'] ? $row['data_filename'] : $row['item_title'])) . '</td>';
393 } else {
394 $lines[] = '<td>&nbsp;</td>';
395 }
396 // Title displayed:
397 $lines[] = '<td' . $titleCellAttribs . '>' . $elTitle . '</td>';
398 // Remove-indexing-link:
399 $lines[] = '<td>' . $cmdLinks . '</td>';
400 $lines[] = '<td style="white-space: normal;">' . htmlspecialchars($row['item_description']) . '...</td>';
401 $lines[] = '<td>' . GeneralUtility::formatSize($row['item_size']) . '</td>';
402 $lines[] = '<td>' . BackendUtility::dateTimeAge($row['tstamp']) . '</td>';
403 }
404 return $lines;
405 }
406
407 /**
408 * Creates the header row for the table
409 *
410 * @return string HTML string (table row)
411 * @todo Define visibility
412 */
413 public function printPhashRowHeader() {
414 $lines = array();
415 switch ($this->pObj->MOD_SETTINGS['type']) {
416 case 1:
417 $lines[] = '<td>&nbsp;</td>';
418 $lines[] = '<td>&nbsp;</td>';
419 $lines[] = '<td>Title</td>';
420 $lines[] = '<td bgcolor="red">' . $this->printRemoveIndexed('ALL', 'Clear ALL phash-rows below!') . '</td>';
421 $lines[] = '<td>pHash</td>';
422 $lines[] = '<td>contentHash</td>';
423 $lines[] = '<td>&amp;id</td>';
424 $lines[] = '<td>&amp;type</td>';
425 $lines[] = '<td>&amp;L</td>';
426 $lines[] = '<td>&amp;MP</td>';
427 $lines[] = '<td>grlist</td>';
428 $lines[] = '<td>Rootline</td>';
429 $lines[] = '<td>page_id</td>';
430 $lines[] = '<td>phash_t3</td>';
431 $lines[] = '<td>CfgUid</td>';
432 $lines[] = '<td>RecUid</td>';
433 $lines[] = '<td>GET-parameters</td>';
434 $lines[] = '<td>&amp;cHash</td>';
435 break;
436 case 2:
437 $lines[] = '<td>&nbsp;</td>';
438 $lines[] = '<td>&nbsp;</td>';
439 $lines[] = '<td>Title</td>';
440 $lines[] = '<td bgcolor="red">' . $this->printRemoveIndexed('ALL', 'Clear ALL phash-rows below!') . '</td>';
441 $lines[] = '<td>Content<br />
442 <img src="clear.gif" width="300" height="1" alt="" /></td>';
443 $lines[] = '<td>Words<br />
444 <img src="clear.gif" width="300" height="1" alt="" /></td>';
445 break;
446 default:
447 $lines[] = '<td>&nbsp;</td>';
448 $lines[] = '<td>&nbsp;</td>';
449 $lines[] = '<td>Title</td>';
450 $lines[] = '<td bgcolor="red">' . $this->printRemoveIndexed('ALL', 'Clear ALL phash-rows below!') . '</td>';
451 $lines[] = '<td>Description</td>';
452 $lines[] = '<td>Size</td>';
453 $lines[] = '<td>Indexed:</td>';
454 }
455 $out = '<tr class="tableheader bgColor5">' . implode('', $lines) . '</tr>';
456 return $out;
457 }
458
459 /**
460 * Returns the number of columns depending on display type of list
461 *
462 * @return integer Number of columns in list:
463 * @todo Define visibility
464 */
465 public function returnNumberOfColumns() {
466 switch ($this->pObj->MOD_SETTINGS['type']) {
467 case 1:
468 return 18;
469 break;
470 case 2:
471 return 6;
472 break;
473 default:
474 return 7;
475 }
476 }
477
478 /*******************************
479 *
480 * Details display, phash row
481 *
482 *******************************/
483 /**
484 * Showing details for a particular phash row
485 *
486 * @param integer phash value to display details for.
487 * @return string HTML content
488 * @todo Define visibility
489 */
490 public function showDetailsForPhash($phash) {
491 $content = '';
492 $phash = (int)$phash;
493 // Selects the result row:
494 $phashRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'index_phash', 'phash = ' . $phash);
495 // If found, display:
496 if (is_array($phashRecord)) {
497 $content .= '<h4>phash row content:</h4>' . \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($phashRecord);
498 // Getting debug information if any:
499 $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'index_debug', 'phash = ' . $phash);
500 if (is_array($ftrows)) {
501 $debugInfo = unserialize($ftrows[0]['debuginfo']);
502 $lexer = $debugInfo['lexer'];
503 unset($debugInfo['lexer']);
504 $content .= '<h3>Debug information:</h3>' . \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($debugInfo);
505 $content .= '<h4>Debug information / lexer splitting:</h4>' . '<hr/><strong>' . $lexer . '</strong><hr/>';
506 }
507 $content .= '<h3>Word statistics</h3>';
508 // Finding all words for this phash:
509 $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_words.*, index_rel.*', 'index_rel, index_words', 'index_rel.phash = ' . $phash . ' AND index_words.wid = index_rel.wid', '', 'index_words.baseword', '');
510 $pageRec = BackendUtility::getRecord('pages', $phashRecord['data_page_id']);
511 $showStopWordCheckBox = $GLOBALS['BE_USER']->isAdmin();
512 $content .= $this->listWords($ftrows, 'All words found on page (' . count($ftrows) . '):', $showStopWordCheckBox, $pageRec);
513 if ($this->enableMetaphoneSearch) {
514 // Group metaphone hash:
515 $metaphone = array();
516 foreach ($ftrows as $row) {
517 $metaphone[$row['metaphone']][] = $row['baseword'];
518 }
519 $content .= $this->listMetaphoneStat($metaphone, 'Metaphone stats:');
520 }
521 // Finding top-20 on frequency for this phash:
522 $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_words.baseword, index_words.metaphone, index_rel.*', 'index_rel, index_words', 'index_rel.phash = ' . $phash . ' AND index_words.wid = index_rel.wid
523 AND index_words.is_stopword=0', '', 'index_rel.freq DESC', '20');
524 $content .= $this->listWords($ftrows, 'Top-20 words by frequency:', 2);
525 // Finding top-20 on count for this phash:
526 $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_words.baseword, index_words.metaphone, index_rel.*', 'index_rel, index_words', 'index_rel.phash = ' . $phash . ' AND index_words.wid = index_rel.wid
527 AND index_words.is_stopword=0', '', 'index_rel.count DESC', '20');
528 $content .= $this->listWords($ftrows, 'Top-20 words by count:', 2);
529 $content .= '<h3>Section records for this phash</h3>';
530 // Finding sections for this record:
531 $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'index_section', 'index_section.phash = ' . $phash, '', '', '');
532 $content .= \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($ftrows);
533 // Add go-back link:
534 $content = $this->linkList() . $content . $this->linkList();
535 } else {
536 $content .= 'Error: No phash row found';
537 }
538 return $content;
539 }
540
541 /**
542 * Create table with list of words from $ftrows
543 *
544 * @param array Array of records selected from index_rel/index_words
545 * @param string Header string to show before table.
546 * @param boolean If set, the stopWord checkboxes will be shown in the word list. Only for admins. (because it is a global setting, not per-site).
547 * @param array The page record from which to load the keywords, if any.
548 * @return string HTML table
549 * @todo Define visibility
550 */
551 public function listWords($ftrows, $header, $stopWordBoxes = FALSE, $page = '') {
552 // Prepare keywords:
553 $keywords = is_array($page) ? array_flip(GeneralUtility::trimExplode(',', $page['keywords'], TRUE)) : '';
554 // Render list:
555 $trows = '';
556 $trows .= '
557 <tr class="tableheader bgColor5">
558 ' . ($stopWordBoxes ? '<td>' . htmlspecialchars('Stopword:') . '</td>' : '') . '
559 <td>' . htmlspecialchars('Word:') . '</td>
560 <td>' . htmlspecialchars('Count:') . '</td>
561 <td>' . htmlspecialchars('First:') . '</td>
562 <td>' . htmlspecialchars('Frequency:') . '</td>
563 <td>' . htmlspecialchars('Flags:') . '</td>
564 ' . (is_array($keywords) ? '<td>' . htmlspecialchars('Page keyword:') . '</td>' : '') . '
565 </tr>
566 ';
567 foreach ($ftrows as $row) {
568 $hiddenField = $stopWordBoxes != 2 ? '<input type="hidden" name="stopWord[' . $row['wid'] . ']" value="0" />' : '';
569 $trows .= '
570 <tr class="' . ($row['is_stopword'] ? 'bgColor' : 'bgColor4') . '">
571 ' . ($stopWordBoxes ? '<td align="center"' . ($row['is_stopword'] ? ' style="background-color:red;"' : '') . '>' . $hiddenField . '<input type="checkbox" name="stopWord[' . $row['wid'] . ']" value="1"' . ($row['is_stopword'] ? 'checked="checked"' : '') . ' /></td>' : '') . '
572 <td>' . $this->linkWordDetails(htmlspecialchars($row['baseword']), $row['wid']) . '</td>
573 <td>' . htmlspecialchars($row['count']) . '</td>
574 <td>' . htmlspecialchars($row['first']) . '</td>
575 <td>' . htmlspecialchars($row['freq']) . '</td>
576 <td>' . htmlspecialchars($this->flagsMsg($row['flags'])) . '</td>
577 ' . (is_array($keywords) ? '<td align="center"' . (isset($keywords[$row['baseword']]) ? ' class="bgColor2"' : '') . '><input type="hidden" name="pageKeyword[' . $row['baseword'] . ']" value="0" /><input type="checkbox" name="pageKeyword[' . $row['baseword'] . ']" value="1"' . (isset($keywords[$row['baseword']]) ? 'checked="checked"' : '') . ' /></td>' : '') . '
578 </tr>
579 ';
580 }
581 return '<h4>' . htmlspecialchars($header) . '</h4>' . '
582 <table border="0" cellspacing="1" cellpadding="2" class="c-list">
583 ' . $trows . '
584 </table>' . ($stopWordBoxes ? '<input type="submit" value="Change stop-word settings" name="_stopwords" onclick="document.webinfoForm.action=\'' . htmlspecialchars(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';" />' : '') . (is_array($keywords) ? '<input type="submit" value="Set page keywords" name="_pageKeywords" onclick="document.webinfoForm.action=\'' . htmlspecialchars(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';" /><input type="hidden" name="pageKeyword_pageUid" value="' . $page['uid'] . '" />' . '<br />Current keywords are: <em>' . htmlspecialchars(implode(', ', array_keys($keywords))) . '</em>' : '');
585 }
586
587 /**
588 * Displays table of metaphone groups larger than 1
589 *
590 * @param array Result from word selection (index_rel/index_words)
591 * @param string Header string
592 * @return string HTML table
593 * @todo Define visibility
594 */
595 public function listMetaphoneStat($ftrows, $header) {
596 $trows = '';
597 $trows .= '
598 <tr class="tableheader bgColor5">
599 <td>' . htmlspecialchars('Metaphone:') . '</td>
600 <td>' . htmlspecialchars('Hash:') . '</td>
601 <td>' . htmlspecialchars('Count:') . '</td>
602 <td>' . htmlspecialchars('Words:') . '</td>
603 </tr>
604 ';
605 foreach ($ftrows as $metaphone => $words) {
606 if (count($words) > 1) {
607 $trows .= '
608 <tr class="bgColor4">
609 <td>' . $this->linkMetaPhoneDetails($this->indexerObj->metaphone($words[0], 1), $metaphone) . '</td>
610 <td>' . htmlspecialchars($metaphone) . '</td>
611 <td>' . htmlspecialchars(count($words)) . '</td>
612 <td style="white-space: normal;">' . htmlspecialchars(implode(', ', $words)) . '</td>
613 </tr>
614 ';
615 }
616 }
617 return '<h4>' . htmlspecialchars($header) . '</h4>' . '<table border="0" cellspacing="1" cellpadding="2" class="c-list">
618 ' . $trows . '
619 </table>';
620 }
621
622 /**
623 * Wraps input string in a link that will display details for the word. Eg. which other pages has the word, metaphone associations etc.
624 *
625 * @param string String to wrap, possibly a title or so.
626 * @param integer wid value to show details for
627 * @return string Wrapped string
628 * @todo Define visibility
629 */
630 public function linkWordDetails($string, $wid) {
631 return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('wid' => $wid, 'phash' => ''))) . '">' . $string . '</a>';
632 }
633
634 /**
635 * Wraps input string in a link to see more details for metaphone value
636 *
637 * @param string String to wrap
638 * @param integer Metaphone value
639 * @return string Wrapped string
640 * @todo Define visibility
641 */
642 public function linkMetaPhoneDetails($string, $metaphone) {
643 return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('metaphone' => $metaphone, 'wid' => '', 'phash' => ''))) . '">' . $string . '</a>';
644 }
645
646 /**
647 * Creates message for flag value
648 *
649 * @param integer Flags integer
650 * @return string Message string
651 * @todo Define visibility
652 */
653 public function flagsMsg($flags) {
654 if ($flags > 0) {
655 return ($flags & 128 ? '<title>' : '') . ($flags & 64 ? '<meta/keywords>' : '') . ($flags & 32 ? '<meta/description>' : '') . ' (' . $flags . ')';
656 }
657 }
658
659 /*******************************
660 *
661 * Details display, words / metaphone
662 *
663 *******************************/
664 /**
665 * Show details for words
666 *
667 * @param integer Word ID (wid)
668 * @return string HTML content
669 * @todo Define visibility
670 */
671 public function showDetailsForWord($wid) {
672 // Select references to this word
673 $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_phash.*, index_section.*, index_rel.*', 'index_rel, index_section, index_phash', 'index_rel.wid = ' . (int)$wid . ' AND index_rel.phash = index_section.phash' . ' AND index_section.phash = index_phash.phash', '', 'index_rel.freq DESC', '');
674 // Headers:
675 $content = '
676 <tr class="tableheader bgColor5">
677 <td>phash</td>
678 <td>page_id</td>
679 <td>data_filename</td>
680 <td>count</td>
681 <td>first</td>
682 <td>freq</td>
683 <td>flags</td>
684 </tr>';
685 if (is_array($ftrows)) {
686 foreach ($ftrows as $wDat) {
687 $content .= '
688 <tr class="bgColor4">
689 <td>' . $this->linkDetails(htmlspecialchars($wDat['phash']), $wDat['phash']) . '</td>
690 <td>' . htmlspecialchars($wDat['page_id']) . '</td>
691 <td>' . htmlspecialchars($wDat['data_filename']) . '</td>
692 <td>' . htmlspecialchars($wDat['count']) . '</td>
693 <td>' . htmlspecialchars($wDat['first']) . '</td>
694 <td>' . htmlspecialchars($wDat['freq']) . '</td>
695 <td>' . htmlspecialchars($wDat['flags']) . '</td>
696 </tr>';
697 }
698 }
699 // Compile table:
700 $content = '
701 <table border="0" cellspacing="1" cellpadding="2" class="c-list">' . $content . '
702 </table>';
703 // Add go-back link:
704 $content = $content . $this->linkList();
705 return $content;
706 }
707
708 /**
709 * Show details for metaphone value
710 *
711 * @param integer Metaphone integer hash
712 * @return string HTML content
713 * @todo Define visibility
714 */
715 public function showDetailsForMetaphone($metaphone) {
716 // Finding top-20 on frequency for this phash:
717 $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_words.*', 'index_words', 'index_words.metaphone = ' . (int)$metaphone, '', 'index_words.baseword', '');
718 if (count($ftrows)) {
719 $content .= '<h4>Metaphone: ' . $this->indexerObj->metaphone($ftrows[0]['baseword'], 1) . '</h4>';
720 $content .= '
721 <tr class="tableheader bgColor5">
722 <td>Word</td>
723 <td>Is stopword?</td>
724 </tr>';
725 if (is_array($ftrows)) {
726 foreach ($ftrows as $wDat) {
727 $content .= '
728 <tr class="bgColor4">
729 <td>' . $this->linkWordDetails(htmlspecialchars($wDat['baseword']), $wDat['wid']) . '</td>
730 <td>' . htmlspecialchars(($wDat['is_stopword'] ? 'YES' : 'No')) . '</td>
731 </tr>';
732 }
733 }
734 $content = '
735 <table border="0" cellspacing="1" cellpadding="2" class="c-list">' . $content . '
736 </table>';
737 if ($this->indexerObj->metaphone($ftrows[0]['baseword']) != $metaphone) {
738 $content .= 'ERROR: Metaphone string and hash did not match for some reason!?';
739 }
740 // Add go-back link:
741 $content = $content . $this->linkList();
742 }
743 return $content;
744 }
745
746 /*******************************
747 *
748 * Helper functions
749 *
750 *******************************/
751 /**
752 * Creates icon which clears indexes for a certain list of phash values.
753 *
754 * @param string List of phash integers
755 * @param string Alt-text for the garbage bin icon.
756 * @return string HTML img-tag with link around.
757 * @todo Define visibility
758 */
759 public function printRemoveIndexed($phash, $alt) {
760 return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('deletePhash' => $phash))) . '" title="' . htmlspecialchars($alt) . '">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-delete') . '</a>';
761 }
762
763 /**
764 * Button for re-indexing of documents
765 *
766 * @param array phash table result row.
767 * @param string Title attribute text for icon
768 * @return string HTML content; Icon wrapped in link.
769 * @todo Define visibility
770 */
771 public function printReindex($resultRow, $alt) {
772 if ($resultRow['item_type'] && $resultRow['item_type'] !== '0') {
773 return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('reindex' => $resultRow['phash'], 'reindex_id' => $resultRow['page_id']))) . '">' . '<img ' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/refresh_n.gif', 'width="14" height="14"') . ' hspace="1" vspace="2" border="0" title="' . htmlspecialchars($alt) . '" alt="" />' . '</a>';
774 }
775 }
776
777 /**
778 * Wraps input string in a link that will display details for the phash value set.
779 *
780 * @param string String to wrap, possibly a title or so.
781 * @param integer phash value to show details for
782 * @return string Wrapped string
783 * @todo Define visibility
784 */
785 public function linkDetails($string, $phash) {
786 return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('phash' => $phash))) . '">' . $string . '</a>';
787 }
788
789 /**
790 * Creates link back to listing
791 *
792 * @return string Link back to list
793 * @todo Define visibility
794 */
795 public function linkList() {
796 return '<br /><a href="' . htmlspecialchars(BackendUtility::getModuleUrl('web_info', array('id' => $this->pObj->id))) . '">Back to list.</a><br />';
797 }
798
799 /**
800 * Wraps input string in a link that will display details for the phash value set.
801 *
802 * @param string String to wrap, possibly a title or so.
803 * @param integer phash value to show details for
804 * @return string Wrapped string
805 * @todo Define visibility
806 */
807 public function showPageDetails($string, $id) {
808 return '<a href="' . htmlspecialchars(BackendUtility::getModuleUrl('web_info', array('id' => $id, 'SET' => array('depth' => 0, 'type' => 1)))) . '">' . $string . '</a>';
809 }
810
811 /**
812 * Prints the gr_lists attached to a indexed entry.
813 *
814 * @param array Array of index_grlist records
815 * @return string HTML code.
816 * @todo Define visibility
817 */
818 public function printExtraGrListRows($extraGrListRows) {
819 if (count($extraGrListRows)) {
820 $lines = array();
821 foreach ($extraGrListRows as $r) {
822 $lines[] = $r['gr_list'];
823 }
824 return '<br />' . $GLOBALS['TBE_TEMPLATE']->dfw(implode('<br />', $lines));
825 }
826 }
827
828 /**
829 * Print path for indexing
830 *
831 * @param array Result row with content from index_section
832 * @return string Rootline information
833 * @todo Define visibility
834 */
835 public function printRootlineInfo($row) {
836 $uidCollection = array();
837 if ($row['rl0']) {
838 $uidCollection[0] = $row['rl0'];
839 if ($row['rl1']) {
840 $uidCollection[1] = $row['rl1'];
841 if ($row['rl2']) {
842 $uidCollection[2] = $row['rl2'];
843 // Additional levels:
844 if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['addRootLineFields'])) {
845 foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['addRootLineFields'] as $fieldName => $rootLineLevel) {
846 if ($row[$fieldName]) {
847 $uidCollection[$rootLineLevel] = $row[$fieldName];
848 }
849 }
850 }
851 }
852 }
853 }
854 // Return root line.
855 ksort($uidCollection);
856 return implode('/', $uidCollection);
857 }
858
859 /**
860 * Return icon for file extension
861 *
862 * @param string File extension / item type
863 * @param string Title attribute value in icon.
864 * @return string <img> tag for icon
865 * @todo Define visibility
866 */
867 public function makeItemTypeIcon($it, $alt = '') {
868 if (!isset($this->iconFileNameCache[$it])) {
869 if ($it === '0') {
870 $icon = 'EXT:indexed_search/pi/res/pages.gif';
871 } elseif ($this->external_parsers[$it]) {
872 $icon = $this->external_parsers[$it]->getIcon($it);
873 }
874 $fullPath = GeneralUtility::getFileAbsFileName($icon);
875 if ($fullPath) {
876 $info = @getimagesize($fullPath);
877 $iconPath = $GLOBALS['BACK_PATH'] . '../' . \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($fullPath);
878 $this->iconFileNameCache[$it] = is_array($info) ? '<img src="' . $iconPath . '" ' . $info[3] . ' title="###TITLE_ATTRIBUTE###" alt="" />' : '';
879 }
880 }
881 return str_replace('###TITLE_ATTRIBUTE###', htmlspecialchars($it . ': ' . $alt), $this->iconFileNameCache[$it]);
882 }
883
884 /********************************
885 *
886 * Reindexing
887 *
888 *******************************/
889 /**
890 * Re-indexing files/records attached to a page.
891 *
892 * @param integer Phash value
893 * @param integer The page uid for the section record (file/url could appear more than one place you know...)
894 * @return string HTML content
895 * @todo Define visibility
896 */
897 public function reindexPhash($phash, $pageId) {
898 // Query:
899 $resultRow = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('ISEC.*, IP.*', 'index_phash IP, index_section ISEC', 'IP.phash = ISEC.phash
900 AND IP.phash = ' . (int)$phash . '
901 AND ISEC.page_id = ' . (int)$pageId);
902 $content = '';
903 if (is_array($resultRow)) {
904 if ($resultRow['item_type'] && $resultRow['item_type'] !== '0') {
905 // (Re)-Indexing file on page.
906 $indexerObj = GeneralUtility::makeInstance('TYPO3\\CMS\\IndexedSearch\\Indexer');
907 $indexerObj->backend_initIndexer($pageId, 0, 0, '', $this->getUidRootLineForClosestTemplate($pageId));
908 // URL or local file:
909 if ($resultRow['externalUrl']) {
910 $indexerObj->indexExternalUrl($resultRow['data_filename']);
911 } else {
912 $indexerObj->indexRegularDocument($resultRow['data_filename'], TRUE);
913 }
914 if ($indexerObj->file_phash_arr['phash'] != $resultRow['phash']) {
915 $content .= 'ERROR: phash (' . $indexerObj->file_phash_arr['phash'] . ') did NOT match ' . $resultRow['phash'] . ' for strange reasons!';
916 }
917 $content .= '<h4>Log for re-indexing of "' . htmlspecialchars($resultRow['data_filename']) . '":</h4>';
918 $content .= \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($indexerObj->internal_log);
919 $content .= '<h4>Hash-array, page:</h4>';
920 $content .= \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($indexerObj->hash);
921 $content .= '<h4>Hash-array, file:</h4>';
922 $content .= \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($indexerObj->file_phash_arr);
923 }
924 }
925 // Link back to list.
926 $content .= $this->linkList();
927 return $content;
928 }
929
930 /**
931 * Get rootline for closest TypoScript template root.
932 * Algorithm same as used in Web > Template, Object browser
933 *
934 * @param integer The page id to traverse rootline back from
935 * @return array Array where the root lines uid values are found.
936 * @todo Define visibility
937 */
938 public function getUidRootLineForClosestTemplate($id) {
939 $tmpl = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\ExtendedTemplateService');
940 // Defined global here!
941 $tmpl->tt_track = 0;
942 // Do not log time-performance information
943 $tmpl->init();
944 // Gets the rootLine
945 $sys_page = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
946 $rootLine = $sys_page->getRootLine($id);
947 $tmpl->runThroughTemplates($rootLine, 0);
948 // This generates the constants/config + hierarchy info for the template.
949 // Root line uids
950 $rootline_uids = array();
951 foreach ($tmpl->rootLine as $rlkey => $rldat) {
952 $rootline_uids[$rlkey] = $rldat['uid'];
953 }
954 return $rootline_uids;
955 }
956
957 /********************************
958 *
959 * SQL functions
960 *
961 *******************************/
962 /**
963 * Removes ALL data regarding a certain list of indexed phash-row
964 *
965 * @param string List of phash integers
966 * @param boolean If set, page cache is cleared as well.
967 * @return void
968 * @todo Define visibility
969 */
970 public function removeIndexedPhashRow($phashList, $clearPageCache = 1) {
971 // FIXME: This is only a workaround
972 if ($phashList == 'ALL') {
973 $this->drawTableOfIndexedPages();
974 $phashRows = $this->allPhashListed;
975 $this->allPhashListed = array();
976 } else {
977 $phashRows = GeneralUtility::trimExplode(',', $phashList, TRUE);
978 }
979 foreach ($phashRows as $phash) {
980 $phash = (int)$phash;
981 if ($phash > 0) {
982 if ($clearPageCache) {
983 // Clearing page cache:
984 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('page_id', 'index_section', 'phash=' . (int)$phash);
985 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
986 $idList = array();
987 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
988 $idList[] = (int)$row['page_id'];
989 }
990 $pageCache = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_pages');
991 foreach ($idList as $pageId) {
992 $pageCache->flushByTag('pageId_' . $pageId);
993 }
994 }
995 }
996 // Removing old registrations for all tables.
997 $tableArr = explode(',', 'index_phash,index_rel,index_section,index_grlist,index_fulltext,index_debug');
998 foreach ($tableArr as $table) {
999 $GLOBALS['TYPO3_DB']->exec_DELETEquery($table, 'phash=' . (int)$phash);
1000 }
1001 }
1002 }
1003 }
1004
1005 /**
1006 * Returns an array with gr_list records for a phash
1007 *
1008 * @param integer phash integer to look up on
1009 * @param string gr_list string to filter OUT of the result (first occurence)
1010 * @return array Array of records from index_grlist table
1011 * @todo Define visibility
1012 */
1013 public function getGrListEntriesForPhash($phash, $gr_list) {
1014 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'index_grlist', 'phash=' . (int)$phash);
1015 $lines = array();
1016 $isRemoved = 0;
1017 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
1018 if (!$isRemoved && (string)$row['gr_list'] === (string)$gr_list) {
1019 $isRemoved = 1;
1020 } else {
1021 $lines[] = $row;
1022 }
1023 }
1024 return $lines;
1025 }
1026
1027 /**
1028 * Setting / Unsetting stopwords
1029 *
1030 * @param array Array of stop-words WIDs with 0/1 to set / unset
1031 * @return void
1032 * @todo Define visibility
1033 */
1034 public function processStopWords($stopWords) {
1035 if ($GLOBALS['BE_USER']->isAdmin()) {
1036 // Traverse words
1037 foreach ($stopWords as $wid => $state) {
1038 $fieldArray = array(
1039 'is_stopword' => $state
1040 );
1041 $GLOBALS['TYPO3_DB']->exec_UPDATEquery('index_words', 'wid=' . $wid, $fieldArray);
1042 }
1043 }
1044 }
1045
1046 /**
1047 * Setting / Unsetting keywords in page header
1048 *
1049 * @param array Page keywords as keys in array with value 0 or 1 for set or unset.
1050 * @param integer The page uid of the header where the keywords are to be set.
1051 * @return void
1052 * @todo Define visibility
1053 */
1054 public function processPageKeywords($pageKeywords, $pageUid) {
1055 // Get pages current keywords
1056 $pageRec = BackendUtility::getRecord('pages', $pageUid);
1057 $keywords = array_flip(GeneralUtility::trimExplode(',', $pageRec['keywords'], TRUE));
1058 // Merge keywords:
1059 foreach ($pageKeywords as $key => $v) {
1060 if ($v) {
1061 $keywords[$key] = 1;
1062 } else {
1063 unset($keywords[$key]);
1064 }
1065 }
1066 // Compile new list:
1067 $data = array();
1068 $data['pages'][$pageUid]['keywords'] = implode(', ', array_keys($keywords));
1069 $tce = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\DataHandling\\DataHandler');
1070 $tce->stripslashes_values = 0;
1071 $tce->start($data, array());
1072 $tce->process_datamap();
1073 }
1074
1075 }