eZ Publish  [trunk]
ezsearch.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZSearch class.
00004  *
00005  * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved.
00006  * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
00007  * @version //autogentag//
00008  * @package kernel
00009  */
00010 
00011 /*!
00012   \class eZSearch
00013   \ingroup eZKernel
00014   \brief eZSearch handles indexing of objects to the search engine
00015 
00016 */
00017 
00018 class eZSearch
00019 {
00020     function eZSearch()
00021     {
00022 
00023     }
00024 
00025    /*!
00026      \static
00027      determine how to pass the commit argument, for deletes and updates
00028      maybe this needs to be further splitted
00029     */
00030 
00031     static function needCommit()
00032     {
00033         $searchEngine = eZSearch::getEngine();
00034 
00035         if ( $searchEngine instanceof ezpSearchEngine )
00036         {
00037             return $searchEngine->needCommit();
00038         }
00039         return true;
00040     }
00041     /*!
00042      \static
00043      See if a remove is needed in an update of content objects
00044     */
00045 
00046     static function needRemoveWithUpdate()
00047     {
00048         $searchEngine = eZSearch::getEngine();
00049 
00050         if ( $searchEngine instanceof ezpSearchEngine )
00051         {
00052             return $searchEngine->needRemoveWithUpdate();
00053         }
00054         return true;
00055     }
00056 
00057     /**
00058      * Removes object $contentObject from the search database.
00059      *
00060      * @param eZContentObject $contentObject the content object to remove
00061      * @param bool $commit Whether to commit after removing the object
00062      * @return bool True if the operation succeed.
00063      */
00064     static function removeObject( $contentObject, $commit = true )
00065     {
00066         $searchEngine = eZSearch::getEngine();
00067 
00068         if ( $searchEngine instanceof ezpSearchEngine )
00069         {
00070             return $searchEngine->removeObject( $contentObject, $commit );
00071         }
00072 
00073         return false;
00074     }
00075 
00076     /**
00077      * Adds object $contentObject to the search database.
00078      *
00079      * @param eZContentObject $contentObject Object to add to search engine
00080      * @param bool $commit Whether to commit after adding the object
00081      * @return bool True if the operation succeed.
00082      */
00083     static function addObject( $contentObject, $commit = true )
00084     {
00085         $searchEngine = eZSearch::getEngine();
00086 
00087         if ( $searchEngine instanceof ezpSearchEngine )
00088         {
00089             return $searchEngine->addObject( $contentObject, $commit );
00090         }
00091 
00092         return false;
00093     }
00094 
00095     /*!
00096      \static
00097      Runs a query to the search engine.
00098     */
00099     static function search( $searchText, $params, $searchTypes = array() )
00100     {
00101         $searchEngine = eZSearch::getEngine();
00102 
00103         if ( $searchEngine instanceof ezpSearchEngine )
00104         {
00105             return $searchEngine->search( $searchText, $params, $searchTypes );
00106         }
00107     }
00108 
00109     /*!
00110      \static
00111     */
00112     static function normalizeText( $text )
00113     {
00114         $searchEngine = eZSearch::getEngine();
00115 
00116         if ( $searchEngine instanceof ezpSearchEngine )
00117         {
00118             return $searchEngine->normalizeText( $text );
00119         }
00120 
00121         return '';
00122     }
00123 
00124     /*!
00125      \static
00126       returns search parameters in array based on supported search types and post variables
00127      */
00128     static function buildSearchArray()
00129     {
00130         $searchEngine = eZSearch::getEngine();
00131 
00132         $searchArray = array();
00133         $andSearchParts = array();
00134         $searchTypesDefinition = array( 'types' => array(), 'general_filter' => array() );
00135 
00136         if ( $searchEngine instanceof ezpSearchEngine )
00137         {
00138             // This method was renamed in pre 3.5 trunk
00139             if ( method_exists( $searchEngine, 'supportedSearchTypes' ) )
00140             {
00141                 $searchTypesDefinition = $searchEngine->supportedSearchTypes();  // new and correct
00142             }
00143             else
00144             {
00145                 $searchTypesDefinition = $searchEngine->suportedSearchTypes();  // deprecated
00146             }
00147         }
00148 
00149         $http = eZHTTPTool::instance();
00150 
00151         foreach ( $searchTypesDefinition['types'] as $searchType )
00152         {
00153             $postVariablePrefix = 'Content_search_' . $searchType['type'] . '_' . $searchType['subtype'] . '_';
00154             //print $postVariablePrefix . "\n";
00155             //print_r( $searchType['params'] );
00156             $searchArrayPartForType = array();
00157 
00158             $searchPart = array();
00159             $valuesFetched = false;
00160             $valuesMissing = false;
00161             foreach ( $searchType['params'] as $parameter )
00162             {
00163                 eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $postVariablePrefix . $parameter,
00164                                             'post variable to check' );
00165 
00166                 if ( $http->hasVariable( $postVariablePrefix . $parameter ) )
00167                 {
00168                     $values = $http->variable( $postVariablePrefix . $parameter );
00169                     eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $values, 'fetched values' );
00170 
00171                     foreach ( $values as $i => $value )
00172                     {
00173                         $searchArrayPartForType[$i][$parameter] = $values[$i];
00174                         $valuesFetched = true;
00175                     }
00176                 }
00177                 else
00178                 {
00179                     eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $postVariablePrefix . $parameter,
00180                                                 'post variable does not exist' );
00181                     $valuesMissing = true;
00182                     break;
00183                 }
00184             }
00185 
00186             if ( $valuesFetched == true && $valuesMissing == false )
00187             {
00188                 eZDebugSetting::writeDebug( 'kernel-search-ezsearch', 'adding values to search' );
00189                 foreach ( array_keys( $searchArrayPartForType ) as $key )
00190                 {
00191                     $part =& $searchArrayPartForType[$key];
00192                     $part['type'] = $searchType['type'];
00193                     $part['subtype'] = $searchType['subtype'];
00194 
00195                     if ( $part['type'] == 'attribute' )
00196                     {
00197                         // Remove incomplete search parts from the search.
00198                         // An incomplete search part is for instance an empty text field,
00199                         // or a select box with no selected values.
00200 
00201                         // This functionality has been moved to the search engine.
00202                         // Checking if it is defined in the search engine
00203                         if ( method_exists( $searchEngine, 'isSearchPartIncomplete' ) )
00204                         {
00205                             $removePart = $searchEngine->isSearchPartIncomplete( $part );
00206                         }
00207                         else // for backwards compatibility
00208                         {
00209                             $removePart = false;
00210                             switch ( $part['subtype'] )
00211                             {
00212                                 case 'fulltext':
00213                                 {
00214                                     if ( !isset( $part['value'] ) || $part['value'] == '' )
00215                                         $removePart = true;
00216                                 }
00217                                 break;
00218 
00219                                 case 'patterntext':
00220                                 {
00221                                     if ( !isset( $part['value'] ) || $part['value'] == '' )
00222                                         $removePart = true;
00223                                 }
00224                                 break;
00225 
00226                                 case 'integer':
00227                                 {
00228                                     if ( !isset( $part['value'] ) || $part['value'] == '' )
00229                                         $removePart = true;
00230                                 }
00231                                 break;
00232 
00233                                 case 'integers':
00234                                 {
00235                                     if ( !isset( $part['values'] ) || count( $part['values'] ) == 0 )
00236                                         $removePart = true;
00237                                 }
00238                                 break;
00239 
00240                                 case 'byrange':
00241                                 {
00242                                     if ( !isset( $part['from'] ) || $part['from'] == '' ||
00243                                          !isset( $part['to'] ) || $part['to'] == '' )
00244                                         $removePart = true;
00245                                 }
00246                                 break;
00247 
00248                                 case 'byidentifier':
00249                                 {
00250                                     if ( !isset( $part['value'] ) || $part['value'] == '' )
00251                                         $removePart = true;
00252                                 }
00253                                 break;
00254 
00255                                 case 'byidentifierrange':
00256                                 {
00257                                     if ( !isset( $part['from'] ) || $part['from'] == '' ||
00258                                          !isset( $part['to'] ) || $part['to'] == '' )
00259                                         $removePart = true;
00260                                 }
00261                                 break;
00262 
00263                                 case 'integersbyidentifier':
00264                                 {
00265                                     if ( !isset( $part['values'] ) || count( $part['values'] ) == 0 )
00266                                         $removePart = true;
00267                                 }
00268                                 break;
00269 
00270                                 case 'byarea':
00271                                 {
00272                                     if ( !isset( $part['from'] ) || $part['from'] == '' ||
00273                                          !isset( $part['to'] ) || $part['to'] == '' ||
00274                                          !isset( $part['minvalue'] ) || $part['minvalue'] == '' ||
00275                                          !isset( $part['maxvalue'] ) || $part['maxvalue'] == '' )
00276                                     {
00277                                         $removePart = true;
00278                                     }
00279                                 }
00280                             }
00281                         }
00282 
00283                         if ( $removePart )
00284                         {
00285                             eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $searchArrayPartForType[$key],
00286                                                         'removing incomplete search part' );
00287                             unSet( $searchArrayPartForType[$key] );
00288                         }
00289                     }
00290                 }
00291                 $andSearchParts = array_merge( $andSearchParts, $searchArrayPartForType );
00292             }
00293         }
00294         $generalFilter = array();
00295         foreach ( $searchTypesDefinition['general_filter'] as $searchType )
00296         {
00297 
00298             $postVariablePrefix = 'Content_search_' . $searchType['type'] . '_' . $searchType['subtype'] . '_';
00299 
00300             $searchArrayPartForType = array();
00301 
00302             $searchPart = array();
00303             $valuesFetched = false;
00304             $valuesMissing = false;
00305 
00306             foreach ( $searchType['params'] as $parameter )
00307             {
00308                 $varName = '';
00309                 $paramName = '';
00310                 if ( is_array( $parameter ) )
00311                 {
00312                     $varName = $postVariablePrefix . $parameter['value'];
00313                     $paramName = $parameter['value'];
00314                 }
00315                 else
00316                 {
00317                     $varName = $postVariablePrefix . $parameter;
00318                     $paramName = $parameter;
00319                 }
00320 
00321                 eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $varName,
00322                                             'post variable to check' );
00323 
00324                 if ( $http->hasVariable( $varName ) )
00325                 {
00326                     $values = $http->variable( $varName );
00327                     eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $values, 'fetched values' );
00328                     $searchArrayPartForType[$paramName] = $values;
00329                     $valuesFetched = true;
00330 
00331                 }
00332                 else
00333                 {
00334                     eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $varName,
00335                                                 'post variable does not exist' );
00336                     $valuesMissing = true;
00337                     break;
00338                 }
00339             }
00340 
00341             if ( $valuesFetched == true && $valuesMissing == false )
00342             {
00343                 eZDebugSetting::writeDebug( 'kernel-search-ezsearch', 'adding values to search' );
00344 
00345                 $part =& $searchArrayPartForType;
00346 
00347                 $part['type'] = $searchType['type'];
00348                 $part['subtype'] = $searchType['subtype'];
00349 
00350                 if ( $part['type'] == 'general' )
00351                 {
00352                         // Remove incomplete search parts from the search.
00353                         // An incomplete search part is for instance an empty text field,
00354                         // or a select box with no selected values.
00355                     $removePart = false;
00356                     switch ( $part['subtype'] )
00357                     {
00358                         case 'class':
00359                         {
00360                             if ( !isset( $part['value'] ) ||
00361                                  ( is_array( $part['value'] ) && count( $part['value'] ) == 0 ) ||
00362                                  ( !is_array( $part['value'] ) && $part['value'] == '' ) )
00363                                 $removePart = true;
00364                         }
00365                         break;
00366                         case 'publishdate':
00367                         {
00368                             if ( !isset( $part['value'] ) ||
00369                                  ( is_array( $part['value'] ) && count( $part['value'] ) == 0 ) ||
00370                                  ( !is_array( $part['value'] ) && $part['value'] == '' ) )
00371                                 $removePart = true;
00372                         }
00373                         break;
00374                         case 'subtree':
00375                         {
00376                             if ( !isset( $part['value'] ) ||
00377                                  ( is_array( $part['value'] ) && count( $part['value'] ) == 0 ) ||
00378                                  ( !is_array( $part['value'] ) && $part['value'] == '' ) )
00379 
00380                                 $removePart = true;
00381                         }
00382                         break;
00383                     }
00384 
00385                     if ( $removePart )
00386                     {
00387                         eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $searchArrayPartForType[$key],
00388                                                     'removing incomplete search part' );
00389                         unSet( $searchArrayPartForType[$key] );
00390                         continue;
00391                     }
00392                 }
00393 
00394                 $generalFilter = array_merge( $generalFilter, array( $searchArrayPartForType ) );
00395             }
00396 
00397 
00398         }
00399 
00400         if ( $andSearchParts != null )
00401         {
00402             $searchArray['and'] = $andSearchParts;
00403         }
00404         if ( $generalFilter != null )
00405         {
00406             $searchArray['general'] = $generalFilter;
00407         }
00408 
00409         eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $searchArray, 'search array' );
00410         return $searchArray;
00411     }
00412 
00413     /*!
00414      \static
00415      Tells the current search engine to cleanup up all data.
00416     */
00417     static function cleanup()
00418     {
00419         $searchEngine = eZSearch::getEngine();
00420 
00421         if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'cleanup' ) )
00422         {
00423             $searchEngine->cleanup();
00424         }
00425     }
00426 
00427     /*!
00428      \static
00429      Get object instance of eZSearch engine to use.
00430 
00431      \return instance of eZSearch class.
00432     */
00433     static function getEngine()
00434     {
00435         // Get instance if already created.
00436         $instanceName = "eZSearchPlugin_" . $GLOBALS["eZCurrentAccess"]["name"];
00437         if ( isset( $GLOBALS[$instanceName] ) )
00438         {
00439             return $GLOBALS[$instanceName];
00440         }
00441 
00442         $ini = eZINI::instance();
00443 
00444         $searchEngineString = 'ezsearch';
00445         if ( $ini->hasVariable( 'SearchSettings', 'SearchEngine' ) == true )
00446         {
00447             $searchEngineString = $ini->variable( 'SearchSettings', 'SearchEngine' );
00448         }
00449 
00450         $directoryList = array();
00451         if ( $ini->hasVariable( 'SearchSettings', 'ExtensionDirectories' ) )
00452         {
00453             $extensionDirectories = $ini->variable( 'SearchSettings', 'ExtensionDirectories' );
00454             if ( is_array( $extensionDirectories ) )
00455             {
00456                 $directoryList = eZExtension::expandedPathList( $extensionDirectories, 'search/plugins' );
00457             }
00458         }
00459 
00460         $kernelDir = array( 'kernel/search/plugins' );
00461         $directoryList = array_merge( $kernelDir, $directoryList );
00462 
00463         foreach( $directoryList as $directory )
00464         {
00465             $searchEngineFile = implode( '/', array( $directory, strtolower( $searchEngineString ), strtolower( $searchEngineString ) ) ) . '.php';
00466 
00467             if ( file_exists( $searchEngineFile ) )
00468             {
00469                 eZDebugSetting::writeDebug( 'kernel-search-ezsearch', 'Loading search engine from ' . $searchEngineFile, 'eZSearch::getEngine' );
00470 
00471                 include_once( $searchEngineFile );
00472                 $GLOBALS[$instanceName] = new $searchEngineString();
00473                 return $GLOBALS[$instanceName];
00474             }
00475         }
00476 
00477         eZDebug::writeDebug( 'Unable to find the search engine:' . $searchEngineString, 'eZSearch' );
00478         eZDebug::writeDebug( 'Tried paths: ' . implode( ', ', $directoryList ), 'eZSearch' );
00479         return false;
00480     }
00481 
00482     /**
00483      * Notifies search engine about the change of section of a set of objects
00484      *
00485      * @since 4.6
00486      * @param array $objectIDs
00487      * @param int $sectionID
00488      * @return false|mixed false in case method is undefined, otherwise return the result of the search engine call
00489      */
00490     public static function updateObjectsSection( array $objectIDs, $sectionID )
00491     {
00492         $searchEngine = eZSearch::getEngine();
00493         if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'updateObjectsSection' ) )
00494         {
00495             return $searchEngine->updateObjectsSection( $objectIDs, $sectionID );
00496         }
00497         return false;
00498     }
00499 
00500     /**
00501      * Notifies search engine about section changes
00502      *
00503      * @since 4.1
00504      * @param int $nodeID
00505      * @param int $sectionID
00506      * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
00507      */
00508     public static function updateNodeSection( $nodeID, $sectionID )
00509     {
00510         $searchEngine = eZSearch::getEngine();
00511 
00512         if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'updateNodeSection' ) )
00513         {
00514             return $searchEngine->updateNodeSection( $nodeID, $sectionID );
00515         }
00516 
00517         return false;
00518     }
00519 
00520     /**
00521      * Notifies search engine about node visibility changes
00522      *
00523      * @since 4.1
00524      * @param int $nodeID
00525      * @param string $action "hide" or "show"
00526      * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
00527      */
00528     public static function updateNodeVisibility( $nodeID, $action )
00529     {
00530         $searchEngine = eZSearch::getEngine();
00531 
00532         if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'updateNodeVisibility' ) )
00533         {
00534             return $searchEngine->updateNodeVisibility( $nodeID, $action );
00535         }
00536 
00537         return false;
00538     }
00539 
00540     /**
00541      * Notifies search engine about new node assignments added
00542      *
00543      * @since 4.1
00544      * @param int $mainNodeID
00545      * @param int $objectID
00546      * @param array $nodeAssignmentIDList
00547      * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
00548      */
00549     public static function addNodeAssignment( $mainNodeID, $objectID, $nodeAssignmentIDList )
00550     {
00551         $searchEngine = eZSearch::getEngine();
00552 
00553         if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'addNodeAssignment' ) )
00554         {
00555             return $searchEngine->addNodeAssignment( $mainNodeID, $objectID, $nodeAssignmentIDList );
00556         }
00557 
00558         return false;
00559     }
00560 
00561     /**
00562      * Notifies search engine about removed node assignments and what the new main node is (same if not changed)
00563      *
00564      * @since 4.1
00565      * @param int $mainNodeID
00566      * @param int $newMainNodeID
00567      * @param int $objectID
00568      * @param array $nodeAssigmentIDList
00569      * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
00570      */
00571     public static function removeNodeAssignment( $mainNodeID, $newMainNodeID, $objectID, $nodeAssigmentIDList )
00572     {
00573         $searchEngine = eZSearch::getEngine();
00574 
00575         if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'removeNodeAssignment' ) )
00576         {
00577             return $searchEngine->removeNodeAssignment( $mainNodeID, $newMainNodeID, $objectID, $nodeAssigmentIDList );
00578         }
00579 
00580         return false;
00581     }
00582 
00583     /**
00584      * Notifies search engine about nodes being removed
00585      *
00586      * @since 4.1
00587      * @param array $nodeIdList Array of node ID to remove.
00588      * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
00589      */
00590     public static function removeNodes( array $nodeIdList )
00591     {
00592         $searchEngine = self::getEngine();
00593 
00594         if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'removeNodes' ) )
00595         {
00596             return $searchEngine->removeNodes( $nodeIdList );
00597         }
00598 
00599         return false;
00600     }
00601 
00602     /**
00603      * Notifies search engine about updates to object states
00604      *
00605      * @since 4.1
00606      * @param int $objectID
00607      * @param array $objectStateList
00608      * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
00609      */
00610     public static function updateObjectState( $objectID, $objectStateList )
00611     {
00612         $searchEngine = eZSearch::getEngine();
00613 
00614         if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'updateObjectState' ) )
00615         {
00616             return $searchEngine->updateObjectState( $objectID, $objectStateList );
00617         }
00618 
00619         return false;
00620     }
00621 
00622     /**
00623      * Notifies search engine about an swap node operation
00624      *
00625      * @since 4.1
00626      * @param int $nodeID
00627      * @param int $selectedNodeID
00628      * @param array $nodeIdList
00629      * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
00630      */
00631     public static function swapNode( $nodeID, $selectedNodeID, $nodeIdList = array() )
00632     {
00633         $searchEngine = eZSearch::getEngine();
00634 
00635         if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'swapNode' ) )
00636         {
00637             return $searchEngine->swapNode( $nodeID, $selectedNodeID, $nodeIdList = array() );
00638         }
00639 
00640         return false;
00641     }
00642 }
00643 
00644 ?>