Skip to content

Commit

Permalink
Update to Drupal 7.90. For more information, see https://www.drupal.o…
Browse files Browse the repository at this point in the history
  • Loading branch information
Pantheon Automation authored and greg-1-anderson committed Jun 1, 2022
1 parent c809267 commit 3f5ccbf
Show file tree
Hide file tree
Showing 41 changed files with 570 additions and 42 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Drupal 7.90, 2022-06-01
-----------------------
- Improved support for PHP 8.1
- Improved support for PostgreSQL
- Various bug fixes, optimizations and improvements

Drupal 7.89, 2022-03-02
-----------------------
- Bug fixes for PHP 8.1
Expand Down
6 changes: 3 additions & 3 deletions includes/bootstrap.inc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* The current system version.
*/
define('VERSION', '7.89');
define('VERSION', '7.90');

/**
* Core API compatibility.
Expand Down Expand Up @@ -1627,7 +1627,7 @@ function drupal_page_header() {
*/
function drupal_serve_page_from_cache(stdClass $cache) {
// Negotiate whether to use compression.
$page_compression = !empty($cache->data['page_compressed']);
$page_compression = !empty($cache->data['page_compressed']) && !empty($cache->data['body']);
$return_compressed = $page_compression && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE;

// Get headers set in hook_boot(). Keys are lower-case.
Expand Down Expand Up @@ -1958,7 +1958,7 @@ function check_plain($text) {
* TRUE if the text is valid UTF-8, FALSE if not.
*/
function drupal_validate_utf8($text) {
if (strlen($text) == 0) {
if (strlen((string) $text) == 0) {
return TRUE;
}
// With the PCRE_UTF8 modifier 'u', preg_match() fails silently on strings
Expand Down
13 changes: 10 additions & 3 deletions includes/common.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1500,7 +1500,7 @@ function filter_xss($string, $allowed_tags = array('a', 'em', 'strong', 'cite',
// Store the text format.
_filter_xss_split($allowed_tags, TRUE);
// Remove NULL characters (ignored by some browsers).
$string = str_replace(chr(0), '', $string);
$string = str_replace(chr(0), '', (string) $string);
// Remove Netscape 4 JS entities.
$string = preg_replace('%&\s*\{[^}]*(\}\s*;?|$)%', '', $string);

Expand Down Expand Up @@ -2696,6 +2696,7 @@ function drupal_deliver_html_page($page_callback_result) {
if ($frame_options && is_null(drupal_get_http_header('X-Frame-Options'))) {
drupal_add_http_header('X-Frame-Options', $frame_options);
}
drupal_add_http_header('X-Content-Type-Options', 'nosniff');

if (variable_get('block_interest_cohort', TRUE)) {
$permissions_policy = drupal_get_http_header('Permissions-Policy');
Expand Down Expand Up @@ -8051,8 +8052,14 @@ function entity_extract_ids($entity_type, $entity) {
$info = entity_get_info($entity_type);

// Objects being created might not have id/vid yet.
$id = isset($entity->{$info['entity keys']['id']}) ? $entity->{$info['entity keys']['id']} : NULL;
$vid = ($info['entity keys']['revision'] && isset($entity->{$info['entity keys']['revision']})) ? $entity->{$info['entity keys']['revision']} : NULL;
if (!empty($info)) {
$id = isset($entity->{$info['entity keys']['id']}) ? $entity->{$info['entity keys']['id']} : NULL;
$vid = ($info['entity keys']['revision'] && isset($entity->{$info['entity keys']['revision']})) ? $entity->{$info['entity keys']['revision']} : NULL;
}
else {
$id = NULL;
$vid = NULL;
}

if (!empty($info['entity keys']['bundle'])) {
// Explicitly fail for malformed entities missing the bundle property.
Expand Down
133 changes: 125 additions & 8 deletions includes/database/pgsql/schema.inc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

class DatabaseSchema_pgsql extends DatabaseSchema {

/**
* PostgreSQL's temporary namespace name.
*
* @var string
*/
protected $tempNamespaceName;

/**
* A cache of information about blob columns and sequences of tables.
*
Expand Down Expand Up @@ -97,23 +104,47 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
public function queryTableInformation($table) {
// Generate a key to reference this table's information on.
$key = $this->connection->prefixTables('{' . $table . '}');
if (!strpos($key, '.')) {

// Take into account that temporary tables are stored in a different schema.
// \DatabaseConnection::generateTemporaryTableName() sets 'db_temporary_'
// prefix to all temporary tables.
if (strpos($key, '.') === FALSE && strpos($table, 'db_temporary_') === FALSE) {
$key = 'public.' . $key;
}
else {
$key = $this->getTempNamespaceName() . '.' . $key;
}

if (!isset($this->tableInformation[$key])) {
// Split the key into schema and table for querying.
list($schema, $table_name) = explode('.', $key);
$table_information = (object) array(
'blob_fields' => array(),
'sequences' => array(),
);
// Don't use {} around information_schema.columns table.
$result = $this->connection->query("SELECT column_name, data_type, column_default FROM information_schema.columns WHERE table_schema = :schema AND table_name = :table AND (data_type = 'bytea' OR (numeric_precision IS NOT NULL AND column_default LIKE :default))", array(
':schema' => $schema,
':table' => $table_name,
':default' => '%nextval%',

// The bytea columns and sequences for a table can be found in
// pg_attribute, which is significantly faster than querying the
// information_schema. The data type of a field can be found by lookup
// of the attribute ID, and the default value must be extracted from the
// node tree for the attribute definition instead of the historical
// human-readable column, adsrc.
$sql = <<<'EOD'
SELECT pg_attribute.attname AS column_name, format_type(pg_attribute.atttypid, pg_attribute.atttypmod) AS data_type, pg_get_expr(pg_attrdef.adbin, pg_attribute.attrelid) AS column_default
FROM pg_attribute
LEFT JOIN pg_attrdef ON pg_attrdef.adrelid = pg_attribute.attrelid AND pg_attrdef.adnum = pg_attribute.attnum
WHERE pg_attribute.attnum > 0
AND NOT pg_attribute.attisdropped
AND pg_attribute.attrelid = :key::regclass
AND (format_type(pg_attribute.atttypid, pg_attribute.atttypmod) = 'bytea'
OR pg_get_expr(pg_attrdef.adbin, pg_attribute.attrelid) LIKE 'nextval%')
EOD;
$result = $this->connection->query($sql, array(
':key' => $key,
));

if (empty($result)) {
return $table_information;
}

foreach ($result as $column) {
if ($column->data_type == 'bytea') {
$table_information->blob_fields[$column->column_name] = TRUE;
Expand All @@ -131,6 +162,19 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
return $this->tableInformation[$key];
}

/**
* Gets PostgreSQL's temporary namespace name.
*
* @return string
* PostgreSQL's temporary namespace anme.
*/
protected function getTempNamespaceName() {
if (!isset($this->tempNamespaceName)) {
$this->tempNamespaceName = $this->connection->query('SELECT nspname FROM pg_namespace WHERE oid = pg_my_temp_schema()')->fetchField();
}
return $this->tempNamespaceName;
}

/**
* Fetch the list of CHECK constraints used on a field.
*
Expand Down Expand Up @@ -370,6 +414,68 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
return implode(', ', $return);
}

/**
* {@inheritdoc}
*/
public function tableExists($table) {
// In PostgreSQL "unquoted names are always folded to lower case."
// @see DatabaseSchema_pgsql::buildTableNameCondition().
$prefixInfo = $this->getPrefixInfo(strtolower($table), TRUE);

return (bool) $this->connection->query("SELECT 1 FROM pg_tables WHERE schemaname = :schema AND tablename = :table", array(':schema' => $prefixInfo['schema'], ':table' => $prefixInfo['table']))->fetchField();
}

/**
* {@inheritdoc}
*/
public function findTables($table_expression) {
$individually_prefixed_tables = $this->connection->getUnprefixedTablesMap();
$default_prefix = $this->connection->tablePrefix();
$default_prefix_length = strlen($default_prefix);
$tables = array();

// 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.
$results = $this->connection->query("SELECT tablename FROM pg_tables WHERE schemaname = :schema", array(':schema' => $this->defaultSchema));
foreach ($results as $table) {
// Take into account tables that have an individual prefix.
if (isset($individually_prefixed_tables[$table->tablename])) {
$prefix_length = strlen($this->connection->tablePrefix($individually_prefixed_tables[$table->tablename]));
}
elseif ($default_prefix && substr($table->tablename, 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->tablename, $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;
}
}

// Need to use strtolower on the table name as it was used previously by
// DatabaseSchema_pgsql::buildTableNameCondition().
// @see https://www.drupal.org/project/drupal/issues/3262341
$table_expression = strtolower($table_expression);

// 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;
}

function renameTable($table, $new_name) {
if (!$this->tableExists($table)) {
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot rename @table to @table_new: table @table doesn't exist.", array('@table' => $table, '@table_new' => $new_name)));
Expand Down Expand Up @@ -493,6 +599,17 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
$this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN "' . $field . '" DROP DEFAULT');
}

/**
* {@inheritdoc}
*/
public function fieldExists($table, $column) {
// In PostgreSQL "unquoted names are always folded to lower case."
// @see DatabaseSchema_pgsql::buildTableNameCondition().
$prefixInfo = $this->getPrefixInfo(strtolower($table));

return (bool) $this->connection->query("SELECT 1 FROM pg_attribute WHERE attrelid = :key::regclass AND attname = :column AND NOT attisdropped AND attnum > 0", array(':key' => $prefixInfo['schema'] . '.' . $prefixInfo['table'], ':column' => $column))->fetchField();
}

public function indexExists($table, $name) {
// Details https://www.postgresql.org/docs/10/view-pg-indexes.html
$index_name = $this->ensureIdentifiersLength($table, $name, 'idx');
Expand Down
5 changes: 4 additions & 1 deletion includes/entity.inc
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,10 @@ class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
* Callback for array_filter that removes non-integer IDs.
*/
protected function filterId($id) {
return is_numeric($id) && $id == (int) $id;
// ctype_digit() is used here instead of a strict comparison as sometimes
// the id is passed as a string containing '0' which may represent a bug
// elsewhere but would fail with a strict comparison.
return is_numeric($id) && $id == (int) $id && ctype_digit((string) $id);
}

/**
Expand Down
4 changes: 4 additions & 0 deletions includes/file.inc
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,10 @@ SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<IfModule mod_php7.c>
php_flag engine off
</IfModule>
# From PHP 8 there is no number in the module name.
<IfModule mod_php.c>
php_flag engine off
</IfModule>
EOF;

if ($private) {
Expand Down
2 changes: 1 addition & 1 deletion includes/locale.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1603,7 +1603,7 @@ function _locale_parse_js_file($filepath) {
if ($source) {
// We already have this source string and now have to add the location
// to the location column, if this file is not yet present in there.
$locations = preg_split('~\s*;\s*~', $source->location);
$locations = preg_split('~\s*;\s*~', (string) $source->location);

if (!in_array($filepath, $locations)) {
$locations[] = $filepath;
Expand Down
9 changes: 6 additions & 3 deletions modules/comment/comment.module
Original file line number Diff line number Diff line change
Expand Up @@ -1918,7 +1918,6 @@ function comment_form($form, &$form_state, $comment) {
if ($is_admin) {
$author = (!$comment->uid && $comment->name ? $comment->name : $comment->registered_name);
$status = (isset($comment->status) ? $comment->status : COMMENT_NOT_PUBLISHED);
$date = (!empty($comment->date) ? $comment->date : format_date($comment->created, 'custom', 'Y-m-d H:i O'));
}
else {
if ($user->uid) {
Expand All @@ -1928,7 +1927,11 @@ function comment_form($form, &$form_state, $comment) {
$author = ($comment->name ? $comment->name : '');
}
$status = (user_access('skip comment approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED);
$date = '';
}

$date = '';
if ($comment->cid) {
$date = !empty($comment->date) ? $comment->date : format_date($comment->created, 'custom', 'Y-m-d H:i:s O');
}

// Add the author name field depending on the current user.
Expand Down Expand Up @@ -2176,7 +2179,7 @@ function comment_submit($comment) {
if (empty($comment->date)) {
$comment->date = 'now';
}
$comment->created = strtotime($comment->date);
$comment->created = strtotime($comment->date, REQUEST_TIME);
$comment->changed = REQUEST_TIME;

// If the comment was posted by a registered user, assign the author's ID.
Expand Down
13 changes: 11 additions & 2 deletions modules/comment/comment.test
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,7 @@ class CommentPreviewTest extends CommentHelperCase {
*/
function testCommentEditPreviewSave() {
$langcode = LANGUAGE_NONE;
$web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'skip comment approval'));
$web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'skip comment approval', 'edit own comments'));
$this->drupalLogin($this->admin_user);
$this->setCommentPreview(DRUPAL_OPTIONAL);
$this->setCommentForm(TRUE);
Expand All @@ -1017,7 +1017,7 @@ class CommentPreviewTest extends CommentHelperCase {
$edit['date'] = '2008-03-02 17:23 +0300';
$raw_date = strtotime($edit['date']);
$expected_text_date = format_date($raw_date);
$expected_form_date = format_date($raw_date, 'custom', 'Y-m-d H:i O');
$expected_form_date = format_date($raw_date, 'custom', 'Y-m-d H:i:s O');
$comment = $this->postComment($this->node, $edit['subject'], $edit['comment_body[' . $langcode . '][0][value]'], TRUE);
$this->drupalPost('comment/' . $comment->id . '/edit', $edit, t('Preview'));

Expand Down Expand Up @@ -1059,7 +1059,16 @@ class CommentPreviewTest extends CommentHelperCase {
$this->assertEqual($comment_loaded->comment_body[$langcode][0]['value'], $edit['comment_body[' . $langcode . '][0][value]'], 'Comment body loaded.');
$this->assertEqual($comment_loaded->name, $edit['name'], 'Name loaded.');
$this->assertEqual($comment_loaded->created, $raw_date, 'Date loaded.');
$this->drupalLogout();

// Check that the date and time of the comment are correct when edited by
// non-admin users.
$user_edit = array();
$expected_created_time = $comment_loaded->created;
$this->drupalLogin($web_user);
$this->drupalPost('comment/' . $comment->id . '/edit', $user_edit, t('Save'));
$comment_loaded = comment_load($comment->id, TRUE);
$this->assertEqual($comment_loaded->created, $expected_created_time, 'Expected date and time for comment edited.');
}

}
Expand Down
10 changes: 8 additions & 2 deletions modules/dblog/dblog.admin.inc
Original file line number Diff line number Diff line change
Expand Up @@ -286,13 +286,19 @@ function theme_dblog_message($variables) {
$event = $variables['event'];
// Check for required properties.
if (isset($event->message) && isset($event->variables)) {
$event_variables = @unserialize($event->variables);
// Messages without variables or user specified text.
if ($event->variables === 'N;') {
if ($event_variables === NULL) {
$output = $event->message;
}
elseif (!is_array($event_variables)) {
$output = t('Log data is corrupted and cannot be unserialized: @message', array(
'@message' => $event->message,
));
}
// Message to translate with injected variables.
else {
$output = t($event->message, unserialize($event->variables));
$output = t($event->message, $event_variables);
}
// If the output is expected to be a link, strip all the tags and
// special characters by using filter_xss() without any allowed tags.
Expand Down
Loading

0 comments on commit 3f5ccbf

Please sign in to comment.