views_natural_sort.module 6.92 KB
Newer Older
1 2 3
<?php

/**
4 5
 * @file
 * Contains views_natural_sort.module..
6 7
 */

8
use Drupal\Core\Routing\RouteMatchInterface;
9
use Drupal\Core\Entity\EntityInterface;
10
use Drupal\views_natural_sort\IndexRecordType;
11 12

/**
13
 * Implements hook_help().
14
 */
15 16 17 18
function views_natural_sort_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    // Main module help for the views_natural_sort module.
    case 'help.page.views_natural_sort':
19 20
      $output = '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('Sort results naturally on a node&#039;s title skipping articles like &quot;the&quot; and &quot;a.&quot;') . '</p>';
21 22 23
      return $output;

    default:
24 25 26
  }
}

27 28 29
/**
 * Implements hook_module_implements_alter().
 */
30 31 32 33 34 35
function views_natural_sort_module_implements_alter(&$implements, $hook) {
  if ($hook == 'views_data_alter') {
    // Make views natural sort always last so we get all the up to date info.
    $group = $implements['views_natural_sort'];
    unset($implements['views_natural_sort']);
    $implements['views_natural_sort'] = $group;
36 37
  }
}
38 39 40

/**
 * Implements hook_views_natural_sort_get_entry_types().
generalredneck's avatar
generalredneck committed
41
 *
42 43 44
 * @Not-Rewritten
 */
function views_natural_sort_views_natural_sort_get_entry_types() {
45
  $service = Drupal::service('views_natural_sort.service');
46
  /*
47
  $supported_entity_properties = $service->getViewsSupportedEntityProperties();
48
  $entry_types = [];
49 50
  foreach ($supported_entity_properties as $entity_type => $properties) {
    foreach ($properties as $property => $schema_info) {
51
      $entry_types = new IndexRecordType($entity_type, $property);
52
    }
53 54 55
  }*/
  $service->getEntryTypes();

56 57 58 59
  return $entry_types;
}

/**
60
 * Implements hook_views_natural_sort_queue_rebuild_data().
61
 */
generalredneck's avatar
generalredneck committed
62
function views_natural_sort_views_natural_sort_queue_rebuild_data(IndexRecordType $entry_type) {
63 64
  $service = Drupal::service('views_natural_sort.service');
  $supported_entity_properties = $service->getViewsSupportedEntityProperties();
65 66
  $entity_type = $entry_type->getEntityType();
  $field = $entry_type->getField();
67

68 69 70
  if (empty($supported_entity_properties[$entity_type]) ||
    empty($supported_entity_properties[$entity_type][$field])) {
    return;
71
  }
72 73 74 75 76 77
  $queue = Drupal::queue('views_natural_sort_entity_index');
  $query = Drupal::entityQuery($entity_type);
  $entity_ids = $query->execute();
  foreach ($entity_ids as $entity_id) {
    $queue->createItem([
      'entity_type' => $entity_type,
generalredneck's avatar
generalredneck committed
78
      'entity_id' => $entity_id,
79 80 81
    ]);
  }
  return 'views_natural_sort_entity_index';
82 83 84 85 86 87 88 89
}

/**
 * Implements hook_entity_insert().
 *
 * This keeps our natural sort index up to date.
 */
function views_natural_sort_entity_insert(EntityInterface $entity) {
90
  $service = Drupal::service('views_natural_sort.service');
91
  $supported_entity_properties = $service->getViewsSupportedEntityProperties();
92 93
  if (isset($supported_entity_properties[$entity->getEntityTypeId()])) {
    $service->storeIndexRecordsFromEntity($entity);
94 95 96 97
  }
}

/**
generalredneck's avatar
generalredneck committed
98
 * Implements hook_entity_update().
99 100 101 102 103 104 105 106
 *
 * This keeps our natural sort index up to date.
 */
function views_natural_sort_entity_update(EntityInterface $entity) {
  views_natural_sort_entity_insert($entity);
}

/**
generalredneck's avatar
generalredneck committed
107
 * Implements hook_entity_delete().
108
 *
109
 * This keeps our natural sort index clean.
110 111
 */
