class Basic in Search API 8
Provides a tracker implementation which uses a FIFO-like processing order.
Plugin annotation
@SearchApiTracker(
id = "default",
label = @Translation("Default"),
description = @Translation("Default index tracker which uses a simple database table for tracking items.")
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\search_api\Plugin\HideablePluginBase implements HideablePluginInterface
- class \Drupal\search_api\Plugin\ConfigurablePluginBase implements ConfigurablePluginInterface uses PluginDependencyTrait
- class \Drupal\search_api\Plugin\IndexPluginBase implements IndexPluginInterface
- class \Drupal\search_api\Tracker\TrackerPluginBase implements TrackerInterface
- class \Drupal\search_api\Plugin\search_api\tracker\Basic implements PluginFormInterface uses LoggerTrait, PluginFormTrait
- class \Drupal\search_api\Tracker\TrackerPluginBase implements TrackerInterface
- class \Drupal\search_api\Plugin\IndexPluginBase implements IndexPluginInterface
- class \Drupal\search_api\Plugin\ConfigurablePluginBase implements ConfigurablePluginInterface uses PluginDependencyTrait
- class \Drupal\search_api\Plugin\HideablePluginBase implements HideablePluginInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of Basic
2 files declare their use of Basic
- IntegrationTest.php in tests/
src/ Functional/ IntegrationTest.php - NoUi.php in tests/
search_api_test_no_ui/ src/ Plugin/ search_api/ tracker/ NoUi.php
File
- src/
Plugin/ search_api/ tracker/ Basic.php, line 24
Namespace
Drupal\search_api\Plugin\search_api\trackerView source
class Basic extends TrackerPluginBase implements PluginFormInterface {
use LoggerTrait;
use PluginFormTrait;
/**
* Status value that represents items which are indexed in their latest form.
*/
const STATUS_INDEXED = 0;
/**
* Status value that represents items which still need to be indexed.
*/
const STATUS_NOT_INDEXED = 1;
/**
* The database connection used by this plugin.
*
* @var \Drupal\Core\Database\Connection
*/
protected $connection;
/**
* The time service.
*
* @var \Drupal\Component\Datetime\TimeInterface|null
*/
protected $timeService;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
/** @var static $tracker */
$tracker = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$tracker
->setDatabaseConnection($container
->get('database'));
$tracker
->setTimeService($container
->get('datetime.time'));
return $tracker;
}
/**
* Retrieves the database connection.
*
* @return \Drupal\Core\Database\Connection
* The database connection used by this plugin.
*/
public function getDatabaseConnection() {
return $this->connection ?: \Drupal::database();
}
/**
* Sets the database connection.
*
* @param \Drupal\Core\Database\Connection $connection
* The database connection to use.
*
* @return $this
*/
public function setDatabaseConnection(Connection $connection) {
$this->connection = $connection;
return $this;
}
/**
* Retrieves the time service.
*
* @return \Drupal\Component\Datetime\TimeInterface
* The time service.
*/
public function getTimeService() {
return $this->timeService ?: \Drupal::time();
}
/**
* Sets the time service.
*
* @param \Drupal\Component\Datetime\TimeInterface $time_service
* The new time service.
*
* @return $this
*/
public function setTimeService(TimeInterface $time_service) {
$this->timeService = $time_service;
return $this;
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'indexing_order' => 'fifo',
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['indexing_order'] = [
'#type' => 'radios',
'#title' => $this
->t('Indexing order'),
'#description' => $this
->t('The order in which items will be indexed.'),
'#options' => [
'fifo' => $this
->t('Index items in the same order in which they were saved'),
'lifo' => $this
->t('Index the most recent items first'),
],
'#default_value' => $this->configuration['indexing_order'],
];
return $form;
}
/**
* Creates a SELECT statement for this tracker.
*
* @return \Drupal\Core\Database\Query\SelectInterface
* A SELECT statement.
*/
protected function createSelectStatement() {
$select = $this
->getDatabaseConnection()
->select('search_api_item', 'sai');
$select
->condition('index_id', $this
->getIndex()
->id());
return $select;
}
/**
* Creates an INSERT statement for this tracker.
*
* @return \Drupal\Core\Database\Query\Insert
* An INSERT statement.
*/
protected function createInsertStatement() {
return $this
->getDatabaseConnection()
->insert('search_api_item')
->fields([
'index_id',
'datasource',
'item_id',
'changed',
'status',
]);
}
/**
* Creates an UPDATE statement for this tracker.
*
* @return \Drupal\Core\Database\Query\Update
* An UPDATE statement.
*/
protected function createUpdateStatement() {
return $this
->getDatabaseConnection()
->update('search_api_item')
->condition('index_id', $this
->getIndex()
->id());
}
/**
* Creates a DELETE statement for this tracker.
*
* @return \Drupal\Core\Database\Query\Delete
* A DELETE Statement.
*/
protected function createDeleteStatement() {
return $this
->getDatabaseConnection()
->delete('search_api_item')
->condition('index_id', $this
->getIndex()
->id());
}
/**
* Creates a SELECT statement which filters on the not indexed items.
*
* @param string|null $datasource_id
* (optional) If specified, only items of the datasource with that ID are
* retrieved.
*
* @return \Drupal\Core\Database\Query\SelectInterface
* A SELECT statement.
*/
protected function createRemainingItemsStatement($datasource_id = NULL) {
$select = $this
->createSelectStatement();
$select
->fields('sai', [
'item_id',
]);
if ($datasource_id) {
$select
->condition('datasource', $datasource_id);
}
$select
->condition('sai.status', $this::STATUS_NOT_INDEXED, '=');
// Use the same direction for both sorts to avoid performance problems.
$order = $this->configuration['indexing_order'] === 'lifo' ? 'DESC' : 'ASC';
$select
->orderBy('sai.changed', $order);
// Add a secondary sort on item ID to make the order completely predictable.
$select
->orderBy('sai.item_id', $order);
return $select;
}
/**
* {@inheritdoc}
*/
public function trackItemsInserted(array $ids) {
try {
$index_id = $this
->getIndex()
->id();
// Process the IDs in chunks so we don't create an overly large INSERT
// statement.
foreach (array_chunk($ids, 1000) as $ids_chunk) {
// We have to make sure we don't try to insert duplicate items.
$select = $this
->createSelectStatement()
->fields('sai', [
'item_id',
]);
$select
->condition('item_id', $ids_chunk, 'IN');
$existing = $select
->execute()
->fetchCol();
$existing = array_flip($existing);
$insert = $this
->createInsertStatement();
foreach ($ids_chunk as $item_id) {
if (isset($existing[$item_id])) {
continue;
}
list($datasource_id) = Utility::splitCombinedId($item_id);
$insert
->values([
'index_id' => $index_id,
'datasource' => $datasource_id,
'item_id' => $item_id,
'changed' => $this
->getTimeService()
->getRequestTime(),
'status' => $this::STATUS_NOT_INDEXED,
]);
}
if ($insert
->count()) {
$insert
->execute();
}
}
} catch (\Exception $e) {
$this
->logException($e);
}
}
/**
* {@inheritdoc}
*/
public function trackItemsUpdated(array $ids = NULL) {
try {
// Process the IDs in chunks so we don't create an overly large UPDATE
// statement.
$ids_chunks = $ids !== NULL ? array_chunk($ids, 1000) : [
NULL,
];
foreach ($ids_chunks as $ids_chunk) {
$update = $this
->createUpdateStatement();
$update
->fields([
'changed' => $this
->getTimeService()
->getRequestTime(),
'status' => $this::STATUS_NOT_INDEXED,
]);
if ($ids_chunk) {
$update
->condition('item_id', $ids_chunk, 'IN');
}
// Update the status of unindexed items only if the item order is LIFO.
// (Otherwise, an item that's regularly being updated might never get
// indexed.)
if ($this->configuration['indexing_order'] === 'fifo') {
$update
->condition('status', self::STATUS_INDEXED);
}
$update
->execute();
}
} catch (\Exception $e) {
$this
->logException($e);
}
}
/**
* {@inheritdoc}
*/
public function trackAllItemsUpdated($datasource_id = NULL) {
try {
$update = $this
->createUpdateStatement();
$update
->fields([
'changed' => $this
->getTimeService()
->getRequestTime(),
'status' => $this::STATUS_NOT_INDEXED,
]);
if ($datasource_id) {
$update
->condition('datasource', $datasource_id);
}
$update
->execute();
} catch (\Exception $e) {
$this
->logException($e);
}
}
/**
* {@inheritdoc}
*/
public function trackItemsIndexed(array $ids) {
try {
// Process the IDs in chunks so we don't create an overly large UPDATE
// statement.
$ids_chunks = array_chunk($ids, 1000);
foreach ($ids_chunks as $ids_chunk) {
$update = $this
->createUpdateStatement();
$update
->fields([
'status' => $this::STATUS_INDEXED,
]);
$update
->condition('item_id', $ids_chunk, 'IN');
$update
->execute();
}
} catch (\Exception $e) {
$this
->logException($e);
}
}
/**
* {@inheritdoc}
*/
public function trackItemsDeleted(array $ids = NULL) {
try {
// Process the IDs in chunks so we don't create an overly large DELETE
// statement.
$ids_chunks = $ids !== NULL ? array_chunk($ids, 1000) : [
NULL,
];
foreach ($ids_chunks as $ids_chunk) {
$delete = $this
->createDeleteStatement();
if ($ids_chunk) {
$delete
->condition('item_id', $ids_chunk, 'IN');
}
$delete
->execute();
}
} catch (\Exception $e) {
$this
->logException($e);
}
}
/**
* {@inheritdoc}
*/
public function trackAllItemsDeleted($datasource_id = NULL) {
try {
$delete = $this
->createDeleteStatement();
if ($datasource_id) {
$delete
->condition('datasource', $datasource_id);
}
$delete
->execute();
} catch (\Exception $e) {
$this
->logException($e);
}
}
/**
* {@inheritdoc}
*/
public function getRemainingItems($limit = -1, $datasource_id = NULL) {
try {
$select = $this
->createRemainingItemsStatement($datasource_id);
if ($limit >= 0) {
$select
->range(0, $limit);
}
return $select
->execute()
->fetchCol();
} catch (\Exception $e) {
$this
->logException($e);
return [];
}
}
/**
* {@inheritdoc}
*/
public function getTotalItemsCount($datasource_id = NULL) {
try {
$select = $this
->createSelectStatement();
if ($datasource_id) {
$select
->condition('datasource', $datasource_id);
}
return (int) $select
->countQuery()
->execute()
->fetchField();
} catch (\Exception $e) {
$this
->logException($e);
return 0;
}
}
/**
* {@inheritdoc}
*/
public function getIndexedItemsCount($datasource_id = NULL) {
try {
$select = $this
->createSelectStatement();
$select
->condition('sai.status', $this::STATUS_INDEXED);
if ($datasource_id) {
$select
->condition('datasource', $datasource_id);
}
return (int) $select
->countQuery()
->execute()
->fetchField();
} catch (\Exception $e) {
$this
->logException($e);
return 0;
}
}
/**
* {@inheritdoc}
*/
public function getRemainingItemsCount($datasource_id = NULL) {
try {
$select = $this
->createRemainingItemsStatement();
if ($datasource_id) {
$select
->condition('datasource', $datasource_id);
}
return (int) $select
->countQuery()
->execute()
->fetchField();
} catch (\Exception $e) {
$this
->logException($e);
return 0;
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
Basic:: |
protected | property | The database connection used by this plugin. | |
Basic:: |
protected | property | The time service. | |
Basic:: |
public | function |
Form constructor. Overrides PluginFormInterface:: |
|
Basic:: |
public static | function |
Creates an instance of the plugin. Overrides ConfigurablePluginBase:: |
|
Basic:: |
protected | function | Creates a DELETE statement for this tracker. | |
Basic:: |
protected | function | Creates an INSERT statement for this tracker. | |
Basic:: |
protected | function | Creates a SELECT statement which filters on the not indexed items. | |
Basic:: |
protected | function | Creates a SELECT statement for this tracker. | |
Basic:: |
protected | function | Creates an UPDATE statement for this tracker. | |
Basic:: |
public | function |
Gets default configuration for this plugin. Overrides ConfigurablePluginBase:: |
|
Basic:: |
public | function | Retrieves the database connection. | |
Basic:: |
public | function |
Retrieves the number of indexed items for this index. Overrides TrackerInterface:: |
|
Basic:: |
public | function |
Retrieves a list of item IDs that need to be indexed. Overrides TrackerInterface:: |
|
Basic:: |
public | function |
Retrieves the total number of pending items for this index. Overrides TrackerInterface:: |
|
Basic:: |
public | function | Retrieves the time service. | |
Basic:: |
public | function |
Retrieves the total number of items that are being tracked for this index. Overrides TrackerInterface:: |
|
Basic:: |
public | function | Sets the database connection. | |
Basic:: |
public | function | Sets the time service. | |
Basic:: |
constant | Status value that represents items which are indexed in their latest form. | ||
Basic:: |
constant | Status value that represents items which still need to be indexed. | ||
Basic:: |
public | function |
Removes all items from the tracker, or only those of a specific datasource. Overrides TrackerInterface:: |
|
Basic:: |
public | function |
Marks all items as updated, or only those of a specific datasource. Overrides TrackerInterface:: |
|
Basic:: |
public | function |
Removes items from the tracking system for this index. Overrides TrackerInterface:: |
|
Basic:: |
public | function |
Marks items as indexed for this index. Overrides TrackerInterface:: |
|
Basic:: |
public | function |
Inserts new items into the tracking system for this index. Overrides TrackerInterface:: |
|
Basic:: |
public | function |
Marks the given items as updated for this index. Overrides TrackerInterface:: |
|
ConfigurablePluginBase:: |
public | function |
Calculates dependencies for the configured plugin. Overrides DependentPluginInterface:: |
6 |
ConfigurablePluginBase:: |
protected | function | Calculates and adds dependencies of a specific plugin instance. | |
ConfigurablePluginBase:: |
public | function |
Gets this plugin's configuration. Overrides ConfigurableInterface:: |
|
ConfigurablePluginBase:: |
public | function |
Returns the plugin's description. Overrides ConfigurablePluginInterface:: |
|
ConfigurablePluginBase:: |
protected | function | Calculates and returns dependencies of a specific plugin instance. | |
ConfigurablePluginBase:: |
public | function |
Returns the label for use on the administration pages. Overrides ConfigurablePluginInterface:: |
|
ConfigurablePluginBase:: |
protected | function | Wraps the module handler. | |
ConfigurablePluginBase:: |
public | function |
Informs the plugin that some of its dependencies are being removed. Overrides ConfigurablePluginInterface:: |
5 |
ConfigurablePluginBase:: |
public | function |
Sets the configuration for this plugin instance. Overrides ConfigurableInterface:: |
3 |
ConfigurablePluginBase:: |
protected | function | Wraps the theme handler. | |
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
DependencyTrait:: |
protected | property | The object's dependencies. | |
DependencyTrait:: |
protected | function | Adds multiple dependencies. | |
DependencyTrait:: |
protected | function | Adds a dependency. | |
HideablePluginBase:: |
public | function |
Determines whether this plugin should be hidden in the UI. Overrides HideablePluginInterface:: |
1 |
IndexPluginBase:: |
protected | property | The index this processor is configured for. | |
IndexPluginBase:: |
public | function |
Retrieves the index this plugin is configured for. Overrides IndexPluginInterface:: |
|
IndexPluginBase:: |
public | function |
Sets the index this plugin is configured for. Overrides IndexPluginInterface:: |
|
IndexPluginBase:: |
public | function |
Constructs a \Drupal\Component\Plugin\PluginBase object. Overrides ConfigurablePluginBase:: |
2 |
LoggerTrait:: |
protected | property | The logging channel to use. | |
LoggerTrait:: |
public | function | Retrieves the logger. | |
LoggerTrait:: |
protected | function | Logs an exception. | |
LoggerTrait:: |
public | function | Sets the logger. | |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
PluginDependencyTrait:: |
protected | function | Calculates and adds dependencies of a specific plugin instance. Aliased as: traitCalculatePluginDependencies | 1 |
PluginDependencyTrait:: |
protected | function | Calculates and returns dependencies of a specific plugin instance. Aliased as: traitGetPluginDependencies | |
PluginDependencyTrait:: |
protected | function | Wraps the module handler. Aliased as: traitModuleHandler | 1 |
PluginDependencyTrait:: |
protected | function | Wraps the theme handler. Aliased as: traitThemeHandler | 1 |
PluginFormTrait:: |
public | function | Form submission handler. | 7 |
PluginFormTrait:: |
public | function | Form validation handler. | 2 |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |