search_api.install 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. <?php
  2. /**
  3. * @file
  4. * Install, update and uninstall functions for the Search API module.
  5. */
  6. /**
  7. * Implements hook_schema().
  8. */
  9. function search_api_schema() {
  10. $schema['search_api_server'] = array(
  11. 'description' => 'Stores all search servers created through the Search API.',
  12. 'fields' => array(
  13. 'id' => array(
  14. 'description' => 'The primary identifier for a server.',
  15. 'type' => 'serial',
  16. 'unsigned' => TRUE,
  17. 'not null' => TRUE,
  18. ),
  19. 'name' => array(
  20. 'description' => 'The displayed name for a server.',
  21. 'type' => 'varchar',
  22. 'length' => 50,
  23. 'not null' => TRUE,
  24. ),
  25. 'machine_name' => array(
  26. 'description' => 'The machine name for a server.',
  27. 'type' => 'varchar',
  28. 'length' => 50,
  29. 'not null' => TRUE,
  30. ),
  31. 'description' => array(
  32. 'description' => 'The displayed description for a server.',
  33. 'type' => 'text',
  34. 'not null' => FALSE,
  35. ),
  36. 'class' => array(
  37. 'description' => 'The id of the service class to use for this server.',
  38. 'type' => 'varchar',
  39. 'length' => 50,
  40. 'not null' => TRUE,
  41. ),
  42. 'options' => array(
  43. 'description' => 'The options used to configure the service object.',
  44. 'type' => 'text',
  45. 'size' => 'medium',
  46. 'serialize' => TRUE,
  47. 'not null' => TRUE,
  48. ),
  49. 'enabled' => array(
  50. 'description' => 'A flag indicating whether the server is enabled.',
  51. 'type' => 'int',
  52. 'size' => 'tiny',
  53. 'not null' => TRUE,
  54. 'default' => 1,
  55. ),
  56. 'status' => array(
  57. 'description' => 'The exportable status of the entity.',
  58. 'type' => 'int',
  59. 'not null' => TRUE,
  60. 'default' => 0x01,
  61. 'size' => 'tiny',
  62. ),
  63. 'module' => array(
  64. 'description' => 'The name of the providing module if the entity has been defined in code.',
  65. 'type' => 'varchar',
  66. 'length' => 255,
  67. 'not null' => FALSE,
  68. ),
  69. ),
  70. 'indexes' => array(
  71. 'enabled' => array('enabled'),
  72. ),
  73. 'unique keys' => array(
  74. 'machine_name' => array('machine_name'),
  75. ),
  76. 'primary key' => array('id'),
  77. );
  78. $schema['search_api_index'] = array(
  79. 'description' => 'Stores all search indexes on a {search_api_server}.',
  80. 'fields' => array(
  81. 'id' => array(
  82. 'description' => 'An integer identifying the index.',
  83. 'type' => 'serial',
  84. 'unsigned' => TRUE,
  85. 'not null' => TRUE,
  86. ),
  87. 'name' => array(
  88. 'description' => 'A name to be displayed for the index.',
  89. 'type' => 'varchar',
  90. 'length' => 50,
  91. 'not null' => TRUE,
  92. ),
  93. 'machine_name' => array(
  94. 'description' => 'The machine name of the index.',
  95. 'type' => 'varchar',
  96. 'length' => 50,
  97. 'not null' => TRUE,
  98. ),
  99. 'description' => array(
  100. 'description' => "A string describing the index' use to users.",
  101. 'type' => 'text',
  102. 'not null' => FALSE,
  103. ),
  104. 'server' => array(
  105. 'description' => 'The {search_api_server}.machine_name with which data should be indexed.',
  106. 'type' => 'varchar',
  107. 'length' => 50,
  108. 'not null' => FALSE,
  109. ),
  110. 'item_type' => array(
  111. 'description' => 'The type of items stored in this index.',
  112. 'type' => 'varchar',
  113. 'length' => 50,
  114. 'not null' => TRUE,
  115. ),
  116. 'options' => array(
  117. 'description' => 'An array of additional arguments configuring this index.',
  118. 'type' => 'text',
  119. 'size' => 'medium',
  120. 'serialize' => TRUE,
  121. 'not null' => TRUE,
  122. ),
  123. 'enabled' => array(
  124. 'description' => 'A flag indicating whether this index is enabled.',
  125. 'type' => 'int',
  126. 'size' => 'tiny',
  127. 'not null' => TRUE,
  128. 'default' => 1,
  129. ),
  130. 'read_only' => array(
  131. 'description' => 'A flag indicating whether to write to this index.',
  132. 'type' => 'int',
  133. 'size' => 'tiny',
  134. 'not null' => TRUE,
  135. 'default' => 0,
  136. ),
  137. 'status' => array(
  138. 'description' => 'The exportable status of the entity.',
  139. 'type' => 'int',
  140. 'not null' => TRUE,
  141. 'default' => 0x01,
  142. 'size' => 'tiny',
  143. ),
  144. 'module' => array(
  145. 'description' => 'The name of the providing module if the entity has been defined in code.',
  146. 'type' => 'varchar',
  147. 'length' => 255,
  148. 'not null' => FALSE,
  149. ),
  150. ),
  151. 'indexes' => array(
  152. 'item_type' => array('item_type'),
  153. 'server' => array('server'),
  154. 'enabled' => array('enabled'),
  155. ),
  156. 'unique keys' => array(
  157. 'machine_name' => array('machine_name'),
  158. ),
  159. 'primary key' => array('id'),
  160. );
  161. $schema['search_api_item'] = array(
  162. 'description' => 'Stores the items which should be indexed for each index, and their status.',
  163. 'fields' => array(
  164. 'item_id' => array(
  165. 'description' => "The item's entity id (e.g. {node}.nid for nodes).",
  166. 'type' => 'int',
  167. 'unsigned' => TRUE,
  168. 'not null' => TRUE,
  169. ),
  170. 'index_id' => array(
  171. 'description' => 'The {search_api_index}.id this item belongs to.',
  172. 'type' => 'int',
  173. 'unsigned' => TRUE,
  174. 'not null' => TRUE,
  175. ),
  176. 'changed' => array(
  177. 'description' => 'Either a flag or a timestamp to indicate if or when the item was changed since it was last indexed.',
  178. 'type' => 'int',
  179. 'size' => 'big',
  180. 'not null' => TRUE,
  181. 'default' => 1,
  182. ),
  183. ),
  184. 'indexes' => array(
  185. 'indexing' => array('index_id', 'changed'),
  186. ),
  187. 'primary key' => array('item_id', 'index_id'),
  188. );
  189. return $schema;
  190. }
  191. /**
  192. * Implements hook_install().
  193. *
  194. * Creates a default node index if the module is installed manually.
  195. */
  196. function search_api_install() {
  197. // In case the module is installed via an installation profile, a batch is
  198. // active and we skip that.
  199. if (batch_get()) {
  200. return;
  201. }
  202. $name = t('Default node index');
  203. $values = array(
  204. 'name' => $name,
  205. 'machine_name' => preg_replace('/[^a-z0-9]+/', '_', drupal_strtolower($name)),
  206. 'description' => t('An automatically created search index for indexing node data. Might be configured to specific needs.'),
  207. 'server' => NULL,
  208. 'item_type' => 'node',
  209. 'options' => array(
  210. 'cron_limit' => '50',
  211. 'data_alter_callbacks' => array(
  212. 'search_api_alter_node_access' => array(
  213. 'status' => 1,
  214. 'weight' => '0',
  215. 'settings' => array(),
  216. ),
  217. ),
  218. 'processors' => array(
  219. 'search_api_case_ignore' => array(
  220. 'status' => 1,
  221. 'weight' => '0',
  222. 'settings' => array(
  223. 'strings' => 0,
  224. ),
  225. ),
  226. 'search_api_html_filter' => array(
  227. 'status' => 1,
  228. 'weight' => '10',
  229. 'settings' => array(
  230. 'title' => 0,
  231. 'alt' => 1,
  232. 'tags' => "h1 = 5\n" .
  233. "h2 = 3\n" .
  234. "h3 = 2\n" .
  235. "strong = 2\n" .
  236. "b = 2\n" .
  237. "em = 1.5\n" .
  238. "u = 1.5",
  239. ),
  240. ),
  241. 'search_api_tokenizer' => array(
  242. 'status' => 1,
  243. 'weight' => '20',
  244. 'settings' => array(
  245. 'spaces' => '[^\\p{L}\\p{N}]',
  246. 'ignorable' => '[-]',
  247. ),
  248. ),
  249. ),
  250. 'fields' => array(
  251. 'type' => array(
  252. 'type' => 'string',
  253. ),
  254. 'title' => array(
  255. 'type' => 'text',
  256. 'boost' => '5.0',
  257. ),
  258. 'promote' => array(
  259. 'type' => 'boolean',
  260. ),
  261. 'sticky' => array(
  262. 'type' => 'boolean',
  263. ),
  264. 'created' => array(
  265. 'type' => 'date',
  266. ),
  267. 'changed' => array(
  268. 'type' => 'date',
  269. ),
  270. 'author' => array(
  271. 'type' => 'integer',
  272. 'entity_type' => 'user',
  273. ),
  274. 'comment_count' => array(
  275. 'type' => 'integer',
  276. ),
  277. 'search_api_language' => array(
  278. 'type' => 'string',
  279. ),
  280. 'body:value' => array(
  281. 'type' => 'text',
  282. ),
  283. ),
  284. ),
  285. );
  286. search_api_index_insert($values);
  287. drupal_set_message('The Search API module was installed. A new default node index was created.');
  288. }
  289. /**
  290. * Implements hook_enable().
  291. *
  292. * Mark all items as "dirty", since we can't know whether they are.
  293. */
  294. function search_api_enable() {
  295. $types = array();
  296. foreach (search_api_index_load_multiple(FALSE) as $index) {
  297. if ($index->enabled) {
  298. $types[$index->item_type][] = $index;
  299. }
  300. }
  301. foreach ($types as $type => $indexes) {
  302. $controller = search_api_get_datasource_controller($type);
  303. $controller->startTracking($indexes);
  304. }
  305. }
  306. /**
  307. * Implements hook_disable().
  308. */
  309. function search_api_disable() {
  310. $types = array();
  311. foreach (search_api_index_load_multiple(FALSE) as $index) {
  312. $types[$index->item_type][] = $index;
  313. }
  314. foreach ($types as $type => $indexes) {
  315. $controller = search_api_get_datasource_controller($type);
  316. $controller->stopTracking($indexes);
  317. }
  318. }
  319. /**
  320. * Implements hook_uninstall().
  321. */
  322. function search_api_uninstall() {
  323. variable_del('search_api_tasks');
  324. variable_del('search_api_index_worker_callback_runtime');
  325. }
  326. /**
  327. * Update function that adds the machine names for servers and indexes.
  328. */
  329. function search_api_update_7101() {
  330. $tx = db_transaction();
  331. try {
  332. // Servers
  333. $spec = array(
  334. 'description' => 'The machine name for a server.',
  335. 'type' => 'varchar',
  336. 'length' => 50,
  337. 'not null' => TRUE,
  338. 'default' => '',
  339. );
  340. db_add_field('search_api_server', 'machine_name', $spec);
  341. $names = array();
  342. $servers = db_select('search_api_server', 's')
  343. ->fields('s')
  344. ->execute();
  345. foreach ($servers as $server) {
  346. $base = $name = drupal_strtolower(preg_replace('/[^a-z0-9]+/i', '_', $server->name));
  347. $i = 0;
  348. while (isset($names[$name])) {
  349. $name = $base . '_' . ++$i;
  350. }
  351. $names[$name] = TRUE;
  352. db_update('search_api_server')
  353. ->fields(array('machine_name' => $name))
  354. ->condition('id', $server->id)
  355. ->execute();
  356. }
  357. db_add_unique_key('search_api_server', 'machine_name', array('machine_name'));
  358. //Indexes
  359. $spec = array(
  360. 'description' => 'The machine name of the index.',
  361. 'type' => 'varchar',
  362. 'length' => 50,
  363. 'not null' => TRUE,
  364. 'default' => '',
  365. );
  366. db_add_field('search_api_index', 'machine_name', $spec);
  367. $names = array();
  368. $indexes = db_select('search_api_index', 'i')
  369. ->fields('i')
  370. ->execute();
  371. foreach ($indexes as $index) {
  372. $base = $name = drupal_strtolower(preg_replace('/[^a-z0-9]+/i', '_', $index->name));
  373. $i = 0;
  374. while (isset($names[$name])) {
  375. $name = $base . '_' . ++$i;
  376. }
  377. $names[$name] = TRUE;
  378. db_update('search_api_index')
  379. ->fields(array('machine_name' => $name))
  380. ->condition('id', $index->id)
  381. ->execute();
  382. }
  383. db_add_unique_key('search_api_index', 'machine_name', array('machine_name'));
  384. }
  385. catch (Exception $e) {
  386. $tx->rollback();
  387. try {
  388. db_drop_field('search_api_server', 'machine_name');
  389. db_drop_field('search_api_index', 'machine_name');
  390. }
  391. catch (Exception $e1) {
  392. // Ignore.
  393. }
  394. throw new DrupalUpdateException(t('An exception occurred during the update: @msg.', array('@msg' => $e->getMessage())));
  395. }
  396. }
  397. /**
  398. * Update replacing IDs with machine names for foreign keys.
  399. * {search_api_index}.server and {search_api_item}.index_id are altered.
  400. */
  401. function search_api_update_7102() {
  402. // Update of search_api_index:
  403. $indexes = array();
  404. $select = db_select('search_api_index', 'i')->fields('i');
  405. foreach ($select->execute() as $index) {
  406. $indexes[$index->id] = $index;
  407. }
  408. $servers = db_select('search_api_server', 's')->fields('s', array('id', 'machine_name'))->execute()->fetchAllKeyed();
  409. db_drop_index('search_api_index', 'server');
  410. db_drop_field('search_api_index', 'server');
  411. $spec = array(
  412. 'description' => 'The {search_api_server}.machine_name with which data should be indexed.',
  413. 'type' => 'varchar',
  414. 'length' => 50,
  415. 'not null' => FALSE,
  416. );
  417. db_add_field('search_api_index', 'server', $spec);
  418. foreach ($indexes as $index) {
  419. db_update('search_api_index')
  420. ->fields(array('server' => $servers[$index->server]))
  421. ->condition('id', $index->id)
  422. ->execute();
  423. }
  424. db_add_index('search_api_index', 'server', array('server'));
  425. // Update of search_api_item:
  426. db_drop_index('search_api_item', 'indexing');
  427. db_drop_primary_key('search_api_item');
  428. $spec = array(
  429. 'description' => 'The {search_api_index}.machine_name this item belongs to.',
  430. 'type' => 'varchar',
  431. 'length' => 50,
  432. 'not null' => TRUE,
  433. );
  434. $keys_new = array(
  435. 'indexes' => array(
  436. 'indexing' => array('index_id', 'changed'),
  437. ),
  438. 'primary key' => array('item_id', 'index_id'),
  439. );
  440. db_change_field('search_api_item', 'index_id', 'index_id', $spec, $keys_new);
  441. foreach ($indexes as $index) {
  442. // We explicitly forbid numeric machine names, therefore we don't have to
  443. // worry about conflicts here.
  444. db_update('search_api_item')
  445. ->fields(array(
  446. 'index_id' => $index->machine_name,
  447. ))
  448. ->condition('index_id', $index->id)
  449. ->execute();
  450. }
  451. }
  452. /**
  453. * Add the database fields newly required for entities by the Entity API.
  454. */
  455. function search_api_update_7103() {
  456. if (!function_exists('entity_exportable_schema_fields')) {
  457. throw new DrupalUpdateException(t('Please update the Entity API module first.'));
  458. }
  459. foreach (array('search_api_server', 'search_api_index') as $table) {
  460. foreach (entity_exportable_schema_fields() as $field => $spec) {
  461. db_add_field($table, $field, $spec);
  462. }
  463. }
  464. }
  465. /**
  466. * Initialize the "Fields to run on" settings for processors.
  467. */
  468. function search_api_update_7107() {
  469. $rows = db_select('search_api_index', 'i')
  470. ->fields('i', array('id', 'options'))
  471. ->execute()
  472. ->fetchAllKeyed();
  473. foreach ($rows as $id => $options) {
  474. $opt = unserialize($options);
  475. $processors = &$opt['processors'];
  476. // Only update our own processors, don't mess with others.
  477. $check_processors = array(
  478. 'search_api_case_ignore' => 1,
  479. 'search_api_html_filter' => 1,
  480. 'search_api_tokenizer' => 1,
  481. );
  482. foreach (array_intersect_key($processors, $check_processors) as $name => $info) {
  483. $types = array('text');
  484. if (!empty($info['settings']['strings'])) {
  485. $types[] = 'string';
  486. unset($processors[$name]['settings']['strings']);
  487. }
  488. foreach ($opt['fields'] as $field => $info) {
  489. if ($info['indexed'] && search_api_is_text_type($info['type'], $types)) {
  490. $processors[$name]['settings']['fields'][$field] = $field;
  491. }
  492. }
  493. }
  494. $opt = serialize($opt);
  495. if ($opt != $options) {
  496. db_update('search_api_index')
  497. ->fields(array(
  498. 'options' => $opt,
  499. ))
  500. ->condition('id', $id)
  501. ->execute();
  502. }
  503. }
  504. }
  505. /**
  506. * Change {search_api_item}.index_id back to the index' numeric ID.
  507. */
  508. function search_api_update_7104() {
  509. $select = db_select('search_api_index', 'i')->fields('i');
  510. foreach ($select->execute() as $index) {
  511. // We explicitly forbid numeric machine names, therefore we don't have to
  512. // worry about conflicts here.
  513. db_update('search_api_item')
  514. ->fields(array(
  515. 'index_id' => $index->id,
  516. ))
  517. ->condition('index_id', $index->machine_name)
  518. ->execute();
  519. }
  520. // Update primary key and index.
  521. db_drop_index('search_api_item', 'indexing');
  522. db_drop_primary_key('search_api_item');
  523. $spec = array(
  524. 'description' => 'The {search_api_index}.id this item belongs to.',
  525. 'type' => 'int',
  526. 'unsigned' => TRUE,
  527. 'not null' => TRUE,
  528. );
  529. $keys_new = array(
  530. 'indexes' => array(
  531. 'indexing' => array('index_id', 'changed'),
  532. ),
  533. 'primary key' => array('item_id', 'index_id'),
  534. );
  535. db_change_field('search_api_item', 'index_id', 'index_id', $spec, $keys_new);
  536. }
  537. /**
  538. * Remove all empty aggregated fields for the search_api_alter_add_fulltext data
  539. * alterations.
  540. */
  541. function search_api_update_7105() {
  542. $rows = db_select('search_api_index', 'i')
  543. ->fields('i', array('id', 'options'))
  544. ->execute()
  545. ->fetchAllKeyed();
  546. foreach ($rows as $id => $options) {
  547. $opt = unserialize($options);
  548. if (isset($opt['data_alter_callbacks']['search_api_alter_add_fulltext']['settings']['fields'])) {
  549. foreach ($opt['data_alter_callbacks']['search_api_alter_add_fulltext']['settings']['fields'] as $name => $field) {
  550. if (empty($field['name']) || empty($field['fields'])) {
  551. unset($opt['data_alter_callbacks']['search_api_alter_add_fulltext']['settings']['fields'][$name]);
  552. }
  553. }
  554. }
  555. $opt = serialize($opt);
  556. if ($opt != $options) {
  557. db_update('search_api_index')
  558. ->fields(array(
  559. 'options' => $opt,
  560. ))
  561. ->condition('id', $id)
  562. ->execute();
  563. }
  564. }
  565. }
  566. /**
  567. * Update the settings for the "Aggregated fields" data alteration.
  568. */
  569. function search_api_update_7106() {
  570. $rows = db_select('search_api_index', 'i')
  571. ->fields('i')
  572. ->execute()
  573. ->fetchAll();
  574. foreach ($rows as $row) {
  575. $opt = unserialize($row->options);
  576. $callbacks = &$opt['data_alter_callbacks'];
  577. if (isset($callbacks['search_api_alter_add_fulltext'])) {
  578. $callbacks['search_api_alter_add_aggregation'] = $callbacks['search_api_alter_add_fulltext'];
  579. unset($callbacks['search_api_alter_add_fulltext']);
  580. if (!empty($callbacks['search_api_alter_add_aggregation']['settings']['fields'])) {
  581. foreach ($callbacks['search_api_alter_add_aggregation']['settings']['fields'] as $field => &$info) {
  582. if (!isset($info['type'])) {
  583. $info['type'] = 'fulltext';
  584. }
  585. }
  586. }
  587. }
  588. $opt = serialize($opt);
  589. if ($opt != $row->options) {
  590. // Mark the entity as overridden, in case it has been defined in code
  591. // only.
  592. $row->status |= 0x01;
  593. db_update('search_api_index')
  594. ->fields(array(
  595. 'options' => $opt,
  596. 'status' => $row->status,
  597. ))
  598. ->condition('id', $row->id)
  599. ->execute();
  600. }
  601. }
  602. }
  603. /**
  604. * Add "read only" property to Search API index entities.
  605. */
  606. function search_api_update_7108() {
  607. $db_field = array(
  608. 'description' => 'A flag indicating whether to write to this index.',
  609. 'type' => 'int',
  610. 'size' => 'tiny',
  611. 'not null' => TRUE,
  612. 'default' => 0,
  613. );
  614. db_add_field('search_api_index', 'read_only', $db_field);
  615. return t('Added a "read only" property to index entities.');
  616. }
  617. /**
  618. * Clear entity info cache, as entity controller classes hae changed.
  619. */
  620. function search_api_update_7109() {
  621. cache_clear_all('entity_info:', 'cache', TRUE);
  622. }
  623. /**
  624. * Rename the "entity_type" field to "item_type" in the {search_api_index} table.
  625. */
  626. function search_api_update_7110() {
  627. $table = 'search_api_index';
  628. // This index isn't used anymore.
  629. db_drop_index($table, 'entity_type');
  630. // Rename the "item_type" field (and change the description).
  631. $item_type = array(
  632. 'description' => 'The type of items stored in this index.',
  633. 'type' => 'varchar',
  634. 'length' => 50,
  635. 'not null' => TRUE,
  636. );
  637. // Also add the new "item_type" index, while we're at it.
  638. $keys_new['indexes']['item_type'] = array('item_type');
  639. db_change_field($table, 'entity_type', 'item_type', $item_type, $keys_new);
  640. // Mark all indexes in code as "OVERRIDDEN".
  641. db_update($table)
  642. ->fields(array(
  643. 'status' => 0x03,
  644. ))
  645. ->condition('status', 0x02)
  646. ->execute();
  647. // Clear entity info caches.
  648. cache_clear_all('*', 'cache', TRUE);
  649. }
  650. /**
  651. * Change the definition of the {search_api_item}.changed field.
  652. */
  653. function search_api_update_7111() {
  654. $spec = array(
  655. 'description' => 'Either a flag or a timestamp to indicate if or when the item was changed since it was last indexed.',
  656. 'type' => 'int',
  657. 'size' => 'big',
  658. 'not null' => TRUE,
  659. 'default' => 1,
  660. );
  661. db_change_field('search_api_item', 'changed', 'changed', $spec);
  662. }
  663. /**
  664. * Changes the size of the {search_api_index}.options and {search_api_server}.options fields to "medium".
  665. */
  666. function search_api_update_7112() {
  667. $spec = array(
  668. 'description' => 'The options used to configure the service object.',
  669. 'type' => 'text',
  670. 'size' => 'medium',
  671. 'serialize' => TRUE,
  672. 'not null' => TRUE,
  673. );
  674. db_change_field('search_api_server', 'options', 'options', $spec);
  675. $spec = array(
  676. 'description' => 'An array of additional arguments configuring this index.',
  677. 'type' => 'text',
  678. 'size' => 'medium',
  679. 'serialize' => TRUE,
  680. 'not null' => TRUE,
  681. );
  682. db_change_field('search_api_index', 'options', 'options', $spec);
  683. }
  684. /**
  685. * Removes superfluous data from the stored index options.
  686. */
  687. function search_api_update_7113() {
  688. $indexes = db_select('search_api_index', 'i')
  689. ->fields('i')
  690. ->execute();
  691. foreach ($indexes as $index) {
  692. $options = unserialize($index->options);
  693. // Weed out fields settings.
  694. if (!empty($options['fields'])) {
  695. foreach ($options['fields'] as $key => $field) {
  696. if (isset($field['indexed']) && !$field['indexed']) {
  697. unset($options['fields'][$key]);
  698. continue;
  699. }
  700. unset($options['fields'][$key]['name'], $options['fields'][$key]['indexed']);
  701. if (isset($field['boost']) && $field['boost'] == '1.0') {
  702. unset($options['fields'][$key]['boost']);
  703. }
  704. }
  705. }
  706. // Weed out processor settings.
  707. if (!empty($options['processors'])) {
  708. // Only weed out settings for our own processors.
  709. $processors = array('search_api_case_ignore', 'search_api_html_filter', 'search_api_tokenizer', 'search_api_stopwords');
  710. foreach ($processors as $key) {
  711. if (empty($options['processors'][$key])) {
  712. continue;
  713. }
  714. $processor = $options['processors'][$key];
  715. if (empty($processor['settings']['fields'])) {
  716. continue;
  717. }
  718. $fields = array_filter($processor['settings']['fields']);
  719. if ($fields) {
  720. $fields = array_combine($fields, array_fill(0, count($fields), TRUE));
  721. }
  722. $options['processors'][$key]['settings']['fields'] = $fields;
  723. }
  724. }
  725. // Weed out settings for the „Aggregated fields“ data alteration.
  726. if (!empty($options['data_alter_callbacks']['search_api_alter_add_aggregation']['settings']['fields'])) {
  727. unset($options['data_alter_callbacks']['search_api_alter_add_aggregation']['settings']['actions']);
  728. $aggregated_fields = &$options['data_alter_callbacks']['search_api_alter_add_aggregation']['settings']['fields'];
  729. foreach ($aggregated_fields as $key => $field) {
  730. unset($aggregated_fields[$key]['actions']);
  731. if (!empty($field['fields'])) {
  732. $aggregated_fields[$key]['fields'] = array_values(array_filter($field['fields']));
  733. }
  734. }
  735. }
  736. $options = serialize($options);
  737. if ($options != $index->options) {
  738. // Mark the entity as overridden, in case it has been defined in code
  739. // only.
  740. $index->status |= 0x01;
  741. db_update('search_api_index')
  742. ->fields(array(
  743. 'options' => $options,
  744. 'status' => $index->status,
  745. ))
  746. ->condition('id', $index->id)
  747. ->execute();
  748. }
  749. }
  750. }
  751. /**
  752. * Sanitize watchdog messages.
  753. */
  754. function search_api_update_7114() {
  755. if (db_table_exists('watchdog')) {
  756. try {
  757. $entries = db_select('watchdog', 'w')
  758. ->fields('w', array('wid', 'message'))
  759. ->condition('type', 'search_api')
  760. ->execute();
  761. foreach ($entries as $entry) {
  762. db_update('watchdog')
  763. ->fields(array(
  764. 'message' => check_plain($entry->message),
  765. ))
  766. ->condition('wid', $entry->wid)
  767. ->execute();
  768. }
  769. }
  770. catch (Exception $e) {
  771. throw new DrupalUpdateException(t('An exception occurred during the update: @msg.', array('@msg' => $e->getMessage())));
  772. }
  773. }
  774. }