コード例 #1
0
 /**
  * {@inheritdoc}
  */
 public function buildForm(array $form, FormStateInterface $form_state)
 {
     $index = $this->entity;
     // Do not allow the form to be cached. See
     // \Drupal\views_ui\ViewEditForm::form().
     $form_state->disableCache();
     if ($index instanceof UnsavedConfigurationInterface && $index->hasChanges()) {
         if ($index->isLocked()) {
             $form['#disabled'] = TRUE;
             $username = array('#theme' => 'username', '#account' => $index->getLockOwner($this->entityTypeManager));
             $lock_message_substitutions = array('@user' => $this->getRenderer()->render($username), '@age' => $this->dateFormatter->formatTimeDiffSince($index->getLastUpdated()), ':url' => $index->toUrl('break-lock-form')->toString());
             $form['locked'] = array('#type' => 'container', '#attributes' => array('class' => array('index-locked', 'messages', 'messages--warning')), '#children' => $this->t('This index is being edited by user @user, and is therefore locked from editing by others. This lock is @age old. Click here to <a href=":url">break this lock</a>.', $lock_message_substitutions), '#weight' => -10);
         }
     }
     $args['%index'] = $index->label();
     $form['#title'] = $this->t('Add fields to index %index', $args);
     $form['properties'] = array('#theme' => 'search_api_form_item_list');
     $datasources = array('' => NULL);
     $datasources += $this->entity->getDatasources();
     foreach ($datasources as $datasource) {
         $form['properties'][] = $this->getDatasourceListItem($datasource);
     }
     // Log any unmapped types that were encountered.
     if ($this->unmappedFields) {
         $unmapped_types = array();
         foreach ($this->unmappedFields as $type => $fields) {
             $unmapped_types[] = implode(', ', $fields) . ' (' . new FormattableMarkup('type @type', array('@type' => $type)) . ')';
         }
         $vars['@fields'] = implode('; ', $unmapped_types);
         $vars['%index'] = $this->entity->label();
         \Drupal::logger('search_api')->warning('Warning while retrieving available fields for index %index: could not find a type mapping for the following fields: @fields.', $vars);
     }
     $form['actions'] = $this->actionsElement($form, $form_state);
     return $form;
 }
コード例 #2
0
 /**
  * Enables a search index without a confirmation form.
  *
  * @param \Drupal\search_api\IndexInterface $search_api_index
  *   The index to be enabled.
  *
  * @return \Symfony\Component\HttpFoundation\Response
  *   The response to send to the browser.
  */
 public function indexBypassEnable(IndexInterface $search_api_index)
 {
     // Enable the index.
     $search_api_index->setStatus(TRUE)->save();
     // \Drupal\search_api\Entity\Index::preSave() doesn't allow an index to be
     // enabled if its server is not set or disabled.
     if ($search_api_index->status()) {
         // Notify the user about the status change.
         drupal_set_message($this->t('The search index %name has been enabled.', array('%name' => $search_api_index->label())));
     } else {
         // Notify the user that the status change did not succeed.
         drupal_set_message($this->t('The search index %name could not be enabled. Check if its server is set and enabled.', array('%name' => $search_api_index->label())));
     }
     // Redirect to the index's "View" page.
     $url = $search_api_index->toUrl('canonical');
     return $this->redirect($url->getRouteName(), $url->getRouteParameters());
 }
コード例 #3
0
ファイル: FieldTrait.php プロジェクト: jkyto/agolf
 public function getDataDefinition() {
   if (!isset($this->dataDefinition)) {
     $definitions = $this->index->getPropertyDefinitions($this->datasourceId);
     if (!isset($definitions[$this->propertyPath])) {
       $args['@field'] = $this->fieldIdentifier;
       $args['%index'] = $this->index->label();
       throw new SearchApiException(new FormattableMarkup('Could not retrieve data definition for field "@field" on index %index.', $args));
     }
     $this->dataDefinition = $definitions[$this->propertyPath];
   }
   return $this->dataDefinition;
 }
