Commit 12e53f92 authored by Crell's avatar Crell
Browse files

Merge remote-tracking branch 'upstream/8.x' into kernel

Resolve conflicts in cron improvements.

Conflicts:
	core/INSTALL.txt
	core/includes/bootstrap.inc
	core/modules/simpletest/drupal_web_test_case.php
	core/modules/system/system.install
	core/modules/system/system.module
	core/modules/system/system.test
	core/scripts/cron-curl.sh
	core/scripts/cron-lynx.sh
parents 71cf6406 fe01ab6e
......@@ -286,11 +286,11 @@ INSTALLATION
crontab utility on Unix/Linux systems. The following crontab line uses the
wget command to visit the cron page, and runs each hour, on the hour:
0 * * * * wget -O - -q -t 1 http://example.com/cron?cron_key=YOURKEY
0 * * * * wget -O - -q -t 1 http://example.com/cron/YOURKEY
Replace the text "http://example.com/cron?cron_key=YOURKEY" in the
example with the full URL displayed under "Cron maintenance tasks" on the
"Status report" page.
Replace the text "http://example.com/cron/YOURKEY" in the example with the
full URL displayed under "Cron maintenance tasks" on the "Status report"
page.
More information about cron maintenance tasks is available at
http://drupal.org/cron, and sample cron shell scripts can be found in the
......
......@@ -146,6 +146,10 @@ User experience and usability
- Roy Scholten 'yoroy' <http://drupal.org/user/41502>
- Bojhan Somers 'Bojhan' <http://drupal.org/user/87969>
Node Access
- Moshe Weitzman 'moshe weitzman' <http://drupal.org/user/23>
- Ken Rickard 'agentrickard' <http://drupal.org/user/20975>
- Jess Myrbo 'xjm' <http://drupal.org/user/65776>
Module maintainers
------------------
......
......@@ -168,7 +168,7 @@
* displayed while awaiting a response from the callback, and add an optional
* message. Possible keys: 'type', 'message', 'url', 'interval'.
* More information is available in the
* @link http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7 Form API Reference @endlink
* @link forms_api_reference.html Form API Reference @endlink
*
* In addition to using Form API for doing in-form modification, Ajax may be
* enabled by adding classes to buttons and links. By adding the 'use-ajax'
......
......@@ -3,7 +3,7 @@
use Drupal\Core\Database\Database;
use Symfony\Component\ClassLoader\UniversalClassLoader;
use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpFoundation\Request;
/**
......@@ -2358,23 +2358,22 @@ function drupal_get_bootstrap_phase() {
* @endcode
*
* @param $reset
* TRUE or FALSE depending on whether the Container instance is to be reset.
* A new container instance to reset the Drupal container to.
*
* @return Symfony\Component\DependencyInjection\ContainerBuilder
* @return Drupal\Component\DependencyInjection\ContainerBuilder
* The instance of the Drupal Container used to set up and maintain object
* instances.
*/
function drupal_container($reset = FALSE) {
function drupal_container(ContainerBuilder $reset = NULL) {
// We do not use drupal_static() here because we do not have a mechanism by
// which to reinitialize the stored objects, so a drupal_static_reset() call
// would leave Drupal in a nonfunctional state.
static $container = NULL;
if ($reset || !isset($container)) {
if (isset($reset)) {
$container = $reset;
}
elseif (!isset($container)) {
$container = new ContainerBuilder();
// An interface language always needs to be available for t() and other
// functions. This default is overridden by drupal_language_initialize()
// during language negotiation.
$container->register(LANGUAGE_TYPE_INTERFACE, 'Drupal\\Core\\Language\\Language');
}
return $container;
}
......@@ -3317,3 +3316,32 @@ function _drupal_shutdown_function() {
}
}
}
/**
* Compares the memory required for an operation to the available memory.
*
* @param $required
* The memory required for the operation, expressed as a number of bytes with
* optional SI or IEC binary unit prefix (e.g. 2, 3K, 5MB, 10G, 6GiB, 8bytes,
* 9mbytes).
* @param $memory_limit
* (optional) The memory limit for the operation, expressed as a number of
* bytes with optional SI or IEC binary unit prefix (e.g. 2, 3K, 5MB, 10G,
* 6GiB, 8bytes, 9mbytes). If no value is passed, the current PHP
* memory_limit will be used. Defaults to NULL.
*
* @return
* TRUE if there is sufficient memory to allow the operation, or FALSE
* otherwise.
*/
function drupal_check_memory_limit($required, $memory_limit = NULL) {
if (!isset($memory_limit)) {
$memory_limit = ini_get('memory_limit');
}
// There is sufficient memory if:
// - No memory limit is set.
// - The memory limit is set to unlimited (-1).
// - The memory limit is greater than the memory required for the operation.
return ((!$memory_limit) || ($memory_limit == -1) || (parse_size($memory_limit) > parse_size($required)));
}
......@@ -646,16 +646,17 @@ function drupal_encode_path($path) {
* @param $options
* An associative array of additional URL options to pass to url().
* @param $http_response_code
* Valid values for an actual "goto" as per RFC 2616 section 10.3 are:
* - 301 Moved Permanently (the recommended value for most redirects)
* - 302 Found (default in Drupal and PHP, sometimes used for spamming search
* engines)
* - 303 See Other
* - 304 Not Modified
* - 305 Use Proxy
* - 307 Temporary Redirect (alternative to "503 Site Down for Maintenance")
* Note: Other values are defined by RFC 2616, but are rarely used and poorly
* supported.
* The valid values for 3xx redirection status codes are defined in
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3 RFC 2616 @endlink
* and the
* @link http://tools.ietf.org/html/draft-reschke-http-status-308-07 draft for the new HTTP status codes: @endlink
* - 301: Moved Permanently (the recommended value for most redirects).
* - 302: Found (default in Drupal and PHP, sometimes used for spamming search
* engines).
* - 303: See Other.
* - 304: Not Modified.
* - 305: Use Proxy.
* - 307: Temporary Redirect.
*
* @see drupal_get_destination()
* @see url()
......@@ -6281,7 +6282,7 @@ function drupal_render_cid_parts($granularity = NULL) {
// part.
if (language_multilingual()) {
foreach (language_types_get_configurable() as $language_type) {
$cid_parts[] = $GLOBALS[$language_type]->langcode;
$cid_parts[] = drupal_container()->get($language_type)->langcode;
}
}
......@@ -7277,50 +7278,116 @@ function drupal_implode_tags($tags) {
}
/**
* Flushes all cached data on the site.
*
* Empties cache tables, rebuilds the menu cache and theme registries, and
* invokes a hook so that other modules' cache data can be cleared as well.
* Flushes all persistent caches, resets all variables, and rebuilds all data structures.
*
* At times, it is necessary to re-initialize the entire system to account for
* changed or new code. This function:
* - Clears all persistent caches (invoking hook_cache_flush()), which always
* includes:
* - The bootstrap cache bin containing base system, module system, and theme
* system information.
* - The common 'cache' cache bin containing arbitrary caches.
* - The page cache.
* - The URL alias path cache.
* - Resets all static variables that have been defined via drupal_static().
* - Clears asset (JS/CSS) file caches.
* - Updates the system with latest information about extensions (modules and
* themes).
* - Updates the bootstrap flag for modules implementing bootstrap_hooks().
* - Rebuilds the full database schema information (invoking hook_schema()).
* - Rebuilds data structures of all modules (invoking hook_rebuild()). In
* core this means
* - blocks, node types, date formats and actions are synchronized with the
* database
* - The 'active' status of fields is refreshed.
* - Rebuilds the menu router.
*
* This means the entire system is reset so all caches and static variables are
* effectively empty. After that is guaranteed, information about the currently
* active code is updated, and rebuild operations are successively called in
* order to synchronize the active system according to the current information
* defined in code.
*
* All modules need to ensure that all of their caches are flushed when
* hook_cache_flush() is invoked; any previously known information must no
* longer exist. All following hook_rebuild() operations must be based on fresh
* and current system data. All modules must be able to rely on this contract.
*
* @see hook_cache_flush()
* @see hook_rebuild()
*
* This function also resets the theme, which means it is not initialized
* anymore and all previously added JavaScript and CSS is gone. Normally, this
* function is called as an end-of-POST-request operation that is followed by a
* redirect, so this effect is not visible. Since the full reset is the whole
* point of this function, callers need to take care for backing up all needed
* variables and properly restoring or re-initializing them on their own. For
* convenience, this function automatically re-initializes the maintenance theme
* if it was initialized before.
*
* @todo Try to clear page/JS/CSS caches last, so cached pages can still be
* served during this possibly long-running operation. (Conflict on bootstrap
* cache though.)
* @todo Add a global lock to ensure that caches are not primed in concurrent
* requests.
*/
function drupal_flush_all_caches() {
// Change query-strings on css/js files to enforce reload for all users.
_drupal_flush_css_js();
// Flush all persistent caches.
// This is executed based on old/previously known information, which is
// sufficient, since new extensions cannot have any primed caches yet.
foreach (module_invoke_all('cache_flush') as $bin) {
cache($bin)->flush();
}
registry_rebuild();
// Flush asset file caches.
drupal_clear_css_cache();
drupal_clear_js_cache();
_drupal_flush_css_js();
// Rebuild the theme data. Note that the module data is rebuilt above, as
// part of registry_rebuild().
system_rebuild_theme_data();
drupal_theme_rebuild();
entity_info_cache_clear();
// Reset all static caches.
drupal_static_reset();
// @todo D8: Split cache flushing from rebuilding.
// @see http://drupal.org/node/996236
if (module_exists('node')) {
node_types_rebuild();
}
// node_menu() defines menu items based on node types so it needs to come
// after node types are rebuilt.
menu_rebuild();
// Clear all non-drupal_static() static caches.
// None currently; kept if any static caches need to be reset in the future.
// Synchronize to catch any actions that were added or removed.
actions_synchronize();
// Update and synchronize the class registry and extension information based
// on current/actual code.
// Module data is rebuilt as part of registry_rebuild().
registry_rebuild();
system_rebuild_theme_data();
// Don't clear cache_form - in-progress form submissions may break.
// Ordered so clearing the page cache will always be the last action.
$core = array('cache', 'path', 'filter', 'bootstrap', 'page');
$cache_bins = array_merge(module_invoke_all('flush_caches'), $core);
foreach ($cache_bins as $bin) {
cache($bin)->flush();
}
// Ensure that all modules that are currently supposed to be enabled are
// actually loaded.
module_load_all();
// Rebuild the bootstrap module list. We do this here so that developers
// can get new hook_boot() implementations registered without having to
// write a hook_update_N() function.
// Update the list of bootstrap modules.
// Allows developers to get new hook_boot() implementations registered without
// having to write a hook_update_N() function.
_system_update_bootstrap_status();
// Rebuild the schema and cache a fully-built schema based on new module data.
// This is necessary for any invocation of index.php, because setting cache
// table entries requires schema information and that occurs during bootstrap
// before any modules are loaded, so if there is no cached schema,
// drupal_get_schema() will try to generate one, but with no loaded modules,
// it will return nothing.
drupal_get_schema(NULL, TRUE);
// Rebuild all information based on new module data.
module_invoke_all('rebuild');
// Rebuild the menu router based on all rebuilt data.
// Important: This rebuild must happen last, so the menu router is guaranteed
// to be based on up to date information.
menu_router_rebuild();
// Re-initialize the maintenance theme, if the current request attempted to
// use it. Unlike regular usages of this function, the installer and update
// scripts need to flush all caches during GET requests/page building.
if (function_exists('_drupal_maintenance_theme')) {
unset($GLOBALS['theme']);
drupal_maintenance_theme();
}
}
/**
......
......@@ -79,7 +79,7 @@
* the elements and properties of the form. For information on the array
* components and format, and more detailed explanations of the Form API
* workflow, see the
* @link http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html Form API reference @endlink
* @link forms_api_reference.html Form API reference @endlink
* and the
* @link http://drupal.org/node/37775 Form API documentation section. @endlink
* In addition, there is a set of Form API tutorials in
......@@ -214,10 +214,10 @@ function drupal_get_form($form_id) {
* set.
* - values: An associative array of values submitted to the form. The
* validation functions and submit functions use this array for nearly all
* their decision making. (Note that
* @link http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7#tree #tree @endlink
* determines whether the values are a flat array or an array whose
* structure parallels the $form array.)
* their decision making. (Note that #tree determines whether the values
* are a flat array or an array whose structure parallels the $form array.
* See the @link forms_api_reference.html Form API reference @endlink for
* more information.)
* - input: The array of values as they were submitted by the user. These are
* raw and unvalidated, so should not be used without a thorough
* understanding of security implications. In almost all cases, code should
......
......@@ -61,7 +61,7 @@ function _locale_import_po($file, $langcode, $overwrite_options, $customized = L
cache()->deletePrefix('locale:');
// Rebuild the menu, strings may have changed.
menu_rebuild();
menu_router_rebuild();
drupal_set_message(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => $additions, '%update' => $updates, '%delete' => $deletes)));
watchdog('locale', 'Imported %file into %locale: %number new strings added, %update updated and %delete removed.', array('%file' => $file->filename, '%locale' => $langcode, '%number' => $additions, '%update' => $updates, '%delete' => $deletes));
......
......@@ -1587,28 +1587,26 @@ function install_import_translations_remaining(&$install_state) {
* A message informing the user that the installation is complete.
*/
function install_finished(&$install_state) {
drupal_set_title(st('@drupal installation complete', array('@drupal' => drupal_install_profile_distribution_name())), PASS_THROUGH);
$messages = drupal_set_message();
$output = '<p>' . st('Congratulations, you installed @drupal!', array('@drupal' => drupal_install_profile_distribution_name())) . '</p>';
$output .= '<p>' . (isset($messages['error']) ? st('Review the messages above before visiting <a href="@url">your new site</a>.', array('@url' => url(''))) : st('<a href="@url">Visit your new site</a>.', array('@url' => url('')))) . '</p>';
// Flush all caches to ensure that any full bootstraps during the installer
// do not leave stale cached data, and that any content types or other items
// registered by the install profile are registered correctly.
drupal_flush_all_caches();
// Remember the profile which was used.
variable_set('install_profile', drupal_get_profile());
// Install profiles are always loaded last
// Install profiles are always loaded last.
db_update('system')
->fields(array('weight' => 1000))
->condition('type', 'module')
->condition('name', drupal_get_profile())
->execute();
// Cache a fully-built schema.
drupal_get_schema(NULL, TRUE);
// Flush all caches to ensure that any full bootstraps during the installer
// do not leave stale cached data, and that any content types or other items
// registered by the install profile are registered correctly.
drupal_flush_all_caches();
drupal_set_title(st('@drupal installation complete', array('@drupal' => drupal_install_profile_distribution_name())), PASS_THROUGH);
$messages = drupal_set_message();
$output = '<p>' . st('Congratulations, you installed @drupal!', array('@drupal' => drupal_install_profile_distribution_name())) . '</p>';
$output .= '<p>' . (isset($messages['error']) ? st('Review the messages above before visiting <a href="@url">your new site</a>.', array('@url' => url(''))) : st('<a href="@url">Visit your new site</a>.', array('@url' => url('')))) . '</p>';
// Run cron to populate update status tables (if available) so that users
// will be warned if they've installed an out of date Drupal version.
......
......@@ -13,9 +13,10 @@
* In most environments, multiple Drupal page requests (a.k.a. threads or
* processes) will execute in parallel. This leads to potential conflicts or
* race conditions when two requests execute the same code at the same time. A
* common example of this is a rebuild like menu_rebuild() where we invoke many
* hook implementations to get and process data from all active modules, and
* then delete the current data in the database to insert the new afterwards.
* common example of this is a rebuild like menu_router_rebuild() where we
* invoke many hook implementations to get and process data from all active
* modules, and then delete the current data in the database to insert the new
* afterwards.
*
* This is a cooperative, advisory lock system. Any long-running operation
* that could potentially be attempted in parallel by multiple requests should
......
......@@ -301,7 +301,7 @@
* then the 1011 bitstring represents node/%/edit/foo where % means that
* any argument matches that part. We limit ourselves to using binary
* numbers that correspond the patterns of wildcards of router items that
* actually exists. This list of 'masks' is built in menu_rebuild().
* actually exists. This list of 'masks' is built in menu_router_rebuild().
*
* @param $parts
* An array of path parts, for the above example
......@@ -450,7 +450,7 @@ function menu_get_item($path = NULL, $router_item = NULL) {
// Rebuild if we know it's needed, or if the menu masks are missing which
// occurs rarely, likely due to a race condition of multiple rebuilds.
if (variable_get('menu_rebuild_needed', FALSE) || !variable_get('menu_masks', array())) {
menu_rebuild();
menu_router_rebuild();
}
$original_map = arg(NULL, $path);
......@@ -2658,12 +2658,12 @@ function menu_reset_static_cache() {
* TRUE if the menu was rebuilt, FALSE if another thread was rebuilding
* in parallel and the current thread just waited for completion.
*/
function menu_rebuild() {
if (!lock_acquire('menu_rebuild')) {
function menu_router_rebuild() {
if (!lock_acquire(__FUNCTION__)) {
// Wait for another request that is already doing this work.
// We choose to block here since otherwise the router item may not
// be available in menu_execute_active_handler() resulting in a 404.
lock_wait('menu_rebuild');
lock_wait(__FUNCTION__);
return FALSE;
}
......@@ -2684,7 +2684,7 @@ function menu_rebuild() {
watchdog_exception('menu', $e);
}
lock_release('menu_rebuild');
lock_release(__FUNCTION__);
return TRUE;
}
......
......@@ -19,7 +19,15 @@
* have been loaded.
*/
function module_load_all($bootstrap = FALSE) {
static $has_run = FALSE;
// Already loaded code cannot be unloaded, but new modules may be added within
// a request, which should be loaded as well.
// Use the advanced drupal_static() pattern, since this is called very often.
// @see theme()
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['has_run'] = &drupal_static(__FUNCTION__, FALSE);
}
$has_run = &$drupal_static_fast['has_run'];
if (isset($bootstrap)) {
foreach (module_list(TRUE, $bootstrap) as $module) {
......@@ -66,7 +74,16 @@ function module_load_all($bootstrap = FALSE) {
* the list.
*/
function module_list($refresh = FALSE, $bootstrap_refresh = FALSE, $sort = FALSE, $fixed_list = NULL) {
static $list = array(), $sorted_list;
// system_list() may be reset within a request, so the module list needs to be
// reset, too.
// Use the advanced drupal_static() pattern, since this is called very often.
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['list'] = &drupal_static(__FUNCTION__ . ':list', array());
$drupal_static_fast['sorted_list'] = &drupal_static(__FUNCTION__ . ':sorted_list');
}
$list = &$drupal_static_fast['list'];
$sorted_list = &$drupal_static_fast['sorted_list'];
if (empty($list) || $refresh || $fixed_list) {
$list = array();
......
......@@ -1489,7 +1489,7 @@ function theme_enable($theme_list) {
}
list_themes(TRUE);
menu_rebuild();
menu_router_rebuild();
drupal_theme_rebuild();
// Invoke hook_themes_enabled() after the themes have been enabled.
......@@ -1522,7 +1522,7 @@ function theme_disable($theme_list) {
}
list_themes(TRUE);
menu_rebuild();
menu_router_rebuild();
drupal_theme_rebuild();
// Invoke hook_themes_disabled after the themes have been disabled.
......@@ -2097,7 +2097,7 @@ function theme_mark($variables) {
*/
function theme_item_list($variables) {
$items = $variables['items'];
$title = $variables['title'];
$title = (string) $variables['title'];
$type = $variables['type'];
$list_attributes = $variables['attributes'];
......@@ -2158,7 +2158,7 @@ function theme_item_list($variables) {
// Check to see whether the block title exists before adding a header.
// Empty headers are not semantic and present accessibility challenges.
if ($output !== '') {
if (isset($title) && $title !== '') {
if ($title !== '') {
$title = '<h3>' . $title . '</h3>';
}
$output = '<div class="item-list">' . $title . $output . '</div>';
......
<?php
/**
* @file
* Definition of Drupal\Core\DependencyInjection\Container.
*/
namespace Drupal\Core\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder as BaseContainerBuilder;
/**
* Drupal's dependency injection container.
*/
class ContainerBuilder extends BaseContainerBuilder {
/**
* Registers the base Drupal services for the dependency injection container.
*/
public function __construct() {
parent::__construct();
// An interface language always needs to be available for t() and other
// functions. This default is overridden by drupal_language_initialize()
// during language negotiation.
$this->register(LANGUAGE_TYPE_INTERFACE, 'Drupal\\Core\\Language\\Language');
}
}
......@@ -527,7 +527,7 @@ $(document).bind('state:checked', function(e) {
$(document).bind('state:collapsed', function(e) {
if (e.trigger) {
if ($(e.target).is('.collapsed') !== e.value) {
$(e.target).find$('> legend a').click();
$(e.target).find('> legend a').click();
}
}
});
......
......@@ -790,7 +790,7 @@ function _aggregator_items($count) {
}
/**
* Implements hook_preprocess_block().
* Implements hook_preprocess_HOOK() for block.tpl.php.
*/
function aggregator_preprocess_block(&$variables) {
if ($variables['block']->module == 'aggregator') {
......
......@@ -893,7 +893,7 @@ class AggregatorRenderingTestCase extends AggregatorTestCase {
$feed->block = 0;
aggregator_save_feed((array) $feed);
// It is nescessary to flush the cache after saving the number of items.
drupal_flush_all_caches();
$this->resetAll();
// Check that the block is no longer displayed.
$this->drupalGet('node');
$this->assertNoText(t($block['title']), 'Feed block is not displayed on the page when number of items is set to 0.');
......
......@@ -935,9 +935,16 @@ function _block_get_renderable_block($element) {
}
/**
* Implements hook_flush_caches().
* Implements hook_cache_flush().
*/
function block_flush_caches() {
function block_cache_flush() {
return array('block');
}
/**
* Implements hook_rebuild().
*/
function block_rebuild() {
// Rehash blocks for active themes. We don't use list_themes() here,
// because if MAINTENANCE_MODE is defined it skips reading the database,
// and we can't tell which themes are active.
......@@ -945,8 +952,6 @@ function block_flush_caches() {
foreach ($themes as $theme) {
_block_rehash($theme->name);
}
return array('block');
}
/**
......
......@@ -391,7 +391,7 @@ class BlockTestCase extends DrupalWebTestCase {
// Disable caching for this block.
variable_set('block_test_caching', DRUPAL_NO_CACHE);
// Flushing all caches should call _block_rehash().
drupal_flush_all_caches();
$this->resetAll();
// Verify that the database is updated with the new caching mode.
$current_caching = db_query("SELECT cache FROM {block} WHERE module = 'block_test' AND delta = 'test_cache'")->fetchField();
$this->assertEqual($current_caching, DRUPAL_NO_CACHE, t("Test block's database entry updated to DRUPAL_NO_CACHE."));
......@@ -833,7 +833,7 @@ class BlockHiddenRegionTestCase extends DrupalWebTestCase {
$theme = 'block_test_theme';
theme_enable(array($theme));
variable_set('theme_default', $theme);
menu_rebuild();
menu_router_rebuild();
// Ensure that "block_test_theme" is set as the default theme.
$this->drupalGet('admin/structure/block');
......
......@@ -1065,7 +1065,7 @@ function _book_link_defaults($nid) {
}
/**
* Implements hook_preprocess_block().
* Implements hook_preprocess_HOOK() for block.tpl.php.
*/
function book_preprocess_block(&$variables) {
if ($variables['block']-> module == 'book') {
......
......@@ -324,9 +324,10 @@ function color_scheme_form_submit($form, &$form_state) {
// memory_get_usage(), therefore we won't inadvertently reject a color