TYPO3 CMS  TYPO3_6-2
IndexedPagesController.php
Go to the documentation of this file.
1 <?php
3 
19 
26 
27  // Internal, dynamic:
31  public $allPhashListed = array();
32 
33  // phash values accumulations for link to clear all
37  public $external_parsers = array();
38 
39  // External content parsers - objects set here with file extensions as keys.
43  public $iconFileNameCache = array();
44 
45  // File extensions - icon map/cache.
49  public $indexerConfig = array();
50 
51  // Indexer configuration, coming from $GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['indexed_search']
55  public $enableMetaphoneSearch = FALSE;
56 
63  public $indexerObj;
64 
68  protected $maxListPerPage;
69 
73  public function __construct() {
74  $GLOBALS['LANG']->includeLLFile('EXT:indexed_search/modfunc1/locallang.xlf');
75  }
76 
83  public function modMenu() {
84  global $LANG;
85  return array(
86  'depth' => array(
87  0 => $LANG->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_0'),
88  1 => $LANG->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_1'),
89  2 => $LANG->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_2'),
90  3 => $LANG->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_3'),
91  999 => $LANG->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_infi')
92  ),
93  'type' => array(
94  0 => 'Overview',
95  1 => 'Technical Details',
96  2 => 'Words and content'
97  )
98  );
99  }
100 
107  public function main() {
108  // Initializes the module. Done in this function because we may need to re-initialize if data is submitted!
109  global $LANG, $TYPO3_CONF_VARS;
110  // Return if no page id:
111  if ($this->pObj->id <= 0) {
112  return;
113  }
114  // Indexer configuration from Extension Manager interface:
115  $this->indexerConfig = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['indexed_search']);
116  // Workaround: If the extension configuration was not updated yet, the value is not existing
117  $this->enableMetaphoneSearch = isset($this->indexerConfig['enableMetaphoneSearch']) ? ($this->indexerConfig['enableMetaphoneSearch'] ? TRUE : FALSE) : TRUE;
118  // Initialize max-list items
119  $this->maxListPerPage = GeneralUtility::_GP('listAll') ? 100000 : 100;
120  // Processing deletion of phash rows:
121  if (GeneralUtility::_GP('deletePhash')) {
122  $this->removeIndexedPhashRow(GeneralUtility::_GP('deletePhash'));
123  }
124  // Processing stop-words:
125  if (GeneralUtility::_POST('_stopwords')) {
126  $this->processStopWords(GeneralUtility::_POST('stopWord'));
127  }
128  // Processing stop-words:
129  if (GeneralUtility::_POST('_pageKeywords')) {
130  $this->processPageKeywords(GeneralUtility::_POST('pageKeyword'), GeneralUtility::_POST('pageKeyword_pageUid'));
131  }
132  // Initialize external document parsers:
133  // Example configuration, see ext_localconf.php of this file!
134  if (is_array($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['external_parsers'])) {
135  foreach ($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['external_parsers'] as $extension => $_objRef) {
136  $this->external_parsers[$extension] = GeneralUtility::getUserObj($_objRef);
137  // Init parser and if it returns FALSE, unset its entry again:
138  if (!$this->external_parsers[$extension]->softInit($extension)) {
139  unset($this->external_parsers[$extension]);
140  }
141  }
142  }
143  // Initialize indexer if we need it (metaphone display does...)
144  $this->indexerObj = GeneralUtility::makeInstance('TYPO3\\CMS\\IndexedSearch\\Indexer');
145  // Set CSS styles specific for this document:
146  $this->pObj->content = str_replace('/*###POSTCSSMARKER###*/', '
147  TABLE.c-list TR TD { white-space: nowrap; vertical-align: top; }
148  ', $this->pObj->content);
149  // Check if details for a phash record should be shown:
150  if (GeneralUtility::_GET('phash')) {
151  // Show title / function menu:
152  $theOutput .= $this->pObj->doc->spacer(5);
153  $theOutput .= $this->pObj->doc->section('Details for a single result row:', $this->showDetailsForPhash(GeneralUtility::_GET('phash')), 0, 1);
154  } elseif (GeneralUtility::_GET('wid')) {
155  // Show title / function menu:
156  $theOutput .= $this->pObj->doc->spacer(5);
157  $theOutput .= $this->pObj->doc->section('Details for a word:', $this->showDetailsForWord(GeneralUtility::_GET('wid')), 0, 1);
158  } elseif ($this->enableMetaphoneSearch && GeneralUtility::_GET('metaphone')) {
159  // Show title / function menu:
160  $theOutput .= $this->pObj->doc->spacer(5);
161  $theOutput .= $this->pObj->doc->section('Details for metaphone value:', $this->showDetailsForMetaphone(GeneralUtility::_GET('metaphone')), 0, 1);
162  } elseif (GeneralUtility::_GET('reindex')) {
163  // Show title / function menu:
164  $theOutput .= $this->pObj->doc->spacer(5);
165  $theOutput .= $this->pObj->doc->section('Reindexing...', $this->reindexPhash(GeneralUtility::_GET('reindex'), GeneralUtility::_GET('reindex_id')), 0, 1);
166  } else {
167  // Detail listings:
168  // Depth function menu:
169  $h_func = BackendUtility::getFuncMenu($this->pObj->id, 'SET[type]', $this->pObj->MOD_SETTINGS['type'], $this->pObj->MOD_MENU['type']);
170  $h_func .= BackendUtility::getFuncMenu($this->pObj->id, 'SET[depth]', $this->pObj->MOD_SETTINGS['depth'], $this->pObj->MOD_MENU['depth']);
171  // Show title / function menu:
172  $theOutput .= $this->pObj->doc->header($LANG->getLL('title'));
173  $theOutput .= $this->pObj->doc->section('', $h_func, 0, 1);
174  $theOutput .= $this->drawTableOfIndexedPages();
175  }
176  return $theOutput;
177  }
178 
179  /*******************************
180  *
181  * Drawing table of indexed pages
182  *
183  ******************************/
190  public function drawTableOfIndexedPages() {
191  global $BACK_PATH;
192  // Drawing tree:
193  $tree = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Tree\\View\\PageTreeView');
194  $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
195  $tree->init('AND ' . $perms_clause);
196  $HTML = '<img src="' . $BACK_PATH . \TYPO3\CMS\Backend\Utility\IconUtility::getIcon('pages', $this->pObj->pageinfo) . '" width="18" height="16" align="top" alt="" />';
197  $tree->tree[] = array(
198  'row' => $this->pObj->pageinfo,
199  'HTML' => $HTML
200  );
201  if ($this->pObj->MOD_SETTINGS['depth']) {
202  $tree->getTree($this->pObj->id, $this->pObj->MOD_SETTINGS['depth'], '');
203  }
204  // Traverse page tree:
205  $code = '';
206  foreach ($tree->tree as $data) {
207  $code .= $this->indexed_info($data['row'], $data['HTML'] . $this->showPageDetails(
208  BackendUtility::getRecordTitlePrep($data['row']['title']), $data['row']['uid']));
209  }
210  if ($code) {
211  $code = '<br /><br />
212  <table border="0" cellspacing="1" cellpadding="2" class="c-list">' . $this->printPhashRowHeader() . $code . '</table>';
213  // Create section to output:
214  $theOutput .= $this->pObj->doc->section('', $code, 0, 1);
215  } else {
216  $theOutput .= $this->pObj->doc->section('', '<br /><br />' . $this->pObj->doc->icons(1) . 'There were no indexed pages found in the tree.<br /><br />', 0, 1);
217  }
218  return $theOutput;
219  }
220 
229  public function indexed_info($data, $firstColContent) {
230  // Query:
231  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('ISEC.phash_t3, ISEC.rl0, ISEC.rl1, ISEC.rl2, ISEC.page_id, ISEC.uniqid, ' . 'IP.phash, IP.phash_grouping, IP.cHashParams, IP.data_filename, IP.data_page_id, ' . 'IP.data_page_reg1, IP.data_page_type, IP.data_page_mp, IP.gr_list, IP.item_type, ' . 'IP.item_title, IP.item_description, IP.item_mtime, IP.tstamp, IP.item_size, ' . 'IP.contentHash, IP.crdate, IP.parsetime, IP.sys_language_uid, IP.item_crdate, ' . 'IP.externalUrl, IP.recordUid, IP.freeIndexUid, IP.freeIndexSetId, count(*) AS count_val', 'index_phash IP, index_section ISEC', 'IP.phash = ISEC.phash AND ISEC.page_id = ' . (int)$data['uid'], 'IP.phash,IP.phash_grouping,IP.cHashParams,IP.data_filename,IP.data_page_id,IP.data_page_reg1,IP.data_page_type,IP.data_page_mp,IP.gr_list,IP.item_type,IP.item_title,IP.item_description,IP.item_mtime,IP.tstamp,IP.item_size,IP.contentHash,IP.crdate,IP.parsetime,IP.sys_language_uid,IP.item_crdate,ISEC.phash,ISEC.phash_t3,ISEC.rl0,ISEC.rl1,ISEC.rl2,ISEC.page_id,ISEC.uniqid,IP.externalUrl,IP.recordUid,IP.freeIndexUid,IP.freeIndexSetId', 'IP.item_type, IP.tstamp', $this->maxListPerPage + 1);
232  // Initialize variables:
233  $rowCount = 0;
234  $lines = array();
235  // Collecting HTML rows here.
236  $phashAcc = array();
237  // Collecting phash values (to remove local indexing for)
238  $phashAcc[] = 0;
239  // Traverse the result set of phash rows selected:
240  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
241  if ($rowCount == $this->maxListPerPage) {
242  $rowCount++;
243  // Increase to the extra warning row will appear as well.
244  break;
245  }
246  // Adds a display row:
247  $lines[$row['phash_grouping']][] = $this->printPhashRow($row, isset($lines[$row['phash_grouping']]), $this->getGrListEntriesForPhash($row['phash'], $row['gr_list']));
248  $rowCount++;
249  $phashAcc[] = $row['phash'];
250  $this->allPhashListed[] = $row['phash'];
251  }
252  // Compile rows into the table:
253  $out = '';
254  $cellAttrib = $data['_CSSCLASS'] ? ' class="' . $data['_CSSCLASS'] . '"' : '';
255  if (count($lines)) {
256  $firstColContent = '<td rowspan="' . $rowCount . '"' . $cellAttrib . '>' . $firstColContent . '</td>';
257  foreach ($lines as $rowSet) {
258  foreach ($rowSet as $rows) {
259  $out .= '
260  <tr class="bgColor-20">' . $firstColContent . implode('', $rows) . '</tr>';
261  $firstColContent = '';
262  }
263  }
264  if ($rowCount > $this->maxListPerPage) {
265  // Now checking greater than, because we increased $rowCount before...
266  $out .= '
267  <tr class="bgColor-20">
268  <td>&nbsp;</td>
269  <td colspan="' . ($this->returnNumberOfColumns() - 1) . '">' . $this->pObj->doc->icons(3) . '<span class="">There were more than ' . $this->maxListPerPage . ' rows. <a href="' . htmlspecialchars(BackendUtility::getModuleUrl('web_info', array('id' => $this->pObj->id, 'listAll' => 1))) . '">Click here to list them ALL!</a></span></td>
270  </tr>';
271  }
272  } else {
273  $out .= '
274  <tr class="bgColor-20">
275  <td' . $cellAttrib . '>' . $firstColContent . '</td>
276  <td colspan="' . ($this->returnNumberOfColumns() - 1) . '"><em>Not indexed</em></td>
277  </tr>';
278  }
279  // Checking for phash-rows which are NOT joined with the section table:
280  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('IP.*', 'index_phash IP', 'IP.data_page_id = ' . (int)$data['uid'] . ' AND IP.phash NOT IN (' . implode(',', $phashAcc) . ')');
281  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
282  $out .= '
283  <tr class="typo3-red">
284  <td colspan="' . $this->returnNumberOfColumns() . '"><strong>Warning:</strong> phash-row "' . $row['phash'] . '" didn\'t have a representation in the index_section table!</td>
285  </tr>';
286  $this->allPhashListed[] = $row['phash'];
287  }
288  return $out;
289  }
290 
301  public function printPhashRow($row, $grouping = 0, $extraGrListRows) {
302  $lines = array();
303  // Title cell attributes will highlight TYPO3 pages with a slightly darker color (bgColor4) than attached medias. Also IF there are more than one section record for a phash row it will be red as a warning that something is wrong!
304  $titleCellAttribs = $row['count_val'] != 1 ? ' bgcolor="red"' : ($row['item_type'] === '0' ? ' class="bgColor4"' : '');
305  if ($row['item_type']) {
306  $arr = unserialize($row['cHashParams']);
307  $page = $arr['key'] ? ' [' . $arr['key'] . ']' : '';
308  } else {
309  $page = '';
310  }
311  $elTitle = $this->linkDetails($row['item_title'] ? htmlspecialchars(GeneralUtility::fixed_lgd_cs($row['item_title'], 20) . $page) : '<em>[No Title]</em>', $row['phash']);
312  $cmdLinks = $this->printRemoveIndexed($row['phash'], 'Clear phash-row') . $this->printReindex($row, 'Re-index element');
313  switch ($this->pObj->MOD_SETTINGS['type']) {
314  case 1:
315  // Technical details:
316  // Display icon:
317  if (!$grouping) {
318  $lines[] = '<td>' . $this->makeItemTypeIcon($row['item_type'], ($row['data_filename'] ? $row['data_filename'] : $row['item_title'])) . '</td>';
319  } else {
320  $lines[] = '<td>&nbsp;</td>';
321  }
322  // Title displayed:
323  $lines[] = '<td' . $titleCellAttribs . '>' . $elTitle . '</td>';
324  // Remove-indexing-link:
325  $lines[] = '<td>' . $cmdLinks . '</td>';
326  // Various data:
327  $lines[] = '<td>' . $row['phash'] . '</td>';
328  $lines[] = '<td>' . $row['contentHash'] . '</td>';
329  if ($row['item_type'] === '0') {
330  $lines[] = '<td>' . ($row['data_page_id'] ? $row['data_page_id'] : '&nbsp;') . '</td>';
331  $lines[] = '<td>' . ($row['data_page_type'] ? $row['data_page_type'] : '&nbsp;') . '</td>';
332  $lines[] = '<td>' . ($row['sys_language_uid'] ? $row['sys_language_uid'] : '&nbsp;') . '</td>';
333  $lines[] = '<td>' . ($row['data_page_mp'] ? $row['data_page_mp'] : '&nbsp;') . '</td>';
334  } else {
335  $lines[] = '<td colspan="4">' . htmlspecialchars($row['data_filename']) . '</td>';
336  }
337  $lines[] = '<td>' . $row['gr_list'] . $this->printExtraGrListRows($extraGrListRows) . '</td>';
338  $lines[] = '<td>' . $this->printRootlineInfo($row) . '</td>';
339  $lines[] = '<td>' . ($row['page_id'] ? $row['page_id'] : '&nbsp;') . '</td>';
340  $lines[] = '<td>' . ($row['phash_t3'] != $row['phash'] ? $row['phash_t3'] : '&nbsp;') . '</td>';
341  $lines[] = '<td>' . ($row['freeIndexUid'] ? $row['freeIndexUid'] . ($row['freeIndexSetId'] ? '/' . $row['freeIndexSetId'] : '') : '&nbsp;') . '</td>';
342  $lines[] = '<td>' . ($row['recordUid'] ? $row['recordUid'] : '&nbsp;') . '</td>';
343  // cHash parameters:
344  $arr = unserialize($row['cHashParams']);
345  if (!is_array($arr)) {
346  $arr = array(
347  'cHash' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_general.xlf:LGL.error', TRUE)
348  );
349  }
350  $theCHash = $arr['cHash'];
351  unset($arr['cHash']);
352  if ($row['item_type']) {
353  // pdf...
354  $lines[] = '<td>' . ($arr['key'] ? 'Page ' . $arr['key'] : '') . '&nbsp;</td>';
355  } elseif ($row['item_type'] == 0) {
356  $lines[] = '<td>' . htmlspecialchars(GeneralUtility::implodeArrayForUrl('', $arr)) . '&nbsp;</td>';
357  } else {
358  $lines[] = '<td class="bgColor">&nbsp;</td>';
359  }
360  $lines[] = '<td>' . $theCHash . '</td>';
361  break;
362  case 2:
363  // Words and content:
364  // Display icon:
365  if (!$grouping) {
366  $lines[] = '<td>' . $this->makeItemTypeIcon($row['item_type'], ($row['data_filename'] ? $row['data_filename'] : $row['item_title'])) . '</td>';
367  } else {
368  $lines[] = '<td>&nbsp;</td>';
369  }
370  // Title displayed:
371  $lines[] = '<td' . $titleCellAttribs . '>' . $elTitle . '</td>';
372  // Remove-indexing-link:
373  $lines[] = '<td>' . $cmdLinks . '</td>';
374  // Query:
375  $ftrow = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'index_fulltext', 'phash = ' . (int)$row['phash']);
376  $lines[] = '<td style="white-space: normal;">' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($ftrow['fulltextdata'], 3000)) . '<hr/><em>Size: ' . strlen($ftrow['fulltextdata']) . '</em>' . '</td>';
377  // Query:
378  $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_words.baseword, index_rel.*', 'index_rel, index_words', 'index_rel.phash = ' . (int)$row['phash'] . ' AND index_words.wid = index_rel.wid', '', '', '', 'baseword');
379  $wordList = '';
380  if (is_array($ftrows)) {
381  $indexed_words = array_keys($ftrows);
382  sort($indexed_words);
383  $wordList = htmlspecialchars(implode(' ', $indexed_words));
384  $wordList .= '<hr/><em>Count: ' . count($indexed_words) . '</em>';
385  }
386  $lines[] = '<td style="white-space: normal;">' . $wordList . '</td>';
387  break;
388  default:
389  // Overview
390  // Display icon:
391  if (!$grouping) {
392  $lines[] = '<td>' . $this->makeItemTypeIcon($row['item_type'], ($row['data_filename'] ? $row['data_filename'] : $row['item_title'])) . '</td>';
393  } else {
394  $lines[] = '<td>&nbsp;</td>';
395  }
396  // Title displayed:
397  $lines[] = '<td' . $titleCellAttribs . '>' . $elTitle . '</td>';
398  // Remove-indexing-link:
399  $lines[] = '<td>' . $cmdLinks . '</td>';
400  $lines[] = '<td style="white-space: normal;">' . htmlspecialchars($row['item_description']) . '...</td>';
401  $lines[] = '<td>' . GeneralUtility::formatSize($row['item_size']) . '</td>';
402  $lines[] = '<td>' . BackendUtility::dateTimeAge($row['tstamp']) . '</td>';
403  }
404  return $lines;
405  }
406 
413  public function printPhashRowHeader() {
414  $lines = array();
415  switch ($this->pObj->MOD_SETTINGS['type']) {
416  case 1:
417  $lines[] = '<td>&nbsp;</td>';
418  $lines[] = '<td>&nbsp;</td>';
419  $lines[] = '<td>Title</td>';
420  $lines[] = '<td bgcolor="red">' . $this->printRemoveIndexed('ALL', 'Clear ALL phash-rows below!') . '</td>';
421  $lines[] = '<td>pHash</td>';
422  $lines[] = '<td>contentHash</td>';
423  $lines[] = '<td>&amp;id</td>';
424  $lines[] = '<td>&amp;type</td>';
425  $lines[] = '<td>&amp;L</td>';
426  $lines[] = '<td>&amp;MP</td>';
427  $lines[] = '<td>grlist</td>';
428  $lines[] = '<td>Rootline</td>';
429  $lines[] = '<td>page_id</td>';
430  $lines[] = '<td>phash_t3</td>';
431  $lines[] = '<td>CfgUid</td>';
432  $lines[] = '<td>RecUid</td>';
433  $lines[] = '<td>GET-parameters</td>';
434  $lines[] = '<td>&amp;cHash</td>';
435  break;
436  case 2:
437  $lines[] = '<td>&nbsp;</td>';
438  $lines[] = '<td>&nbsp;</td>';
439  $lines[] = '<td>Title</td>';
440  $lines[] = '<td bgcolor="red">' . $this->printRemoveIndexed('ALL', 'Clear ALL phash-rows below!') . '</td>';
441  $lines[] = '<td>Content<br />
442  <img src="clear.gif" width="300" height="1" alt="" /></td>';
443  $lines[] = '<td>Words<br />
444  <img src="clear.gif" width="300" height="1" alt="" /></td>';
445  break;
446  default:
447  $lines[] = '<td>&nbsp;</td>';
448  $lines[] = '<td>&nbsp;</td>';
449  $lines[] = '<td>Title</td>';
450  $lines[] = '<td bgcolor="red">' . $this->printRemoveIndexed('ALL', 'Clear ALL phash-rows below!') . '</td>';
451  $lines[] = '<td>Description</td>';
452  $lines[] = '<td>Size</td>';
453  $lines[] = '<td>Indexed:</td>';
454  }
455  $out = '<tr class="tableheader bgColor5">' . implode('', $lines) . '</tr>';
456  return $out;
457  }
458 
465  public function returnNumberOfColumns() {
466  switch ($this->pObj->MOD_SETTINGS['type']) {
467  case 1:
468  return 18;
469  break;
470  case 2:
471  return 6;
472  break;
473  default:
474  return 7;
475  }
476  }
477 
478  /*******************************
479  *
480  * Details display, phash row
481  *
482  *******************************/
490  public function showDetailsForPhash($phash) {
491  $content = '';
492  $phash = (int)$phash;
493  // Selects the result row:
494  $phashRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'index_phash', 'phash = ' . $phash);
495  // If found, display:
496  if (is_array($phashRecord)) {
497  $content .= '<h4>phash row content:</h4>' . \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($phashRecord);
498  // Getting debug information if any:
499  $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'index_debug', 'phash = ' . $phash);
500  if (is_array($ftrows)) {
501  $debugInfo = unserialize($ftrows[0]['debuginfo']);
502  $lexer = $debugInfo['lexer'];
503  unset($debugInfo['lexer']);
504  $content .= '<h3>Debug information:</h3>' . \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($debugInfo);
505  $content .= '<h4>Debug information / lexer splitting:</h4>' . '<hr/><strong>' . $lexer . '</strong><hr/>';
506  }
507  $content .= '<h3>Word statistics</h3>';
508  // Finding all words for this phash:
509  $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_words.*, index_rel.*', 'index_rel, index_words', 'index_rel.phash = ' . $phash . ' AND index_words.wid = index_rel.wid', '', 'index_words.baseword', '');
510  $pageRec = BackendUtility::getRecord('pages', $phashRecord['data_page_id']);
511  $showStopWordCheckBox = $GLOBALS['BE_USER']->isAdmin();
512  $content .= $this->listWords($ftrows, 'All words found on page (' . count($ftrows) . '):', $showStopWordCheckBox, $pageRec);
513  if ($this->enableMetaphoneSearch) {
514  // Group metaphone hash:
515  $metaphone = array();
516  foreach ($ftrows as $row) {
517  $metaphone[$row['metaphone']][] = $row['baseword'];
518  }
519  $content .= $this->listMetaphoneStat($metaphone, 'Metaphone stats:');
520  }
521  // Finding top-20 on frequency for this phash:
522  $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_words.baseword, index_words.metaphone, index_rel.*', 'index_rel, index_words', 'index_rel.phash = ' . $phash . ' AND index_words.wid = index_rel.wid
523  AND index_words.is_stopword=0', '', 'index_rel.freq DESC', '20');
524  $content .= $this->listWords($ftrows, 'Top-20 words by frequency:', 2);
525  // Finding top-20 on count for this phash:
526  $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_words.baseword, index_words.metaphone, index_rel.*', 'index_rel, index_words', 'index_rel.phash = ' . $phash . ' AND index_words.wid = index_rel.wid
527  AND index_words.is_stopword=0', '', 'index_rel.count DESC', '20');
528  $content .= $this->listWords($ftrows, 'Top-20 words by count:', 2);
529  $content .= '<h3>Section records for this phash</h3>';
530  // Finding sections for this record:
531  $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'index_section', 'index_section.phash = ' . $phash, '', '', '');
533  // Add go-back link:
534  $content = $this->linkList() . $content . $this->linkList();
535  } else {
536  $content .= 'Error: No phash row found';
537  }
538  return $content;
539  }
540 
551  public function listWords($ftrows, $header, $stopWordBoxes = FALSE, $page = '') {
552  // Prepare keywords:
553  $keywords = is_array($page) ? array_flip(GeneralUtility::trimExplode(',', $page['keywords'], TRUE)) : '';
554  // Render list:
555  $trows = '';
556  $trows .= '
557  <tr class="tableheader bgColor5">
558  ' . ($stopWordBoxes ? '<td>' . htmlspecialchars('Stopword:') . '</td>' : '') . '
559  <td>' . htmlspecialchars('Word:') . '</td>
560  <td>' . htmlspecialchars('Count:') . '</td>
561  <td>' . htmlspecialchars('First:') . '</td>
562  <td>' . htmlspecialchars('Frequency:') . '</td>
563  <td>' . htmlspecialchars('Flags:') . '</td>
564  ' . (is_array($keywords) ? '<td>' . htmlspecialchars('Page keyword:') . '</td>' : '') . '
565  </tr>
566  ';
567  foreach ($ftrows as $row) {
568  $hiddenField = $stopWordBoxes != 2 ? '<input type="hidden" name="stopWord[' . $row['wid'] . ']" value="0" />' : '';
569  $trows .= '
570  <tr class="' . ($row['is_stopword'] ? 'bgColor' : 'bgColor4') . '">
571  ' . ($stopWordBoxes ? '<td align="center"' . ($row['is_stopword'] ? ' style="background-color:red;"' : '') . '>' . $hiddenField . '<input type="checkbox" name="stopWord[' . $row['wid'] . ']" value="1"' . ($row['is_stopword'] ? 'checked="checked"' : '') . ' /></td>' : '') . '
572  <td>' . $this->linkWordDetails(htmlspecialchars($row['baseword']), $row['wid']) . '</td>
573  <td>' . htmlspecialchars($row['count']) . '</td>
574  <td>' . htmlspecialchars($row['first']) . '</td>
575  <td>' . htmlspecialchars($row['freq']) . '</td>
576  <td>' . htmlspecialchars($this->flagsMsg($row['flags'])) . '</td>
577  ' . (is_array($keywords) ? '<td align="center"' . (isset($keywords[$row['baseword']]) ? ' class="bgColor2"' : '') . '><input type="hidden" name="pageKeyword[' . $row['baseword'] . ']" value="0" /><input type="checkbox" name="pageKeyword[' . $row['baseword'] . ']" value="1"' . (isset($keywords[$row['baseword']]) ? 'checked="checked"' : '') . ' /></td>' : '') . '
578  </tr>
579  ';
580  }
581  return '<h4>' . htmlspecialchars($header) . '</h4>' . '
582  <table border="0" cellspacing="1" cellpadding="2" class="c-list">
583  ' . $trows . '
584  </table>' . ($stopWordBoxes ? '<input type="submit" value="Change stop-word settings" name="_stopwords" onclick="document.webinfoForm.action=\'' . htmlspecialchars(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';" />' : '') . (is_array($keywords) ? '<input type="submit" value="Set page keywords" name="_pageKeywords" onclick="document.webinfoForm.action=\'' . htmlspecialchars(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';" /><input type="hidden" name="pageKeyword_pageUid" value="' . $page['uid'] . '" />' . '<br />Current keywords are: <em>' . htmlspecialchars(implode(', ', array_keys($keywords))) . '</em>' : '');
585  }
586 
595  public function listMetaphoneStat($ftrows, $header) {
596  $trows = '';
597  $trows .= '
598  <tr class="tableheader bgColor5">
599  <td>' . htmlspecialchars('Metaphone:') . '</td>
600  <td>' . htmlspecialchars('Hash:') . '</td>
601  <td>' . htmlspecialchars('Count:') . '</td>
602  <td>' . htmlspecialchars('Words:') . '</td>
603  </tr>
604  ';
605  foreach ($ftrows as $metaphone => $words) {
606  if (count($words) > 1) {
607  $trows .= '
608  <tr class="bgColor4">
609  <td>' . $this->linkMetaPhoneDetails($this->indexerObj->metaphone($words[0], 1), $metaphone) . '</td>
610  <td>' . htmlspecialchars($metaphone) . '</td>
611  <td>' . htmlspecialchars(count($words)) . '</td>
612  <td style="white-space: normal;">' . htmlspecialchars(implode(', ', $words)) . '</td>
613  </tr>
614  ';
615  }
616  }
617  return '<h4>' . htmlspecialchars($header) . '</h4>' . '<table border="0" cellspacing="1" cellpadding="2" class="c-list">
618  ' . $trows . '
619  </table>';
620  }
621 
630  public function linkWordDetails($string, $wid) {
631  return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('wid' => $wid, 'phash' => ''))) . '">' . $string . '</a>';
632  }
633 
642  public function linkMetaPhoneDetails($string, $metaphone) {
643  return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('metaphone' => $metaphone, 'wid' => '', 'phash' => ''))) . '">' . $string . '</a>';
644  }
645 
653  public function flagsMsg($flags) {
654  if ($flags > 0) {
655  return ($flags & 128 ? '<title>' : '') . ($flags & 64 ? '<meta/keywords>' : '') . ($flags & 32 ? '<meta/description>' : '') . ' (' . $flags . ')';
656  }
657  }
658 
659  /*******************************
660  *
661  * Details display, words / metaphone
662  *
663  *******************************/
671  public function showDetailsForWord($wid) {
672  // Select references to this word
673  $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_phash.*, index_section.*, index_rel.*', 'index_rel, index_section, index_phash', 'index_rel.wid = ' . (int)$wid . ' AND index_rel.phash = index_section.phash' . ' AND index_section.phash = index_phash.phash', '', 'index_rel.freq DESC', '');
674  // Headers:
675  $content = '
676  <tr class="tableheader bgColor5">
677  <td>phash</td>
678  <td>page_id</td>
679  <td>data_filename</td>
680  <td>count</td>
681  <td>first</td>
682  <td>freq</td>
683  <td>flags</td>
684  </tr>';
685  if (is_array($ftrows)) {
686  foreach ($ftrows as $wDat) {
687  $content .= '
688  <tr class="bgColor4">
689  <td>' . $this->linkDetails(htmlspecialchars($wDat['phash']), $wDat['phash']) . '</td>
690  <td>' . htmlspecialchars($wDat['page_id']) . '</td>
691  <td>' . htmlspecialchars($wDat['data_filename']) . '</td>
692  <td>' . htmlspecialchars($wDat['count']) . '</td>
693  <td>' . htmlspecialchars($wDat['first']) . '</td>
694  <td>' . htmlspecialchars($wDat['freq']) . '</td>
695  <td>' . htmlspecialchars($wDat['flags']) . '</td>
696  </tr>';
697  }
698  }
699  // Compile table:
700  $content = '
701  <table border="0" cellspacing="1" cellpadding="2" class="c-list">' . $content . '
702  </table>';
703  // Add go-back link:
704  $content = $content . $this->linkList();
705  return $content;
706  }
707 
715  public function showDetailsForMetaphone($metaphone) {
716  // Finding top-20 on frequency for this phash:
717  $ftrows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('index_words.*', 'index_words', 'index_words.metaphone = ' . (int)$metaphone, '', 'index_words.baseword', '');
718  if (count($ftrows)) {
719  $content .= '<h4>Metaphone: ' . $this->indexerObj->metaphone($ftrows[0]['baseword'], 1) . '</h4>';
720  $content .= '
721  <tr class="tableheader bgColor5">
722  <td>Word</td>
723  <td>Is stopword?</td>
724  </tr>';
725  if (is_array($ftrows)) {
726  foreach ($ftrows as $wDat) {
727  $content .= '
728  <tr class="bgColor4">
729  <td>' . $this->linkWordDetails(htmlspecialchars($wDat['baseword']), $wDat['wid']) . '</td>
730  <td>' . htmlspecialchars(($wDat['is_stopword'] ? 'YES' : 'No')) . '</td>
731  </tr>';
732  }
733  }
734  $content = '
735  <table border="0" cellspacing="1" cellpadding="2" class="c-list">' . $content . '
736  </table>';
737  if ($this->indexerObj->metaphone($ftrows[0]['baseword']) != $metaphone) {
738  $content .= 'ERROR: Metaphone string and hash did not match for some reason!?';
739  }
740  // Add go-back link:
741  $content = $content . $this->linkList();
742  }
743  return $content;
744  }
745 
746  /*******************************
747  *
748  * Helper functions
749  *
750  *******************************/
759  public function printRemoveIndexed($phash, $alt) {
760  return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('deletePhash' => $phash))) . '" title="' . htmlspecialchars($alt) . '">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-delete') . '</a>';
761  }
762 
771  public function printReindex($resultRow, $alt) {
772  if ($resultRow['item_type'] && $resultRow['item_type'] !== '0') {
773  return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('reindex' => $resultRow['phash'], 'reindex_id' => $resultRow['page_id']))) . '">' . '<img ' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/refresh_n.gif', 'width="14" height="14"') . ' hspace="1" vspace="2" border="0" title="' . htmlspecialchars($alt) . '" alt="" />' . '</a>';
774  }
775  }
776 
785  public function linkDetails($string, $phash) {
786  return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('phash' => $phash))) . '">' . $string . '</a>';
787  }
788 
795  public function linkList() {
796  return '<br /><a href="' . htmlspecialchars(BackendUtility::getModuleUrl('web_info', array('id' => $this->pObj->id))) . '">Back to list.</a><br />';
797  }
798 
807  public function showPageDetails($string, $id) {
808  return '<a href="' . htmlspecialchars(BackendUtility::getModuleUrl('web_info', array('id' => $id, 'SET' => array('depth' => 0, 'type' => 1)))) . '">' . $string . '</a>';
809  }
810 
818  public function printExtraGrListRows($extraGrListRows) {
819  if (count($extraGrListRows)) {
820  $lines = array();
821  foreach ($extraGrListRows as $r) {
822  $lines[] = $r['gr_list'];
823  }
824  return '<br />' . $GLOBALS['TBE_TEMPLATE']->dfw(implode('<br />', $lines));
825  }
826  }
827 
835  public function printRootlineInfo($row) {
836  $uidCollection = array();
837  if ($row['rl0']) {
838  $uidCollection[0] = $row['rl0'];
839  if ($row['rl1']) {
840  $uidCollection[1] = $row['rl1'];
841  if ($row['rl2']) {
842  $uidCollection[2] = $row['rl2'];
843  // Additional levels:
844  if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['addRootLineFields'])) {
845  foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['addRootLineFields'] as $fieldName => $rootLineLevel) {
846  if ($row[$fieldName]) {
847  $uidCollection[$rootLineLevel] = $row[$fieldName];
848  }
849  }
850  }
851  }
852  }
853  }
854  // Return root line.
855  ksort($uidCollection);
856  return implode('/', $uidCollection);
857  }
858 
867  public function makeItemTypeIcon($it, $alt = '') {
868  if (!isset($this->iconFileNameCache[$it])) {
869  if ($it === '0') {
870  $icon = 'EXT:indexed_search/pi/res/pages.gif';
871  } elseif ($this->external_parsers[$it]) {
872  $icon = $this->external_parsers[$it]->getIcon($it);
873  }
874  $fullPath = GeneralUtility::getFileAbsFileName($icon);
875  if ($fullPath) {
876  $info = @getimagesize($fullPath);
877  $iconPath = $GLOBALS['BACK_PATH'] . '../' . \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($fullPath);
878  $this->iconFileNameCache[$it] = is_array($info) ? '<img src="' . $iconPath . '" ' . $info[3] . ' title="###TITLE_ATTRIBUTE###" alt="" />' : '';
879  }
880  }
881  return str_replace('###TITLE_ATTRIBUTE###', htmlspecialchars($it . ': ' . $alt), $this->iconFileNameCache[$it]);
882  }
883 
884  /********************************
885  *
886  * Reindexing
887  *
888  *******************************/
897  public function reindexPhash($phash, $pageId) {
898  // Query:
899  $resultRow = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('ISEC.*, IP.*', 'index_phash IP, index_section ISEC', 'IP.phash = ISEC.phash
900  AND IP.phash = ' . (int)$phash . '
901  AND ISEC.page_id = ' . (int)$pageId);
902  $content = '';
903  if (is_array($resultRow)) {
904  if ($resultRow['item_type'] && $resultRow['item_type'] !== '0') {
905  // (Re)-Indexing file on page.
906  $indexerObj = GeneralUtility::makeInstance('TYPO3\\CMS\\IndexedSearch\\Indexer');
907  $indexerObj->backend_initIndexer($pageId, 0, 0, '', $this->getUidRootLineForClosestTemplate($pageId));
908  // URL or local file:
909  if ($resultRow['externalUrl']) {
910  $indexerObj->indexExternalUrl($resultRow['data_filename']);
911  } else {
912  $indexerObj->indexRegularDocument($resultRow['data_filename'], TRUE);
913  }
914  if ($indexerObj->file_phash_arr['phash'] != $resultRow['phash']) {
915  $content .= 'ERROR: phash (' . $indexerObj->file_phash_arr['phash'] . ') did NOT match ' . $resultRow['phash'] . ' for strange reasons!';
916  }
917  $content .= '<h4>Log for re-indexing of "' . htmlspecialchars($resultRow['data_filename']) . '":</h4>';
918  $content .= \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($indexerObj->internal_log);
919  $content .= '<h4>Hash-array, page:</h4>';
920  $content .= \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($indexerObj->hash);
921  $content .= '<h4>Hash-array, file:</h4>';
922  $content .= \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($indexerObj->file_phash_arr);
923  }
924  }
925  // Link back to list.
926  $content .= $this->linkList();
927  return $content;
928  }
929 
938  public function getUidRootLineForClosestTemplate($id) {
939  $tmpl = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\ExtendedTemplateService');
940  // Defined global here!
941  $tmpl->tt_track = 0;
942  // Do not log time-performance information
943  $tmpl->init();
944  // Gets the rootLine
945  $sys_page = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
946  $rootLine = $sys_page->getRootLine($id);
947  $tmpl->runThroughTemplates($rootLine, 0);
948  // This generates the constants/config + hierarchy info for the template.
949  // Root line uids
950  $rootline_uids = array();
951  foreach ($tmpl->rootLine as $rlkey => $rldat) {
952  $rootline_uids[$rlkey] = $rldat['uid'];
953  }
954  return $rootline_uids;
955  }
956 
957  /********************************
958  *
959  * SQL functions
960  *
961  *******************************/
970  public function removeIndexedPhashRow($phashList, $clearPageCache = 1) {
971  // FIXME: This is only a workaround
972  if ($phashList == 'ALL') {
973  $this->drawTableOfIndexedPages();
974  $phashRows = $this->allPhashListed;
975  $this->allPhashListed = array();
976  } else {
977  $phashRows = GeneralUtility::trimExplode(',', $phashList, TRUE);
978  }
979  foreach ($phashRows as $phash) {
980  $phash = (int)$phash;
981  if ($phash > 0) {
982  if ($clearPageCache) {
983  // Clearing page cache:
984  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('page_id', 'index_section', 'phash=' . (int)$phash);
985  if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
986  $idList = array();
987  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
988  $idList[] = (int)$row['page_id'];
989  }
990  $pageCache = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_pages');
991  foreach ($idList as $pageId) {
992  $pageCache->flushByTag('pageId_' . $pageId);
993  }
994  }
995  }
996  // Removing old registrations for all tables.
997  $tableArr = explode(',', 'index_phash,index_rel,index_section,index_grlist,index_fulltext,index_debug');
998  foreach ($tableArr as $table) {
999  $GLOBALS['TYPO3_DB']->exec_DELETEquery($table, 'phash=' . (int)$phash);
1000  }
1001  }
1002  }
1003  }
1004 
1013  public function getGrListEntriesForPhash($phash, $gr_list) {
1014  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'index_grlist', 'phash=' . (int)$phash);
1015  $lines = array();
1016  $isRemoved = 0;
1017  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
1018  if (!$isRemoved && (string)$row['gr_list'] === (string)$gr_list) {
1019  $isRemoved = 1;
1020  } else {
1021  $lines[] = $row;
1022  }
1023  }
1024  return $lines;
1025  }
1026 
1034  public function processStopWords($stopWords) {
1035  if ($GLOBALS['BE_USER']->isAdmin()) {
1036  // Traverse words
1037  foreach ($stopWords as $wid => $state) {
1038  $fieldArray = array(
1039  'is_stopword' => $state
1040  );
1041  $GLOBALS['TYPO3_DB']->exec_UPDATEquery('index_words', 'wid=' . $wid, $fieldArray);
1042  }
1043  }
1044  }
1045 
1054  public function processPageKeywords($pageKeywords, $pageUid) {
1055  // Get pages current keywords
1056  $pageRec = BackendUtility::getRecord('pages', $pageUid);
1057  $keywords = array_flip(GeneralUtility::trimExplode(',', $pageRec['keywords'], TRUE));
1058  // Merge keywords:
1059  foreach ($pageKeywords as $key => $v) {
1060  if ($v) {
1061  $keywords[$key] = 1;
1062  } else {
1063  unset($keywords[$key]);
1064  }
1065  }
1066  // Compile new list:
1067  $data = array();
1068  $data['pages'][$pageUid]['keywords'] = implode(', ', array_keys($keywords));
1069  $tce = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\DataHandling\\DataHandler');
1070  $tce->stripslashes_values = 0;
1071  $tce->start($data, array());
1072  $tce->process_datamap();
1073  }
1074 
1075 }
$TYPO3_CONF_VARS['SYS']['contentTable']
static getUserObj($classRef, $checkPrefix='', $silent=FALSE)
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
static getModuleUrl($moduleName, $urlParameters=array(), $backPathOverride=FALSE, $returnAbsoluteUrl=FALSE)
$BACK_PATH
Definition: conf.php:3
static getIcon($table, $row=array(), $shaded=FALSE)
static getFuncMenu($mainParams, $elementName, $currentValue, $menuItems, $script='', $addparams='')
listWords($ftrows, $header, $stopWordBoxes=FALSE, $page='')
static implodeArrayForUrl($name, array $theArray, $str='', $skipBlank=FALSE, $rawurlencodeParamName=FALSE)
static formatSize($sizeInBytes, $labels='')
static fixed_lgd_cs($string, $chars, $appendString='...')
static getRecordTitlePrep($title, $titleLength=0)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
static dateTimeAge($tstamp, $prefix=1, $date='')