request = clone $request;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('request_stack')->getMainRequest()
);
}
/**
* {@inheritdoc}
*/
public function build() {
$id = $this->getDerivativeId();
[$view_id, $display_id] = $this->getViewAndDisplayIdentifiers();
$view = View::Load($view_id);
$view_executable = $view->getExecutable();
$view_executable->setDisplay($display_id);
// Allow advanced search to alter the query.
$advanced_search_query = new AdvancedSearchQuery();
$advanced_search_query->alterView($this->request, $view_executable, $display_id);
$view_executable->execute();
$pager = $view_executable->getPager();
$exposed_input = $view_executable->getExposedInput();
$query_parameters = $this->request->query->all();
$build = [
'#attached' => [
'drupalSettings' => [
'advanced_search_pager_views_ajax' => [
$id => [
'view_id' => $view_id,
'current_display_id' => $display_id,
'ajax_path' => '/views/ajax',
],
],
],
],
'#attributes' => [
'class' => ['advanced_search_result_pager'],
'data-drupal-pager-id' => $id,
],
'result_summary' => $this->buildResultsSummary($view_executable),
'container' => [
'#prefix' => '
',
'results_per_page_links' => $this->buildResultsPerPageLinks($pager, $query_parameters),
'display_links' => $this->buildDisplayLinks($query_parameters),
'sort_by' => $this->buildSortByForm($view_executable->sort, $query_parameters),
'pager' => array_merge($pager->render($exposed_input), ['#wrapper_attributes' => ['class' => ['container']]]),
],
];
return $build;
}
/**
* Build the results summary portion of the pager.
*
* @param Drupal\views\ViewExecutable $view_executable
* The view to build the summary for.
*
* @return array
* A renderable array that represents the current page, and number of
* results in the view.
*/
protected function buildResultsSummary(ViewExecutable $view_executable) {
$current_page = (int) $view_executable->getCurrentPage() + 1;
$per_page = (int) $view_executable->getItemsPerPage();
$total = $view_executable->total_rows ?? count($view_executable->result);
// If there is no result the "start" and "current_record_count" should be
// equal to 0. To have the same calculation logic, we use a "start offset"
// to handle all the cases.
$start_offset = empty($total) ? 0 : 1;
if ($per_page === 0) {
$start = $start_offset;
$end = $total;
}
else {
$total_count = $current_page * $per_page;
if ($total_count > $total) {
$total_count = $total;
}
$start = ($current_page - 1) * $per_page + $start_offset;
$end = $total_count;
}
if (!empty($total)) {
// Return as render array.
return [
'#prefix' => '',
'#markup' => $this->t('Displaying @start - @end of @total', [
'@start' => $start,
'@end' => $end,
'@total' => $total,
]),
];
}
return [];
}
/**
* Build the results per page portion of the pager.
*
* @param Drupal\views\Plugin\views\pager\SqlBase $pager
* The pager for the view.
* @param array $query_parameters
* The query parameters used to change the number of results per page.
*
* @return array
* A renderable array representing the results per page portion of pager.
*/
protected function buildResultsPerPageLinks(SqlBase $pager, array $query_parameters) {
$active_items_per_page = $query_parameters['items_per_page'] ?? $pager->options['items_per_page'];
$items_per_page_options = array_map(function ($value) {
return trim($value);
}, explode(',', $pager->options['expose']['items_per_page_options']));
$items = [];
foreach ($items_per_page_options as $items_per_page) {
$url = Url::fromRoute('', [], [
// When changing the number of items displayed always return the user
// to the first page.
'query' => array_merge($query_parameters, [
'items_per_page' => $items_per_page,
'page' => 0,
]),
'absolute' => TRUE,
]);
$active = $items_per_page == $active_items_per_page;
$items[] = [
'#type' => 'link',
'#url' => $url,
'#title' => $items_per_page,
'#attributes' => [
'aria-label' => $this->t("@item items per page", ["@item" => $items_per_page]),
'class' => $active ?
['pager__link', 'pager__link--is-active', 'pager__itemsperpage'] :
['pager__link', 'pager__itemsperpage'],
],
'#wrapper_attributes' => [
'class' => $active ? ['pager__item', 'is-active'] : ['pager__item'],
],
];
}
return [
'#theme' => 'item_list',
'#title' => $this->t('Results per page'),
'#list_type' => 'ul',
'#items' => $items,
'#attributes' => [],
'#wrapper_attributes' => ['class' => ['pager__results', 'container']],
];
}
/**
* Build the display links portion of the pager (list/grid).
*
* @param array $query_parameters
* The query parameters used to change the display format.
*
* @return array
* A renderable array representing the display links portion of pager.
*/
protected function buildDisplayLinks(array $query_parameters) {
$config = \Drupal::config(SettingsForm::CONFIG_NAME);
$display_options = [];
if ($config->get(SettingsForm::DISPLAY_LIST_FLAG) == 1) {
$display_options['list'] = [
'title' => $this->t('List'),
];
}
if ($config->get(SettingsForm::DISPLAY_GRID_FLAG) == 1) {
$display_options['grid'] = [
'title' => $this->t('Grid'),
];
}
$active_display = $query_parameters['display'] ?? $config->get(SettingsForm::DISPLAY_DEFAULT);
$items = [];
foreach ($display_options as $display => $options) {
$url = Url::fromRoute('', [], [
'query' => array_merge($query_parameters, ['display' => $display]),
'absolute' => TRUE,
]);
$text = "{$options['title']}";
$active = $active_display == $display;
$items[] = [
'#type' => 'link',
'#url' => $url,
'#title' => Markup::create($text),
'#attributes' => [
'class' => $active ?
['pager__link', 'pager__link--is-active', 'pager__display'] :
['pager__link', 'pager__display'],
'aria-label' => $this->t("Display as @link", ["@link" => Markup::create($text)]),
],
'#wrapper_attributes' => [
'class' => $active ? ['pager__item', 'is-active'] : ['pager__item'],
],
];
}
return [
'#theme' => 'item_list',
'#list_type' => 'ul',
'#items' => $items,
'#attributes' => [],
'#wrapper_attributes' => ['class' => ['pager__display', 'container']],
];
}
/**
* Build the sort by portion of the pager.
*
* @param array $sort_criteria
* The search fields which can be sorted.
* @param array $query_parameters
* The query parameters used to change the display format.
*
* @return array
* A renderable array representing the sort by portion of pager.
*/
protected function buildSortByForm(array $sort_criteria, array $query_parameters) {
$default_order = $query_parameters['sort_order'] ?? 'DESC';
$default_sort_by = $query_parameters['sort_by'] ?? 'search_api_relevance';
$default_value = $default_sort_by . '_' . strtolower($default_order);
$options = [];
$options_attributes = [];
// Not sure if this will work without defining a sort per direction.
foreach ($sort_criteria as $sort) {
if ($sort->options['exposed'] == TRUE) {
$id = $sort->options['id'];
// Label should be translated via views already.
$label = $sort->options['expose']['label'];
$asc = "{$id}_asc";
$desc = "{$id}_desc";
$options[$asc] = "{$label} ↓";
$options[$desc] = "{$label} ↑";
$options_attributes[$asc] = [
'data-sort_by' => $id,
'data-sort_order' => 'ASC',
];
$options_attributes[$desc] = [
'data-sort_by' => $id,
'data-sort_order' => 'DESC',
];
}
}
return [
'#type' => 'select',
'#title' => 'Sort',
'#title_display' => 'invisible',
'#options' => $options,
'#options_attributes' => $options_attributes,
'#attributes' => ['autocomplete' => 'off', "aria-label" => "Sort By"],
'#wrapper_attributes' => ['class' => ['pager__sort', 'container']],
'#name' => 'order',
'#value' => $default_value,
];
}
/**
* {@inheritdoc}
*/
public function getCacheMaxAge() {
// The block cannot be cached, because it must always match the current
// search results.
return 0;
}
}