diff --git a/views_url_alias.module b/views_url_alias.module index 1440020..0e15cef 100644 --- a/views_url_alias.module +++ b/views_url_alias.module @@ -5,6 +5,7 @@ * Allows content entity Views to be filtered by path aliases. */ +use Drupal\Core\Batch\BatchBuilder; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; @@ -20,10 +21,15 @@ use Drupal\path_alias\PathAliasInterface; * @return \Drupal\Core\Entity\ContentEntityInterface|null * Returns the entity type. */ -function views_url_alias_get_path_entity_type(string $path): ?ContentEntityInterface { +function views_url_alias_get_path_entity_type(string $path) { /** @var \Drupal\Core\Routing\Router $router */ $router = \Drupal::service('router.no_access_checks'); - $result = $router->match($path); + // Guard against no match. + try { + $result = $router->match($path); + } catch (Exception $e) { + return NULL; + } /** @var \Symfony\Component\Routing\Route $route */ $route = $result['_route_object']; $params = $route->getOption('parameters'); @@ -197,16 +203,53 @@ function views_url_alias_save(EntityInterface $entity, $alias = NULL) { * This function typically only needs to be called when this module is * installed. */ -function views_url_alias_rebuild_path() { +function views_url_alias_rebuild_path(): void { $database = \Drupal::database(); // Purge view_url_alias table. $database->truncate('views_url_alias')->execute(); + + // Load all path IDs. + $path_ids = $database->select('path_alias', 'pa') + ->fields('pa', ['id']) + ->orderBy('id') + ->execute()->fetchCol(); + + // Split path IDs up in processable chunks. + $split_path_ids = array_chunk($path_ids, 50); + + // Create batch. + $batch_builder = (new BatchBuilder()) + ->setTitle(' Rebuilding the "view_url_alias"-table.') + ->setProgressMessage('Processed @current out of @total (@percentage%) chunks. Estimated time: @estimate.') + ->setErrorMessage('Step @current completed with an error.') + ->setFinishCallback('_views_url_alias_rebuild_path_finished'); + + // Fill batch. + foreach ($split_path_ids as $chunk) { + $batch_builder->addOperation('_views_url_alias_rebuild_path_process', [$chunk]); + } + + // Start batch. + batch_set($batch_builder->toArray()); +} + +/** + * Processes a chunk of path IDs. + * + * @param array $path_ids + * The path IDs to be processed. + * @param array $context + * The context. + * + * @throws Exception + */ +function _views_url_alias_rebuild_path_process (array $path_ids, array &$context): void { /** @var \Drupal\path_alias\PathAliasStorage $path_aliases */ $path_alias_storage = \Drupal::entityTypeManager()->getStorage('path_alias'); $languages = \Drupal::languageManager()->getLanguages(); /** @var \Drupal\path_alias\PathAliasInterface $path_alias $path_alias */ - foreach ($path_alias_storage->loadMultiple() as $path_alias) { + foreach ($path_alias_storage->loadMultiple($path_ids) as $path_alias) { foreach ($languages as $language) { if ($path_alias->hasTranslation($language->getId())) { $translated_path_alias = $path_alias->getTranslation($language->getId()); @@ -221,3 +264,23 @@ function views_url_alias_rebuild_path() { } } } + +/** + * Indicate if the batch processing was successful. + * + * @param $success + * The success flag. + * @param $results + * The results. + * @param $operations + * The operations. + */ +function _views_url_alias_rebuild_path_finished($success, $results, $operations): void { + // Setup final message after process is done. + if ($success) { + \Drupal::messenger()->addStatus(t('All paths have been processed.')); + } + else { + \Drupal::messenger()->addError(t('An error occurred while processing the paths.')); + } +}