View source
<?php
namespace Drupal\entity_usage;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\entity_track\EntityTrackStorageInterface;
use Drupal\entity_usage\Events\Events;
use Drupal\entity_usage\Events\EntityUsageEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class EntityUsage implements EntityUsageInterface, EntityTrackStorageInterface {
protected $connection;
protected $tableName;
protected $eventDispatcher;
protected $config;
protected $moduleHandler;
public function __construct(Connection $connection, EventDispatcherInterface $event_dispatcher, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, $table = 'entity_usage') {
$this->connection = $connection;
$this->tableName = $table;
$this->eventDispatcher = $event_dispatcher;
$this->moduleHandler = $module_handler;
$this->config = $config_factory
->get('entity_usage.settings');
}
public function registerUsage($target_id, $target_type, $source_id, $source_type, $source_langcode, $source_vid, $method, $field_name, $count = 1) {
$enabled_target_entity_types = $this->config
->get('track_enabled_target_entity_types');
if (is_array($enabled_target_entity_types) && !in_array($target_type, $enabled_target_entity_types, TRUE)) {
return;
}
$context = [
'target_id' => $target_id,
'target_type' => $target_type,
'source_id' => $source_id,
'source_type' => $source_type,
'source_langcode' => $source_langcode,
'source_vid' => $source_vid,
'method' => $method,
'field_name' => $field_name,
'count' => $count,
];
$abort = $this->moduleHandler
->invokeAll('entity_usage_block_tracking', $context);
if (in_array(TRUE, $abort, TRUE)) {
return;
}
$target_id_column = $this
->isInt($target_id) ? 'target_id' : 'target_id_string';
$source_id_column = $this
->isInt($source_id) ? 'source_id' : 'source_id_string';
if ($count <= 0) {
$this->connection
->delete($this->tableName)
->condition($target_id_column, $target_id)
->condition('target_type', $target_type)
->condition($source_id_column, $source_id)
->condition('source_type', $source_type)
->condition('source_langcode', $source_langcode)
->condition('source_vid', $source_vid)
->condition('method', $method)
->condition('field_name', $field_name)
->execute();
}
else {
$this->connection
->merge($this->tableName)
->keys([
$target_id_column => $target_id,
'target_type' => $target_type,
$source_id_column => $source_id,
'source_type' => $source_type,
'source_langcode' => $source_langcode,
'source_vid' => $source_vid ?: 0,
'method' => $method,
'field_name' => $field_name,
])
->fields([
'count' => $count,
])
->execute();
}
$event = new EntityUsageEvent($target_id, $target_type, $source_id, $source_type, $source_langcode, $source_vid, $method, $field_name, $count);
$this->eventDispatcher
->dispatch(Events::USAGE_REGISTER, $event);
}
public function bulkDeleteTargets($target_type) {
$query = $this->connection
->delete($this->tableName)
->condition('target_type', $target_type);
$query
->execute();
$event = new EntityUsageEvent(NULL, $target_type, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
$this->eventDispatcher
->dispatch(Events::BULK_DELETE_DESTINATIONS, $event);
}
public function bulkDeleteSources($source_type) {
$query = $this->connection
->delete($this->tableName)
->condition('source_type', $source_type);
$query
->execute();
$event = new EntityUsageEvent(NULL, NULL, NULL, $source_type, NULL, NULL, NULL, NULL, NULL);
$this->eventDispatcher
->dispatch(Events::BULK_DELETE_SOURCES, $event);
}
public function bulkDeleteAll() {
$query = $this->connection
->delete($this->tableName);
$query
->execute();
$event = new EntityUsageEvent(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
$this->eventDispatcher
->dispatch(Events::BULK_DELETE_ALL, $event);
}
public function deleteTrackingInformation() {
$this
->bulkDeleteAll();
}
public function deleteByField($source_type, $field_name) {
$query = $this->connection
->delete($this->tableName)
->condition('source_type', $source_type)
->condition('field_name', $field_name);
$query
->execute();
$event = new EntityUsageEvent(NULL, NULL, NULL, $source_type, NULL, NULL, NULL, $field_name, NULL);
$this->eventDispatcher
->dispatch(Events::DELETE_BY_FIELD, $event);
}
public function deleteBySourceEntity($source_id, $source_type, $source_langcode = NULL, $source_vid = NULL) {
$source_id_column = $this
->isInt($source_id) ? 'source_id' : 'source_id_string';
$query = $this->connection
->delete($this->tableName)
->condition($source_id_column, $source_id)
->condition('source_type', $source_type);
if ($source_langcode) {
$query
->condition('source_langcode', $source_langcode);
}
if ($source_vid) {
$query
->condition('source_vid', $source_vid);
}
$query
->execute();
$event = new EntityUsageEvent(NULL, NULL, $source_id, $source_type, $source_langcode, $source_vid, NULL, NULL, NULL);
$this->eventDispatcher
->dispatch(Events::DELETE_BY_SOURCE_ENTITY, $event);
}
public function deleteByTargetEntity($target_id, $target_type) {
$target_id_column = $this
->isInt($target_id) ? 'target_id' : 'target_id_string';
$query = $this->connection
->delete($this->tableName)
->condition($target_id_column, $target_id)
->condition('target_type', $target_type);
$query
->execute();
$event = new EntityUsageEvent($target_id, $target_type, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
$this->eventDispatcher
->dispatch(Events::DELETE_BY_TARGET_ENTITY, $event);
}
public function listSources(EntityInterface $target_entity, $nest_results = TRUE) {
$target_id_column = $this
->isInt($target_entity
->id()) ? 'target_id' : 'target_id_string';
$result = $this->connection
->select($this->tableName, 'e')
->fields('e', [
'source_id',
'source_id_string',
'source_type',
'source_langcode',
'source_vid',
'method',
'field_name',
'count',
])
->condition($target_id_column, $target_entity
->id())
->condition('target_type', $target_entity
->getEntityTypeId())
->condition('count', 0, '>')
->orderBy('source_type')
->orderBy('source_id', 'DESC')
->orderBy('source_vid', 'DESC')
->orderBy('source_langcode')
->execute();
$references = [];
foreach ($result as $usage) {
$source_id_value = !empty($usage->source_id) ? (string) $usage->source_id : (string) $usage->source_id_string;
if ($nest_results) {
$references[$usage->source_type][$source_id_value][] = [
'source_langcode' => $usage->source_langcode,
'source_vid' => $usage->source_vid,
'method' => $usage->method,
'field_name' => $usage->field_name,
'count' => $usage->count,
];
}
else {
$references[] = [
'source_type' => $usage->source_type,
'source_id' => $source_id_value,
'source_langcode' => $usage->source_langcode,
'source_vid' => $usage->source_vid,
'method' => $usage->method,
'field_name' => $usage->field_name,
'count' => $usage->count,
];
}
}
return $references;
}
public function listTargets(EntityInterface $source_entity) {
$source_id_column = $this
->isInt($source_entity
->id()) ? 'source_id' : 'source_id_string';
$result = $this->connection
->select($this->tableName, 'e')
->fields('e', [
'target_id',
'target_id_string',
'target_type',
'method',
'field_name',
'count',
])
->condition($source_id_column, $source_entity
->id())
->condition('source_type', $source_entity
->getEntityTypeId())
->condition('count', 0, '>')
->orderBy('target_id', 'DESC')
->execute();
$references = [];
foreach ($result as $usage) {
$target_id_value = !empty($usage->target_id) ? $usage->target_id : $usage->target_id_string;
$references[$usage->target_type][(string) $target_id_value][] = [
'method' => $usage->method,
'field_name' => $usage->field_name,
'count' => $usage->count,
];
}
return $references;
}
protected function isInt($value) {
return (string) (int) $value === (string) $value && strlen($value) < 11;
}
public function listUsage(EntityInterface $entity, $include_method = FALSE) {
$result = $this
->listSources($entity);
$references = [];
foreach ($result as $source_entity_type => $entity_record) {
foreach ($entity_record as $entity_id => $records) {
foreach ($records as $record) {
if ($include_method) {
if (empty($references[$record['method']][$source_entity_type][$entity_id])) {
$references[$record['method']][$source_entity_type][$entity_id] = $record['count'];
}
else {
$references[$record['method']][$source_entity_type][$entity_id] += $record['count'];
}
}
else {
if (empty($references[$source_entity_type][$entity_id])) {
$references[$source_entity_type][$entity_id] = $record['count'];
}
else {
$references[$source_entity_type][$entity_id] += $record['count'];
}
}
}
}
}
return $references;
}
public function listReferencedEntities(EntityInterface $entity) {
$result = $this
->listTargets($entity);
$references = [];
foreach ($result as $target_entity_type => $entity_record) {
foreach ($entity_record as $entity_id => $records) {
foreach ($records as $record) {
if (empty($references[$target_entity_type][$entity_id])) {
$references[$target_entity_type][$entity_id] = $record['count'];
}
else {
$references[$target_entity_type][$entity_id] += $record['count'];
}
}
}
}
return $references;
}
}