View source
<?php
namespace Drupal\linkchecker;
use Drupal\Core\Batch\BatchBuilder;
use Drupal\Core\Database\Connection;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Entity\FieldableEntityInterface;
class LinkExtractorBatch {
use DependencySerializationTrait;
use MessengerTrait;
use StringTranslationTrait;
protected $extractor;
protected $entityTypeManager;
protected $database;
public function __construct(LinkExtractorService $extractor, EntityTypeManagerInterface $entityTypeManager, Connection $dbConnection) {
$this->extractor = $extractor;
$this->entityTypeManager = $entityTypeManager;
$this->database = $dbConnection;
}
public function getEntityTypesToProcess() {
$fieldConfigs = $this->entityTypeManager
->getStorage('field_config')
->loadMultiple(NULL);
$entityTypes = [];
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;
}
public function processEntities($numberOfItems = 20) {
$entityTypes = $this
->getEntityTypesToProcess();
$numberOfProcessedItems = 0;
foreach ($entityTypes as $entityTypeData) {
$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;
}
public function getTotalEntitiesToProcess() {
$entityTypes = $this
->getEntityTypesToProcess();
$total = 0;
foreach ($entityTypes as $entityTypeData) {
$entityType = $entityTypeData['entity_type'];
$bundle = $entityTypeData['bundle'];
$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;
}
public function getNumberOfProcessedEntities() {
$query = $this->database
->select('linkchecker_index', 'i');
$query
->fields('i');
$query = $query
->countQuery();
$total = $query
->execute()
->fetchField();
return $total;
}
public function batch() {
$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());
}
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;
}
}
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.'));
}
}
}