コード例 #4
0
ファイル: ServerTaskUnitTest.php プロジェクト: jkyto/agolf
  /**
   * Tests task system integration for the server's removeIndex() method.
   */
  public function testRemoveIndex() {
    // Set exception for updateIndex() and removeIndex(), and reset the list of
    // successful backend method calls.
    $this->state->set('search_api_test_backend.exception.updateIndex', TRUE);
    $this->state->set('search_api_test_backend.exception.removeIndex', TRUE);
    $this->getCalledServerMethods();

    // First try to update the index and fail. Then try to remove it and check
    // that the tasks were set correctly.
    $this->server->updateIndex($this->index);
    $this->server->removeIndex($this->index);
    $this->assertEquals(array(), $this->getCalledServerMethods(), 'updateIndex and removeIndex correctly threw exceptions.');
    $tasks = $this->getServerTasks();
    if (count($tasks) == 1) {
      $task_created = $tasks[0]->type === 'removeIndex';
    }
    $this->assertTrue(!empty($task_created), 'The removeIndex task was successfully added and other tasks removed.');
    if ($tasks) {
      $this->assertEquals($this->index->id(), $tasks[0]->index_id, 'The right index ID was used for the removeIndex task.');
    }

    // Check whether other task-system-integrated methods now fail, too.
    try {
      $this->server->indexItems($this->index, array());
      $this->fail('Pending server tasks did not prevent indexing of items.');
    }
    catch (SearchApiException $e) {
      $args['%index'] = $this->index->label();
      $expected_message = new FormattableMarkup('Could not index items on index %index because pending server tasks could not be executed.', $args);
      $this->assertEquals($expected_message, $e->getMessage(), 'Pending server tasks prevented indexing of items.');
    }
    $this->assertEquals(array(), $this->getCalledServerMethods(), 'indexItems was not executed.');
    $tasks = $this->getServerTasks();
    $this->assertEquals(1, count($tasks), 'No task added for indexItems.');

    // Let removeIndex() succeed again, then trigger the task execution with a
    // cron run.
    $this->state->set("search_api_test_backend.exception.removeIndex", FALSE);
    search_api_cron();
    $this->assertEquals(array(), $this->getServerTasks(), 'Server tasks were correctly executed.');
    $this->assertEquals(array('removeIndex'), $this->getCalledServerMethods(), 'Right methods were called during task execution.');
  }
