You are here

date.install in Date 6

Same filename and directory in other branches
  1. 5.2 date/date.install
  2. 6.2 date/date.install

File

date/date.install
View source
<?php

function date_install_load() {

  // Updates happen in random order, whether or not the module is enabled,
  // so include critical code here just to be sure.
  include_once './' . drupal_get_path('module', 'content') . '/content.module';
  include_once './' . drupal_get_path('module', 'content') . '/includes/content.admin.inc';
  include_once './' . drupal_get_path('module', 'date_api') . '/date_api.module';
  include_once './' . drupal_get_path('module', 'date') . '/date.module';
  if (module_exists('views')) {
    include_once './' . drupal_get_path('module', 'date') . '/date.views.inc';
  }
}

/**
 * Implementation of hook_install().
 */

/**
 * Implementation of hook_install().
 * Reset the date caches.
 */
function date_install() {
  date_install_load();
  content_notify('install', 'date');
  $ret = array();
  date_clear_all();
  return $ret;
}

/**
 * Implementation of hook_uninstall().
 */
function date_uninstall() {
  date_install_load();
  content_notify('uninstall', 'date');
  $ret = array();

  // Empty the date caches.
  date_clear_all(TRUE);
  return $ret;
}

/**
 * Implementation of hook_enable().
 * Reset the calendar caches.
 */
function date_enable() {
  date_install_load();
  content_notify('enable', 'date');
  date_clear_all();
}

/**
 * Implementation of hook_disable().
 * Empty the date caches.
 */
function date_disable() {
  date_install_load();
  content_notify('disable', 'date');
  date_clear_all(TRUE);
}
function date_update_last_removed() {
  return 7;
}

/**
 * Prepare for Version 5.2 updates, make changes to field and widget settings.
 */
function date_update_5100() {
  date_install_load();
  $ret = array();
  $fields = content_fields();
  foreach ($fields as $field) {
    if (strstr($field['type'], 'date')) {
      $field_settings = unserialize(db_result(db_query("SELECT global_settings from {" . content_field_tablename() . "} where field_name = '%s'", $field['field_name'])));
      $widget_settings = unserialize(db_result(db_query("SELECT widget_settings from {" . content_instance_tablename() . "} where field_name = '%s'", $field['field_name'])));

      // Move input format from field settings to widget settings, where it should have been all along.
      $input_format = $field_settings['input_format'];
      $input_format_custom = $field_settings['input_format_custom'];
      $widget_settings['input_format'] = $input_format;
      $widget_settings['input_format_custom'] = $input_format_custom;

      // New PHP 5 date handling will handle timezone formats correctly, so
      // add timezone formats to format string and drop old setting for tracking zones.
      $replace = array(
        '0000' => 'O',
        '00:00' => 'P',
        'name' => 'e',
        '' => '',
      );
      if (!empty($field_settings['output_format_zone'])) {
        $field_settings['output_format_date'] .= ' ' . $replace[$field_settings['output_format_zone']];
        if (!empty($field_settings['output_format_custom'])) {
          $field_settings['output_format_custom'] .= ' ' . $replace[$field_settings['output_format_zone']];
        }
      }
      if (!empty($field_settings['output_format_zone_short'])) {
        $field_settings['output_format_date_short'] .= ' ' . $replace[$field_settings['output_format_zone_short']];
        if (!empty($field_settings['output_format_custom_short'])) {
          $field_settings['output_format_custom_short'] .= ' ' . $replace[$field_settings['output_format_zone_short']];
        }
      }
      if (!empty($field_settings['output_format_zone_medium'])) {
        $field_settings['output_format_date_medium'] .= ' ' . $replace[$field_settings['output_format_zone_medium']];
        if (!empty($field_settings['output_format_custom_medium'])) {
          $field_settings['output_format_custom_medium'] .= ' ' . $replace[$field_settings['output_format_zone_medium']];
        }
      }
      if (!empty($field_settings['output_format_zone_long'])) {
        $field_settings['output_format_date_long'] .= ' ' . $replace[$field_settings['output_format_zone_long']];
        if (!empty($field_settings['output_format_custom_long'])) {
          $field_settings['output_format_custom_long'] .= ' ' . $replace[$field_settings['output_format_zone_long']];
        }
      }

      // Add new timezone_db setting.
      // For now this is fixed at 'UTC', but it provides a method to store a different timezone in the future.
      $field_settings['timezone_db'] = 'UTC';

      // Change select_year, select_month, select_day to array of text_parts and add to widget settings.
      $text_parts = array();
      if (isset($widget_settings['select_year']) && empty($widget_settings['select_year'])) {
        $text_parts[] = 'year';
      }
      if (isset($widget_settings['select_month']) && empty($widget_settings['select_month'])) {
        $text_parts[] = 'mon';
      }
      if (isset($widget_settings['select_day']) && empty($widget_settings['select_day'])) {
        $text_parts[] = 'mday';
      }
      $widget_settings['text_parts'] = $text_parts;

      // Combine years_back and years_forward into single year_range
      $widget_settings['year_range'] = '-' . intval(isset($widget_settings['years_back']) ? $widget_settings['years_back'] : 3) . ':+' . intval(isset($widget_settings['years_forward']) ? $widget_settings['years_forward'] : 3);

      // Clean up settings by removing all that are not valid.
      $fields = array(
        'granularity',
        'field_timezone',
        'timezone_db',
        'tz_handling',
        'todate',
        'output_format_date',
        'output_format_date_short',
        'output_format_date_medium',
        'output_format_date_long',
        'output_format_custom',
        'output_format_custom_short',
        'output_format_custom_medium',
        'output_format_custom_long',
      );
      foreach (array_keys($field_settings) as $setting) {
        if (!in_array($setting, $fields)) {
          unset($field_settings[$setting]);
        }
      }
      $widgets = array(
        'default_value',
        'default_value_custom',
        'default_value2',
        'default_value_custom2',
        'input_format',
        'input_format_custom',
        'increment',
        'text_parts',
        'year_range',
      );
      foreach (array_keys($widget_settings) as $setting) {
        if (!in_array($setting, $widgets)) {
          unset($widget_settings[$setting]);
        }
      }

      // Save the new settings. Use db_query instead of update_sql to get proper handling for serialized array and
      // because the query must be run immediately so we can rebuild the cache.
      db_query("UPDATE {" . content_field_tablename() . "} SET global_settings = '%s' WHERE field_name='%s'", serialize($field_settings), $field['field_name']);
      db_query("UPDATE {" . content_instance_tablename() . "} SET widget_settings = '%s' WHERE field_name='%s'", serialize($widget_settings), $field['field_name']);
      $ret[] = array(
        'success' => TRUE,
        'query' => 'field settings updated to ' . serialize($field_settings) . '<br />widget settings updated to ' . serialize($widget_settings),
      );
    }
  }

  // Rebuild the cache.
  content_clear_type_cache();
  return $ret;
}

