Commit b78f496a authored by generalredneck's avatar generalredneck

Moving the common functionalities from the .module file to the VNS service.

parent e7d419cf
......@@ -29,12 +29,14 @@ class IndexRecord {
}
public function setEntityType($entity_type) {
$this->entityType = $entity_type;
$this->generateType();
}
public function getEntityType() {
return $this->entityType;
}
public function setField($field) {
$this->field = $field;
$this->generateType();
}
public function getField() {
return $this->field;
......@@ -64,6 +66,12 @@ class IndexRecord {
}
return substr($transformed_content, 0, 255);
}
private function generateType() {
$this->type = new IndexRecordType($this->entityType, $this->field);
}
public function getType() {
return $this->type;
}
public function save() {
$this->database->merge('views_natural_sort')
......
<?php
namespace Drupal\views_natural_sort;
class IndexRecordType {
protected $entityType;
protected $field;
public function __construct($entity_type_id, $field_machine_name) {
$this->setEntityType($entity_type_id);
$this->setField($field_machine_name);
}
public function getEntityType() {
return $this->entityType;
}
public function setEntityType($entity_type_id) {
$this->entityType = $entity_type_id;
}
public function getField() {
return $this->field;
}
public function setField($field_machine_name) {
$this->field = $field_machine_name;
}
}
......@@ -8,25 +8,38 @@ use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Database\Connection;
use Drupal\views_natural_sort\Plugin\IndexRecordContentTransformationManager as TransformationManager;
use Drupal\views\ViewsData;
use Drupal\Core\Queue\QueueWorkerManagerInterface;
use Drupal\Core\Queue\QueueFactory;
/**
* Service that manages Views Natural Sort records.
*/
class ViewsNaturalSortService {
public $config;
/**
* Constructor.
*/
public function __construct(TransformationManager $transformationManager, ConfigFactory $configFactory, ModuleHandlerInterface $moduleHandler, LoggerChannelFactory $loggerFactory, Connection $database) {
public function __construct(TransformationManager $transformationManager, ConfigFactory $configFactory, ModuleHandlerInterface $moduleHandler, LoggerChannelFactory $loggerFactory, Connection $database, ViewsData $viewsData, QueueFactory $queue, QueueWorkerManagerInterface $queueManager) {
$this->configFactory = $configFactory;
$this->moduleHandler = $moduleHandler;
$this->loggerFactory = $loggerFactory->get('views_natural_sort');
$this->transformationManager = $transformationManager;
$this->database = $database;
$this->viewsData = $viewsData;
$this->queue = $queue;
$this->queueManager = $queueManager;
}
/**
* Get the full list of transformations to run when saving an index record.
*
* @param \Drupal\views_natural_sort\IndexRecord $record
* The original entry to be written to the views_natural_sort table.
*
* @return array
* The final list of transformations.
*/
public function getTransformations(IndexRecord $record) {
$transformations = $this->getDefaultTransformations();
$this->moduleHandler->alter('views_natural_sort_transformations', $transformations, $record);
......@@ -51,6 +64,52 @@ class ViewsNaturalSortService {
return $transformations;
}
/**
* Retrieve the full list of entities and properties that can be supported.
*
* @return array
* An array of property information keyed by entity machine name. Example:
* [
* 'node' => [
* 'type' => [
* 'base_table' => 'node',
* 'schema_field' => 'type',
* ]
* 'title' => [
* 'base_table' => 'node',
* 'schema_field' => 'title',
* ]
* 'language' => [
* 'base_table' => 'node',
* 'schema_field' => 'language',
* ]
* ]
* 'user' => [
* 'name' => [
* 'base_table' => 'users',
* 'schema_field' => 'name',
* ]
* 'mail' => [
* 'base_table' => 'users',
* 'schema_field' => 'mail',
* ]
* 'theme' => [
* 'base_table' => 'users',
* 'schema_field' => 'theme',
* ]
* ]
* 'file' => [
* 'name' => [
* 'base_table' => 'file_managed',
* 'schema_field' => 'filename',
* ]
* 'mime' => [
* 'base_table' => 'file_managed',
* 'schema_field' => 'filemime',
* ]
* ]
* )
*/
public function getSupportedEntityProperties() {
static $supported_properties = [];
if (empty($supported_properties)) {
......@@ -66,9 +125,31 @@ class ViewsNaturalSortService {
return $supported_properties;
}
public function getViewsSupportedEntityProperties() {
static $views_supported_properties = [];
if (empty($views_supported_properties)) {
$supported_entity_properties = $this->getSupportedEntityProperties();
$views_data = $this->viewsData->getAll();
if (empty($views_data)) {
return FALSE;
}
foreach ($supported_entity_properties as $entity => $properties) {
foreach ($properties as $property => $schema_info) {
if (!empty($views_data[$schema_info['base_table']][$schema_info['schema_field']]) &&
!empty($views_data[$schema_info['base_table']][$schema_info['schema_field']]['sort']) &&
!empty($views_data[$schema_info['base_table']][$schema_info['schema_field']]['sort']['handler']) &&
in_array($views_data[$schema_info['base_table']][$schema_info['schema_field']]['sort']['handler'], array('views_natural_sort_handler_sort', 'views_handler_sort'))) {
$views_supported_properties[$entity][$property] = $schema_info;
}
}
}
}
return $views_supported_properties;
}
public function storeIndexRecordsFromEntity(EntityInterface $entity) {
$entity_type = $entity->getEntityTypeId();
$supported_entity_properties = $this->getSupportedEntityProperties();
$supported_entity_properties = $this->getViewsSupportedEntityProperties();
foreach ($supported_entity_properties[$entity_type] as $field => $field_info) {
if (!isset($entity->{$field})) {
continue;
......@@ -87,6 +168,82 @@ class ViewsNaturalSortService {
}
}
public function queueDataForRebuild(array $entry_types = []) {
if (empty($entry_types)) {
$entry_types = $this->moduleHandler->invokeAll('views_natural_sort_get_entry_types');
}
$queues = [];
foreach ($entry_types as $entry_type) {
$queues = array_unique(array_merge($queues, array_filter($this->moduleHandler->invokeAll('views_natural_sort_queue_rebuild_data', $entry_type))));
}
$operations = [];
foreach ($queues as $queue) {
$operations[] = [
[$this, 'rebuildIndex'],
[$queue],
];
}
$batch = [
'operations' => $operations,
'title' => t('Rebuilding Views Natural Sort Indexing Entries'),
'finished' => [$this, 'finishRebuild'],
];
batch_set($batch);
}
public function rebuildIndex($queue_name, &$context) {
/** @var QueueInterface $queue */
$queue = $this->queueFactory->get($queue_name);
/** @var QueueWorkerInterface $queue_worker */
$queue_worker = $this->queueManager->createInstance($queue_name);
$config = $this->configFactory->get('views_natural_sort.settings');
// Alias sandbox for easier referencing.
$sandbox = &$context['sandbox'];
// Alias results for easier referencing.
$results = &$context['results'];
if (empty($sandbox)) {
$sandbox['current'] = 0;
$sandbox['max'] = $queue->numberOfItems();
$sandbox['items_per_batch'] = $config->get('rebuild_items_per_batch');
}
for ($i = 0; $i < $sandbox['items_per_batch'] && $sandbox['current'] < $sandbox['max']; $i++) {
while($item = $queue->claimItem()) {
try {
$queue_worker->processItem($item->data);
$queue->deleteItem($item);
}
catch (SuspendQueueException $e) {
$queue->releaseItem($item);
break;
}
catch (\Exception $e) {
watchdog_exception('npq', $e);
}
}
$item = $queue->claimItem(10);
if ($item) {
views_natural_sort_process_index_queue($item->data);
$queue->deleteItem($item);
}
$sandbox['current']++;
}
$results['entries'] = $sandbox['current'];
if ($sandbox['current'] != $sandbox['max']) {
$context['finished'] = $sandbox['current'] / $sandbox['max'];
}
}
public function finishRebuild($success, $results, $operations) {
if ($success) {
drupal_set_message($this->t('Index rebuild has completed.'));
drupal_set_message($this->t('Indexed %count.', [
'%count' => format_plural($results['entries'], '1 entry', '@count entries'),
]));
}
}
public function createIndexRecord(array $values = []) {
$record = new IndexRecord($this->database, $values);
$transformations = $this->getTransformations($record);
......
......@@ -7,6 +7,7 @@
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\views_natural_sort\IndexRecordType;
/**
* Implements hook_help().
......@@ -54,36 +55,25 @@ function views_natural_sort_views_natural_sort_get_entry_types() {
}
/**
* Implements hook_views_natural_sort_get_rebuild_data();
* @Not-Rewritten
* Implements hook_views_natural_sort_queue_rebuild_data().
*/
function views_natural_sort_views_natural_sort_get_rebuild_data($entry_type){
$supported_entity_properties = views_natural_sort_get_views_configurable_properties();
if (empty($supported_entity_properties[$entry_type['entity_type']]) ||
empty($supported_entity_properties[$entry_type['entity_type']][$entry_type['field']])) {
return array();
}
$query = Drupal::entityQuery($entity_type['entity_type']);
function views_natural_sort_views_natural_sort_queue_rebuild_data(IndexRecordType $entry_type){
$service = Drupal::service('views_natural_sort.service');
$supported_entity_properties = $service->getViewsSupportedEntityProperties();
$entity_type = $entry_type->getEntityType();
$field = $entry_type->getField();
if (empty($supported_entity_properties[$entity_type]) ||
empty($supported_entity_properties[$entity_type][$field])) {
return;
}
$queue = Drupal::queue('views_natural_sort_entity_index');
$query = Drupal::entityQuery($entity_type);
$entity_ids = $query->execute();
$storage = \Drupal::entityManager()->getStorage($entity_type['entity_type']);
$data = array();
foreach ($entity_ids as $entity_id) {
$entity = $storage->load($entity_id);
$data[] = array(
'eid' => $entity_id,
'entity_type' => $entry_type['entity_type'],
'field' => $entry_type['field'],
'delta' => 0,
'content' => $entity->{$entry_type['field']}->getValue(),
);
$queue->createItem($entity_id);
}
return $data;
return 'views_natural_sort_entity_index';
}
/**
......@@ -93,7 +83,7 @@ function views_natural_sort_views_natural_sort_get_rebuild_data($entry_type){
*/
function views_natural_sort_entity_insert(EntityInterface $entity) {
$service = Drupal::service('views_natural_sort.service');
$supported_entity_properties = $service->getSupportedEntityProperties();
$supported_entity_properties = $service->getViewsSupportedEntityProperties();
if (isset($supported_entity_properties[$entity->getEntityTypeId()])) {
$service->storeIndexRecordsFromEntity($entity);
}
......@@ -120,62 +110,6 @@ function views_natural_sort_entity_delete(EntityInterface $entity) {
));
}
/**
* Store Multiple views_natural_sort entries
*
* @param array $index_entries
* An array of entries to store in the views_natural_sort table.
*
* @see views_natural_sort_store
* @Not-Rewritten
*/
function views_natural_sort_store_multiple(array $index_entries) {
foreach($index_entries as $entry) {
views_natural_sort_store($entry);
}
}
/**
* Save an entry to the database that represents a views_natural_sort index
*
* @param array $index_entry
* Mirrors the views_natural_sort table
* $eid - Entity Id of the item referenced
* $entity_type - The Entity Type. Ex. node
* $field - reference to the property or field name
* $delta - the item number in that field or property
* $content - The transformed data that a field will
* be sorted by.
* @Not-Rewritten
*/
function views_natural_sort_store(array $index_entry) {
// This should take a formatted object and store it into the views_natural_sort table.
$string = views_natural_sort_transform($index_entry);
// The size limit on the content field for views_natural_sort is sometimes not
// enough. Let's truncate all data down to that size. I personally feel the
// inaccuracy is an acceptable loss, as the bigger the string gets, the less
// permanent the sort.
//
// TODO: Have this pick up off of the schema so if someone does a
// hook_schema_alter() on me.
return db_merge('views_natural_sort')
->key(array(
'eid' => $index_entry['eid'],
'entity_type' => $index_entry['entity_type'],
'field' => $index_entry['field'],
'delta' => $index_entry['delta'],
))
->fields(array(
'eid' => $index_entry['eid'],
'entity_type' => $index_entry['entity_type'],
'field' => $index_entry['field'],
'delta' => $index_entry['delta'],
'content' => substr($string, 0, 255),
))
->execute();
}
/**
* Remove a views_natural_sort index entry based on keys
*
......@@ -202,123 +136,6 @@ function views_natural_sort_remove($index_entry) {
$query->execute();
}
/**
* Encodes a string into an ascii-sortable string such as:
* - Leading articles in common languages are ignored: The A An El La Le Il
* - Unimportant punctuation is ignored: # ' " ( )
* - Unimportant words are ignored: and of or
*
* @param array $index_entry
* Mirrors the views_natural_sort table
* $eid - Entity Id of the item referenced
* $entity_type - The Entity Type. Ex. node
* $field - reference to the property or field name
* $delta - the item number in that field or property
*
* @return string
* The transformed string
* @Not-Rewritten
*/
function views_natural_sort_transform($index_entry) {
// Get copy the original string.
$string = $index_entry['content'];
module_load_include('inc', 'views_natural_sort', 'views_natural_sort');
foreach (views_natural_sort_get_transformations($index_entry) as $transformation_method) {
$string = $transformation_method($string);
}
return $string;
}
/**
* Get the full list of transformations to run when saving a natural sort entry.
* @param array $index_entry
* The original entry to be written to the views_natural_sort table.
* $eid - Entity Id of the item referenced
* $entity_type - The Entity Type. Ex. node
* $field - reference to the property or field name
* $delta - the item number in that field or property
* $content - The transformed data that a field will
* be sorted by.
*
* @return array
* The final list of transformations.
* @STUBBED
*/
function views_natural_sort_get_transformations($index_entry) {
$transformations = array(
'views_natural_sort_remove_beginning_words',
'views_natural_sort_remove_words',
'views_natural_sort_remove_symbols',
'views_natural_sort_numbers',
);
// Allow other modules to modify the transformation that happens here if
// needed.
Drupal::moduleHandler()->alter('views_natural_sort_transformations', $transformations, $index_entry);
return $transformations;
}
/**
* Retrieve the full list of entities and properties that can be supported.
*
* @return array
* An array of property information keyed by entity machine name. Example:
* array (
* 'node' => array (
* 'type' => array (
* 'base_table' => 'node',
* 'schema_field' => 'type',
* ),
* 'title' => array (
* 'base_table' => 'node',
* 'schema_field' => 'title',
* ),
* 'language' => array (
* 'base_table' => 'node',
* 'schema_field' => 'language',
* ),
* ),
* 'user' => array (
* 'name' => array (
* 'base_table' => 'users',
* 'schema_field' => 'name',
* ),
* 'mail' => array (
* 'base_table' => 'users',
* 'schema_field' => 'mail',
* ),
* 'theme' => array (
* 'base_table' => 'users',
* 'schema_field' => 'theme',
* ),
* ),
* 'file' => array (
* 'name' => array (
* 'base_table' => 'file_managed',
* 'schema_field' => 'filename',
* ),
* 'mime' => array (
* 'base_table' => 'file_managed',
* 'schema_field' => 'filemime',
* ),
* ),
* )
* @STUBBED
*/
function views_natural_sort_get_supported_entity_properties() {
$supported_properties = &drupal_static(__FUNCTION__, array());
if (empty($supported_properties)) {
$supported_properties = [
'node' => [
'title' => [
'base_table' => 'node_field_data',
'schema_field' => 'title',
],
],
];
}
return $supported_properties;
}
/**
* Returns a list of properties that we know views will allow us to alter.
*
......@@ -341,33 +158,3 @@ function views_natural_sort_get_views_configurable_properties() {
}
return $supported_entity_properties;
}
/**
* A helper function for creating a VNS record for storage.
*
* @param stdClass $entity
* @param string $field
*
* @return array
* An array that represents the VNS table row to be inserted.
*/
function views_natural_sort_entity_to_vns(EntityInterface $entity, $field) {
$entity_type = $entity->getEntityTypeId();
$supported_entity_properties = views_natural_sort_get_views_configurable_properties();
if (empty($supported_entity_properties[$entity_type]) ||
empty($supported_entity_properties[$entity_type][$field])) {
throw new Exception("$entity_type -> $field doesn't exist. Cannot create Views Natural Sort record");
}
$data = [];
foreach ($entity->get($field)->getValue() as $delta => $value) {
$data[] = [
'eid' => $entity->id(),
'entity_type' => $entity_type,
'field' => $field,
'delta' => $delta,
// This may have to be passed in if it's not always ['value'].
'content' => $value['value'],
];
}
return $data;
}
......@@ -10,3 +10,6 @@ services:
- '@module_handler'
- '@logger.factory'
- '@database'
- '@views.views_data'
- '@queue'
- '@plugin.manager.queue_worker'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment