You are here

public function SearchApiEntityDataSourceController::startTracking in Search API 7

Initializes tracking of the index status of items for the given indexes.

All currently known items of this data source's type should be inserted into the tracking table for the given indexes, with status "changed". If items were already present, these should also be set to "changed" and not be inserted again.

Parameters

SearchApiIndex[] $indexes: The SearchApiIndex objects for which item tracking should be initialized.

Throws

SearchApiDataSourceException If any error state was encountered.

Overrides SearchApiAbstractDataSourceController::startTracking

File

includes/datasource_entity.inc, line 139
Contains the SearchApiEntityDataSourceController class.

Class

SearchApiEntityDataSourceController
Represents a datasource for all entities known to the Entity API.

Code

public function startTracking(array $indexes) {
  if (!$this->table) {
    return;
  }

  // We first clear the tracking table for all indexes, so we can just insert
  // all items again without any key conflicts.
  $this
    ->stopTracking($indexes);
  if (!empty($this->entityInfo['base table']) && $this->idKey) {

    // Use a subselect, which will probably be much faster than entity_load().
    // Assumes that all entities use the "base table" property and the
    // "entity keys[id]" in the same way as the default controller.
    $table = $this->entityInfo['base table'];

    // We could also use a single insert (with a UNION in the nested query),
    // but this method will be mostly called with a single index, anyways.
    foreach ($indexes as $index) {

      // Select all entity ids.
      $query = db_select($table, 't');
      $query
        ->addField('t', $this->idKey, 'item_id');
      $query
        ->addExpression(':index_id', 'index_id', array(
        ':index_id' => $index->id,
      ));
      $query
        ->addExpression('1', 'changed');
      if ($bundles = $this
        ->getIndexBundles($index)) {
        $bundle_column = $this->bundleKey;
        if (!db_field_exists($table, $bundle_column)) {
          if ($this->entityType == 'taxonomy_term') {
            $bundle_column = 'vid';
            $bundles = db_query('SELECT vid FROM {taxonomy_vocabulary} WHERE machine_name IN (:bundles)', array(
              ':bundles' => $bundles,
            ))
              ->fetchCol();
          }
          elseif ($this->entityType == 'flagging') {
            $bundle_column = 'fid';
            $bundles = db_query('SELECT fid FROM {flag} WHERE name IN (:bundles)', array(
              ':bundles' => $bundles,
            ))
              ->fetchCol();
          }
          elseif ($this->entityType == 'comment') {

            // Comments are significantly more complicated, since they don't
            // store their bundle explicitly in their database table. Instead,
            // we need to get all the nodes from the enabled types and filter
            // by those.
            $bundle_column = 'nid';
            $node_types = array();
            foreach ($bundles as $bundle) {
              if (substr($bundle, 0, 13) === 'comment_node_') {
                $node_types[] = substr($bundle, 13);
              }
            }
            if ($node_types) {
              $bundles = db_query('SELECT nid FROM {node} WHERE type IN (:bundles)', array(
                ':bundles' => $node_types,
              ))
                ->fetchCol();
            }
            else {
              continue;
            }
          }
          else {
            $this
              ->startTrackingFallback(array(
              $index->machine_name => $index,
            ));
            continue;
          }
        }
        if ($bundles) {
          $query
            ->condition($bundle_column, $bundles);
        }
      }

      // INSERT ... SELECT ...
      db_insert($this->table)
        ->from($query)
        ->execute();
    }
  }
  else {
    $this
      ->startTrackingFallback($indexes);
  }
}