コード例 #5
0
 /**
  * Builds the form for the basic index properties.
  *
  * @param \Drupal\search_api\IndexInterface $index
  *   The index that is being created or edited.
  */
 public function buildEntityForm(array &$form, FormStateInterface $form_state, IndexInterface $index)
 {
     $form['#tree'] = TRUE;
     $form['name'] = array('#type' => 'textfield', '#title' => $this->t('Index name'), '#description' => $this->t('Enter the displayed name for the index.'), '#default_value' => $index->label(), '#required' => TRUE);
     $form['id'] = array('#type' => 'machine_name', '#default_value' => $index->id(), '#maxlength' => 50, '#required' => TRUE, '#machine_name' => array('exists' => array($this->getIndexStorage(), 'load'), 'source' => array('name')));
     // If the user changed the datasources or the tracker, notify them that they
     // need to be configured.
     // @todo Only do that if the datasources/tracker have configuration forms.
     //   (Same in \Drupal\search_api\Form\ServerForm.)
     $values = $form_state->getValues();
     if (!empty($values['datasources'])) {
         drupal_set_message($this->t('Please configure the used datasources.'), 'warning');
     }
     if (!empty($values['tracker'])) {
         drupal_set_message($this->t('Please configure the used tracker.'), 'warning');
     }
     $form['#attached']['library'][] = 'search_api/drupal.search_api.admin_css';
     $datasource_options = array();
     foreach ($this->getDatasourcePluginManager()->getDefinitions() as $datasource_id => $definition) {
         $datasource_options[$datasource_id] = !empty($definition['label']) ? $definition['label'] : $datasource_id;
     }
     $form['datasources'] = array('#type' => 'select', '#title' => $this->t('Data sources'), '#description' => $this->t('Select one or more data sources of items that will be stored in this index.'), '#options' => $datasource_options, '#default_value' => $index->getDatasourceIds(), '#multiple' => TRUE, '#required' => TRUE, '#ajax' => array('trigger_as' => array('name' => 'datasourcepluginids_configure'), 'callback' => '::buildAjaxDatasourceConfigForm', 'wrapper' => 'search-api-datasources-config-form', 'method' => 'replace', 'effect' => 'fade'));
     $form['datasource_configs'] = array('#type' => 'container', '#attributes' => array('id' => 'search-api-datasources-config-form'), '#tree' => TRUE);
     $form['datasource_configure_button'] = array('#type' => 'submit', '#name' => 'datasourcepluginids_configure', '#value' => $this->t('Configure'), '#limit_validation_errors' => array(array('datasources')), '#submit' => array('::submitAjaxDatasourceConfigForm'), '#ajax' => array('callback' => '::buildAjaxDatasourceConfigForm', 'wrapper' => 'search-api-datasources-config-form'), '#attributes' => array('class' => array('js-hide')));
     $this->buildDatasourcesConfigForm($form, $form_state, $index);
     $tracker_options = $this->getTrackerPluginManager()->getOptionsList();
     $form['tracker'] = array('#type' => 'radios', '#title' => $this->t('Tracker'), '#description' => $this->t('Select the type of tracker which should be used for keeping track of item changes.'), '#options' => $this->getTrackerPluginManager()->getOptionsList(), '#default_value' => $index->hasValidTracker() ? $index->getTracker()->getPluginId() : key($tracker_options), '#required' => TRUE, '#disabled' => !$index->isNew(), '#ajax' => array('trigger_as' => array('name' => 'trackerpluginid_configure'), 'callback' => '::buildAjaxTrackerConfigForm', 'wrapper' => 'search-api-tracker-config-form', 'method' => 'replace', 'effect' => 'fade'), '#access' => count($tracker_options) > 1);
     $form['tracker_config'] = array('#type' => 'container', '#attributes' => array('id' => 'search-api-tracker-config-form'), '#tree' => TRUE);
     $form['tracker_configure_button'] = array('#type' => 'submit', '#name' => 'trackerpluginid_configure', '#value' => $this->t('Configure'), '#limit_validation_errors' => array(array('tracker')), '#submit' => array('::submitAjaxTrackerConfigForm'), '#ajax' => array('callback' => '::buildAjaxTrackerConfigForm', 'wrapper' => 'search-api-tracker-config-form'), '#attributes' => array('class' => array('js-hide')), '#access' => count($tracker_options) > 1);
     $this->buildTrackerConfigForm($form, $form_state, $index);
     $form['server'] = array('#type' => 'radios', '#title' => $this->t('Server'), '#description' => $this->t('Select the server this index should use. Indexes cannot be enabled without a connection to a valid, enabled server.'), '#options' => array(NULL => '<em>' . $this->t('- No server -') . '</em>') + $this->getServerOptions(), '#default_value' => $index->hasValidServer() ? $index->getServerId() : NULL);
     $form['status'] = array('#type' => 'checkbox', '#title' => $this->t('Enabled'), '#description' => $this->t('Only enabled indexes can be used for indexing and searching. This setting will only take effect if the selected server is also enabled.'), '#default_value' => $index->status(), '#disabled' => !$index->status() && (!$index->hasValidServer() || !$index->getServer()->status()), '#states' => array('invisible' => array(':input[name="server"]' => array('value' => ''))));
     $form['description'] = array('#type' => 'textarea', '#title' => $this->t('Description'), '#description' => $this->t('Enter a description for the index.'), '#default_value' => $index->getDescription());
     $form['options'] = array('#tree' => TRUE, '#type' => 'details', '#title' => $this->t('Index options'), '#collapsed' => TRUE);
     // We display the "read-only" flag along with the other options, even though
     // it is a property directly on the index object. We use "#parents" to move
     // it to the correct place in the form values.
     $form['options']['read_only'] = array('#type' => 'checkbox', '#title' => $this->t('Read only'), '#description' => $this->t('Do not write to this index or track the status of items in this index.'), '#default_value' => $index->isReadOnly(), '#parents' => array('read_only'));
     $form['options']['index_directly'] = array('#type' => 'checkbox', '#title' => $this->t('Index items immediately'), '#description' => $this->t('Immediately index new or updated items instead of waiting for the next cron run. This might have serious performance drawbacks and is generally not advised for larger sites.'), '#default_value' => $index->getOption('index_directly'));
     $form['options']['cron_limit'] = array('#type' => 'textfield', '#title' => $this->t('Cron batch size'), '#description' => $this->t('Set how many items will be indexed at once when indexing items during a cron run. "0" means that no items will be indexed by cron for this index, "-1" means that cron should index all items at once.'), '#default_value' => $index->getOption('cron_limit'), '#size' => 4);
 }
