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