Skip to content

Commit

Permalink
Update to Drupal 7.101. For more information, see https://www.drupal.…
Browse files Browse the repository at this point in the history
  • Loading branch information
Pantheon Automation committed Jun 5, 2024
1 parent 465daa9 commit 47a5d0c
Show file tree
Hide file tree
Showing 26 changed files with 376 additions and 67 deletions.
40 changes: 27 additions & 13 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,35 @@
################

################
# Includes
# Workflow
#
# Additional configuration can be provided through includes.
# One advantage of include files is that if they are updated upstream, the
# changes affect all pipelines using that include.
# Define conditions for when the pipeline will run.
# For example:
# * On commit
# * On merge request
# * On manual trigger
# * etc.
# https://docs.gitlab.com/ee/ci/jobs/job_control.html#specify-when-jobs-run-with-rules
#
# Includes can be overriden by re-declaring anything provided in an include,
# here in gitlab-ci.yml
# https://docs.gitlab.com/ee/ci/yaml/includes.html#override-included-configuration-values
# Pipelines can also be configured to run on a schedule,though they still must meet the conditions defined in Workflow and Rules. This can be used, for example, to do nightly regression testing:
# https://gitlab.com/help/ci/pipelines/schedules
################

include:
- project: $_GITLAB_TEMPLATES_REPO
ref: $_GITLAB_TEMPLATES_REF
file:
- '/includes/include.drupalci.variables.yml'
- '/includes/include.drupalci.workflows.yml'
workflow:
rules:
# These 3 rules from https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Workflows/MergeRequest-Pipelines.gitlab-ci.yml
# Run on merge requests
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
# Run when called from an upstream pipeline https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html?tab=Multi-project+pipeline#use-rules-to-control-downstream-pipeline-jobs
- if: $CI_PIPELINE_SOURCE == 'pipeline'
# Run on commits.
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_ROOT_NAMESPACE == "project"
# The last rule above blocks manual and scheduled pipelines on non-default branch. The rule below allows them:
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_ROOT_NAMESPACE == "project"
# Run if triggered from Web using 'Run Pipelines'
- if: $CI_PIPELINE_SOURCE == "web"
# Run if triggered from WebIDE
- if: $CI_PIPELINE_SOURCE == "webide"

################
# Variables
Expand All @@ -42,9 +54,11 @@ include:
################

variables:
_CONFIG_DOCKERHUB_ROOT: "drupalci"
_TARGET_PHP: "8.1"
CONCURRENCY: 15
GIT_DEPTH: "3"
COMPOSER_ALLOW_SUPERUSER: 1

################
# Stages
Expand Down
7 changes: 7 additions & 0 deletions .htaccess
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ DirectoryIndex index.php index.html index.htm

# Various header fixes.
<IfModule mod_headers.c>
# Disable content sniffing for all responses, since it's an attack vector.
# This header is also set in drupal_deliver_html_page(), which depending on
# Apache configuration might get placed in the 'onsuccess' table. To prevent
# header duplication, unset that one prior to setting in the 'always' table.
# See "To circumvent this limitation..." in
# https://httpd.apache.org/docs/current/mod/mod_headers.html.
Header onsuccess unset X-Content-Type-Options
# Disable content sniffing, since it's an attack vector.
Header always set X-Content-Type-Options nosniff
# Disable Proxy header, since it's an attack vector.
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
Drupal 7.101, 2024-06-05
-----------------------
- Various security improvements
- Various bug fixes, optimizations and improvements