コード例 #6
0
ファイル: IndexProcessorsForm.php プロジェクト: jkyto/agolf
  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state) {
    $form['#attached']['library'][] = 'search_api/drupal.search_api.admin_css';

    // Retrieve lists of all processors, and the stages and weights they have.
    if (!$form_state->has('processors')) {
      $all_processors = $this->entity->getProcessors(FALSE);
      $sort_processors = function (ProcessorInterface $a, ProcessorInterface $b) {
        return strnatcasecmp($a->label(), $b->label());
      };
      uasort($all_processors, $sort_processors);
    }
    else {
      $all_processors = $form_state->get('processors');
    }

    $stages = $this->processorPluginManager->getProcessingStages();
    $processors_by_stage = array();
    foreach ($stages as $stage => $definition) {
      $processors_by_stage[$stage] = $this->entity->getProcessorsByStage($stage, FALSE);
    }

    $processor_settings = $this->entity->getOption('processors');

    $form['#tree'] = TRUE;
    $form['#attached']['library'][] = 'search_api/drupal.search_api.index-active-formatters';
    $form['#title'] = $this->t('Manage processors for search index %label', array('%label' => $this->entity->label()));
    $form['description']['#markup'] = '<p>' . $this->t('Configure processors which will pre- and post-process data at index and search time.') . '</p>';

    // Add the list of processors with checkboxes to enable/disable them.
    $form['status'] = array(
      '#type' => 'fieldset',
      '#title' => $this->t('Enabled'),
      '#attributes' => array('class' => array(
        'search-api-status-wrapper',
      )),
    );
    foreach ($all_processors as $processor_id => $processor) {
      $clean_css_id = Html::cleanCssIdentifier($processor_id);
      $form['status'][$processor_id] = array(
        '#type' => 'checkbox',
        '#title' => $processor->label(),
        '#default_value' => $processor->isLocked() || !empty($processor_settings[$processor_id]),
        '#description' => $processor->getDescription(),
        '#attributes' => array(
          'class' => array(
            'search-api-processor-status-' . $clean_css_id,
          ),
          'data-id' => $clean_css_id,
        ),
        '#disabled' => $processor->isLocked(),
        '#access' => !$processor->isHidden(),
      );
    }

    $form['weights'] = array(
      '#type' => 'fieldset',
      '#title' => t('Processor order'),
    );
    // Order enabled processors per stage.
    foreach ($stages as $stage => $description) {
      $form['weights'][$stage] = array (
        '#type' => 'fieldset',
        '#title' => $description['label'],
        '#attributes' => array('class' => array(
          'search-api-stage-wrapper',
          'search-api-stage-wrapper-' . Html::cleanCssIdentifier($stage),
        )),
      );
      $form['weights'][$stage]['order'] = array(
        '#type' => 'table',
      );
      $form['weights'][$stage]['order']['#tabledrag'][] = array(
        'action' => 'order',
        'relationship' => 'sibling',
        'group' => 'search-api-processor-weight-' . Html::cleanCssIdentifier($stage),
      );
    }
    foreach ($processors_by_stage as $stage => $processors) {
      /** @var \Drupal\search_api\Processor\ProcessorInterface $processor */
      foreach ($processors as $processor_id => $processor) {
        $weight = isset($processor_settings[$processor_id]['weights'][$stage])
          ? $processor_settings[$processor_id]['weights'][$stage]
          : $processor->getDefaultWeight($stage);
        if ($processor->isHidden()) {
          $form['processors'][$processor_id]['weights'][$stage] = array(
            '#type' => 'value',
            '#value' => $weight,
          );
          continue;
        }
        $form['weights'][$stage]['order'][$processor_id]['#attributes']['class'][] = 'draggable';
        $form['weights'][$stage]['order'][$processor_id]['#attributes']['class'][] = 'search-api-processor-weight--' . Html::cleanCssIdentifier($processor_id);
        $form['weights'][$stage]['order'][$processor_id]['#weight'] = $weight;
        $form['weights'][$stage]['order'][$processor_id]['label']['#plain_text'] = $processor->label();
        $form['weights'][$stage]['order'][$processor_id]['weight'] = array(
          '#type' => 'weight',
          '#title' => $this->t('Weight for processor %title', array('%title' => $processor->label())),
          '#title_display' => 'invisible',
          '#default_value' => $weight,
          '#parents' => array('processors', $processor_id, 'weights', $stage),
          '#attributes' => array('class' => array(
            'search-api-processor-weight-' . Html::cleanCssIdentifier($stage),
          )),
        );
      }
    }

    // Add vertical tabs containing the settings for the processors. Tabs for
    // disabled processors are hidden with JS magic, but need to be included in
    // case the processor is enabled.
    $form['processor_settings'] = array(
      '#title' => $this->t('Processor settings'),
      '#type' => 'vertical_tabs',
    );

    foreach ($all_processors as $processor_id => $processor) {
      $processor_form_state = new SubFormState($form_state, array('processors', $processor_id, 'settings'));
      $processor_form = $processor->buildConfigurationForm($form, $processor_form_state);
      if ($processor_form) {
        $form['settings'][$processor_id] = array(
          '#type' => 'details',
          '#title' => $processor->label(),
          '#group' => 'processor_settings',
          '#parents' => array('processors', $processor_id, 'settings'),
          '#attributes' => array('class' => array(
            'search-api-processor-settings-' . Html::cleanCssIdentifier($processor_id),
          )),
        );
        $form['settings'][$processor_id] += $processor_form;
      }
    }

    return $form;
  }
