class LinkExtractorBatch in Link checker 8
Helper service to handle extraction index.
Hierarchy
- class \Drupal\linkchecker\LinkExtractorBatch uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of LinkExtractorBatch
2 files declare their use of LinkExtractorBatch
- LinkCheckerAdminSettingsForm.php in src/
Form/ LinkCheckerAdminSettingsForm.php - LinkCheckerCommands.php in src/
Commands/ LinkCheckerCommands.php
1 string reference to 'LinkExtractorBatch'
1 service uses LinkExtractorBatch
File
- src/
LinkExtractorBatch.php, line 16
Namespace
Drupal\linkcheckerView source
class LinkExtractorBatch {
use DependencySerializationTrait;
use MessengerTrait;
use StringTranslationTrait;
/**
* The link extractor.
*
* @var \Drupal\linkchecker\LinkExtractorService
*/
protected $extractor;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* LinkExtractorBatch constructor.
*/
public function __construct(LinkExtractorService $extractor, EntityTypeManagerInterface $entityTypeManager, Connection $dbConnection) {
$this->extractor = $extractor;
$this->entityTypeManager = $entityTypeManager;
$this->database = $dbConnection;
}
/**
* Gets list of entity types that selected for extraction.
*
* @return array
* List of entity types with bundles.
*/
public function getEntityTypesToProcess() {
$fieldConfigs = $this->entityTypeManager
->getStorage('field_config')
->loadMultiple(NULL);
$entityTypes = [];
/** @var \Drupal\Core\Field\FieldConfigInterface $config */
foreach ($fieldConfigs as $config) {
$scan = $config
->getThirdPartySetting('linkchecker', 'scan', FALSE);
if ($scan) {
$entityTypeId = $config
->getTargetEntityTypeId();
$bundle = $config
->getTargetBundle();
if (!isset($entityTypes[$entityTypeId . '-' . $bundle])) {
$entityType = $this->entityTypeManager
->getDefinition($entityTypeId);
$entityTypes[$entityTypeId . '-' . $bundle] = [
'entity_type' => $entityType,
'bundle' => $bundle,
];
}
}
}
return $entityTypes;
}
/**
* Process part of entities.
*
* @param int $numberOfItems
* Number of items to process.
*
* @return int
* Number of items that were processed.
*/
public function processEntities($numberOfItems = 20) {
$entityTypes = $this
->getEntityTypesToProcess();
$numberOfProcessedItems = 0;
foreach ($entityTypes as $entityTypeData) {
/** @var \Drupal\Core\Entity\EntityTypeInterface $entityType */
$entityType = $entityTypeData['entity_type'];
$bundle = $entityTypeData['bundle'];
$query = $this->database
->select($entityType
->getBaseTable(), 'base');
$query
->fields('base', [
$entityType
->getKey('id'),
]);
$query
->leftJoin('linkchecker_index', 'i', 'i.entity_id = base.' . $entityType
->getKey('id') . ' AND i.entity_type = :entity_type', [
':entity_type' => $entityType
->id(),
]);
$query
->isNull('i.entity_id');
if (!empty($bundle)) {
$query
->condition('base.' . $entityType
->getKey('bundle'), $bundle);
}
$query
->range(0, $numberOfItems - $numberOfProcessedItems);
$ids = $query
->execute()
->fetchCol();
$storage = $this->entityTypeManager
->getStorage($entityType
->id());
foreach ($ids as $id) {
$entity = $storage
->load($id);
if ($entity instanceof FieldableEntityInterface) {
$links = $this->extractor
->extractFromEntity($entity);
$this->extractor
->saveLinkMultiple($links);
$this->extractor
->updateEntityExtractIndex($entity);
}
$numberOfProcessedItems++;
}
if ($numberOfProcessedItems >= $numberOfItems) {
break;
}
}
return $numberOfProcessedItems;
}
/**
* Gets total number of entities to process.
*
* @return int
* Total number of entities.
*/
public function getTotalEntitiesToProcess() {
$entityTypes = $this
->getEntityTypesToProcess();
$total = 0;
foreach ($entityTypes as $entityTypeData) {
/** @var \Drupal\Core\Entity\EntityTypeInterface $entityType */
$entityType = $entityTypeData['entity_type'];
$bundle = $entityTypeData['bundle'];
// We don`t use $this->getQuery() cause we do not need left join
// on linkchecker_index table.
$query = $this->database
->select($entityType
->getBaseTable(), 'base');
$query
->fields('base', [
$entityType
->getKey('id'),
]);
if (!empty($bundle)) {
$query
->condition('base.' . $entityType
->getKey('bundle'), $bundle);
}
$query = $query
->countQuery();
$total += $query
->execute()
->fetchField();
}
return $total;
}
/**
* Gets number of processed entities.
*
* @return int
* Number of entities.
*/
public function getNumberOfProcessedEntities() {
$query = $this->database
->select('linkchecker_index', 'i');
$query
->fields('i');
$query = $query
->countQuery();
$total = $query
->execute()
->fetchField();
return $total;
}
/**
* Sets a batch to extract links from entities.
*/
public function batch() {
// Clear index to reindex all entities.
$this->database
->truncate('linkchecker_index')
->execute();
$batch = new BatchBuilder();
$batch
->setTitle('Extract entities')
->addOperation([
$this,
'batchProcessEntities',
], [
20,
])
->setProgressive()
->setFinishCallback([
$this,
'batchFinished',
]);
batch_set($batch
->toArray());
}
/**
* Process part of entities within a batch operation.
*
* @param int $numberOfItems
* Number of items to process.
* @param mixed $context
* Context data from batch API.
*/
public function batchProcessEntities($numberOfItems, &$context) {
if (!isset($context['sandbox']['total'])) {
$context['sandbox']['total'] = $this
->getTotalEntitiesToProcess();
$context['sandbox']['current'] = $this
->getNumberOfProcessedEntities();
}
$context['sandbox']['current'] += $this
->processEntities($numberOfItems);
if (!empty($context['sandbox']['total'])) {
$context['finished'] = $context['sandbox']['current'] / $context['sandbox']['total'];
}
else {
$context['finished'] = 1;
}
}
/**
* Finished callback for batch.
*/
public function batchFinished($success) {
if ($success) {
$this
->messenger()
->addStatus($this
->t('Links were successfully extracted.'));
}
else {
$this
->messenger()
->addError($this
->t('Links were not extracted.'));
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
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 | |
LinkExtractorBatch:: |
protected | property | The database connection. | |
LinkExtractorBatch:: |
protected | property | The entity type manager. | |
LinkExtractorBatch:: |
protected | property | The link extractor. | |
LinkExtractorBatch:: |
public | function | Sets a batch to extract links from entities. | |
LinkExtractorBatch:: |
public | function | Finished callback for batch. | |
LinkExtractorBatch:: |
public | function | Process part of entities within a batch operation. | |
LinkExtractorBatch:: |
public | function | Gets list of entity types that selected for extraction. | |
LinkExtractorBatch:: |
public | function | Gets number of processed entities. | |
LinkExtractorBatch:: |
public | function | Gets total number of entities to process. | |
LinkExtractorBatch:: |
public | function | Process part of entities. | |
LinkExtractorBatch:: |
public | function | LinkExtractorBatch constructor. | |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
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. |