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