コード例 #7
0
 /**
  * Tests whether loading an index works correctly.
  *
  * @param \Drupal\search_api\IndexInterface $index
  *   The index used for the test.
  */
 public function indexLoad(IndexInterface $index)
 {
     $loaded_index = $this->storage->load($index->id());
     $this->assertIdentical($index->label(), $loaded_index->label());
 }
コード例 #8
0
ファイル: Server.php プロジェクト: curveagency/intranet
 /**
  * {@inheritdoc}
  */
 public function deleteAllIndexItems(IndexInterface $index)
 {
     if ($index->isReadOnly()) {
         $vars = array('%index' => $index->label());
         \Drupal::logger('search_api')->warning('Trying to delete items from index %index which is marked as read-only.', $vars);
         return;
     }
     $server_task_manager = \Drupal::getContainer()->get('search_api.server_task_manager');
     try {
         if ($server_task_manager->execute($this)) {
             $this->getBackend()->deleteAllIndexItems($index);
             return;
         }
     } catch (SearchApiException $e) {
         $vars = array('%server' => $this->label(), '%index' => $index->label());
         watchdog_exception('search_api', $e, '%type while deleting items of index %index from server %server: @message in %function (line %line of %file).', $vars);
     }
     $server_task_manager->add($this, __FUNCTION__, $index);
 }
コード例 #9
0
 /**
  * Tests whether loading an index works correctly.
  *
  * @param \Drupal\search_api\IndexInterface $index
  *   The index used for the test.
  */
 protected function indexLoad(IndexInterface $index)
 {
     $loaded_index = $this->storage->load($index->id());
     $this->assertSame($index->label(), $loaded_index->label());
 }
コード例 #10
0
ファイル: IndexBatchHelper.php プロジェクト: jkyto/agolf
 /**
  * Creates an indexing batch for a given search index.
  *
  * @param \Drupal\search_api\IndexInterface $index
  *   The search index for which items should be indexed.
  * @param int|null $batch_size
  *   (optional) Number of items to index per batch. Defaults to the cron limit
  *   set for the index.
  * @param int $limit
  *   (optional) Maximum number of items to index. Defaults to indexing all
  *   remaining items.
  *
  * @throws \Drupal\search_api\SearchApiException
  *   Thrown if the batch could not be created.
  */
 public static function create(IndexInterface $index, $batch_size = NULL, $limit = -1) {
   // Check if the size should be determined by the index cron limit option.
   if ($batch_size === NULL) {
     // Use the size set by the index.
     $batch_size = $index->getOption('cron_limit', \Drupal::config('search_api.settings')->get('default_cron_limit'));
   }
   // Check if indexing items is allowed.
   if ($index->status() && !$index->isReadOnly() && $batch_size !== 0 && $limit !== 0) {
     // Define the search index batch definition.
     $batch_definition = array(
       'operations' => array(
         array(array(__CLASS__, 'process'), array($index, $batch_size, $limit)),
       ),
       'finished' => array(__CLASS__, 'finish'),
       'progress_message' => static::t('Completed about @percentage% of the indexing operation (@current of @total).'),
     );
     // Schedule the batch.
     batch_set($batch_definition);
   }
   else {
     $args = array(
       '%size' => $batch_size,
       '%limit' => $limit,
       '%name' => $index->label(),
     );
     throw new SearchApiException(new FormattableMarkup('Failed to create a batch with batch size %size and limit %limit for index %name', $args));
   }
 }
