Code coverage for /20080809/modules/system/system.install

Line #Times calledCode
1
<?php
2
// $Id: system.install,v 1.258 2008/08/02 19:01:02 dries Exp $
3
4
/**
5
 * Test and report Drupal installation requirements.
6
 *
7
 * @param $phase
8
 *   The current system installation phase.
9
 * @return
10
 *   An array of system requirements.
11
 */
1280
function system_requirements($phase) {
133
  $requirements = array();
14
  // Ensure translations don't break at install time
153
  $t = get_t();
16
17
  // Report Drupal version
183
  if ($phase == 'runtime') {
193
    $requirements['drupal'] = array(
203
      'title' => $t('Drupal'),
213
      'value' => VERSION,
223
      'severity' => REQUIREMENT_INFO,
233
      'weight' => -10,
24
    );
253
  }
26
27
  // Web server information.
283
  $software = $_SERVER['SERVER_SOFTWARE'];
293
  $requirements['webserver'] = array(
303
    'title' => $t('Web server'),
313
    'value' => $software,
32
  );
33
34
  // Test PHP version
353
  $requirements['php'] = array(
363
    'title' => $t('PHP'),
373
    'value' => ($phase == 'runtime') ? l(phpversion(),
'admin/reports/status/php') : phpversion(),
38
  );
393
  if (version_compare(phpversion(), DRUPAL_MINIMUM_PHP) < 0) {
400
    $requirements['php']['description'] = $t('Your PHP installation is too
old. Drupal requires at least PHP %version.', array('%version' =>
DRUPAL_MINIMUM_PHP));
410
    $requirements['php']['severity'] = REQUIREMENT_ERROR;
420
  }
43
44
  // Test PHP register_globals setting.
453
  $requirements['php_register_globals'] = array(
463
    'title' => $t('PHP register globals'),
47
  );
483
  $register_globals = trim(ini_get('register_globals'));
49
  // Unfortunately, ini_get() may return many different values, and we
can't
50
  // be certain which values mean 'on', so we instead check for 'not off'
51
  // since we never want to tell the user that their site is secure
52
  // (register_globals off), when it is in fact on. We can only guarantee
53
  // register_globals is off if the value returned is 'off', '', or 0.
543
  if (!empty($register_globals) && strtolower($register_globals) != 'off')
{
550
    $requirements['php_register_globals']['description'] =
$t('<em>register_globals</em> is enabled. Drupal requires this
configuration directive to be disabled. Your site may not be secure when
<em>register_globals</em> is enabled. The PHP manual has instructions for
<a href="http://php.net/configuration.changes">how to change configuration
settings</a>.');
560
    $requirements['php_register_globals']['severity'] = REQUIREMENT_ERROR;
570
    $requirements['php_register_globals']['value'] = $t("Enabled
('@value')", array('@value' => $register_globals));
580
  }
59
  else {
603
    $requirements['php_register_globals']['value'] = $t('Disabled');
61
  }
62
63
  // Test PHP memory_limit
643
  $memory_limit = ini_get('memory_limit');
653
  $requirements['php_memory_limit'] = array(
663
    'title' => $t('PHP memory limit'),
673
    'value' => $memory_limit,
68
  );
69
703
  if ($memory_limit && parse_size($memory_limit) <
parse_size(DRUPAL_MINIMUM_PHP_MEMORY_LIMIT)) {
710
    $description = '';
720
    if ($phase == 'install') {
730
      $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));
740
    }
750
    elseif ($phase == 'update') {
760
      $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));
770
    }
780
    elseif ($phase == 'runtime') {
790
      $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));
800
    }
81
820
    if (!empty($description)) {
830
      if ($php_ini_path = get_cfg_var('cfg_file_path')) {
840
        $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));
850
      }
86
      else {
870
        $description .= ' ' . $t('Contact your system administrator or
hosting provider for assistance with increasing your PHP memory limit.');
88
      }
89
900
      $requirements['php_memory_limit']['description'] = $description . ' '
. $t('See the <a href="@url">Drupal requirements</a> for more
information.', array('@url' => 'http://drupal.org/requirements'));
910
      $requirements['php_memory_limit']['severity'] = REQUIREMENT_WARNING;
920
    }
930
  }
94
95
  // Test DB version
963
  global $db_type;
973
  if (function_exists('db_status_report')) {
983
    $requirements += db_status_report($phase);
993
  }
100
101
  // Test settings.php file writability
1023
  if ($phase == 'runtime') {
1033
    $conf_dir = drupal_verify_install_file(conf_path(), FILE_NOT_WRITABLE,
'dir');
1043
    $conf_file = drupal_verify_install_file(conf_path() . '/settings.php',
FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE);
1053
    if (!$conf_dir || !$conf_file) {
1063
      $requirements['settings.php'] = array(
1073
        'value' => $t('Not protected'),
1083
        'severity' => REQUIREMENT_ERROR,
1093
        'description' => '',
110
      );
1113
      if (!$conf_dir) {
1123
        $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()));
1133
      }
1143
      if (!$conf_file) {
1153
        $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'));
1163
      }
1173
    }
118
    else {
1190
      $requirements['settings.php'] = array(
1200
        'value' => $t('Protected'),
121
      );
122
    }
1233
    $requirements['settings.php']['title'] = $t('Configuration file');
1243
  }
125
126
  // Report cron status.
1273
  if ($phase == 'runtime') {
128
    // Cron warning threshold defaults to two days.
1293
    $threshold_warning = variable_get('cron_threshold_warning', 172800);
130
    // Cron error threshold defaults to two weeks.
1313
    $threshold_error = variable_get('cron_threshold_error', 1209600);
132
    // Cron configuration help text.
1333
    $help = $t('For more information, see the online handbook entry for <a
href="@cron-handbook">configuring cron jobs</a>.', array('@cron-handbook'
=> 'http://drupal.org/cron'));
134
135
    // Determine when cron last ran. If never, use the install time to
136
    // determine the warning or error status.
1373
    $cron_last = variable_get('cron_last', NULL);
1383
    $never_run = FALSE;
1393
    if (!is_numeric($cron_last)) {
1402
      $never_run = TRUE;
1412
      $cron_last = variable_get('install_time', 0);
1422
    }
143
144
    // Determine severity based on time since cron last ran.
1453
    $severity = REQUIREMENT_OK;
1463
    if (time() - $cron_last > $threshold_error) {
1472
      $severity = REQUIREMENT_ERROR;
1482
    }
1491
    else if ($never_run || (time() - $cron_last > $threshold_warning)) {
1500
      $severity = REQUIREMENT_WARNING;
1510
    }
152
153
    // If cron hasn't been run, and the user is viewing the main
154
    // administration page, instead of an error, we display a helpful
reminder
155
    // to configure cron jobs.
1563
    if ($never_run && $severity != REQUIREMENT_ERROR && $_GET['q'] ==
'admin' && user_access('administer site configuration')) {
1570
      drupal_set_message($t('Cron has not run. Please visit the <a
href="@status">status report</a> for more information.', array('@status' =>
url('admin/reports/status'))));
1580
    }
159
160
    // Set summary and description based on values determined above.
1613
    if ($never_run) {
1622
      $summary = $t('Never run');
1632
      $description = $t('Cron has not run.') . ' ' . $help;
1642
    }
165
    else {
1661
      $summary = $t('Last run !time ago', array('!time' =>
format_interval(time() - $cron_last)));
1671
      $description = '';
1681
      if ($severity != REQUIREMENT_OK) {
1690
        $description = $t('Cron has not run recently.') . ' ' . $help;
1700
      }
171
    }
172
1733
    $description .= ' ' . $t('You can <a href="@cron">run cron
manually</a>.', array('@cron' => url('admin/reports/status/run-cron')));
1743
    $description .= '<br />' . $t('To run cron from outside the site, go to
<a href="!cron">!cron</a>', array('!cron' => url('cron.php',
array('absolute' => true, 'query' => 'cron_key=' . variable_get('cron_key',
'drupal')))));
175
1763
    $requirements['cron'] = array(
1773
      'title' => $t('Cron maintenance tasks'),
1783
      'severity' => $severity,
1793
      'value' => $summary,
180
      'description' => $description
1813
    );
1823
  }
183
184
  // Test files directory
1853
  $directory = file_directory_path();
1863
  $requirements['file system'] = array(
1873
    'title' => $t('File system'),
188
  );
189
190
  // For installer, create the directory if possible.
1913
  if ($phase == 'install' && !is_dir($directory) && @mkdir($directory)) {
1920
    @chmod($directory, 0775); // Necessary for non-webserver users.
1930
  }
194
1953
  $is_writable = is_writable($directory);
1963
  $is_directory = is_dir($directory);
1973
  if (!$is_writable || !$is_directory) {
1980
    $description = '';
1990
    $requirements['file system']['value'] = $t('Not writable');
2000
    if (!$is_directory) {
2010
      $error = $t('The directory %directory does not exist.',
array('%directory' => $directory));
2020
    }
203
    else {
2040
      $error = $t('The directory %directory is not writable.',
array('%directory' => $directory));
205
    }
206
    // The files directory requirement check is done only during install
and runtime.
2070
    if ($phase == 'runtime') {
2080
      $description = $error . ' ' . $t('You may need to set the correct
directory at the <a href="@admin-file-system">file system settings page</a>
or change the current directory\'s permissions so that it is writable.',
array('@admin-file-system' => url('admin/settings/file-system')));
2090
    }
2100
    elseif ($phase == 'install') {
211
      // For the installer UI, we need different wording. 'value' will
212
      // be treated as version, so provide none there.
2130
      $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 <a
href="@handbook_url">online handbook</a>.', array('@handbook_url' =>
'http://drupal.org/server-permissions'));
2140
      $requirements['file system']['value'] = '';
2150
    }
2160
    if (!empty($description)) {
2170
      $requirements['file system']['description'] = $description;
2180
      $requirements['file system']['severity'] = REQUIREMENT_ERROR;
2190
    }
2200
  }
221
  else {
2223
    if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) ==
FILE_DOWNLOADS_PUBLIC) {
2233
      $requirements['file system']['value'] = $t('Writable (<em>public</em>
download method)');
2243
    }
225
    else {
2260
      $requirements['file system']['value'] = $t('Writable
(<em>private</em> download method)');
227
    }
228
  }
229
230
  // See if updates are available in update.php.
2313
  if ($phase == 'runtime') {
2323
    $requirements['update'] = array(
2333
      'title' => $t('Database updates'),
2343
      'severity' => REQUIREMENT_OK,
2353
      'value' => $t('Up to date'),
236
    );
237
238
    // Check installed modules.
2393
    foreach (module_list() as $module) {
2403
      $updates = drupal_get_schema_versions($module);
2413
      if ($updates !== FALSE) {
2423
        $default = drupal_get_installed_schema_version($module);
2433
        if (max($updates) > $default) {
2440
          $requirements['update']['severity'] = REQUIREMENT_ERROR;
2450
          $requirements['update']['value'] = $t('Out of date');
2460
          $requirements['update']['description'] = $t('Some modules have
database schema updates to install. You should run the <a
href="@update">database update script</a> immediately.', array('@update' =>
base_path() . 'update.php'));
2470
          break;
2480
        }
2493
      }
2503
    }
2513
  }
252
253
  // Verify the update.php access setting
2543
  if ($phase == 'runtime') {
2553
    if (!empty($GLOBALS['update_free_access'])) {
2560
      $requirements['update access'] = array(
2570
        'value' => $t('Not protected'),
2580
        'severity' => REQUIREMENT_ERROR,
2590
        '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.'),
260
      );
2610
    }
262
    else {
2633
      $requirements['update access'] = array(
2643
        'value' => $t('Protected'),
265
      );
266
    }
2673
    $requirements['update access']['title'] = $t('Access to update.php');
2683
  }
269
270
  // Test Unicode library
2713
  include_once './includes/unicode.inc';
2723
  $requirements = array_merge($requirements, unicode_requirements());
273
274
  // Check for update status module.
2753
  if ($phase == 'runtime') {
2763
    if (!module_exists('update')) {
2773
      $requirements['update status'] = array(
2783
        'value' => $t('Not enabled'),
2793
        'severity' => REQUIREMENT_ERROR,
2803
        'description' => $t('Update notifications are not enabled. It is
<strong>highly recommended</strong> that you enable the update status
module from the <a href="@module">module administration page</a> in order
to stay up-to-date on new releases. For more information please read the <a
href="@update">Update status handbook page</a>.', array('@update' =>
'http://drupal.org/handbook/modules/update', '@module' =>
url('admin/build/modules'))),
281
      );
2823
    }
283
    else {
2840
      $requirements['update status'] = array(
2850
        'value' => $t('Enabled'),
286
      );
2870
      if (variable_get('drupal_http_request_fails', FALSE)) {
2880
        $requirements['http requests'] = array(
2890
          'title' => $t('HTTP request status'),
2900
          'value' => $t('Fails'),
2910
          'severity' => REQUIREMENT_ERROR,
2920
          '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.'),
293
        );
2940
      }
295
    }
2963
    $requirements['update status']['title'] = $t('Update notifications');
2973
  }
298
2993
  return $requirements;
3000
}
301
302
/**
303
 * Implementation of hook_install().
304
 */
