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