$t('Drupal'), 'value' => VERSION, 'severity' => REQUIREMENT_INFO, 'weight' => -10, ); // Display the currently active install profile, if the site // is not running the default install profile. $profile = drupal_get_profile(); if ($profile != 'default') { $info = install_profile_info($profile); $requirements['install_profile'] = array( 'title' => $t('Install profile'), 'value' => $t('%profile_name (%profile-%version)', array( '%profile_name' => $info['name'], '%profile' => $profile, '%version' => $info['version'] )), 'severity' => REQUIREMENT_INFO, 'weight' => -9 ); } } // Web server information. $software = $_SERVER['SERVER_SOFTWARE']; $requirements['webserver'] = array( 'title' => $t('Web server'), 'value' => $software, ); // Test PHP version and show link to phpinfo() if it's available $phpversion = phpversion(); if (function_exists('phpinfo')) { $requirements['php'] = array( 'title' => $t('PHP'), 'value' => ($phase == 'runtime') ? $phpversion .' ('. l($t('more information'), 'admin/reports/status/php') .')' : $phpversion, ); } else { $requirements['php'] = array( 'title' => $t('PHP'), 'value' => $phpversion, 'description' => $t('The phpinfo() function has been disabled for security reasons. To see your server\'s phpinfo() information, change your PHP settings or contact your server administrator. For more information, please read the Enabling and disabling phpinfo() handbook page.', array('@phpinfo' => 'http://drupal.org/node/243993')), 'severity' => REQUIREMENT_INFO, ); } if (version_compare($phpversion, DRUPAL_MINIMUM_PHP) < 0) { $requirements['php']['description'] = $t('Your PHP installation is too old. Drupal requires at least PHP %version.', array('%version' => DRUPAL_MINIMUM_PHP)); $requirements['php']['severity'] = REQUIREMENT_ERROR; } // Test PHP register_globals setting. $requirements['php_register_globals'] = array( 'title' => $t('PHP register globals'), ); $register_globals = trim(ini_get('register_globals')); // Unfortunately, ini_get() may return many different values, and we can't // be certain which values mean 'on', so we instead check for 'not off' // since we never want to tell the user that their site is secure // (register_globals off), when it is in fact on. We can only guarantee // register_globals is off if the value returned is 'off', '', or 0. if (!empty($register_globals) && strtolower($register_globals) != 'off') { $requirements['php_register_globals']['description'] = $t('register_globals is enabled. Drupal requires this configuration directive to be disabled. Your site may not be secure when register_globals is enabled. The PHP manual has instructions for how to change configuration settings.'); $requirements['php_register_globals']['severity'] = REQUIREMENT_ERROR; $requirements['php_register_globals']['value'] = $t("Enabled ('@value')", array('@value' => $register_globals)); } else { $requirements['php_register_globals']['value'] = $t('Disabled'); } // Test PHP memory_limit $memory_limit = ini_get('memory_limit'); $requirements['php_memory_limit'] = array( 'title' => $t('PHP memory limit'), 'value' => $memory_limit == -1 ? t('-1 (Unlimited)') : $memory_limit, ); if ($memory_limit && $memory_limit != -1 && parse_size($memory_limit) < parse_size(DRUPAL_MINIMUM_PHP_MEMORY_LIMIT)) { $description = ''; if ($phase == 'install') { $description = $t('Consider increasing your PHP memory limit to %memory_minimum_limit to help prevent errors in the installation process.', array('%memory_minimum_limit' => DRUPAL_MINIMUM_PHP_MEMORY_LIMIT)); } elseif ($phase == 'update') { $description = $t('Consider increasing your PHP memory limit to %memory_minimum_limit to help prevent errors in the update process.', array('%memory_minimum_limit' => DRUPAL_MINIMUM_PHP_MEMORY_LIMIT)); } elseif ($phase == 'runtime') { $description = $t('Depending on your configuration, Drupal can run with a %memory_limit PHP memory limit. However, a %memory_minimum_limit PHP memory limit or above is recommended, especially if your site uses additional custom or contributed modules.', array('%memory_limit' => $memory_limit, '%memory_minimum_limit' => DRUPAL_MINIMUM_PHP_MEMORY_LIMIT)); } if (!empty($description)) { if ($php_ini_path = get_cfg_var('cfg_file_path')) { $description .= ' ' . $t('Increase the memory limit by editing the memory_limit parameter in the file %configuration-file and then restart your web server (or contact your system administrator or hosting provider for assistance).', array('%configuration-file' => $php_ini_path)); } else { $description .= ' ' . $t('Contact your system administrator or hosting provider for assistance with increasing your PHP memory limit.'); } $requirements['php_memory_limit']['description'] = $description . ' ' . $t('See the Drupal requirements for more information.', array('@url' => 'http://drupal.org/requirements')); $requirements['php_memory_limit']['severity'] = REQUIREMENT_WARNING; } } // Test settings.php file writability if ($phase == 'runtime') { $conf_dir = drupal_verify_install_file(conf_path(), FILE_NOT_WRITABLE, 'dir'); $conf_file = drupal_verify_install_file(conf_path() . '/settings.php', FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE); if (!$conf_dir || !$conf_file) { $requirements['settings.php'] = array( 'value' => $t('Not protected'), 'severity' => REQUIREMENT_ERROR, 'description' => '', ); if (!$conf_dir) { $requirements['settings.php']['description'] .= $t('The directory %file is not protected from modifications and poses a security risk. You must change the directory\'s permissions to be non-writable. ', array('%file' => conf_path())); } if (!$conf_file) { $requirements['settings.php']['description'] .= $t('The file %file is not protected from modifications and poses a security risk. You must change the file\'s permissions to be non-writable.', array('%file' => conf_path() . '/settings.php')); } } else { $requirements['settings.php'] = array( 'value' => $t('Protected'), ); } $requirements['settings.php']['title'] = $t('Configuration file'); } // Report cron status. if ($phase == 'runtime') { // Cron warning threshold defaults to two days. $threshold_warning = variable_get('cron_threshold_warning', 172800); // Cron error threshold defaults to two weeks. $threshold_error = variable_get('cron_threshold_error', 1209600); // Cron configuration help text. $help = $t('For more information, see the online handbook entry for configuring cron jobs.', array('@cron-handbook' => 'http://drupal.org/cron')); // Determine when cron last ran. $cron_last = variable_get('cron_last'); if (!is_numeric($cron_last)) { $cron_last = variable_get('install_time', 0); } // Determine severity based on time since cron last ran. $severity = REQUIREMENT_OK; if (REQUEST_TIME - $cron_last > $threshold_error) { $severity = REQUIREMENT_ERROR; } elseif (REQUEST_TIME - $cron_last > $threshold_warning) { $severity = REQUIREMENT_WARNING; } // Set summary and description based on values determined above. $summary = $t('Last run !time ago', array('!time' => format_interval(REQUEST_TIME - $cron_last))); $description = ''; if ($severity != REQUIREMENT_OK) { $description = $t('Cron has not run recently.') . ' ' . $help; } $description .= ' ' . $t('You can run cron manually.', array('@cron' => url('admin/reports/status/run-cron'))); $description .= '
' . $t('To run cron from outside the site, go to !cron', array('!cron' => url($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => variable_get('cron_key', 'drupal')))))); $requirements['cron'] = array( 'title' => $t('Cron maintenance tasks'), 'severity' => $severity, 'value' => $summary, 'description' => $description ); } // Test files directories. $directories = array( variable_get('file_public_path', conf_path() . '/files'), variable_get('file_private_path', conf_path() . '/private/files'), variable_get('file_temporary_path', conf_path() . '/private/temp'), ); $requirements['file system'] = array( 'title' => $t('File system'), ); $error = ''; // For installer, create the directories if possible. foreach ($directories as $directory) { if ($phase == 'install') { file_prepare_directory($directory, FILE_CREATE_DIRECTORY); } $is_writable = is_writable($directory); $is_directory = is_dir($directory); if (!$is_writable || !$is_directory) { $description = ''; $requirements['file system']['value'] = $t('Not writable'); if (!$is_directory) { $error .= $t('The directory %directory does not exist.', array('%directory' => $directory)) . ' '; } else { $error .= $t('The directory %directory is not writable.', array('%directory' => $directory)) . ' '; } // The files directory requirement check is done only during install and runtime. if ($phase == 'runtime') { $description = $error . $t('You may need to set the correct directory at the file system settings page or change the current directory\'s permissions so that it is writable.', array('@admin-file-system' => url('admin/config/media/file-system'))); } elseif ($phase == 'install') { // For the installer UI, we need different wording. 'value' will // be treated as version, so provide none there. $description = $error . $t('An automated attempt to create this directory failed, possibly due to a permissions problem. To proceed with the installation, either create the directory and modify its permissions manually, or ensure that the installer has the permissions to create it automatically. For more information, please see INSTALL.txt or the online handbook.', array('@handbook_url' => 'http://drupal.org/server-permissions')); $requirements['file system']['value'] = ''; } if (!empty($description)) { $requirements['file system']['description'] = $description; $requirements['file system']['severity'] = REQUIREMENT_ERROR; } } else { if (variable_get('file_default_scheme', 'public') == 'public') { $requirements['file system']['value'] = $t('Writable (public download method)'); } else { $requirements['file system']['value'] = $t('Writable (private download method)'); } } } // See if updates are available in update.php. if ($phase == 'runtime') { $requirements['update'] = array( 'title' => $t('Database updates'), 'severity' => REQUIREMENT_OK, 'value' => $t('Up to date'), ); // Check installed modules. foreach (module_list() as $module) { $updates = drupal_get_schema_versions($module); if ($updates !== FALSE) { $default = drupal_get_installed_schema_version($module); if (max($updates) > $default) { $requirements['update']['severity'] = REQUIREMENT_ERROR; $requirements['update']['value'] = $t('Out of date'); $requirements['update']['description'] = $t('Some modules have database schema updates to install. You should run the database update script immediately.', array('@update' => base_path() . 'update.php')); break; } } } } // Verify the update.php access setting if ($phase == 'runtime') { if (!empty($GLOBALS['update_free_access'])) { $requirements['update access'] = array( 'value' => $t('Not protected'), 'severity' => REQUIREMENT_ERROR, 'description' => $t('The update.php script is accessible to everyone without authentication check, which is a security risk. You must change the $update_free_access value in your settings.php back to FALSE.'), ); } else { $requirements['update access'] = array( 'value' => $t('Protected'), ); } $requirements['update access']['title'] = $t('Access to update.php'); } // Test Unicode library include_once DRUPAL_ROOT . '/includes/unicode.inc'; $requirements = array_merge($requirements, unicode_requirements()); // Verify if the DOM PHP 5 extension is available. $has_dom = class_exists('DOMDocument'); if (!$has_dom) { $requirements['php_dom'] = array( 'title' => $t('PHP DOM Extension'), 'value' => $t('Not found'), 'severity' => REQUIREMENT_ERROR, 'description' => $t("The DOM extension is part of PHP 5 core, but doesn't seem to be enabled on your system. You need to enable the DOM extension on your PHP installation."), ); } if ($phase == 'runtime') { // Check for update status module. if (!module_exists('update')) { $requirements['update status'] = array( 'value' => $t('Not enabled'), 'severity' => REQUIREMENT_WARNING, 'description' => $t('Update notifications are not enabled. It is highly recommended that you enable the update status module from the module administration page in order to stay up-to-date on new releases. For more information please read the Update status handbook page.', array('@update' => 'http://drupal.org/handbook/modules/update', '@module' => url('admin/modules'))), ); } else { $requirements['update status'] = array( 'value' => $t('Enabled'), ); } $requirements['update status']['title'] = $t('Update notifications'); // Check that Drupal can issue HTTP requests. if (variable_get('drupal_http_request_fails', TRUE) && !system_check_http_request()) { $requirements['http requests'] = array( 'title' => $t('HTTP request status'), 'value' => $t('Fails'), 'severity' => REQUIREMENT_ERROR, 'description' => $t('Your system or network configuration does not allow Drupal to access web pages, resulting in reduced functionality. This could be due to your webserver configuration or PHP settings, and should be resolved in order to download information about available updates, fetch aggregator feeds, sign in via OpenID, or use other network-dependent services. If you are certain that Drupal can access web pages but you are still seeing this message, you may add $conf[\'drupal_http_request_fails\'] = FALSE; to the bottom of your settings.php file.'), ); } } return $requirements; } /** * Implements hook_install(). */ function system_install() { // Create tables. $modules = array('system', 'filter', 'user', 'node'); foreach ($modules as $module) { drupal_install_schema($module); $versions = drupal_get_schema_versions($module); $version = $versions ? max($versions) : SCHEMA_INSTALLED; drupal_set_installed_schema_version($module, $version); } // Clear out module list and hook implementation statics before calling // system_rebuild_theme_data(). module_list(TRUE); module_implements('', FALSE, TRUE); // Load system theme data appropriately. system_rebuild_theme_data(); db_insert('users') ->fields(array( 'uid' => 0, 'name' => '', 'mail' => '', )) ->execute(); // We need some placeholders here as name and mail are uniques and data is // presumed to be a serialized array. This will be changed by the settings // form. db_insert('users') ->fields(array( 'uid' => 1, 'name' => 'placeholder-for-uid-1', 'mail' => 'placeholder-for-uid-1', 'created' => REQUEST_TIME, 'status' => 1, 'data' => serialize(array()), )) ->execute(); // Built-in roles. $rid_anonymous = db_insert('role') ->fields(array('name' => 'anonymous user')) ->execute(); $rid_authenticated = db_insert('role') ->fields(array('name' => 'authenticated user')) ->execute(); // Sanity check to ensure the anonymous and authenticated role IDs are the // same as the drupal defined constants. In certain situations, this will // not be true. if ($rid_anonymous != DRUPAL_ANONYMOUS_RID) { db_update('role') ->fields(array('rid' => DRUPAL_ANONYMOUS_RID)) ->condition('rid', $rid_anonymous) ->execute(); } if ($rid_authenticated != DRUPAL_AUTHENTICATED_RID) { db_update('role') ->fields(array('rid' => DRUPAL_AUTHENTICATED_RID)) ->condition('rid', $rid_authenticated) ->execute(); } variable_set('theme_default', 'garland'); db_update('system') ->fields(array('status' => 1)) ->condition('type', 'theme') ->condition('name', 'garland') ->execute(); db_insert('node_access') ->fields(array( 'nid' => 0, 'gid' => 0, 'realm' => 'all', 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0, )) ->execute(); $cron_key = md5(mt_rand()); variable_set('cron_key', $cron_key); } /** * Implements hook_schema(). */ function system_schema() { // NOTE: {variable} needs to be created before all other tables, as // some database drivers, e.g. Oracle and DB2, will require variable_get() // and variable_set() for overcoming some database specific limitations. $schema['variable'] = array( 'description' => 'Named variable/value pairs created by Drupal core or any other module or theme. All variables are cached in memory at the start of every Drupal request so developers should not be careless about what is stored here.', 'fields' => array( 'name' => array( 'description' => 'The name of the variable.', 'type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => '', ), 'value' => array( 'description' => 'The value of the variable.', 'type' => 'text', 'not null' => TRUE, 'size' => 'big', 'translatable' => TRUE, ), ), 'primary key' => array('name'), ); $schema['actions'] = array( 'description' => 'Stores action information.', 'fields' => array( 'aid' => array( 'description' => 'Primary Key: Unique actions ID.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '0', ), 'type' => array( 'description' => 'The object that that action acts on (node, user, comment, system or custom types.)', 'type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => '', ), 'callback' => array( 'description' => 'The callback function that executes when the action runs.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'parameters' => array( 'description' => 'Parameters to be passed to the callback function.', 'type' => 'text', 'not null' => TRUE, 'size' => 'big', ), 'label' => array( 'description' => 'Label of the action.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '0', ), ), 'primary key' => array('aid'), ); $schema['batch'] = array( 'description' => 'Stores details about batches (processes that run in multiple HTTP requests).', 'fields' => array( 'bid' => array( 'description' => 'Primary Key: Unique batch ID.', 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, ), 'token' => array( 'description' => "A string token generated against the current user's session id and the batch id, used to ensure that only the user who submitted the batch can effectively access it.", 'type' => 'varchar', 'length' => 64, 'not null' => TRUE, ), 'timestamp' => array( 'description' => 'A Unix timestamp indicating when this batch was submitted for processing. Stale batches are purged at cron time.', 'type' => 'int', 'not null' => TRUE, ), 'batch' => array( 'description' => 'A serialized array containing the processing data for the batch.', 'type' => 'text', 'not null' => FALSE, 'size' => 'big', ), ), 'primary key' => array('bid'), 'indexes' => array( 'token' => array('token'), ), ); $schema['blocked_ips'] = array( 'description' => 'Stores blocked IP addresses.', 'fields' => array( 'iid' => array( 'description' => 'Primary Key: unique ID for IP addresses.', 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, ), 'ip' => array( 'description' => 'IP address', 'type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => '', ), ), 'indexes' => array( 'blocked_ip' => array('ip'), ), 'primary key' => array('iid'), ); $schema['cache'] = array( 'description' => 'Generic cache table for caching things not separated out into their own tables. Contributed modules may also use this to store cached items.', 'fields' => array( 'cid' => array( 'description' => 'Primary Key: Unique cache ID.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'data' => array( 'description' => 'A collection of data to cache.', 'type' => 'blob', 'not null' => FALSE, 'size' => 'big', ), 'expire' => array( 'description' => 'A Unix timestamp indicating when the cache entry should expire, or 0 for never.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'created' => array( 'description' => 'A Unix timestamp indicating when the cache entry was created.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'headers' => array( 'description' => 'Any custom HTTP headers to be added to cached data.', 'type' => 'text', 'not null' => FALSE, ), 'serialized' => array( 'description' => 'A flag to indicate whether content is serialized (1) or not (0).', 'type' => 'int', 'size' => 'small', 'not null' => TRUE, 'default' => 0, ), ), 'indexes' => array( 'expire' => array('expire'), ), 'primary key' => array('cid'), ); $schema['cache_bootstrap'] = $schema['cache']; $schema['cache_bootstrap']['description'] = 'Cache table for data required to bootstrap Drupal, may be routed to a shared memory cache.'; $schema['cache_form'] = $schema['cache']; $schema['cache_form']['description'] = 'Cache table for the form system to store recently built forms and their storage data, to be used in subsequent page requests.'; $schema['cache_page'] = $schema['cache']; $schema['cache_page']['description'] = 'Cache table used to store compressed pages for anonymous users, if page caching is enabled.'; $schema['cache_menu'] = $schema['cache']; $schema['cache_menu']['description'] = 'Cache table for the menu system to store router information as well as generated link trees for various menu/page/user combinations.'; $schema['cache_path'] = $schema['cache']; $schema['cache_path']['description'] = 'Cache table for path alias lookup.'; $schema['date_format_type'] = array( 'description' => 'Stores configured date format types.', 'fields' => array( 'type' => array( 'description' => 'The date format type, e.g. medium.', 'type' => 'varchar', 'length' => 64, 'not null' => TRUE, ), 'title' => array( 'description' => 'The human readable name of the format type.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, ), 'locked' => array( 'description' => 'Whether or not this is a system provided format.', 'type' => 'int', 'size' => 'tiny', 'default' => 0, 'not null' => TRUE, ), ), 'primary key' => array('type'), 'indexes' => array( 'title' => array('title'), ), ); // This table's name is plural as some versions of MySQL can't create a // table named 'date_format'. $schema['date_formats'] = array( 'description' => 'Stores configured date formats.', 'fields' => array( 'dfid' => array( 'description' => 'The date format identifier.', 'type' => 'serial', 'not null' => TRUE, 'unsigned' => TRUE, ), 'format' => array( 'description' => 'The date format string.', 'type' => 'varchar', 'length' => 100, 'not null' => TRUE, ), 'type' => array( 'description' => 'The date format type, e.g. medium.', 'type' => 'varchar', 'length' => 64, 'not null' => TRUE, ), 'locked' => array( 'description' => 'Whether or not this format can be modified.', 'type' => 'int', 'size' => 'tiny', 'default' => 0, 'not null' => TRUE, ), ), 'primary key' => array('dfid'), 'unique keys' => array('formats' => array('format', 'type')), ); $schema['date_format_locale'] = array( 'description' => 'Stores configured date formats for each locale.', 'fields' => array( 'format' => array( 'description' => 'The date format string.', 'type' => 'varchar', 'length' => 100, 'not null' => TRUE, ), 'type' => array( 'description' => 'The date format type, e.g. medium.', 'type' => 'varchar', 'length' => 64, 'not null' => TRUE, ), 'language' => array( 'description' => 'A {languages}.language for this format to be used with.', 'type' => 'varchar', 'length' => 12, 'not null' => TRUE, ), ), 'primary key' => array('type', 'language'), ); $schema['file'] = array( 'description' => 'Stores information for uploaded files.', 'fields' => array( 'fid' => array( 'description' => 'File ID.', 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, ), 'uid' => array( 'description' => 'The {users}.uid of the user who is associated with the file.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'filename' => array( 'description' => 'Name of the file with no path components. This may differ from the basename of the filepath if the file is renamed to avoid overwriting an existing file.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'uri' => array( 'description' => 'Path of the file relative to Drupal root.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'filemime' => array( 'description' => "The file's MIME type.", 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'filesize' => array( 'description' => 'The size of the file in bytes.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'status' => array( 'description' => 'A bitmapped field indicating the status of the file. The least significant bit indicates temporary (0) or permanent (1). Temporary files older than DRUPAL_MAXIMUM_TEMP_FILE_AGE will be removed during a cron run.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'timestamp' => array( 'description' => 'UNIX timestamp for when the file was added.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), ), 'indexes' => array( 'uid' => array('uid'), 'status' => array('status'), 'timestamp' => array('timestamp'), ), 'unique keys' => array( 'uri' => array('uri'), ), 'primary key' => array('fid'), 'foreign keys' => array( 'uid' => array('users' => 'uid'), ), ); $schema['flood'] = array( 'description' => 'Flood controls the threshold of events, such as the number of contact attempts.', 'fields' => array( 'fid' => array( 'description' => 'Unique flood event ID.', 'type' => 'serial', 'not null' => TRUE, ), 'event' => array( 'description' => 'Name of event (e.g. contact).', 'type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => '', ), 'identifier' => array( 'description' => 'Identifier of the visitor, such as an IP address or hostname.', 'type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => '', ), 'timestamp' => array( 'description' => 'Timestamp of the event.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'expiration' => array( 'description' => 'Expiration timestamp. Expired events are purged on cron run.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), ), 'primary key' => array('fid'), 'indexes' => array( 'allow' => array('event', 'identifier', 'timestamp'), 'purge' => array('expiration'), ), ); $schema['history'] = array( 'description' => 'A record of which {users} have read which {node}s.', 'fields' => array( 'uid' => array( 'description' => 'The {users}.uid that read the {node} nid.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'nid' => array( 'description' => 'The {node}.nid that was read.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'timestamp' => array( 'description' => 'The Unix timestamp at which the read occurred.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), ), 'primary key' => array('uid', 'nid'), 'indexes' => array( 'nid' => array('nid'), ), ); $schema['menu_router'] = array( 'description' => 'Maps paths to various callbacks (access, page and title)', 'fields' => array( 'path' => array( 'description' => 'Primary Key: the Drupal path this entry describes', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'load_functions' => array( 'description' => 'A serialized array of function names (like node_load) to be called to load an object corresponding to a part of the current path.', 'type' => 'text', 'not null' => TRUE, ), 'to_arg_functions' => array( 'description' => 'A serialized array of function names (like user_uid_optional_to_arg) to be called to replace a part of the router path with another string.', 'type' => 'text', 'not null' => TRUE, ), 'access_callback' => array( 'description' => 'The callback which determines the access to this router path. Defaults to user_access.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'access_arguments' => array( 'description' => 'A serialized array of arguments for the access callback.', 'type' => 'text', 'not null' => FALSE, ), 'page_callback' => array( 'description' => 'The name of the function that renders the page.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'page_arguments' => array( 'description' => 'A serialized array of arguments for the page callback.', 'type' => 'text', 'not null' => FALSE, ), 'delivery_callback' => array( 'description' => 'The name of the function that sends the result of the page_callback function to the browser.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'fit' => array( 'description' => 'A numeric representation of how specific the path is.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'number_parts' => array( 'description' => 'Number of parts in this router path.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small', ), 'context' => array( 'description' => 'Only for local tasks (tabs) - the context of a local task to control its placement.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'tab_parent' => array( 'description' => 'Only for local tasks (tabs) - the router path of the parent page (which may also be a local task).', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'tab_root' => array( 'description' => 'Router path of the closest non-tab parent page. For pages that are not local tasks, this will be the same as the path.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'title' => array( 'description' => 'The title for the current page, or the title for the tab if this is a local task.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'title_callback' => array( 'description' => 'A function which will alter the title. Defaults to t()', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'title_arguments' => array( 'description' => 'A serialized array of arguments for the title callback. If empty, the title will be used as the sole argument for the title callback.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'theme_callback' => array( 'description' => 'A function which returns the name of the theme that will be used to render this page. If left empty, the default theme will be used.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'theme_arguments' => array( 'description' => 'A serialized array of arguments for the theme callback.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'type' => array( 'description' => 'Numeric representation of the type of the menu item, like MENU_LOCAL_TASK.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'block_callback' => array( 'description' => 'Name of a function used to render the block on the system administration page for this item.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'description' => array( 'description' => 'A description of this item.', 'type' => 'text', 'not null' => TRUE, ), 'position' => array( 'description' => 'The position of the block (left or right) on the system administration page for this item.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'weight' => array( 'description' => 'Weight of the element. Lighter weights are higher up, heavier weights go down.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'file' => array( 'description' => 'The file to include for this element, usually the page callback function lives in this file.', 'type' => 'text', 'size' => 'medium' ), ), 'indexes' => array( 'fit' => array('fit'), 'tab_parent' => array(array('tab_parent', 64), 'weight', 'title'), 'tab_root_weight_title' => array(array('tab_root', 64), 'weight', 'title'), ), 'primary key' => array('path'), ); $schema['menu_links'] = array( 'description' => 'Contains the individual links within a menu.', 'fields' => array( 'menu_name' => array( 'description' => "The menu name. All links with the same menu name (such as 'navigation') are part of the same menu.", 'type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => '', ), 'mlid' => array( 'description' => 'The menu link ID (mlid) is the integer primary key.', 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, ), 'plid' => array( 'description' => 'The parent link ID (plid) is the mlid of the link above in the hierarchy, or zero if the link is at the top level in its menu.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'link_path' => array( 'description' => 'The Drupal path or external path this link points to.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'router_path' => array( 'description' => 'For links corresponding to a Drupal path (external = 0), this connects the link to a {menu_router}.path for joins.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'link_title' => array( 'description' => 'The text displayed for the link, which may be modified by a title callback stored in {menu_router}.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', 'translatable' => TRUE, ), 'options' => array( 'description' => 'A serialized array of options to be passed to the url() or l() function, such as a query string or HTML attributes.', 'type' => 'text', 'not null' => FALSE, 'translatable' => TRUE, ), 'module' => array( 'description' => 'The name of the module that generated this link.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => 'system', ), 'hidden' => array( 'description' => 'A flag for whether the link should be rendered in menus. (1 = a disabled menu item that may be shown on admin screens, -1 = a menu callback, 0 = a normal, visible link)', 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small', ), 'external' => array( 'description' => 'A flag to indicate if the link points to a full URL starting with a protocol, like http:// (1 = external, 0 = internal).', 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small', ), 'has_children' => array( 'description' => 'Flag indicating whether any links have this link as a parent (1 = children exist, 0 = no children).', 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small', ), 'expanded' => array( 'description' => 'Flag for whether this link should be rendered as expanded in menus - expanded links always have their child links displayed, instead of only when the link is in the active trail (1 = expanded, 0 = not expanded)', 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small', ), 'weight' => array( 'description' => 'Link weight among links in the same menu at the same depth.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'depth' => array( 'description' => 'The depth relative to the top level. A link with plid == 0 will have depth == 1.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small', ), 'customized' => array( 'description' => 'A flag to indicate that the user has manually created or edited the link (1 = customized, 0 = not customized).', 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small', ), 'p1' => array( 'description' => 'The first mlid in the materialized path. If N = depth, then pN must equal the mlid. If depth > 1 then p(N-1) must equal the plid. All pX where X > depth must equal zero. The columns p1 .. p9 are also called the parents.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'p2' => array( 'description' => 'The second mlid in the materialized path. See p1.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'p3' => array( 'description' => 'The third mlid in the materialized path. See p1.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'p4' => array( 'description' => 'The fourth mlid in the materialized path. See p1.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'p5' => array( 'description' => 'The fifth mlid in the materialized path. See p1.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'p6' => array( 'description' => 'The sixth mlid in the materialized path. See p1.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'p7' => array( 'description' => 'The seventh mlid in the materialized path. See p1.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'p8' => array( 'description' => 'The eighth mlid in the materialized path. See p1.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'p9' => array( 'description' => 'The ninth mlid in the materialized path. See p1.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'updated' => array( 'description' => 'Flag that indicates that this link was generated during the update from Drupal 5.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small', ), ), 'indexes' => array( 'path_menu' => array(array('link_path', 128), 'menu_name'), 'menu_plid_expand_child' => array('menu_name', 'plid', 'expanded', 'has_children'), 'menu_parents' => array('menu_name', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8', 'p9'), 'router_path' => array(array('router_path', 128)), ), 'primary key' => array('mlid'), ); $schema['queue'] = array( 'description' => 'Stores items in queues.', 'fields' => array( 'item_id' => array( 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, 'description' => 'Primary Key: Unique item ID.', ), 'name' => array( 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', 'description' => 'The queue name.', ), 'data' => array( 'type' => 'text', 'not null' => FALSE, 'size' => 'big', 'serialize' => TRUE, 'description' => 'The arbitrary data for the item.', ), 'expire' => array( 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'description' => 'Timestamp when the claim lease expires on the item.', ), 'created' => array( 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'description' => 'Timestamp when the item was created.', ), ), 'primary key' => array('item_id'), 'indexes' => array( 'name_created' => array('name', 'created'), 'expire' => array('expire'), ), ); $schema['registry'] = array( 'description' => "Each record is a function, class, or interface name and the file it is in.", 'fields' => array( 'name' => array( 'description' => 'The name of the function, class, or interface.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'type' => array( 'description' => 'Either function or class or interface.', 'type' => 'varchar', 'length' => 9, 'not null' => TRUE, 'default' => '', ), 'filename' => array( 'description' => 'Name of the file.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, ), 'module' => array( 'description' => 'Name of the module the file belongs to.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '' ), 'weight' => array( 'description' => "The order in which this module's hooks should be invoked relative to other modules. Equal-weighted modules are ordered by name.", 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), ), 'primary key' => array('name', 'type'), 'indexes' => array( 'hook' => array('type', 'weight', 'module'), ), ); $schema['registry_file'] = array( 'description' => "Files parsed to build the registry.", 'fields' => array( 'filename' => array( 'description' => 'Path to the file.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, ), 'filectime' => array( 'description' => "The creation time of the file when last parsed.", 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'filemtime' => array( 'description' => "The modification time of the file when last parsed.", 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), ), 'primary key' => array('filename'), ); $schema['semaphore'] = array( 'description' => 'Table for holding semaphores, locks, flags, etc. that cannot be stored as Drupal variables since they must not be cached.', 'fields' => array( 'name' => array( 'description' => 'Primary Key: Unique name.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '' ), 'value' => array( 'description' => 'A value for the semaphore.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '' ), 'expire' => array( 'description' => 'A Unix timestamp with microseconds indicating when the semaphore should expire.', 'type' => 'float', 'size' => 'big', 'not null' => TRUE ), ), 'indexes' => array('value' => array('value')), 'primary key' => array('name'), ); $schema['sequences'] = array( 'description' => 'Stores IDs.', 'fields' => array( 'value' => array( 'description' => 'The value of the sequence.', 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, ), ), 'primary key' => array('value'), ); $schema['sessions'] = array( 'description' => "Drupal's session handlers read and write into the sessions table. Each record represents a user session, either anonymous or authenticated.", 'fields' => array( 'uid' => array( 'description' => 'The {users}.uid corresponding to a session, or 0 for anonymous user.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, ), 'sid' => array( 'description' => "Primary key: A session ID. The value is generated by PHP's Session API.", 'type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => '', ), 'ssid' => array( 'description' => "Unique key: Secure session ID. The value is generated by PHP's Session API.", 'type' => 'varchar', 'length' => 64, 'not null' => FALSE, 'default' => NULL, ), 'hostname' => array( 'description' => 'The IP address that last used this session ID (sid).', 'type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => '', ), 'timestamp' => array( 'description' => 'The Unix timestamp when this session last requested a page. Old records are purged by PHP automatically.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'cache' => array( 'description' => "The time of this user's last post. This is used when the site has specified a minimum_cache_lifetime. See cache_get().", 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'session' => array( 'description' => 'The serialized contents of $_SESSION, an array of name/value pairs that persists across page requests by this session ID. Drupal loads $_SESSION from here at the start of each request and saves it at the end.', 'type' => 'text', 'not null' => FALSE, 'size' => 'big', ), ), 'primary key' => array('sid'), 'indexes' => array( 'timestamp' => array('timestamp'), 'uid' => array('uid'), ), 'unique keys' => array( 'ssid' => array('ssid'), ), 'foreign keys' => array( 'uid' => array('users' => 'uid'), ), ); $schema['system'] = array( 'description' => "A list of all modules, themes, and theme engines that are or have been installed in Drupal's file system.", 'fields' => array( 'filename' => array( 'description' => 'The path of the primary file for this item, relative to the Drupal root; e.g. modules/node/node.module.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'name' => array( 'description' => 'The name of the item; e.g. node.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'type' => array( 'description' => 'The type of the item, either module, theme, or theme_engine.', 'type' => 'varchar', 'length' => 12, 'not null' => TRUE, 'default' => '', ), 'owner' => array( 'description' => "A theme's 'parent' . Can be either a theme or an engine.", 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'status' => array( 'description' => 'Boolean indicating whether or not this item is enabled.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'bootstrap' => array( 'description' => "Boolean indicating whether this module is loaded during Drupal's early bootstrapping phase (e.g. even before the page cache is consulted).", 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'schema_version' => array( 'description' => "The module's database schema version number. -1 if the module is not installed (its tables do not exist); 0 or the largest N of the module's hook_update_N() function that has either been run or existed when the module was first installed.", 'type' => 'int', 'not null' => TRUE, 'default' => -1, 'size' => 'small', ), 'weight' => array( 'description' => "The order in which this module's hooks should be invoked relative to other modules. Equal-weighted modules are ordered by name.", 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'info' => array( 'description' => "A serialized array containing information from the module's .info file; keys can include name, description, package, version, core, dependencies, dependents, and php.", 'type' => 'text', 'not null' => FALSE, ), ), 'primary key' => array('filename'), 'indexes' => array( 'bootstrap' => array('status', 'bootstrap', 'type', 'weight', 'name'), 'system_list' => array('weight', 'name'), 'type_name' => array('type', 'name'), ), ); $schema['url_alias'] = array( 'description' => 'A list of URL aliases for Drupal paths; a user may visit either the source or destination path.', 'fields' => array( 'pid' => array( 'description' => 'A unique path alias identifier.', 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, ), 'source' => array( 'description' => 'The Drupal path this alias is for; e.g. node/12.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'alias' => array( 'description' => 'The alias for this path; e.g. title-of-the-story.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'language' => array( 'description' => 'The language this alias is for; if blank, the alias will be used for unknown languages. Each Drupal path can have an alias for each supported language.', 'type' => 'varchar', 'length' => 12, 'not null' => TRUE, 'default' => '', ), ), 'unique keys' => array( 'alias_language_pid' => array('alias', 'language', 'pid'), ), 'primary key' => array('pid'), 'indexes' => array( 'source_language_pid' => array('source', 'language', 'pid'), ), ); return $schema; } // Updates for core. function system_update_last_removed() { return 6047; } /** * @defgroup updates-6.x-extra Extra system updates for 6.x * @{ */ /** * Increase the size of the 'load_functions' and 'to_arg_functions' fields in table 'menu_router'. */ function system_update_6048() { db_change_field('menu_router', 'load_functions', 'load_functions', array('type' => 'text', 'not null' => TRUE,)); db_change_field('menu_router', 'to_arg_functions', 'to_arg_functions', array('type' => 'text', 'not null' => TRUE,)); } /** * Replace src index on the {url_alias} table with src, language. */ function system_update_6049() { db_drop_index('url_alias', 'src'); db_add_index('url_alias', 'src_language', array('src', 'language')); } /** * Clear any menu router blobs stored in the cache table. */ function system_update_6050() { cache_clear_all('router:', 'cache_menu', TRUE); } /** * Create a signature_format column. */ function system_update_6051() { if (!db_column_exists('users', 'signature_format')) { // Set future input formats to FILTER_FORMAT_DEFAULT to ensure a safe default // when incompatible modules insert into the users table. An actual format // will be assigned when users save their signature. $schema = array( 'type' => 'int', 'size' => 'small', 'not null' => TRUE, 'default' => FILTER_FORMAT_DEFAULT, 'description' => 'The {filter_formats}.format of the signature.', ); db_add_field($ret, 'users', 'signature_format', $schema); // Set the format of existing signatures to the current default input format. if ($current_default_filter = variable_get('filter_default_format', 0)) { db_update('users') ->fields(array( 'signature_format' => $current_default_filter, )) ->execute(); } drupal_set_message("User signatures no longer inherit comment input formats. Each user's signature now has its own associated format that can be selected on the user's account page. Existing signatures have been set to your site's default input format."); } return $ret; } /** * Add a missing index on the {menu_router} table. */ function system_update_6052() { $ret = array(); db_add_index($ret, 'menu_router', 'tab_root_weight_title', array(array('tab_root', 64), 'weight', 'title')); return $ret; } /** * Add a {system} index on type and name. */ function system_update_6053() { $ret = array(); db_add_index($ret, 'system', 'type_name', array(array('type', 12), 'name')); return $ret; } /** * @} End of "defgroup updates-6.x-extra" * The next series of updates should start at 7000. */ /** * @defgroup updates-6.x-to-7.x System updates from 6.x to 7.x * @{ */ /** * Rename blog and forum permissions to be consistent with other content types. */ function system_update_7000() { $result = db_query("SELECT rid, perm FROM {permission} ORDER BY rid"); foreach ($result as $role) { $renamed_permission = preg_replace('/(?<=^|,\ )create\ blog\ entries(?=,|$)/', 'create blog content', $role->perm); $renamed_permission = preg_replace('/(?<=^|,\ )edit\ own\ blog\ entries(?=,|$)/', 'edit own blog content', $role->perm); $renamed_permission = preg_replace('/(?<=^|,\ )edit\ any\ blog\ entry(?=,|$)/', 'edit any blog content', $role->perm); $renamed_permission = preg_replace('/(?<=^|,\ )delete\ own\ blog\ entries(?=,|$)/', 'delete own blog content', $role->perm); $renamed_permission = preg_replace('/(?<=^|,\ )delete\ any\ blog\ entry(?=,|$)/', 'delete any blog content', $role->perm); $renamed_permission = preg_replace('/(?<=^|,\ )create\ forum\ topics(?=,|$)/', 'create forum content', $role->perm); $renamed_permission = preg_replace('/(?<=^|,\ )delete\ any\ forum\ topic(?=,|$)/', 'delete any forum content', $role->perm); $renamed_permission = preg_replace('/(?<=^|,\ )delete\ own\ forum\ topics(?=,|$)/', 'delete own forum content', $role->perm); $renamed_permission = preg_replace('/(?<=^|,\ )edit\ any\ forum\ topic(?=,|$)/', 'edit any forum content', $role->perm); $renamed_permission = preg_replace('/(?<=^|,\ )edit\ own\ forum\ topics(?=,|$)/', 'edit own forum content', $role->perm); if ($renamed_permission != $role->perm) { db_update('permission') ->fields(array('perm' => $renamed_permission)) ->condition('rid', $role->rid) ->execute(); } } } /** * Generate a cron key and save it in the variables table. */ function system_update_7001() { variable_set('cron_key', md5(mt_rand())); } /** * Add a table to store blocked IP addresses. */ function system_update_7002() { $schema['blocked_ips'] = array( 'description' => 'Stores blocked IP addresses.', 'fields' => array( 'iid' => array( 'description' => 'Primary Key: unique ID for IP addresses.', 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, ), 'ip' => array( 'description' => 'IP address', 'type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => '', ), ), 'indexes' => array( 'blocked_ip' => array('ip'), ), 'primary key' => array('iid'), ); db_create_table('blocked_ips', $schema['blocked_ips']); } /** * Update {blocked_ips} with valid IP addresses from {access}. */ function system_update_7003() { $messages = array(); $type = 'host'; $result = db_query("SELECT mask FROM {access} WHERE status = :status AND type = :type", array( ':status' => 0, ':type' => $type, )); foreach ($result as $blocked) { if (filter_var($blocked->mask, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) !== FALSE) { db_insert('blocked_ips') ->fields(array('ip' => $blocked->mask)) ->execute(); } else { $invalid_host = check_plain($blocked->mask); $messages[] = t('The host !host is no longer blocked because it is not a valid IP address.', array('!host' => $invalid_host )); } } if (isset($invalid_host)) { drupal_set_message('Drupal no longer supports wildcard IP address blocking. Visitors whose IP addresses match ranges you have previously set using access rules will no longer be blocked from your site when you put the site online. See the IP address and referrer blocking Handbook page for alternative methods.', 'warning'); } // Make sure not to block any IP addresses that were specifically allowed by access rules. if (!empty($result)) { $result = db_query("SELECT mask FROM {access} WHERE status = :status AND type = :type", array( ':status' => 1, ':type' => $type, )); $or = db_condition('or'); foreach ($result as $allowed) { $or->where('LOWER(ip) LIKE LOWER(:mask)', array(':mask' => $allowed->mask)); } if (count($or)) { db_delete('blocked_ips') ->condition($or) ->execute(); } } } /** * Remove hardcoded numeric deltas from all blocks in core. */ function system_update_7004(&$sandbox) { // Get an array of the renamed block deltas, organized by module. $renamed_deltas = array( 'blog' => array('0' => 'recent'), 'book' => array('0' => 'navigation'), 'comment' => array('0' => 'recent'), 'forum' => array( '0' => 'active', '1' => 'new', ), 'locale' => array('0' => 'language-switcher'), 'node' => array('0' => 'syndicate'), 'poll' => array('0' => 'recent'), 'profile' => array('0' => 'author-information'), 'search' => array('0' => 'form'), 'statistics' => array('0' => 'popular'), 'system' => array('0' => 'powered-by'), 'user' => array( '0' => 'login', '1' => 'navigation', '2' => 'new', '3' => 'online', ), ); // Loop through each block and make changes to the core block tables. // Only run this the first time through the batch update. if (!isset($sandbox['progress'])) { $block_tables = array('blocks', 'blocks_roles'); foreach ($block_tables as $table) { foreach ($renamed_deltas as $module => $deltas) { foreach ($deltas as $old_delta => $new_delta) { // Only do the update if the old block actually exists. $block_exists = db_query("SELECT COUNT(*) FROM {" . $table . "} WHERE module = :module AND delta = :delta", array( ':module' => $module, ':delta' => $old_delta, )) ->fetchField(); if ($block_exists) { db_update($table) ->fields(array('delta' => $new_delta)) ->condition('module', $module) ->condition('delta', $old_delta) ->execute(); } } } } // Rename forum module's block variables. $forum_block_num_0 = variable_get('forum_block_num_0'); if (isset($forum_block_num_0)) { variable_set('forum_block_num_active', $forum_block_num_0); variable_del('forum_block_num_0'); } $forum_block_num_1 = variable_get('forum_block_num_1'); if (isset($forum_block_num_1)) { variable_set('forum_block_num_new', $forum_block_num_1); variable_del('forum_block_num_1'); } // Initialize batch update information. $sandbox['progress'] = 0; $sandbox['last_user_processed'] = -1; $sandbox['max'] = db_query("SELECT COUNT(*) FROM {users} WHERE data IS NOT NULL")->fetchField(); } // Now do the batch update of the user-specific block visibility settings. $limit = 100; $result = db_select('users', 'u') ->fields('u', array('uid', 'data')) ->condition('uid', $sandbox['last_user_processed'], '>') ->where('data IS NOT NULL') ->range(0, $limit) ->execute(); foreach ($result as $row) { $data = unserialize($row->data); $user_needs_update = FALSE; foreach ($renamed_deltas as $module => $deltas) { foreach ($deltas as $old_delta => $new_delta) { if (isset($data['block'][$module][$old_delta])) { // Transfer the old block visibility settings to the newly-renamed // block, and mark this user for a database update. $data['block'][$module][$new_delta] = $data['block'][$module][$old_delta]; unset($data['block'][$module][$old_delta]); $user_needs_update = TRUE; } } } // Update the current user. if ($user_needs_update) { db_update('users') ->fields(array('data' => serialize($data))) ->condition('uid', $row->uid) ->execute(); } // Update our progress information for the batch update. $sandbox['progress']++; $sandbox['last_user_processed'] = $row->uid; } // Indicate our current progress to the batch update system. if ($sandbox['progress'] < $sandbox['max']) { $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max']; } } /** * Remove throttle columns and variables. */ function system_update_7005() { db_drop_field('blocks', 'throttle'); db_drop_field('system', 'throttle'); variable_del('throttle_user'); variable_del('throttle_anonymous'); variable_del('throttle_level'); variable_del('throttle_probability_limiter'); } /** * Registry tables and drop the file key of the menu router, since it is no * longer needed. */ function system_update_7006() { $schema['registry'] = array( 'fields' => array( 'name' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), 'type' => array('type' => 'varchar', 'length' => 9, 'not null' => TRUE, 'default' => ''), 'filename' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), 'module' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), 'weight' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), ), 'primary key' => array('name', 'type'), 'indexes' => array( 'hook' => array('type', 'weight', 'module'), ), ); $schema['registry_file'] = array( 'fields' => array( 'filename' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE), 'filectime' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), 'filemtime' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), ), 'primary key' => array('filename'), ); db_create_table('registry', $schema['registry']); db_create_table('registry_file', $schema['registry_file']); registry_rebuild(); } /** * Convert to new method of storing permissions. * * This update is in system.install rather than user.install so that * all modules can use the updated permission scheme during their updates. */ function system_update_7007() { // Copy the permissions from the old {permission} table to the new {role_permission} table. $messages = array(); $result = db_query("SELECT rid, perm FROM {permission} ORDER BY rid ASC"); $query = db_insert('role_permission')->fields(array('rid', 'permission')); foreach ($result as $role) { foreach (explode(', ', $role->perm) as $perm) { $query->values(array( 'rid' => $role->rid, 'permission' => $perm, )); } $messages[] = t('Inserted into {role_permission} the permissions for role ID !id', array('!id' => $role->rid)); } $query->execute(); db_drop_table('permission'); return implode(', ', $messages); } /** * Use the poll_choice primary key to record votes in poll_votes rather than * the choice order. Rename chorder to weight. */ function system_update_7008() { if (db_table_exists('poll_votes')) { // Add chid column and convert existing votes. db_add_field('poll_votes', 'chid', array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0)); db_add_index('poll_votes', 'chid', array('chid')); db_query("UPDATE {poll_votes} SET chid = (SELECT chid FROM {poll_choices} c WHERE {poll_votes}.chorder = c.chorder AND {poll_votes}.nid = c.nid)"); // Remove old chorder column. db_drop_field('poll_votes', 'chorder'); } if (db_table_exists('poll_choices')) { // Change the chorder column to weight in poll_choices. db_change_field('poll_choices', 'chorder', 'weight', array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny')); } } /** * Rename the variables for primary and secondary links. * */ function system_update_7009() { db_update('variable') ->fields(array('name' => 'main_menu_links_source')) ->condition('name', 'menu_primary_links_source') ->execute(); } /** * Moved to system_update_6048(). */ function system_update_7010() { return ''; } /** * Split the 'bypass node access' permission from 'administer nodes'. */ function system_update_7011() { // Get existing roles that can 'administer nodes'. $rids = array(); $rids = db_query("SELECT rid FROM {role_permission} WHERE permission = :perm", array(':perm' => 'administer nodes'))->fetchCol(); // None found. if (empty($rids)) { return; } $insert = db_insert('role_permission')->fields(array('rid', 'permission')); foreach ($rids as $rid) { $insert->values(array( 'rid' => $rid, 'permission' => 'bypass node access', )); } $insert->execute(); } /** * Rename {blocks} table to {block}, {blocks_roles} to {block_role} and * {boxes} to {box}. */ function system_update_7012() { db_rename_table('blocks', 'block'); db_rename_table('blocks_roles', 'block_role'); db_rename_table('boxes', 'box'); } /** * Convert default time zone offset to default time zone name. */ function system_update_7013() { $timezone = NULL; $timezones = system_time_zones(); // If the contributed Date module set a default time zone name, use this // setting as the default time zone. if (($timezone_name = variable_get('date_default_timezone_name')) && isset($timezones[$timezone_name])) { $timezone = $timezone_name; } // If the contributed Event module has set a default site time zone, look up // the time zone name and use it as the default time zone. if (!$timezone && ($timezone_id = variable_get('date_default_timezone_id', 0))) { try { $timezone_name = db_query('SELECT name FROM {event_timezones} WHERE timezone = :timezone_id', array(':timezone_id' => $timezone_id))->fetchField(); if (($timezone_name = str_replace(' ', '_', $timezone_name)) && isset($timezones[$timezone_name])) { $timezone = $timezone_name; } } catch (PDOException $e) { // Ignore error if event_timezones table does not exist or unexpected // schema found. } } // If the previous default time zone was a non-zero offset, guess the site's // intended time zone based on that offset and the server's daylight saving // time status. if (!$timezone && ($offset = variable_get('date_default_timezone', 0)) && ($timezone_name = timezone_name_from_abbr('', intval($offset), date('I'))) && isset($timezones[$timezone_name])) { $timezone = $timezone_name; } // Otherwise, the default time zone offset was zero, which is UTC. if (!$timezone) { $timezone = 'UTC'; } variable_set('date_default_timezone', $timezone); drupal_set_message('The default time zone has been set to ' . check_plain($timezone) . '. Please check the ' . l('date and time configuration page', 'admin/config/regional/settings') . ' to configure it correctly.', 'warning'); } /** * Drop the bootstrap column from the {system} table. This was reverted. */ function system_update_7014() { } /** * Change the user logout path. */ function system_update_7015() { db_update('menu_links') ->fields(array('link_path' => 'user/logout')) ->condition('link_path', 'logout') ->execute(); db_update('menu_links') ->fields(array('router_path' => 'user/logout')) ->condition('router_path', 'logout') ->execute(); } /** * Remove custom datatype *_unsigned in PostgreSQL. */ function system_update_7016() { // Only run these queries if the driver used is pgsql. if (db_driver() == 'pgsql') { $result = db_query("SELECT c.relname AS table, a.attname AS field, pg_catalog.format_type(a.atttypid, a.atttypmod) AS type FROM pg_catalog.pg_attribute a LEFT JOIN pg_class c ON (c.oid = a.attrelid) WHERE pg_catalog.pg_table_is_visible(c.oid) AND c.relkind = 'r' AND pg_catalog.format_type(a.atttypid, a.atttypmod) LIKE '%unsigned%'"); foreach ($result as $row) { switch ($row->type) { case 'smallint_unsigned': $datatype = 'int'; break; case 'int_unsigned': case 'bigint_unsigned': default: $datatype = 'bigint'; break; } db_query('ALTER TABLE ' . $row->table . ' ALTER COLUMN ' . $row->field . ' TYPE ' . $datatype); db_query('ALTER TABLE ' . $row->table . ' ADD CHECK (' . $row->field . ' >= 0)'); } db_query('DROP DOMAIN smallint_unsigned'); db_query('DROP DOMAIN int_unsigned'); db_query('DROP DOMAIN bigint_unsigned'); } } /** * Change the theme setting 'toggle_node_info' into a per content type variable. */ function system_update_7017() { $types = node_type_get_types(); if (count($types)) { foreach ($types as $type) { $node_info = theme_get_setting('toggle_node_info_' . $type->type); if ($node_info !== NULL) { variable_set('node_submitted_' . $type->type, $node_info); } } } // Unset deprecated 'toggle_node_info' theme settings. $theme_settings = variable_get('theme_settings', array()); foreach ($theme_settings as $setting => $value) { if (substr($setting, 0, 16) == 'toggle_node_info') { unset($theme_settings[$setting]); } } variable_set('theme_settings', $theme_settings); } /** * Shorten the {system}.type column and modify indexes. */ function system_update_7018() { db_drop_index('system', 'modules'); db_drop_index('system', 'type_name'); db_change_field('system', 'type', 'type', array('type' => 'varchar', 'length' => 12, 'not null' => TRUE, 'default' => '')); db_add_index('system', 'type_name', array('type', 'name')); db_add_index('system', 'system_list', array('weight', 'name')); } /** * Enable field module. */ function system_update_7020() { $module_list = array('field_sql_storage', 'field'); drupal_install_modules($module_list); module_enable($module_list); } /** * Add new blocks to new regions, migrate custom variables to blocks. */ function system_update_7021() { // Collect a list of themes with blocks. $themes_with_blocks = array(); $result = db_query("SELECT s.name FROM {system} s INNER JOIN {block} b ON s.name = b.theme WHERE s.type = 'theme' GROUP by s.name"); $insert = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'pages', 'cache')); foreach ($result as $theme) { $themes_with_blocks[] = $theme->name; // Add new system generated help block. $insert->values(array( 'module' => 'system', 'delta' => 'help', 'theme' => $theme->name, 'status' => 1, 'weight' => 0, 'region' => 'help', 'pages' => '', 'cache' => 1, )); // Add new system generated main page content block. $insert->values(array( 'module' => 'system', 'delta' => 'main', 'theme' => $theme->name, 'status' => 1, 'weight' => 0, 'region' => 'content', 'pages' => '', 'cache' => -1, )); } $insert->execute(); // Migrate blocks from left/right regions to first/second regions. db_update('block') ->fields(array('region' => 'sidebar_first')) ->condition('region', 'left') ->execute(); db_update('block') ->fields(array('region' => 'sidebar_second')) ->condition('region', 'right') ->execute(); // Migrate contact form information. $default_format = variable_get('filter_default_format', 1); if ($contact_help = variable_get('contact_form_information', '')) { $bid = db_insert('box') ->fields(array( 'body' => $contact_help, 'info' => 'Contact page help', 'format' => $default_format, )) ->execute(); $insert = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'visibility', 'pages', 'cache')); foreach ($themes_with_blocks as $theme) { // Add contact help block for themes, which had blocks. $insert->values(array( 'module' => 'block', 'delta' => $bid, 'theme' => $theme, 'status' => 1, 'weight' => 5, 'region' => 'help', 'visibility' => 1, 'pages' => 'contact', 'cache' => -1, )); } drupal_set_message('The contact form information setting was migrated to a custom block and set up to only show on the site-wide contact page. The block was set to use the default text format, which might differ from the HTML based format used before. Please check the block and ensure that the output is right.'); } $insert->execute(); // Migrate user help setting. if ($user_help = variable_get('user_registration_help', '')) { $bid = db_insert('box')->fields(array('body' => $user_help, 'info' => 'User registration guidelines', 'format' => $default_format))->execute(); $insert = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'visibility', 'pages', 'cache')); foreach ($themes_with_blocks as $theme) { // Add user registration help block for themes, which had blocks. $insert->values(array( 'module' => 'block', 'delta' => $bid, 'theme' => $theme, 'status' => 1, 'weight' => 5, 'region' => 'help', 'visibility' => 1, 'pages' => 'user/register', 'cache' => -1, )); } drupal_set_message('The user registration guidelines were migrated to a custom block and set up to only show on the user registration page. The block was set to use the default text format, which might differ from the HTML based format used before. Please check the block and ensure that the output is right.'); $insert->execute(); } // Migrate site mission setting. if ($mission = variable_get('site_mission')) { $bid = db_insert('box')->fields(array('body' => $mission, 'info' => 'Site mission', 'format' => $default_format))->execute(); $insert = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'visibility', 'pages', 'cache')); foreach ($themes_with_blocks as $theme) { // Add mission block for themes, which had blocks. $insert->values(array( 'module' => 'block', 'delta' => $bid, 'theme' => $theme, 'status' => 1, 'weight' => 0, 'region' => 'highlight', 'visibility' => 1, 'pages' => '', 'cache' => -1, )); } drupal_set_message('The site mission was migrated to a custom block and set up to only show on the front page in the highlighted content region. The block was set to use the default text format, which might differ from the HTML based format used before. Please check the block and ensure that the output is right. If your theme does not have a highlighted content region, you might need to relocate the block.'); $insert->execute(); // Migrate mission to RSS site description. variable_set('feed_description', $mission); } // Migrate site footer message to a custom block. if ($footer_message = variable_get('site_footer', '')) { $bid = db_insert('box')->fields(array('body' => $footer_message, 'info' => 'Footer message', 'format' => $default_format))->execute(); $insert = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'pages', 'cache')); foreach ($themes_with_blocks as $theme) { // Add site footer block for themes, which had blocks. // Set low weight, so the block comes early (it used to be // before the other blocks). $insert->values(array( 'module' => 'block', 'delta' => $bid, 'theme' => $theme, 'status' => 1, 'weight' => -10, 'region' => 'footer', 'pages' => '', 'cache' => -1, )); } drupal_set_message('The footer message was migrated to a custom block and set up to appear in the footer. The block was set to use the default text format, which might differ from the HTML based format used before. Please check the block and ensure that the output is right. If your theme does not have a footer region, you might need to relocate the block.'); $insert->execute(); } // Remove the variables (even if they were saved empty on the admin interface), // to avoid keeping clutter in the variables table. variable_del('contact_form_information'); variable_del('user_registration_help'); variable_del('site_mission'); variable_del('site_footer'); // Rebuild theme data, so the new 'help' region is identified. system_rebuild_theme_data(); } /** * Add the queue tables. */ function system_update_7022() { $schema['queue'] = array( 'description' => 'Stores items in queues.', 'fields' => array( 'item_id' => array( 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, 'description' => 'Primary Key: Unique item ID.', ), 'name' => array( 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', 'description' => 'The queue name.', ), 'data' => array( 'type' => 'text', 'not null' => FALSE, 'size' => 'big', 'serialize' => TRUE, 'description' => 'The arbitrary data for the item.', ), 'expire' => array( 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'description' => 'Timestamp when the claim lease expires on the item.', ), 'created' => array( 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'description' => 'Timestamp when the item was created.', ), ), 'primary key' => array('item_id'), 'indexes' => array( 'name_created' => array('name', 'created'), 'expire' => array('expire'), ), ); db_create_table('queue', $schema['queue']); } /** * Change the PHP for settings permission. */ function system_update_7023() { db_update('role_permission') ->fields(array('permission' => 'use PHP for settings')) ->condition('permission', 'use PHP for block visibility') ->execute(); } /** * Add the substr_index() function to PostgreSQL. * * Note: this should go into the driver itself, but we have no support * for driver-specific updates yet. */ function system_update_7024() { if (db_driver() == 'pgsql') { db_query('CREATE OR REPLACE FUNCTION "substring_index"(text, text, integer) RETURNS text AS \'SELECT array_to_string((string_to_array($1, $2)) [1:$3], $2);\' LANGUAGE \'sql\'' ); } } /** * Improve indexes on the {url_alias} table. */ function system_update_7025() { db_drop_index('url_alias', 'src_language'); db_drop_index('url_alias', 'dst_language'); db_add_index('url_alias', 'dst_language_pid', array('dst', 'language', 'pid')); db_add_index('url_alias', 'src_language_pid', array('src', 'language', 'pid')); } /** * Increase permitted length of url aliases to 255 characters. * */ function system_update_7026() { db_change_field('url_alias', 'src', 'src', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE)); db_change_field('url_alias', 'dst', 'dst', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE)); } /** * Enable field type modules. */ function system_update_7027() { $module_list = array('text', 'number', 'list', 'options'); db_delete('system') ->condition('type', 'module') ->condition('name', $module_list) ->execute(); drupal_install_modules($module_list); module_enable($module_list); } /** * Rename taxonomy tables. */ function system_update_7028() { db_rename_table('term_data', 'taxonomy_term_data'); db_rename_table('term_hierarchy', 'taxonomy_term_hierarchy'); db_rename_table('term_node', 'taxonomy_term_node'); db_rename_table('term_relation', 'taxonomy_term_relation'); db_rename_table('term_synonym', 'taxonomy_term_synonym'); db_rename_table('vocabulary', 'taxonomy_vocabulary'); db_rename_table('vocabulary_node_types', 'taxonomy_vocabulary_node_type'); } /** * Add new 'view own unpublished content' permission for authenticated users. * Preserves legacy behavior from Drupal 6.x. */ function system_update_7029() { db_insert('role_permission') ->fields(array( 'rid' => DRUPAL_AUTHENTICATED_RID, 'permission' => 'view own unpublished content', )) ->execute(); } /** * Moved to comment_update_7011(). */ function system_update_7030() { } /** * Removed in favour of Drupal 6 backport. * @see system_update_6052() */ function system_update_7031() { } /** * Alter field hostname to identifier in the {flood} table. */ function system_update_7032() { db_drop_index('flood', 'allow'); db_change_field('flood', 'hostname', 'identifier', array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => '')); db_add_index('flood', 'allow', array('event', 'identifier', 'timestamp')); } /** * Move CACHE_AGGRESSIVE to CACHE_NORMAL. */ function system_update_7033() { if (variable_get('cache') == 2) { variable_set('cache', CACHE_NORMAL); return t('Aggressive caching was disabled and replaced with normal caching, please read the page caching section in default.settings.php for more information on how to enable similar functionality.'); } } /** * Migrate the file_downloads setting and create the new {file} table. */ function system_update_7034() { $files_directory = variable_get('file_directory_path', NULL); if (variable_get('file_downloads', 1) == 1) { // Our default is public, so we don't need to set anything. if (!empty($files_directory)) { variable_set('file_public_path', $files_directory); } } elseif (variable_get('file_downloads', 1) == 2) { variable_set('file_default_scheme', 'private'); if (!empty($files_directory)) { variable_set('file_private_path', $files_directory); } } variable_del('file_downloads'); $schema['file'] = array( 'description' => 'Stores information for uploaded files.', 'fields' => array( 'fid' => array( 'description' => 'File ID.', 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, ), 'uid' => array( 'description' => 'The {user}.uid of the user who is associated with the file.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'filename' => array( 'description' => 'Name of the file with no path components. This may differ from the basename of the filepath if the file is renamed to avoid overwriting an existing file.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'uri' => array( 'description' => 'URI of file.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'filemime' => array( 'description' => "The file's MIME type.", 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), 'filesize' => array( 'description' => 'The size of the file in bytes.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'status' => array( 'description' => 'A bitmapped field indicating the status of the file the least sigifigant bit indicates temporary (1) or permanent (0). Temporary files older than DRUPAL_MAXIMUM_TEMP_FILE_AGE will be removed during a cron run.', 'type' => 'int', 'not null' => TRUE, 'default' => 0, ), 'timestamp' => array( 'description' => 'UNIX timestamp for when the file was added.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), ), 'indexes' => array( 'uid' => array('uid'), 'status' => array('status'), 'timestamp' => array('timestamp'), ), 'unique keys' => array( 'uri' => array('uri'), ), 'primary key' => array('fid'), ); db_create_table('file', $schema['file']); } /** * Migrate upload module files to the new {file} table. */ function system_update_7035() { if (!db_table_exists('upload')) { return; } // The old {files} tables still exists. We migrate core data from upload // module, but any contrib module using it will need to do its own update. $result = db_query('SELECT fid, uid, filename, filepath AS uri, filemime, filesize, status, timestamp FROM {files} f INNER JOIN {upload} u ON u.fid = f.fid', array(), array('fetch' => PDO::FETCH_ASSOC)); // We will convert filepaths to uri using the default schmeme // and stripping off the existing file directory path. $basename = variable_get('file_directory_path', conf_path() . '/files'); $scheme = variable_get('file_default_scheme', 'public') . '://'; $fids = array(); // TODO: does this function need to run in batch mode, or should we use a multi-insert? foreach ($result as $file) { $file['uri'] = $scheme . str_replace($basename, '', $file['uri']); $file['uri'] = file_stream_wrapper_uri_normalize($file['uri']); db_insert('file')->fields($file)->execute(); $fids[] = $file['fid']; } // TODO: delete the found fids from {files}? } /** * Split the 'access site in maintenance mode' permission from 'administer site configuration'. */ function system_update_7036() { // Get existing roles that can 'administer site configuration'. $rids = db_query("SELECT rid FROM {role_permission} WHERE permission = :perm", array(':perm' => 'administer site configuration'))->fetchCol(); // None found. if (empty($rids)) { return; } $insert = db_insert('role_permission')->fields(array('rid', 'permission')); foreach ($rids as $rid) { $insert->values(array( 'rid' => $rid, 'permission' => 'access site in maintenance mode', )); } $insert->execute(); // Remove obsolete variable 'site_offline_message'. // @see update_fix_d7_requirements(). variable_del('site_offline_message'); } /** * Rename {box} table to {block_custom}. */ function system_update_7037() { db_rename_table('box', 'block_custom'); } /** * Rename action description to label. */ function system_update_7038() { db_change_field('actions', 'description', 'label', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '0')); } /** * Adds fields to the {menu_router} table to allow custom themes to be set per * page. */ function system_update_7039() { // Moved to update_fix_d7_requirements(). } /** * Create new date format tables. */ function system_update_7040() { // Moved to update_fix_d7_requirements(). } /** * Adds 'delivery_callback' field to the {menu_router} table to allow a custom * function to be used for final page rendering and sending to browser. */ function system_update_7041() { // Moved to update_fix_d7_requirements(). } /** * Rename dst and src to source and alias. */ function system_update_7042() { // update_fix_d7_requirements() adds 'fake' source and alias columns to // allow bootstrap to run without fatal errors. Remove those columns now // so that we can rename properly. db_drop_field('url_alias', 'source'); db_drop_field('url_alias', 'alias'); // Add the cache_path table. $schema['cache_path'] = drupal_get_schema_unprocessed('system', 'cache'); $schema['cache_path']['description'] = 'Cache table used for path alias lookups.'; db_create_table('cache_path', $schema['cache_path']); // Drop indexes. db_drop_index('url_alias', 'src_language_pid'); db_drop_unique_key('url_alias', 'dst_language_pid'); // Rename fields. db_change_field('url_alias', 'src', 'source', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '')); db_change_field('url_alias', 'dst', 'alias', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '')); // Add indexes back. db_add_index('url_alias', 'source_language_pid', array('source', 'language', 'pid')); db_add_unique_key('url_alias', 'alias_language_pid', array('alias', 'language', 'pid')); } /** * Add a 'context' field to {menu_router} to control contextual placement of local tasks. */ function system_update_7043() { // Moved to update_fix_d7_requirements(). } /** * Reuse the actions_aid table as sequences. */ function system_update_7044() { $schema['sequences'] = array( 'description' => 'Stores IDs.', 'fields' => array( 'value' => array( 'description' => 'The value of the sequence.', 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, ), ), 'primary key' => array('value'), ); db_create_table('sequences', $schema['sequences']); $max_aid = db_query('SELECT MAX(aid) FROM {actions_aid}')->fetchField(); $max_uid = db_query('SELECT MAX(uid) FROM {users}')->fetchField(); db_insert('sequences')->fields(array('value' => max($max_aid, $max_uid)))->execute(); db_drop_table('actions_aid'); } /** * Add expiration field to the {flood} table. */ function system_update_7045() { db_add_field('flood', 'expiration', array('description' => 'Expiration timestamp. Expired events are purged on cron run.', 'type' => 'int', 'not null' => TRUE, 'default' => 0)); db_add_index('flood', 'purge', array('expiration')); } /** * Switch from the Minnelli theme if it is the default or admin theme. */ function system_update_7046() { if (variable_get('theme_default') == 'minnelli' || variable_get('admin_theme') == 'minnelli') { // Make sure Garland is enabled. db_update('system') ->fields(array('status' => 1)) ->condition('type', 'theme') ->condition('name', 'garland') ->execute(); if (variable_get('theme_default') != 'garland') { // If the default theme isn't Garland, transfer all of Minnelli's old // settings to Garland. $settings = variable_get('theme_minnelli_settings', array()); // Set the theme setting width to "fixed" to match Minnelli's old layout. $settings['garland_width'] = 'fixed'; variable_set('theme_garland_settings', $settings); // Remove Garland's color files since they won't match Minnelli's. foreach (variable_get('color_garland_files', array()) as $file) { @unlink($file); } if (isset($file) && $file = dirname($file)) { @rmdir($file); } variable_del('color_garland_palette'); variable_del('color_garland_stylesheets'); variable_del('color_garland_logo'); variable_del('color_garland_files'); variable_del('color_garland_screenshot'); } if (variable_get('theme_default') == 'minnelli') { variable_set('theme_default', 'garland'); } if (variable_get('admin_theme') == 'minnelli') { variable_set('admin_theme', 'garland'); } } } /** * Normalize the front page path variable. */ function system_update_7047() { variable_set('site_frontpage', drupal_get_normal_path(variable_get('site_frontpage', 'node'))); } /** * Convert path languages from the empty string to LANGUAGE_NONE. */ function system_update_7048() { db_update('url_alias') ->fields(array('language' => LANGUAGE_NONE)) ->condition('language', '') ->execute(); } /** * @} End of "defgroup updates-6.x-to-7.x" * The next series of updates should start at 8000. */