30580
function system_install() {
30662
  if ($GLOBALS['db_type'] == 'pgsql') {
307
    // We create some custom types and functions using global names instead
of
308
    // prefixing them like we do with table names. If this function is
ever
309
    // called again (for example, by the test framework when creating
prefixed
310
    // test databases), the global names will already exist. We therefore
avoid
311
    // trying to create them again in that case.
312
313
    // Create unsigned types.
3140
    if (!db_result(db_query("SELECT COUNT(*) FROM pg_constraint WHERE
conname = 'int_unsigned_check'"))) {
3150
      db_query("CREATE DOMAIN int_unsigned integer CHECK (VALUE >= 0)");
3160
    }
3170
    if (!db_result(db_query("SELECT COUNT(*) FROM pg_constraint WHERE
conname = 'smallint_unsigned_check'"))) {
3180
      db_query("CREATE DOMAIN smallint_unsigned smallint CHECK (VALUE >=
0)");
3190
    }
3200
    if (!db_result(db_query("SELECT COUNT(*) FROM pg_constraint WHERE
conname = 'bigint_unsigned_check'"))) {
3210
      db_query("CREATE DOMAIN bigint_unsigned bigint CHECK (VALUE >= 0)");
3220
    }
323
324
    // Create functions.
3250
    db_query('CREATE OR REPLACE FUNCTION "greatest"(numeric, numeric)
RETURNS numeric AS
326
      \'SELECT CASE WHEN (($1 > $2) OR ($2 IS NULL)) THEN $1 ELSE $2
END;\'
327
      LANGUAGE \'sql\''
3280
    );
3290
    db_query('CREATE OR REPLACE FUNCTION "greatest"(numeric, numeric,
numeric) RETURNS numeric AS
330
      \'SELECT greatest($1, greatest($2, $3));\'
331
      LANGUAGE \'sql\''
3320
    );
3330
    if (!db_result(db_query("SELECT COUNT(*) FROM pg_proc WHERE proname =
'rand'"))) {
3340
      db_query('CREATE OR REPLACE FUNCTION "rand"() RETURNS float AS
335
        \'SELECT random();\'
336
        LANGUAGE \'sql\''
3370
      );
3380
    }
339
3400
    if (!db_result(db_query("SELECT COUNT(*) FROM pg_proc WHERE proname =
'concat'"))) {
3410
      db_query('CREATE OR REPLACE FUNCTION "concat"(text, text) RETURNS
text AS
342
        \'SELECT $1 || $2;\'
343
        LANGUAGE \'sql\''
3440
      );
3450
    }
3460
    db_query('CREATE OR REPLACE FUNCTION "if"(boolean, text, text) RETURNS
text AS
347
      \'SELECT CASE WHEN $1 THEN $2 ELSE $3 END;\'
348
      LANGUAGE \'sql\''
3490
    );
3500
    db_query('CREATE OR REPLACE FUNCTION "if"(boolean, integer, integer)
RETURNS integer AS
351
      \'SELECT CASE WHEN $1 THEN $2 ELSE $3 END;\'
352
      LANGUAGE \'sql\''
3530
    );
3540
  }
355
356
  // Create tables.
35762
  $modules = array('system', 'filter', 'block', 'user', 'node', 'comment',
'taxonomy');
35862
  foreach ($modules as $module) {
35962
    drupal_install_schema($module);
36062
  }
361
362
  // Load system theme data appropriately.
36362
  system_theme_data();
364
365
  // Inserting uid 0 here confuses MySQL -- the next user might be created
as
366
  // uid 2 which is not what we want. So we insert the first user here,
the
367
  // anonymous user. uid is 1 here for now, but very soon it will be
changed
368
  // to 0.
36962
  db_query("INSERT INTO {users} (name, mail) VALUES('%s', '%s')", '', '');
370
  // We need some placeholders here as name and mail are uniques and data
is
371
  // presumed to be a serialized array. Install will change uid 1
immediately
372
  // anyways. So we insert the superuser here, the uid is 2 here for now,
but
373
  // very soon it will be changed to 1.
37462
  db_query("INSERT INTO {users} (name, mail, created, data) VALUES('%s',
'%s', %d, '%s')", 'placeholder-for-uid-1', 'placeholder-for-uid-1', time(),
serialize(array()));
375
  // This sets the above two users uid 0 (anonymous). We avoid an explicit
0
376
  // otherwise MySQL might insert the next auto_increment value.
37762
  db_query("UPDATE {users} SET uid = uid - uid WHERE name = '%s'", '');
378
  // This sets uid 1 (superuser). We skip uid 2 but that's not a big
problem.
37962
  db_query("UPDATE {users} SET uid = 1 WHERE name = '%s'",
'placeholder-for-uid-1');
380
381
  // Built-in roles.
38262
  db_query("INSERT INTO {role} (name) VALUES ('%s')", 'anonymous user');
38362
  db_query("INSERT INTO {role} (name) VALUES ('%s')", 'authenticated
user');
384
385
  // Anonymous role permissions.
38662
  db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d,
'%s')", 1, 'access content');
387
388
  // Authenticated role permissions.
38962
  db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d,
'%s')", 2, 'access comments');
39062
  db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d,
'%s')", 2, 'access content');
39162
  db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d,
'%s')", 2, 'post comments');
39262
  db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d,
'%s')", 2, 'post comments without approval');
393
39462
  db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')",
'theme_default', 's:7:"garland";');
39562
  db_query("UPDATE {system} SET status = %d WHERE type = '%s' AND name =
'%s'", 1, 'theme', 'garland');
39662
  db_query("INSERT INTO {blocks} (module, delta, theme, status, weight,
region, pages, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', '%s', %d)",
'user', 'login', 'garland', 1, 0, 'left', '', -1);
39762
  db_query("INSERT INTO {blocks} (module, delta, theme, status, weight,
region, pages, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', '%s', %d)",
'user', 'navigation', 'garland', 1, 0, 'left', '', -1);
39862
  db_query("INSERT INTO {blocks} (module, delta, theme, status, weight,
region, pages, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', '%s', %d)",
'system', 'powered-by', 'garland', 1, 10, 'footer', '', -1);
399
40062
  db_query("INSERT INTO {node_access} (nid, gid, realm, grant_view,
grant_update, grant_delete) VALUES (%d, %d, '%s', %d, %d, %d)", 0, 0,
'all', 1, 0, 0);
401
402
  // Add input formats.
40362
  db_query("INSERT INTO {filter_formats} (name, roles, cache) VALUES ('%s',
'%s', %d)", 'Filtered HTML', ',1,2,', 1);
40462
  db_query("INSERT INTO {filter_formats} (name, roles, cache) VALUES ('%s',
'%s', %d)", 'Full HTML', '', 1);
405
406
  // Enable filters for each input format.
407
408
  // Filtered HTML:
409
  // URL filter.
41062
  db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES
(%d, '%s', %d, %d)", 1, 'filter', 2, 0);
411
  // HTML filter.
41262
  db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES
(%d, '%s', %d, %d)", 1, 'filter', 0, 1);
413
  // Line break filter.
41462
  db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES
(%d, '%s', %d, %d)", 1, 'filter', 1, 2);
415
  // HTML corrector filter.
41662
  db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES
(%d, '%s', %d, %d)", 1, 'filter', 3, 10);
417
418
  // Full HTML:
419
  // URL filter.
42062
  db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES
(%d, '%s', %d, %d)", 2, 'filter', 2, 0);
421
  // Line break filter.
42262
  db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES
(%d, '%s', %d, %d)", 2, 'filter', 1, 1);
423
  // HTML corrector filter.
42462
  db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES
(%d, '%s', %d, %d)", 2, 'filter', 3, 10);
425
42662
  db_query("INSERT INTO {variable} (name, value) VALUES ('%s','%s')",
'filter_html_1', 'i:1;');
427
42862
  db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')",
'node_options_forum', 'a:1:{i:0;s:6:"status";}');
429
43062
  $cron_key = serialize(md5(mt_rand()));
431
43262
  db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')",
'cron_key', $cron_key);
43362
}
434
435
/**
436
 * Implementation of hook_schema().
437
 */
43880
function system_schema() {
439
  // NOTE: {variable} needs to be created before all other tables, as
440
  // some database drivers, e.g. Oracle and DB2, will require
variable_get()
441
  // and variable_set() for overcoming some database specific limitations.
44277
  $schema['variable'] = array(
44377
    'description' => t('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.'),
444
    'fields' => array(
445
      'name' => array(
44677
        'description' => t('The name of the variable.'),
44777
        'type' => 'varchar',
44877
        'length' => 128,
44977
        'not null' => TRUE,
45077
        'default' => '',
45177
      ),
452
      'value' => array(
45377
        'description' => t('The value of the variable.'),
45477
        'type' => 'text',
45577
        'not null' => TRUE,
45677
        'size' => 'big',
45777
      ),
45877
    ),
45977
    'primary key' => array('name'),
460
  );
461
46277
  $schema['actions'] = array(
46377
    'description' => t('Stores action information.'),
464
    'fields' => array(
465
      'aid' => array(
46677
        'description' => t('Primary Key: Unique actions ID.'),
46777
        'type' => 'varchar',
46877
        'length' => 255,
46977
        'not null' => TRUE,
47077
        'default' => '0',
47177
      ),
472
      'type' => array(
47377
        'description' => t('The object that that action acts on (node,
user, comment, system or custom types.)'),
47477
        'type' => 'varchar',
47577
        'length' => 32,
47677
        'not null' => TRUE,
47777
        'default' => '',
47877
      ),
479
      'callback' => array(
48077
        'description' => t('The callback function that executes when the
action runs.'),
48177
        'type' => 'varchar',
48277
        'length' => 255,
48377
        'not null' => TRUE,
48477
        'default' => '',
48577
      ),
486
      'parameters' => array(
48777
        'description' => t('Parameters to be passed to the callback
function.'),
48877
        'type' => 'text',
48977
        'not null' => TRUE,
49077
        'size' => 'big',
49177
      ),
492
      'description' => array(
49377
        'description' => t('Description of the action.'),
49477
        'type' => 'varchar',
49577
        'length' => 255,
49677
        'not null' => TRUE,
49777
        'default' => '0',
49877
      ),
49977
    ),
50077
    'primary key' => array('aid'),
501
  );
502
50377
  $schema['actions_aid'] = array(
50477
    'description' => t('Stores action IDs for non-default actions.'),
505
    'fields' => array(
506
      'aid' => array(
50777
        'description' => t('Primary Key: Unique actions ID.'),
50877
        'type' => 'serial',
50977
        'unsigned' => TRUE,
51077
        'not null' => TRUE,
51177
      ),
51277
    ),
51377
    'primary key' => array('aid'),
514
  );
515
51677
  $schema['batch'] = array(
51777
    'description' => t('Stores details about batches (processes that run in
multiple HTTP requests).'),
518
    'fields' => array(
519
      'bid' => array(
52077
        'description' => t('Primary Key: Unique batch ID.'),
52177
        'type' => 'serial',
52277
        'unsigned' => TRUE,
52377
        'not null' => TRUE,
52477
      ),
525
      'token' => array(
52677
        'description' => t("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."),
52777
        'type' => 'varchar',
52877
        'length' => 64,
52977
        'not null' => TRUE,
53077
      ),
531
      'timestamp' => array(
53277
        'description' => t('A Unix timestamp indicating when this batch was
submitted for processing. Stale batches are purged at cron time.'),
53377
        'type' => 'int',
53477
        'not null' => TRUE,
53577
      ),
536
      'batch' => array(
53777
        'description' => t('A serialized array containing the processing
data for the batch.'),
53877
        'type' => 'text',
53977
        'not null' => FALSE,
54077
        'size' => 'big',
54177
      ),
54277
    ),
54377
    'primary key' => array('bid'),
544
    'indexes' => array(
54577
      'token' => array('token'),
54677
    ),
547
  );
548
54977
  $schema['blocked_ips'] = array(
55077
    'description' => t('Stores blocked IP addresses.'),
551
    'fields' => array(
552
       'iid' => array(
55377
        'description' => t('Primary Key: unique ID for IP addresses.'),
55477
        'type' => 'serial',
55577
        'unsigned' => TRUE,
55677
        'not null' => TRUE,
55777
      ),
558
      'ip' => array(
55977
        'description' => t('IP address'),
56077
        'type' => 'varchar',
56177
        'length' => 32,
56277
        'not null' => TRUE,
56377
        'default' => '',
56477
      ),
56577
    ),
566
    'indexes' => array(
56777
      'blocked_ip' => array('ip'),
56877
    ),
56977
    'primary key' => array('iid'),
570
  );
571
57277
  $schema['cache'] = array(
57377
    'description' => t('Generic cache table for caching things not
separated out into their own tables. Contributed modules may also use this
to store cached items.'),
574
    'fields' => array(
575
      'cid' => array(
57677
        'description' => t('Primary Key: Unique cache ID.'),
57777
        'type' => 'varchar',
57877
        'length' => 255,
57977
        'not null' => TRUE,
58077
        'default' => '',
58177
      ),
582
      'data' => array(
58377
        'description' => t('A collection of data to cache.'),
58477
        'type' => 'blob',
58577
        'not null' => FALSE,
58677
        'size' => 'big',
58777
      ),
588
      'expire' => array(
58977
        'description' => t('A Unix timestamp indicating when the cache
entry should expire, or 0 for never.'),
59077
        'type' => 'int',
59177
        'not null' => TRUE,
59277
        'default' => 0,
59377
      ),
594
      'created' => array(
59577
        'description' => t('A Unix timestamp indicating when the cache
entry was created.'),
59677
        'type' => 'int',
59777
        'not null' => TRUE,
59877
        'default' => 0,
59977
      ),
600
      'headers' => array(
60177
        'description' => t('Any custom HTTP headers to be added to cached
data.'),
60277
        'type' => 'text',
60377
        'not null' => FALSE,
60477
      ),
605
      'serialized' => array(
60677
        'description' => t('A flag to indicate whether content is
serialized (1) or not (0).'),
60777
        'type' => 'int',
60877
        'size' => 'small',
60977
        'not null' => TRUE,
61077
        'default' => 0,
61177
      ),
61277
    ),
613
    'indexes' => array(
61477
      'expire' => array('expire'),
61577
    ),
61677
    'primary key' => array('cid'),
617
  );
618
61977
  $schema['cache_form'] = $schema['cache'];
62077
  $schema['cache_form']['description'] = t('Cache table for the form system
to store recently built forms and their storage data, to be used in
subsequent page requests.');
62177
  $schema['cache_page'] = $schema['cache'];
62277
  $schema['cache_page']['description'] = t('Cache table used to store
compressed pages for anonymous users, if page caching is enabled.');
62377
  $schema['cache_menu'] = $schema['cache'];
62477
  $schema['cache_menu']['description'] = t('Cache table for the menu system
to store router information as well as generated link trees for various
menu/page/user combinations.');
62577
  $schema['cache_registry'] = $schema['cache'];
62677
  $schema['cache_registry']['description'] = t('Cache table for the code
registry system to remember what code files need to be loaded on any given
page.');
627
62877
  $schema['files'] = array(
62977
    'description' => t('Stores information for uploaded files.'),
630
    'fields' => array(
631
      'fid' => array(
63277
        'description' => t('Primary Key: Unique files ID.'),
63377
        'type' => 'serial',
63477
        'unsigned' => TRUE,
63577
        'not null' => TRUE,
63677
      ),
637
      'uid' => array(
63877
        'description' => t('The {users}.uid of the user who is associated
with the file.'),
63977
        'type' => 'int',
64077
        'unsigned' => TRUE,
64177
        'not null' => TRUE,
64277
        'default' => 0,
64377
      ),
644
      'filename' => array(
64577
        'description' => t('Name of the file.'),
64677
        'type' => 'varchar',
64777
        'length' => 255,
64877
        'not null' => TRUE,
64977
        'default' => '',
65077
      ),
651
      'filepath' => array(
65277
        'description' => t('Path of the file relative to Drupal root.'),
65377
        'type' => 'varchar',
65477
        'length' => 255,
65577
        'not null' => TRUE,
65677
        'default' => '',
65777
      ),
658
      'filemime' => array(
65977
        'description' => t('The file MIME type.'),
66077
        'type' => 'varchar',
66177
        'length' => 255,
66277
        'not null' => TRUE,
66377
        'default' => '',
66477
      ),
665
      'filesize' => array(
66677
        'description' => t('The size of the file in bytes.'),
66777
        'type' => 'int',
66877
        'unsigned' => TRUE,
66977
        'not null' => TRUE,
67077
        'default' => 0,
67177
      ),
672
      'status' => array(
67377
        'description' => t('A flag indicating whether file is temporary (1)
or permanent (0).'),
67477
        'type' => 'int',
67577
        'not null' => TRUE,
67677
        'default' => 0,
67777
      ),
678
      'timestamp' => array(
67977
        'description' => t('UNIX timestamp for when the file was added.'),
68077
        'type' => 'int',
68177
        'unsigned' => TRUE,
68277
        'not null' => TRUE,
68377
        'default' => 0,
68477
      ),
68577
    ),
686
    'indexes' => array(
68777
      'uid' => array('uid'),
68877
      'status' => array('status'),
68977
      'timestamp' => array('timestamp'),
69077
    ),
69177
    'primary key' => array('fid'),
692
  );
693
69477
  $schema['flood'] = array(
69577
    'description' => t('Flood controls the threshold of events, such as the
number of contact attempts.'),
696
    'fields' => array(
697
      'fid' => array(
69877
        'description' => t('Unique flood event ID.'),
69977
        'type' => 'serial',
70077
        'not null' => TRUE,
70177
      ),
702
      'event' => array(
70377
        'description' => t('Name of event (e.g. contact).'),
70477
        'type' => 'varchar',
70577
        'length' => 64,
70677
        'not null' => TRUE,
70777
        'default' => '',
70877
      ),
709
      'hostname' => array(
71077
        'description' => t('Hostname of the visitor.'),
71177
        'type' => 'varchar',
71277
        'length' => 128,
71377
        'not null' => TRUE,
71477
        'default' => '',
71577
      ),
716
      'timestamp' => array(
71777
        'description' => t('Timestamp of the event.'),
71877
        'type' => 'int',
71977
        'not null' => TRUE,
72077
        'default' => 0,
72177
      ),
72277
    ),
72377
    'primary key' => array('fid'),
724
    'indexes' => array(
72577
      'allow' => array('event', 'hostname', 'timestamp'),
72677
    ),
727
  );
728
72977
  $schema['history'] = array(
73077
    'description' => t('A record of which {users} have read which
{node}s.'),
731
    'fields' => array(
732
      'uid' => array(
73377
        'description' => t('The {users}.uid that read the {node} nid.'),
73477
        'type' => 'int',
73577
        'not null' => TRUE,
73677
        'default' => 0,
73777
      ),
738
      'nid' => array(
73977
        'description' => t('The {node}.nid that was read.'),
74077
        'type' => 'int',
74177
        'not null' => TRUE,
74277
        'default' => 0,
74377
      ),
744
      'timestamp' => array(
74577
        'description' => t('The Unix timestamp at which the read
occurred.'),
74677
        'type' => 'int',
74777
        'not null' => TRUE,
74877
        'default' => 0,
74977
      ),
75077
    ),
75177
    'primary key' => array('uid', 'nid'),
752
    'indexes' => array(
75377
      'nid' => array('nid'),
75477
    ),
755
  );
75677
  $schema['menu_router'] = array(
75777
    'description' => t('Maps paths to various callbacks (access, page and
title)'),
758
    'fields' => array(
759
      'path' => array(
76077
        'description' => t('Primary Key: the Drupal path this entry
describes'),
76177
        'type' => 'varchar',
76277
        'length' => 255,
76377
        'not null' => TRUE,
76477
        'default' => '',
76577
      ),
766
      'load_functions' => array(
76777
        'description' => t('A serialized array of function names (like
node_load) to be called to load an object corresponding to a part of the
current path.'),
76877
        'type' => 'varchar',
76977
        'length' => 255,
77077
        'not null' => TRUE,
77177
        'default' => '',
77277
      ),
773
      'to_arg_functions' => array(
77477
        'description' => t('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.'),
77577
        'type' => 'varchar',
77677
        'length' => 255,
77777
        'not null' => TRUE,
77877
        'default' => '',
77977
      ),
780
      'access_callback' => array(
78177
        'description' => t('The callback which determines the access to
this router path. Defaults to user_access.'),
78277
        'type' => 'varchar',
78377
        'length' => 255,
78477
        'not null' => TRUE,
78577
        'default' => '',
78677
      ),
787
      'access_arguments' => array(
78877
        'description' => t('A serialized array of arguments for the access
callback.'),
78977
        'type' => 'text',
79077
        'not null' => FALSE,
79177
      ),
792
      'page_callback' => array(
79377
        'description' => t('The name of the function that renders the
page.'),
79477
        'type' => 'varchar',
79577
        'length' => 255,
79677
        'not null' => TRUE,
79777
        'default' => '',
79877
      ),
799
      'page_arguments' => array(
80077
        'description' => t('A serialized array of arguments for the page
callback.'),
80177
        'type' => 'text',
80277
        'not null' => FALSE,
80377
      ),
804
      'fit' => array(
80577
        'description' => t('A numeric representation of how specific the
path is.'),
80677
        'type' => 'int',
80777
        'not null' => TRUE,
80877
        'default' => 0,
80977
      ),
810
      'number_parts' => array(
81177
        'description' => t('Number of parts in this router path.'),
81277
        'type' => 'int',
81377
        'not null' => TRUE,
81477
        'default' => 0,
81577
        'size' => 'small',
81677
      ),
817
      'tab_parent' => array(
81877
        'description' => t('Only for local tasks (tabs) - the router path
of the parent page (which may also be a local task).'),
81977
        'type' => 'varchar',
82077
        'length' => 255,
82177
        'not null' => TRUE,
82277
        'default' => '',
82377
      ),
824
      'tab_root' => array(
82577
        'description' => t('Router path of the closest non-tab parent page.
For pages that are not local tasks, this will be the same as the path.'),
82677
        'type' => 'varchar',
82777
        'length' => 255,
82877
        'not null' => TRUE,
82977
        'default' => '',
83077
      ),
831
      'title' => array(
83277
        'description' => t('The title for the current page, or the title
for the tab if this is a local task.'),
83377
        'type' => 'varchar',
83477
        'length' => 255,
83577
        'not null' => TRUE,
83677
        'default' => '',
83777
      ),
838
      'title_callback' => array(
83977
        'description' => t('A function which will alter the title. Defaults
to t()'),
84077
        'type' => 'varchar',
84177
        'length' => 255,
84277
        'not null' => TRUE,
84377
        'default' => '',
84477
      ),
845
      'title_arguments' => array(
84677
        'description' => t('A serialized array of arguments for the title
callback. If empty, the title will be used as the sole argument for the
title callback.'),
84777
        'type' => 'varchar',
84877
        'length' => 255,
84977
        'not null' => TRUE,
85077
        'default' => '',
85177
      ),
852
      'type' => array(
85377
        'description' => t('Numeric representation of the type of the menu
item, like MENU_LOCAL_TASK.'),
85477
        'type' => 'int',
85577
        'not null' => TRUE,
85677
        'default' => 0,
85777
      ),
858
      'block_callback' => array(
85977
        'description' => t('Name of a function used to render the block on
the system administration page for this item.'),
86077
        'type' => 'varchar',
86177
        'length' => 255,
86277
        'not null' => TRUE,
86377
        'default' => '',
86477
      ),
865
      'description' => array(
86677
        'description' => t('A description of this item.'),
86777
        'type' => 'text',
86877
        'not null' => TRUE,
86977
      ),
870
      'position' => array(
87177
        'description' => t('The position of the block (left or right) on
the system administration page for this item.'),
87277
        'type' => 'varchar',
87377
        'length' => 255,
87477
        'not null' => TRUE,
87577
        'default' => '',
87677
      ),
877
      'weight' => array(
87877
        'description' => t('Weight of the element. Lighter weights are
higher up, heavier weights go down.'),
87977
        'type' => 'int',
88077
        'not null' => TRUE,
88177
        'default' => 0,
88277
      ),
88377
    ),
884
    'indexes' => array(
88577
      'fit' => array('fit'),
88677
      'tab_parent' => array('tab_parent'),
88777
    ),
88877
    'primary key' => array('path'),
889
  );
890
89177
  $schema['menu_links'] = array(
89277
    'description' => t('Contains the individual links within a menu.'),
893
    'fields' => array(
894
     'menu_name' => array(
89577
        'description' => t("The menu name. All links with the same menu
name (such as 'navigation') are part of the same menu."),
89677
        'type' => 'varchar',
89777
        'length' => 32,
89877
        'not null' => TRUE,
89977
        'default' => '',
90077
      ),
901
      'mlid' => array(
90277
        'description' => t('The menu link ID (mlid) is the integer primary
key.'),
90377
        'type' => 'serial',
90477
        'unsigned' => TRUE,
90577
        'not null' => TRUE,
90677
      ),
907
      'plid' => array(
90877
        'description' => t('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.'),
90977
        'type' => 'int',
91077
        'unsigned' => TRUE,
91177
        'not null' => TRUE,
91277
        'default' => 0,
91377
      ),
914
      'link_path' => array(
91577
        'description' => t('The Drupal path or external path this link
points to.'),
91677
        'type' => 'varchar',
91777
        'length' => 255,
91877
        'not null' => TRUE,
91977
        'default' => '',
92077
      ),
921
      'router_path' => array(
92277
        'description' => t('For links corresponding to a Drupal path
(external = 0), this connects the link to a {menu_router}.path for
joins.'),
92377
        'type' => 'varchar',
92477
        'length' => 255,
92577
        'not null' => TRUE,
92677
        'default' => '',
92777
      ),
928
      'link_title' => array(
92977
      'description' => t('The text displayed for the link, which may be
modified by a title callback stored in {menu_router}.'),
93077
        'type' => 'varchar',
93177
        'length' => 255,
93277
        'not null' => TRUE,
93377
        'default' => '',
93477
      ),
935
      'options' => array(
93677
        'description' => t('A serialized array of options to be passed to
the url() or l() function, such as a query string or HTML attributes.'),
93777
        'type' => 'text',
93877
        'not null' => FALSE,
93977
      ),
940
      'module' => array(
94177
        'description' => t('The name of the module that generated this
link.'),
94277
        'type' => 'varchar',
94377
        'length' => 255,
94477
        'not null' => TRUE,
94577
        'default' => 'system',
94677
      ),
947
      'hidden' => array(
94877
        'description' => t('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)'),
94977
        'type' => 'int',
95077
        'not null' => TRUE,
95177
        'default' => 0,
95277
        'size' => 'small',
95377
      ),
954
      'external' => array(
95577
        'description' => t('A flag to indicate if the link points to a full
URL starting with a protocol, like http:// (1 = external, 0 =
internal).'),
95677
        'type' => 'int',
95777
        'not null' => TRUE,
95877
        'default' => 0,
95977
        'size' => 'small',
96077
      ),
961
      'has_children' => array(
96277
        'description' => t('Flag indicating whether any links have this
link as a parent (1 = children exist, 0 = no children).'),
96377
        'type' => 'int',
96477
        'not null' => TRUE,
96577
        'default' => 0,
96677
        'size' => 'small',
96777
      ),
968
      'expanded' => array(
96977
        'description' => t('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)'),
97077
        'type' => 'int',
97177
        'not null' => TRUE,
97277
        'default' => 0,
97377
        'size' => 'small',
97477
      ),
975
      'weight' => array(
97677
        'description' => t('Link weight among links in the same menu at the
same depth.'),
97777
        'type' => 'int',
97877
        'not null' => TRUE,
97977
        'default' => 0,
98077
      ),
981
      'depth' => array(
98277
        'description' => t('The depth relative to the top level. A link
with plid == 0 will have depth == 1.'),
98377
        'type' => 'int',
98477
        'not null' => TRUE,
98577
        'default' => 0,
98677
        'size' => 'small',
98777
      ),
988
      'customized' => array(
98977
        'description' => t('A flag to indicate that the user has manually
created or edited the link (1 = customized, 0 = not customized).'),
99077
        'type' => 'int',
99177
        'not null' => TRUE,
99277
        'default' => 0,
99377
        'size' => 'small',
99477
      ),
995
      'p1' => array(
99677
        'description' => t('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.'),
99777
        'type' => 'int',
99877
        'unsigned' => TRUE,
99977
        'not null' => TRUE,
100077
        'default' => 0,
100177
      ),
1002
      'p2' => array(
100377
        'description' => t('The second mlid in the materialized path. See
p1.'),
100477
        'type' => 'int',
100577
        'unsigned' => TRUE,
100677
        'not null' => TRUE,
100777
        'default' => 0,
100877
      ),
1009
      'p3' => array(
101077
        'description' => t('The third mlid in the materialized path. See
p1.'),
101177
        'type' => 'int',
101277
        'unsigned' => TRUE,
101377
        'not null' => TRUE,
101477
        'default' => 0,
101577
      ),
1016
      'p4' => array(
101777
        'description' => t('The fourth mlid in the materialized path. See
p1.'),
101877
        'type' => 'int',
101977
        'unsigned' => TRUE,
102077
        'not null' => TRUE,
102177
        'default' => 0,
102277
      ),
1023
      'p5' => array(
102477
        'description' => t('The fifth mlid in the materialized path. See
p1.'),
102577
        'type' => 'int',
102677
        'unsigned' => TRUE,
102777
        'not null' => TRUE,
102877
        'default' => 0,
102977
      ),
1030
      'p6' => array(
103177
        'description' => t('The sixth mlid in the materialized path. See
p1.'),
103277
        'type' => 'int',
103377
        'unsigned' => TRUE,
103477
        'not null' => TRUE,
103577
        'default' => 0,
103677
      ),
1037
      'p7' => array(
103877
        'description' => t('The seventh mlid in the materialized path. See
p1.'),
103977
        'type' => 'int',
104077
        'unsigned' => TRUE,
104177
        'not null' => TRUE,
104277
        'default' => 0,
104377
      ),
1044
      'p8' => array(
104577
        'description' => t('The eighth mlid in the materialized path. See
p1.'),
104677
        'type' => 'int',
104777
        'unsigned' => TRUE,
104877
        'not null' => TRUE,
104977
        'default' => 0,
105077
      ),
1051
      'p9' => array(
105277
        'description' => t('The ninth mlid in the materialized path. See
p1.'),
105377
        'type' => 'int',
105477
        'unsigned' => TRUE,
105577
        'not null' => TRUE,
105677
        'default' => 0,
105777
      ),
1058
      'updated' => array(
105977
        'description' => t('Flag that indicates that this link was
generated during the update from Drupal 5.'),
106077
        'type' => 'int',
106177
        'not null' => TRUE,
106277
        'default' => 0,
106377
        'size' => 'small',
106477
      ),
106577
    ),
1066
    'indexes' => array(
106777
      'path_menu' => array(array('link_path', 128), 'menu_name'),
106877
      'menu_plid_expand_child' => array('menu_name', 'plid', 'expanded',
'has_children'),
106977
      'menu_parents' => array('menu_name', 'p1', 'p2', 'p3', 'p4', 'p5',
'p6', 'p7', 'p8', 'p9'),
107077
      'router_path' => array(array('router_path', 128)),
107177
    ),
107277
    'primary key' => array('mlid'),
1073
  );
1074
107577
  $schema['registry'] = array(
107677
    'description' => t("Each record is a function, class, or interface name
and the file it is in."),
1077
    'fields' => array(
1078
      'name'   => array(
107977
        'description' => t('The name of the function, class, or
interface.'),
108077
        'type' => 'varchar',
108177
        'length' => 255,
108277
        'not null' => TRUE,
108377
        'default' => '',
108477
      ),
1085
      'type'   => array(
108677
        'description' => t('Either function or class or interface.'),
108777
        'type' => 'varchar',
108877
        'length' => 9,
108977
        'not null' => TRUE,
109077
        'default' => '',
109177
      ),
1092
      'filename'   => array(
109377
        'description' => t('Name of the file.'),
109477
        'type' => 'varchar',
109577
        'length' => 255,
109677
        'not null' => TRUE,
109777
      ),
109877
    ),
109977
    'primary key' => array('name', 'type'),
1100
  );
1101
110277
  $schema['registry_file'] = array(
110377
    'description' => t("Files parsed to build the registry."),
1104
    'fields' => array(
1105
      'filename'   => array(
110677
        'description' => t('Path to the file.'),
110777
        'type' => 'varchar',
110877
        'length' => 255,
110977
        'not null' => TRUE,
111077
      ),
1111
      'md5'  => array(
111277
        'description' => t("Md5 hash of the file's contents when last
parsed."),
111377
        'type' => 'varchar',
111477
        'length' => 32,
111577
        'not null' => TRUE,
111677
      ),
111777
    ),
111877
    'primary key' => array('filename'),
1119
  );
1120
112177
  $schema['sessions'] = array(
112277
    'description' => t("Drupal's session handlers read and write into the
sessions table. Each record represents a user session, either anonymous or
authenticated."),
1123
    'fields' => array(
1124
      'uid' => array(
112577
        'description' => t('The {users}.uid corresponding to a session, or
0 for anonymous user.'),
112677
        'type' => 'int',
112777
        'unsigned' => TRUE,
112877
        'not null' => TRUE,
112977
      ),
1130
      'sid' => array(
113177
        'description' => t("Primary key: A session ID. The value is
generated by PHP's Session API."),
113277
        'type' => 'varchar',
113377
        'length' => 64,
113477
        'not null' => TRUE,
113577
        'default' => '',
113677
      ),
1137
      'hostname' => array(
113877
        'description' => t('The IP address that last used this session ID
(sid).'),
113977
        'type' => 'varchar',
114077
        'length' => 128,
114177
        'not null' => TRUE,
114277
        'default' => '',
114377
      ),
1144
      'timestamp' => array(
114577
        'description' => t('The Unix timestamp when this session last
requested a page. Old records are purged by PHP automatically.'),
114677
        'type' => 'int',
114777
        'not null' => TRUE,
114877
        'default' => 0,
114977
      ),
1150
      'cache' => array(
115177
        'description' => t("The time of this user's last post. This is used
when the site has specified a minimum_cache_lifetime. See cache_get()."),
115277
        'type' => 'int',
115377
        'not null' => TRUE,
115477
        'default' => 0,
115577
      ),
1156
      'session' => array(
115777
        'description' => t('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.'),
115877
        'type' => 'text',
115977
        'not null' => FALSE,
116077
        'size' => 'big',
116177
      ),
116277
    ),
116377
    'primary key' => array('sid'),
1164
    'indexes' => array(
116577
      'timestamp' => array('timestamp'),
116677
      'uid' => array('uid'),
116777
    ),
1168
  );
1169
117077
  $schema['system'] = array(
117177
    'description' => t("A list of all modules, themes, and theme engines
that are or have been installed in Drupal's file system."),
1172
    'fields' => array(
1173
      'filename' => array(
117477
        'description' => t('The path of the primary file for this item,
relative to the Drupal root; e.g. modules/node/node.module.'),
117577
        'type' => 'varchar',
117677
        'length' => 255,
117777
        'not null' => TRUE,
117877
        'default' => '',
117977
      ),
1180
      'name' => array(
118177
        'description' => t('The name of the item; e.g. node.'),
118277
        'type' => 'varchar',
118377
        'length' => 255,
118477
        'not null' => TRUE,
118577
        'default' => '',
118677
      ),
1187
      'type' => array(
118877
        'description' => t('The type of the item, either module, theme, or
theme_engine.'),
118977
        'type' => 'varchar',
119077
        'length' => 255,
119177
        'not null' => TRUE,
119277
        'default' => '',
119377
      ),
1194
      'owner' => array(
119577
        'description' => t("A theme's 'parent' . Can be either a theme or
an engine."),
119677
        'type' => 'varchar',
119777
        'length' => 255,
119877
        'not null' => TRUE,
119977
        'default' => '',
120077
      ),
1201
      'status' => array(
120277
        'description' => t('Boolean indicating whether or not this item is
enabled.'),
120377
        'type' => 'int',
120477
        'not null' => TRUE,
120577
        'default' => 0,
120677
      ),
1207
      'throttle' => array(
120877
        'description' => t('Boolean indicating whether this item is
disabled when the throttle.module disables throttleable items.'),
120977
        'type' => 'int',
121077
        'not null' => TRUE,
121177
        'default' => 0,
121277
        'size' => 'tiny',
121377
      ),
1214
      'bootstrap' => array(
121577
        'description' => t("Boolean indicating whether this module is
loaded during Drupal's early bootstrapping phase (e.g. even before the page
cache is consulted)."),
121677
        'type' => 'int',
121777
        'not null' => TRUE,
121877
        'default' => 0,
121977
      ),
1220
      'schema_version' => array(
122177
        'description' => t("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."),
122277
        'type' => 'int',
122377
        'not null' => TRUE,
122477
        'default' => -1,
122577
        'size' => 'small',
122677
      ),
1227
      'weight' => array(
122877
        'description' => t("The order in which this module's hooks should
be invoked relative to other modules. Equal-weighted modules are ordered by
name."),
122977
        'type' => 'int',
123077
        'not null' => TRUE,
123177
        'default' => 0,
123277
      ),
1233
      'info' => array(
123477
        'description' => t("A serialized array containing information from
the module's .info file; keys can include name, description, package,
version, core, dependencies, dependents, and php."),
123577
        'type' => 'text',
123677
        'not null' => FALSE,
123777
      ),
123877
    ),
123977
    'primary key' => array('filename'),
1240
    'indexes' => array(
124177
      'modules' => array(array('type', 12), 'status', 'weight',
'filename'),
124277
      'bootstrap' => array(array('type', 12), 'status', 'bootstrap',
'weight', 'filename'),
124377
    ),
1244
  );
1245
124677
  $schema['url_alias'] = array(
124777
    'description' => t('A list of URL aliases for Drupal paths; a user may
visit either the source or destination path.'),
1248
    'fields' => array(
1249
      'pid' => array(
125077
        'description' => t('A unique path alias identifier.'),
125177
        'type' => 'serial',
125277
        'unsigned' => TRUE,
125377
        'not null' => TRUE,
125477
      ),
1255
      'src' => array(
125677
        'description' => t('The Drupal path this alias is for; e.g.
node/12.'),
125777
        'type' => 'varchar',
125877
        'length' => 128,
125977
        'not null' => TRUE,
126077
        'default' => '',
126177
      ),
1262
      'dst' => array(
126377
        'description' => t('The alias for this path; e.g.
title-of-the-story.'),
126477
        'type' => 'varchar',
126577
        'length' => 128,
126677
        'not null' => TRUE,
126777
        'default' => '',
126877
      ),
1269
      'language' => array(
127077
        'description' => t('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.'),
127177
        'type' => 'varchar',
127277
        'length' => 12,
127377
        'not null' => TRUE,
127477
        'default' => '',
127577
      ),
127677
    ),
1277
    'unique keys' => array(
127877
      'dst_language' => array('dst', 'language'),
127977
    ),
128077
    'primary key' => array('pid'),
1281
    'indexes' => array(
128277
      'src' => array('src'),
128377
    ),
1284
  );
1285
128677
  return $schema;
12870
}
1288
1289
// Updates for core.
1290
129180
function system_update_last_removed() {
12920
  return 1021;
12930
}
1294
1295
/**
1296
 * @defgroup updates-5.x-extra Extra system updates for 5.x
1297
 * @{
1298
 */
1299
1300
/**
1301
 * Add index on users created column.
1302
 */
130380
function system_update_1022() {
13040
  $ret = array();
13050
  db_add_index($ret, 'users', 'created', array('created'));
1306
  // Also appears as system_update_6004(). Ensure we don't update twice.
13070
  variable_set('system_update_1022', TRUE);
13080
  return $ret;
13090
}
1310
1311
/**
1312
 * @} End of "defgroup updates-5.x-extra"
1313
 */
1314
1315
/**
1316
 * @defgroup updates-5.x-to-6.x System updates from 5.x to 6.x
1317
 * @{
1318
 */
1319
1320
/**
1321
 * Remove auto_increment from {boxes} to allow adding custom blocks with
1322
 * visibility settings.
1323
 */
132480
function system_update_6000() {
13250
  $ret = array();
13260
  switch ($GLOBALS['db_type']) {
13270
    case 'mysql':
13280
    case 'mysqli':
13290
      $max = (int)db_result(db_query('SELECT MAX(bid) FROM {boxes}'));
13300
      $ret[] = update_sql('ALTER TABLE {boxes} CHANGE COLUMN bid bid int
NOT NULL');
13310
      $ret[] = update_sql("REPLACE INTO {sequences} VALUES ('{boxes}_bid',
$max)");
13320
      break;
13330
  }
13340
  return $ret;
13350
}
1336
1337
/**
1338
 * Add version id column to {term_node} to allow taxonomy module to use
revisions.
1339
 */
134080
function system_update_6001() {
13410
  $ret = array();
1342
1343
  // Add vid to term-node relation.  The schema says it is unsigned.
13440
  db_add_field($ret, 'term_node', 'vid', array('type' => 'int', 'unsigned'
=> TRUE, 'not null' => TRUE, 'default' => 0));
13450
  db_drop_primary_key($ret, 'term_node');
13460
  db_add_primary_key($ret, 'term_node', array('vid', 'tid', 'nid'));
13470
  db_add_index($ret, 'term_node', 'vid', array('vid'));
1348
13490
  db_query('UPDATE {term_node} t SET vid = (SELECT vid FROM {node} n WHERE
t.nid = n.nid)');
13500
  return $ret;
13510
}
1352
1353
/**
1354
 * Increase the maximum length of variable names from 48 to 128.
1355
 */
135680
function system_update_6002() {
13570
  $ret = array();
13580
  db_drop_primary_key($ret, 'variable');
13590
  db_change_field($ret, 'variable', 'name', 'name', array('type' =>
'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''));
13600
  db_add_primary_key($ret, 'variable', array('name'));
13610
  return $ret;
13620
}
1363
1364
/**
1365
 * Add index on comments status column.
1366
 */
136780
function system_update_6003() {
13680
  $ret = array();
13690
  db_add_index($ret, 'comments', 'status', array('status'));
13700
  return $ret;
13710
}
1372
1373
/**
1374
 * This update used to add an index on users created column (#127941).
1375
 * However, system_update_1022() does the same thing.  This update
1376
 * tried to detect if 1022 had already run but failed to do so,
1377
 * resulting in an "index already exists" error.
1378
 *
1379
 * Adding the index here is never necessary.  Sites installed before
1380
 * 1022 will run 1022, getting the update.  Sites installed on/after 1022
1381
 * got the index when the table was first created.  Therefore, this
1382
 * function is now a no-op.
1383
 */
138480
function system_update_6004() {
13850
  return array();
13860
}
1387
1388
/**
1389
 * Add language to url_alias table and modify indexes.
1390
 */
139180
function system_update_6005() {
13920
  $ret = array();
13930
  switch ($GLOBALS['db_type']) {
13940
    case 'pgsql':
13950
      db_add_column($ret, 'url_alias', 'language', 'varchar(12)',
array('default' => "''", 'not null' => TRUE));
1396
1397
      // As of system.install:1.85 (before the new language
1398
      // subsystem), new installs got a unique key named
1399
      // url_alias_dst_key on url_alias.dst.  Unfortunately,
1400
      // system_update_162 created a unique key inconsistently named
1401
      // url_alias_dst_idx on url_alias.dst (keys should have the _key
1402
      // suffix, indexes the _idx suffix).  Therefore, sites installed
1403
      // before system_update_162 have a unique key with a different
1404
      // name than sites installed after system_update_162().  Now, we
1405
      // want to drop the unique key on dst which may have either one
1406
      // of two names and create a new unique key on (dst, language).
1407
      // There is no way to know which key name exists so we have to
1408
      // drop both, causing an SQL error.  Thus, we just hide the
1409
      // error and only report the update_sql results that work.
14100
      $err = error_reporting(0);
14110
      $ret1 = update_sql('DROP INDEX {url_alias}_dst_idx');
14120
      if ($ret1['success']) {
14130
  $ret[] = $ret1;
14140
      }
14150
      $ret1 = array();
14160
      db_drop_unique_key($ret, 'url_alias', 'dst');
14170
      foreach ($ret1 as $r) {
14180
  if ($r['success']) {
14190
    $ret[] = $r;
14200
  }
14210
      }
14220
      error_reporting($err);
1423
14240
      $ret[] = update_sql('CREATE UNIQUE INDEX {url_alias}_dst_language_idx
ON {url_alias}(dst, language)');
14250
      break;
14260
    case 'mysql':
14270
    case 'mysqli':
14280
      $ret[] = update_sql("ALTER TABLE {url_alias} ADD language varchar(12)
NOT NULL default ''");
14290
      $ret[] = update_sql("ALTER TABLE {url_alias} DROP INDEX dst");
14300
      $ret[] = update_sql("ALTER TABLE {url_alias} ADD UNIQUE dst_language
(dst, language)");
14310
      break;
14320
  }
14330
  return $ret;
14340
}
1435
1436
/**
1437
 * Drop useless indices on node_counter table.
1438
 */
143980
function system_update_6006() {
14400
  $ret = array();
14410
  switch ($GLOBALS['db_type']) {
14420
    case 'pgsql':
14430
      $ret[] = update_sql('DROP INDEX {node_counter}_daycount_idx');
14440
      $ret[] = update_sql('DROP INDEX {node_counter}_totalcount_idx');
14450
      $ret[] = update_sql('DROP INDEX {node_counter}_timestamp_idx');
14460
      break;
14470
    case 'mysql':
14480
    case 'mysqli':
14490
      $ret[] = update_sql("ALTER TABLE {node_counter} DROP INDEX
daycount");
14500
      $ret[] = update_sql("ALTER TABLE {node_counter} DROP INDEX
totalcount");
14510
      $ret[] = update_sql("ALTER TABLE {node_counter} DROP INDEX
timestamp");
14520
      break;
14530
  }
14540
  return $ret;
14550
}
1456
1457
/**
1458
 * Change the severity column in the watchdog table to the new values.
1459
 */
146080
function system_update_6007() {
14610
  $ret = array();
14620
  $ret[] = update_sql("UPDATE {watchdog} SET severity = " . WATCHDOG_NOTICE
. " WHERE severity = 0");
14630
  $ret[] = update_sql("UPDATE {watchdog} SET severity = " .
WATCHDOG_WARNING . " WHERE severity = 1");
14640
  $ret[] = update_sql("UPDATE {watchdog} SET severity = " . WATCHDOG_ERROR
. " WHERE severity = 2");
14650
  return $ret;
14660
}
1467
1468
/**
1469
 * Add info files to themes.  The info and owner columns are added by
1470
 * update_fix_d6_requirements() in update.php to avoid a large number
1471
 * of error messages from update.php.  All we need to do here is copy
1472
 * description to owner and then drop description.
1473
 */
147480
function system_update_6008() {
14750
  $ret = array();
14760
  $ret[] = update_sql('UPDATE {system} SET owner = description');
14770
  db_drop_field($ret, 'system', 'description');
1478
1479
  // Rebuild system table contents.
14800
  module_rebuild_cache();
14810
  system_theme_data();
1482
14830
  return $ret;
14840
}
1485
1486
/**
1487
 * The PHP filter is now a separate module.
1488
 */
148980
function system_update_6009() {
14900
  $ret = array();
1491
1492
  // If any input format used the Drupal 5 PHP filter.
14930
  if (db_result(db_query("SELECT COUNT(format) FROM {filters} WHERE module
= 'filter' AND delta = 1"))) {
1494
    // Enable the PHP filter module.
14950
    $ret[] = update_sql("UPDATE {system} SET status = 1 WHERE name = 'php'
AND type = 'module'");
1496
    // Update the input filters.
14970
    $ret[] = update_sql("UPDATE {filters} SET delta = 0, module = 'php'
WHERE module = 'filter' AND delta = 1");
14980
  }
1499
1500
  // With the removal of the PHP evaluator filter, the deltas of the line
break
1501
  // and URL filter have changed.
15020
  $ret[] = update_sql("UPDATE {filters} SET delta = 1 WHERE module =
'filter' AND delta = 2");
15030
  $ret[] = update_sql("UPDATE {filters} SET delta = 2 WHERE module =
'filter' AND delta = 3");
1504
15050
  return $ret;
15060
}
1507
1508
/**
1509
 * Add variable replacement for watchdog messages.
1510
 *
1511
 * The variables field is NOT NULL and does not have a default value.
1512
 * Existing log messages should not be translated in the new system,
1513
 * so we insert 'N;' (serialize(NULL)) as the temporary default but
1514
 * then remove the default value to match the schema.
1515
 */
151680
function system_update_6010() {
15170
  $ret = array();
15180
  db_add_field($ret, 'watchdog', 'variables', array('type' => 'text',
'size' => 'big', 'not null' => TRUE, 'initial' => 'N;'));
15190
  return $ret;
15200
}
1521
1522
/**
1523
 * Add language support to nodes
1524
 */
152580
function system_update_6011() {
15260
  $ret = array();
15270
  switch ($GLOBALS['db_type']) {
15280
    case 'pgsql':
15290
      db_add_column($ret, 'node', 'language', 'varchar(12)',
array('default' => "''", 'not null' => TRUE));
15300
      break;
15310
    case 'mysql':
15320
    case 'mysqli':
15330
      $ret[] = update_sql("ALTER TABLE {node} ADD language varchar(12) NOT
NULL default ''");
15340
      break;
15350
  }
15360
  return $ret;
15370
}
1538
1539
/**
1540
 * Add serialized field to cache tables.  This is now handled directly
1541
 * by update.php, so this function is a no-op.
1542
 */
154380
function system_update_6012() {
15440
  return array();
15450
}
1546
1547
/**
1548
 * Rebuild cache data for theme system changes
1549
 */
155080
function system_update_6013() {
1551
  // Rebuild system table contents.
15520
  module_rebuild_cache();
15530
  system_theme_data();
1554
15550
  return array(array('success' => TRUE, 'query' => 'Cache rebuilt.'));
15560
}
1557
1558
/**
1559
 * Record that the installer is done, so it is not
1560
 * possible to run the installer on upgraded sites.
1561
 */
156280
function system_update_6014() {
15630
  variable_set('install_task', 'done');
1564
15650
  return array(array('success' => TRUE, 'query' =>
"variable_set('install_task')"));
15660
}
1567
1568
/**
1569
 * Add the form cache table.
1570
 */
157180
function system_update_6015() {
15720
  $ret = array();
1573
15740
  switch ($GLOBALS['db_type']) {
15750
    case 'pgsql':
15760
      $ret[] = update_sql("CREATE TABLE {cache_form} (
1577
        cid varchar(255) NOT NULL default '',
1578
        data bytea,
1579
        expire int NOT NULL default '0',
1580
        created int NOT NULL default '0',
1581
        headers text,
1582
        serialized smallint NOT NULL default '0',
1583
        PRIMARY KEY (cid)
15840
    )");
15850
      $ret[] = update_sql("CREATE INDEX {cache_form}_expire_idx ON
{cache_form} (expire)");
15860
      break;
15870
    case 'mysql':
15880
    case 'mysqli':
15890
      $ret[] = update_sql("CREATE TABLE {cache_form} (
1590
        cid varchar(255) NOT NULL default '',
1591
        data longblob,
1592
        expire int NOT NULL default '0',
1593
        created int NOT NULL default '0',
1594
        headers text,
1595
        serialized int(1) NOT NULL default '0',
1596
        PRIMARY KEY (cid),
1597
        INDEX expire (expire)
15980
      ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
15990
      break;
16000
  }
1601
16020
  return $ret;
16030
}
1604
1605
/**
1606
 * Make {node}'s primary key be nid, change nid,vid to a unique key.
1607
 * Add primary keys to block, filters, flood, permission, and
term_relation.
1608
 */
160980
function system_update_6016() {
16100
  $ret = array();
1611
16120
  switch ($GLOBALS['db_type']) {
16130
    case 'pgsql':
16140
      $ret[] = update_sql("ALTER TABLE {node} ADD CONSTRAINT
{node}_nid_vid_key UNIQUE (nid, vid)");
16150
      db_add_column($ret, 'blocks', 'bid', 'serial');
16160
      $ret[] = update_sql("ALTER TABLE {blocks} ADD PRIMARY KEY (bid)");
16170
      db_add_column($ret, 'filters', 'fid', 'serial');
16180
      $ret[] = update_sql("ALTER TABLE {filters} ADD PRIMARY KEY (fid)");
16190
      db_add_column($ret, 'flood', 'fid', 'serial');
16200
      $ret[] = update_sql("ALTER TABLE {flood} ADD PRIMARY KEY (fid)");
16210
      db_add_column($ret, 'permission', 'pid', 'serial');
16220
      $ret[] = update_sql("ALTER TABLE {permission} ADD PRIMARY KEY
(pid)");
16230
      db_add_column($ret, 'term_relation', 'trid', 'serial');
16240
      $ret[] = update_sql("ALTER TABLE {term_relation} ADD PRIMARY KEY
(trid)");
16250
      db_add_column($ret, 'term_synonym', 'tsid', 'serial');
16260
      $ret[] = update_sql("ALTER TABLE {term_synonym} ADD PRIMARY KEY
(tsid)");
16270
      break;
16280
    case 'mysql':
16290
    case 'mysqli':
16300
      $ret[] = update_sql('ALTER TABLE {node} ADD UNIQUE KEY nid_vid (nid,
vid)');
16310
      $ret[] = update_sql("ALTER TABLE {blocks} ADD bid int NOT NULL
AUTO_INCREMENT PRIMARY KEY");
16320
      $ret[] = update_sql("ALTER TABLE {filters} ADD fid int NOT NULL
AUTO_INCREMENT PRIMARY KEY");
16330
      $ret[] = update_sql("ALTER TABLE {flood} ADD fid int NOT NULL
AUTO_INCREMENT PRIMARY KEY");
16340
      $ret[] = update_sql("ALTER TABLE {permission} ADD pid int NOT NULL
AUTO_INCREMENT PRIMARY KEY");
16350
      $ret[] = update_sql("ALTER TABLE {term_relation} ADD trid int NOT
NULL AUTO_INCREMENT PRIMARY KEY");
16360
      $ret[] = update_sql("ALTER TABLE {term_synonym} ADD tsid int NOT NULL
AUTO_INCREMENT PRIMARY KEY");
16370
      break;
16380
  }
1639
16400
  return $ret;
16410
}
1642
1643
/**
1644
 * Rename settings related to user.module email notifications.
1645
 */
164680
function system_update_6017() {
16470
  $ret = array();
1648
  // Maps old names to new ones.
1649
  $var_names = array(
16500
    'admin'    => 'register_admin_created',
16510
    'approval' => 'register_pending_approval',
16520
    'welcome'  => 'register_no_approval_required',
16530
    'pass'     => 'password_reset',
16540
  );
16550
  foreach ($var_names as $old => $new) {
16560
    foreach (array('_subject', '_body') as $suffix) {
16570
      $old_name = 'user_mail_' . $old . $suffix;
16580
      $new_name = 'user_mail_' . $new . $suffix;
16590
      if ($old_val = variable_get($old_name, FALSE)) {
16600
        variable_set($new_name, $old_val);
16610
        variable_del($old_name);
16620
        $ret[] = array('success' => TRUE, 'query' =>
"variable_set($new_name)");
16630
        $ret[] = array('success' => TRUE, 'query' =>
"variable_del($old_name)");
16640
        if ($old_name == 'user_mail_approval_body') {
16650
          drupal_set_message('Saving an old value of the welcome message
body for users that are pending administrator approval. However, you should
consider modifying this text, since Drupal can now be configured to
automatically notify users and send them their login information when their
accounts are approved. See the <a href="' . url('admin/user/settings') .
'">User settings</a> page for details.');
16660
        }
16670
      }
16680
    }
16690
  }
16700
  return $ret;
16710
}
1672
1673
/**
1674
 * Add HTML corrector to HTML formats or replace the old module if it was
in use.
1675
 */
167680
function system_update_6018() {
16770
  $ret = array();
1678
1679
  // Disable htmlcorrector.module, if it exists and replace its filter.
16800
  if (module_exists('htmlcorrector')) {
16810
    module_disable(array('htmlcorrector'));
16820
    $ret[] = update_sql("UPDATE {filter_formats} SET module = 'filter',
delta = 3 WHERE module = 'htmlcorrector'");
16830
    $ret[] = array('success' => TRUE, 'query' => 'HTML Corrector module was
disabled; this functionality has now been added to core.');
16840
    return $ret;
16850
  }
1686
1687
  // Otherwise, find any format with 'HTML' in its name and add the filter
at the end.
16880
  $result = db_query("SELECT format, name FROM {filter_formats} WHERE name
LIKE '%HTML%'");
16890
  while ($format = db_fetch_object($result)) {
16900
    $weight = db_result(db_query("SELECT MAX(weight) FROM {filters} WHERE
format = %d", $format->format));
16910
    db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES
(%d, '%s', %d, %d)", $format->format, 'filter', 3, max(10, $weight + 1));
16920
    $ret[] = array('success' => TRUE, 'query' => "HTML corrector filter
added to the '" . $format->name . "' input format.");
16930
  }
1694
16950
  return $ret;
16960
}
1697
1698
/**
1699
 * Reconcile small differences in the previous, manually created mysql
1700
 * and pgsql schemas so they are the same and can be represented by a
1701
 * single schema structure.
1702
 *
1703
 * Note that the mysql and pgsql cases make different changes.  This
1704
 * is because each schema needs to be tweaked in different ways to
1705
 * conform to the new schema structure.  Also, since they operate on
1706
 * tables defined by many optional core modules which may not ever
1707
 * have been installed, they must test each table for existence.  If
1708
 * the modules are first installed after this update exists the tables
1709
 * will be created from the schema structure and will start out
1710
 * correct.
1711
 */
171280
function system_update_6019() {
17130
  $ret = array();
1714
17150
  switch ($GLOBALS['db_type']) {
17160
    case 'pgsql':
1717
      // Remove default ''.
17180
      if (db_table_exists('aggregator_feed')) {
17190
        db_field_set_no_default($ret, 'aggregator_feed', 'description');
17200
        db_field_set_no_default($ret, 'aggregator_feed', 'image');
17210
      }
17220
      db_field_set_no_default($ret, 'blocks', 'pages');
17230
      if (db_table_exists('contact')) {
17240
        db_field_set_no_default($ret, 'contact', 'recipients');
17250
        db_field_set_no_default($ret, 'contact', 'reply');
17260
      }
17270
      db_field_set_no_default($ret, 'watchdog', 'location');
17280
      db_field_set_no_default($ret, 'node_revisions', 'body');
17290
      db_field_set_no_default($ret, 'node_revisions', 'teaser');
17300
      db_field_set_no_default($ret, 'node_revisions', 'log');
1731
1732
      // Update from pgsql 'float' (which means 'double precision') to
1733
      // schema 'float' (which in pgsql means 'real').
17340
      if (db_table_exists('search_index')) {
17350
        db_change_field($ret, 'search_index', 'score', 'score',
array('type' => 'float'));
17360
      }
17370
      if (db_table_exists('search_total')) {
17380
        db_change_field($ret, 'search_total', 'count', 'count',
array('type' => 'float'));
17390
      }
1740
1741
      // Replace unique index dst_language with a unique constraint.  The
1742
      // result is the same but the unique key fits our current schema
1743
      // structure.  Also, the postgres documentation implies that
1744
      // unique constraints are preferable to unique indexes.  See
1745
      //
http://www.postgresql.org/docs/8.2/interactive/indexes-unique.html.
17460
      if (db_table_exists('url_alias')) {
17470
        db_drop_index($ret, 'url_alias', 'dst_language');
17480
        db_add_unique_key($ret, 'url_alias', 'dst_language',
17490
          array('dst', 'language'));
17500
      }
1751
1752
      // Fix term_node pkey: mysql and pgsql code had different orders.
17530
      if (db_table_exists('term_node')) {
17540
        db_drop_primary_key($ret, 'term_node');
17550
        db_add_primary_key($ret, 'term_node', array('vid', 'tid', 'nid'));
17560
      }
1757
1758
      // Make boxes.bid unsigned.
17590
      db_drop_primary_key($ret, 'boxes');
17600
      db_change_field($ret, 'boxes', 'bid', 'bid', array('type' =>
'serial', 'unsigned' => TRUE, 'not null' => TRUE), array('primary key' =>
array('bid')));
1761
1762
      // Fix primary key
17630
      db_drop_primary_key($ret, 'node');
17640
      db_add_primary_key($ret, 'node', array('nid'));
1765
17660
      break;
1767
17680
    case 'mysql':
17690
    case 'mysqli':
1770
      // Rename key 'link' to 'url'.
17710
      if (db_table_exists('aggregator_feed')) {
17720
        db_drop_unique_key($ret, 'aggregator_feed', 'link');
17730
        db_add_unique_key($ret, 'aggregator_feed', 'url', array('url'));
17740
      }
1775
1776
      // Change to size => small.
17770
      if (db_table_exists('boxes')) {
17780
        db_change_field($ret, 'boxes', 'format', 'format', array('type' =>
'int', 'size' => 'small', 'not null' => TRUE, 'default' => 0));
17790
      }
1780
1781
      // Change to size => small.
1782
      // Rename index 'lid' to 'nid'.
17830
      if (db_table_exists('comments')) {
17840
        db_change_field($ret, 'comments', 'format', 'format', array('type'
=> 'int', 'size' => 'small', 'not null' => TRUE, 'default' => 0));
17850
        db_drop_index($ret, 'comments', 'lid');
17860
        db_add_index($ret, 'comments', 'nid', array('nid'));
17870
      }
1788
1789
      // Change to size => small.
17900
      db_change_field($ret, 'cache', 'serialized', 'serialized',
array('type' => 'int', 'size' => 'small', 'not null' => TRUE, 'default' =>
0));
17910
      db_change_field($ret, 'cache_filter', 'serialized', 'serialized',
array('type' => 'int', 'size' => 'small', 'not null' => TRUE, 'default' =>
0));
17920
      db_change_field($ret, 'cache_page', 'serialized', 'serialized',
array('type' => 'int', 'size' => 'small', 'not null' => TRUE, 'default' =>
0));
17930
      db_change_field($ret, 'cache_form', 'serialized', 'serialized',
array('type' => 'int', 'size' => 'small', 'not null' => TRUE, 'default' =>
0));
1794
1795
      // Remove default => 0, set auto increment.
17960
      $new_uid = 1 + db_result(db_query('SELECT MAX(uid) FROM {users}'));
17970
      $ret[] = update_sql('UPDATE {users} SET uid = ' . $new_uid . ' WHERE
uid = 0');
17980
      db_drop_primary_key($ret, 'users');
17990
      db_change_field($ret, 'users', 'uid', 'uid', array('type' =>
'serial', 'unsigned' => TRUE, 'not null' => TRUE), array('primary key' =>
array('uid')));
18000
      $ret[] = update_sql('UPDATE {users} SET uid = 0 WHERE uid = ' .
$new_uid);
1801
1802
      // Special field names.
18030
      $map = array('node_revisions' => 'vid');
1804
      // Make sure these tables have proper auto_increment fields.
18050
      foreach (array('boxes', 'files', 'node', 'node_revisions') as $table)
{
18060
        $field = isset($map[$table]) ? $map[$table] : $table[0] . 'id';
18070
        db_drop_primary_key($ret, $table);
18080
        db_change_field($ret, $table, $field, $field, array('type' =>
'serial', 'unsigned' => TRUE, 'not null' => TRUE), array('primary key' =>
array($field)));
18090
      }
1810
18110
      break;
18120
  }
1813
18140
  return $ret;
18150
}
1816
1817
/**
1818
 * Create the tables for the new menu system.
1819
 */
182080
function system_update_6020() {
18210
  $ret = array();
1822
18230
  $schema['menu_router'] = array(
1824
    'fields' => array(
18250
      'path'             => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18260
      'load_functions'   => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18270
      'to_arg_functions' => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18280
      'access_callback'  => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18290
      'access_arguments' => array('type' => 'text', 'not null' => FALSE),
18300
      'page_callback'    => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18310
      'page_arguments'   => array('type' => 'text', 'not null' => FALSE),
18320
      'fit'              => array('type' => 'int', 'not null' => TRUE,
'default' => 0),
18330
      'number_parts'     => array('type' => 'int', 'not null' => TRUE,
'default' => 0, 'size' => 'small'),
18340
      'tab_parent'       => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18350
      'tab_root'         => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18360
      'title'            => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18370
      'title_callback'   => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18380
      'title_arguments'  => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18390
      'type'             => array('type' => 'int', 'not null' => TRUE,
'default' => 0),
18400
      'block_callback'   => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18410
      'description'      => array('type' => 'text', 'not null' => TRUE),
18420
      'position'         => array('type' => 'varchar', 'length' => 255,
'not null' => TRUE, 'default' => ''),
18430
      'weight'           => array('type' => 'int', 'not null' => TRUE,
'default' => 0),
18440
      'file'             => array('type' => 'text', 'size' => 'medium')
18450
    ),
1846
    'indexes' => array(
18470
      'fit'        => array('fit'),
18480
      'tab_parent' => array('tab_parent')
18490
    ),
18500
    'primary key' => array('path'),
1851
  );
1852
18530
  $schema['menu_links'] = array(
1854
    'fields' => array(
18550
      'menu_name'    => array('type' => 'varchar', 'length' => 32, 'not
null' => TRUE, 'default' => ''),
18560
      'mlid'         => array('type' => 'serial', 'unsigned' => TRUE, 'not
null' => TRUE),
18570
      'plid'         => array('type' => 'int', 'unsigned' => TRUE, 'not
null' => TRUE, 'default' => 0),
18580
      'link_path'    => array('type' => 'varchar', 'length' => 255, 'not
null' => TRUE, 'default' => ''),
18590
      'router_path'  => array('type' => 'varchar', 'length' => 255, 'not
null' => TRUE, 'default' => ''),
18600
      'link_title'   => array('type' => 'varchar', 'length' => 255, 'not
null' => TRUE, 'default' => ''),
18610
      'options'      => array('type' => 'text', 'not null' => FALSE),
18620
      'module'       => array('type' => 'varchar', 'length' => 255, 'not
null' => TRUE, 'default' => 'system'),
18630
      'hidden'       => array('type' => 'int', 'not null' => TRUE,
'default' => 0, 'size' => 'small'),
18640
      'external'     => array('type' => 'int', 'not null' => TRUE,
'default' => 0, 'size' => 'small'),
18650
      'has_children' => array('type' => 'int', 'not null' => TRUE,
'default' => 0, 'size' => 'small'),
18660
      'expanded'     => array('type' => 'int', 'not null' => TRUE,
'default' => 0, 'size' => 'small'),
18670
      'weight'       => array('type' => 'int', 'not null' => TRUE,
'default' => 0),
18680
      'depth'        => array('type' => 'int', 'not null' => TRUE,
'default' => 0, 'size' => 'small'),
18690
      'customized'   => array('type' => 'int', 'not null' => TRUE,
'default' => 0, 'size' => 'small'),
18700
      'p1'           => array('type' => 'int', 'unsigned' => TRUE, 'not
null' => TRUE, 'default' => 0),
18710
      'p2'           => array('type' => 'int', 'unsigned' => TRUE, 'not
null' => TRUE, 'default' => 0),
18720
      'p3'           => array('type' => 'int', 'unsigned' => TRUE, 'not
null' => TRUE, 'default' => 0),
18730
      'p4'           => array('type' => 'int', 'unsigned' => TRUE, 'not
null' => TRUE, 'default' => 0),
18740
      'p5'           => array('type' => 'int', 'unsigned' => TRUE, 'not
null' => TRUE, 'default' => 0),
18750
      'p6'           => array('type' => 'int', 'unsigned' => TRUE, 'not
null' => TRUE, 'default' => 0),
18760
      'p7'           => array('type' => 'int', 'unsigned' => TRUE, 'not
null' => TRUE, 'default' => 0),
18770
      'p8'           => array('type' => 'int', 'unsigned' => TRUE, 'not
null' => TRUE, 'default' => 0),
18780
      'p9'           => array('type' => 'int', 'unsigned' => TRUE, 'not
null' => TRUE, 'default' => 0),
18790
      'updated'      => array('type' => 'int', 'not null' => TRUE,
'default' => 0, 'size' => 'small'),
18800
    ),
1881
    'indexes' => array(
18820
      'path_menu'              => array(array('link_path', 128),
'menu_name'),
18830
      'menu_plid_expand_child' => array('menu_name', 'plid', 'expanded',
'has_children'),
18840
      'menu_parents'           => array('menu_name', 'p1', 'p2', 'p3',
'p4', 'p5', 'p6', 'p7', 'p8', 'p9'),
18850
      'router_path'            => array(array('router_path', 128)),
18860
    ),
18870
    'primary key' => array('mlid'),
1888
  );
1889
18900
  foreach ($schema as $name => $table) {
18910
    db_create_table($ret, $name, $table);
18920
  }
18930
  return $ret;
18940
}
1895
1896
/**
1897
 * Migrate the menu items from the old menu system to the new menu_links
table.
1898
 */
189980
function system_update_6021() {
19000
  $ret = array('#finished' => 0);
1901
  $menus = array(
1902
    'navigation' => array(
19030
      'menu_name' => 'navigation',
19040
      'title' => 'Navigation',
19050
      'description' => 'The navigation menu is provided by Drupal and is
the main interactive menu for any site. It is usually the only menu that
contains personalized links for authenticated users, and is often not even
visible to anonymous users.',
19060
    ),
1907
    'primary-links' => array(
19080
      'menu_name' => 'primary-links',
19090
      'title' => 'Primary links',
19100
      'description' => 'Primary links are often used at the theme layer to
show the major sections of a site. A typical representation for primary
links would be tabs along the top.',
19110
    ),
1912
    'secondary-links' => array(
19130
      'menu_name' => 'secondary-links',
19140
      'title' => 'Secondary links',
19150
      'description' => 'Secondary links are often used for pages like legal
notices, contact details, and other secondary navigation items that play a
lesser role than primary links.',
19160
    ),
19170
  );
1918
  // Multi-part update
19190
  if (!isset($_SESSION['system_update_6021'])) {
19200
    db_add_field($ret, 'menu', 'converted', array('type' => 'int',
'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, 'size' =>
'tiny'));
19210
    $_SESSION['system_update_6021_max'] = db_result(db_query('SELECT
COUNT(*) FROM {menu}'));
19220
    $_SESSION['menu_menu_map'] = array(1 => 'navigation');
1923
    // 0 => FALSE is for new menus, 1 => FALSE is for the navigation.
19240
    $_SESSION['menu_item_map'] = array(0 => FALSE, 1 => FALSE);
1925
    $table = array(
1926
      'fields' => array(
19270
        'menu_name'   => array('type' => 'varchar', 'length' => 32, 'not
null' => TRUE, 'default' => ''),
19280
        'title'       => array('type' => 'varchar', 'length' => 255, 'not
null' => TRUE, 'default' => ''),
19290
        'description' => array('type' => 'text', 'not null' => FALSE),
19300
      ),
19310
      'primary key' => array('menu_name'),
19320
    );
19330
    db_create_table($ret, 'menu_custom', $table);
19340
    db_query("INSERT INTO {menu_custom} (menu_name, title, description)
VALUES ('%s', '%s', '%s')", $menus['navigation']);
19350
    $_SESSION['system_update_6021'] = 0;
19360
  }
1937
19380
  $limit = 50;
19390
  while ($limit-- && ($item = db_fetch_array(db_query_range('SELECT * FROM
{menu} WHERE converted = 0', 0, 1)))) {
1940
    // If it's not a menu...
19410
    if ($item['pid']) {
1942
      // Let's climb up until we find an item with a converted parent.
19430
      $item_original = $item;
19440
      while ($item && !isset($_SESSION['menu_item_map'][$item['pid']])) {
19450
        $item = db_fetch_array(db_query('SELECT * FROM {menu} WHERE mid =
%d', $item['pid']));
19460
      }
1947
      // This can only occur if the menu entry is a leftover in the menu
table.
1948
      // These do not appear in Drupal 5 anyways, so we skip them.
19490
      if (!$item) {
19500
        db_query('UPDATE {menu} SET converted = %d WHERE mid = %d', 1,
$item_original['mid']);
19510
        $_SESSION['system_update_6021']++;
19520
        continue;
19530
      }
19540
    }
1955
    // We need to recheck because item might have changed.
19560
    if ($item['pid']) {
1957
      // Fill the new fields.
19580
      $item['link_title'] = $item['title'];
19590
      $item['link_path'] = drupal_get_normal_path($item['path']);
1960
      // We know the parent is already set. If it's not FALSE then it's an
item.
19610
      if ($_SESSION['menu_item_map'][$item['pid']]) {
1962
        // The new menu system parent link id.
19630
        $item['plid'] = $_SESSION['menu_item_map'][$item['pid']]['mlid'];
1964
        // The new menu system menu name.
19650
        $item['menu_name'] =
$_SESSION['menu_item_map'][$item['pid']]['menu_name'];
19660
      }
1967
      else {
1968
        // This a top level element.
19690
        $item['plid'] = 0;
1970
        // The menu name is stored among the menus.
19710
        $item['menu_name'] = $_SESSION['menu_menu_map'][$item['pid']];
1972
      }
1973
      // Is the element visible in the menu block?
19740
      $item['hidden'] = !($item['type'] & MENU_VISIBLE_IN_TREE);
1975
      // Is it a custom(ized) element?
19760
      if ($item['type'] & (MENU_CREATED_BY_ADMIN | MENU_MODIFIED_BY_ADMIN))
{
19770
        $item['customized'] = TRUE;
19780
      }
1979
      // Items created via the menu module need to be assigned to it.
19800
      if ($item['type'] & MENU_CREATED_BY_ADMIN) {
19810
        $item['module'] = 'menu';
19820
        $item['router_path'] = '';
19830
        $item['updated'] = TRUE;
19840
      }
1985
      else {
19860
        $item['module'] = 'system';
19870
        $item['router_path'] = $item['path'];
19880
        $item['updated'] = FALSE;
1989
      }
1990
      // Save the link.
19910
      menu_link_save($item);
19920
      $_SESSION['menu_item_map'][$item['mid']] = array('mlid' =>
$item['mlid'], 'menu_name' => $item['menu_name']);
19930
    }
19940
    elseif (!isset($_SESSION['menu_menu_map'][$item['mid']])) {
19950
      $item['menu_name'] = 'menu-' . preg_replace('/[^a-zA-Z0-9]/', '-',
strtolower($item['title']));
19960
      $item['menu_name'] = substr($item['menu_name'], 0, 20);
19970
      $original_menu_name = $item['menu_name'];
19980
      $i = 0;
19990
      while (db_result(db_query("SELECT menu_name FROM {menu_custom} WHERE
menu_name = '%s'", $item['menu_name']))) {
20000
        $item['menu_name'] = $original_menu_name . ($i++);
20010
      }
20020
      if ($item['path']) {
2003
        // Another bunch of bogus entries. Apparently, these are leftovers
2004
        // from Drupal 4.7 .
20050
        $_SESSION['menu_bogus_menus'][] = $item['menu_name'];
20060
      }
2007
      else {
2008
        // Add this menu to the list of custom menus.
20090
        db_query("INSERT INTO {menu_custom} (menu_name, title, description)
VALUES ('%s', '%s', '')", $item['menu_name'], $item['title']);
2010
      }
20110
      $_SESSION['menu_menu_map'][$item['mid']] = $item['menu_name'];
20120
      $_SESSION['menu_item_map'][$item['mid']] = FALSE;
20130
    }
20140
    db_query('UPDATE {menu} SET converted = %d WHERE mid = %d', 1,
$item['mid']);
20150
    $_SESSION['system_update_6021']++;
20160
  }
2017
20180
  if ($_SESSION['system_update_6021'] >=
$_SESSION['system_update_6021_max']) {
20190
    if (!empty($_SESSION['menu_bogus_menus'])) {
2020
      // Remove entries in bogus menus. This is secure because we deleted
2021
      // every non-alpanumeric character from the menu name.
20220
      $ret[] = update_sql("DELETE FROM {menu_links} WHERE menu_name IN ('"
. implode("', '", $_SESSION['menu_bogus_menus']) . "')");
20230
    }
2024
20250
    $menu_primary_menu = variable_get('menu_primary_menu', 0);
2026
    // Ensure that we wind up with a system menu named 'primary-links'.
20270
    if (isset($_SESSION['menu_menu_map'][2])) {
2028
      // The primary links menu that ships with Drupal 5 has mid = 2.  If
this
2029
      // menu hasn't been deleted by the site admin, we use that.
20300
      $updated_primary_links_menu = 2;
20310
    }
20320
    elseif (isset($_SESSION['menu_menu_map'][$menu_primary_menu]) &&
$menu_primary_menu > 1) {
2033
      // Otherwise, we use the menu that is currently assigned to the
primary
2034
      // links region of the theme, as long as it exists and isn't the
2035
      // Navigation menu.
20360
      $updated_primary_links_menu = $menu_primary_menu;
20370
    }
2038
    else {
2039
      // As a last resort, create 'primary-links' as a new menu.
20400
      $updated_primary_links_menu = 0;
20410
      db_query("INSERT INTO {menu_custom} (menu_name, title, description)
VALUES ('%s', '%s', '%s')", $menus['primary-links']);
2042
    }
2043
20440
    if ($updated_primary_links_menu) {
2045
      // Change the existing menu name to 'primary-links'.
20460
      $replace = array('%new_name' => 'primary-links', '%desc' =>
$menus['primary-links']['description'], '%old_name' =>
$_SESSION['menu_menu_map'][$updated_primary_links_menu]);
20470
      $ret[] = update_sql(strtr("UPDATE {menu_custom} SET menu_name =
'%new_name', description = '%desc' WHERE menu_name = '%old_name'",
$replace));
20480
      $ret[] = update_sql("UPDATE {menu_links} SET menu_name =
'primary-links' WHERE menu_name = '" .
$_SESSION['menu_menu_map'][$updated_primary_links_menu] . "'");
20490
      $_SESSION['menu_menu_map'][$updated_primary_links_menu] =
'primary-links';
20500
    }
2051
20520
    $menu_secondary_menu = variable_get('menu_secondary_menu', 0);
2053
    // Ensure that we wind up with a system menu named 'secondary-links'.
20540
    if (isset($_SESSION['menu_menu_map'][$menu_secondary_menu]) &&
$menu_secondary_menu > 1 && $menu_secondary_menu !=
$updated_primary_links_menu) {
2055
      // We use the menu that is currently assigned to the secondary links
2056
      // region of the theme, as long as (a) it exists, (b) it isn't the
2057
      // Navigation menu, (c) it isn't the same menu we assigned as the
2058
      // system 'primary-links' menu above, and (d) it isn't the same menu
2059
      // assigned to the primary links region of the theme.
20600
      $updated_secondary_links_menu = $menu_secondary_menu;
20610
    }
2062
    else {
2063
      // Otherwise, create 'secondary-links' as a new menu.
20640
      $updated_secondary_links_menu = 0;
20650
      db_query("INSERT INTO {menu_custom} (menu_name, title, description)
VALUES ('%s', '%s', '%s')", $menus['secondary-links']);
2066
    }
2067
20680
    if ($updated_secondary_links_menu) {
2069
      // Change the existing menu name to 'secondary-links'.
20700
      $replace = array('%new_name' => 'secondary-links', '%desc' =>
$menus['secondary-links']['description'], '%old_name' =>
$_SESSION['menu_menu_map'][$updated_secondary_links_menu]);
20710
      $ret[] = update_sql(strtr("UPDATE {menu_custom} SET menu_name =
'%new_name', description = '%desc' WHERE menu_name = '%old_name'",
$replace));
20720
      $ret[] = update_sql("UPDATE {menu_links} SET menu_name =
'secondary-links' WHERE menu_name = '" .
$_SESSION['menu_menu_map'][$updated_secondary_links_menu] . "'");
20730
      $_SESSION['menu_menu_map'][$updated_secondary_links_menu] =
'secondary-links';
20740
    }
2075
2076
    // Update menu OTF preferences.
20770
    $mid = variable_get('menu_parent_items', 0);
20780
    $menu_name = ($mid && isset($_SESSION['menu_menu_map'][$mid])) ?
$_SESSION['menu_menu_map'][$mid] : 'navigation';
20790
    variable_set('menu_default_node_menu', $menu_name);
20800
    variable_del('menu_parent_items');
2081
2082
    // Update the source of the primary and secondary links.
20830
    $menu_name = ($menu_primary_menu &&
isset($_SESSION['menu_menu_map'][$menu_primary_menu])) ?
$_SESSION['menu_menu_map'][$menu_primary_menu] : '';
20840
    variable_set('menu_primary_links_source', $menu_name);
20850
    variable_del('menu_primary_menu');
2086
20870
    $menu_name = ($menu_secondary_menu &&
isset($_SESSION['menu_menu_map'][$menu_secondary_menu])) ?
$_SESSION['menu_menu_map'][$menu_secondary_menu] : '';
20880
    variable_set('menu_secondary_links_source', $menu_name);
20890
    variable_del('menu_secondary_menu');
2090
2091
    // Skip the navigation menu - it is handled by the user module.
20920
    unset($_SESSION['menu_menu_map'][1]);
2093
    // Update the deltas for all menu module blocks.
20940
    foreach ($_SESSION['menu_menu_map'] as $mid => $menu_name) {
2095
      // This is again secure because we deleted every non-alpanumeric
2096
      // character from the menu name.
20970
      $ret[] = update_sql("UPDATE {blocks} SET delta = '" . $menu_name . "'
WHERE module = 'menu' AND delta = '" . $mid . "'");
20980
      $ret[] = update_sql("UPDATE {blocks_roles} SET delta = '" .
$menu_name . "' WHERE module = 'menu' AND delta = '" . $mid . "'");
20990
    }
21000
    $ret[] = array('success' => TRUE, 'query' => 'Relocated ' .
$_SESSION['system_update_6021'] . ' existing items to the new menu
system.');
21010
    $ret[] = update_sql("DROP TABLE {menu}");
21020
    unset($_SESSION['system_update_6021'],
$_SESSION['system_update_6021_max'], $_SESSION['menu_menu_map'],
$_SESSION['menu_item_map'], $_SESSION['menu_bogus_menus']);
2103
    // Create the menu overview links - also calls menu_rebuild(). If menu
is
2104
    // disabled, then just call menu_rebuild.
21050
    if (function_exists('menu_enable')) {
21060
      menu_enable();
21070
    }
2108
    else {
21090
      menu_rebuild();
2110
    }
21110
    $ret['#finished'] = 1;
21120
  }
2113
  else {
21140
    $ret['#finished'] = $_SESSION['system_update_6021'] /
$_SESSION['system_update_6021_max'];
2115
  }
21160
  return $ret;
21170
}
2118
2119
/**
2120
 * Update files tables to associate files to a uid by default instead of a
nid.
2121
 * Rename file_revisions to upload since it should only be used by the
upload
2122
 * module used by upload to link files to nodes.
2123
 */
212480
function system_update_6022() {
21250
  $ret = array();
2126
2127
  // Rename the nid field to vid, add status and timestamp fields, and
indexes.
21280
  db_drop_index($ret, 'files', 'nid');
21290
  db_change_field($ret, 'files', 'nid', 'uid', array('type' => 'int',
'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0));
21300
  db_add_field($ret, 'files', 'status', array('type' => 'int', 'not null'
=> TRUE, 'default' => 0));
21310
  db_add_field($ret, 'files', 'timestamp', array('type' => 'int',
'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0));
21320
  db_add_index($ret, 'files', 'uid', array('uid'));
21330
  db_add_index($ret, 'files', 'status', array('status'));
21340
  db_add_index($ret, 'files', 'timestamp', array('timestamp'));
2135
2136
  // Rename the file_revisions table to upload then add nid column. Since
we're
2137
  // changing the table name we need to drop and re-add the indexes and
2138
  // the primary key so both mysql and pgsql end up with the correct index
2139
  // names.
21400
  db_drop_primary_key($ret, 'file_revisions');
21410
  db_drop_index($ret, 'file_revisions', 'vid');
21420
  db_rename_table($ret, 'file_revisions', 'upload');
21430
  db_add_field($ret, 'upload', 'nid', array('type' => 'int', 'unsigned' =>
TRUE, 'not null' => TRUE, 'default' => 0));
21440
  db_add_index($ret, 'upload', 'nid', array('nid'));
21450
  db_add_primary_key($ret, 'upload', array('vid', 'fid'));
21460
  db_add_index($ret, 'upload', 'fid', array('fid'));
2147
2148
  // The nid column was renamed to uid. Use the old nid to find the node's
uid.
21490
  update_sql('UPDATE {files} SET uid = (SELECT n.uid FROM {node} n WHERE
{files}.uid = n.nid)');
21500
  update_sql('UPDATE {upload} SET nid = (SELECT r.nid FROM {node_revisions}
r WHERE {upload}.vid = r.vid)');
2151
2152
  // Mark all existing files as FILE_STATUS_PERMANENT.
21530
  $ret[] = update_sql('UPDATE {files} SET status = 1');
2154
21550
  return $ret;
21560
}
2157
215880
function system_update_6023() {
21590
  $ret = array();
2160
2161
  // nid is DEFAULT 0
21620
  db_drop_index($ret, 'node_revisions', 'nid');
21630
  db_change_field($ret, 'node_revisions', 'nid', 'nid', array('type' =>
'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0));
21640
  db_add_index($ret, 'node_revisions', 'nid', array('nid'));
21650
  return $ret;
21660
}
2167
2168
/**
2169
 * Add translation fields to nodes used by translation module.
2170
 */
217180
function system_update_6024() {
21720
  $ret = array();
21730
  db_add_field($ret, 'node', 'tnid', array('type' => 'int', 'unsigned' =>
TRUE, 'not null' => TRUE, 'default' => 0));
21740
  db_add_field($ret, 'node', 'translate', array('type' => 'int', 'not null'
=> TRUE, 'default' => 0));
21750
  db_add_index($ret, 'node', 'tnid', array('tnid'));
21760
  db_add_index($ret, 'node', 'translate', array('translate'));
21770
  return $ret;
21780
}
2179
2180
/**
2181
 * Increase the maximum length of node titles from 128 to 255.
2182
 */
218380
function system_update_6025() {
21840
  $ret = array();
21850
  db_drop_index($ret, 'node', 'node_title_type');
21860
  db_change_field($ret, 'node', 'title', 'title', array('type' =>
'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''));
21870
  db_add_index($ret, 'node', 'node_title_type', array('title',
array('type', 4)));
21880
  db_change_field($ret, 'node_revisions', 'title', 'title', array('type' =>
'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''));
21890
  return $ret;
21900
}
2191
2192
/**
2193
 * Display warning about new Update status module.
2194
 */
219580
function system_update_6026() {
21960
  $ret = array();
2197
2198
  // Notify user that new update module exists.
21990
  drupal_set_message('Drupal can check periodically for important bug fixes
and security releases using the new update status module. This module can
be turned on from the <a href="' . url('admin/build/modules') . '">modules
administration page</a>. For more information please read the <a
href="http://drupal.org/handbook/modules/update">Update status handbook
page</a>.');
2200
22010
  return $ret;
22020
}
2203
2204
/**
2205
 * Add block cache.
2206
 */
220780
function system_update_6027() {
22080
  $ret = array();
2209
2210
  // Create the blocks.cache column.
22110
  db_add_field($ret, 'blocks', 'cache', array('type' => 'int', 'not null'
=> TRUE, 'default' => 1, 'size' => 'tiny'));
2212
2213
  // The cache_block table is created in update_fix_d6_requirements()
since
2214
  // calls to cache_clear_all() would otherwise cause warnings.
2215
2216
  // Fill in the values for the new 'cache' column in the {blocks} table.
22170
  foreach (module_list() as $module) {
22180
    if ($module_blocks = module_invoke($module, 'block', 'list')) {
22190
      foreach ($module_blocks as $delta => $block) {
22200
        if (isset($block['cache'])) {
22210
          db_query("UPDATE {blocks} SET cache = %d WHERE module = '%s' AND
delta = %d", $block['cache'], $module, $delta);
22220
        }
22230
      }
22240
    }
22250
  }
2226
22270
  return $ret;
22280
}
2229
2230
/**
2231
 * Add the node load cache table.
2232
 */
223380
function system_update_6028() {
2234
  // Removed node_load cache to discuss it more for Drupal 7.
22350
  return array();
22360
}
2237
2238
/**
2239
 * Enable the dblog module on sites that upgrade, since otherwise
2240
 * watchdog logging will stop unexpectedly.
2241
 */
224280
function system_update_6029() {
2243
  // The watchdog table is now owned by dblog, which is not yet
2244
  // "installed" according to the system table, but the table already
2245
  // exists.  We set the module as "installed" here to avoid an error
2246
  // later.
2247
  //
2248
  // Although not the case for the initial D6 release, it is likely
2249
  // that dblog.install will have its own update functions eventually.
2250
  // However, dblog did not exist in D5 and this update is part of the
2251
  // initial D6 release, so we know that dblog is not installed yet.
2252
  // It is therefore correct to install it as version 0.  If
2253
  // dblog updates exist, the next run of update.php will get them.
22540
  drupal_set_installed_schema_version('dblog', 0);
22550
  module_enable(array('dblog'));
22560
  menu_rebuild();
22570
  return array(array('success' => TRUE, 'query' => "'dblog' module
enabled."));
22580
}
2259
2260
/**
2261
 * Add the tables required by actions.inc.
2262
 */
226380
function system_update_6030() {
22640
  $ret = array();
2265
2266
  // Rename the old contrib actions table if it exists so the contrib
version
2267
  // of the module can do something with the old data.
22680
  if (db_table_exists('actions')) {
22690
    db_rename_table($ret, 'actions', 'actions_old_contrib');
22700
  }
2271
22720
  $schema['actions'] = array(
2273
    'fields' => array(
22740
      'aid' => array('type' => 'varchar', 'length' => 255, 'not null' =>
TRUE, 'default' => '0'),
22750
      'type' => array('type' => 'varchar', 'length' => 32, 'not null' =>
TRUE, 'default' => ''),
22760
      'callback' => array('type' => 'varchar', 'length' => 255, 'not null'
=> TRUE, 'default' => ''),
22770
      'parameters' => array('type' => 'text', 'not null' => TRUE, 'size' =>
'big'),
22780
      'description' => array('type' => 'varchar', 'length' => 255, 'not
null' => TRUE, 'default' => '0'),
22790
    ),
22800
    'primary key' => array('aid'),
2281
  );
2282
22830
  $schema['actions_aid'] = array(
2284
    'fields' => array(
22850
      'aid' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' =>
TRUE),
22860
    ),
22870
    'primary key' => array('aid'),
2288
  );
2289
22900
  db_create_table($ret, 'actions', $schema['actions']);
22910
  db_create_table($ret, 'actions_aid', $schema['actions_aid']);
2292
22930
  return $ret;
22940
}
2295
2296
/**
2297
 * Ensure that installer cannot be run again after updating from Drupal 5.x
to 6.x
2298
 * Actually, this is already done by system_update_6014(), so this is now a
no-op.
2299
 */
230080
function system_update_6031() {
23010
  return array();
23020
}
2303
2304
/**
2305
 * profile_fields.name used to be nullable but is part of a unique key
2306
 * and so shouldn't be.
2307
 */
230880
function system_update_6032() {
23090
  $ret = array();
23100
  if (db_table_exists('profile_fields')) {
23110
    db_drop_unique_key($ret, 'profile_fields', 'name');
23120
    db_change_field($ret, 'profile_fields', 'name', 'name', array('type' =>
'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''));
23130
    db_add_unique_key($ret, 'profile_fields', 'name', array('name'));
23140
  }
23150
  return $ret;
23160
}
2317
2318
/**
2319
 * Change node_comment_statistics to be not autoincrement.
2320
 */
232180
function system_update_6033() {
23220
  $ret = array();
23230
  if (db_table_exists('node_comment_statistics')) {
2324
    // On pgsql but not mysql, db_change_field() drops all keys
2325
    // involving the changed field, which in this case is the primary
2326
    // key.  The normal approach is explicitly drop the pkey, change the
2327
    // field, and re-create the pkey.
2328
    //
2329
    // Unfortunately, in this case that won't work on mysql; we CANNOT
2330
    // drop the pkey because on mysql auto-increment fields must be
2331
    // included in at least one key or index.
2332
    //
2333
    // Since we cannot drop the pkey before db_change_field(), after
2334
    // db_change_field() we may or may not still have a pkey.  The
2335
    // simple way out is to re-create the pkey only when using pgsql.
2336
    // Realistic requirements trump idealistic purity.
23370
    db_change_field($ret, 'node_comment_statistics', 'nid', 'nid',
array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' =>
0));
23380
    if ($GLOBALS['db_type'] == 'pgsql') {
23390
      db_add_primary_key($ret, 'node_comment_statistics', array('nid'));
23400
    }
23410
  }
23420
  return $ret;
23430
}
2344
2345
/**
2346
 * Rename permission "administer access control" to "administer
permissions".
2347
 */
234880
function system_update_6034() {
23490
  $ret = array();
23500
  $result = db_query("SELECT rid, perm FROM {permission} ORDER BY rid");
23510
  while ($role = db_fetch_object($result)) {
23520
    $renamed_permission = preg_replace('/administer access control/',
'administer permissions', $role->perm);
23530
    if ($renamed_permission != $role->perm) {
23540
      $ret[] = update_sql("UPDATE {permission} SET perm =
'$renamed_permission' WHERE rid = $role->rid");
23550
    }
23560
  }
23570
  return $ret;
23580
}
2359
2360
/**
2361
 * Change index on system table for better performance.
2362
 */
236380
function system_update_6035() {
23640
  $ret = array();
23650
  db_drop_index($ret, 'system', 'weight');
23660
  db_add_index($ret, 'system', 'modules', array(array('type', 12),
'status', 'weight', 'filename'));
23670
  db_add_index($ret, 'system', 'bootstrap', array(array('type', 12),
'status', 'bootstrap', 'weight', 'filename'));
23680
  return $ret;
23690
}
2370
2371
/**
2372
 * Change the search schema and indexing.
2373
 *
2374
 * The table data is preserved where possible in MYSQL and MYSQLi using
2375
 * ALTER IGNORE. Other databases don't support that, so for them the
2376
 * tables are dropped and re-created, and will need to be re-indexed
2377
 * from scratch.
2378
 */
237980
function system_update_6036() {
23800
  $ret = array();
23810
  if (db_table_exists('search_index')) {
2382
    // Create the search_dataset.reindex column.
23830
    db_add_field($ret, 'search_dataset', 'reindex', array('type' => 'int',
'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0));
2384
2385
    // Drop the search_index.from fields which are no longer used.
23860
    db_drop_index($ret, 'search_index', 'from_sid_type');
23870
    db_drop_field($ret, 'search_index', 'fromsid');
23880
    db_drop_field($ret, 'search_index', 'fromtype');
2389
2390
    // Drop the search_dataset.sid_type index, so that it can be made
unique.
23910
    db_drop_index($ret, 'search_dataset', 'sid_type');
2392
2393
    // Create the search_node_links Table.
2394
    $search_node_links_schema = array(
2395
      'fields' => array(
23960
        'sid'      => array('type' => 'int', 'unsigned' => TRUE, 'not null'
=> TRUE, 'default' => 0),
23970
        'type'     => array('type' => 'varchar', 'length' => 16, 'not null'
=> TRUE, 'default' => ''),
23980
        'nid'      => array('type' => 'int', 'unsigned' => TRUE, 'not null'
=> TRUE, 'default' => 0),
23990
        'caption'    => array('type' => 'text', 'size' => 'big', 'not null'
=> FALSE),
24000
      ),
24010
      'primary key' => array('sid', 'type', 'nid'),
24020
      'indexes' => array('nid' => array('nid')),
24030
    );
24040
    db_create_table($ret, 'search_node_links', $search_node_links_schema);
2405
2406
    // with the change to search_dataset.reindex, the search queue is
handled differently,
2407
    // and this is no longer needed
24080
    variable_del('node_cron_last');
2409
2410
    // Add a unique index for the search_index.
24110
    if ($GLOBALS['db_type'] == 'mysql' || $GLOBALS['db_type'] == 'mysqli')
{
2412
      // Since it's possible that some existing sites have duplicates,
2413
      // create the index using the IGNORE keyword, which ignores duplicate
errors.
2414
      // However, pgsql doesn't support it
24150
      $ret[] = update_sql("ALTER IGNORE TABLE {search_index} ADD UNIQUE KEY
word_sid_type (word, sid, type)");
24160
      $ret[] = update_sql("ALTER IGNORE TABLE {search_dataset} ADD UNIQUE
KEY sid_type (sid, type)");
2417
2418
      // Everything needs to be reindexed.
24190
      $ret[] = update_sql("UPDATE {search_dataset} SET reindex = 1");
24200
    }
2421
    else {
2422
      // Delete the existing tables if there are duplicate values
24230
      if (db_result(db_query("SELECT sid FROM {search_dataset} GROUP BY
sid, type HAVING COUNT(*) > 1")) || db_result(db_query("SELECT sid FROM
{search_index} GROUP BY word, sid, type HAVING COUNT(*) > 1"))) {
24240
        $ret[] = update_sql('DELETE FROM {search_dataset}');
24250
        $ret[] = update_sql('DELETE FROM {search_index}');
24260
        $ret[] = update_sql('DELETE FROM {search_total}');
24270
      }
2428
      else {
2429
        // Everything needs to be reindexed.
24300
        $ret[] = update_sql("UPDATE {search_dataset} SET reindex = 1");
2431
      }
2432
2433
      // create the new indexes
24340
      db_add_unique_key($ret, 'search_index', 'word_sid_type',
array('word', 'sid', 'type'));
24350
      db_add_unique_key($ret, 'search_dataset', 'sid_type', array('sid',
'type'));
2436
    }
24370
  }
24380
  return $ret;
24390
}
2440
2441
/**
2442
 * Create consistent empty region for disabled blocks.
2443
 */
244480
function system_update_6037() {
24450
  $ret = array();
24460
  db_change_field($ret, 'blocks', 'region', 'region', array('type' =>
'varchar', 'length' => 64, 'not null' => TRUE, 'default' => ''));
24470
  $ret[] = update_sql("UPDATE {blocks} SET region = '' WHERE status = 0");
24480
  return $ret;
24490
}
2450
2451
/**
2452
 * Ensure that "Account" is not used as a Profile category.
2453
 */
245480
function system_update_6038() {
24550
  $ret = array();
24560
  if (db_table_exists('profile_fields')) {
24570
    $ret[] = update_sql("UPDATE {profile_fields} SET category = 'Account
settings' WHERE LOWER(category) = 'account'");
24580
    if ($affectedrows = db_affected_rows()) {
24590
      drupal_set_message('There were ' . $affectedrows . ' profile fields
that used a reserved category name. They have been assigned to the category
"Account settings".');
24600
    }
24610
  }
24620
  return $ret;
24630
}
2464
2465
/**
2466
 * Rename permissions "edit foo content" to "edit any foo content".
2467
 * Also update poll module permission "create polls" to "create
2468
 * poll content".
2469
 */
247080
function system_update_6039() {
24710
  $ret = array();
24720
  $result = db_query("SELECT rid, perm FROM {permission} ORDER BY rid");
24730
  while ($role = db_fetch_object($result)) {
24740
    $renamed_permission = preg_replace('/(?<=^|,\ )edit\ ([a-zA-Z0-9_\-]+)\
content(?=,|$)/', 'edit any $1 content', $role->perm);
24750
    $renamed_permission = preg_replace('/(?<=^|,\ )create\ polls(?=,|$)/',
'create poll content', $renamed_permission);
24760
    if ($renamed_permission != $role->perm) {
24770
      $ret[] = update_sql("UPDATE {permission} SET perm =
'$renamed_permission' WHERE rid = $role->rid");
24780
    }
24790
  }
24800
  return $ret;
24810
}
2482
2483
/**
2484
 * Add a weight column to the upload table.
2485
 */
248680
function system_update_6040() {
24870
  $ret = array();
24880
  if (db_table_exists('upload')) {
24890
    db_add_field($ret, 'upload', 'weight', array('type' => 'int', 'not
null' => TRUE, 'default' => 0, 'size' => 'tiny'));
24900
  }
24910
  return $ret;
24920
}
2493
2494
/**
2495
 * Change forum vocabulary not to be required by default and set the weight
of the forum.module 1 higher than the taxonomy.module.
2496
 */
249780
function system_update_6041() {
24980
  $weight = intval((db_result(db_query("SELECT weight FROM {system} WHERE
name = 'taxonomy'"))) + 1);
24990
  $ret = array();
25000
  $vid = intval(variable_get('forum_nav_vocabulary', ''));
25010
  if (db_table_exists('vocabulary') && $vid) {
25020
    $ret[] = update_sql("UPDATE {vocabulary} SET required = 0 WHERE vid = "
. $vid);
25030
    $ret[] = update_sql("UPDATE {system} SET weight = " . $weight . " WHERE
name = 'forum'");
25040
  }
25050
  return $ret;
25060
}
2507
2508
/**
2509
 * Upgrade recolored theme stylesheets to new array structure.
2510
 */
251180
function system_update_6042() {
25120
  foreach (list_themes() as $theme) {
25130
    $stylesheet = variable_get('color_' . $theme->name . '_stylesheet',
NULL);
25140
    if (!empty($stylesheet)) {
25150
      variable_set('color_' . $theme->name . '_stylesheets',
array($stylesheet));
25160
      variable_del('color_' . $theme->name . '_stylesheet');
25170
    }
25180
  }
25190
  return array();
25200
}
2521
2522
/**
2523
 * Update table indices to make them more rational and useful.
2524
 */
252580
function system_update_6043() {
25260
  $ret = array();
2527
  // Required modules first.
2528
  // Add new system module indexes.
25290
  db_add_index($ret, 'flood', 'allow', array('event', 'hostname',
'timestamp'));
25300
  db_add_index($ret, 'history', 'nid', array('nid'));
2531
  // Change length of theme field in {blocks} to be consistent with module,
and
2532
  // to avoid a MySQL error regarding a too-long index.  Also add new
indices.
25330
  db_change_field($ret, 'blocks', 'theme', 'theme', array('type' =>
'varchar', 'length' => 64, 'not null' => TRUE, 'default' => ''),array(
25340
                  'unique keys' => array('tmd' => array('theme', 'module',
'delta'),),
25350
                  'indexes' => array('list' => array('theme', 'status',
'region', 'weight', 'module'),),));
25360
  db_add_index($ret, 'blocks_roles', 'rid', array('rid'));
2537
  // Improve filter module indices.
25380
  db_drop_index($ret, 'filters', 'weight');
25390
  db_add_unique_key($ret, 'filters', 'fmd', array('format', 'module',
'delta'));
25400
  db_add_index($ret, 'filters', 'list', array('format', 'weight', 'module',
'delta'));
2541
  // Drop unneeded keys form the node table.
25420
  db_drop_index($ret, 'node', 'status');
25430
  db_drop_unique_key($ret, 'node', 'nid_vid');
2544
  // Improve user module indices.
25450
  db_add_index($ret, 'users', 'mail', array('mail'));
25460
  db_add_index($ret, 'users_roles', 'rid', array('rid'));
2547
2548
  // Optional modules - need to check if the tables exist.
2549
  // Alter aggregator module's tables primary keys to make them more
useful.
25500
  if (db_table_exists('aggregator_category_feed')) {
25510
    db_drop_primary_key($ret, 'aggregator_category_feed');
25520
    db_add_primary_key($ret, 'aggregator_category_feed', array('cid',
'fid'));
25530
    db_add_index($ret, 'aggregator_category_feed', 'fid', array('fid'));
25540
  }
25550
  if (db_table_exists('aggregator_category_item')) {
25560
    db_drop_primary_key($ret, 'aggregator_category_item');
25570
    db_add_primary_key($ret, 'aggregator_category_item', array('cid',
'iid'));
25580
    db_add_index($ret, 'aggregator_category_item', 'iid', array('iid'));
25590
  }
2560
  // Alter contact module's table to add an index.
25610
  if (db_table_exists('contact')) {
25620
    db_add_index($ret, 'contact', 'list', array('weight', 'category'));
25630
  }
2564
  // Alter locale table to add a primary key, drop an index.
25650
  if (db_table_exists('locales_target')) {
25660
    db_add_primary_key($ret, 'locales_target', array('language', 'lid',
'plural'));
25670
  }
2568
  // Alter a poll module table to add a primary key.
25690
  if (db_table_exists('poll_votes')) {
25700
    db_drop_index($ret, 'poll_votes', 'nid');
25710
    db_add_primary_key($ret, 'poll_votes', array('nid', 'uid',
'hostname'));
25720
  }
2573
  // Alter a profile module table to add a primary key.
25740
  if (db_table_exists('profile_values')) {
25750
    db_drop_index($ret, 'profile_values', 'uid');
25760
    db_drop_index($ret, 'profile_values', 'fid');
25770
    db_change_field($ret,'profile_values' ,'fid', 'fid', array('type' =>
'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0,),
array('indexes' => array('fid' => array('fid'),)));
25780
    db_change_field($ret,'profile_values' ,'uid', 'uid', array('type' =>
'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0,));
25790
    db_add_primary_key($ret, 'profile_values', array('uid', 'fid'));
25800
  }
2581
  // Alter a statistics module table to add an index.
25820
  if (db_table_exists('accesslog')) {
25830
    db_add_index($ret, 'accesslog', 'uid', array('uid'));
25840
  }
2585
  // Alter taxonomy module's tables.
25860
  if (db_table_exists('term_data')) {
25870
    db_drop_index($ret, 'term_data', 'vid');
25880
    db_add_index($ret, 'term_data', 'vid_name', array('vid', 'name'));
25890
    db_add_index($ret, 'term_data', 'taxonomy_tree', array('vid', 'weight',
'name'));
25900
  }
25910
  if (db_table_exists('term_node')) {
25920
    db_drop_primary_key($ret, 'term_node');
25930
    db_drop_index($ret, 'term_node', 'tid');
25940
    db_add_primary_key($ret, 'term_node', array('tid', 'vid'));
25950
  }
25960
  if (db_table_exists('term_relation')) {
25970
    db_drop_index($ret, 'term_relation', 'tid1');
25980
    db_add_unique_key($ret, 'term_relation', 'tid1_tid2', array('tid1',
'tid2'));
25990
  }
26000
  if (db_table_exists('term_synonym')) {
26010
    db_drop_index($ret, 'term_synonym', 'name');
26020
    db_add_index($ret, 'term_synonym', 'name_tid', array('name', 'tid'));
26030
  }
26040
  if (db_table_exists('vocabulary')) {
26050
    db_add_index($ret, 'vocabulary', 'list', array('weight', 'name'));
26060
  }
26070
  if (db_table_exists('vocabulary_node_types')) {
26080
    db_drop_primary_key($ret, 'vocabulary_node_types');
26090
    db_add_primary_key($ret, 'vocabulary_node_types', array('type',
'vid'));
26100
    db_add_index($ret, 'vocabulary_node_types', 'vid', array('vid'));
26110
  }
2612
  // If we updated in RC1 or before ensure we don't update twice.
26130
  variable_set('system_update_6043_RC2', TRUE);
2614
26150
  return $ret;
26160
}
2617
2618
/**
2619
 * RC1 to RC2 index cleanup.
2620
 */
262180
function system_update_6044() {
26220
  $ret = array();
2623
2624
  // Delete invalid entries in {term_node} after system_update_6001.
26250
  $ret[] = update_sql("DELETE FROM {term_node} WHERE vid = 0");
2626
2627
  // Only execute the rest of this function if 6043 was run in RC1 or
before.
26280
  if (variable_get('system_update_6043_RC2', FALSE)) {
26290
    variable_del('system_update_6043_RC2');
26300
    return $ret;
26310
  }
2632
2633
  // User module indices.
26340
  db_drop_unique_key($ret, 'users', 'mail');
26350
  db_add_index($ret, 'users', 'mail', array('mail'));
2636
2637
  // Optional modules - need to check if the tables exist.
2638
  // Alter taxonomy module's tables.
26390
  if (db_table_exists('term_data')) {
26400
    db_drop_unique_key($ret, 'term_data', 'vid_name');
26410
    db_add_index($ret, 'term_data', 'vid_name', array('vid', 'name'));
26420
  }
26430
  if (db_table_exists('term_synonym')) {
26440
    db_drop_unique_key($ret, 'term_synonym', 'name_tid', array('name',
'tid'));
26450
    db_add_index($ret, 'term_synonym', 'name_tid', array('name', 'tid'));
26460
  }
2647
26480
  return $ret;
26490
}
2650
2651
/**
2652
 * Update blog, book and locale module permissions.
2653
 *
2654
 * Blog module got "edit own blog" replaced with the more granular "create
2655
 * blog entries", "edit own blog entries" and "delete own blog entries"
2656
 * permissions. We grant create and edit to previously privileged users,
but
2657
 * delete is not granted to be in line with other permission changes in
Drupal 6.
2658
 *
2659
 * Book module's "edit book pages" was upgraded to the bogus "edit book
content"
2660
 * in Drupal 6 RC1 instead of "edit any book content", which would be
correct.
2661
 *
2662
 * Locale module introduced "administer languages" and "translate
interface"
2663
 * in place of "administer locales".
2664
 *
2665
 * Modeled after system_update_6039().
2666
 */
266780
function system_update_6045() {
26680
  $ret = array();
26690
  $result = db_query("SELECT rid, perm FROM {permission} ORDER BY rid");
26700
  while ($role = db_fetch_object($result)) {
26710
    $renamed_permission = preg_replace('/(?<=^|,\ )edit\ own\
blog(?=,|$)/', 'create blog entries, edit own blog entries', $role->perm);
26720
    $renamed_permission = preg_replace('/(?<=^|,\ )edit\ book\
content(?=,|$)/', 'edit any book content', $renamed_permission);
26730
    $renamed_permission = preg_replace('/(?<=^|,\ )administer\
locales(?=,|$)/', 'administer languages, translate interface',
$renamed_permission);
26740
    if ($renamed_permission != $role->perm) {
26750
      $ret[] = update_sql("UPDATE {permission} SET perm =
'$renamed_permission' WHERE rid = $role->rid");
26760
    }
26770
  }
2678
2679
  // Notify user that delete permissions may have been changed. This was
in
2680
  // effect since system_update_6039(), but there was no user notice.
26810
  drupal_set_message('Drupal now has separate edit and delete permissions.
Previously, users who were able to edit content were automatically allowed
to delete it. For added security, delete permissions for individual core
content types have been <strong>removed</strong> from all roles on your
site (only roles with the "administer nodes" permission can now delete
these types of content). If you would like to reenable any individual
delete permissions, you can do this at the <a href="' .
url('admin/user/permissions', array('fragment' => 'module-node')) .
'">permissions page</a>.');
26820
  return $ret;
26830
}
2684
2685
/**
2686
 * Ensure that the file_directory_path variable is set (using the old 5.x
2687
 * default, if necessary), so that the changed 6.x default won't break
2688
 * existing sites.
2689
 */
269080
function system_update_6046() {
26910
  $ret = array();
26920
  if (!variable_get('file_directory_path', FALSE)) {
26930
    variable_set('file_directory_path', 'files');
26940
    $ret[] = array('success' => TRUE, 'query' =>
"variable_set('file_directory_path')");
26950
  }
26960
  return $ret;
26970
}
2698
2699
/**
2700
 * Fix cache mode for blocks inserted in system_install() in fresh installs
of previous RC.
2701
 */
270280
function system_update_6047() {
27030
  $ret = array();
27040
  $ret[] = update_sql("UPDATE {blocks} SET cache = -1 WHERE module = 'user'
AND delta IN ('0', '1')");
27050
  $ret[] = update_sql("UPDATE {blocks} SET cache = -1 WHERE module =
'system' AND delta = '0'");
27060
  return $ret;
27070
}
2708
2709
/**
2710
 * @} End of "defgroup updates-5.x-to-6.x"
2711
 * The next series of updates should start at 7000.
2712
 */
2713
2714
/**
2715
 * @defgroup updates-6.x-to-7.x System updates from 6.x to 7.x
2716
 * @{
2717
 */
2718
2719
/**
2720
 * Rename blog and forum permissions to be consistent with other content
types.
2721
 */
272280
function system_update_7000() {
27230
  $ret = array();
27240
  $result = db_query("SELECT rid, perm FROM {permission} ORDER BY rid");
27250
  while ($role = db_fetch_object($result)) {
27260
    $renamed_permission = preg_replace('/(?<=^|,\ )create\ blog\
entries(?=,|$)/', 'create blog content', $role->perm);
27270
    $renamed_permission = preg_replace('/(?<=^|,\ )edit\ own\ blog\
entries(?=,|$)/', 'edit own blog content', $role->perm);
27280
    $renamed_permission = preg_replace('/(?<=^|,\ )edit\ any\ blog\
entry(?=,|$)/', 'edit any blog content', $role->perm);
27290
    $renamed_permission = preg_replace('/(?<=^|,\ )delete\ own\ blog\
entries(?=,|$)/', 'delete own blog content', $role->perm);
27300
    $renamed_permission = preg_replace('/(?<=^|,\ )delete\ any\ blog\
entry(?=,|$)/', 'delete any blog content', $role->perm);
2731
27320
    $renamed_permission = preg_replace('/(?<=^|,\ )create\ forum\
topics(?=,|$)/', 'create forum content', $role->perm);
27330
    $renamed_permission = preg_replace('/(?<=^|,\ )delete\ any\ forum\
topic(?=,|$)/', 'delete any forum content', $role->perm);
27340
    $renamed_permission = preg_replace('/(?<=^|,\ )delete\ own\ forum\
topics(?=,|$)/', 'delete own forum content', $role->perm);
27350
    $renamed_permission = preg_replace('/(?<=^|,\ )edit\ any\ forum\
topic(?=,|$)/', 'edit any forum content', $role->perm);
27360
    $renamed_permission = preg_replace('/(?<=^|,\ )edit\ own\ forum\
topics(?=,|$)/', 'edit own forum content', $role->perm);
2737
27380
    if ($renamed_permission != $role->perm) {
27390
      $ret[] = update_sql("UPDATE {permission} SET perm =
'$renamed_permission' WHERE rid = $role->rid");
27400
    }
27410
  }
2742
27430
  return $ret;
27440
}
2745
2746
/**
2747
 * Generate a cron key and save it in the variables table.
2748
 */
274980
function system_update_7001() {
27500
  $ret = array();
27510
  variable_set('cron_key', md5(mt_rand()));
27520
  $ret[] = array('success' => TRUE, 'query' =>
"variable_set('cron_key')");
27530
  return $ret;
27540
}
2755
2756
/**
2757
 * Add a table to store blocked IP addresses.
2758
 */
275980
function system_update_7002() {
27600
  $ret = array();
27610
  $schema['blocked_ips'] = array(
27620
    'description' => t('Stores blocked IP addresses.'),
2763
    'fields' => array(
2764
      'iid' => array(
27650
        'description' => t('Primary Key: unique ID for IP addresses.'),
27660
        'type' => 'serial',
27670
        'unsigned' => TRUE,
27680
        'not null' => TRUE,
27690
      ),
2770
      'ip' => array(
27710
        'description' => t('IP address'),
27720
        'type' => 'varchar',
27730
        'length' => 32,
27740
        'not null' => TRUE,
27750
        'default' => '',
27760
      ),
27770
    ),
2778
    'indexes' => array(
27790
      'blocked_ip' => array('ip'),
27800
    ),
27810
    'primary key' => array('iid'),
2782
  );
2783
27840
  db_create_table($ret, 'blocked_ips', $schema['blocked_ips']);
2785
27860
  return $ret;
27870
}
2788
2789
/**
2790
 * Update {blocked_ips} with valid IP addresses from {access}.
2791
 */
279280
function system_update_7003() {
27930
  $ret = array();
27940
  $type = 'host';
27950
  $result = db_query("SELECT mask FROM {access} WHERE status = %d AND TYPE
= '%s'", 0, $type);
27960
  while ($blocked = db_fetch_object($result)) {
27970
    if (filter_var($blocked->mask, FILTER_VALIDATE_IP,
FILTER_FLAG_NO_RES_RANGE) !== FALSE) {
27980
      $ret[] = update_sql("INSERT INTO {blocked_ips} (ip) VALUES
('$blocked->mask')");
27990
    }
2800
    else {
28010
      $invalid_host = check_plain($blocked->mask);
28020
      $ret[] = array('success' => TRUE, 'query' => 'The host ' .
$invalid_host . ' is no longer blocked because it is not a valid IP
address.');
2803
    }
28040
  }
28050
  if (isset($invalid_host)) {
28060
    drupal_set_message('Drupal no longer supports wildcard IP address
blocking. Visitors whose IP addresses match ranges you have previously set
using <em>access rules</em> will no longer be blocked from your site when
you take it out of maintenance mode. See the <a
href="http://drupal.org/node/24302">IP address and referrer blocking
Handbook page</a> for alternative methods.', 'warning');
28070
    $ret[] = array('success' => TRUE, 'query' => '');
28080
  }
2809
  // Make sure not to block any IP addresses that were specifically allowed
by access rules.
28100
  if (!empty($result)) {
28110
    $result = db_query("SELECT mask FROM {access} WHERE status = %d AND
type = '%s'", 1, $type);
28120
    while ($allowed = db_fetch_object($result)) {
28130
      $ret[] = update_sql("DELETE FROM {blocked_ips} WHERE LOWER(ip) LIKE
LOWER('$allowed->mask')");
28140
    }
28150
  }
2816
28170
  return $ret;
28180
}
2819
2820
/**
2821
 * Remove hardcoded numeric deltas from all blocks in core.
2822
 */
282380
function system_update_7004(&$sandbox) {
28240
  $ret = array();
2825
  // Get an array of the renamed block deltas, organized by module.
2826
  $renamed_deltas = array(
28270
    'blog' => array('0' => 'recent'),
28280
    'book' => array('0' => 'navigation'),
28290
    'comment' => array('0' => 'recent'),
2830
    'forum' => array(
28310
      '0' => 'active',
28320
      '1' => 'new',
28330
    ),
28340
    'locale' => array('0' => 'language-switcher'),
28350
    'node' => array('0' => 'syndicate'),
28360
    'poll' => array('0' => 'recent'),
28370
    'profile' => array('0' => 'author-information'),
28380
    'search' => array('0' => 'form'),
28390
    'statistics' => array('0' => 'popular'),
28400
    'system' => array('0' => 'powered-by'),
2841
    'user' => array(
28420
      '0' => 'login',
28430
      '1' => 'navigation',
28440
      '2' => 'new',
28450
      '3' => 'online',
28460
    ),
28470
  );
2848
  // Loop through each block and make changes to the core block tables.
2849
  // Only run this the first time through the batch update.
28500
  if (!isset($sandbox['progress'])) {
28510
    $block_tables = array('blocks', 'blocks_roles');
28520
    foreach ($block_tables as $table) {
28530
      foreach ($renamed_deltas as $module => $deltas) {
28540
        foreach ($deltas as $old_delta => $new_delta) {
2855
          // Only do the update if the old block actually exists.
28560
          if (db_result(db_query("SELECT COUNT(*) FROM {" . $table . "}
WHERE module = '%s' AND delta = '%s'", $module, $old_delta))) {
28570
            $ret[] = update_sql("UPDATE {" . $table . "} SET delta = '" .
$new_delta . "' WHERE module = '" . $module . "' AND delta = '" .
$old_delta . "'");
28580
          }
28590
        }
28600
      }
28610
    }
2862
    // Rename forum module's block variables.
28630
    $forum_block_num_0 = variable_get('forum_block_num_0', NULL);
28640
    if (isset($forum_block_num_0)) {
28650
      variable_set('forum_block_num_active', $forum_block_num_0);
28660
      variable_del('forum_block_num_0');
28670
    }
28680
    $forum_block_num_1 = variable_get('forum_block_num_1', NULL);
28690
    if (isset($forum_block_num_1)) {
28700
      variable_set('forum_block_num_new', $forum_block_num_1);
28710
      variable_del('forum_block_num_1');
28720
    }
2873
    // Initialize batch update information.
28740
    $sandbox['progress'] = 0;
28750
    $sandbox['last_user_processed'] = -1;
28760
    $sandbox['max'] = db_result(db_query("SELECT COUNT(*) FROM {users}
WHERE data IS NOT NULL"));
28770
  }
2878
  // Now do the batch update of the user-specific block visibility
settings.
28790
  $limit = 100;
28800
  $result = db_query_range("SELECT uid, data FROM {users} WHERE uid > %d
AND data IS NOT NULL", $sandbox['last_user_processed'], 0, $limit);
28810
  while ($row = db_fetch_object($result)) {
28820
    $data = unserialize($row->data);
28830
    $user_needs_update = FALSE;
28840
    foreach ($renamed_deltas as $module => $deltas) {
28850
      foreach ($deltas as $old_delta => $new_delta) {
28860
        if (isset($data['block'][$module][$old_delta])) {
2887
          // Transfer the old block visibility settings to the
newly-renamed
2888
          // block, and mark this user for a database update.
28890
          $data['block'][$module][$new_delta] =
$data['block'][$module][$old_delta];
28900
          unset($data['block'][$module][$old_delta]);
28910
          $user_needs_update = TRUE;
28920
        }
28930
      }
28940
    }
2895
    // Update the current user.
28960
    if ($user_needs_update) {
28970
      db_query("UPDATE {users} SET data = '%s' WHERE uid = %d",
serialize($data), $row->uid);
28980
    }
2899
    // Update our progress information for the batch update.
29000
    $sandbox['progress']++;
29010
    $sandbox['last_user_processed'] = $row->uid;
29020
  }
2903
  // Indicate our current progress to the batch update system.
29040
  if ($sandbox['progress'] < $sandbox['max']) {
29050
    $ret['#finished'] = $sandbox['progress'] / $sandbox['max'];
29060
  }
29070
  return $ret;
29080
}
2909
2910
/**
2911
 * Remove throttle columns and variables.
2912
 */
291380
function system_update_7005() {
29140
  $ret = array();
29150
  db_drop_field($ret, 'blocks', 'throttle');
29160
  db_drop_field($ret, 'system', 'throttle');
29170
  variable_del('throttle_user');
29180
  variable_del('throttle_anonymous');
29190
  variable_del('throttle_level');
29200
  variable_del('throttle_probability_limiter');
2921
29220
  return $ret;
29230
}
2924
2925
/**
2926
 * Registry tables and drop the file key of the menu router, since it is
no
2927
 * longer needed.
2928
 */
292980
function system_update_7006() {
29300
  $ret = array();
29310
  db_drop_field($ret, 'menu_router', 'file');
29320
  $schema['registry'] = array(
2933
    'fields' => array(
29340
      'name'   => array('type' => 'varchar', 'length' => 255, 'not null' =>
TRUE, 'default' => ''),
29350
      'type'   => array('type' => 'varchar', 'length' => 9, 'not null' =>
TRUE, 'default' => ''),
29360
      'filename'   => array('type' => 'varchar', 'length' => 255, 'not
null' => TRUE, 'default' => ''),
29370
    ),
29380
    'primary key' => array('name', 'type'),
2939
  );
29400
  $schema['registry_file'] = array(
2941
    'fields' => array(
29420
      'filename'   => array('type' => 'varchar', 'length' => 255, 'not
null' => TRUE, 'default' => ''),
29430
      'md5'   => array('type' => 'varchar', 'length' => 32, 'not null' =>
TRUE, 'default' => ''),
29440
    ),
29450
    'primary key' => array('filename'),
2946
  );
29470
  $schema['cache_registry'] = array(
2948
    'fields' => array(
29490
      'cid'        => array('type' => 'varchar', 'length' => 255, 'not
null' => TRUE, 'default' => ''),
29500
      'data'       => array('type' => 'blob', 'not null' => FALSE, 'size'
=> 'big'),
29510
      'expire'     => array('type' => 'int', 'not null' => TRUE, 'default'
=> 0),
29520
      'created'    => array('type' => 'int', 'not null' => TRUE, 'default'
=> 0),
29530
      'headers'    => array('type' => 'text', 'not null' => FALSE),
29540
      'serialized' => array('type' => 'int', 'size' => 'small', 'not null'
=> TRUE, 'default' => 0)
29550
    ),
29560
    'indexes' => array('expire' => array('expire')),
29570
    'primary key' => array('cid'),
2958
  );
29590
  db_create_table($ret, 'cache_registry', $schema['cache_registry']);
29600
  db_create_table($ret, 'registry', $schema['registry']);
29610
  db_create_table($ret, 'registry_file', $schema['registry_file']);
29620
  registry_rebuild();
29630
  return $ret;
29640
}
2965
2966
/**
2967
 * Convert to new method of storing permissions.
2968
 *
2969
 * This update is in system.install rather than user.install so that
2970
 * all modules can use the updated permission scheme during their updates.
2971
 */
297280
function system_update_7007() {
29730
  $ret = array();
2974
29750
  $schema['role_permission'] = array(
2976
    'fields' => array(
2977
      'rid' => array(
29780
        'type' => 'int',
29790
        'unsigned' => TRUE,
29800
        'not null' => TRUE,
29810
      ),
2982
      'permission' => array(
29830
        'type' => 'varchar',
29840
        'length' => 64,
29850
        'not null' => TRUE,
29860
        'default' => '',
29870
      ),
29880
    ),
29890
    'primary key' => array('rid', 'permission'),
2990
    'indexes' => array(
29910
      'permission' => array('permission'),
29920
    ),
2993
  );
2994
29950
  db_create_table($ret, 'role_permission', $schema['role_permission']);
2996
2997
  // Copy the permissions from the old {permission} table to the new
{role_permission} table.
29980
  $result = db_query("SELECT rid, perm FROM {permission} ORDER BY rid
ASC");
29990
  while ($role = db_fetch_object($result)) {
30000
    foreach (explode(', ', $role->perm) as $perm) {
30010
      db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d,
'%s')", $role->rid, $perm);
30020
    }
30030
    $ret[] = array('success' => TRUE, 'query' => "Inserted into
{role_permission} the permissions for role ID " . $role->rid);
30040
  }
30050
  db_drop_table($ret, 'permission');
3006
30070
  return $ret;
30080
}
3009
3010
3011
/**
3012
 * Use the poll_choice primary key to record votes in poll_votes rather
than
3013
 * the choice order. Rename chorder to weight.
3014
 */
301580
function system_update_7008() {
30160
  $ret = array();
30170
  if (db_table_exists('poll_votes')) {
3018
    // Add chid column and convert existing votes.
30190
    db_add_field($ret, 'poll_votes', 'chid', array('type' => 'int',
'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0));
30200
    db_add_index($ret, 'poll_votes', 'chid', array('chid'));
30210
    $ret[] = update_sql("UPDATE {poll_votes} v SET chid = (SELECT chid FROM
{poll_choices} c WHERE v.chorder = c.chorder AND v.nid = c.nid)");
3022
    // Remove old chorder column.
30230
    db_drop_field($ret, 'poll_votes', 'chorder');
30240
  }
30250
  if (db_table_exists('poll_choices')) {
3026
    // Change the chorder column to weight in poll_choices.
30270
    db_change_field($ret, 'poll_choices', 'chorder', 'weight', array('type'
=> 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'));
30280
  }
30290
  return $ret;
30300
}
3031
3032
/**
3033
 * Rename the variables for primary and secondary links.
3034
 *
3035
 */
303680
function system_update_7009() {
30370
  $ret = array();
30380
  $ret[] = update_sql("UPDATE {variable} SET name = 'menu_main_menu_source'
WHERE name = 'menu_primary_links_source'");
30390
  $ret[] = update_sql("UPDATE {variable} SET name = 'menu_main_menu_source'
WHERE name = 'menu_primary_links_source'");
3040
30410
  return $ret;
30420
}
3043
3044
/**
3045
 * @} End of "defgroup updates-6.x-to-7.x"
3046
 * The next series of updates should start at 8000.
3047
 */
3048
304980