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