Development

Changeset 9031

You must first sign up to be able to contribute.

Changeset 9031

Show
Ignore:
Timestamp:
05/18/08 07:57:37 (5 years ago)
Author:
Carl.Vondrick
Message:

sfHighlight: added specialized readers and symfony filter

  • new readers:
    • xfHighlightReaderXML: takes an XML string
    • xfHighlightReaderXHTML: takes an XHTML string
  • introduced reader aggregates:
    • xfHighlightReaderAggregate interface tells xfHighlighter that object contains a reader
    • useful for creating convenience layers (see new readers)
  • added highlighting filter:
    • filter taps into filter chain and looks for sf_highlight querystring
    • reads querystring and highlights the content using sfHighlight
    • customizable with many options
    • extensible with methods broken down into small functions so you can swap them out
  • bundled XML catalog tarball
    • to improve perfomance on XML highlighting, follow the instructions in the tarball
  • and unit tests for all (maintains 100% unit test coverage)
  • core library still completely decoupled from symfony
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • plugins/sfHighlightPlugin/trunk/README

    r8890 r9031  
    3232$h->addKeyword(new xfHighlightKeyword(new xfHighlightTokenizerSimple(array('baz')), new xfHighlightMarkerSprint('[%s]'))); 
    3333 
    34 // now highlight a DOM document using the highlighter 
     34// highlight a DOM document using the highlighter 
    3535$dom = new DOMDocument; 
    3636$dom->loadXml($xml); 
    37 $highlightedDom = $h->highlight(new xfHighlightReaderDOM($dom))
     37$highlightedDom = $h->highlight(new xfHighlightReaderDOM($dom))->getDocument()
    3838 
    39 // now highlight a string with the same configuration 
     39// highlight a XHTML string 
     40$highlightedXhtml = $h->highlight(new xfHighlightReaderXHTML($xhtml))->getString(); 
     41 
     42// highlight a string with the same configuration 
    4043$string = 'Why don\'t you foobar when you can baz?'; 
    41 $highlightedstring = $h->highlight(new xfHighlightReaderString($string))
     44$highlightedstring = $h->highlight(new xfHighlightReaderString($string))->getString()
    4245}}} 
    4346 
    4447Please refer to the unit tests until the documentation is complete. 
     48 
     49= Improve XML Performance = 
     50Highlighting XML documents may take longer than expected because PHP makes network calls to fetch the DTD from W3C's server.  You can remove this bottleneck by caching the DTD through your XML catalog.  Refer to tarball {{{ XMLCatalog.tar.gz }}} included in this package for more information. 
  • plugins/sfHighlightPlugin/trunk/lib/highlight/xfHighlighter.class.php

    r8994 r9031  
    6060   * Does the highlighting on the reader. 
    6161   * 
    62    * @param xfHighlightReader $reader 
    63    * @returns xfHighlightReader 
     62   * @param xfHighlightReaderInterface $inReader 
     63   * @returns xfHighlightReaderInterface 
    6464   */ 
    65   public function highlight(xfHighlightReader $reader) 
     65  public function highlight(xfHighlightReaderInterface $inReader) 
    6666  { 
     67    $reader = $this->resolveReader($inReader); 
     68 
    6769    $reader->rewind(); 
    6870 
     
    8587    } 
    8688 
     89    return $inReader; 
     90  } 
     91 
     92  /** 
     93   * Resolves the reader and its aggregates 
     94   * 
     95   * @param xfHighlightReaderInterface $reader 
     96   * @returns xfHighlightReader 
     97   */ 
     98  private function resolveReader(xfHighlightReaderInterface $reader) 
     99  { 
     100    if ($reader instanceof xfHighlightReaderAggregate) 
     101    { 
     102      $reader = $this->resolveReader($reader->getReader()); 
     103    } 
     104 
    87105    return $reader; 
    88106  } 
  • plugins/sfHighlightPlugin/trunk/lib/reader/xfHighlightReader.interface.php

    r8994 r9031  
    1515 * @author Carl Vondrick 
    1616 */ 
    17 interface xfHighlightReader 
     17interface xfHighlightReader extends xfHighlightReaderInterface 
    1818{ 
    1919  /** 
  • plugins/sfHighlightPlugin/trunk/lib/reader/xfHighlightReaderDOM.class.php

    r8994 r9031  
    2121   * The document 
    2222   * 
    23    * @var DOMDocument 
     23   * @var DOMNode 
    2424   */ 
    2525  private $document; 
     
    4949 
    5050  /** 
     51   * Callbacks to determine if the node should be ignored 
     52   * 
     53   * @var array 
     54   */ 
     55  private $ignoreCallbacks = array(); 
     56 
     57  /** 
    5158   * The current position in the text array 
    5259   * 
     
    5663 
    5764  /** 
     65   * Boolean to indicate if reader has been initialized 
     66   * 
     67   * @var bool 
     68   */ 
     69  private $initialized = false; 
     70 
     71  /** 
    5872   * Constructor to set the DOMNode 
    5973   * 
    6074   * @param DOMNode $document 
    6175   */ 
    62   public function __construct(DOMDocument $document) 
     76  public function __construct(DOMNode $document) 
    6377  { 
    6478    $this->document = clone $document; 
     79  } 
    6580 
    66     $this->buildTexts($this->document); 
     81  /** 
     82   * Initializes the reader 
     83   */ 
     84  public function initialize() 
     85  { 
     86    if (!$this->initialized) 
     87    { 
     88      $this->buildTexts($this->document); 
     89 
     90      $this->initialized = true; 
     91    } 
     92  } 
     93 
     94  /** 
     95   * Adds an ignore callback 
     96   * 
     97   * @param callable $callback 
     98   */ 
     99  public function registerIgnoreCallback($callback) 
     100  { 
     101    $this->ignoreCallbacks[] = $callback; 
    67102  } 
    68103 
     
    70105   * Gets the original document 
    71106   * 
    72    * @returns DOMDocument 
     107   * @returns DOMNode 
    73108   */ 
    74109  public function getDocument() 
     
    87122    { 
    88123      return; 
     124    } 
     125 
     126    // stop building this node if callback returns true 
     127    foreach ($this->ignoreCallbacks as $callback) 
     128    { 
     129      if (call_user_func($callback, $node) === true) 
     130      { 
     131        return; 
     132      } 
    89133    } 
    90134 
     
    108152  public function rewind() 
    109153  { 
     154    $this->initialize(); 
     155 
    110156    $this->position = -1; 
    111157  } 
     
    138184    } 
    139185 
    140     return $this->texts[$this->position]->textContent; 
     186    $response = $this->texts[$this->position]->textContent; 
     187 
     188    if (trim($response) == '') 
     189    { 
     190      return $this->next(); 
     191    } 
     192 
     193    return $response; 
    141194  } 
    142195} 
  • plugins/sfHighlightPlugin/trunk/lib/reader/xfHighlightReaderString.class.php

    r8994 r9031  
    8181   * @returns string 
    8282   */ 
    83   public function getText() 
     83  public function getString() 
    8484  { 
    8585    return $this->text; 
  • plugins/sfHighlightPlugin/trunk/lib/search/xfHighlightRetortFilterCallback.class.php

    r8994 r9031  
    5353      $h->addKeyword($keyword); 
    5454 
    55       $response = $h->highlight(new xfHighlightReaderString($response))->getText(); 
     55      $response = $h->highlight(new xfHighlightReaderString($response))->getString(); 
    5656    } 
    5757 
  • plugins/sfHighlightPlugin/trunk/test/unit/highlight/xfHighlighterTest.php

    r8994 r9031  
    1717require 'marker/xfHighlightMarkerUppercase.class.php'; 
    1818require 'marker/xfHighlightMarkerSprint.class.php'; 
     19require 'reader/xfHighlightReaderInterface.interface.php'; 
     20require 'reader/xfHighlightReaderAggregate.interface.php'; 
    1921require 'reader/xfHighlightReader.interface.php'; 
    2022require 'reader/xfHighlightReaderString.class.php'; 
    2123 
    22 $t = new lime_test(3, new lime_output_color); 
     24class MockReaderAggregate implements xfHighlightReaderAggregate 
     25
     26  public $reader; 
     27 
     28  public function getReader() 
     29  { 
     30    if (!$this->reader) 
     31    { 
     32      $this->reader = new xfHighlightReaderString('foo is awesome'); 
     33    } 
     34 
     35    return $this->reader; 
     36  } 
     37
     38 
     39class MockReaderDoubleAggregate implements xfHighlightReaderAggregate 
     40
     41  public $reader; 
     42 
     43  public function getReader() 
     44  { 
     45    if (!$this->reader) 
     46    { 
     47      $this->reader = new MockReaderAggregate; 
     48    } 
     49 
     50    return $this->reader; 
     51  } 
     52
     53 
     54$t = new lime_test(5, new lime_output_color); 
    2355 
    2456$keywords = array( 
     
    3365 
    3466$t->isa_ok($reader, 'xfHighlightReaderString', '->highlight() returns a xfHighlightReader'); 
    35 $t->is($reader->getText(), 'FOO is better than BAR if only because of the small amount of [baz]', '->highlight() highlights the string according to the reader and keywords'); 
     67$t->is($reader->getString(), 'FOO is better than BAR if only because of the small amount of [baz]', '->highlight() highlights the string according to the reader and keywords'); 
    3668 
    37 $t->is($h->highlight(new xfHighlightReaderString('baz! bow before baz for i am baz'))->getText(), '[baz]! bow before [baz] for i am [baz]', '->highlight() works with changing string length'); 
     69$t->is($h->highlight(new xfHighlightReaderString('baz! bow before baz for i am baz'))->getString(), '[baz]! bow before [baz] for i am [baz]', '->highlight() works with changing string length'); 
     70 
     71$t->is($h->highlight(new MockReaderAggregate)->getReader()->getString(), 'FOO is awesome', '->highlight() accepts reader aggregates'); 
     72$t->is($h->highlight(new MockReaderDoubleAggregate)->getReader()->getReader()->getString(), 'FOO is awesome', '->highlight() accepts double reader aggregates'); 
  • plugins/sfHighlightPlugin/trunk/test/unit/reader/xfHighlightReaderDOMTest.php

    r8890 r9031  
    99 
    1010require dirname(__FILE__) . '/../../bootstrap/unit.php'; 
     11require 'reader/xfHighlightReaderInterface.interface.php'; 
    1112require 'reader/xfHighlightReader.interface.php'; 
    1213require 'reader/xfHighlightReaderDOM.class.php'; 
     
    1516$t = new lime_test(9, new lime_output_color); 
    1617 
    17 function getFullText($reader
     18function ignoreCallback(DOMNode $node
    1819{ 
    19   do 
    20   { 
    21     $text = trim($reader->next()); 
    22   } while ($text === ''); 
    23  
    24   return $text; 
     20  return $node->nodeName == 'ignoreme'; 
    2521} 
    2622 
     
    3733    Pie is bad for you! 
    3834  </parent> 
     35  <ignoreme>foobar</ignoreme> 
    3936</root> 
    4037XML; 
     
    4441 
    4542$reader = new xfHighlightReaderDOM($domdoc); 
     43$reader->registerIgnoreCallback('ignoreCallback'); 
     44$reader->rewind(); 
    4645 
    4746$t->ok($reader->getDocument() == $domdoc && $reader->getDocument() !== $domdoc, '->__construct() clones the DOMDocument'); 
     
    5756foreach ($expected as $phrase) 
    5857{ 
    59   $t->is(getFullText($reader), $phrase, '->next() returns node "' . $phrase . '"'); 
     58  $t->is(trim($reader->next()), $phrase, '->next() returns node "' . $phrase . '"'); 
    6059} 
    6160 
     
    6463 
    6564$reader->rewind(); 
    66 $t->is(getFullText($reader), 'I love pie', '->rewind() starts the iterator over'); 
     65$t->is($reader->next(), 'I love pie', '->rewind() starts the iterator over'); 
    6766 
    6867$reader->replaceText(new xfHighlightToken('love', 2, 6), 'hate'); 
     
    8281    Pie is bad for you! 
    8382  </parent> 
     83  <ignoreme>foobar</ignoreme> 
    8484</root> 
    8585 
     
    8787 
    8888$t->is($text, $expected, '->replaceText() replaces the text in the correct node'); 
     89 
  • plugins/sfHighlightPlugin/trunk/test/unit/reader/xfHighlightReaderStringTest.php

    r8890 r9031  
    99 
    1010require dirname(__FILE__) . '/../../bootstrap/unit.php'; 
     11require 'reader/xfHighlightReaderInterface.interface.php'; 
    1112require 'reader/xfHighlightReader.interface.php'; 
    1213require 'reader/xfHighlightReaderString.class.php'; 
     
    2627$token = new xfHighlightToken('walrus', 7, 13); 
    2728$reader->replaceText($token, 'lucy'); 
    28 $t->is($reader->getText(), 'I am a lucy in the sky with diamonds.', '->replaceText() does the replacement'); 
     29$t->is($reader->getString(), 'I am a lucy in the sky with diamonds.', '->replaceText() does the replacement'); 
  • plugins/sfHighlightPlugin/trunk/test/unit/search/xfHighlightRetortFilterCallbackTest.php

    r8994 r9031  
    2323require 'marker/xfHighlightMarker.interface.php'; 
    2424require 'marker/xfHighlightMarkerUppercase.class.php'; 
     25require 'reader/xfHighlightReaderInterface.interface.php'; 
    2526require 'reader/xfHighlightReader.interface.php'; 
    2627require 'reader/xfHighlightReaderString.class.php';