Unverified Commit 52224e37 authored by larowlan's avatar larowlan

Issue #3001201 by voleger, andypost, goodboy: Convert tablesort.inc functions to a static class

parent b659cbd9
......@@ -9,18 +9,20 @@
* column.
*/
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Url;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Utility\TableSort;
/**
* Initializes the table sort context.
*
* @deprecated as of Drupal 8.7.x and will be removed before Drupal 9.0.0. Use
* \Drupal\Core\Utility\TableSort::getContextFromRequest() instead.
*
* @see \Drupal\Core\Utility\TableSortInterface::getContextFromRequest()
* @see https://www.drupal.org/node/3009182
*/
function tablesort_init($header) {
$ts = tablesort_get_order($header);
$ts['sort'] = tablesort_get_sort($header);
$ts['query'] = tablesort_get_query_parameters();
return $ts;
@trigger_error(__FUNCTION__ . '() is deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Utility\TableSort::getContextFromRequest() instead. See https://www.drupal.org/node/3009182', E_USER_DEPRECATED);
return TableSort::getContextFromRequest($header, \Drupal::request());
}
/**
......@@ -37,39 +39,16 @@ function tablesort_init($header) {
* An array of column headers in the format described in '#type' => 'table'.
* @param array $ts
* The current table sort context as returned from tablesort_init().
*
* @deprecated as of Drupal 8.7.x and will be removed before Drupal 9.0.0. Use
* \Drupal\Core\Utility\TableSort::header() instead.
*
* @see \Drupal\Core\Utility\TableSortInterface::header()
* @see https://www.drupal.org/node/3009182
*/
function tablesort_header(&$cell_content, array &$cell_attributes, array $header, array $ts) {
// Special formatting for the currently sorted column header.
if (isset($cell_attributes['field'])) {
$title = t('sort by @s', ['@s' => $cell_content]);
if ($cell_content == $ts['name']) {
// aria-sort is a WAI-ARIA property that indicates if items in a table
// or grid are sorted in ascending or descending order. See
// http://www.w3.org/TR/wai-aria/states_and_properties#aria-sort
$cell_attributes['aria-sort'] = ($ts['sort'] == 'asc') ? 'ascending' : 'descending';
$ts['sort'] = (($ts['sort'] == 'asc') ? 'desc' : 'asc');
$cell_attributes['class'][] = 'is-active';
$tablesort_indicator = [
'#theme' => 'tablesort_indicator',
'#style' => $ts['sort'],
];
$image = \Drupal::service('renderer')->render($tablesort_indicator);
}
else {
// If the user clicks a different header, we want to sort ascending initially.
$ts['sort'] = 'asc';
$image = '';
}
$cell_content = \Drupal::l(new FormattableMarkup('@cell_content@image', ['@cell_content' => $cell_content, '@image' => $image]), new Url('<current>', [], [
'attributes' => ['title' => $title],
'query' => array_merge($ts['query'], [
'sort' => $ts['sort'],
'order' => $cell_content,
]),
]));
unset($cell_attributes['field'], $cell_attributes['sort']);
}
@trigger_error(__FUNCTION__ . '() is deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Utility\TableSort::header() instead. See https://www.drupal.org/node/3009182', E_USER_DEPRECATED);
TableSort::header($cell_content, $cell_attributes, $header, $ts);
}
/**
......@@ -78,9 +57,16 @@ function tablesort_header(&$cell_content, array &$cell_attributes, array $header
* @return
* A URL query parameter array that consists of all components of the current
* page request except for those pertaining to table sorting.
*
* @deprecated as of Drupal 8.7.x and will be removed before Drupal 9.0.0. Use
* \Drupal\Core\Utility\TableSort::getQueryParameters() instead.
*
* @see \Drupal\Core\Utility\TableSort::getQueryParameters()
* @see https://www.drupal.org/node/3009182
*/
function tablesort_get_query_parameters() {
return UrlHelper::filterQueryParameters(\Drupal::request()->query->all(), ['sort', 'order']);
@trigger_error(__FUNCTION__ . '() is deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Utility\TableSort::getQueryParameters() instead. See https://www.drupal.org/node/3009182', E_USER_DEPRECATED);
return TableSort::getQueryParameters(\Drupal::request());
}
/**
......@@ -93,31 +79,16 @@ function tablesort_get_query_parameters() {
* An associative array describing the criterion, containing the keys:
* - "name": The localized title of the table column.
* - "sql": The name of the database field to sort on.
*
* @deprecated as of Drupal 8.7.x and will be removed before Drupal 9.0.0. Use
* \Drupal\Core\Utility\TableSort::getOrder() instead.
*
* @see \Drupal\Core\Utility\TableSortInterface::getOrder()
* @see https://www.drupal.org/node/3009182
*/
function tablesort_get_order($headers) {
$order = \Drupal::request()->query->get('order', '');
foreach ($headers as $header) {
if (is_array($header)) {
if (isset($header['data']) && $order == $header['data']) {
$default = $header;
break;
}
if (empty($default) && isset($header['sort']) && ($header['sort'] == 'asc' || $header['sort'] == 'desc')) {
$default = $header;
}
}
}
if (!isset($default)) {
$default = reset($headers);
if (!is_array($default)) {
$default = ['data' => $default];
}
}
$default += ['data' => NULL, 'field' => NULL];
return ['name' => $default['data'], 'sql' => $default['field']];
@trigger_error(__FUNCTION__ . '() is deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Utility\TableSort::getOrder() instead. See https://www.drupal.org/node/3009182', E_USER_DEPRECATED);
return TableSort::getOrder($headers, \Drupal::request());
}
/**
......@@ -128,22 +99,14 @@ function tablesort_get_order($headers) {
*
* @return
* The current sort direction ("asc" or "desc").
*
* @deprecated as of Drupal 8.7.x and will be removed before Drupal 9.0.0. Use
* \Drupal\Core\Utility\TableSort::getSort() instead.
*
* @see \Drupal\Core\Utility\TableSortInterface::getSort()
* @see https://www.drupal.org/node/3009182
*/
function tablesort_get_sort($headers) {
$query = \Drupal::request()->query;
if ($query->has('sort')) {
return (strtolower($query->get('sort')) == 'desc') ? 'desc' : 'asc';
}
// The user has not specified a sort. Use the default for the currently sorted
// header if specified; otherwise use "asc".
else {
// Find out which header is currently being sorted.
$ts = tablesort_get_order($headers);
foreach ($headers as $header) {
if (is_array($header) && isset($header['data']) && $header['data'] == $ts['name'] && isset($header['sort'])) {
return $header['sort'];
}
}
}
return 'asc';
@trigger_error(__FUNCTION__ . '() is deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Utility\TableSort::getSort() instead. See https://www.drupal.org/node/3009182', E_USER_DEPRECATED);
return TableSort::getSort($headers, \Drupal::request());
}
......@@ -23,6 +23,7 @@
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\Markup;
use Drupal\Core\Utility\TableSort;
/**
* @defgroup content_flags Content markers
......@@ -944,7 +945,7 @@ function template_preprocess_table(&$variables) {
$ts = [];
$header_columns = 0;
if (!empty($variables['header'])) {
$ts = tablesort_init($variables['header']);
$ts = TableSort::getContextFromRequest($variables['header'], \Drupal::request());
// Use a separate index with responsive classes as headers
// may be associative.
......@@ -988,9 +989,9 @@ function template_preprocess_table(&$variables) {
}
}
tablesort_header($cell_content, $cell, $variables['header'], $ts);
TableSort::header($cell_content, $cell, $variables['header'], $ts);
// tablesort_header() removes the 'sort' and 'field' keys.
// TableSort::header() removes the 'sort' and 'field' keys.
$cell_attributes = new Attribute($cell);
}
$variables['header'][$col_key] = [];
......
......@@ -3,6 +3,7 @@
namespace Drupal\Core\Database\Query;
use Drupal\Core\Database\Connection;
use Drupal\Core\Utility\TableSort;
/**
* Query extender class for tablesort queries.
......@@ -10,10 +11,8 @@
class TableSortExtender extends SelectExtender {
/**
* The array of fields that can be sorted by.
* {@inheritdoc}
*/
protected $header = [];
public function __construct(SelectInterface $query, Connection $connection) {
parent::__construct($query, $connection);
......@@ -35,67 +34,17 @@ public function __construct(SelectInterface $query, Connection $connection) {
* @see table.html.twig
*/
public function orderByHeader(array $header) {
$this->header = $header;
$ts = $this->init();
if (!empty($ts['sql'])) {
$context = TableSort::getContextFromRequest($header, \Drupal::request());
if (!empty($context['sql'])) {
// Based on code from \Drupal\Core\Database\Connection::escapeTable(),
// but this can also contain a dot.
$field = preg_replace('/[^A-Za-z0-9_.]+/', '', $ts['sql']);
$field = preg_replace('/[^A-Za-z0-9_.]+/', '', $context['sql']);
// orderBy() will ensure that only ASC/DESC values are accepted, so we
// don't need to sanitize that here.
$this->orderBy($field, $ts['sort']);
$this->orderBy($field, $context['sort']);
}
return $this;
}
/**
* Initialize the table sort context.
*/
protected function init() {
$ts = $this->order();
$ts['sort'] = $this->getSort();
$ts['query'] = $this->getQueryParameters();
return $ts;
}
/**
* Determine the current sort direction.
*
* @return
* The current sort direction ("asc" or "desc").
*
* @see tablesort_get_sort()
*/
protected function getSort() {
return tablesort_get_sort($this->header);
}
/**
* Compose a URL query parameter array to append to table sorting requests.
*
* @return
* A URL query parameter array that consists of all components of the current
* page request except for those pertaining to table sorting.
*
* @see tablesort_get_query_parameters()
*/
protected function getQueryParameters() {
return tablesort_get_query_parameters();
}
/**
* Determine the current sort criterion.
*
* @return
* An associative array describing the criterion, containing the keys:
* - "name": The localized title of the table column.
* - "sql": The name of the database field to sort on.
*
* @see tablesort_get_order()
*/
protected function order() {
return tablesort_get_order($this->header);
}
}
......@@ -4,6 +4,7 @@
use Drupal\Core\Database\Query\PagerSelectExtender;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Utility\TableSort;
/**
* The base entity query class.
......@@ -329,8 +330,8 @@ public function tableSort(&$headers) {
}
}
$order = tablesort_get_order($headers);
$direction = tablesort_get_sort($headers);
$order = TableSort::getOrder($headers, \Drupal::request());
$direction = TableSort::getSort($headers, \Drupal::request());
foreach ($headers as $header) {
if (is_array($header) && ($header['data'] == $order['name'])) {
$this->sort($header['specifier'], $direction, isset($header['langcode']) ? $header['langcode'] : NULL);
......
<?php
namespace Drupal\Core\Utility;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Link;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Symfony\Component\HttpFoundation\Request;
/**
* Provides a class for table sorting processing and rendering.
*/
class TableSort {
const ASC = 'asc';
const DESC = 'desc';
/**
* Initializes the table sort context.
*
* @param array $headers
* An array of column headers in the format described in '#type' => 'table'.
* @param \Symfony\Component\HttpFoundation\Request $request
* A current request.
*
* @return array
* The current table sort context.
*/
public static function getContextFromRequest(array $headers, Request $request) {
$context = static::getOrder($headers, $request);
$context['sort'] = static::getSort($headers, $request);
$context['query'] = static::getQueryParameters($request);
return $context;
}
/**
* Formats a column header.
*
* If the cell in question is the column header for the current sort
* criterion, it gets special formatting. All possible sort criteria become
* links.
*
* @param string $cell_content
* The cell content to format. Passed by reference.
* @param array $cell_attributes
* The cell attributes. Passed by reference.
* @param array $header
* An array of column headers in the format described in '#type' => 'table'.
* @param array $context
* The current table sort context as returned from
* TableSort::getContextFromRequest() method.
*
* @throws \Exception
*
* @see getContextFromRequest()
*/
public static function header(&$cell_content, array &$cell_attributes, array $header, array $context) {
// Special formatting for the currently sorted column header.
if (isset($cell_attributes['field'])) {
$title = new TranslatableMarkup('sort by @s', ['@s' => $cell_content]);
if ($cell_content == $context['name']) {
// aria-sort is a WAI-ARIA property that indicates if items in a table
// or grid are sorted in ascending or descending order. See
// http://www.w3.org/TR/wai-aria/states_and_properties#aria-sort
$cell_attributes['aria-sort'] = ($context['sort'] == self::ASC) ? 'ascending' : 'descending';
$context['sort'] = (($context['sort'] == self::ASC) ? self::DESC : self::ASC);
$cell_attributes['class'][] = 'is-active';
$tablesort_indicator = [
'#theme' => 'tablesort_indicator',
'#style' => $context['sort'],
];
$image = \Drupal::service('renderer')->render($tablesort_indicator);
}
else {
// If the user clicks a different header, we want to sort ascending
// initially.
$context['sort'] = self::ASC;
$image = '';
}
$cell_content = Link::createFromRoute(new FormattableMarkup('@cell_content@image', ['@cell_content' => $cell_content, '@image' => $image]), '<current>', [], [
'attributes' => ['title' => $title],
'query' => array_merge($context['query'], [
'sort' => $context['sort'],
'order' => $cell_content,
]),
]);
unset($cell_attributes['field'], $cell_attributes['sort']);
}
}
/**
* Determines the current sort criterion.
*
* @param array $headers
* An array of column headers in the format described in '#type' => 'table'.
* @param \Symfony\Component\HttpFoundation\Request $request
* A current request.
*
* @return array
* An associative array describing the criterion, containing the keys:
* - "name": The localized title of the table column.
* - "sql": The name of the database field to sort on.
*/
public static function getOrder(array $headers, Request $request) {
$order = $request->query->get('order', '');
foreach ($headers as $header) {
if (is_array($header)) {
if (isset($header['data']) && $order == $header['data']) {
$default = $header;
break;
}
if (empty($default) && isset($header['sort']) && in_array($header['sort'], [self::ASC, self::DESC])) {
$default = $header;
}
}
}
if (!isset($default)) {
$default = reset($headers);
if (!is_array($default)) {
$default = ['data' => $default];
}
}
$default += ['data' => NULL, 'field' => NULL];
return ['name' => $default['data'], 'sql' => $default['field']];
}
/**
* Determines the current sort direction.
*
* @param array $headers
* An array of column headers in the format described in '#type' => 'table'.
* @param \Symfony\Component\HttpFoundation\Request|null $request
* A current request.
*
* @return string
* The current sort direction ("asc" or "desc").
*/
public static function getSort(array $headers, Request $request) {
$query = $request->query;
if ($query->has('sort')) {
return (strtolower($query->get('sort')) == self::DESC) ? self::DESC : self::ASC;
}
// The user has not specified a sort. Use the default for the currently
// sorted header if specified; otherwise use "asc".
// Find out which header is currently being sorted.
$order = static::getOrder($headers, $request);
foreach ($headers as $header) {
if (is_array($header) && isset($header['data']) && $header['data'] == $order['name'] && isset($header['sort'])) {
return $header['sort'];
}
}
return self::ASC;
}
/**
* Composes a URL query parameter array for table sorting links.
*
* @param \Symfony\Component\HttpFoundation\Request|null $request
* A current request.
*
* @return array
* A URL query parameter array that consists of all components of the
* current page request except for those pertaining to table sorting.
*
* @internal
*/
public static function getQueryParameters(Request $request) {
return UrlHelper::filterQueryParameters($request->query->all(), ['sort', 'order']);
}
}
......@@ -9,6 +9,7 @@
use Drupal\Component\Utility\Xss;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Url;
use Drupal\Core\Utility\TableSort;
/**
* Prepares variables for view templates.
......@@ -449,7 +450,7 @@ function template_preprocess_views_view_table(&$variables) {
// working URLs.
$route_name = !empty($view->live_preview) ? '<current>' : '<none>';
$query = tablesort_get_query_parameters();
$query = TableSort::getQueryParameters(\Drupal::request());
if (isset($view->exposed_raw_input)) {
$query += $view->exposed_raw_input;
}
......
......@@ -3,6 +3,7 @@
namespace Drupal\KernelTests\Core\Render\Element;
use Drupal\Component\Utility\Html;
use Drupal\Core\Utility\TableSort;
use Drupal\KernelTests\KernelTestBase;
use Symfony\Component\HttpFoundation\Request;
......@@ -14,7 +15,7 @@
class TableSortExtenderTest extends KernelTestBase {
/**
* Tests tablesort_init().
* Tests \Drupal\Core\Utility\TableSort::getContextFromRequest().
*/
public function testTableSortInit() {
......@@ -32,7 +33,7 @@ public function testTableSortInit() {
$request = Request::createFromGlobals();
$request->query->replace([]);
\Drupal::getContainer()->get('request_stack')->push($request);
$ts = tablesort_init($headers);
$ts = TableSort::getContextFromRequest($headers, $request);
$this->verbose(strtr('$ts: <pre>!ts</pre>', ['!ts' => Html::escape(var_export($ts, TRUE))]));
$this->assertEqual($ts, $expected_ts, 'Simple table headers sorted correctly.');
......@@ -45,7 +46,7 @@ public function testTableSortInit() {
'order' => 'bar',
]);
\Drupal::getContainer()->get('request_stack')->push($request);
$ts = tablesort_init($headers);
$ts = TableSort::getContextFromRequest($headers, $request);
$this->verbose(strtr('$ts: <pre>!ts</pre>', ['!ts' => Html::escape(var_export($ts, TRUE))]));
$this->assertEqual($ts, $expected_ts, 'Simple table headers plus non-overriding $_GET parameters sorted correctly.');
......@@ -61,7 +62,7 @@ public function testTableSortInit() {
\Drupal::getContainer()->get('request_stack')->push($request);
$expected_ts['sort'] = 'desc';
$expected_ts['query'] = ['alpha' => 'beta'];
$ts = tablesort_init($headers);
$ts = TableSort::getContextFromRequest($headers, $request);
$this->verbose(strtr('$ts: <pre>!ts</pre>', ['!ts' => Html::escape(var_export($ts, TRUE))]));
$this->assertEqual($ts, $expected_ts, 'Simple table headers plus $_GET parameters sorted correctly.');
......@@ -87,7 +88,7 @@ public function testTableSortInit() {
'order' => '2',
]);
\Drupal::getContainer()->get('request_stack')->push($request);
$ts = tablesort_init($headers);
$ts = TableSort::getContextFromRequest($headers, $request);
$expected_ts = [
'name' => '2',
'sql' => 'two',
......@@ -106,7 +107,7 @@ public function testTableSortInit() {
'order' => 'bar',
]);
\Drupal::getContainer()->get('request_stack')->push($request);
$ts = tablesort_init($headers);
$ts = TableSort::getContextFromRequest($headers, $request);
$expected_ts = [
'name' => '1',
'sql' => 'one',
......@@ -133,7 +134,7 @@ public function testTableSortInit() {
'sort' => 'asc',
'query' => ['alpha' => 'beta'],
];
$ts = tablesort_init($headers);
$ts = TableSort::getContextFromRequest($headers, $request);
$this->verbose(strtr('$ts: <pre>!ts</pre>', ['!ts' => Html::escape(var_export($ts, TRUE))]));
$this->assertEqual($ts, $expected_ts, 'Complex table headers plus $_GET parameters sorted correctly.');
}
......
<?php
namespace Drupal\KernelTests\Core\Theme;
use Drupal\Core\Utility\TableSort;
use Drupal\KernelTests\KernelTestBase;
/**
* Deprecation tests cases for the tablesort.inc file functions.
*
* @package Drupal\KernelTests\Core\Theme
*
* @group legacy
*/
class TableSortLegacyTest extends KernelTestBase {
/**
* Tests deprecation of the tablesort_init() function.
*
* @expectedDeprecation tablesort_init() is deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Utility\TableSort::getContextFromRequest() instead. See https://www.drupal.org/node/3009182
*/
public function testInit() {
$context = tablesort_init([]);
$this->assertArrayHasKey('query', $context);
$this->assertArrayHasKey('sort', $context);
}
/**
* Tests deprecation of the tablesort_header() function.
*
* @expectedDeprecation tablesort_header() is deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Utility\TableSort::header() instead. See https://www.drupal.org/node/3009182
*/
public function testHeader() {
$cell_content = '';
$cell_attributes = [];
tablesort_header($cell_content, $cell_attributes, [], []);
$this->assertEquals('', $cell_content);
}
/**
* Tests deprecation of the tablesort_get_query_parameters() function.
*
* @expectedDeprecation tablesort_get_query_parameters() is deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Utility\TableSort::getQueryParameters() instead. See https://www.drupal.org/node/3009182
*/
public function testQueryParameters() {
$parameters = tablesort_get_query_parameters();
$this->assertArrayNotHasKey('sort', $parameters);
$this->assertArrayNotHasKey('order', $parameters);
}
/**
* Tests deprecation of the tablesort_get_order() function.
*
* @expectedDeprecation tablesort_get_order() is deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Utility\TableSort::getOrder() instead. See https://www.drupal.org/node/3009182
*/
public function testOrder() {
$this->assertEquals(
[
'name' => NULL,
'sql' => NULL,
],
tablesort_get_order([])
);
}
/**
* Tests deprecation of the tablesort_get_sort() function.
*
* @expectedDeprecation tablesort_get_sort() is deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Utility\TableSort::getSort() instead. See https://www.drupal.org/node/3009182
*/
public function testSort() {
$this->assertEquals(TableSort::ASC, tablesort_get_sort([]));
}
}
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