Add registry_rebuild.php

This commit is contained in:
Oliver Davies 2018-11-25 19:33:41 +00:00
parent 3cb9f04441
commit 239a8a9e0a

247
web/registry_rebuild.php Normal file
View file

@ -0,0 +1,247 @@
<?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";
}