diff --git a/alpha_pagination.services.yml b/alpha_pagination.services.yml index 45a3fd05221b158e7a43a4cc5eacdc51f7a58fd5..8f79479ec1e7983027c9f628e73bc8699c0065cb 100644 --- a/alpha_pagination.services.yml +++ b/alpha_pagination.services.yml @@ -1,4 +1,4 @@ services: alpha_pagination: class: Drupal\alpha_pagination\AlphaPagination - arguments: ['@entity_field.manager', '@language_manager', '@module_handler', '@cache.default', '@transliteration', '@database', '@token'] + arguments: ['@entity_type.manager', '@entity_field.manager', '@language_manager', '@module_handler', '@cache.default', '@transliteration', '@database', '@token', '@path.current'] diff --git a/src/AlphaPagination.php b/src/AlphaPagination.php index 801819cfb9424ec0b41b4ce09a447f132a9521b2..5bb1bb292a68b4f610d687dcc8a1a1d9556699b9 100644 --- a/src/AlphaPagination.php +++ b/src/AlphaPagination.php @@ -8,9 +8,11 @@ use Drupal\Component\Transliteration\TransliterationInterface; use Drupal\Component\Utility\Crypt; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Database\Connection; +use Drupal\Core\Entity\entityTypeManagerInterface; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Language\LanguageManagerInterface; +use Drupal\Core\Path\CurrentPathStack; use Drupal\Core\Utility\Token; use Drupal\views\Views; use Drupal\views\Plugin\views\ViewsHandlerInterface; @@ -27,6 +29,13 @@ class AlphaPagination { */ protected $handler; + /** + * The Entity Manager Interface. + * + * @var \Drupal\Core\Entity\entityTypeManagerInterface + */ + protected $entityTypeManager; + /** * The Entity Field Manager Interface. * @@ -83,9 +92,18 @@ class AlphaPagination { */ protected $url; + /** + * The current path stack. + * + * @var \Drupal\Core\Path\CurrentPathStack + */ + protected $currentPath; + /** * Contructs the AlphaPagination object. * + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager + * The Entity Manager Interface. * @param \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager * The Entity Field Manager Interface. * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager @@ -101,7 +119,8 @@ class AlphaPagination { * @param \Drupal\Core\Utility\Token $token * The token service. */ - public function __construct(EntityFieldManagerInterface $field_manager, LanguageManagerInterface $language_manager, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, TransliterationInterface $transliteration, Connection $database, Token $token) { + public function __construct(EntityTypeManagerInterface $entity_manager, EntityFieldManagerInterface $field_manager, LanguageManagerInterface $language_manager, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, TransliterationInterface $transliteration, Connection $database, Token $token, CurrentPathStack $current_path) { + $this->entityTypeManager = $entity_manager; $this->fieldManager = $field_manager; $this->language = $language_manager->getCurrentLanguage()->getId(); $this->moduleHandler = $module_handler; @@ -109,6 +128,7 @@ class AlphaPagination { $this->transliteration = $transliteration; $this->database = $database; $this->token = $token; + $this->currentPath = $current_path; } /** @@ -140,7 +160,7 @@ class AlphaPagination { * {@inheritdoc} */ public function __wakeup() { - list($name, $display_id, $type, $id, $language) = explode(':', $this->_handler); + [$name, $display_id, $type, $id, $language] = explode(':', $this->_handler); $view = Views::getView($name); $view->setDisplay($display_id); $this->handler = $view->display_handler->getHandler($type, $id); @@ -580,42 +600,45 @@ class AlphaPagination { $prefixes = []; if ($entity_ids = $this->getEntityIds()) { + $paginate_view_field = $this->getOption('paginate_view_field'); switch ($this->getOption('paginate_view_field')) { case 'name': - $table = $this->handler->view->storage->get('base_table'); - $where = $this->handler->view->storage->get('base_field'); - - // Extract the "name" field from the entity property info. - $entity_type = $this->handler->view->getBaseEntityType->id(); - $entity_info = $this->fieldManager->getBaseFieldDefinitions($entity_type); - $field = isset($entity_info['properties']['name']['schema field']) ? $entity_info['properties']['name']['schema field'] : 'name'; - break; - case 'title': $table = $this->handler->view->storage->get('base_table'); $where = $this->handler->view->storage->get('base_field'); - // Extract the "title" field from the entity property info. - $entity_type = $this->handler->view->getBaseEntityType()->id(); - $entity_info = $this->fieldManager->getBaseFieldDefinitions($entity_type); - $field = isset($entity_info['properties']['title']['schema field']) ? $entity_info['properties']['title']['schema field'] : 'title'; + $entity_type_id = $this->handler->view->getBaseEntityType()->id(); + /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */ + $entity_storage = $this->entityTypeManager->getStorage($entity_type_id); + $table_mapping = $entity_storage->getTableMapping(); + $field = $table_mapping->getColumnNames($paginate_view_field) !== null ? $table_mapping->getColumnNames($paginate_view_field)["value"] : $paginate_view_field; break; default: - if (strpos($this->getOption('paginate_view_field'), ':') === FALSE) { + [$entity_type_id, $field_name] = explode('__', $paginate_view_field, 2); + $entity_info = $this->fieldManager->getBaseFieldDefinitions($entity_type_id); + if (isset($entity_info[$field_name])) { + // Format field name and table for base field + $table = $this->handler->view->storage->get('base_table'); + $where = $this->handler->view->storage->get('base_field'); + /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */ + $entity_storage = $this->entityTypeManager->getStorage($entity_type_id); + $table_mapping = $entity_storage->getTableMapping(); + $field = $table_mapping->getColumnNames($field_name) !== null ? $table_mapping->getColumnNames($field_name)["value"] : $field_name; + } + elseif (strpos($paginate_view_field, ':') === FALSE) { // Format field name and table for single value fields. - list($entityType, $field_name) = explode('__', $this->getOption('paginate_view_field'), 2); $field = $field_name . '_value'; - $table = $this->getOption('paginate_view_field'); + $table = $paginate_view_field; + $where = 'entity_id'; } else { // Format field name and table for compound value fields. - list($entityType, $field_name) = explode('__', $this->getOption('paginate_view_field'), 2); $field = str_replace(':', '_', $field_name); $field_name_components = explode(':', $field_name); $table = $field_name_components[0]; + $where = 'entity_id'; } - $where = 'entity_id'; break; } $result = $this->database->query('SELECT DISTINCT(SUBSTR(' . $field . ', 1, 1)) AS prefix @@ -770,18 +793,7 @@ class AlphaPagination { // Don't bother working if there's nothing to do: if (empty($path) || (empty($args) && strpos($path, '%') === FALSE)) { - $path = \Drupal::service('path.current')->getPath(); - $pieces = explode('/', $path); - // If getPath returns heading slash, remove it as it will ba - // added later. - if ($pieces[0] == '') { - array_shift($pieces); - } - if (array_key_exists(end($pieces), $this->getCharacters())) { - array_pop($pieces); - } - $this->url = implode('/', $pieces); - return $this->url; + return $this->getUrlPieced(); } $pieces = []; @@ -798,8 +810,8 @@ class AlphaPagination { $pieces[] = $this->handler->view->argument[$id]->options['exception']['value']; } else { - // Gotta put something if there just isn't one. - $pieces[] = '*'; + // Get current path if arguments are multiple. + return $this->getUrlPieced(); } } else { @@ -872,7 +884,7 @@ class AlphaPagination { $parts = explode(',', $string); foreach ($parts as $attribute) { if (strpos($attribute, '|') !== FALSE) { - list($key, $value) = explode('|', $this->token->replace($attribute, $tokens, ['clear' => TRUE])); + [$key, $value] = explode('|', $this->token->replace($attribute, $tokens, ['clear' => TRUE])); $attributes[$key] = $value; } } @@ -920,4 +932,22 @@ class AlphaPagination { return $errors["$name:$display_id"]; } + /** + * @return \Drupal\Core\Url|string + */ + public function getUrlPieced(): \Drupal\Core\Url|string { + $path = \Drupal::service('path.current')->getPath(); + $pieces = explode('/', $path); + // If getPath returns heading slash, remove it as it will ba + // added later. + if ($pieces[0] == '') { + array_shift($pieces); + } + if (array_key_exists(end($pieces), $this->getCharacters())) { + array_pop($pieces); + } + $this->url = implode('/', $pieces); + return $this->url; + } + } diff --git a/src/AlphaPaginationCharacter.php b/src/AlphaPaginationCharacter.php index a825a714443315d06c9e99af2075d652ba876152..aa1162c5e996701e08e4506b0d148636370c9b11 100644 --- a/src/AlphaPaginationCharacter.php +++ b/src/AlphaPaginationCharacter.php @@ -117,9 +117,14 @@ class AlphaPaginationCharacter { $tokens = $this->alphaPagination->getTokens($this->getValue()); $path = $token->replace($this->getOption('paginate_link_path'), $tokens); // Determine if link is external (automatically enforcing for anchors). - if ($this->getOption('paginate_link_external') || ($path && $path[0] === '#')) { + if ($this->getOption('paginate_link_external') && ($path && $path[0] ==! '#')) { $options['external'] = TRUE; - }else{ + } + elseif ($path && $path[0] === '#'){ + $options['fragment'] = substr($path, 1); + $path = 'internal:'; + } + else { $path = 'internal:/'.$path; } // Add in additional attributes. diff --git a/src/Plugin/views/area/AlphaPaginationArea.php b/src/Plugin/views/area/AlphaPaginationArea.php index 93ae781f02daeb38eb64022287e796ddb2d8fe4b..afd7f7eb40a3f9fedae9f8e1375928a5427e975d 100644 --- a/src/Plugin/views/area/AlphaPaginationArea.php +++ b/src/Plugin/views/area/AlphaPaginationArea.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\views\Plugin\views\area\AreaPluginBase; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\field\Entity\FieldStorageConfig; /** * Views area handler to display alphabetic pagination. @@ -222,7 +223,7 @@ class AlphaPaginationArea extends AreaPluginBase { // Global options. $base_table = $this->view->storage->get('base_table'); - if ($base_table == 'taxonomy_term_data' || $base_table == 'media_field_data') { + if ($base_table == 'taxonomy_term_field_data' || $base_table == 'media_field_data') { // Get an array list of all non-image, non-entity or other assorted // reference fields. $fields = ['name' => 'name']; @@ -234,15 +235,16 @@ class AlphaPaginationArea extends AreaPluginBase { } $compound_field_types = ['name']; - $single_field_types = ['text', 'text_long', 'text_with_summary', 'string', 'string_long']; + $single_field_types = ['string', 'string_long']; // 'text', 'text_long', 'text_with_summary', can be added but + // they will probably contain HTML tags that will be caught as first character (except if we strit tags + // in AlphaPagination:getEntityPrefixes but that would be heavy on performance) $all_field_types = array_merge($single_field_types, $compound_field_types); $all_fields = $this->fieldManager->getFieldMap(); $baseEntityType = $this->view->getBaseEntityType()->id(); foreach ($all_fields[$baseEntityType] as $field_name => $field_definition) { if (in_array($field_definition['type'], $all_field_types)) { if (in_array($field_definition['type'], $compound_field_types)) { - $field_info = FieldStorageConfig::loadByName('node', $field_name); - $field_info = field_info_field($field_name); + $field_info = FieldStorageConfig::loadByName($baseEntityType, $field_name); foreach (array_keys($field_info['columns']) as $compoundFieldKey) { $compound_field_field_name = sprintf('%s:%s', $field_name, $compoundFieldKey); $fields[$baseEntityType . '__' . $compound_field_field_name] = $compound_field_field_name;