You are here

function date_data_integrity in Date 5

Same name and namespace in other branches
  1. 5.2 date/date.install \date_data_integrity()
  2. 6 date/date.install \date_data_integrity()

Progressive update of date information, integrity checking of all date values.

Parameters

name - name of the update:

File

./date.install, line 379

Code

function date_data_integrity($name, $force_recalc = FALSE) {

  // Use this to turn extra debugging on or off.
  $debug = TRUE;

  // The number of nodes to process in each pass.
  $limit = 5;
  $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',
    ));
  }
  include_once drupal_get_path('module', 'content') . '/content.module';
  include_once drupal_get_path('module', 'content') . '/content_admin.inc';
  include_once drupal_get_path('module', 'date_api') . '/date.inc';
  include_once drupal_get_path('module', 'date') . '/date.module';
  include_once drupal_get_path('module', 'date') . '/date_timezones.inc';
  $fields = content_fields();

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

    // Find all tables that have date fields and store them in an array.
    // There could be more than one date field in each table,
    // so store fields as sub-array.
    $update = array();
    foreach ($fields as $field) {
      $db_info = content_database_info($field);
      if ($field['type'] == 'date' || $field['type'] == 'datestamp') {
        $update[$db_info['table']][$field['field_name']] = $field;
      }
    }

    // keep track of progress
    $_SESSION[$update_name]['tables'] = $update;
    $_SESSION[$update_name]['counted'] = 0;
    foreach ($update as $table => $field) {
      $_SESSION[$update_name][$table]['nid'] = 0;
      $_SESSION[$update_name][$table]['to_count'] = db_result(db_query("SELECT COUNT(nid) FROM {" . $table . "}"));
      $_SESSION[$update_name]['count_total'] += $_SESSION[$update_name][$table]['to_count'];
    }
  }
  $update = $_SESSION[$update_name]['tables'];
  if ($debug) {
    $_SESSION[$update_name]['nids'] = array();
    $_SESSION[$update_name]['nids_ok'] = array();
    $_SESSION[$update_name]['dates'] = array();
  }

  // Fetch the next $limit nodes
  $i = 0;
  foreach ($update as $table => $fields) {
    $results = db_query_range("SELECT nid FROM {" . $table . "} WHERE nid > %d ORDER BY nid", $_SESSION[$update_name][$table]['nid'], 0, $limit);
    while ($arr = db_fetch_array($results)) {
      $node = node_load($arr['nid']);

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

          // 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', 'db', $field['type'] == 'date' ? DATE_ISO : DATE_UNIX);
              date_convert_timezone($date, 'GMT', $timezone, 'local');
              $add[$delta]['timezone'] = $field['required'] || $item['value'] ? $timezone : NULL;
              $add[$delta]['offset'] = $field['required'] || $item['value'] ? $date->local->offset : NULL;
            }
          }
        }
        $node->{$field}['field_name'] = $add;

        // Debugging information.
        if ($debug) {
          $_SESSION[$update_name]['dates'][$i] = $node->nid . ' > Value: ' . (!empty($add[$delta]['value']) ? $add[$delta]['value'] : 'set to NULL');
          if (!empty($add[$delta]['value2'])) {
            $_SESSION[$update_name]['dates'][$i] .= ' > Value2: ' . (!empty($add[$delta]['value2']) ? $add[$delta]['value2'] : 'set to NULL');
          }
          if ($field['tz_handling'] == 'date' && isset($date)) {
            $_SESSION[$update_name]['dates'][$i] .= ' > Computed timezone: ' . $date->local->timezone . ' > Computed offset: ' . $date->local->offset;
          }
        }
        $i++;
      }

      // More debugging information.
      if ($debug) {
        if ($needs_fix) {
          $_SESSION[$update_name]['nids'][] = $node->nid;
        }
        else {
          $_SESSION[$update_name]['nids_ok'][] = $node->nid;
        }
      }
      if ($needs_fix) {
        node_submit($node);
        node_save($node);
      }

      // reset nid
      $_SESSION[$update_name][$table]['nid'] = $node->nid;

      // add to count total
      $_SESSION[$update_name]['counted']++;

      // reduce the number of items in this table left to count
      $_SESSION[$update_name][$table]['to_count']--;
    }

    // if everything in this table has been done, move to next table
    if ($_SESSION[$update_name][$table]['to_count'] < 1) {
      array_shift($_SESSION[$update_name]['tables']);
    }

    // See if we are done
    if ($_SESSION[$update_name]['counted'] && $_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]['nids']) . '<br>Unchanged nodes: ' . implode(', ', $_SESSION[$update_name]['nids_ok']) . '<br>Date Computations:<br>' . implode('<br>', $_SESSION[$update_name]['dates']);
        unset($_SESSION[$update_name]['nids']);
        unset($_SESSION[$update_name]['nids_ok']);
        unset($_SESSION[$update_name]['dates']);
      }
      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]['nids']) . '<br>Unchanged nodes: ' . implode(', ', $_SESSION[$update_name]['nids_ok']) . '<br>Date Computations:<br>' . implode('<br>', $_SESSION[$update_name]['dates']);
      }
      unset($_SESSION[$update_name]);
      content_clear_type_cache();
      db_query('DELETE FROM {cache_content}');
      return array(
        '#finished' => 1,
        array(
          'success' => TRUE,
          'query' => $message,
        ),
      );
    }
  }
}