/**
 * Date offsets were not getting saved. Need to repair the database.
 * Superceded by update 5103().
 */
function date_update_5101() {
  $ret = array();
  return $ret;
}

/**
 * Make sure date module loads after date_api.
 */
function date_update_5102() {
  date_install_load();
  variable_del('date_version');
  $ret[] = update_sql("UPDATE {system} SET weight = 1 WHERE name = 'date'");
  return date_db_integrity('5103');
}

/**
 * Data integrity update, moved to Version 2 because it can make
 * lots of db changes and we want people to be prepared for a
 * significant change.
 */
function date_update_5103() {
  $ret = array();
  return $ret;
}

/**
 * Move these caches from 'cache' to 'cache_views' so they get cleared
 * automatically whenever views_invalidate_cache() is called.
 */
function date_update_5104() {
  date_install_load();
  $ret = array();
  cache_clear_all('date_browser_views', 'cache');
  return $ret;
}

/**
 * Version 5.2 updates.
 */
function date_update_5200() {
  date_install_load();
  $ret = array();
  module_enable(array(
    'date_timezone',
  ));

  // Make sure date module loads after date_api.
  $ret[] = update_sql("UPDATE {system} SET weight = 1 WHERE name = 'date'");

  // No longer using the cached formats.
  cache_clear_all('date_formats', 'cache', TRUE);

  // Granularity names have been changed to conform with keys used in date arrays.
  $replace = array(
    'Y' => 'year',
    'M' => 'month',
    'D' => 'day',
    'H' => 'hour',
    'N' => 'minute',
    'S' => 'second',
  );
  $fields = content_fields();
  foreach ($fields as $field) {
    if (strstr($field['type'], 'date')) {
      $field_settings = unserialize(db_result(db_query("SELECT global_settings from {" . content_field_tablename() . "} where field_name = '%s'", $field['field_name'])));
      $granularity = array();
      foreach ((array) $field_settings['granularity'] as $item) {
        $granularity[] = strtr($item, $replace);
      }
      $field_settings['granularity'] = $granularity;

      // Save the new settings.
      db_query("UPDATE {" . content_field_tablename() . "} SET global_settings = '%s' WHERE field_name='%s'", serialize($field_settings), $field['field_name']);
    }
  }
  content_clear_type_cache();
  return $ret;
}

