Changeset 6816
- Timestamp:
- 12/29/07 22:29:23 (1 year ago)
- Files:
-
- plugins/sfLucenePlugin/branches/1.1/lib/filter/sfLuceneHighlightFilter.class.php (modified) (12 diffs)
- plugins/sfLucenePlugin/branches/1.1/lib/form/sfLuceneAdvancedFormBase.class.php (modified) (3 diffs)
- plugins/sfLucenePlugin/branches/1.1/lib/form/sfLuceneForm.class.php (modified) (4 diffs)
- plugins/sfLucenePlugin/branches/1.1/lib/form/sfLuceneSimpleFormBase.class.php (modified) (3 diffs)
- plugins/sfLucenePlugin/branches/1.1/lib/indexer/sfLuceneIndexer.class.php (modified) (5 diffs)
- plugins/sfLucenePlugin/branches/1.1/lib/indexer/sfLuceneModelIndexer.class.php (modified) (1 diff)
- plugins/sfLucenePlugin/branches/1.1/lib/indexer/sfLucenePropelIndexer.class.php (modified) (17 diffs)
- plugins/sfLucenePlugin/branches/1.1/lib/storage/sfLuceneStorageBlackhole.class.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
plugins/sfLucenePlugin/branches/1.1/lib/filter/sfLuceneHighlightFilter.class.php
r6735 r6816 53 53 'css' => '../sfLucenePlugin/css/search.css', 54 54 'possible_refers' => array( 55 'google' => array('qs' => 'q', 'name' => 'Google'), 56 'yahoo' => array('qs' => 'p', 'name' => 'Yahoo'), 57 'msn' => array('qs' => 'q', 'name' => 'MSN'), 58 'ask' => array('qs' => 'q', 'name' => 'Ask') 55 'google' => array('qs' => 'q', 'name' => 'Google'), 56 'yahoo' => array('qs' => 'p', 'name' => 'Yahoo!'), 57 'msn' => array('qs' => 'q', 'name' => 'MSN'), 58 'live' => array('qs' => 'q', 'name' => 'Live'), 59 'ask' => array('qs' => 'q', 'name' => 'Ask'), 60 'a9' => array('qs' => 'query', 'name' => 'A9'), 59 61 ) 60 62 ) … … 67 69 } 68 70 71 /** 72 * Executes the filter 73 */ 69 74 public function execute($filterChain) 70 75 { … … 97 102 if (!$this->highlight()) 98 103 { 104 // highlighting did not occur, so remove notice 99 105 $this->removeNotice(); 100 106 } 101 107 } 102 catch ( sfLuceneHighlighterException $e)108 catch (Exception $e) 103 109 { 104 110 $timer->addTime(); 105 111 throw $e; 106 112 } 107 catch (Exception $e)108 {109 $timer->addTime();110 throw $e;111 }112 113 113 114 $timer->addTime(); 114 115 } 115 116 117 /** 118 * Attempt to highlight the page 119 * @return bool True if highlighting occured, false otherwise 120 */ 116 121 protected function highlight() 117 122 { 118 $terms = $this->getContext()->getRequest()->getParameter( $this->getParameter('highlight_qs'));123 $terms = $this->getContext()->getRequest()->getParameter($this->getParameter('highlight_qs')); 119 124 $terms = $this->prepareTerms($terms); 120 125 126 // attempt to highlight from sfLucene 121 127 if (count($terms)) 122 128 { … … 127 133 return true; 128 134 } 135 // attempt to highlight from referer (ie, google) 129 136 elseif ($this->getParameter('check_referer')) 130 137 { 131 138 $referer = $this->getContext()->getRequest()->getReferer(); 132 139 140 // continue only if we have a referer 133 141 if ($referer) 134 142 { 143 // go through each referer and stop once we have a match 135 144 foreach ($this->getParameter('possible_refers') as $domain => $value) 136 145 { 137 if (preg_match($this->getRefererRegex($domain, $value['qs']), $referer, $matches)) 146 $regex = '#^https?://(?:\w+\.)*' . preg_quote($domain, '#') . '(?:\.[a-z]+)+.*' . preg_quote($value['qs'], '#') . '=(.*?)(&|$)#'; 147 148 // valid referer? 149 if (preg_match($regex, $referer, $matches)) 138 150 { 151 // referer match. highlight! 152 139 153 $terms = $this->prepareTerms($matches[1]); 140 154 … … 142 156 $this->addCss(); 143 157 $this->doHighlight($terms); 158 159 // stop looking for referers now. 144 160 145 161 return true; … … 149 165 } 150 166 167 // we failed to do anything, so return false 151 168 return false; 152 169 } 153 170 154 protected function doHighlight($terms) 171 /** 172 * Highlights the content for $terms 173 */ 174 protected function doHighlight(array $terms) 155 175 { 156 176 $content = $this->getContext()->getResponse()->getContent(); 157 177 178 // configure highlighter 158 179 $lighter = new sfLuceneHighlighter($content); 159 180 $lighter->addKeywords($terms); … … 164 185 } 165 186 187 /** 188 * Add the neccessary CSS for the response 189 */ 166 190 protected function addCss() 167 191 { … … 181 205 } 182 206 207 /** 208 * Prepares terms by exploding them out 209 */ 183 210 protected function prepareTerms($terms) 184 211 { … … 190 217 } 191 218 219 /** 220 * Removes the notice token from the content because highlighting didn't happen 221 */ 192 222 protected function removeNotice() 193 223 { … … 197 227 } 198 228 229 /** 230 * Replace the notice with a message that highlighting did occur 231 */ 199 232 protected function addNotice($terms, $from = null) 200 233 { … … 223 256 } 224 257 258 /** 259 * Helper function to do translations 260 */ 225 261 protected function translate($text, $args) 226 262 { … … 234 270 } 235 271 } 236 237 protected function getRefererRegex($domain, $qs)238 {239 $domain = preg_quote($domain, '#');240 $qs = preg_quote($qs, '#');241 242 return '#^https?://(?:\w+\.)*' . $domain . '(?:\.[a-z]+)+.*' . $qs . '=(.*?)(&|$)#';243 }244 272 } plugins/sfLucenePlugin/branches/1.1/lib/form/sfLuceneAdvancedFormBase.class.php
r6525 r6816 23 23 abstract class sfLuceneAdvancedFormBase extends sfLuceneForm 24 24 { 25 /** 26 * This overriden constructor looks useless, but it is important: it specifies 27 * not to use a CRSF Secret by default! 28 */ 25 29 public function __construct($defaults = array(), $options = array(), $CSRFSecret = false) 26 30 { … … 28 32 } 29 33 34 /** 35 * Setup the form. To overload, you should use ->configure() 36 */ 30 37 public function setup() 31 38 { … … 71 78 { 72 79 $widgetSchema['category'] = new sfWidgetFormSelect(array('choices' => $this->getCategories(), 'multiple' => false)); 73 74 80 $widgetSchema->setLabel('category', 'Must be in category'); 75 81 plugins/sfLucenePlugin/branches/1.1/lib/form/sfLuceneForm.class.php
r6525 r6816 12 12 * sfLuceneSimpleForm instead. 13 13 * 14 * This form represents the simple form that is displayed on the standard search15 * interface.16 *17 14 * @package sfLucenePlugin 18 15 * @subpackage Form … … 23 20 abstract class sfLuceneForm extends sfForm 24 21 { 25 public function setCategories($categories = array()) 22 /** 23 * Gives this form these categories 24 * @param array $categories The array of categories to assign to this form 25 */ 26 public function setCategories($categories) 26 27 { 27 28 if (!is_array($categories)) … … 30 31 } 31 32 33 // set categories 32 34 $this->setOption('categories', $categories); 33 35 36 // we now must reconfigure the form 34 37 $this->setup(); 35 38 $this->configure(); 36 39 } 37 40 41 /** 42 * Returns all the categories configured for this form 43 */ 38 44 public function getCategories() 39 45 { … … 41 47 } 42 48 49 /** 50 * Returns true if the form has categories, false if not 51 */ 43 52 public function hasCategories() 44 53 { plugins/sfLucenePlugin/branches/1.1/lib/form/sfLuceneSimpleFormBase.class.php
r6577 r6816 23 23 abstract class sfLuceneSimpleFormBase extends sfLuceneForm 24 24 { 25 /** 26 * This overriden constructor looks useless, but it is important: it specifies 27 * not to use a CRSF Secret by default! 28 */ 25 29 public function __construct($defaults = array(), $options = array(), $CSRFSecret = false) 26 30 { … … 28 32 } 29 33 34 /** 35 * Setup the form. To overload, you should use ->configure() 36 */ 30 37 public function setup() 31 38 { … … 71 78 } 72 79 80 /** 81 * Gets the query string for a certain page 82 */ 73 83 public function getQueryString($page = null) 74 84 { plugins/sfLucenePlugin/branches/1.1/lib/indexer/sfLuceneIndexer.class.php
r6689 r6816 67 67 } 68 68 69 /** 70 * Return the context that the search is bound to 71 */ 69 72 protected function getContext() 70 73 { … … 73 76 74 77 /** 75 * Searches the index for anything with that guid and will delete it. 78 * Searches the index for anything with that guid and will delete it, while 79 * taking care to update categories cache. 80 * 76 81 * @param string $guid The guid to search for 82 * @return int The number of documents deleted 77 83 */ 78 84 protected function deleteGuid($guid) … … 84 90 } 85 91 86 $term = $this->getLuceneField('index term', 'sfl_guid', $guid ); 87 92 $term = $this->getLuceneField('index term', 'sfl_guid', $guid); 88 93 $query = new Zend_Search_Lucene_Search_Query_Term($term); 89 94 90 95 $hits = $this->getSearch()->find($query); 91 96 97 // loop through each document that has this guid 92 98 foreach ($hits as $hit) 93 99 { 100 // build categories that this document has 94 101 $categories = unserialize($hit->sfl_categories_cache); 95 102 103 // delete each category that this document references 96 104 foreach ($categories as $category) 97 105 { … … 99 107 } 100 108 109 // delete item from index 101 110 $this->getSearch()->getLucene()->delete($hit->id); 102 111 } 103 112 113 // commit changes 104 114 $this->getSearch()->commit(); 105 115 … … 108 118 109 119 /** 110 * Adds a document 120 * Adds a document to the index while attaching a GUID 111 121 */ 112 protected function addDocument( $document, $guid)122 protected function addDocument(Zend_Search_Lucene_Document $document, $guid) 113 123 { 114 124 $document->addField($this->getLuceneField('keyword', 'sfl_guid', $guid)); plugins/sfLucenePlugin/branches/1.1/lib/indexer/sfLuceneModelIndexer.class.php
r6689 r6816 85 85 return $categories; 86 86 } 87 88 /** 89 * Configures meta data about the document 90 */ 91 protected function configureDocumentMetas(Zend_Search_Lucene_Document $doc) 92 { 93 $doc->addField($this->getLuceneField('unindexed', 'sfl_model', $this->getModelName())); 94 $doc->addField($this->getLuceneField('unindexed', 'sfl_type', 'model')); 95 96 return $doc; 97 } 98 99 /** 100 * Configures categories into the document 101 */ 102 protected function configureDocumentCategories(Zend_Search_Lucene_Document $doc) 103 { 104 $categories = $this->getModelCategories(); 105 106 if (count($categories) > 0) 107 { 108 foreach ($categories as $category) 109 { 110 $this->addCategory($category); 111 } 112 113 $doc->addField( $this->getLuceneField('text', 'sfl_category', implode(' ', $categories)) ); 114 } 115 116 $doc->addField( $this->getLuceneField('unindexed', 'sfl_categories_cache', serialize($categories)) ); 117 118 return $doc; 119 } 87 120 } plugins/sfLucenePlugin/branches/1.1/lib/indexer/sfLucenePropelIndexer.class.php
r6792 r6816 18 18 class sfLucenePropelIndexer extends sfLuceneModelIndexer 19 19 { 20 /** 21 * Constructs a new instance 22 * @param sfLucene $search The search instance to index to 23 * @param BaseObject $instance The model instance to index 24 */ 20 25 public function __construct($search, $instance) 21 26 { … … 30 35 /** 31 36 * Inserts the provided model into the index based off parameters in search.yml. 32 * @param BaseObject $this->getModel() The model to insert33 37 */ 34 38 public function insert() … … 37 41 if (!$this->shouldIndex()) 38 42 { 43 // indexer said to skip indexing 39 44 $this->getSearch()->getEventDispatcher()->notify(new sfEvent($this, 'indexer.log', array('Ignoring model "%s" from index with primary key = %s', $this->getModelName(), $this->getModel()->getPrimaryKey()))); 40 45 … … 51 56 } 52 57 58 // build document 53 59 $doc = $this->getBaseDocument(); 54 60 $doc = $this->configureDocumentFields($doc); … … 56 62 $doc = $this->configureDocumentMetas($doc); 57 63 58 // add document 64 // add document to index 59 65 $this->addDocument($doc, $this->getModelGuid()); 60 66 … … 65 71 } 66 72 73 // notify about new record 67 74 $this->getSearch()->getEventDispatcher()->notify(new sfEvent($this, 'indexer.log', array('Inserted model "%s" from index with primary key = %s', $this->getModelName(), $this->getModel()->getPrimaryKey()))); 68 75 … … 71 78 72 79 /** 73 * Returns the base document 80 * Returns the base document to work with. Most of the time this will just 81 * return an empty Zend_Search_Lucene_Document, but if a callback is specified 82 * it will return that. 74 83 */ 75 84 protected function getBaseDocument() … … 81 90 { 82 91 $cb = $properties->get('callback'); 83 84 92 $doc = $this->getModel()->$cb(); 85 93 … … 98 106 99 107 /** 100 * Builds the fields into the document as configured by the search.yml file.101 */ 102 protected function configureDocumentFields( $doc)108 * Builds the fields into the document as configured by the parameters. 109 */ 110 protected function configureDocumentFields(Zend_Search_Lucene_Document $doc) 103 111 { 104 112 $properties = $this->getModelProperties(); 105 113 114 // loop through each field 106 115 foreach ($properties->get('fields')->getNames() as $field) 107 116 { 108 117 $field_properties = $properties->get('fields')->get($field); 109 118 119 // build getter by converting from underscore case to camel case 110 120 $getter = 'get' . sfInflector::camelize($field); 121 $value = $this->getModel()->$getter(); 111 122 112 123 $type = $field_properties->get('type'); 113 124 $boost = $field_properties->get('boost'); 114 125 115 $value = $this->getModel()->$getter(); 116 117 // validate value 126 // validate value to make sure we can really index this 118 127 if (is_object($value) && method_exists($value, '__toString')) 119 128 { … … 126 135 elseif (!is_scalar($value)) 127 136 { 128 throw new sfLuceneIndexerException('Field value returned is not a string (got a ' . gettype($value) . ' ) and it could be casted to a string .');137 throw new sfLuceneIndexerException('Field value returned is not a string (got a ' . gettype($value) . ' ) and it could be casted to a string for field ' . $field); 129 138 } 130 139 131 140 // handle a possible transformation function 132 if ($ field_properties->get('transform'))133 { 134 if (!is_callable($ field_properties->get('transform')))135 { 136 throw new sfLuceneIndexerException('Transformation function cannot be called in field "' . $field . '" on model "' . $this->getModelName() . '"');137 } 138 139 $value = call_user_func($ field_properties->get('transform'), $value);141 if ($transform = $field_properties->get('transform')) 142 { 143 if (!is_callable($transform)) 144 { 145 throw new sfLuceneIndexerException('Transformation function ' . $transform . ' does not exist'); 146 } 147 148 $value = call_user_func($transform, $value); 140 149 } 141 150 … … 149 158 } 150 159 151 protected function configureDocumentMetas($doc)152 {153 $doc->addField($this->getLuceneField('unindexed', 'sfl_model', $this->getModelName()));154 $doc->addField($this->getLuceneField('unindexed', 'sfl_type', 'model'));155 156 return $doc;157 }158 159 protected function configureDocumentCategories($doc)160 {161 // category support162 $categories = $this->getModelCategories();163 164 if (count($categories) > 0)165 {166 foreach ($categories as $category)167 {168 $this->addCategory($category);169 }170 171 $doc->addField( $this->getLuceneField('text', 'sfl_category', implode(' ', $categories)) );172 }173 174 $doc->addField( $this->getLuceneField('unindexed', 'sfl_categories_cache', serialize($categories)) );175 176 return $doc;177 }178 179 160 /** 180 161 * Deletes the old model 181 * @param BaseObject $this->getModel() The model to delete182 162 */ 183 163 public function delete() … … 199 179 $method = $properties->get('validator'); 200 180 201 if ($method && method_exists($this->getModel(), $method))181 if ($method) 202 182 { 203 183 return (bool) $this->getModel()->$method(); … … 207 187 } 208 188 189 /** 190 * Returns an array of all the categories that this model is configured for 191 */ 209 192 protected function getModelCategories() 210 193 { 211 194 $retval = array(); 212 195 196 // change i18n to this culture 213 197 if (sfConfig::get('sf_i18n')) 214 198 { … … 220 204 foreach (parent::getModelCategories() as $category) 221 205 { 206 // if category fits into syntax "%XXX%" then we must replace it with ->getXXX() on the model 222 207 if (substr($category, 0, 1) == '%' && substr($category, -1, 1) == '%') 223 208 { … … 225 210 226 211 $getter = 'get' . sfInflector::camelize($category); 227 228 212 $getterValue = $this->getModel()->$getter(); 229 213 214 // attempt to convert value to string 230 215 if (is_object($getterValue) && method_exists($getterValue, '__toString')) 231 216 { … … 234 219 elseif (!is_scalar($getterValue)) 235 220 { 236 throw new sfLuceneIndexerException('Category value returned is not a string (got a ' . gettype($getterValue) . ' ) and could not be transformed into a string.'); 237 } 238 221 throw new sfLuceneIndexerException('Category value returned is not a string (got a ' . gettype($getterValue) . ') and could not be transformed into a string.'); 222 } 223 224 // store value for returning. as the value comes the model, it is already 225 // configured for i18n 239 226 $retval[] = $getterValue; 240 227 } 241 228 else 242 229 { 230 // value did not come from model, so store it using i18n if possible 231 243 232 if (isset($i18n) && $i18n) 244 233 { … … 255 244 } 256 245 246 /** 247 * Calculates the GUID for the model 248 */ 257 249 public function getModelGuid() 258 250 { plugins/sfLucenePlugin/branches/1.1/lib/storage/sfLuceneStorageBlackhole.class.php
r6392 r6816 10 10 /** 11 11 * This storage container does not write to the disc, but instead just stores 12 * in memory. This is useful for memory teesting.12 * in memory. This is useful for unit testing. 13 13 * @package sfLucenePlugin 14 14 * @subpackage Storage