contao/test — Issue #2948: Fehlerhafter Parser für indexer::stop/continue-Markierungen
Author: importer
Created: 2011-11-29 10:37:38+00:00
State: open
Labels: Defect, framework, Pending

Der Parser, welcher in `system/libraries/Search.php` die indexer-Markierungen vor der Indizierung entfernt, ist in mehrerer Hinsicht fehlerhaft. Konkret geht es mir um diesen doch zu einfachen Code:

```
while (preg_match('/<

![](-- indexer::stop -->/', $strContent, $arrOuter, PREG_OFFSET_CAPTURE))
{
if ()preg_match('/<

![](-- indexer::continue -->/', $strContent, $arrInner, PREG_OFFSET_CAPTURE, (strlen($arrOuter[0][0]) + $arrOuter[0][1])))
{
break;
}

$strContent = substr($strContent, 0, $arrOuter[0][1]) . substr($strContent, (strlen($arrInner[0][0]) + $arrInner[0][1]));
}
```

Dieser Code enthält folgende Fehler:

# Verschachtelte Markierungen werden nicht korrekt verarbeitet. Das kann bspw. bei Einbettung der Paginierung oberhalb der Newsliste im Template mod_newslist.tpl dazu führen, dass die Newsliste selbst indiziert wird, obwohl beide Templates (Paginierung und Newsliste) den Indexer komplett deaktivieren.
# Daneben ignoriert der Code ein `indexer::stop`, wenn kein `indexer::continue` mehr gefunden wird. Analog würde gelten, dass eine Dreißigerzone komplett aufgehoben ist, wenn nicht an allen Ausfahrten auch ein Schild steht, dass deren Ende markiert.

Desweiteren fällt das wiederholte Parsing des Seitencodes per preg_match als weniger performant negativ auf.

Folgender Code sollte die genannten Fehler beheben:

```
$contMark = '<)-- indexer::continue -->';
$contMarkSize = strlen( $contMark );

preg_match_all( '//', $strContent, $indexerStops, PREG_OFFSET_CAPTURE+PREG_SET_ORDER );
preg_match_all( "/$contMark/", $strContent, $indexerConts, PREG_OFFSET_CAPTURE+PREG_SET_ORDER );

$offsetExtractor = create_function( '$a', 'return $a[0][1];' );

$indexerMarks = array_combine( array_map( $offsetExtractor, $indexerStops ), array_pad( array(), count( $indexerStops ), true ) ) +
array_combine( array_map( $offsetExtractor, $indexerConts ), array_pad( array(), count( $indexerConts ), false ) );

ksort( $indexerMarks );

$depth = 1;
foreach ( $indexerMarks as $offset => $isStarter )
$indexerMarks[$offset] = $isStarter ? $depth++ : ( ( $depth == 1 ) ? 0 : --$depth );

$indexerMarks = array_filter( $indexerMarks, create_function( '$a', 'return ( $a == 1 );' ) );
if ( count( $indexerMarks ) & 1 )
$indexerMarks += array( strlen( $strContent ) => false );

foreach ( array_reverse( array_chunk( array_keys( $indexerMarks ), 2 ) ) as $chunk )
$strContent = substr_replace( $strContent, '', $chunk[0], $chunk[1] + $contMarkSize - $chunk[0] );
```

Related issues: #546, #2520

--- _Originally created by soletan on March 21st, 2011, at 06:00pm (ID 2949)_