Skip to content
......@@ -31,7 +31,8 @@
"symfony/psr-http-message-bridge": "v0.2",
"zendframework/zend-diactoros": "~1.1",
"composer/semver": "~1.0",
"paragonie/random_compat": "~1.0"
"paragonie/random_compat": "^1|^2",
"asm89/stack-cors": "~1.0"
},
"require-dev": {
"behat/mink": "~1.7",
......@@ -39,7 +40,7 @@
"jcalderonzumba/gastonjs": "~1.0.2",
"jcalderonzumba/mink-phantomjs-driver": "~0.3.1",
"mikey179/vfsStream": "~1.2",
"phpunit/phpunit": "~4.8",
"phpunit/phpunit": ">=4.8.28 <5",
"symfony/css-selector": "~2.8"
},
"replace": {
......@@ -62,6 +63,7 @@
"drupal/config": "self.version",
"drupal/config_translation": "self.version",
"drupal/contact": "self.version",
"drupal/content_moderation": "self.version",
"drupal/content_translation": "self.version",
"drupal/contextual": "self.version",
"drupal/core-annotation": "self.version",
......@@ -86,6 +88,7 @@
"drupal/core-utility": "self.version",
"drupal/core-uuid": "self.version",
"drupal/datetime": "self.version",
"drupal/datetime_range": "self.version",
"drupal/dblog": "self.version",
"drupal/dynamic_page_cache": "self.version",
"drupal/editor": "self.version",
......@@ -111,6 +114,7 @@
"drupal/migrate_drupal_ui": "self.version",
"drupal/node": "self.version",
"drupal/options": "self.version",
"drupal/outside_in": "self.version",
"drupal/page_cache": "self.version",
"drupal/path": "self.version",
"drupal/quickedit": "self.version",
......
......@@ -1073,8 +1073,9 @@
* yourmodule/tests/src/Unit directory, according to the PSR-4 standard.
* - Your test class needs a phpDoc comment block with a description and
* a @group annotation, which gives information about the test.
* - Methods in your test class whose names start with 'test' are the actual
* test cases. Each one should test a logical subset of the functionality.
* - Add test cases by adding method names that start with 'test' and have no
* arguments, for example testYourTestCase(). Each one should test a logical
* subset of the functionality.
* For more details, see:
* - https://www.drupal.org/phpunit for full documentation on how to write
* PHPUnit tests for Drupal.
......@@ -1110,9 +1111,9 @@
* set up content types and similar procedures.
* - In some cases, you may need to write a test module to support your test;
* put such modules under the yourmodule/tests/modules directory.
* - Methods in your test class whose names start with 'test', and which have
* no arguments, are the actual test cases. Each one should test a logical
* subset of the functionality, and each one runs in a new, isolated test
* - Add test cases by adding method names that start with 'test' and have no
* arguments, for example testYourTestCase(). Each one should test a logical
* subset of the functionality. Each method runs in a new, isolated test
* environment, so it can only rely on the setUp() method, not what has
* been set up by other test methods.
* For more details, see:
......@@ -1121,6 +1122,52 @@
* - @link oo_conventions Object-oriented programming topic @endlink for more
* on PSR-4, namespaces, and where to place classes.
*
* @section write_functional_phpunit Write functional PHP tests (phpunit)
* Functional tests extend the BrowserTestBase base class, and use PHPUnit as
* their underlying framework. They use a simulated browser, in which the test
* can click links, visit URLs, post to forms, etc. To write a functional test:
* - Extend \Drupal\Tests\BrowserTestBase.
* - Place the test in the yourmodule/tests/src/Functional/ directory and use
* the \Drupal\Tests\yourmodule\Functional namespace.
* - Add a @group annotation. For example, if the test is for a Drupal 6
* migration process, the group core uses is migrate_drupal_6. Use yourmodule
* as the group name if the test does not belong to another larger group.
* - You may also override the default setUp() method, which can be used to set
* up content types and similar procedures. Don't forget to call the parent
* method.
* - In some cases, you may need to write a test module to support your test;
* put such modules under the yourmodule/tests/modules directory.
* - Add test cases by adding method names that start with 'test' and have no
* arguments, for example testYourTestCase(). Each one should test a logical
* subset of the functionality. Each method runs in a new, isolated test
* environment, so it can only rely on the setUp() method, not what has
* been set up by other test methods.
* For more details, see:
* - https://www.drupal.org/docs/8/phpunit/phpunit-browser-test-tutorial for
* a full tutorial on how to write functional PHPUnit tests for Drupal.
* - https://www.drupal.org/phpunit for the full documentation on how to write
* PHPUnit tests for Drupal.
*
* @section write_jsfunctional_phpunit Write functional JavaScript tests (phpunit)
* To write a functional test that relies on JavaScript:
* - Extend \Drupal\FunctionalJavaScriptTests\JavascriptTestBase.
* - Place the test into the yourmodule/tests/src/FunctionalJavascript/
* directory and use the \Drupal\Tests\yourmodule\FunctionalJavascript
* namespace.
* - Add a @group annotation. Use yourmodule as the group name if the test does
* not belong to another larger group.
* - Set up PhantomJS; see http://phantomjs.org/download.html.
* - To run tests, see core/tests/README.md.
* - When clicking a link/button with Ajax behavior attached, keep in mind that
* the underlying browser might take time to deliver changes to the HTML. Use
* $this->assertSession()->assertWaitOnAjaxRequest() to wait for the Ajax
* request to finish.
* For more details, see:
* - https://www.drupal.org/docs/8/phpunit/phpunit-javascript-testing-tutorial
* for a full tutorial on how to write PHPUnit JavaScript tests for Drupal.
* - https://www.drupal.org/phpunit for the full documentation on how to write
* PHPUnit tests for Drupal.
*
* @section running Running tests
* You can run both Simpletest and PHPUnit tests by enabling the core Testing
* module (core/modules/simpletest). Once that module is enabled, tests can be
......@@ -1692,7 +1739,11 @@
* // Create a $form API array.
* $form['phone_number'] = array(
* '#type' => 'tel',
* '#title' => $this->t('Your phone number')
* '#title' => $this->t('Your phone number'),
* );
* $form['save'] = array(
* '#type' => 'submit',
* '#value' => $this->t('Save'),
* );
* return $form;
* }
......@@ -1894,21 +1945,32 @@
function hook_cron() {
// Short-running operation example, not using a queue:
// Delete all expired records since the last cron run.
$expires = \Drupal::state()->get('mymodule.cron_last_run', REQUEST_TIME);
db_delete('mymodule_table')
$expires = \Drupal::state()->get('mymodule.last_check', 0);
\Drupal::database()->delete('mymodule_table')
->condition('expires', $expires, '>=')
->execute();
\Drupal::state()->set('mymodule.cron_last_run', REQUEST_TIME);
\Drupal::state()->set('mymodule.last_check', REQUEST_TIME);
// Long-running operation example, leveraging a queue:
// Fetch feeds from other sites.
$result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh <> :never', array(
':time' => REQUEST_TIME,
':never' => AGGREGATOR_CLEAR_NEVER,
));
// Queue news feeds for updates once their refresh interval has elapsed.
$queue = \Drupal::queue('aggregator_feeds');
foreach ($result as $feed) {
$queue->createItem($feed);
$ids = \Drupal::entityManager()->getStorage('aggregator_feed')->getFeedIdsToRefresh();
foreach (Feed::loadMultiple($ids) as $feed) {
if ($queue->createItem($feed)) {
// Add timestamp to avoid queueing item more than once.
$feed->setQueuedTime(REQUEST_TIME);
$feed->save();
}
}
$ids = \Drupal::entityQuery('aggregator_feed')
->condition('queued', REQUEST_TIME - (3600 * 6), '<')
->execute();
if ($ids) {
$feeds = Feed::loadMultiple($ids);
foreach ($feeds as $feed) {
$feed->setQueuedTime(0);
$feed->save();
}
}
}
......@@ -2036,7 +2098,7 @@ function hook_mail_alter(&$message) {
* An array of parameters supplied by the caller of
* MailManagerInterface->mail().
*
* @see \Drupal\Core\Mail\MailManagerInterface->mail()
* @see \Drupal\Core\Mail\MailManagerInterface::mail()
*/
function hook_mail($key, &$message, $params) {
$account = $params['account'];
......@@ -2478,7 +2540,7 @@ function hook_validation_constraint_alter(array &$definitions) {
* this class is subscribed to, and which methods on the class should be
* called for each one. Example:
* @code
* public function getSubscribedEvents() {
* public static function getSubscribedEvents() {
* // Subscribe to kernel terminate with priority 100.
* $events[KernelEvents::TERMINATE][] = array('onTerminate', 100);
* // Subscribe to kernel request with default priority of 0.
......
......@@ -24,10 +24,10 @@ classList:
ckeditor:
remote: https://github.com/ckeditor/ckeditor-dev
version: "4.5.10"
version: "4.5.11"
license:
name: GNU-GPL-2.0-or-later
url: https://github.com/ckeditor/ckeditor-dev/blob/4.5.10/LICENSE.md
url: https://github.com/ckeditor/ckeditor-dev/blob/4.5.11/LICENSE.md
gpl-compatible: true
js:
assets/vendor/ckeditor/ckeditor.js: { preprocess: false, minified: true }
......
......@@ -33,6 +33,14 @@ parameters:
- sftp
- webcal
- rtsp
cors.config:
enabled: false
allowedHeaders: []
allowedMethods: []
allowedOrigins: ['*']
exposedHeaders: false
maxAge: false
supportsCredentials: false
services:
# Simple cache contexts, directly derived from the request context.
cache_context.ip:
......@@ -706,6 +714,11 @@ services:
- { name: http_middleware, priority: 50 }
calls:
- [setContainer, ['@service_container']]
http_middleware.cors:
class: Asm89\Stack\Cors
arguments: ['%cors.config%']
tags:
- { name: http_middleware }
psr7.http_foundation_factory:
class: Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory
psr7.http_message_factory:
......@@ -1578,10 +1591,13 @@ services:
tags:
- { name: mime_type_guesser }
lazy: true
# Currently needs to be public as it is called by
# \Drupal\Core\Render\Element\StatusMessages.
# @todo Consider making this service private again after
# https://www.drupal.org/node/2367555 lands.
render_placeholder_generator:
class: Drupal\Core\Render\PlaceholderGenerator
arguments: ['%renderer.config%']
public: false
render_cache:
class: Drupal\Core\Render\PlaceholderingRenderCache
arguments: ['@request_stack', '@cache_factory', '@cache_contexts_manager', '@render_placeholder_generator']
......
<?php
/**
* @file
* Functions that need to be loaded on every Drupal request.
......@@ -11,6 +12,7 @@
use Drupal\Core\Logger\RfcLogLevel;
use Drupal\Core\Render\Markup;
use Drupal\Component\Render\MarkupInterface;
use Drupal\Core\Test\TestDatabase;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\Utility\Error;
......@@ -599,7 +601,7 @@ function _drupal_exception_handler_additional($exception, $exception2) {
* @param string $new_prefix
* Internal use only. A new prefix to be stored.
*
* @return string|FALSE
* @return string|false
* Either the simpletest prefix (the string "simpletest" followed by any
* number of digits) or FALSE if the user agent does not contain a valid
* HMAC and timestamp.
......@@ -622,7 +624,7 @@ function drupal_valid_test_ua($new_prefix = NULL) {
// string.
$http_user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : NULL;
$user_agent = isset($_COOKIE['SIMPLETEST_USER_AGENT']) ? $_COOKIE['SIMPLETEST_USER_AGENT'] : $http_user_agent;
if (isset($user_agent) && preg_match("/^(simpletest\d+):(.+):(.+):(.+)$/", $user_agent, $matches)) {
if (isset($user_agent) && preg_match("/^simple(\w+\d+):(.+):(.+):(.+)$/", $user_agent, $matches)) {
list(, $prefix, $time, $salt, $hmac) = $matches;
$check_string = $prefix . ':' . $time . ':' . $salt;
// Read the hash salt prepared by drupal_generate_test_ua().
......@@ -630,7 +632,8 @@ function drupal_valid_test_ua($new_prefix = NULL) {
// handlers are set up. While Drupal's error handling may be properly
// configured on production sites, the server's PHP error_reporting may not.
// Ensure that no information leaks on production sites.
$key_file = DRUPAL_ROOT . '/sites/simpletest/' . substr($prefix, 10) . '/.htkey';
$test_db = new TestDatabase($prefix);
$key_file = DRUPAL_ROOT . '/' . $test_db->getTestSitePath() . '/.htkey';
if (!is_readable($key_file)) {
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
exit;
......@@ -640,11 +643,15 @@ function drupal_valid_test_ua($new_prefix = NULL) {
$key = $private_key . filectime(__FILE__) . fileinode(__FILE__);
$time_diff = REQUEST_TIME - $time;
$test_hmac = Crypt::hmacBase64($check_string, $key);
// Since we are making a local request a 5 second time window is allowed,
// Since we are making a local request a 600 second time window is allowed,
// and the HMAC must match.
if ($time_diff >= 0 && $time_diff <= 5 && $hmac === $test_hmac) {
if ($time_diff >= 0 && $time_diff <= 600 && $hmac === $test_hmac) {
$test_prefix = $prefix;
}
else {
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden (SIMPLETEST_USER_AGENT invalid)');
exit;
}
}
return $test_prefix;
}
......@@ -657,7 +664,8 @@ function drupal_generate_test_ua($prefix) {
if (!isset($key) || $last_prefix != $prefix) {
$last_prefix = $prefix;
$key_file = DRUPAL_ROOT . '/sites/simpletest/' . substr($prefix, 10) . '/.htkey';
$test_db = new TestDatabase($prefix);
$key_file = DRUPAL_ROOT . '/' . $test_db->getTestSitePath() . '/.htkey';
// When issuing an outbound HTTP client request from within an inbound test
// request, then the outbound request has to use the same User-Agent header
// as the inbound request. A newly generated private key for the same test
......@@ -682,7 +690,7 @@ function drupal_generate_test_ua($prefix) {
// Generate a moderately secure HMAC based on the database credentials.
$salt = uniqid('', TRUE);
$check_string = $prefix . ':' . time() . ':' . $salt;
return $check_string . ':' . Crypt::hmacBase64($check_string, $key);
return 'simple' . $check_string . ':' . Crypt::hmacBase64($check_string, $key);
}
/**
......
......@@ -464,7 +464,7 @@ function entity_view_multiple(array $entities, $view_mode, $langcode = NULL, $re
* 'bundle' => $bundle,
* 'mode' => $view_mode,
* 'status' => TRUE,
* ));
* );
* \Drupal::entityTypeManager()
* ->getStorage('entity_view_display')
* ->create($values);
......@@ -539,12 +539,12 @@ function entity_get_display($entity_type, $bundle, $view_mode) {
* When the entity form display is not available in configuration, you can
* create a new EntityFormDisplay object using:
* @code
* $values = ('entity_form_display', array(
* $values = array(
* 'targetEntityType' => $entity_type,
* 'bundle' => $bundle,
* 'mode' => $form_mode,
* 'status' => TRUE,
* ));
* );
* \Drupal::entityTypeManager()
* ->getStorage('entity_form_display')
* ->create($values);
......
......@@ -80,6 +80,7 @@ function _drupal_error_handler_real($error_level, $message, $filename, $line, $c
'%line' => $caller['line'],
'severity_level' => $severity_level,
'backtrace' => $backtrace,
'@backtrace_string' => (new \Exception())->getTraceAsString(),
), $recoverable || $to_string);
}
}
......@@ -116,9 +117,9 @@ function error_displayable($error = NULL) {
*
* @param $error
* An array with the following keys: %type, @message, %function, %file,
* %line, severity_level, and backtrace. All the parameters are plain-text,
* with the exception of @message, which needs to be an HTML string, and
* backtrace, which is a standard PHP backtrace.
* %line, @backtrace_string, severity_level, and backtrace. All the parameters
* are plain-text, with the exception of @message, which needs to be an HTML
* string, and backtrace, which is a standard PHP backtrace.
* @param bool $fatal
* TRUE for:
* - An exception is thrown and not caught by something else.
......@@ -163,18 +164,18 @@ function _drupal_log_error($error, $fatal = FALSE) {
// installer.
if (\Drupal::hasService('logger.factory')) {
try {
\Drupal::logger('php')->log($error['severity_level'], '%type: @message in %function (line %line of %file).', $error);
\Drupal::logger('php')->log($error['severity_level'], '%type: @message in %function (line %line of %file) @backtrace_string.', $error);
}
catch (\Exception $e) {
// We can't log, for example because the database connection is not
// available. At least try to log to PHP error log.
error_log(strtr('Failed to log error: %type: @message in %function (line %line of %file).', $error));
error_log(strtr('Failed to log error: %type: @message in %function (line %line of %file). @backtrace_string', $error));
}
}
// Log fatal errors, so developers can find and debug them.
if ($fatal) {
error_log(sprintf('%s: %s in %s on line %d', $error['%type'], $error['@message'], $error['%file'], $error['%line']));
error_log(sprintf('%s: %s in %s on line %d %s', $error['%type'], $error['@message'], $error['%file'], $error['%line'], $error['@backtrace_string']));
}
if (PHP_SAPI === 'cli') {
......
This diff is collapsed.
......@@ -511,8 +511,6 @@ function template_preprocess_form_element_label(&$variables) {
$variables['title'] = ['#markup' => $element['#title']];
}
$variables['attributes'] = array();
// Pass elements title_display to template.
$variables['title_display'] = $element['#title_display'];
......
This diff is collapsed.
This diff is collapsed.
......@@ -74,7 +74,7 @@ function drupal_get_schema_versions($module) {
* module is not installed.
*/
function drupal_get_installed_schema_version($module, $reset = FALSE, $array = FALSE) {
static $versions = array();
$versions = &drupal_static(__FUNCTION__, array());
if ($reset) {
$versions = array();
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.