248 lines
9 KiB
PHP
248 lines
9 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Root directory of Drupal installation. Note that you can change this
|
|
* if you need to. It just has to point to the actual root. This assumes
|
|
* that the php file is being run in sites/all/modules/registry_rebuild.
|
|
*/
|
|
|
|
ini_set('memory_limit', -1);
|
|
define('DRUPAL_ROOT', define_drupal_root());
|
|
chdir(DRUPAL_ROOT);
|
|
print "DRUPAL_ROOT is " . DRUPAL_ROOT . ".<br/>\n";
|
|
define('MAINTENANCE_MODE', 'update');
|
|
|
|
global $_SERVER;
|
|
$_SERVER['REMOTE_ADDR'] = 'nothing';
|
|
|
|
global $include_dir;
|
|
$include_dir = DRUPAL_ROOT . '/includes';
|
|
$module_dir = DRUPAL_ROOT . '/modules';
|
|
// Use core directory if it exists.
|
|
if (file_exists(DRUPAL_ROOT . '/core/includes/bootstrap.inc')) {
|
|
$include_dir = DRUPAL_ROOT . '/core/includes';
|
|
$module_dir = DRUPAL_ROOT . '/core/modules';
|
|
}
|
|
|
|
require_once($include_dir . '/bootstrap.inc');
|
|
drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
|
|
|
|
$includes = array(
|
|
$include_dir . '/common.inc',
|
|
$include_dir . '/database.inc',
|
|
$include_dir . '/schema.inc',
|
|
$include_dir . '/actions.inc',
|
|
$include_dir . '/entity.inc',
|
|
$module_dir . '/system/system.module',
|
|
$include_dir . '/database/database.inc',
|
|
$include_dir . '/database/query.inc',
|
|
$include_dir . '/database/select.inc',
|
|
$include_dir . '/registry.inc',
|
|
$include_dir . '/module.inc',
|
|
$include_dir . '/menu.inc',
|
|
$include_dir . '/file.inc',
|
|
$include_dir . '/theme.inc',
|
|
$include_dir . '/locale.inc',
|
|
);
|
|
|
|
if (function_exists('registry_rebuild')) { // == D7
|
|
$cache_lock_path_absolute = variable_get('lock_inc');
|
|
if (!empty($cache_lock_path_absolute)) {
|
|
$cache_lock_path_relative = DRUPAL_ROOT . '/'. variable_get('lock_inc');
|
|
// Ensure that the configured lock.inc really exists at that location and
|
|
// is accessible. Otherwise we use the core lock.inc as fallback.
|
|
if (is_readable($cache_lock_path_relative) && is_file($cache_lock_path_relative)) {
|
|
$includes[] = $cache_lock_path_relative;
|
|
print "We will use relative variant of lock.inc.<br/>\n";
|
|
}
|
|
elseif (is_readable($cache_lock_path_absolute) && is_file($cache_lock_path_absolute)) {
|
|
$includes[] = $cache_lock_path_absolute;
|
|
print "We will use absolute variant of lock.inc.<br/>\n";
|
|
}
|
|
else {
|
|
print "We will use core implementation of lock.inc as fallback.<br/>\n";
|
|
$includes[] = DRUPAL_ROOT . '/includes/lock.inc';
|
|
}
|
|
}
|
|
else {
|
|
$includes[] = DRUPAL_ROOT . '/includes/lock.inc';
|
|
}
|
|
}
|
|
elseif (!function_exists('cache_clear_all')) { // D8+
|
|
// TODO
|
|
// http://api.drupal.org/api/drupal/namespace/Drupal!Core!Lock/8
|
|
$includes[] = $module_dir . '/entity/entity.module';
|
|
$includes[] = $module_dir . '/entity/entity.controller.inc';
|
|
}
|
|
// In Drupal 6 the configured lock.inc is already loaded during
|
|
// DRUSH_BOOTSTRAP_DRUPAL_DATABASE
|
|
|
|
foreach ($includes as $include) {
|
|
if (file_exists($include)) {
|
|
require_once($include);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('module_list')) {
|
|
print "ERROR! Registry Rebuild requires a working Drupal site to operate on.<br/>\n";
|
|
print "Please run this script from the correct Drupal site directory,<br/>\n";
|
|
print "or specify Drupal root path on command line, for example:<br/>\n";
|
|
print "php registry_rebuild.php --root=/path/to/drupal/root<br/>\n";
|
|
print "BYE!<br/>\n";
|
|
exit;
|
|
}
|
|
|
|
print "Bootstrapping to DRUPAL_BOOTSTRAP_SESSION<br/>\n";
|
|
drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
|
|
|
|
registry_rebuild_rebuild();
|
|
|
|
/**
|
|
* Find the drupal root directory by looking in parent directories.
|
|
* If unable to discover it, fail and exit.
|
|
*/
|
|
function define_drupal_root() {
|
|
$args = getopt(NULL, array('root::'));
|
|
if (!empty($args['root'])) {
|
|
return $args['root'];
|
|
}
|
|
|
|
// This is the smallest number of directories to go up: from /sites/all/modules/registry_rebuild.
|
|
$parent_count = 4;
|
|
// 8 seems reasonably far to go looking up.
|
|
while ($parent_count < 8) {
|
|
$dir = realpath(getcwd() . str_repeat('/..', $parent_count));
|
|
if (file_exists($dir . '/index.php')) {
|
|
return $dir;
|
|
}
|
|
$parent_count++;
|
|
}
|
|
print "Failure: Unable to discover DRUPAL_ROOT. You may want to explicitly define it near the top of registry_rebuild.php";
|
|
exit(1);
|
|
}
|
|
|
|
/**
|
|
* Before calling this we need to be bootstrapped to DRUPAL_BOOTSTRAP_SESSION.
|
|
*/
|
|
function registry_rebuild_rebuild() {
|
|
// This section is not functionally important. It's just using the
|
|
// registry_get_parsed_files() so that it can report the change. Drupal 7 only.
|
|
if (function_exists('registry_rebuild')) {
|
|
$connection_info = Database::getConnectionInfo();
|
|
$driver = $connection_info['default']['driver'];
|
|
global $include_dir;
|
|
require_once $include_dir . '/database/' . $driver . '/query.inc';
|
|
$parsed_before = registry_get_parsed_files();
|
|
}
|
|
|
|
// Separate bootstrap cache exists only in Drupal 7 or newer.
|
|
// They are cleared later again via drupal_flush_all_caches().
|
|
if (function_exists('registry_rebuild')) { // D7
|
|
cache_clear_all('lookup_cache', 'cache_bootstrap');
|
|
cache_clear_all('variables', 'cache_bootstrap');
|
|
cache_clear_all('module_implements', 'cache_bootstrap');
|
|
print "Bootstrap caches have been cleared in DRUPAL_BOOTSTRAP_SESSION<br/>\n";
|
|
}
|
|
elseif (!function_exists('cache_clear_all')) { // D8+
|
|
cache('bootstrap')->deleteAll();
|
|
print "Bootstrap caches have been cleared in DRUPAL_BOOTSTRAP_SESSION<br/>\n";
|
|
}
|
|
|
|
// We later run system_rebuild_module_data() and registry_update() on Drupal 7 via
|
|
// D7-only registry_rebuild() wrapper, which is run inside drupal_flush_all_caches().
|
|
// It is an equivalent of module_rebuild_cache() in D5-D6 and is normally run via
|
|
// our universal wrapper registry_rebuild_cc_all() -- see further below.
|
|
// However, we are still on the DRUPAL_BOOTSTRAP_SESSION level here,
|
|
// and we want to make the initial rebuild as atomic as possible, so we can't
|
|
// run everything from registry_rebuild_cc_all() yet, so we run an absolute
|
|
// minimum we can at this stage, core specific.
|
|
if (function_exists('registry_rebuild')) { // D7 only
|
|
print "Doing registry_rebuild() in DRUPAL_BOOTSTRAP_SESSION<br/>\n";
|
|
registry_rebuild();
|
|
}
|
|
elseif (!function_exists('registry_rebuild') && function_exists('system_rebuild_module_data')) { // D8+
|
|
print "Doing system_rebuild_module_data() in DRUPAL_BOOTSTRAP_SESSION<br/>\n";
|
|
system_rebuild_module_data();
|
|
}
|
|
else { // D5-D6
|
|
print "Doing module_rebuild_cache() in DRUPAL_BOOTSTRAP_SESSION<br/>\n";
|
|
module_list(TRUE, FALSE);
|
|
module_rebuild_cache();
|
|
}
|
|
|
|
print "Bootstrapping to DRUPAL_BOOTSTRAP_FULL<br/>\n";
|
|
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
|
|
// We can run our wrapper now, since we are in a full bootstrap already.
|
|
print "Rebuilding registry via registry_rebuild_cc_all in DRUPAL_BOOTSTRAP_FULL<br/>\n";
|
|
registry_rebuild_cc_all();
|
|
|
|
// Extra cleanup available for D7 only.
|
|
if (function_exists('registry_rebuild')) {
|
|
$parsed_after = registry_get_parsed_files();
|
|
// Remove files which don't exist anymore.
|
|
$filenames = array();
|
|
foreach ($parsed_after as $filename => $file) {
|
|
if (!file_exists($filename)) {
|
|
$filenames[] = $filename;
|
|
}
|
|
}
|
|
if (!empty($filenames)) {
|
|
db_delete('registry_file')
|
|
->condition('filename', $filenames)
|
|
->execute();
|
|
db_delete('registry')
|
|
->condition('filename', $filenames)
|
|
->execute();
|
|
print("Deleted " . count($filenames) . ' stale files from registry manually.');
|
|
}
|
|
$parsed_after = registry_get_parsed_files();
|
|
print "There were " . count($parsed_before) . " files in the registry before and " . count($parsed_after) . " files now.<br/>\n";
|
|
registry_rebuild_cc_all();
|
|
}
|
|
print "If you don't see any crazy fatal errors, your registry has been rebuilt.<br/>\n";
|
|
}
|
|
|
|
/**
|
|
* Registry Rebuild needs to aggressively clear all caches,
|
|
* not just some bins (at least to attempt it) also *before*
|
|
* attempting to rebuild registry, or it may not be able
|
|
* to fix the problem at all, if it relies on some cached
|
|
* and no longer valid data/paths etc. This problem has been
|
|
* confirmed and reproduced many times with option --fire-bazooka
|
|
* which is available only in the Drush variant, but it confirms
|
|
* the importance of starting with real, raw and not cached
|
|
* in any way site state. While the --no-cache-clear option
|
|
* still disables this procedure, --fire-bazooka takes precedence
|
|
* and forces all caches clear action. All caches are cleared
|
|
* by default in the PHP script variant.
|
|
*/
|
|
function registry_rebuild_cc_all() {
|
|
module_invoke_all('pre_flush_all_caches');
|
|
if (function_exists('cache_clear_all')) {
|
|
cache_clear_all('*', 'cache', TRUE);
|
|
cache_clear_all('*', 'cache_form', TRUE);
|
|
}
|
|
else {
|
|
cache('cache')->deleteAll();
|
|
cache('cache_form')->deleteAll();
|
|
}
|
|
|
|
module_invoke_all('pre_flush_all_caches');
|
|
|
|
if (function_exists('module_rebuild_cache')) { // D5-D6
|
|
module_list(TRUE, FALSE);
|
|
module_rebuild_cache();
|
|
}
|
|
|
|
if (function_exists('drupal_flush_all_caches')) { // D6+
|
|
drupal_flush_all_caches();
|
|
}
|
|
else { // D5
|
|
cache_clear_all();
|
|
system_theme_data();
|
|
node_types_rebuild();
|
|
menu_rebuild();
|
|
}
|
|
print "All caches have been cleared with registry_rebuild_cc_all.<br/>\n";
|
|
}
|