PageRenderTime 71ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/typo3/sysext/indexed_search/modfunc1/class.tx_indexedsearch_modfunc1.php

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