/**
 * Get rid of jscalendar popup and use jQuery popup instead.
 *
 * @return unknown
 */
function date_update_5201() {
  date_install_load();
  $ret = array();
  if (db_result(db_query("SELECT COUNT(*) FROM {" . content_instance_tablename() . "} WHERE widget_type = 'date_js'"))) {
    $result = db_query("SELECT field_name, widget_type, widget_settings from {" . content_instance_tablename() . "} where widget_type = 'date_js'");
    while ($widget = db_fetch_array($result)) {

      // Change the format to one date_popup can use.
      $widget_settings = unserialize($widget['widget_settings']);
      $widget_settings['input_format'] = DATE_FORMAT_DATETIME;
      $widget_settings['input_format_custom'] = '';
      db_query("UPDATE {" . content_instance_tablename() . "} SET widget_type = 'date_popup', widget_settings = '%s' WHERE field_name = '%s'", serialize($widget_settings), $widget['field_name']);
    }
  }
  content_clear_type_cache();
  return $ret;
}

/**
 * Database integrity update, supercedes most previous data integrity updates.
 */
function date_update_5202() {
  date_install_load();
  return date_db_integrity('5202');
}

/**
 * Data integrity update, supercedes most previous data integrity updates.
 */
function date_update_5203() {
  date_install_load();
  return date_data_integrity('5203');
}

/**
 * Get rid of deprecated timezone names.
 */
function date_update_5204() {
  date_install_load();
  $ret = array();
  $fields = content_fields();
  foreach ($fields as $field) {
    if (($field['type'] == 'date' || $field['type'] == 'datestamp') && $field['tz_handling'] == 'date') {
      $db_info = content_database_info($field);
      $table = $db_info['table'];
      $column = $db_info['columns']['timezone']['column'];
      $results = db_query("SELECT DISTINCT {$column} FROM {$table} ORDER BY {$column}");
      while ($row = db_fetch_object($results)) {
        if (!empty($row->timezone_name)) {
          $new = date_timezone_replacement($row->timezone_name);
          if (!empty($new) && $new != $row->timezone_name) {
            db_query("UPDATE {$table} SET {$column} = '%s' WHERE {$column} = '%s'", $new, $row->timezone_name);
          }
        }
      }
    }
  }
  return $ret;
}
function date_update_5205() {
  date_install_load();
  $ret = array();
  $fields = content_fields();
  foreach ($fields as $field) {
    if (strstr($field['type'], 'date')) {
      $field_settings = unserialize(db_result(db_query("SELECT global_settings from {" . content_field_tablename() . "} where field_name = '%s'", $field['field_name'])));
      foreach ($field_settings as $key => $value) {
        if ($key == 'tz_handling' && $value == 'gmt') {
          $field_settings[$key] = 'utc';
        }
      }
      db_query("UPDATE {" . content_field_tablename() . "} SET global_settings = '%s' WHERE field_name = '%s'", serialize($field_settings), $field['field_name']);
    }
  }
  return $ret;
}
function date_db_integrity($name) {
  $ret = array();
  $fields = content_fields();
  foreach ($fields as $field) {
    $db_info = content_database_info($field);
    if ($field['type'] == 'date' || $field['type'] == 'datestamp') {
      $table = $db_info['table'];

      // start with the new column patterns.
      $columns_start = $db_info['columns'];
      $columns_end = $db_info['columns'];

      // alter the start column values to invalid or empty
      // values to force the new columns to be reset.
      $columns_start['value']['length'] = 90;
      if ($field['todate']) {
        if (!db_column_exists($table, $columns_start['value2']['column'])) {
          unset($columns_start['value2']);
        }
        else {
          $columns_start['value2']['length'] = 80;
        }
      }
      if ($field['tz_handling'] == 'date') {
        if (!db_column_exists($table, $columns_start['timezone']['column'])) {
          unset($columns_start['timezone']);
        }
        else {
          $columns_start['timezone']['length'] = 80;
        }
        if (!db_column_exists($table, $columns_start['offset']['column'])) {
          unset($columns_start['offset']);
        }
        else {
          $columns_start['offset']['length'] = 80;
        }
        if ($field['todate']) {
          if (!db_column_exists($table, $columns_start['offset2']['column'])) {
            unset($columns_start['offset2']);
          }
          else {
            $columns_start['offset2']['length'] = 80;
          }
        }
      }
      if ($field['repeat'] == 1) {
        if (!db_column_exists($table, $columns_start['rrule']['column'])) {
          unset($columns_start['rrule']);
        }
        else {
          $columns_start['rrule']['length'] = 80;
        }
      }
      content_alter_db_field($field, $columns_start, $field, $columns_end);
      $message = 'Date database integrity check. Updated table ' . $table . ' to set all columns to accept NULL values.';
      $ret[] = array(
        'success' => TRUE,
        'query' => $message,
      );
    }
  }
  content_clear_type_cache();
  return $ret;
}