コード例 #11
0
ファイル: Query.php プロジェクト: jkyto/agolf
 /**
  * Constructs a Query object.
  *
  * @param \Drupal\search_api\IndexInterface $index
  *   The index the query should be executed on.
  * @param \Drupal\search_api\Query\ResultsCacheInterface $results_cache
  *   The results cache that should be used for this query.
  * @param array $options
  *   (optional) Associative array of options configuring this query. See
  *   \Drupal\search_api\Query\QueryInterface::setOption() for a list of
  *   options that are recognized by default.
  *
  * @throws \Drupal\search_api\SearchApiException
  *   Thrown if a search on that index (or with those options) won't be
  *   possible.
  */
 public function __construct(IndexInterface $index, ResultsCacheInterface $results_cache, array $options = array()) {
   if (!$index->status()) {
     throw new SearchApiException(new FormattableMarkup("Can't search on index %index which is disabled.", array('%index' => $index->label())));
   }
   if (isset($options['parse mode'])) {
     $modes = $this->parseModes();
     if (!isset($modes[$options['parse mode']])) {
       throw new SearchApiException(new FormattableMarkup('Unknown parse mode: @mode.', array('@mode' => $options['parse mode'])));
     }
   }
   $this->index = $index;
   $this->resultsCache = $results_cache;
   $this->options = $options + array(
     'conjunction' => 'AND',
     'parse mode' => 'terms',
     'filter class' => '\Drupal\search_api\Query\Filter',
     'search id' => __CLASS__,
   );
   $this->filter = $this->createFilter('AND');
 }
コード例 #12
0
ファイル: Query.php プロジェクト: curveagency/intranet
 /**
  * Constructs a Query object.
  *
  * @param \Drupal\search_api\IndexInterface $index
  *   The index the query should be executed on.
  * @param \Drupal\search_api\Query\ResultsCacheInterface $results_cache
  *   The results cache that should be used for this query.
  * @param array $options
  *   (optional) Associative array of options configuring this query. See
  *   \Drupal\search_api\Query\QueryInterface::setOption() for a list of
  *   options that are recognized by default.
  *
  * @throws \Drupal\search_api\SearchApiException
  *   Thrown if a search on that index (or with those options) won't be
  *   possible.
  */
 public function __construct(IndexInterface $index, ResultsCacheInterface $results_cache, array $options = array())
 {
     if (!$index->status()) {
         throw new SearchApiException(new FormattableMarkup("Can't search on index %index which is disabled.", array('%index' => $index->label())));
     }
     $this->index = $index;
     $this->resultsCache = $results_cache;
     $this->options = $options + array('conjunction' => 'AND', 'search id' => __CLASS__);
     $this->conditionGroup = $this->createConditionGroup('AND');
 }
コード例 #13
0
 /**
  * {@inheritdoc}
  */
 public function label()
 {
     return $this->entity->label();
 }
コード例 #14
0
ファイル: search_api.api.php プロジェクト: jkyto/agolf
/**
 * Allows you to log or alter the items that are indexed.
 *
 * Please be aware that generally preventing the indexing of certain items is
 * deprecated. This is better done with processors, which can easily be
 * configured and only added to indexes where this behaviour is wanted.
 * If your module will use this hook to reject certain items from indexing,
 * please document this clearly to avoid confusion.
 *
 * @param \Drupal\search_api\IndexInterface $index
 *   The search index on which items will be indexed.
 * @param \Drupal\search_api\Item\ItemInterface[] $items
 *   The items that will be indexed.
 */
function hook_search_api_index_items_alter(\Drupal\search_api\IndexInterface $index, array &$items) {
  foreach ($items as $item_id => $item) {
    list(, $raw_id) = \Drupal\search_api\Utility::splitCombinedId($item->getId());
    if ($raw_id % 5 == 0) {
      unset($items[$item_id]);
    }
  }
  drupal_set_message(t('Indexing items on index %index with the following IDs: @ids', array('%index' => $index->label(), '@ids' => implode(', ', array_keys($items)))));
}