Drupal 7.100, 2024-03-06
------------------------
- Security improvements
Expand Down
2 changes: 1 addition & 1 deletion includes/ajax.inc
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ function ajax_render($commands = array()) {
function ajax_get_form() {
$form_state = form_state_defaults();

$form_build_id = $_POST['form_build_id'];
$form_build_id = (isset($_POST['form_build_id']) ? $_POST['form_build_id'] : '');

// Get the form from the cache.
$form = form_get_cache($form_build_id, $form_state);
Expand Down
5 changes: 3 additions & 2 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.100');
define('VERSION', '7.101');

/**
* Core API compatibility.
Expand Down Expand Up @@ -2310,7 +2310,8 @@ function drupal_block_denied($ip) {
* The number of random bytes to fetch and base64 encode.
*
* @return string
* The base64 encoded result will have a length of up to 4 * $byte_count.
* A base-64 encoded string, with + replaced with -, / with _ and any =
* padding characters removed.
*/
function drupal_random_key($byte_count = 32) {
return drupal_base64_encode(drupal_random_bytes($byte_count));
Expand Down
38 changes: 37 additions & 1 deletion includes/common.inc
Original file line number Diff line number Diff line change
Expand Up @@ -5561,15 +5561,48 @@ function drupal_cron_run() {
DrupalQueue::get($queue_name)->createQueue();
}

$module_previous = '';

// If detailed logging isn't enabled, don't log individual execution times.
$time_logging_enabled = variable_get('cron_detailed_logging', DRUPAL_CRON_DETAILED_LOGGING);

// Iterate through the modules calling their cron handlers (if any):
foreach (module_implements('cron') as $module) {
if ($time_logging_enabled) {
if (!$module_previous) {
watchdog('cron', 'Starting execution of @module_cron().', array('@module' => $module));
}
else {
watchdog('cron', 'Starting execution of @module_cron(), execution of @module_previous_cron() took @time.', array(
'@module' => $module,
'@module_previous' => $module_previous,
'@time' => timer_read('cron_' . $module_previous) . 'ms',
));
}
timer_start('cron_' . $module);
}

// Do not let an exception thrown by one module disturb another.
try {
module_invoke($module, 'cron');
}
catch (Exception $e) {
watchdog_exception('cron', $e);
}

if ($time_logging_enabled) {
timer_stop('cron_' . $module);
$module_previous = $module;
}
}

if ($time_logging_enabled) {
if ($module_previous) {
watchdog('cron', 'Execution of @module_previous_cron() took @time.', array(
'@module_previous' => $module_previous,
'@time' => timer_read('cron_' . $module_previous) . 'ms',
));
}
}

// Record cron time.
Expand Down Expand Up @@ -8229,7 +8262,10 @@ function entity_get_controller($entity_type) {
$controllers = &drupal_static(__FUNCTION__, array());
if (!isset($controllers[$entity_type])) {
$type_info = entity_get_info($entity_type);
$class = $type_info['controller class'];
// Explicitly fail for malformed entities missing a valid controller class.
if (!isset($type_info['controller class']) || !class_exists($class = $type_info['controller class'])) {
throw new EntityMalformedException(t('Missing or non-existent controller class on entity of type @entity_type.', array('@entity_type' => $entity_type)));
}
$controllers[$entity_type] = new $class($entity_type);
}
return $controllers[$entity_type];
Expand Down
2 changes: 1 addition & 1 deletion includes/errors.inc
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ function _drupal_log_error($error, $fatal = FALSE) {
if ($fatal) {
// When called from CLI, simply output a plain text message.
print html_entity_decode(strip_tags(t('%type: !message in %function (line %line of %file).', $error))). "\n";
exit;
exit(1);
}
}

Expand Down
2 changes: 1 addition & 1 deletion includes/file.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2086,7 +2086,7 @@ function file_download() {
$target = implode('/', $args);
$uri = $scheme . '://' . $target;
$uri = file_uri_normalize_dot_segments($uri);
if (file_stream_wrapper_valid_scheme($scheme) && file_exists($uri)) {
if (file_stream_wrapper_valid_scheme($scheme) && is_file($uri)) {
$headers = file_download_headers($uri);
if (count($headers)) {
file_transfer($uri, $headers);
Expand Down
3 changes: 3 additions & 0 deletions includes/unicode.inc
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,9 @@ function decode_entities($text) {
*/
function drupal_strlen($text) {
global $multibyte;
if (is_null($text)) {
return 0;
}
if ($multibyte == UNICODE_MULTIBYTE) {
return mb_strlen($text);
}
Expand Down
3 changes: 0 additions & 3 deletions includes/updater.inc
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,6 @@ class Updater {
// Make sure the installation parent directory exists and is writable.
$this->prepareInstallDirectory($filetransfer, $args['install_dir']);

// Note: If the project is installed in sites/all, it will not be
// deleted. It will be installed in sites/default as that will override
// the sites/all reference and not break other sites which are using it.
if (is_dir($args['install_dir'] . '/' . $this->name)) {
// Remove the existing installed file.
$filetransfer->removeDirectory($args['install_dir'] . '/' . $this->name);
Expand Down
26 changes: 22 additions & 4 deletions modules/dblog/dblog.test
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,30 @@ class DBLogTestCase extends DrupalWebTestCase {
$count = db_query('SELECT COUNT(wid) FROM {watchdog}')->fetchField();
$this->assertTrue($count > $row_limit, format_string('Dblog row count of @count exceeds row limit of @limit', array('@count' => $count, '@limit' => $row_limit)));

// Get last ID to compare against; log entries get deleted, so we can't
// reliably add the number of newly created log entries to the current count
// to measure number of log entries created by cron.
$last_id = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField();

// Run a cron job.
$this->cronRun();
// Verify that the database log row count equals the row limit plus one
// because cron adds a record after it runs.
$count = db_query('SELECT COUNT(wid) FROM {watchdog}')->fetchField();
$this->assertTrue($count == $row_limit + 1, format_string('Dblog row count of @count equals row limit of @limit plus one', array('@count' => $count, '@limit' => $row_limit)));

// Get last ID after cron was run.
$current_id = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField();

// Only one final "cron is finished" message should be logged.
$this->assertEqual($current_id - $last_id, 1, format_string('Cron added @count of @expected new log entries', array('@count' => $current_id - $last_id, '@expected' => 1)));

// Test enabling of detailed cron logging.
// Get the number of enabled modules. Cron adds a log entry for each module.
$module_count = count(module_implements('cron'));
variable_set('cron_detailed_logging', 1);
$last_id = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField();
$this->cronRun();
$current_id = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField();

// The number of log entries created.
$this->assertEqual($current_id - $last_id, $module_count + 2, format_string('Cron added @count of @expected new log entries', array('@count' => $current_id - $last_id, '@expected' => $module_count + 2)));
}

/**
Expand Down
7 changes: 1 addition & 6 deletions modules/node/node.admin.inc
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,7 @@ function node_filter_form() {
);
foreach ($session as $filter) {
list($type, $value) = $filter;
if ($type == 'term') {
// Load term name from DB rather than search and parse options array.
$value = module_invoke('taxonomy', 'term_load', $value);
$value = $value->name;
}
elseif ($type == 'language') {
if ($type == 'language') {
$value = $value == LANGUAGE_NONE ? t('Language neutral') : module_invoke('locale', 'language_name', $value);
}
else {
Expand Down
25 changes: 12 additions & 13 deletions modules/simpletest/drupal_web_test_case.php
Original file line number Diff line number Diff line change
Expand Up @@ -560,23 +560,22 @@ public function run(array $methods = array()) {
'function' => $class . '->' . $method . '()',
);
$completion_check_id = DrupalTestCase::insertAssert($this->testId, $class, FALSE, t('The test did not complete due to a fatal error.'), 'Completion check', $caller);
$this->setUp();
if ($this->setup) {
try {
try {
$this->setUp();
if ($this->setup) {
$this->$method();
// Finish up.
$this->tearDown();
}
catch (Throwable $e) {
$this->exceptionHandler($e);
}
catch (Exception $e) {
// Cater for older PHP versions.
$this->exceptionHandler($e);
else {
$this->fail(t("The test cannot be executed because it has not been set up properly."));
}
$this->tearDown();
}
else {
$this->fail(t("The test cannot be executed because it has not been set up properly."));
catch (Throwable $e) {
$this->exceptionHandler($e);
}
catch (Exception $e) {
// Cater for older PHP versions.
$this->exceptionHandler($e);
}
// Remove the completion check record.
DrupalTestCase::deleteAssert($completion_check_id);
Expand Down
12 changes: 12 additions & 0 deletions modules/simpletest/tests/ajax.test
Original file line number Diff line number Diff line change
Expand Up @@ -618,4 +618,16 @@ class AJAXElementValidation extends AJAXTestCase {
$this->assertNoText(t('Error message'), "No error message in resultant JSON");
$this->assertText('ajax_forms_test_validation_form_callback invoked', 'The correct callback was invoked');
}

/**
* Try to open default Ajax callback without passing required data.
*/
function testAJAXPathWithoutData() {
$this->drupalGet('system/ajax');
$query_parameters = array(
':type' => 'php',
':severity' => WATCHDOG_WARNING,
);
$this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND severity = :severity', $query_parameters)->fetchField(), 0, 'No warning message appears in the logs.');
}
}
29 changes: 29 additions & 0 deletions modules/simpletest/tests/entity_crud.test
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,33 @@ class EntityLoadTestCase extends DrupalWebTestCase {
$nodes_loaded = entity_load('node', array('1.', '2'));
$this->assertEqual(count($nodes_loaded), 1);
}

/**
* Tests the controller class loading functionality on non-existing entity
* types and on entities without valid controller class.
*/
public function testEntityLoadInvalidControllerClass() {
// Ensure that loading a non-existing entity type will throw an
// EntityMalformedException.
try {
entity_load('test', array('1'));
$this->fail(t('Cannot load a controller class on non-existing entity type.'));
}
catch (EntityMalformedException $e) {
$this->pass(t('Cannot load a controller class on non-existing entity type.'));
}

// Ensure that loading an entity without valid controller class will throw
// an EntityMalformedException.
module_enable(array('entity_crud_hook_test'));
variable_set('entity_crud_hook_test_alter_controller_class', TRUE);
try {
entity_load('node', array('1'));
$this->fail(t('Cannot load a missing or non-existent controller class.'));
}
catch (EntityMalformedException $e) {
$this->pass(t('Cannot load a missing or non-existent controller class.'));
}
variable_set('entity_crud_hook_test_alter_controller_class', FALSE);
}
}
10 changes: 10 additions & 0 deletions modules/simpletest/tests/entity_crud_hook_test.module
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,13 @@ function entity_crud_hook_test_taxonomy_vocabulary_delete() {
function entity_crud_hook_test_user_delete() {
$_SESSION['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
}

/**
* Implements hook_entity_info_alter().
*/
function entity_crud_hook_test_entity_info_alter(&$entity_info) {
if (variable_get('entity_crud_hook_test_alter_controller_class', FALSE)) {
// Set the controller class for nodes to NULL.
$entity_info['node']['controller class'] = NULL;
}
}
Loading

0 comments on commit 47a5d0c

Please sign in to comment.