/**
 *  Progressive update of date information, integrity checking of all date values.
 *
 * @param name - name of the update
 */
function date_data_integrity($name, $force_recalc = FALSE) {

  // Use this to turn extra debugging on or off.
  $debug = TRUE;
  $ret = array();
  $update_name = 'date_update_' . $name;

  // Make sure Date API module is installed before proceeding.
  if (!module_exists('date_api')) {
    drupal_install_modules(array(
      'date_api',
    ));
  }
  if (!module_exists('content')) {
    drupal_install_modules(array(
      'content',
    ));
  }

  // See if being called for the first time
  if (!isset($_SESSION[$update_name]) || empty($_SESSION[$update_name]['search'])) {

    // Find all nids that have date fields and store them in an array.
    $tables = array();
    $_SESSION[$update_name]['search'] = array();
    $_SESSION[$update_name]['fields'] = array();
    $fields = content_fields();
    foreach ($fields as $field) {
      if ($field['type'] == 'date' || $field['type'] == 'datestamp') {
        $_SESSION[$update_name]['fields'][$field['field_name']] = $field;
        $db_info = content_database_info($field);
        $tables[] = $db_info['table'];
      }
    }

    // keep track of progress
    $_SESSION[$update_name]['counted'] = 0;
    $tables = array_unique($tables);
    foreach ($tables as $table) {
      $result = db_query("SELECT nid, vid FROM {" . $table . "} ORDER BY nid, vid");
      while ($row = db_fetch_array($result)) {
        $_SESSION[$update_name]['search'][] = $row['nid'] . ':' . $row['vid'];
      }
    }
    sort($_SESSION[$update_name]['search']);
    $_SESSION[$update_name]['search_all'] = $_SESSION[$update_name]['search'];
    $_SESSION[$update_name]['count_total'] = count($_SESSION[$update_name]['search']);
    $_SESSION[$update_name]['counted'] = 0;
  }
  $_SESSION[$update_name]['changed'] = array();
  $_SESSION[$update_name]['unchanged'] = array();

  // Do 5 updates in each pass.
  for ($i = 0; $i <= 5; $i++) {
    $update = !empty($_SESSION[$update_name]['search']) ? array_shift($_SESSION[$update_name]['search']) : array();
    if (!empty($update)) {
      $ids = explode(':', $update);
      $node = node_load($ids[0], $ids[1]);

      // Iterate through all the date fields in this node and re-compute
      // values to make sure they are correct.
      $needs_fix = FALSE;
      foreach ($_SESSION[$update_name]['fields'] as $field_name => $field) {
        $items = (array) $node->{$field_name};
        $add = array();
        foreach ($items as $delta => $item) {

          // Check for non-required fields that still have the old default values and make them NULL.
          if ($field['type'] == 'date' && !$field['required'] && (substr($item['value'], 0, 10) == '0000-00-00' || substr($item['value'], 0, 10) == '0001-00-00')) {
            $item['value'] = NULL;
            $needs_fix = TRUE;
          }
          if ($field['type'] == 'datestamp' && !$field['required'] && empty($item['value'])) {
            $item['value'] = NULL;
            $needs_fix = TRUE;
          }
          $add[$delta]['value'] = $item['value'];

          // Check for missing todates.
          if ($field['todate']) {
            if (empty($item['value2']) && !empty($item['value']) || $force_recalc) {
              $needs_fix = TRUE;
            }
            $add[$delta]['value2'] = !empty($item['value2']) ? $item['value2'] : $item['value'];
          }

          // Check for missing timezone and offset information.
          if ($field['tz_handling'] == 'date') {
            if (empty($item['offset']) || empty($item['timezone']) || $force_recalc) {
              $needs_fix = TRUE;
              $timezone = date_get_timezone($field['tz_handling'], $item['timezone']);
              $date = date_make_date($item['value'], 'GMT', $field['type']);
              if (!empty($date) && !empty($timezone)) {
                date_timezone_set($date, timezone_open($timezone));
                $add[$delta]['timezone'] = $field['required'] || $item['value'] ? $timezone : NULL;
                $add[$delta]['offset'] = $field['required'] || $item['value'] ? date_offset_get($date) : NULL;
              }
              $date = date_make_date($item['value2'], 'GMT', $field['type']);
              if (!empty($date) && !empty($timezone)) {
                date_timezone_set($date, timezone_open($timezone));
                $add[$delta]['offset2'] = $field['required'] || $item['value'] ? date_offset_get($date) : NULL;
              }
            }
          }
        }
        if (!empty($add)) {
          $node->{$field_name} = $add;
        }
      }
      $_SESSION[$update_name]['counted']++;
      if ($needs_fix) {

        //node_submit($node);
        node_save($node);
        $_SESSION[$update_name]['changed'][] = $node->nid . ($node->vid != $node->nid ? ':' . $node->vid : '');
      }
      else {
        $_SESSION[$update_name]['unchanged'][] = $node->nid . ($node->vid != $node->nid ? ':' . $node->vid : '');
      }
    }
  }

  // See if we are done
  if ($_SESSION[$update_name]['counted'] && $_SESSION[$update_name]['count_total'] && $_SESSION[$update_name]['counted'] < $_SESSION[$update_name]['count_total']) {

    // Not done yet. Return the progress and a progress debug message.
    $progress = floatval($_SESSION[$update_name]['counted'] / $_SESSION[$update_name]['count_total']);
    if ($debug) {
      $message = 'Date data integrity check. Total nodes checked: ' . $_SESSION[$update_name]['counted'] . '<br />Updated nodes: ' . implode(', ', $_SESSION[$update_name]['changed']) . '<br />Unchanged nodes: ' . implode(', ', $_SESSION[$update_name]['unchanged']);
    }
    if ($debug) {
      return array(
        '#finished' => $progress,
        array(
          'success' => TRUE,
          'query' => $message,
        ),
      );
    }
    else {
      return array(
        '#finished' => $progress,
      );
    }
  }
  else {

    // Done. Clean up and indicate we're finished.
    drupal_set_message(t('All nodes with date fields have been checked.'));
    $message = 'Date data integrity check. Total nodes checked: ' . $_SESSION[$update_name]['counted'];
    if ($debug) {
      $message .= '<br />Updated nodes: ' . implode(', ', $_SESSION[$update_name]['changed']) . '<br />Unchanged nodes: ' . implode(', ', $_SESSION[$update_name]['unchanged']);
    }
    unset($_SESSION[$update_name]);
    content_clear_type_cache();
    db_query('DELETE FROM {cache_content}');
    return array(
      '#finished' => 1,
      array(
        'success' => TRUE,
        'query' => $message,
      ),
    );
  }
}

Functions

Namesort descending Description
date_data_integrity Progressive update of date information, integrity checking of all date values.
date_db_integrity
date_disable Implementation of hook_disable(). Empty the date caches.
date_enable Implementation of hook_enable(). Reset the calendar caches.
date_install Implementation of hook_install(). Reset the date caches.
date_install_load
date_uninstall Implementation of hook_uninstall().
date_update_5100 Prepare for Version 5.2 updates, make changes to field and widget settings.
date_update_5101 Date offsets were not getting saved. Need to repair the database. Superceded by update 5103().
date_update_5102 Make sure date module loads after date_api.
date_update_5103 Data integrity update, moved to Version 2 because it can make lots of db changes and we want people to be prepared for a significant change.
date_update_5104 Move these caches from 'cache' to 'cache_views' so they get cleared automatically whenever views_invalidate_cache() is called.
date_update_5200 Version 5.2 updates.
date_update_5201 Get rid of jscalendar popup and use jQuery popup instead.
date_update_5202 Database integrity update, supercedes most previous data integrity updates.
date_update_5203 Data integrity update, supercedes most previous data integrity updates.
date_update_5204 Get rid of deprecated timezone names.
date_update_5205
date_update_last_removed