server_entity.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. <?php
  2. /**
  3. * @file
  4. * Contains SearchApiServer.
  5. */
  6. /**
  7. * Class representing a search server.
  8. *
  9. * This can handle the same calls as defined in the SearchApiServiceInterface
  10. * and pass it on to the service implementation appropriate for this server.
  11. */
  12. class SearchApiServer extends Entity {
  13. /* Database values that will be set when object is loaded: */
  14. /**
  15. * The primary identifier for a server.
  16. *
  17. * @var integer
  18. */
  19. public $id = 0;
  20. /**
  21. * The displayed name for a server.
  22. *
  23. * @var string
  24. */
  25. public $name = '';
  26. /**
  27. * The machine name for a server.
  28. *
  29. * @var string
  30. */
  31. public $machine_name = '';
  32. /**
  33. * The displayed description for a server.
  34. *
  35. * @var string
  36. */
  37. public $description = '';
  38. /**
  39. * The id of the service class to use for this server.
  40. *
  41. * @var string
  42. */
  43. public $class = '';
  44. /**
  45. * The options used to configure the service object.
  46. *
  47. * @var array
  48. */
  49. public $options = array();
  50. /**
  51. * A flag indicating whether the server is enabled.
  52. *
  53. * @var integer
  54. */
  55. public $enabled = 1;
  56. /**
  57. * Proxy object for invoking service methods.
  58. *
  59. * @var SearchApiServiceInterface
  60. */
  61. protected $proxy;
  62. /**
  63. * Constructor as a helper to the parent constructor.
  64. */
  65. public function __construct(array $values = array(), $entity_type = 'search_api_server') {
  66. parent::__construct($values, $entity_type);
  67. }
  68. /**
  69. * Helper method for updating entity properties.
  70. *
  71. * NOTE: You shouldn't change any properties of this object before calling
  72. * this method, as this might lead to the fields not being saved correctly.
  73. *
  74. * @param array $fields
  75. * The new field values.
  76. *
  77. * @return int|false
  78. * SAVE_UPDATED on success, FALSE on failure, 0 if the fields already had
  79. * the specified values.
  80. */
  81. public function update(array $fields) {
  82. $changeable = array('name' => 1, 'enabled' => 1, 'description' => 1, 'options' => 1);
  83. $changed = FALSE;
  84. foreach ($fields as $field => $value) {
  85. if (isset($changeable[$field]) && $value !== $this->$field) {
  86. $this->$field = $value;
  87. $changed = TRUE;
  88. }
  89. }
  90. // If there are no new values, just return 0.
  91. if (!$changed) {
  92. return 0;
  93. }
  94. return $this->save();
  95. }
  96. /**
  97. * Magic method for determining which fields should be serialized.
  98. *
  99. * Serialize all properties except the proxy object.
  100. *
  101. * @return array
  102. * An array of properties to be serialized.
  103. */
  104. public function __sleep() {
  105. $ret = get_object_vars($this);
  106. unset($ret['proxy'], $ret['status'], $ret['module'], $ret['is_new']);
  107. return array_keys($ret);
  108. }
  109. /**
  110. * Helper method for ensuring the proxy object is set up.
  111. */
  112. protected function ensureProxy() {
  113. if (!isset($this->proxy)) {
  114. $class = search_api_get_service_info($this->class);
  115. if ($class && class_exists($class['class'])) {
  116. if (empty($this->options)) {
  117. // We always have to provide the options.
  118. $this->options = array();
  119. }
  120. $this->proxy = new $class['class']($this);
  121. }
  122. if (!($this->proxy instanceof SearchApiServiceInterface)) {
  123. throw new SearchApiException(t('Search server with machine name @name specifies illegal service class @class.', array('@name' => $this->machine_name, '@class' => $this->class)));
  124. }
  125. }
  126. }
  127. /**
  128. * Reacts to calls of undefined methods on this object.
  129. *
  130. * If the service class defines additional methods, not specified in the
  131. * SearchApiServiceInterface interface, then they are called via this magic
  132. * method.
  133. */
  134. public function __call($name, $arguments = array()) {
  135. $this->ensureProxy();
  136. return call_user_func_array(array($this->proxy, $name), $arguments);
  137. }
  138. // Proxy methods
  139. // For increased clarity, and since some parameters are passed by reference,
  140. // we don't use the __call() magic method for those. This also gives us the
  141. // opportunity to do additional error handling.
  142. /**
  143. * Form constructor for the server configuration form.
  144. *
  145. * @see SearchApiServiceInterface::configurationForm()
  146. */
  147. public function configurationForm(array $form, array &$form_state) {
  148. $this->ensureProxy();
  149. return $this->proxy->configurationForm($form, $form_state);
  150. }
  151. /**
  152. * Validation callback for the form returned by configurationForm().
  153. *
  154. * @see SearchApiServiceInterface::configurationFormValidate()
  155. */
  156. public function configurationFormValidate(array $form, array &$values, array &$form_state) {
  157. $this->ensureProxy();
  158. return $this->proxy->configurationFormValidate($form, $values, $form_state);
  159. }
  160. /**
  161. * Submit callback for the form returned by configurationForm().
  162. *
  163. * @see SearchApiServiceInterface::configurationFormSubmit()
  164. */
  165. public function configurationFormSubmit(array $form, array &$values, array &$form_state) {
  166. $this->ensureProxy();
  167. return $this->proxy->configurationFormSubmit($form, $values, $form_state);
  168. }
  169. /**
  170. * Determines whether this service class supports a given feature.
  171. *
  172. * @see SearchApiServiceInterface::supportsFeature()
  173. */
  174. public function supportsFeature($feature) {
  175. $this->ensureProxy();
  176. return $this->proxy->supportsFeature($feature);
  177. }
  178. /**
  179. * Displays this server's settings.
  180. *
  181. * @see SearchApiServiceInterface::viewSettings()
  182. */
  183. public function viewSettings() {
  184. $this->ensureProxy();
  185. return $this->proxy->viewSettings();
  186. }
  187. /**
  188. * Reacts to the server's creation.
  189. *
  190. * @see SearchApiServiceInterface::postCreate()
  191. */
  192. public function postCreate() {
  193. $this->ensureProxy();
  194. return $this->proxy->postCreate();
  195. }
  196. /**
  197. * Notifies this server that its fields are about to be updated.
  198. *
  199. * @see SearchApiServiceInterface::postUpdate()
  200. */
  201. public function postUpdate() {
  202. $this->ensureProxy();
  203. return $this->proxy->postUpdate();
  204. }
  205. /**
  206. * Notifies this server that it is about to be deleted from the database.
  207. *
  208. * @see SearchApiServiceInterface::preDelete()
  209. */
  210. public function preDelete() {
  211. $this->ensureProxy();
  212. return $this->proxy->preDelete();
  213. }
  214. /**
  215. * Adds a new index to this server.
  216. *
  217. * If an exception in the service class implementation of this method occurs,
  218. * it will be caught and the operation saved as an pending server task.
  219. *
  220. * @see SearchApiServiceInterface::addIndex()
  221. * @see search_api_server_tasks_add()
  222. */
  223. public function addIndex(SearchApiIndex $index) {
  224. $this->ensureProxy();
  225. try {
  226. $this->proxy->addIndex($index);
  227. }
  228. catch (SearchApiException $e) {
  229. $vars = array(
  230. '%server' => $this->name,
  231. '%index' => $index->name,
  232. );
  233. watchdog_exception('search_api', $e, '%type while adding index %index to server %server: !message in %function (line %line of %file).', $vars);
  234. search_api_server_tasks_add($this, __FUNCTION__, $index);
  235. }
  236. }
  237. /**
  238. * Notifies the server that the field settings for the index have changed.
  239. *
  240. * If the service class implementation of the method returns TRUE, this will
  241. * automatically take care of marking the items on the index for re-indexing.
  242. *
  243. * If an exception in the service class implementation of this method occurs,
  244. * it will be caught and the operation saved as an pending server task.
  245. *
  246. * @see SearchApiServiceInterface::fieldsUpdated()
  247. * @see search_api_server_tasks_add()
  248. */
  249. public function fieldsUpdated(SearchApiIndex $index) {
  250. $this->ensureProxy();
  251. try {
  252. if ($this->proxy->fieldsUpdated($index)) {
  253. _search_api_index_reindex($index);
  254. return TRUE;
  255. }
  256. }
  257. catch (SearchApiException $e) {
  258. $vars = array(
  259. '%server' => $this->name,
  260. '%index' => $index->name,
  261. );
  262. watchdog_exception('search_api', $e, '%type while updating the fields of index %index on server %server: !message in %function (line %line of %file).', $vars);
  263. search_api_server_tasks_add($this, __FUNCTION__, $index, isset($index->original) ? $index->original : NULL);
  264. }
  265. return FALSE;
  266. }
  267. /**
  268. * Removes an index from this server.
  269. *
  270. * If an exception in the service class implementation of this method occurs,
  271. * it will be caught and the operation saved as an pending server task.
  272. *
  273. * @see SearchApiServiceInterface::removeIndex()
  274. * @see search_api_server_tasks_add()
  275. */
  276. public function removeIndex($index) {
  277. // When removing an index from a server, it doesn't make any sense anymore to
  278. // delete items from it, or react to other changes.
  279. search_api_server_tasks_delete(NULL, $this, $index);
  280. $this->ensureProxy();
  281. try {
  282. $this->proxy->removeIndex($index);
  283. }
  284. catch (SearchApiException $e) {
  285. $vars = array(
  286. '%server' => $this->name,
  287. '%index' => is_object($index) ? $index->name : $index,
  288. );
  289. watchdog_exception('search_api', $e, '%type while removing index %index from server %server: !message in %function (line %line of %file).', $vars);
  290. search_api_server_tasks_add($this, __FUNCTION__, $index);
  291. }
  292. }
  293. /**
  294. * Indexes the specified items.
  295. *
  296. * @see SearchApiServiceInterface::indexItems()
  297. */
  298. public function indexItems(SearchApiIndex $index, array $items) {
  299. $this->ensureProxy();
  300. return $this->proxy->indexItems($index, $items);
  301. }
  302. /**
  303. * Deletes indexed items from this server.
  304. *
  305. * If an exception in the service class implementation of this method occurs,
  306. * it will be caught and the operation saved as an pending server task.
  307. *
  308. * @see SearchApiServiceInterface::deleteItems()
  309. * @see search_api_server_tasks_add()
  310. */
  311. public function deleteItems($ids = 'all', SearchApiIndex $index = NULL) {
  312. $this->ensureProxy();
  313. try {
  314. $this->proxy->deleteItems($ids, $index);
  315. }
  316. catch (SearchApiException $e) {
  317. $vars = array(
  318. '%server' => $this->name,
  319. );
  320. watchdog_exception('search_api', $e, '%type while deleting items from server %server: !message in %function (line %line of %file).', $vars);
  321. search_api_server_tasks_add($this, __FUNCTION__, $index, $ids);
  322. }
  323. }
  324. /**
  325. * Creates a query object for searching on an index lying on this server.
  326. *
  327. * @see SearchApiServiceInterface::query()
  328. */
  329. public function query(SearchApiIndex $index, $options = array()) {
  330. $this->ensureProxy();
  331. return $this->proxy->query($index, $options);
  332. }
  333. /**
  334. * Executes a search on the server represented by this object.
  335. *
  336. * @see SearchApiServiceInterface::search()
  337. */
  338. public function search(SearchApiQueryInterface $query) {
  339. $this->ensureProxy();
  340. return $this->proxy->search($query);
  341. }
  342. /**
  343. * Retrieves additional information for the server, if available.
  344. *
  345. * Retrieving such information is only supported if the service class supports
  346. * the "search_api_service_extra" feature.
  347. *
  348. * @return array
  349. * An array containing additional, service class-specific information about
  350. * the server.
  351. *
  352. * @see SearchApiAbstractService::getExtraInformation()
  353. */
  354. public function getExtraInformation() {
  355. if ($this->proxy->supportsFeature('search_api_service_extra')) {
  356. return $this->proxy->getExtraInformation();
  357. }
  358. return array();
  359. }
  360. }