Commit 67af8a49 authored by Dries's avatar Dries

Merge branch '8.x' of git.drupal.org:project/drupal into 8.x

parents 8d53c534 84ca10a3
......@@ -150,12 +150,12 @@
/**
* Role ID for anonymous users; should match what's in the "role" table.
*/
const DRUPAL_ANONYMOUS_RID = 1;
const DRUPAL_ANONYMOUS_RID = 'anonymous';
/**
* Role ID for authenticated users; should match what's in the "role" table.
*/
const DRUPAL_AUTHENTICATED_RID = 2;
const DRUPAL_AUTHENTICATED_RID = 'authenticated';
/**
* The number of bytes in a kilobyte.
......
......@@ -451,7 +451,7 @@ function drupal_get_query_array($query) {
if (!empty($query)) {
foreach (explode('&', $query) as $param) {
$param = explode('=', $param);
$result[$param[0]] = isset($param[1]) ? rawurldecode($param[1]) : '';
$result[$param[0]] = isset($param[1]) ? rawurldecode($param[1]) : NULL;
}
}
return $result;
......
......@@ -29,10 +29,10 @@
* inherits much of its syntax and semantics.
*
* Most Drupal database SELECT queries are performed by a call to db_query() or
* db_query_range(). Module authors should also consider using the PagerDefault
* Extender for queries that return results that need to be presented on
* multiple pages, and the Tablesort Extender for generating appropriate queries
* for sortable tables.
* db_query_range(). Module authors should also consider using the
* Drupal\Core\Database\Query\PagerSelectExtender for queries that return
* results that need to be presented on multiple pages, and the Tablesort
* Extender for generating appropriate queries for sortable tables.
*
* For example, one might wish to return a list of the most recent 10 nodes
* authored by a given user. Instead of directly issuing the SQL query
......
......@@ -227,8 +227,10 @@ function _drupal_log_error($error, $fatal = FALSE) {
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
if ($fatal) {
// When called from JavaScript, simply output the error message.
print t('%type: !message in %function (line %line of %file).', $error);
if (error_displayable($error)) {
// When called from JavaScript, simply output the error message.
print t('%type: !message in %function (line %line of %file).', $error);
}
exit;
}
}
......
<?php
use Drupal\Core\Database\Connection;
use Drupal\Core\Database\Query\SelectExtender;
use Drupal\Core\Database\Query\SelectInterface;
/**
* @file
* Functions to aid in presenting database results as a set of pages.
*/
/**
* Query extender for pager queries.
*
* This is the "default" pager mechanism. It creates a paged query with a fixed
* number of entries per page.
*/
class PagerDefault extends SelectExtender {
/**
* The highest element we've autogenerated so far.
*
* @var int
*/
static $maxElement = 0;
/**
* The number of elements per page to allow.
*
* @var int
*/
protected $limit = 10;
/**
* The unique ID of this pager on this page.
*
* @var int
*/
protected $element = NULL;
/**
* The count query that will be used for this pager.
*
* @var SelectQueryInterface
*/
protected $customCountQuery = FALSE;
public function __construct(SelectInterface $query, Connection $connection) {
parent::__construct($query, $connection);
// Add pager tag. Do this here to ensure that it is always added before
// preExecute() is called.
$this->addTag('pager');
}
/**
* Override the execute method.
*
* Before we run the query, we need to add pager-based range() instructions
* to it.
*/
public function execute() {
// Add convenience tag to mark that this is an extended query. We have to
// do this in the constructor to ensure that it is set before preExecute()
// gets called.
if (!$this->preExecute($this)) {
return NULL;
}
// A NULL limit is the "kill switch" for pager queries.
if (empty($this->limit)) {
return;
}
$this->ensureElement();
$total_items = $this->getCountQuery()->execute()->fetchField();
$current_page = pager_default_initialize($total_items, $this->limit, $this->element);
$this->range($current_page * $this->limit, $this->limit);
// Now that we've added our pager-based range instructions, run the query normally.
return $this->query->execute();
}
/**
* Ensure that there is an element associated with this query.
* If an element was not specified previously, then the value of the
* $maxElement counter is taken, after which the counter is incremented.
*
* After running this method, access $this->element to get the element for this
* query.
*/
protected function ensureElement() {
if (!isset($this->element)) {
$this->element = self::$maxElement++;
}
}
/**
* Specify the count query object to use for this pager.
*
* You will rarely need to specify a count query directly. If not specified,
* one is generated off of the pager query itself.
*
* @param SelectQueryInterface $query
* The count query object. It must return a single row with a single column,
* which is the total number of records.
*/
public function setCountQuery(SelectInterface $query) {
$this->customCountQuery = $query;
}
/**
* Retrieve the count query for this pager.
*
* The count query may be specified manually or, by default, taken from the
* query we are extending.
*
* @return SelectQueryInterface
* A count query object.
*/
public function getCountQuery() {
if ($this->customCountQuery) {
return $this->customCountQuery;
}
else {
return $this->query->countQuery();
}
}
/**
* Specify the maximum number of elements per page for this query.
*
* The default if not specified is 10 items per page.
*
* @param $limit
* An integer specifying the number of elements per page. If passed a false
* value (FALSE, 0, NULL), the pager is disabled.
*/
public function limit($limit = 10) {
$this->limit = $limit;
return $this;
}
/**
* Specify the element ID for this pager query.
*
* The element is used to differentiate different pager queries on the same
* page so that they may be operated independently. If you do not specify an
* element, every pager query on the page will get a unique element. If for
* whatever reason you want to explicitly define an element for a given query,
* you may do so here.
*
* Setting the element here also increments the static $maxElement counter,
* which is used for determining the $element when there's none specified.
*
* Note that no collision detection is done when setting an element ID
* explicitly, so it is possible for two pagers to end up using the same ID
* if both are set explicitly.
*
* @param $element
*/
public function element($element) {
$this->element = $element;
if ($element >= self::$maxElement) {
self::$maxElement = $element + 1;
}
return $this;
}
}
/**
* Returns the current page being requested for display within a pager.
*
......@@ -206,10 +42,11 @@ function pager_find_page($element = 0) {
* If the items being displayed result from a database query performed using
* Drupal's database API, and if you have control over the construction of the
* database query, you do not need to call this function directly; instead, you
* can simply extend the query object with the 'PagerDefault' extender before
* executing it. For example:
* can simply extend the query object with the 'PagerSelectExtender' extender
* before executing it. For example:
* @code
* $query = db_select('some_table')->extend('PagerDefault');
* $query = db_select('some_table')
* ->extend('Drupal\Core\Database\Query\PagerSelectExtender');
* @endcode
*
* However, if you are using a different method for generating the items to be
......
......@@ -25,8 +25,7 @@ interface ExtendableInterface {
* @param $extender_name
* The base name of the extending class. The base name will be checked
* against the current database connection to allow driver-specific subclasses
* as well, using the same logic as the query objects themselves. For example,
* PagerDefault_mysql is the MySQL-specific override for PagerDefault.
* as well, using the same logic as the query objects themselves.
* @return Drupal\Core\Database\Query\ExtendableInterface
* The extender object, which now contains a reference to this object.
*/
......
<?php
/**
* @file
* Definition of Drupal\Core\Database\Query\PagerSelectExtender
*/
namespace Drupal\Core\Database\Query;
use Drupal\Core\Database\Connection;
use Drupal\Core\Database\Query\SelectExtender;
use Drupal\Core\Database\Query\SelectInterface;
/**
* Query extender for pager queries.
*
* This is the "default" pager mechanism. It creates a paged query with a fixed
* number of entries per page.
*/
class PagerSelectExtender extends SelectExtender {
/**
* The highest element we've autogenerated so far.
*
* @var int
*/
static $maxElement = 0;
/**
* The number of elements per page to allow.
*
* @var int
*/
protected $limit = 10;
/**
* The unique ID of this pager on this page.
*
* @var int
*/
protected $element = NULL;
/**
* The count query that will be used for this pager.
*
* @var SelectQueryInterface
*/
protected $customCountQuery = FALSE;
public function __construct(SelectInterface $query, Connection $connection) {
parent::__construct($query, $connection);
// Add pager tag. Do this here to ensure that it is always added before
// preExecute() is called.
$this->addTag('pager');
}
/**
* Override the execute method.
*
* Before we run the query, we need to add pager-based range() instructions
* to it.
*/
public function execute() {
// Add convenience tag to mark that this is an extended query. We have to
// do this in the constructor to ensure that it is set before preExecute()
// gets called.
if (!$this->preExecute($this)) {
return NULL;
}
// A NULL limit is the "kill switch" for pager queries.
if (empty($this->limit)) {
return;
}
$this->ensureElement();
$total_items = $this->getCountQuery()->execute()->fetchField();
$current_page = pager_default_initialize($total_items, $this->limit, $this->element);
$this->range($current_page * $this->limit, $this->limit);
// Now that we've added our pager-based range instructions, run the query normally.
return $this->query->execute();
}
/**
* Ensure that there is an element associated with this query.
* If an element was not specified previously, then the value of the
* $maxElement counter is taken, after which the counter is incremented.
*
* After running this method, access $this->element to get the element for this
* query.
*/
protected function ensureElement() {
if (!isset($this->element)) {
$this->element = self::$maxElement++;
}
}
/**
* Specify the count query object to use for this pager.
*
* You will rarely need to specify a count query directly. If not specified,
* one is generated off of the pager query itself.
*
* @param SelectQueryInterface $query
* The count query object. It must return a single row with a single column,
* which is the total number of records.
*/
public function setCountQuery(SelectInterface $query) {
$this->customCountQuery = $query;
}
/**
* Retrieve the count query for this pager.
*
* The count query may be specified manually or, by default, taken from the
* query we are extending.
*
* @return SelectQueryInterface
* A count query object.
*/
public function getCountQuery() {
if ($this->customCountQuery) {
return $this->customCountQuery;
}
else {
return $this->query->countQuery();
}
}
/**
* Specify the maximum number of elements per page for this query.
*
* The default if not specified is 10 items per page.
*
* @param $limit
* An integer specifying the number of elements per page. If passed a false
* value (FALSE, 0, NULL), the pager is disabled.
*/
public function limit($limit = 10) {
$this->limit = $limit;
return $this;
}
/**
* Specify the element ID for this pager query.
*
* The element is used to differentiate different pager queries on the same
* page so that they may be operated independently. If you do not specify an
* element, every pager query on the page will get a unique element. If for
* whatever reason you want to explicitly define an element for a given query,
* you may do so here.
*
* Setting the element here also increments the static $maxElement counter,
* which is used for determining the $element when there's none specified.
*
* Note that no collision detection is done when setting an element ID
* explicitly, so it is possible for two pagers to end up using the same ID
* if both are set explicitly.
*
* @param $element
*/
public function element($element) {
$this->element = $element;
if ($element >= self::$maxElement) {
self::$maxElement = $element + 1;
}
return $this;
}
}
......@@ -84,10 +84,7 @@ Drupal.tableDrag = function (table, tableSettings) {
// Make each applicable row draggable.
// Match immediate children of the parent element to allow nesting.
var $rows = $table.find('> tr.draggable, > tbody > tr.draggable');
if ($rows.length > 1) {
$rows.each(function () { self.makeDraggable(this); });
}
$table.find('> tr.draggable, > tbody > tr.draggable').each(function () { self.makeDraggable(this); });
// Add a link before the table for users to show or hide weight columns.
$table.before($('<a href="#" class="tabledrag-toggle-weight"></a>')
......
......@@ -134,7 +134,7 @@ function aggregator_load_feed_items($type, $data = NULL) {
}
$result = $query
->extend('PagerDefault')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->limit(20)
->orderBy('i.timestamp', 'DESC')
->orderBy('i.iid', 'DESC')
......
......@@ -118,8 +118,8 @@ function block_schema() {
'description' => "The block's unique delta within module, from {block}.delta.",
),
'rid' => array(
'type' => 'int',
'unsigned' => TRUE,
'type' => 'varchar',
'length' => 64,
'not null' => TRUE,
'description' => "The user's role ID from {users_roles}.rid.",
),
......@@ -128,6 +128,12 @@ function block_schema() {
'indexes' => array(
'rid' => array('rid'),
),
'foreign keys' => array(
'role' => array(
'table' => 'role',
'columns' => array('rid' => 'rid'),
),
),
);
$schema['block_custom'] = array(
......@@ -222,6 +228,17 @@ function block_install() {
* @{
*/
/**
* Implements hook_update_dependencies().
*/
function block_update_dependencies() {
// Convert role IDs after User module converted {role}.
$dependencies['block'][8002] = array(
'user' => 8002,
);
return $dependencies;
}
/**
* Block cache is always enabled in 8.x.
*
......@@ -268,6 +285,32 @@ function block_update_8001() {
db_create_table('block_language', $schema);
}
/**
* Replace serial role IDs with machine name strings.
*
* @see user_update_8002()
*/
function block_update_8002() {
// Change serial rid column into string.
$column = array(
'type' => 'varchar',
'length' => 64,
'not null' => TRUE,
'description' => "The user's role ID from {users_roles}.rid.",
);
db_change_field('block_role', 'rid', 'rid', $column);
// Rename the built-in serial role IDs into the hardcoded machine names.
db_update('block_role')
->fields(array('rid' => DRUPAL_ANONYMOUS_RID))
->condition('rid', 1)
->execute();
db_update('block_role')
->fields(array('rid' => DRUPAL_AUTHENTICATED_RID))
->condition('rid', 2)
->execute();
}
/**
* @} End of "addtogroup updates-7.x-to-8.x".
* The next series of updates should start at 9000.
......
......@@ -79,7 +79,9 @@ function comment_admin_overview($form, &$form_state, $arg) {
'operations' => array('data' => t('Operations')),
);
$query = db_select('comment', 'c')->extend('PagerDefault')->extend('TableSort');
$query = db_select('comment', 'c')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->extend('TableSort');
$query->join('node', 'n', 'n.nid = c.nid');
$query->addField('n', 'title', 'node_title');
$query->addTag('node_access');
......
......@@ -849,7 +849,8 @@ function comment_node_page_additions(Node $node) {
* to consider the trailing "/" so we use a substring only.
*/
function comment_get_thread(Node $node, $mode, $comments_per_page) {
$query = db_select('comment', 'c')->extend('PagerDefault');
$query = db_select('comment', 'c')
->extend('Drupal\Core\Database\Query\PagerSelectExtender');
$query->addField('c', 'cid');
$query
->condition('c.nid', $node->nid)
......
......@@ -37,7 +37,9 @@ function dblog_overview() {
array('data' => t('Operations')),
);
$query = db_select('watchdog', 'w')->extend('PagerDefault')->extend('TableSort');
$query = db_select('watchdog', 'w')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->extend('TableSort');
$query->leftJoin('users', 'u', 'w.uid = u.uid');
$query
->fields('w', array('wid', 'uid', 'severity', 'type', 'timestamp', 'message', 'variables', 'link'))
......@@ -96,7 +98,9 @@ function dblog_top($type) {
$count_query->addExpression('COUNT(DISTINCT(message))');
$count_query->condition('type', $type);
$query = db_select('watchdog', 'w')->extend('PagerDefault')->extend('TableSort');
$query = db_select('watchdog', 'w')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->extend('TableSort');
$query->addExpression('COUNT(wid)', 'count');
$query = $query
->fields('w', array('message', 'variables'))
......
......@@ -9,7 +9,7 @@
use Drupal\entity\EntityFieldQueryException;
use Drupal\Core\Database\Query\Select;
use PagerDefault;
use Drupal\Core\Database\Query\PagerSelectExtender;
/**
* Retrieves entities matching a given set of conditions.
......@@ -571,10 +571,10 @@ public function range($start = NULL, $length = NULL) {
*/
public function pager($limit = 10, $element = NULL) {
if (!isset($element)) {
$element = PagerDefault::$maxElement++;
$element = PagerSelectExtender::$maxElement++;
}
elseif ($element >= PagerDefault::$maxElement) {
PagerDefault::$maxElement = $element + 1;
elseif ($element >= PagerSelectExtender::$maxElement) {
PagerSelectExtender::$maxElement = $element + 1;
}
$this->pager = array(
......
......@@ -215,7 +215,9 @@ class TextFieldTestCase extends WebTestBase {
$format = filter_format_load($edit['format']);
$format_id = $format->format;
$permission = filter_permission_name($format);
$rid = max(array_keys($this->web_user->roles));
$roles = $this->web_user->roles;
unset($roles[DRUPAL_AUTHENTICATED_RID]);
$rid = key($roles);
user_role_grant_permissions($rid, array($permission));
$this->drupalLogin($this->web_user);
......
......@@ -106,8 +106,10 @@ function testFormatPermissions() {
}
function testFormatRoles() {
// Get the role ID assigned to the regular user; it must be the maximum.
$rid = max(array_keys($this->web_user->roles));
// Get the role ID assigned to the regular user.
$roles = $this->web_user->roles;
unset($roles[DRUPAL_AUTHENTICATED_RID]);
$rid = key($roles);
// Check that this role appears in the list of roles that have access to an
// allowed text format, but does not appear in the list of roles that have
......
......@@ -893,7 +893,9 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
}
}
$query = db_select('forum_index', 'f')->extend('PagerDefault')->extend('TableSort');
$query = db_select('forum_index', 'f')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->extend('TableSort');
$query->fields('f');