function views_natural_sort_entity_delete(EntityInterface $entity) {
112
  views_natural_sort_remove($entry = [
113 114
    'eid' => $entity->id(),
    'entity_type' => $entity->getEntityTypeId(),
115
  ]);
116 117 118
}

/**
generalredneck's avatar
generalredneck committed
119
 * Remove a views_natural_sort index entry based on keys.
120 121 122 123 124 125 126
 *
 * @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 - (optional) reference to the property or field name
 *     $delta - (optional)the item number in that field or property
127
 *   If an optional parameter doesn't exist, this is treated as a wild card
generalredneck's avatar
generalredneck committed
128 129
 *   delete.
 *
130 131
 * @Not-Rewritten
 */
generalredneck's avatar
generalredneck committed
132
function views_natural_sort_remove(array $index_entry) {
133 134
  $query = \Drupal::database()
    ->delete('views_natural_sort')
135 136 137 138 139 140 141 142 143 144
    ->condition('eid', $index_entry['eid'])
    ->condition('entity_type', $index_entry['entity_type']);
  if (isset($index_entry['field'])) {
    $query->condition('field', $index_entry['field']);
  }
  if (isset($index_entry['delta'])) {
    $query->condition('delta', $index_entry['delta']);
  }
  $query->execute();
}
145

generalredneck's avatar
generalredneck committed
146 147 148 149 150 151
/**
 * Views_natural_sort_queue_data_for_rebuild description.
 *
 * @param array $entry_types
 *   Description.
 */
152 153 154 155 156
function views_natural_sort_queue_data_for_rebuild(array $entry_types = []) {
  $moduleHandler = \Drupal::moduleHandler();
  if (empty($entry_types)) {
    $entry_types = $moduleHandler->invokeAll('views_natural_sort_get_entry_types');
  }
157 158 159 160
  $queues = [];
  foreach ($entry_types as $entry_type) {
    $queues = array_unique(array_merge($queues, array_filter($moduleHandler->invokeAll('views_natural_sort_queue_rebuild_data', [$entry_type]))));
  }
161 162 163
  $operations = [];
  foreach ($queues as $queue) {
    $operations[] = [
164
      'views_natural_sort_rebuild_index',
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
      [$queue],
    ];
  }

  $batch = [
    'operations' => $operations,
    'title' => t('Rebuilding Views Natural Sort Indexing Entries'),
    'finished' => 'views_natural_sort_finish_rebuild',
  ];
  batch_set($batch);
}

function views_natural_sort_rebuild_index($queue_name, &$context) {
  /** @var QueueInterface $queue */
  $queue = \Drupal::queue($queue_name);
  /** @var QueueWorkerInterface $queue_worker */
  $queue_worker = \Drupal::service('plugin.manager.queue_worker')->createInstance($queue_name);
  $config = \Drupal::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++) {
194
    if ($item = $queue->claimItem(10)) {
195 196 197 198 199 200 201 202 203
      try {
        $queue_worker->processItem($item->data);
        $queue->deleteItem($item);
      }
      catch (SuspendQueueException $e) {
        $queue->releaseItem($item);
        break;
      }
      catch (\Exception $e) {
204
        watchdog_exception('views_natural_sort', $e);
205 206 207 208 209 210 211
      }
    }
    $sandbox['current']++;
  }
  $results['entries'] = $sandbox['current'];
  if ($sandbox['current'] != $sandbox['max']) {
    $context['finished'] = $sandbox['current'] / $sandbox['max'];
212
    $context['message'] = t('Processed %current out of %max records.', ['%current' => $sandbox['current'], '%max' => $sandbox['max']]);
213 214 215 216 217 218 219 220 221 222 223
  }
}

function views_natural_sort_finish_rebuild($success, $results, $operations) {
  if ($success) {
    drupal_set_message(t('Index rebuild has completed.'));
    drupal_set_message(t('Indexed %count.', [
      '%count' => \Drupal::translation()->formatPlural($results['entries'], '1 entry', '@count entries'),
    ]));
  }
}