PageRenderTime 48ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/kernel/classes/ezsearch.php

http://github.com/ezsystems/ezpublish
PHP | 659 lines | 422 code | 91 blank | 146 comment | 110 complexity | 3193a9bbd89180d91df32df9812ee295 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * File containing the eZSearch class.
  4. *
  5. * @copyright Copyright (C) eZ Systems AS. All rights reserved.
  6. * @license For full copyright and license information view LICENSE file distributed with this source code.
  7. * @version //autogentag//
  8. * @package kernel
  9. */
  10. /*!
  11. \class eZSearch
  12. \ingroup eZKernel
  13. \brief eZSearch handles indexing of objects to the search engine
  14. */
  15. class eZSearch
  16. {
  17. /*!
  18. \static
  19. determine how to pass the commit argument, for deletes and updates
  20. maybe this needs to be further splitted
  21. */
  22. static function needCommit()
  23. {
  24. $searchEngine = eZSearch::getEngine();
  25. if ( $searchEngine instanceof ezpSearchEngine )
  26. {
  27. return $searchEngine->needCommit();
  28. }
  29. return true;
  30. }
  31. /*!
  32. \static
  33. See if a remove is needed in an update of content objects
  34. */
  35. static function needRemoveWithUpdate()
  36. {
  37. $searchEngine = eZSearch::getEngine();
  38. if ( $searchEngine instanceof ezpSearchEngine )
  39. {
  40. return $searchEngine->needRemoveWithUpdate();
  41. }
  42. return true;
  43. }
  44. /**
  45. * Removes object $contentObject from the search database.
  46. *
  47. * @deprecated Since 5.0, use removeObjectById()
  48. * @param eZContentObject $contentObject the content object to remove
  49. * @param bool $commit Whether to commit after removing the object
  50. * @return bool True if the operation succeed.
  51. */
  52. static function removeObject( $contentObject, $commit = null )
  53. {
  54. $searchEngine = eZSearch::getEngine();
  55. if ( $searchEngine instanceof ezpSearchEngine )
  56. {
  57. return $searchEngine->removeObjectById( $contentObject->attribute( "id" ), $commit );
  58. }
  59. return false;
  60. }
  61. /**
  62. * Removes a content object by Id from the search database.
  63. *
  64. * @since 5.0
  65. * @param int $contentObjectId the content object to remove by id
  66. * @param bool $commit Whether to commit after removing the object
  67. * @return bool True if the operation succeed.
  68. */
  69. static function removeObjectById( $contentObjectId, $commit = null )
  70. {
  71. $searchEngine = eZSearch::getEngine();
  72. if ( $searchEngine instanceof ezpSearchEngine )
  73. {
  74. return $searchEngine->removeObjectById( $contentObjectId, $commit );
  75. }
  76. return false;
  77. }
  78. /**
  79. * Adds object $contentObject to the search database.
  80. *
  81. * @param eZContentObject $contentObject Object to add to search engine
  82. * @param bool $commit Whether to commit after adding the object
  83. * @return bool True if the operation succeed.
  84. */
  85. static function addObject( $contentObject, $commit = true )
  86. {
  87. $searchEngine = eZSearch::getEngine();
  88. if ( $searchEngine instanceof ezpSearchEngine )
  89. {
  90. return $searchEngine->addObject( $contentObject, $commit );
  91. }
  92. return false;
  93. }
  94. /*!
  95. \static
  96. Runs a query to the search engine.
  97. */
  98. static function search( $searchText, $params, $searchTypes = array() )
  99. {
  100. $searchEngine = eZSearch::getEngine();
  101. if ( $searchEngine instanceof ezpSearchEngine )
  102. {
  103. return $searchEngine->search( $searchText, $params, $searchTypes );
  104. }
  105. }
  106. /*!
  107. \static
  108. */
  109. static function normalizeText( $text )
  110. {
  111. $searchEngine = eZSearch::getEngine();
  112. if ( $searchEngine instanceof ezpSearchEngine )
  113. {
  114. return $searchEngine->normalizeText( $text );
  115. }
  116. return '';
  117. }
  118. /*!
  119. \static
  120. returns search parameters in array based on supported search types and post variables
  121. */
  122. static function buildSearchArray()
  123. {
  124. $searchEngine = eZSearch::getEngine();
  125. $searchArray = array();
  126. $andSearchParts = array();
  127. $searchTypesDefinition = array( 'types' => array(), 'general_filter' => array() );
  128. if ( $searchEngine instanceof ezpSearchEngine )
  129. {
  130. // This method was renamed in pre 3.5 trunk
  131. if ( method_exists( $searchEngine, 'supportedSearchTypes' ) )
  132. {
  133. $searchTypesDefinition = $searchEngine->supportedSearchTypes(); // new and correct
  134. }
  135. else
  136. {
  137. $searchTypesDefinition = $searchEngine->suportedSearchTypes(); // deprecated
  138. }
  139. }
  140. $http = eZHTTPTool::instance();
  141. foreach ( $searchTypesDefinition['types'] as $searchType )
  142. {
  143. $postVariablePrefix = 'Content_search_' . $searchType['type'] . '_' . $searchType['subtype'] . '_';
  144. //print $postVariablePrefix . "\n";
  145. //print_r( $searchType['params'] );
  146. $searchArrayPartForType = array();
  147. $searchPart = array();
  148. $valuesFetched = false;
  149. $valuesMissing = false;
  150. foreach ( $searchType['params'] as $parameter )
  151. {
  152. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $postVariablePrefix . $parameter,
  153. 'post variable to check' );
  154. if ( $http->hasVariable( $postVariablePrefix . $parameter ) )
  155. {
  156. $values = $http->variable( $postVariablePrefix . $parameter );
  157. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $values, 'fetched values' );
  158. foreach ( $values as $i => $value )
  159. {
  160. $searchArrayPartForType[$i][$parameter] = $values[$i];
  161. $valuesFetched = true;
  162. }
  163. }
  164. else
  165. {
  166. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $postVariablePrefix . $parameter,
  167. 'post variable does not exist' );
  168. $valuesMissing = true;
  169. break;
  170. }
  171. }
  172. if ( $valuesFetched == true && $valuesMissing == false )
  173. {
  174. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', 'adding values to search' );
  175. foreach ( array_keys( $searchArrayPartForType ) as $key )
  176. {
  177. $part =& $searchArrayPartForType[$key];
  178. $part['type'] = $searchType['type'];
  179. $part['subtype'] = $searchType['subtype'];
  180. if ( $part['type'] == 'attribute' )
  181. {
  182. // Remove incomplete search parts from the search.
  183. // An incomplete search part is for instance an empty text field,
  184. // or a select box with no selected values.
  185. // This functionality has been moved to the search engine.
  186. // Checking if it is defined in the search engine
  187. if ( method_exists( $searchEngine, 'isSearchPartIncomplete' ) )
  188. {
  189. $removePart = $searchEngine->isSearchPartIncomplete( $part );
  190. }
  191. else // for backwards compatibility
  192. {
  193. $removePart = false;
  194. switch ( $part['subtype'] )
  195. {
  196. case 'fulltext':
  197. {
  198. if ( !isset( $part['value'] ) || $part['value'] == '' )
  199. $removePart = true;
  200. }
  201. break;
  202. case 'patterntext':
  203. {
  204. if ( !isset( $part['value'] ) || $part['value'] == '' )
  205. $removePart = true;
  206. }
  207. break;
  208. case 'integer':
  209. {
  210. if ( !isset( $part['value'] ) || $part['value'] == '' )
  211. $removePart = true;
  212. }
  213. break;
  214. case 'integers':
  215. {
  216. if ( !isset( $part['values'] ) || count( $part['values'] ) == 0 )
  217. $removePart = true;
  218. }
  219. break;
  220. case 'byrange':
  221. {
  222. if ( !isset( $part['from'] ) || $part['from'] == '' ||
  223. !isset( $part['to'] ) || $part['to'] == '' )
  224. $removePart = true;
  225. }
  226. break;
  227. case 'byidentifier':
  228. {
  229. if ( !isset( $part['value'] ) || $part['value'] == '' )
  230. $removePart = true;
  231. }
  232. break;
  233. case 'byidentifierrange':
  234. {
  235. if ( !isset( $part['from'] ) || $part['from'] == '' ||
  236. !isset( $part['to'] ) || $part['to'] == '' )
  237. $removePart = true;
  238. }
  239. break;
  240. case 'integersbyidentifier':
  241. {
  242. if ( !isset( $part['values'] ) || count( $part['values'] ) == 0 )
  243. $removePart = true;
  244. }
  245. break;
  246. case 'byarea':
  247. {
  248. if ( !isset( $part['from'] ) || $part['from'] == '' ||
  249. !isset( $part['to'] ) || $part['to'] == '' ||
  250. !isset( $part['minvalue'] ) || $part['minvalue'] == '' ||
  251. !isset( $part['maxvalue'] ) || $part['maxvalue'] == '' )
  252. {
  253. $removePart = true;
  254. }
  255. }
  256. }
  257. }
  258. if ( $removePart )
  259. {
  260. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $searchArrayPartForType[$key],
  261. 'removing incomplete search part' );
  262. unSet( $searchArrayPartForType[$key] );
  263. }
  264. }
  265. }
  266. $andSearchParts = array_merge( $andSearchParts, $searchArrayPartForType );
  267. }
  268. }
  269. $generalFilter = array();
  270. foreach ( $searchTypesDefinition['general_filter'] as $searchType )
  271. {
  272. $postVariablePrefix = 'Content_search_' . $searchType['type'] . '_' . $searchType['subtype'] . '_';
  273. $searchArrayPartForType = array();
  274. $searchPart = array();
  275. $valuesFetched = false;
  276. $valuesMissing = false;
  277. foreach ( $searchType['params'] as $parameter )
  278. {
  279. $varName = '';
  280. $paramName = '';
  281. if ( is_array( $parameter ) )
  282. {
  283. $varName = $postVariablePrefix . $parameter['value'];
  284. $paramName = $parameter['value'];
  285. }
  286. else
  287. {
  288. $varName = $postVariablePrefix . $parameter;
  289. $paramName = $parameter;
  290. }
  291. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $varName,
  292. 'post variable to check' );
  293. if ( $http->hasVariable( $varName ) )
  294. {
  295. $values = $http->variable( $varName );
  296. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $values, 'fetched values' );
  297. $searchArrayPartForType[$paramName] = $values;
  298. $valuesFetched = true;
  299. }
  300. else
  301. {
  302. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $varName,
  303. 'post variable does not exist' );
  304. $valuesMissing = true;
  305. break;
  306. }
  307. }
  308. if ( $valuesFetched == true && $valuesMissing == false )
  309. {
  310. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', 'adding values to search' );
  311. $part =& $searchArrayPartForType;
  312. $part['type'] = $searchType['type'];
  313. $part['subtype'] = $searchType['subtype'];
  314. if ( $part['type'] == 'general' )
  315. {
  316. // Remove incomplete search parts from the search.
  317. // An incomplete search part is for instance an empty text field,
  318. // or a select box with no selected values.
  319. $removePart = false;
  320. switch ( $part['subtype'] )
  321. {
  322. case 'class':
  323. {
  324. if ( !isset( $part['value'] ) ||
  325. ( is_array( $part['value'] ) && count( $part['value'] ) == 0 ) ||
  326. ( !is_array( $part['value'] ) && $part['value'] == '' ) )
  327. $removePart = true;
  328. }
  329. break;
  330. case 'publishdate':
  331. {
  332. if ( !isset( $part['value'] ) ||
  333. ( is_array( $part['value'] ) && count( $part['value'] ) == 0 ) ||
  334. ( !is_array( $part['value'] ) && $part['value'] == '' ) )
  335. $removePart = true;
  336. }
  337. break;
  338. case 'subtree':
  339. {
  340. if ( !isset( $part['value'] ) ||
  341. ( is_array( $part['value'] ) && count( $part['value'] ) == 0 ) ||
  342. ( !is_array( $part['value'] ) && $part['value'] == '' ) )
  343. $removePart = true;
  344. }
  345. break;
  346. }
  347. if ( $removePart )
  348. {
  349. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $searchArrayPartForType[$key],
  350. 'removing incomplete search part' );
  351. unSet( $searchArrayPartForType[$key] );
  352. continue;
  353. }
  354. }
  355. $generalFilter = array_merge( $generalFilter, array( $searchArrayPartForType ) );
  356. }
  357. }
  358. if ( $andSearchParts != null )
  359. {
  360. $searchArray['and'] = $andSearchParts;
  361. }
  362. if ( $generalFilter != null )
  363. {
  364. $searchArray['general'] = $generalFilter;
  365. }
  366. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', $searchArray, 'search array' );
  367. return $searchArray;
  368. }
  369. /*!
  370. \static
  371. Tells the current search engine to cleanup up all data.
  372. */
  373. static function cleanup()
  374. {
  375. $searchEngine = eZSearch::getEngine();
  376. if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'cleanup' ) )
  377. {
  378. $searchEngine->cleanup();
  379. }
  380. }
  381. /**
  382. * Get object instance of eZSearch engine to use.
  383. *
  384. * @return \ezpSearchEngine|bool Returns false (+ writes debug) if no engine was found
  385. */
  386. static public function getEngine()
  387. {
  388. // Get instance if already created.
  389. $instanceName = "eZSearchPlugin_" . $GLOBALS["eZCurrentAccess"]["name"];
  390. if ( isset( $GLOBALS[$instanceName] ) )
  391. {
  392. return $GLOBALS[$instanceName];
  393. }
  394. $ini = eZINI::instance();
  395. $searchEngineString = 'ezsearch';
  396. if ( $ini->hasVariable( 'SearchSettings', 'SearchEngine' ) == true )
  397. {
  398. $searchEngineString = $ini->variable( 'SearchSettings', 'SearchEngine' );
  399. }
  400. $directoryList = array();
  401. if ( $ini->hasVariable( 'SearchSettings', 'ExtensionDirectories' ) )
  402. {
  403. $extensionDirectories = $ini->variable( 'SearchSettings', 'ExtensionDirectories' );
  404. if ( is_array( $extensionDirectories ) )
  405. {
  406. $directoryList = eZExtension::expandedPathList( $extensionDirectories, 'search/plugins' );
  407. }
  408. }
  409. $kernelDir = array( 'kernel/search/plugins' );
  410. $directoryList = array_merge( $kernelDir, $directoryList );
  411. foreach( $directoryList as $directory )
  412. {
  413. $searchEngineFile = implode( '/', array( $directory, strtolower( $searchEngineString ), strtolower( $searchEngineString ) ) ) . '.php';
  414. if ( file_exists( $searchEngineFile ) )
  415. {
  416. eZDebugSetting::writeDebug( 'kernel-search-ezsearch', 'Loading search engine from ' . $searchEngineFile, 'eZSearch::getEngine' );
  417. include_once( $searchEngineFile );
  418. $GLOBALS[$instanceName] = new $searchEngineString();
  419. return $GLOBALS[$instanceName];
  420. }
  421. }
  422. eZDebug::writeDebug( 'Unable to find the search engine:' . $searchEngineString, 'eZSearch' );
  423. eZDebug::writeDebug( 'Tried paths: ' . implode( ', ', $directoryList ), 'eZSearch' );
  424. return false;
  425. }
  426. /**
  427. * Notifies search engine about the change of section of a set of objects
  428. *
  429. * @since 4.6
  430. * @param array $objectIDs
  431. * @param int $sectionID
  432. * @return false|mixed false in case method is undefined, otherwise return the result of the search engine call
  433. */
  434. public static function updateObjectsSection( array $objectIDs, $sectionID )
  435. {
  436. $searchEngine = eZSearch::getEngine();
  437. if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'updateObjectsSection' ) )
  438. {
  439. return $searchEngine->updateObjectsSection( $objectIDs, $sectionID );
  440. }
  441. return false;
  442. }
  443. /**
  444. * Notifies search engine about section changes
  445. *
  446. * @since 4.1
  447. * @param int $nodeID
  448. * @param int $sectionID
  449. * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
  450. */
  451. public static function updateNodeSection( $nodeID, $sectionID )
  452. {
  453. $searchEngine = eZSearch::getEngine();
  454. if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'updateNodeSection' ) )
  455. {
  456. return $searchEngine->updateNodeSection( $nodeID, $sectionID );
  457. }
  458. return false;
  459. }
  460. /**
  461. * Notifies search engine about node visibility changes
  462. *
  463. * @since 4.1
  464. * @param int $nodeID
  465. * @param string $action "hide" or "show"
  466. * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
  467. */
  468. public static function updateNodeVisibility( $nodeID, $action )
  469. {
  470. $searchEngine = eZSearch::getEngine();
  471. if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'updateNodeVisibility' ) )
  472. {
  473. return $searchEngine->updateNodeVisibility( $nodeID, $action );
  474. }
  475. return false;
  476. }
  477. /**
  478. * Notifies search engine about new node assignments added
  479. *
  480. * @since 4.1
  481. * @param int $mainNodeID
  482. * @param int $objectID
  483. * @param array $nodeAssignmentIDList
  484. * @param bool $isMoved true if node is being moved
  485. * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
  486. */
  487. public static function addNodeAssignment( $mainNodeID, $objectID, $nodeAssignmentIDList, $isMoved = false )
  488. {
  489. $searchEngine = eZSearch::getEngine();
  490. if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'addNodeAssignment' ) )
  491. {
  492. return $searchEngine->addNodeAssignment( $mainNodeID, $objectID, $nodeAssignmentIDList, $isMoved );
  493. }
  494. return false;
  495. }
  496. /**
  497. * Notifies search engine about removed node assignments and what the new main node is (same if not changed)
  498. *
  499. * @since 4.1
  500. * @param int $mainNodeID
  501. * @param int $newMainNodeID
  502. * @param int $objectID
  503. * @param array $nodeAssigmentIDList
  504. * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
  505. */
  506. public static function removeNodeAssignment( $mainNodeID, $newMainNodeID, $objectID, $nodeAssigmentIDList )
  507. {
  508. $searchEngine = eZSearch::getEngine();
  509. if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'removeNodeAssignment' ) )
  510. {
  511. return $searchEngine->removeNodeAssignment( $mainNodeID, $newMainNodeID, $objectID, $nodeAssigmentIDList );
  512. }
  513. return false;
  514. }
  515. /**
  516. * Notifies search engine about nodes being removed
  517. *
  518. * @since 4.1
  519. * @param array $nodeIdList Array of node ID to remove.
  520. * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
  521. */
  522. public static function removeNodes( array $nodeIdList )
  523. {
  524. $searchEngine = self::getEngine();
  525. if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'removeNodes' ) )
  526. {
  527. return $searchEngine->removeNodes( $nodeIdList );
  528. }
  529. return false;
  530. }
  531. /**
  532. * Notifies search engine about updates to object states
  533. *
  534. * @since 4.1
  535. * @param int $objectID
  536. * @param array $objectStateList
  537. * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
  538. */
  539. public static function updateObjectState( $objectID, $objectStateList )
  540. {
  541. $searchEngine = eZSearch::getEngine();
  542. if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'updateObjectState' ) )
  543. {
  544. return $searchEngine->updateObjectState( $objectID, $objectStateList );
  545. }
  546. return false;
  547. }
  548. /**
  549. * Notifies search engine about an swap node operation
  550. *
  551. * @since 4.1
  552. * @param int $nodeID
  553. * @param int $selectedNodeID
  554. * @param array $nodeIdList
  555. * @return false|mixed False in case method is undefined, otherwise return the result of the search engine call
  556. */
  557. public static function swapNode( $nodeID, $selectedNodeID, $nodeIdList = array() )
  558. {
  559. $searchEngine = eZSearch::getEngine();
  560. if ( $searchEngine instanceof ezpSearchEngine && method_exists( $searchEngine, 'swapNode' ) )
  561. {
  562. return $searchEngine->swapNode( $nodeID, $selectedNodeID, $nodeIdList = array() );
  563. }
  564. return false;
  565. }
  566. }
  567. ?>