[ Index ] |
|
Code source de LifeType 1.2.4 |
1 <?php 2 3 lt_include( PLOG_CLASS_PATH."class/dao/articlestatus.class.php" ); 4 lt_include( PLOG_CLASS_PATH."class/dao/model.class.php" ); 5 lt_include( PLOG_CLASS_PATH."class/dao/searchresult.class.php" ); 6 lt_include( PLOG_CLASS_PATH."class/dao/blogstatus.class.php" ); 7 8 define( "SEARCH_ARTICLE", 1 ); 9 define( "SEARCH_BLOG", 2 ); 10 define( "SEARCH_GALLERYRESOURCE", 3 ); 11 12 /** 13 * \ingroup DAO 14 * 15 * Provides search facilities. 16 * 17 * This class provides methods for searching through articles, comments and custom fields. 18 * 19 * @see Articles 20 * @see ArticleComments 21 * @see CustomFields 22 */ 23 class SearchEngine extends Model 24 { 25 /** 26 * takes the search string as originally input by a user and makes it "better", in the sense 27 * that for example converts it to "term1 AND term2" instead of "term1 OR term2" which is the 28 * default behaviour. In order to do so, the "+" operator must be added before each one of the 29 * search terms as long as it is not already there. 30 * 31 * @param searchTerms The original search string 32 * @return Returns an 'improved' version of the search terms 33 * @static 34 */ 35 function adaptSearchString( $searchTerms ) 36 { 37 // load this module only if needed... 38 lt_include( PLOG_CLASS_PATH."class/data/textfilter.class.php" ); 39 $tf = new Textfilter(); 40 $resultTerms = $tf->filterCharacters( $searchTerms, Array( '"', ';', '.' )); 41 $resultTerms = Db::qstr($resultTerms); 42 43 $resultTerms = trim($resultTerms); 44 return $resultTerms; 45 } 46 47 /** 48 * MARKWU: 49 * takes the search string as originally input by a user and makes it "better", in the sense 50 * that for example converts it to "term1 AND term2" instead of "term1 OR term2" which is the 51 * default behaviour. In order to do so, the "+" operator must be added before each one of the 52 * search terms as long as it is not already there. This one is for public use, and will also 53 * convert the search string to a search terms array. 54 * 55 * @param searchTerms The original search string 56 * @return Returns an 'improved' and 'arraized' version of the search terms 57 */ 58 function getAdaptSearchTerms ( $searchTerms ) 59 { 60 $resultTerms = Db::qstr($searchTerms); 61 $resultTerms = trim($resultTerms); 62 $resultTerms = explode(' ',$resultTerms); 63 return $resultTerms; 64 } 65 66 /** 67 * Searches through articles, custom fields and comments only if enabled 68 * 69 * @param blogId The blog id where we're searching, or -1 if we're doing a global search 70 * @param searchTerms A string containing the search terms 71 * @param status In case we're looking for a particular status 72 * @param includeFuture 73 * @param page Page of results to return 74 * @param itemsPerPage Number of items per page 75 * @return 76 * @see searchArticles 77 * @see searchCustomFields 78 * @see searchComments 79 */ 80 function search( $blogId, $searchTerms, $status = POST_STATUS_PUBLISHED, $includeFuture = true, $page = -1, $itemsPerPage = -1 ) 81 { 82 // calculate the conditions right away, they will be used by both sides of the union 83 $conds = ""; 84 if( $blogId != -1 ) 85 $conds .= " AND a.blog_id = ".Db::qstr( $blogId ); 86 if( $status != -1 ) 87 $conds .= " AND a.status = ".$status; 88 if( !$includeFuture ) 89 $conds .= " AND a.date < NOW()"; 90 91 // first change 92 $prefix = $this->getPrefix(); 93 94 // check if we can use fulltext indexes 95 $db =& Db::getDb(); 96 if( $db->isFullTextSupported()) { 97 $query = "(SELECT a.* FROM {$prefix}articles a 98 INNER JOIN {$prefix}articles_text at ON a.id = at.article_id 99 WHERE MATCH(at.normalized_text, at.normalized_topic) AGAINST ('".Db::qstr($searchTerms)."' IN BOOLEAN MODE) 100 {$conds}) 101 UNION 102 (SELECT a.* FROM {$prefix}articles a 103 INNER JOIN {$prefix}custom_fields_values cfv ON a.id = cfv.article_id 104 WHERE MATCH(cfv.normalized_value) AGAINST ('".Db::qstr($searchTerms)."' IN BOOLEAN MODE) 105 {$conds}) 106 ORDER BY date DESC"; 107 } 108 else { 109 $query = "SELECT DISTINCT a.id AS id FROM {$prefix}articles a ". 110 "WHERE ".$this->getArticleSearchConditions( $searchTerms )." {$conds} ORDER BY a.date DESC"; 111 } 112 113 $result = $this->Execute( $query, $page, $itemsPerPage ); 114 115 lt_include( PLOG_CLASS_PATH."class/dao/articles.class.php" ); 116 $articles = new Articles(); 117 118 if( !$result ) 119 return( Array()); 120 121 $results = Array(); 122 while( $row = $result->FetchRow()) { 123 // depending on whether fulltext is available, we will have either fetched all we need so that 124 // we can map the row directly into an object, or then we have to use the cache to get all 125 // articles one by one 126 if( $db->isFullTextSupported()) 127 $results[] = new SearchResult( $articles->mapRow( $row ), SEARCH_RESULT_ARTICLE, $searchTerms ); 128 else 129 $results[] = new SearchResult( $articles->getArticle( $row["id"] ), SEARCH_RESULT_ARTICLE, $searchTerms ); 130 } 131 132 return( $results ); 133 } 134 135 /** 136 * Returns the number of search results, but this method only applies to article 137 * searches. If you're interested in getting the number of total matching blogs or 138 * resources, use getNumSiteSearchResults 139 * 140 * @param blogId 141 * @param searchTerms 142 * @param status 143 * @return 144 */ 145 function getNumSearchResults( $blogId, $searchTerms, $status, $includeFuture = true ) 146 { 147 $prefix = $this->getPrefix(); 148 149 // calculate the additional conditions beforehad 150 $conds = ""; 151 if( $blogId != -1 ) 152 $conds .= " AND a.blog_id = ".Db::qstr( $blogId ); 153 if( $status != -1 ) 154 $conds .= " AND a.status = ".$status; 155 if( !$includeFuture ) 156 $conds .= " AND a.date < NOW()"; 157 158 // check if the db supports fulltext searches and if so act accordingly 159 $db =& Db::getDb(); 160 if( $db->isFullTextSupported()) { 161 // faster path via the fulltext indexes 162 $query = "(SELECT COUNT(a.id) AS total FROM {$prefix}articles a 163 INNER JOIN {$prefix}articles_text at ON a.id = at.article_id 164 WHERE MATCH(at.normalized_text, at.normalized_topic) AGAINST ('".Db::qstr($searchTerms)."' IN BOOLEAN MODE) 165 {$conds}) 166 UNION 167 (SELECT COUNT(a.id) AS total FROM {$prefix}articles a 168 INNER JOIN {$prefix}custom_fields_values cfv ON a.id = cfv.article_id 169 WHERE MATCH(cfv.normalized_value) AGAINST ('".Db::qstr($searchTerms)."' IN BOOLEAN MODE) 170 {$conds})"; 171 // execute the query, and it should give us exactly two rows: one per each one of the queries of the union, so 172 // the total amount of posts that match the search condition should be the sum of those two rows 173 $result = $this->Execute( $query ); 174 if( !$result ) 175 return 0; 176 177 $total = 0; 178 while( $row = $result->FetchRow()) { 179 $total += $row["total"]; 180 } 181 } 182 else { 183 // alternative, slower path 184 $query = $this->getArticleSearchConditions( $searchTerms ); 185 186 $total = $this->getNumItems( "{$prefix}articles a", $query, "a.id" ); 187 } 188 189 return( $total ); 190 } 191 192 /** 193 * @private 194 * Returns a string that can be used as part of WHERE condition in an SQL query and that will return 195 * all the articles in any blog that match the given search terms. It works by building 3 196 * different queries, one to find all the matching articles, one to find all the matching custom fields 197 * and another one to find all the matching comments and then puts the results together. 198 */ 199 function getArticleSearchConditions( $searchTerms ) 200 { 201 lt_include( PLOG_CLASS_PATH."class/dao/articles.class.php" ); 202 lt_include( PLOG_CLASS_PATH."class/dao/articlecomments.class.php" ); 203 lt_include( PLOG_CLASS_PATH."class/dao/customfields/customfieldsvalues.class.php" ); 204 205 $prefix = $this->getPrefix(); 206 207 // get the search conditions for articles 208 $articles = new Articles(); 209 $articlesConds = $articles->getSearchConditions( $searchTerms ); 210 211 // now for comments 212 $comments = new ArticleComments(); 213 $tmpCond = $comments->getSearchConditions( $searchTerms ); 214 $query = "SELECT c.article_id AS article_id FROM {$prefix}articles_comments c 215 WHERE $tmpCond AND c.status = ".COMMENT_STATUS_NONSPAM; 216 $result = $this->Execute( $query ); 217 218 $ids = Array(); 219 while( $row = $result->FetchRow()) { 220 $ids[] = $row['article_id']; 221 } 222 $result->Close(); 223 if ( !empty( $ids ) ) 224 $commentsConds = 'a.id IN ('.implode( ', ', $ids ).')'; 225 else 226 $commentsConds = 'a.id = -1'; 227 228 // and finally for custom fields 229 $fields = new CustomFieldsValues(); 230 $tmpCond = $fields->getSearchConditions( $searchTerms ); 231 $query = "SELECT v.article_id AS article_id FROM {$prefix}custom_fields_values v WHERE $tmpCond"; 232 $result = $this->Execute( $query ); 233 234 $ids = Array(); 235 while( $row = $result->FetchRow()) { 236 $ids[] = $row['article_id']; 237 } 238 $result->Close(); 239 if ( !empty( $ids ) ) 240 $fieldsConds = 'a.id IN ('.implode( ', ', $ids ).')'; 241 else 242 $fieldsConds = 'a.id = -1'; 243 244 // and try to build a combined query 245 $query = "(({$articlesConds}) OR ({$commentsConds}) OR ({$fieldsConds}))"; 246 247 return( $query ); 248 } 249 250 /** 251 * performs a site-wide search 252 * @param searchTerms An string with the terms for the search 253 * @param searchType One of the following: SEARCH_ARTICLE, SEARCH_BLOG or SEARCH_GALLERYRESOURCE 254 * @param status The status. Each item has its own constants for status codes, so this value will depend 255 * on what we're looking for. 256 * @param includeFuture Whether to include posts with a future date in the results 257 * @param page The page of results to get 258 * @param itemsPerPage Number of items per page 259 * @return 260 * @see search 261 * @see searchArticles 262 * @see searchCustomFields 263 * @see searchComments 264 */ 265 function siteSearch( $searchTerms, $searchType, $status = -1, $includeFuture = true, $page = -1, $itemsPerPage = DEFAULT_ITEMS_PER_PAGE ) 266 { 267 switch ( $searchType ) 268 { 269 case SEARCH_BLOG: 270 if ( $status == -1 ) 271 $status = BLOG_STATUS_ACTIVE; 272 $result = $this->searchBlogs( $searchTerms, $status, $includeFuture, $page, $itemsPerPage ); 273 break; 274 case SEARCH_GALLERYRESOURCE: 275 $result = $this->searchGalleryResources( '_all_', $searchTerms, $page, $itemsPerPage ); 276 break; 277 default: 278 // search articles and any other value of the $searchType parameter 279 if ( $status == -1 ) 280 $status = POST_STATUS_PUBLISHED; 281 $result = $this->search( -1, $searchTerms, $status, $includeFuture, $page, $itemsPerPage ); 282 } 283 return $result; 284 } 285 286 /** 287 * Returns the total number of matching items, be it articles, blogs or files. 288 * 289 * @param searchTerms An string with the terms for the search 290 * @param searchType One of the following: SEARCH_ARTICLE, SEARCH_BLOG or SEARCH_GALLERYRESOURCE 291 * @param status The status. Each item has its own constants for status codes, so this value will depend 292 * on what we're looking for. 293 * @param includeFuture whether to include future articles in the search 294 * @return The number of matching items for the given search terms 295 */ 296 function getNumSiteSearchResults( $searchTerms, $searchType, $status = -1, $includeFuture = true ) 297 { 298 if( $searchType == SEARCH_ARTICLE ) { 299 if( $status == -1 ) 300 $status = POST_STATUS_PUBLISHED; 301 302 $result = $this->getNumSearchResults( -1, $searchTerms, $status, $includeFuture ); 303 } 304 elseif( $searchType == SEARCH_BLOG ) { 305 if ( $status == -1 ) 306 $status = BLOG_STATUS_ACTIVE; 307 308 lt_include( PLOG_CLASS_PATH."class/dao/blogs.class.php" ); 309 310 $blogs = new Blogs(); 311 $result = $blogs->getNumBlogs( $status, ALL_BLOG_CATEGORIES, $searchTerms ); 312 } 313 else { 314 lt_include( PLOG_CLASS_PATH."class/gallery/dao/galleryresources.class.php" ); 315 316 $resources = new GalleryResources(); 317 $result = $resources->getNumUserResources( -1, // owner id 318 GALLERY_NO_ALBUM, // any album 319 GALLERY_RESOURCE_ANY, // of any kind 320 $searchTerms // search terms 321 ); 322 } 323 324 return( $result ); 325 } 326 327 /** 328 * Returns an array of SearchResult objects containing information about the search, such as the 329 * relevance (not very relevant, though :)), and the BlogObject 330 * 331 * @param searchTerms An string with the terms for the search 332 * @param blogStatus 333 * @param page The page of results to get 334 * @param itemsPerPage Number of items per page 335 * @return An array of SearchResult objects 336 */ 337 function searchBlogs( $searchTerms, $blogStatus = BLOG_STATUS_ACTIVE, $page = -1, $itemsPerPage = DEFAULT_ITEMS_PER_PAGE ) 338 { 339 lt_include( PLOG_CLASS_PATH."class/dao/blogs.class.php" ); 340 341 $blogs = new Blogs(); 342 $blogsResult = $blogs->getAllBlogs( $blogStatus, 343 ALL_BLOG_CATEGORIES, 344 $searchTerms, 345 $page, 346 $itemsPerPage ); 347 348 $results = Array(); 349 foreach( $blogsResult as $blog ) { 350 $results[] = new SearchResult( $blog, SEARCH_RESULT_ARTICLE, $searchTerms ); 351 } 352 353 return( $results ); 354 } 355 356 /** 357 * Returns an array of SearchResult objects containing information about the searchand the GalleryResource object 358 * 359 * @param ownerId the id of the blog/user whose pictures we're searching, or "-1" or "_all_" to search through 360 * all of them. 361 * @param searchTerms An string with the terms for the search 362 * @param page The page of results to get 363 * @param itemsPerPage Number of items per page 364 * @return An array of SearchResult objects 365 */ 366 function searchGalleryResources( $ownerId, $searchTerms, $page = -1, $itemsPerPage = DEFAULT_ITEMS_PER_PAGE ) 367 { 368 lt_include( PLOG_CLASS_PATH."class/gallery/dao/galleryresources.class.php" ); 369 370 $galleryResources = new GalleryResources(); 371 $galleryResourcesResult = $galleryResources->getUserResources( $ownerId, 372 GALLERY_NO_ALBUM, 373 GALLERY_RESOURCE_ANY, 374 $searchTerms, 375 $page, 376 $itemsPerPage ); 377 378 $results = Array(); 379 foreach( $galleryResourcesResult as $galleryResource ) { 380 $results[] = new SearchResult( $galleryResource, SEARCH_RESULT_GALLERYRESOURCE, $searchTerms ); 381 } 382 383 return( $results ); 384 } 385 } 386 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Mon Nov 26 21:04:15 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |