Drupal: update core 7.77

This commit is contained in:
Robert 2020-12-06 20:45:26 +01:00
parent 952071c7bc
commit 61a194dcb9
169 changed files with 1672 additions and 447 deletions

View File

@ -1,3 +1,13 @@
Drupal 7.77, 2020-12-03
-----------------------
- Hotfix for schema.prefixed tables
Drupal 7.76, 2020-12-02
-----------------------
- Support for MySQL 8
- Core tests pass in SQLite
- Better user flood control logging
Drupal 7.75, 2020-11-26 Drupal 7.75, 2020-11-26
----------------------- -----------------------
- Fixed security issues: - Fixed security issues:

View File

@ -12,7 +12,7 @@ The branch maintainers for Drupal 7 are:
- Dries Buytaert 'dries' https://www.drupal.org/u/dries - Dries Buytaert 'dries' https://www.drupal.org/u/dries
- Fabian Franz 'Fabianx' https://www.drupal.org/u/fabianx - Fabian Franz 'Fabianx' https://www.drupal.org/u/fabianx
- (provisional) Drew Webber 'mcdruid' https://www.drupal.org/u/mcdruid - Drew Webber 'mcdruid' https://www.drupal.org/u/mcdruid
Component maintainers Component maintainers

View File

@ -8,7 +8,7 @@
/** /**
* The current system version. * The current system version.
*/ */
define('VERSION', '7.75'); define('VERSION', '7.77');
/** /**
* Core API compatibility. * Core API compatibility.
@ -1189,19 +1189,21 @@ function variable_initialize($conf = array()) {
$variables = $cached->data; $variables = $cached->data;
} }
else { else {
// Cache miss. Avoid a stampede. // Cache miss. Avoid a stampede by acquiring a lock. If the lock fails to
// acquire, optionally just continue with uncached processing.
$name = 'variable_init'; $name = 'variable_init';
if (!lock_acquire($name, 1)) { $lock_acquired = lock_acquire($name, 1);
// Another request is building the variable cache. if (!$lock_acquired && variable_get('variable_initialize_wait_for_lock', FALSE)) {
// Wait, then re-run this function.
lock_wait($name); lock_wait($name);
return variable_initialize($conf); return variable_initialize($conf);
} }
else { else {
// Proceed with variable rebuild. // Load the variables from the table.
$variables = array_map('unserialize', db_query('SELECT name, value FROM {variable}')->fetchAllKeyed()); $variables = array_map('unserialize', db_query('SELECT name, value FROM {variable}')->fetchAllKeyed());
cache_set('variables', $variables, 'cache_bootstrap'); if ($lock_acquired) {
lock_release($name); cache_set('variables', $variables, 'cache_bootstrap');
lock_release($name);
}
} }
} }

View File

@ -6653,30 +6653,41 @@ function element_children(&$elements, $sort = FALSE) {
$sort = isset($elements['#sorted']) ? !$elements['#sorted'] : $sort; $sort = isset($elements['#sorted']) ? !$elements['#sorted'] : $sort;
// Filter out properties from the element, leaving only children. // Filter out properties from the element, leaving only children.
$children = array(); $count = count($elements);
$child_weights = array();
$i = 0;
$sortable = FALSE; $sortable = FALSE;
foreach ($elements as $key => $value) { foreach ($elements as $key => $value) {
if (is_int($key) || $key === '' || $key[0] !== '#') { if (is_int($key) || $key === '' || $key[0] !== '#') {
$children[$key] = $value;
if (is_array($value) && isset($value['#weight'])) { if (is_array($value) && isset($value['#weight'])) {
$weight = $value['#weight'];
$sortable = TRUE; $sortable = TRUE;
} }
else {
$weight = 0;
}
// Support weights with up to three digit precision and conserve the
// insertion order.
$child_weights[$key] = floor($weight * 1000) + $i / $count;
} }
$i++;
} }
// Sort the children if necessary. // Sort the children if necessary.
if ($sort && $sortable) { if ($sort && $sortable) {
uasort($children, 'element_sort'); asort($child_weights);
// Put the sorted children back into $elements in the correct order, to // Put the sorted children back into $elements in the correct order, to
// preserve sorting if the same element is passed through // preserve sorting if the same element is passed through
// element_children() twice. // element_children() twice.
foreach ($children as $key => $child) { foreach ($child_weights as $key => $weight) {
$value = $elements[$key];
unset($elements[$key]); unset($elements[$key]);
$elements[$key] = $child; $elements[$key] = $value;
} }
$elements['#sorted'] = TRUE; $elements['#sorted'] = TRUE;
} }
return array_keys($children); return array_keys($child_weights);
} }
/** /**

View File

@ -310,6 +310,13 @@ abstract class DatabaseConnection extends PDO {
*/ */
protected $escapedAliases = array(); protected $escapedAliases = array();
/**
* List of un-prefixed table names, keyed by prefixed table names.
*
* @var array
*/
protected $unprefixedTablesMap = array();
function __construct($dsn, $username, $password, $driver_options = array()) { function __construct($dsn, $username, $password, $driver_options = array()) {
// Initialize and prepare the connection prefix. // Initialize and prepare the connection prefix.
$this->setPrefix(isset($this->connectionOptions['prefix']) ? $this->connectionOptions['prefix'] : ''); $this->setPrefix(isset($this->connectionOptions['prefix']) ? $this->connectionOptions['prefix'] : '');
@ -338,7 +345,9 @@ abstract class DatabaseConnection extends PDO {
// Destroy all references to this connection by setting them to NULL. // Destroy all references to this connection by setting them to NULL.
// The Statement class attribute only accepts a new value that presents a // The Statement class attribute only accepts a new value that presents a
// proper callable, so we reset it to PDOStatement. // proper callable, so we reset it to PDOStatement.
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement', array())); if (!empty($this->statementClass)) {
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement', array()));
}
$this->schema = NULL; $this->schema = NULL;
} }
@ -442,6 +451,13 @@ abstract class DatabaseConnection extends PDO {
$this->prefixReplace[] = $this->prefixes['default']; $this->prefixReplace[] = $this->prefixes['default'];
$this->prefixSearch[] = '}'; $this->prefixSearch[] = '}';
$this->prefixReplace[] = ''; $this->prefixReplace[] = '';
// Set up a map of prefixed => un-prefixed tables.
foreach ($this->prefixes as $table_name => $prefix) {
if ($table_name !== 'default') {
$this->unprefixedTablesMap[$prefix . $table_name] = $table_name;
}
}
} }
/** /**
@ -477,6 +493,17 @@ abstract class DatabaseConnection extends PDO {
} }
} }
/**
* Gets a list of individually prefixed table names.
*
* @return array
* An array of un-prefixed table names, keyed by their fully qualified table
* names (i.e. prefix + table_name).
*/
public function getUnprefixedTablesMap() {
return $this->unprefixedTablesMap;
}
/** /**
* Prepares a query string and returns the prepared statement. * Prepares a query string and returns the prepared statement.
* *
@ -2840,7 +2867,6 @@ function db_field_exists($table, $field) {
* *
* @param $table_expression * @param $table_expression
* An SQL expression, for example "simpletest%" (without the quotes). * An SQL expression, for example "simpletest%" (without the quotes).
* BEWARE: this is not prefixed, the caller should take care of that.
* *
* @return * @return
* Array, both the keys and the values are the matching tables. * Array, both the keys and the values are the matching tables.
@ -2849,6 +2875,23 @@ function db_find_tables($table_expression) {
return Database::getConnection()->schema()->findTables($table_expression); return Database::getConnection()->schema()->findTables($table_expression);
} }
/**
* Finds all tables that are like the specified base table name. This is a
* backport of the change made to db_find_tables in Drupal 8 to work with
* virtual, un-prefixed table names. The original function is retained for
* Backwards Compatibility.
* @see https://www.drupal.org/node/2552435
*
* @param $table_expression
* An SQL expression, for example "simpletest%" (without the quotes).
*
* @return
* Array, both the keys and the values are the matching tables.
*/
function db_find_tables_d8($table_expression) {
return Database::getConnection()->schema()->findTablesD8($table_expression);
}
function _db_create_keys_sql($spec) { function _db_create_keys_sql($spec) {
return Database::getConnection()->schema()->createKeysSql($spec); return Database::getConnection()->schema()->createKeysSql($spec);
} }

View File

@ -5,6 +5,11 @@
* Database interface code for MySQL database servers. * Database interface code for MySQL database servers.
*/ */
/**
* The default character for quoting identifiers in MySQL.
*/
define('MYSQL_IDENTIFIER_QUOTE_CHARACTER_DEFAULT', '`');
/** /**
* @addtogroup database * @addtogroup database
* @{ * @{
@ -19,6 +24,277 @@ class DatabaseConnection_mysql extends DatabaseConnection {
*/ */
protected $needsCleanup = FALSE; protected $needsCleanup = FALSE;
/**
* The list of MySQL reserved key words.
*
* @link https://dev.mysql.com/doc/refman/8.0/en/keywords.html
*/
private $reservedKeyWords = array(
'accessible',
'add',
'admin',
'all',
'alter',
'analyze',
'and',
'as',
'asc',
'asensitive',
'before',
'between',
'bigint',
'binary',
'blob',
'both',
'by',
'call',
'cascade',
'case',
'change',
'char',
'character',
'check',
'collate',
'column',
'condition',
'constraint',
'continue',
'convert',
'create',
'cross',
'cube',
'cume_dist',
'current_date',
'current_time',
'current_timestamp',
'current_user',
'cursor',
'database',
'databases',
'day_hour',
'day_microsecond',
'day_minute',
'day_second',
'dec',
'decimal',
'declare',
'default',
'delayed',
'delete',
'dense_rank',
'desc',
'describe',
'deterministic',
'distinct',
'distinctrow',
'div',
'double',
'drop',
'dual',
'each',
'else',
'elseif',
'empty',
'enclosed',
'escaped',
'except',
'exists',
'exit',
'explain',
'false',
'fetch',
'first_value',
'float',
'float4',
'float8',
'for',
'force',
'foreign',
'from',
'fulltext',
'function',
'generated',
'get',
'grant',
'group',
'grouping',
'groups',
'having',
'high_priority',
'hour_microsecond',
'hour_minute',
'hour_second',
'if',
'ignore',
'in',
'index',
'infile',
'inner',
'inout',
'insensitive',
'insert',
'int',
'int1',
'int2',
'int3',
'int4',
'int8',
'integer',
'interval',
'into',
'io_after_gtids',
'io_before_gtids',
'is',
'iterate',
'join',
'json_table',
'key',
'keys',
'kill',
'lag',
'last_value',
'lead',
'leading',
'leave',
'left',
'like',
'limit',
'linear',
'lines',
'load',
'localtime',
'localtimestamp',
'lock',
'long',
'longblob',
'longtext',
'loop',
'low_priority',
'master_bind',
'master_ssl_verify_server_cert',
'match',
'maxvalue',
'mediumblob',
'mediumint',
'mediumtext',
'middleint',
'minute_microsecond',
'minute_second',
'mod',
'modifies',
'natural',
'not',
'no_write_to_binlog',
'nth_value',
'ntile',
'null',
'numeric',
'of',
'on',
'optimize',
'optimizer_costs',
'option',
'optionally',
'or',
'order',
'out',
'outer',
'outfile',
'over',
'partition',
'percent_rank',
'persist',
'persist_only',
'precision',
'primary',
'procedure',
'purge',
'range',
'rank',
'read',
'reads',
'read_write',
'real',
'recursive',
'references',
'regexp',
'release',
'rename',
'repeat',
'replace',
'require',
'resignal',
'restrict',
'return',
'revoke',
'right',
'rlike',
'row',
'rows',
'row_number',
'schema',
'schemas',
'second_microsecond',
'select',
'sensitive',
'separator',
'set',
'show',
'signal',
'smallint',
'spatial',
'specific',
'sql',
'sqlexception',
'sqlstate',
'sqlwarning',
'sql_big_result',
'sql_calc_found_rows',
'sql_small_result',
'ssl',
'starting',
'stored',
'straight_join',
'system',
'table',
'terminated',
'then',
'tinyblob',
'tinyint',
'tinytext',
'to',
'trailing',
'trigger',
'true',
'undo',
'union',
'unique',
'unlock',
'unsigned',
'update',
'usage',
'use',
'using',
'utc_date',
'utc_time',
'utc_timestamp',
'values',
'varbinary',
'varchar',
'varcharacter',
'varying',
'virtual',
'when',
'where',
'while',
'window',
'with',
'write',
'xor',
'year_month',
'zerofill',
);
public function __construct(array $connection_options = array()) { public function __construct(array $connection_options = array()) {
// This driver defaults to transaction support, except if explicitly passed FALSE. // This driver defaults to transaction support, except if explicitly passed FALSE.
$this->transactionSupport = !isset($connection_options['transactions']) || ($connection_options['transactions'] !== FALSE); $this->transactionSupport = !isset($connection_options['transactions']) || ($connection_options['transactions'] !== FALSE);
@ -86,15 +362,95 @@ class DatabaseConnection_mysql extends DatabaseConnection {
$connection_options += array( $connection_options += array(
'init_commands' => array(), 'init_commands' => array(),
); );
$sql_mode = 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO';
// NO_AUTO_CREATE_USER was removed in MySQL 8.0.11
// https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-11.html#mysqld-8-0-11-deprecation-removal
if (version_compare($this->getAttribute(PDO::ATTR_SERVER_VERSION), '8.0.11', '<')) {
$sql_mode .= ',NO_AUTO_CREATE_USER';
}
$connection_options['init_commands'] += array( $connection_options['init_commands'] += array(
'sql_mode' => "SET sql_mode = 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER'", 'sql_mode' => "SET sql_mode = '$sql_mode'",
); );
// Execute initial commands. // Execute initial commands.
foreach ($connection_options['init_commands'] as $sql) { foreach ($connection_options['init_commands'] as $sql) {
$this->exec($sql); $this->exec($sql);
} }
} }
/**
* {@inheritdoc}}
*/
protected function setPrefix($prefix) {
parent::setPrefix($prefix);
// Successive versions of MySQL have become increasingly strict about the
// use of reserved keywords as table names. Drupal 7 uses at least one such
// table (system). Therefore we surround all table names with quotes.
$quote_char = variable_get('mysql_identifier_quote_character', MYSQL_IDENTIFIER_QUOTE_CHARACTER_DEFAULT);
foreach ($this->prefixSearch as $i => $prefixSearch) {
if (substr($prefixSearch, 0, 1) === '{') {
// If the prefix already contains one or more quotes remove them.
// This can happen when - for example - DrupalUnitTestCase sets up a
// "temporary prefixed database". Also if there's a dot in the prefix,
// wrap it in quotes to cater for schema names in prefixes.
$search = array($quote_char, '.');
$replace = array('', $quote_char . '.' . $quote_char);
$this->prefixReplace[$i] = $quote_char . str_replace($search, $replace, $this->prefixReplace[$i]);
}
if (substr($prefixSearch, -1) === '}') {
$this->prefixReplace[$i] .= $quote_char;
}
}
}
/**
* {@inheritdoc}
*/
public function escapeField($field) {
$field = parent::escapeField($field);
return $this->quoteIdentifier($field);
}
public function escapeFields(array $fields) {
foreach ($fields as &$field) {
$field = $this->escapeField($field);
}
return $fields;
}
/**
* {@inheritdoc}
*/
public function escapeAlias($field) {
$field = parent::escapeAlias($field);
return $this->quoteIdentifier($field);
}
/**
* Quotes an identifier if it matches a MySQL reserved keyword.
*
* @param string $identifier
* The field to check.
*
* @return string
* The identifier, quoted if it matches a MySQL reserved keyword.
*/
private function quoteIdentifier($identifier) {
// Quote identifiers so that MySQL reserved words like 'function' can be
// used as column names. Sometimes the 'table.column_name' format is passed
// in. For example, menu_load_links() adds a condition on "ml.menu_name".
if (strpos($identifier, '.') !== FALSE) {
list($table, $identifier) = explode('.', $identifier, 2);
}
if (in_array(strtolower($identifier), $this->reservedKeyWords, TRUE)) {
// Quote the string for MySQL reserved keywords.
$quote_char = variable_get('mysql_identifier_quote_character', MYSQL_IDENTIFIER_QUOTE_CHARACTER_DEFAULT);
$identifier = $quote_char . $identifier . $quote_char;
}
return isset($table) ? $table . '.' . $identifier : $identifier;
}
public function __destruct() { public function __destruct() {
if ($this->needsCleanup) { if ($this->needsCleanup) {
$this->nextIdDelete(); $this->nextIdDelete();

View File

@ -48,6 +48,10 @@ class InsertQuery_mysql extends InsertQuery {
// Default fields are always placed first for consistency. // Default fields are always placed first for consistency.
$insert_fields = array_merge($this->defaultFields, $this->insertFields); $insert_fields = array_merge($this->defaultFields, $this->insertFields);
if (method_exists($this->connection, 'escapeFields')) {
$insert_fields = $this->connection->escapeFields($insert_fields);
}
// If we're selecting from a SelectQuery, finish building the query and // If we're selecting from a SelectQuery, finish building the query and
// pass it back, as any remaining options are irrelevant. // pass it back, as any remaining options are irrelevant.
if (!empty($this->fromQuery)) { if (!empty($this->fromQuery)) {
@ -89,6 +93,20 @@ class InsertQuery_mysql extends InsertQuery {
class TruncateQuery_mysql extends TruncateQuery { } class TruncateQuery_mysql extends TruncateQuery { }
class UpdateQuery_mysql extends UpdateQuery {
public function __toString() {
if (method_exists($this->connection, 'escapeField')) {
$escapedFields = array();
foreach ($this->fields as $field => $data) {
$field = $this->connection->escapeField($field);
$escapedFields[$field] = $data;
}
$this->fields = $escapedFields;
}
return parent::__toString();
}
}
/** /**
* @} End of "addtogroup database". * @} End of "addtogroup database".
*/ */

View File

@ -57,6 +57,11 @@ class DatabaseSchema_mysql extends DatabaseSchema {
protected function buildTableNameCondition($table_name, $operator = '=', $add_prefix = TRUE) { protected function buildTableNameCondition($table_name, $operator = '=', $add_prefix = TRUE) {
$info = $this->connection->getConnectionOptions(); $info = $this->connection->getConnectionOptions();
// Ensure the table name is not surrounded with quotes as that is not
// appropriate for schema queries.
$quote_char = variable_get('mysql_identifier_quote_character', MYSQL_IDENTIFIER_QUOTE_CHARACTER_DEFAULT);
$table_name = str_replace($quote_char, '', $table_name);
$table_info = $this->getPrefixInfo($table_name, $add_prefix); $table_info = $this->getPrefixInfo($table_name, $add_prefix);
$condition = new DatabaseCondition('AND'); $condition = new DatabaseCondition('AND');
@ -494,11 +499,11 @@ class DatabaseSchema_mysql extends DatabaseSchema {
$condition->condition('column_name', $column); $condition->condition('column_name', $column);
$condition->compile($this->connection, $this); $condition->compile($this->connection, $this);
// Don't use {} around information_schema.columns table. // Don't use {} around information_schema.columns table.
return $this->connection->query("SELECT column_comment FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments())->fetchField(); return $this->connection->query("SELECT column_comment AS column_comment FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments())->fetchField();
} }
$condition->compile($this->connection, $this); $condition->compile($this->connection, $this);
// Don't use {} around information_schema.tables table. // Don't use {} around information_schema.tables table.
$comment = $this->connection->query("SELECT table_comment FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchField(); $comment = $this->connection->query("SELECT table_comment AS table_comment FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchField();
// Work-around for MySQL 5.0 bug http://bugs.mysql.com/bug.php?id=11379 // Work-around for MySQL 5.0 bug http://bugs.mysql.com/bug.php?id=11379
return preg_replace('/; InnoDB free:.*$/', '', $comment); return preg_replace('/; InnoDB free:.*$/', '', $comment);
} }

View File

@ -169,6 +169,11 @@ require_once dirname(__FILE__) . '/query.inc';
*/ */
abstract class DatabaseSchema implements QueryPlaceholderInterface { abstract class DatabaseSchema implements QueryPlaceholderInterface {
/**
* The database connection.
*
* @var DatabaseConnection
*/
protected $connection; protected $connection;
/** /**
@ -343,7 +348,70 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
// couldn't use db_select() here because it would prefix // couldn't use db_select() here because it would prefix
// information_schema.tables and the query would fail. // information_schema.tables and the query would fail.
// Don't use {} around information_schema.tables table. // Don't use {} around information_schema.tables table.
return $this->connection->query("SELECT table_name FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchAllKeyed(0, 0); return $this->connection->query("SELECT table_name AS table_name FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchAllKeyed(0, 0);
}
/**
* Finds all tables that are like the specified base table name. This is a
* backport of the change made to findTables in Drupal 8 to work with virtual,
* un-prefixed table names. The original function is retained for Backwards
* Compatibility.
* @see https://www.drupal.org/node/2552435
*
* @param string $table_expression
* An SQL expression, for example "cache_%" (without the quotes).
*
* @return array
* Both the keys and the values are the matching tables.
*/
public function findTablesD8($table_expression) {
// Load all the tables up front in order to take into account per-table
// prefixes. The actual matching is done at the bottom of the method.
$condition = $this->buildTableNameCondition('%', 'LIKE');
$condition->compile($this->connection, $this);
$individually_prefixed_tables = $this->connection->getUnprefixedTablesMap();
$default_prefix = $this->connection->tablePrefix();
$default_prefix_length = strlen($default_prefix);
$tables = array();
// Normally, we would heartily discourage the use of string
// concatenation for conditionals like this however, we
// couldn't use db_select() here because it would prefix
// information_schema.tables and the query would fail.
// Don't use {} around information_schema.tables table.
$results = $this->connection->query("SELECT table_name AS table_name FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments());
foreach ($results as $table) {
// Take into account tables that have an individual prefix.
if (isset($individually_prefixed_tables[$table->table_name])) {
$prefix_length = strlen($this->connection->tablePrefix($individually_prefixed_tables[$table->table_name]));
}
elseif ($default_prefix && substr($table->table_name, 0, $default_prefix_length) !== $default_prefix) {
// This table name does not start the default prefix, which means that
// it is not managed by Drupal so it should be excluded from the result.
continue;
}
else {
$prefix_length = $default_prefix_length;
}
// Remove the prefix from the returned tables.
$unprefixed_table_name = substr($table->table_name, $prefix_length);
// The pattern can match a table which is the same as the prefix. That
// will become an empty string when we remove the prefix, which will
// probably surprise the caller, besides not being a prefixed table. So
// remove it.
if (!empty($unprefixed_table_name)) {
$tables[$unprefixed_table_name] = $unprefixed_table_name;
}
}
// Convert the table expression from its SQL LIKE syntax to a regular
// expression and escape the delimiter that will be used for matching.
$table_expression = str_replace(array('%', '_'), array('.*?', '.'), preg_quote($table_expression, '/'));
$tables = preg_grep('/^' . $table_expression . '$/i', $tables);
return $tables;
} }
/** /**

View File

@ -1520,13 +1520,16 @@ class SelectQuery extends Query implements SelectQueryInterface {
$fields = array(); $fields = array();
foreach ($this->tables as $alias => $table) { foreach ($this->tables as $alias => $table) {
if (!empty($table['all_fields'])) { if (!empty($table['all_fields'])) {
$fields[] = $this->connection->escapeTable($alias) . '.*'; $fields[] = $this->connection->escapeAlias($alias) . '.*';
} }
} }
foreach ($this->fields as $alias => $field) { foreach ($this->fields as $alias => $field) {
// Note that $field['table'] holds the table alias.
// @see \SelectQuery::addField
$table = isset($field['table']) ? $this->connection->escapeAlias($field['table']) . '.' : '';
// Always use the AS keyword for field aliases, as some // Always use the AS keyword for field aliases, as some
// databases require it (e.g., PostgreSQL). // databases require it (e.g., PostgreSQL).
$fields[] = (isset($field['table']) ? $this->connection->escapeTable($field['table']) . '.' : '') . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeAlias($field['alias']); $fields[] = $table . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeAlias($field['alias']);
} }
foreach ($this->expressions as $alias => $expression) { foreach ($this->expressions as $alias => $expression) {
$fields[] = $expression['expression'] . ' AS ' . $this->connection->escapeAlias($expression['alias']); $fields[] = $expression['expression'] . ' AS ' . $this->connection->escapeAlias($expression['alias']);
@ -1555,7 +1558,7 @@ class SelectQuery extends Query implements SelectQueryInterface {
// Don't use the AS keyword for table aliases, as some // Don't use the AS keyword for table aliases, as some
// databases don't support it (e.g., Oracle). // databases don't support it (e.g., Oracle).
$query .= $table_string . ' ' . $this->connection->escapeTable($table['alias']); $query .= $table_string . ' ' . $this->connection->escapeAlias($table['alias']);
if (!empty($table['condition'])) { if (!empty($table['condition'])) {
$query .= ' ON ' . $table['condition']; $query .= ' ON ' . $table['condition'];

View File

@ -107,6 +107,18 @@ class DatabaseConnection_sqlite extends DatabaseConnection {
$this->sqliteCreateFunction('substring_index', array($this, 'sqlFunctionSubstringIndex'), 3); $this->sqliteCreateFunction('substring_index', array($this, 'sqlFunctionSubstringIndex'), 3);
$this->sqliteCreateFunction('rand', array($this, 'sqlFunctionRand')); $this->sqliteCreateFunction('rand', array($this, 'sqlFunctionRand'));
// Enable the Write-Ahead Logging (WAL) option for SQLite if supported.
// @see https://www.drupal.org/node/2348137
// @see https://sqlite.org/wal.html
if (version_compare($version, '3.7') >= 0) {
$connection_options += array(
'init_commands' => array(),
);
$connection_options['init_commands'] += array(
'wal' => "PRAGMA journal_mode=WAL",
);
}
// Execute sqlite init_commands. // Execute sqlite init_commands.
if (isset($connection_options['init_commands'])) { if (isset($connection_options['init_commands'])) {
$this->exec(implode('; ', $connection_options['init_commands'])); $this->exec(implode('; ', $connection_options['init_commands']));
@ -128,10 +140,10 @@ class DatabaseConnection_sqlite extends DatabaseConnection {
$count = $this->query('SELECT COUNT(*) FROM ' . $prefix . '.sqlite_master WHERE type = :type AND name NOT LIKE :pattern', array(':type' => 'table', ':pattern' => 'sqlite_%'))->fetchField(); $count = $this->query('SELECT COUNT(*) FROM ' . $prefix . '.sqlite_master WHERE type = :type AND name NOT LIKE :pattern', array(':type' => 'table', ':pattern' => 'sqlite_%'))->fetchField();
// We can prune the database file if it doesn't have any tables. // We can prune the database file if it doesn't have any tables.
if ($count == 0) { if ($count == 0 && $this->connectionOptions['database'] != ':memory:') {
// Detach the database. // Detaching the database fails at this point, but no other queries
$this->query('DETACH DATABASE :schema', array(':schema' => $prefix)); // are executed after the connection is destructed so we can simply
// Destroy the database file. // remove the database file.
unlink($this->connectionOptions['database'] . '-' . $prefix); unlink($this->connectionOptions['database'] . '-' . $prefix);
} }
} }
@ -143,6 +155,18 @@ class DatabaseConnection_sqlite extends DatabaseConnection {
} }
} }
/**
* Gets all the attached databases.
*
* @return array
* An array of attached database names.
*
* @see DatabaseConnection_sqlite::__construct().
*/
public function getAttachedDatabases() {
return $this->attachedDatabases;
}
/** /**
* SQLite compatibility implementation for the IF() SQL function. * SQLite compatibility implementation for the IF() SQL function.
*/ */

View File

@ -23,7 +23,7 @@ class InsertQuery_sqlite extends InsertQuery {
if (!$this->preExecute()) { if (!$this->preExecute()) {
return NULL; return NULL;
} }
if (count($this->insertFields)) { if (count($this->insertFields) || !empty($this->fromQuery)) {
return parent::execute(); return parent::execute();
} }
else { else {
@ -36,7 +36,10 @@ class InsertQuery_sqlite extends InsertQuery {
$comments = $this->connection->makeComment($this->comments); $comments = $this->connection->makeComment($this->comments);
// Produce as many generic placeholders as necessary. // Produce as many generic placeholders as necessary.
$placeholders = array_fill(0, count($this->insertFields), '?'); $placeholders = array();
if (!empty($this->insertFields)) {
$placeholders = array_fill(0, count($this->insertFields), '?');
}
// If we're selecting from a SelectQuery, finish building the query and // If we're selecting from a SelectQuery, finish building the query and
// pass it back, as any remaining options are irrelevant. // pass it back, as any remaining options are irrelevant.

View File

@ -668,6 +668,9 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
$this->alterTable($table, $old_schema, $new_schema); $this->alterTable($table, $old_schema, $new_schema);
} }
/**
* {@inheritdoc}
*/
public function findTables($table_expression) { public function findTables($table_expression) {
// Don't add the prefix, $table_expression already includes the prefix. // Don't add the prefix, $table_expression already includes the prefix.
$info = $this->getPrefixInfo($table_expression, FALSE); $info = $this->getPrefixInfo($table_expression, FALSE);
@ -680,4 +683,32 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
)); ));
return $result->fetchAllKeyed(0, 0); return $result->fetchAllKeyed(0, 0);
} }
/**
* {@inheritdoc}
*/
public function findTablesD8($table_expression) {
$tables = array();
// The SQLite implementation doesn't need to use the same filtering strategy
// as the parent one because individually prefixed tables live in their own
// schema (database), which means that neither the main database nor any
// attached one will contain a prefixed table name, so we just need to loop
// over all known schemas and filter by the user-supplied table expression.
$attached_dbs = $this->connection->getAttachedDatabases();
foreach ($attached_dbs as $schema) {
// Can't use query placeholders for the schema because the query would
// have to be :prefixsqlite_master, which does not work. We also need to
// ignore the internal SQLite tables.
$result = db_query("SELECT name FROM " . $schema . ".sqlite_master WHERE type = :type AND name LIKE :table_name AND name NOT LIKE :pattern", array(
':type' => 'table',
':table_name' => $table_expression,
':pattern' => 'sqlite_%',
));
$tables += $result->fetchAllKeyed(0, 0);
}
return $tables;
}
} }

View File

@ -1361,7 +1361,10 @@ function _form_validate(&$elements, &$form_state, $form_id = NULL) {
// The following errors are always shown. // The following errors are always shown.
if (isset($elements['#needs_validation'])) { if (isset($elements['#needs_validation'])) {
// Verify that the value is not longer than #maxlength. // Verify that the value is not longer than #maxlength.
if (isset($elements['#maxlength']) && drupal_strlen($elements['#value']) > $elements['#maxlength']) { if (isset($elements['#maxlength']) && (isset($elements['#value']) && !is_scalar($elements['#value']))) {
form_error($elements, $t('An illegal value has been detected. Please contact the site administrator.'));
}
elseif (isset($elements['#maxlength']) && drupal_strlen($elements['#value']) > $elements['#maxlength']) {
form_error($elements, $t('!name cannot be longer than %max characters but is currently %length characters long.', array('!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title'], '%max' => $elements['#maxlength'], '%length' => drupal_strlen($elements['#value'])))); form_error($elements, $t('!name cannot be longer than %max characters but is currently %length characters long.', array('!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title'], '%max' => $elements['#maxlength'], '%length' => drupal_strlen($elements['#value']))));
} }
@ -4124,9 +4127,17 @@ function form_process_weight($element) {
$max_elements = variable_get('drupal_weight_select_max', DRUPAL_WEIGHT_SELECT_MAX); $max_elements = variable_get('drupal_weight_select_max', DRUPAL_WEIGHT_SELECT_MAX);
if ($element['#delta'] <= $max_elements) { if ($element['#delta'] <= $max_elements) {
$element['#type'] = 'select'; $element['#type'] = 'select';
$weights = array();
for ($n = (-1 * $element['#delta']); $n <= $element['#delta']; $n++) { for ($n = (-1 * $element['#delta']); $n <= $element['#delta']; $n++) {
$weights[$n] = $n; $weights[$n] = $n;
} }
if (isset($element['#default_value'])) {
$default_value = (int) $element['#default_value'];
if (!isset($weights[$default_value])) {
$weights[$default_value] = $default_value;
ksort($weights);
}
}
$element['#options'] = $weights; $element['#options'] = $weights;
$element += element_info('select'); $element += element_info('select');
} }

View File

@ -12,6 +12,12 @@
*/ */
define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE) ? "\r\n" : "\n"); define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE) ? "\r\n" : "\n");
/**
* Special characters, defined in RFC_2822.
*/
define('MAIL_RFC_2822_SPECIALS', '()<>[]:;@\,."');
/** /**
* Composes and optionally sends an e-mail message. * Composes and optionally sends an e-mail message.
* *
@ -148,8 +154,13 @@ function drupal_mail($module, $key, $to, $language, $params = array(), $from = N
// Return-Path headers should have a domain authorized to use the originating // Return-Path headers should have a domain authorized to use the originating
// SMTP server. // SMTP server.
$headers['From'] = $headers['Sender'] = $headers['Return-Path'] = $default_from; $headers['From'] = $headers['Sender'] = $headers['Return-Path'] = $default_from;
if (variable_get('mail_display_name_site_name', FALSE)) {
$display_name = variable_get('site_name', 'Drupal');
$headers['From'] = drupal_mail_format_display_name($display_name) . ' <' . $default_from . '>';
}
} }
if ($from) { if ($from && $from != $default_from) {
$headers['From'] = $from; $headers['From'] = $from;
} }
$message['headers'] = $headers; $message['headers'] = $headers;
@ -557,10 +568,59 @@ function drupal_html_to_text($string, $allowed_tags = NULL) {
return $output . $footnotes; return $output . $footnotes;
} }
/**
* Return a RFC-2822 compliant "display-name" component.
*
* The "display-name" component is used in mail header "Originator" fields
* (From, Sender, Reply-to) to give a human-friendly description of the
* address, i.e. From: My Display Name <xyz@example.org>. RFC-822 and
* RFC-2822 define its syntax and rules. This method gets as input a string
* to be used as "display-name" and formats it to be RFC compliant.
*
* @param string $string
* A string to be used as "display-name".
*
* @return string
* A RFC compliant version of the string, ready to be used as
* "display-name" in mail originator header fields.
*/
function drupal_mail_format_display_name($string) {
// Make sure we don't process html-encoded characters. They may create
// unneeded trouble if left encoded, besides they will be correctly
// processed if decoded.
$string = decode_entities($string);
// If string contains non-ASCII characters it must be (short) encoded
// according to RFC-2047. The output of a "B" (Base64) encoded-word is
// always safe to be used as display-name.
$safe_display_name = mime_header_encode($string, TRUE);
// Encoded-words are always safe to be used as display-name because don't
// contain any RFC 2822 "specials" characters. However
// mimeHeaderEncode() encodes a string only if it contains any
// non-ASCII characters, and leaves its value untouched (un-encoded) if
// ASCII only. For this reason in order to produce a valid display-name we
// still need to make sure there are no "specials" characters left.
if (preg_match('/[' . preg_quote(MAIL_RFC_2822_SPECIALS) . ']/', $safe_display_name)) {
// If string is already quoted, it may or may not be escaped properly, so
// don't trust it and reset.
if (preg_match('/^"(.+)"$/', $safe_display_name, $matches)) {
$safe_display_name = str_replace(array('\\\\', '\\"'), array('\\', '"'), $matches[1]);
}
// Transform the string in a RFC-2822 "quoted-string" by wrapping it in
// double-quotes. Also make sure '"' and '\' occurrences are escaped.
$safe_display_name = '"' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $safe_display_name) . '"';
}
return $safe_display_name;
}
/** /**
* Wraps words on a single line. * Wraps words on a single line.
* *
* Callback for array_walk() winthin drupal_wrap_mail(). * Callback for array_walk() within drupal_wrap_mail().
*/ */
function _drupal_wrap_mail_line(&$line, $key, $values) { function _drupal_wrap_mail_line(&$line, $key, $values) {
// Use soft-breaks only for purely quoted or unindented text. // Use soft-breaks only for purely quoted or unindented text.

View File

@ -1067,7 +1067,7 @@ function menu_tree_output($tree) {
// the active class accordingly. But local tasks do not appear in menu // the active class accordingly. But local tasks do not appear in menu
// trees, so if the current path is a local task, and this link is its // trees, so if the current path is a local task, and this link is its
// tab root, then we have to set the class manually. // tab root, then we have to set the class manually.
if ($data['link']['href'] == $router_item['tab_root_href'] && $data['link']['href'] != $_GET['q']) { if ($router_item && $data['link']['href'] == $router_item['tab_root_href'] && $data['link']['href'] != $_GET['q']) {
$data['link']['localized_options']['attributes']['class'][] = 'active'; $data['link']['localized_options']['attributes']['class'][] = 'active';
} }

View File

@ -1,4 +1,3 @@
/*! /*!
* jQuery JavaScript Library v1.4.4 * jQuery JavaScript Library v1.4.4
* http://jquery.com/ * http://jquery.com/

View File

@ -7,7 +7,7 @@ files[] = aggregator.test
configure = admin/config/services/aggregator/settings configure = admin/config/services/aggregator/settings
stylesheets[all][] = aggregator.css stylesheets[all][] = aggregator.css
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
files[] = block.test files[] = block.test
configure = admin/structure/block configure = admin/structure/block
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -13,7 +13,7 @@ regions[footer] = Footer
regions[highlighted] = Highlighted regions[highlighted] = Highlighted
regions[help] = Help regions[help] = Help
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
files[] = blog.test files[] = blog.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -7,7 +7,7 @@ files[] = book.test
configure = admin/content/book/settings configure = admin/content/book/settings
stylesheets[all][] = book.css stylesheets[all][] = book.css
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
files[] = color.test files[] = color.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -9,7 +9,7 @@ files[] = comment.test
configure = admin/content/comment configure = admin/content/comment
stylesheets[all][] = comment.css stylesheets[all][] = comment.css
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
files[] = contact.test files[] = contact.test
configure = admin/structure/contact configure = admin/structure/contact
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
files[] = contextual.test files[] = contextual.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -7,7 +7,7 @@ files[] = dashboard.test
dependencies[] = block dependencies[] = block
configure = admin/dashboard/customize configure = admin/dashboard/customize
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
files[] = dblog.test files[] = dblog.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -11,7 +11,7 @@ dependencies[] = field_sql_storage
required = TRUE required = TRUE
stylesheets[all][] = theme/field.css stylesheets[all][] = theme/field.css
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -7,7 +7,7 @@ dependencies[] = field
files[] = field_sql_storage.test files[] = field_sql_storage.test
required = TRUE required = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -313,9 +313,13 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
$field = array('field_name' => 'test_text', 'type' => 'text', 'settings' => array('max_length' => 255)); $field = array('field_name' => 'test_text', 'type' => 'text', 'settings' => array('max_length' => 255));
$field = field_create_field($field); $field = field_create_field($field);
// Attempt to update the field in a way that would break the storage. // Attempt to update the field in a way that would break the storage. The
// parenthesis suffix is needed because SQLite has *very* relaxed rules for
// data types, so we actually need to provide an invalid SQL syntax in order
// to break it.
// @see https://www.sqlite.org/datatype3.html
$prior_field = $field; $prior_field = $field;
$field['settings']['max_length'] = -1; $field['settings']['max_length'] = '-1)';
try { try {
field_update_field($field); field_update_field($field);
$this->fail(t('Update succeeded.')); $this->fail(t('Update succeeded.'));

View File

@ -7,7 +7,7 @@ dependencies[] = field
dependencies[] = options dependencies[] = options
files[] = tests/list.test files[] = tests/list.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ package = Testing
version = VERSION version = VERSION
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
dependencies[] = field dependencies[] = field
files[] = number.test files[] = number.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
dependencies[] = field dependencies[] = field
files[] = options.test files[] = options.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -7,7 +7,7 @@ dependencies[] = field
files[] = text.test files[] = text.test
required = TRUE required = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ files[] = field_test.entity.inc
version = VERSION version = VERSION
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
dependencies[] = field dependencies[] = field
files[] = field_ui.test files[] = field_ui.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
dependencies[] = field dependencies[] = field
files[] = tests/file.test files[] = tests/file.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -281,10 +281,11 @@ function file_ajax_upload() {
} }
// Otherwise just add the new content class on a placeholder. // Otherwise just add the new content class on a placeholder.
else { else {
$form['#suffix'] .= '<span class="ajax-new-content"></span>'; $form['#suffix'] = (isset($form['#suffix']) ? $form['#suffix'] : '') . '<span class="ajax-new-content"></span>';
} }
$form['#prefix'] .= theme('status_messages'); $form['#prefix'] = (isset($form['#prefix']) ? $form['#prefix'] : '') . theme('status_messages');
$output = drupal_render($form); $output = drupal_render($form);
$js = drupal_add_js(); $js = drupal_add_js();
$settings = drupal_array_merge_deep_array($js['settings']['data']); $settings = drupal_array_merge_deep_array($js['settings']['data']);

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -7,7 +7,7 @@ files[] = filter.test
required = TRUE required = TRUE
configure = admin/config/content/formats configure = admin/config/content/formats
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -9,7 +9,7 @@ files[] = forum.test
configure = admin/structure/forum configure = admin/structure/forum
stylesheets[all][] = forum.css stylesheets[all][] = forum.css
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
files[] = help.test files[] = help.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -7,7 +7,7 @@ dependencies[] = file
files[] = image.test files[] = image.test
configure = admin/config/media/image-styles configure = admin/config/media/image-styles
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
files[] = image_module_test.module files[] = image_module_test.module
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
files[] = locale.test files[] = locale.test
configure = admin/config/regional/language configure = admin/config/regional/language
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -564,6 +564,7 @@ function locale_language_types_info() {
* Implements hook_language_negotiation_info(). * Implements hook_language_negotiation_info().
*/ */
function locale_language_negotiation_info() { function locale_language_negotiation_info() {
require_once DRUPAL_ROOT . '/includes/locale.inc';
$file = 'includes/locale.inc'; $file = 'includes/locale.inc';
$providers = array(); $providers = array();

View File

@ -5,7 +5,7 @@ package = Testing
version = VERSION version = VERSION
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
files[] = menu.test files[] = menu.test
configure = admin/structure/menu configure = admin/structure/menu
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -9,7 +9,7 @@ required = TRUE
configure = admin/structure/types configure = admin/structure/types
stylesheets[all][] = node.css stylesheets[all][] = node.css
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ package = Core
core = 7.x core = 7.x
files[] = openid.test files[] = openid.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
dependencies[] = openid dependencies[] = openid
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -4,7 +4,7 @@ package = Core
version = VERSION version = VERSION
core = 7.x core = 7.x
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
files[] = path.test files[] = path.test
configure = admin/config/search/path configure = admin/config/search/path
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
files[] = php.test files[] = php.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
files[] = poll.test files[] = poll.test
stylesheets[all][] = poll.css stylesheets[all][] = poll.css
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -11,7 +11,7 @@ configure = admin/config/people/profile
; See user_system_info_alter(). ; See user_system_info_alter().
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
files[] = rdf.test files[] = rdf.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
hidden = TRUE hidden = TRUE
dependencies[] = blog dependencies[] = blog
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -8,7 +8,7 @@ files[] = search.test
configure = admin/config/search/settings configure = admin/config/search/settings
stylesheets[all][] = search.css stylesheets[all][] = search.css
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
files[] = shortcut.test files[] = shortcut.test
configure = admin/config/user-interface/shortcut configure = admin/config/user-interface/shortcut
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -1677,15 +1677,12 @@ class DrupalWebTestCase extends DrupalTestCase {
file_unmanaged_delete_recursive($this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10)); file_unmanaged_delete_recursive($this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10));
// Remove all prefixed tables. // Remove all prefixed tables.
$tables = db_find_tables($this->databasePrefix . '%'); $tables = db_find_tables_d8('%');
$connection_info = Database::getConnectionInfo('default');
$tables = db_find_tables($connection_info['default']['prefix']['default'] . '%');
if (empty($tables)) { if (empty($tables)) {
$this->fail('Failed to find test tables to drop.'); $this->fail('Failed to find test tables to drop.');
} }
$prefix_length = strlen($connection_info['default']['prefix']['default']);
foreach ($tables as $table) { foreach ($tables as $table) {
if (db_drop_table(substr($table, $prefix_length))) { if (db_drop_table($table)) {
unset($tables[$table]); unset($tables[$table]);
} }
} }

View File

@ -58,7 +58,7 @@ files[] = tests/upgrade/update.trigger.test
files[] = tests/upgrade/update.field.test files[] = tests/upgrade/update.field.test
files[] = tests/upgrade/update.user.test files[] = tests/upgrade/update.user.test
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -563,7 +563,7 @@ function simpletest_clean_environment() {
* Removed prefixed tables from the database that are left over from crashed tests. * Removed prefixed tables from the database that are left over from crashed tests.
*/ */
function simpletest_clean_database() { function simpletest_clean_database() {
$tables = db_find_tables(Database::getConnection()->prefixTables('{simpletest}') . '%'); $tables = db_find_tables_d8(Database::getConnection()->prefixTables('{simpletest}') . '%');
$schema = drupal_get_schema_unprocessed('simpletest'); $schema = drupal_get_schema_unprocessed('simpletest');
$count = 0; $count = 0;
foreach (array_diff_key($tables, $schema) as $table) { foreach (array_diff_key($tables, $schema) as $table) {

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ package = Testing
version = VERSION version = VERSION
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ package = Testing
version = VERSION version = VERSION
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ package = Testing
version = VERSION version = VERSION
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -2051,6 +2051,32 @@ class DrupalRenderTestCase extends DrupalWebTestCase {
// The elements should appear in output in the same order as the array. // The elements should appear in output in the same order as the array.
$this->assertTrue(strpos($output, $second) < strpos($output, $first), 'Elements were not sorted.'); $this->assertTrue(strpos($output, $second) < strpos($output, $first), 'Elements were not sorted.');
// The order of children with same weight should be preserved.
$element_mixed_weight = array(
'child5' => array('#weight' => 10),
'child3' => array('#weight' => -10),
'child1' => array(),
'child4' => array('#weight' => 10),
'child2' => array(),
'child6' => array('#weight' => 10),
'child9' => array(),
'child8' => array('#weight' => 10),
'child7' => array(),
);
$expected = array(
'child3',
'child1',
'child2',
'child9',
'child7',
'child5',
'child4',
'child6',
'child8',
);
$this->assertEqual($expected, element_children($element_mixed_weight, TRUE), 'Order of elements with the same weight is preserved.');
} }
/** /**

View File

@ -7,7 +7,7 @@ stylesheets[all][] = common_test.css
stylesheets[print][] = common_test.print.css stylesheets[print][] = common_test.print.css
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ package = Testing
version = VERSION version = VERSION
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -217,5 +217,24 @@ function database_test_schema() {
), ),
); );
$schema['virtual'] = array(
'description' => 'Basic test table with a reserved name.',
'fields' => array(
'id' => array(
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
),
'function' => array(
'description' => "A column with a reserved name.",
'type' => 'varchar',
'length' => 255,
'not null' => FALSE,
'default' => '',
),
),
'primary key' => array('id'),
);
return $schema; return $schema;
} }

View File

@ -163,6 +163,12 @@ class DatabaseTestCase extends DrupalWebTestCase {
'priority' => 3, 'priority' => 3,
)) ))
->execute(); ->execute();
db_insert('virtual')
->fields(array(
'function' => 'Function value 1',
))
->execute();
} }
} }
@ -3457,7 +3463,6 @@ class DatabaseQueryTestCase extends DatabaseTestCase {
->fetchField(); ->fetchField();
$this->assertFalse($result, 'SQL injection attempt did not result in a row being inserted in the database table.'); $this->assertFalse($result, 'SQL injection attempt did not result in a row being inserted in the database table.');
} }
} }
/** /**
@ -4033,6 +4038,8 @@ class ConnectionUnitTest extends DrupalUnitTestCase {
protected $monitor; protected $monitor;
protected $originalCount; protected $originalCount;
protected $skipTest;
public static function getInfo() { public static function getInfo() {
return array( return array(
'name' => 'Connection unit tests', 'name' => 'Connection unit tests',
@ -4053,7 +4060,7 @@ class ConnectionUnitTest extends DrupalUnitTestCase {
// @todo Make this test driver-agnostic, or find a proper way to skip it. // @todo Make this test driver-agnostic, or find a proper way to skip it.
// @see http://drupal.org/node/1273478 // @see http://drupal.org/node/1273478
$connection_info = Database::getConnectionInfo('default'); $connection_info = Database::getConnectionInfo('default');
$this->skipTest = (bool) $connection_info['default']['driver'] != 'mysql'; $this->skipTest = (bool) ($connection_info['default']['driver'] != 'mysql');
if ($this->skipTest) { if ($this->skipTest) {
// Insert an assertion to prevent Simpletest from interpreting the test // Insert an assertion to prevent Simpletest from interpreting the test
// as failure. // as failure.
@ -4238,5 +4245,178 @@ class ConnectionUnitTest extends DrupalUnitTestCase {
// Verify that we are back to the original connection count. // Verify that we are back to the original connection count.
$this->assertNoConnection($id); $this->assertNoConnection($id);
} }
}
/**
* Test reserved keyword handling (introduced for MySQL 8+)
*/
class DatabaseReservedKeywordTestCase extends DatabaseTestCase {
public static function getInfo() {
return array(
'name' => 'Reserved Keywords',
'description' => 'Test handling of reserved keywords.',
'group' => 'Database',
);
}
function setUp() {
parent::setUp('database_test');
}
public function testTableNameQuoting() {
// Test db_query with {table} pattern.
$record = db_query('SELECT * FROM {system} LIMIT 1')->fetchObject();
$this->assertTrue(isset($record->filename), 'Successfully queried the {system} table.');
$connection = Database::getConnection()->getConnectionOptions();
if ($connection['driver'] === 'sqlite') {
// In SQLite simpletest's prefixed db tables exist in their own schema
// (e.g. simpletest124904.system), so we cannot test the schema.{table}
// syntax here as the table name will have the schema name prepended to it
// when prefixes are processed.
$this->assert(TRUE, 'Skipping schema.{system} test for SQLite.');
}
else {
$database = $connection['database'];
// Test db_query with schema.{table} pattern
db_query('SELECT * FROM ' . $database . '.{system} LIMIT 1')->fetchObject();
$this->assertTrue(isset($record->filename), 'Successfully queried the schema.{system} table.');
}
}
public function testSelectReservedWordTableCount() {
$rows = db_select('virtual')
->countQuery()
->execute()
->fetchField();
$this->assertEqual($rows, 1, 'Successful count query on a table with a reserved name.');
}
public function testSelectReservedWordTableSpecificField() {
$record = db_select('virtual')
->fields('virtual', array('function'))
->execute()
->fetchAssoc();
$this->assertEqual($record['function'], 'Function value 1', 'Successfully read a field from a table with a name and column which are reserved words.');
}
public function testSelectReservedWordTableAllFields() {
$record = db_select('virtual')
->fields('virtual')
->execute()
->fetchAssoc();
$this->assertEqual($record['function'], 'Function value 1', 'Successful all_fields query from a table with a name and column which are reserved words.');
}
public function testSelectReservedWordAliasCount() {
$rows = db_select('test', 'character')
->countQuery()
->execute()
->fetchField();
$this->assertEqual($rows, 4, 'Successful count query using an alias which is a reserved word.');
}
public function testSelectReservedWordAliasSpecificFields() {
$record = db_select('test', 'high_priority')
->fields('high_priority', array('name'))
->condition('age', 27)
->execute()->fetchAssoc();
$this->assertEqual($record['name'], 'George', 'Successful query using an alias which is a reserved word.');
}
public function testSelectReservedWordAliasAllFields() {
$record = db_select('test', 'high_priority')
->fields('high_priority')
->condition('age', 27)
->execute()->fetchAssoc();
$this->assertEqual($record['name'], 'George', 'Successful all_fields query using an alias which is a reserved word.');
}
public function testInsertReservedWordTable() {
$num_records_before = db_query('SELECT COUNT(*) FROM {virtual}')->fetchField();
db_insert('virtual')
->fields(array(
'function' => 'Inserted function',
))
->execute();
$num_records_after = db_query('SELECT COUNT(*) FROM {virtual}')->fetchField();
$this->assertIdentical($num_records_before + 1, (int) $num_records_after, 'Successful insert into a table with a name and column which are reserved words.');
}
public function testDeleteReservedWordTable() {
$delete = db_delete('virtual')
->condition('function', 'Function value 1');
$num_deleted = $delete->execute();
$this->assertEqual($num_deleted, 1, "Deleted 1 record from a table with a name and column which are reserved words..");
}
function testTruncateReservedWordTable() {
db_truncate('virtual')->execute();
$num_records_after = db_query("SELECT COUNT(*) FROM {virtual}")->fetchField();
$this->assertEqual(0, $num_records_after, 'Truncated a table with a reserved name.');
}
function testUpdateReservedWordTable() {
$num_updated = db_update('virtual')
->fields(array('function' => 'Updated function'))
->execute();
$this->assertIdentical($num_updated, 1, 'Updated 1 record in a table with a name and column which are reserved words.');
}
function testMergeReservedWordTable() {
$key = db_query('SELECT id FROM {virtual} LIMIT 1')->fetchField();
$num_records_before = db_query('SELECT COUNT(*) FROM {virtual}')->fetchField();
db_merge('virtual')
->key(array('id' => $key))
->fields(array('function' => 'Merged function'))
->execute();
$num_records_after = db_query('SELECT COUNT(*) FROM {virtual}')->fetchField();
$this->assertIdentical($num_records_before, $num_records_after, 'Successful merge query on a table with a name and column which are reserved words.');
}
}
/**
* Test table prefix handling.
*/
class DatabaseTablePrefixTestCase extends DatabaseTestCase {
public static function getInfo() {
return array(
'name' => 'Table prefixes',
'description' => 'Test handling of table prefixes.',
'group' => 'Database',
);
}
public function testSchemaDotTablePrefixes() {
// Get a copy of the default connection options.
$db = Database::getConnection('default', 'default');
$connection_options = $db->getConnectionOptions();
if ($connection_options['driver'] === 'sqlite') {
// In SQLite simpletest's prefixed db tables exist in their own schema
// (e.g. simpletest124904.system), so we cannot test the schema.table
// prefix syntax here.
$this->assert(TRUE, 'Skipping schema.table prefixed tables test for SQLite.');
return;
}
$db_name = $connection_options['database'];
// This prefix is usually something like simpletest12345
$test_prefix = $connection_options['prefix']['default'];
// Set up a new connection with table prefixes in the form "schema.table"
$prefixed = $connection_options;
$prefixed['prefix'] = array(
'default' => $test_prefix,
'users' => $db_name . '.' . $test_prefix,
'role' => $db_name . '.' . $test_prefix,
);
Database::addConnectionInfo('default', 'prefixed', $prefixed);
// Test that the prefixed database connection can query the prefixed tables.
$num_users_prefixed = Database::getConnection('prefixed', 'default')->query('SELECT COUNT(1) FROM {users}')->fetchField();
$this->assertTrue((int) $num_users_prefixed > 0, 'Successfully queried the users table using a schema.table prefix');
$num_users_default = Database::getConnection('default', 'default')->query('SELECT COUNT(1) FROM {users}')->fetchField();
$this->assertEqual($num_users_default, $num_users_prefixed, 'Verified results of query using a connection with schema.table prefixed tables');
}
} }

View File

@ -7,7 +7,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
dependencies[] = entity_cache_test_dependency dependencies[] = entity_cache_test_dependency
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ package = Testing
version = VERSION version = VERSION
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -6,7 +6,7 @@ core = 7.x
files[] = file_test.module files[] = file_test.module
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -591,6 +591,19 @@ class FormElementTestCase extends DrupalWebTestCase {
))); )));
} }
} }
/**
* Tests Weight form element #default_value behavior.
*/
public function testWeightDefaultValue() {
$element = array(
'#type' => 'weight',
'#delta' => 10,
'#default_value' => 15,
);
$element = form_process_weight($element);
$this->assertTrue(isset($element['#options'][$element['#default_value']]), 'Default value exists in #options list');
}
} }
/** /**

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

View File

@ -59,6 +59,81 @@ class MailTestCase extends DrupalWebTestCase implements MailSystemInterface {
$this->assertNull(self::$sent_message, 'Message was canceled.'); $this->assertNull(self::$sent_message, 'Message was canceled.');
} }
/**
* Checks for the site name in an auto-generated From: header.
*/
function testFromHeader() {
global $language;
$default_from = variable_get('site_mail', ini_get('sendmail_from'));
$site_name = variable_get('site_name', 'Drupal');
// Reset the class variable holding a copy of the last sent message.
self::$sent_message = NULL;
// Send an e-mail with a sender address specified.
$from_email = 'someone_else@example.com';
$message = drupal_mail('simpletest', 'from_test', 'from_test@example.com', $language, array(), $from_email);
// Test that the from e-mail is just the e-mail and not the site name and
// default sender e-mail.
$this->assertEqual($from_email, self::$sent_message['headers']['From']);
// Check default behavior is only email in FROM header.
self::$sent_message = NULL;
// Send an e-mail and check that the From-header contains only default mail address.
variable_del('mail_display_name_site_name');
$message = drupal_mail('simpletest', 'from_test', 'from_test@example.com', $language);
$this->assertEqual($default_from, self::$sent_message['headers']['From']);
self::$sent_message = NULL;
// Send an e-mail and check that the From-header contains the site name.
variable_set('mail_display_name_site_name', TRUE);
$message = drupal_mail('simpletest', 'from_test', 'from_test@example.com', $language);
$this->assertEqual($site_name . ' <' . $default_from . '>', self::$sent_message['headers']['From']);
}
/**
* Checks for the site name in an auto-generated From: header.
*/
function testFromHeaderRfc2822Compliant() {
global $language;
$default_from = variable_get('site_mail', ini_get('sendmail_from'));
// Enable adding a site name to From.
variable_set('mail_display_name_site_name', TRUE);
$site_names = array(
// Simple ASCII characters.
'Test site' => 'Test site',
// ASCII with html entity.
'Test &amp; site' => 'Test & site',
// Non-ASCII characters.
'Tést site' => '=?UTF-8?B?VMOpc3Qgc2l0ZQ==?=',
// Non-ASCII with special characters.
'Tést; site' => '=?UTF-8?B?VMOpc3Q7IHNpdGU=?=',
// Non-ASCII with html entity.
'T&eacute;st; site' => '=?UTF-8?B?VMOpc3Q7IHNpdGU=?=',
// ASCII with special characters.
'Test; site' => '"Test; site"',
// ASCII with special characters as html entity.
'Test &lt; site' => '"Test < site"',
// ASCII with special characters and '\'.
'Test; \ "site"' => '"Test; \\\\ \"site\""',
// String already RFC-2822 compliant.
'"Test; site"' => '"Test; site"',
// String already RFC-2822 compliant.
'"Test; \\\\ \"site\""' => '"Test; \\\\ \"site\""',
);
foreach ($site_names as $original_name => $safe_string) {
variable_set('site_name', $original_name);
// Reset the class variable holding a copy of the last sent message.
self::$sent_message = NULL;
// Send an e-mail and check that the From-header contains is RFC-2822 compliant.
drupal_mail('simpletest', 'from_test', 'from_test@example.com', $language);
$this->assertEqual($safe_string . ' <' . $default_from . '>', self::$sent_message['headers']['From']);
}
}
/** /**
* Concatenate and wrap the e-mail body for plain-text mails. * Concatenate and wrap the e-mail body for plain-text mails.
* *

View File

@ -5,7 +5,7 @@ version = VERSION
core = 7.x core = 7.x
hidden = TRUE hidden = TRUE
; Information added by Drupal.org packaging script on 2020-11-26 ; Information added by Drupal.org packaging script on 2020-12-03
version = "7.75" version = "7.77"
project = "drupal" project = "drupal"
datestamp = "1606357834" datestamp = "1607003447"

Some files were not shown because too many files have changed in this diff Show More