Index: date.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/date/date.css,v
retrieving revision 1.20.4.11
diff -u -p -r1.20.4.11 date.css
--- date.css	12 Aug 2008 19:30:22 -0000	1.20.4.11
+++ date.css	17 Oct 2008 10:00:03 -0000
@@ -141,4 +141,18 @@ span.date-display-separator {
 .date-clear-block {
   display: block;
 }
-/* End hide from IE-mac */
\ No newline at end of file
+/* End hide from IE-mac */
+
+.date-format-settings .form-item {
+  float: left;
+  margin-right: 1em;
+}
+
+.date-format-settings .date-format-title {
+  clear: left;
+}
+
+.date-format-settings .date-format-delete {
+  padding-top: 3em;
+}
+
Index: date_format/date_format.info
===================================================================
RCS file: date_format/date_format.info
diff -N date_format/date_format.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ date_format/date_format.info	17 Oct 2008 10:00:03 -0000
@@ -0,0 +1,6 @@
+; $Id$
+name = Date Format
+description = Allows the site admin to configure multiple formats for date/time display to taylor dates for a specific locale or audience.
+package = Date/Time
+dependencies[] = date_api
+core = 6.x
Index: date_format/date_format.install
===================================================================
RCS file: date_format/date_format.install
diff -N date_format/date_format.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ date_format/date_format.install	17 Oct 2008 10:00:03 -0000
@@ -0,0 +1,73 @@
+<?php
+// $Id$
+
+function date_format_schema() {
+  $schema['date_format'] = array(
+    'description' => t('For storing configured date formats.'),
+    'fields' => array(
+      'dfid' => array(
+        'description' => t('The primary identifier for a date format.'),
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE
+      ),
+      'title' => array(
+        'description' => t('Name of the date format.'),
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+      ),
+      'format' => array(
+        'description' => t('The date format string.'),
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+      ),
+    ),
+    'primary key' => array('dfid'),
+  );
+
+  $schema['date_format_locale'] = array(
+    'description' => t('For storing configured date formats for each locale.'),
+    'fields' => array(
+      'language' => array(
+        'description' => t('Language code.'),
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+      ),
+      'format_type' => array(
+        'description' => t('Format type - short, medium or large.'),
+        'type' => 'varchar',
+        'length' => 10,
+        'not null' => TRUE,
+      ),
+      'dfid' => array(
+        'description' => t('The primary identifier for a date format.'),
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE
+      ),
+    ),
+    'primary key' => array('language', 'format_type'),
+  );
+  return $schema;
+}
+
+
+function date_format_install() {
+  drupal_install_schema('date_format');
+  $date_format_short = variable_get('date_format_short', 'm/d/Y - H:i');
+  variable_set('date_format_short_default', $date_format_short);
+  $date_format_medium = variable_get('date_format_medium', 'D, m/d/Y - H:i');
+  variable_set('date_format_medium_default', $date_format_medium);
+  $date_format_long = variable_get('date_format_long', 'l, F j, Y - H:i');
+  variable_set('date_format_long_default', $date_format_long);
+}
+
+function date_format_uninstall() {
+  drupal_uninstall_schema('date_format');
+  variable_del('date_format_short_default');
+  variable_del('date_format_medium_default');
+  variable_del('date_format_long_default');
+}
Index: date_format/date_format.module
===================================================================
RCS file: date_format/date_format.module
diff -N date_format/date_format.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ date_format/date_format.module	17 Oct 2008 10:00:04 -0000
@@ -0,0 +1,490 @@
+<?php
+// $Id$
+/**
+ * @file
+ * Enable different locales to have their own date formats.
+ */
+
+/**
+ * Implementation of hook_init().
+ */
+function date_format_init() {
+  global $conf;
+  global $language;
+  $languages = array($language->language);
+  drupal_alter('date_format_languages', $languages);
+  $formats = date_format_get_locale_date_format($languages);
+  foreach ($formats as $format_type => $format) {
+    $conf[$format_type] = $format;
+  }
+}
+
+/**
+ * Implementation of hook_menu().
+ */
+function date_format_menu() {
+  $items = array();
+  $items['admin/settings/date-time/delete/%'] = array(
+    'title' => 'Delete date format',
+    'description' => 'Allow users to delete a configured date format.',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('date_format_delete_format_form', 4),
+    'access arguments' => array('administer site configuration'),
+  );
+  $items['admin/settings/date-time/formats'] = array(
+    'title' => 'Formats',
+    'description' => 'Allow users to modify date formats.',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('date_format_edit_formats_form'),
+    'access arguments' => array('administer site configuration'),
+    'weight' => 1,
+  );
+  $items['admin/settings/date-time/add-format'] = array(
+    'title' => 'Add format',
+    'description' => 'Allow users to add date formats.',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('date_format_add_format_form'),
+    'access arguments' => array('administer site configuration'),
+    'weight' => 1,
+  );
+  return $items;
+}
+
+/**
+ * Implementation of hook_menu_alter().
+ */
+function date_format_menu_alter(&$callbacks) {
+  $callbacks['admin/settings/date-time/configure'] = $callbacks['admin/settings/date-time'];
+  $callbacks['admin/settings/date-time/configure']['type'] = MENU_DEFAULT_LOCAL_TASK;
+
+  $callbacks['admin/settings/date-time']['page callback'] = 'date_format_menu_callback';
+  $form = $callbacks['admin/settings/date-time']['page arguments'][0];
+  $callbacks['admin/settings/date-time']['page arguments'] = array('drupal_get_form', $form);
+}
+
+/**
+ * Wrapper function to be able to set menu callbacks.
+ */
+function date_format_menu_callback() {
+  $args = func_get_args();
+  $function = array_shift($args);
+  return call_user_func_array($function, $args);
+}
+
+/**
+ * Implementation of hook_form_alter().
+ *
+ * Override system handling of date format selection.
+ */
+function date_format_form_system_date_time_settings_alter(&$form, $form_state, $form_id = 'system_date_time_settings') {
+  $form['date_formats'] = NULL;
+}
+
+
+/**
+ * Allow users to modify date format settings.
+ */
+function date_format_edit_formats_form($form_state) {
+  $form = array();
+
+  // Get default settings.
+  module_load_include('inc', 'system', 'system.admin');
+  $date_form = system_date_time_settings();
+  $form['default_date_formats'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Default formatting'),
+    '#description' => t("Formatting to be used if no per-language date settings are available for the user's locale."),
+  );
+  $form['default_date_formats']['date_format_short_default'] = $date_form['date_formats']['date_format_short'];
+  $form['default_date_formats']['date_format_medium_default'] = $date_form['date_formats']['date_format_medium'];
+  $form['default_date_formats']['date_format_long_default'] = $date_form['date_formats']['date_format_long'];
+
+  // Need to overwrite the default values so it's _not_ for the current language / country.
+  // variable_get('date_format_short', ...) is returning the default for the
+  // current language / country because of our implementation of hook_init().
+  $form['default_date_formats']['date_format_short_default']['#default_value'] = variable_get('date_format_short_default', 'm/d/Y - H:i');
+  $form['default_date_formats']['date_format_medium_default']['#default_value'] = variable_get('date_format_medium_default', 'D, m/d/Y - H:i');
+  $form['default_date_formats']['date_format_long_default']['#default_value'] = variable_get('date_format_long_default', 'l, F j, Y - H:i');
+
+
+  // Add custom formats.
+  $formats = date_format_get_formats();
+
+  if (count($formats)) {
+    $form['date_formats'] = array(
+      '#title' => t('Formatting'),
+      '#description' => t('If entering a custom date format, see the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://php.net/manual/function.date.php')),
+      '#type' => 'fieldset',
+      '#tree' => TRUE,
+      '#attributes' => array('class' => 'date-format-settings'),
+    );
+
+    foreach ($formats as $format) {
+      date_format_format_fields(&$form, $format);
+    }
+
+    $form = system_settings_form($form);
+    $form['#submit'][] = 'date_format_date_time_settings_submit';
+  }
+  else {
+    drupal_set_message(t('No custom formats configured. Please <a href="@link">add</a> one.', array('@link' => url('admin/settings/date-time/add-format'))), 'error');
+  }
+
+  return $form;
+}
+
+
+/**
+ * Allow users to add date format settings.
+ */
+function date_format_add_format_form($form_state) {
+  $form = array();
+
+  $form['date_formats'] = array(
+    '#title' => t('Formatting'),
+    '#description' => t('If entering a custom date format, see the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://php.net/manual/function.date.php')),
+    '#type' => 'fieldset',
+    '#tree' => TRUE,
+    '#attributes' => array('class' => 'date-format-settings'),
+  );
+
+  // TODO: It would be more Drupally to do this on a separate page or add AHAH, rather than "save for more".
+  $format = new stdClass();
+  $format->dfid = 'new';
+
+  date_format_format_fields(&$form, $format);
+
+  $form['buttons']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save configuration'),
+  );
+  $form['#submit'][] = 'date_format_add_date_time_settings_submit';
+
+  return $form;
+}
+
+/**
+ * Helper function; return form fields for a particular date format.
+ */
+function date_format_format_fields(&$form, $format) {
+  require_once('./'. drupal_get_path('module', 'date') .'/date_admin.inc');
+  $options = date_format_list();
+  $form['date_formats'][$format->dfid]['title'] = array(
+    '#title' => t('Date format name'),
+    '#type' => 'textfield',
+    '#default_value' => check_plain($format->title),
+    '#size' => 20,
+    '#prefix' => '<div class="date-format-title">',
+    '#suffix' => '</div>',
+  );
+  $form['date_formats'][$format->dfid]['format'] = array(
+    '#title' => t('Date display'),
+    '#type' => 'select',
+    '#options' => $options,
+    '#multiple' => false,
+  );
+  // TODO: Add a little javascript to hide this until 'Custom' is selected.
+  $form['date_formats'][$format->dfid]['custom'] = array(
+    '#title' => t('Custom display format'),
+    '#type' => 'textfield',
+    '#size' => 20,
+  );
+  if ($format->dfid != 'new') {
+    $form['date_formats'][$format->dfid]['delete'] = array(
+      '#value' => '<div class="date-format-delete">' . l(t('remove'), 'admin/settings/date-time/delete/' . $format->dfid) . '</div>',
+    );
+  }
+
+  // Set for existing formats, using 'custom' if it is not a standard format.
+  if (isset($options[$format->format])) {
+    $form['date_formats'][$format->dfid]['format']['#default_value'] = check_plain($format->format);
+  }
+  else {
+    $form['date_formats'][$format->dfid]['format']['#default_value'] = 'custom';
+    $form['date_formats'][$format->dfid]['custom']['#default_value'] = check_plain($format->format);
+  }
+}
+
+/**
+ * Save date format(s) to the database.
+ */
+function date_format_date_time_settings_submit($form, &$form_state) {
+  foreach ($form_state['values']['date_formats'] as $dfid => $format) {
+    // If 'custom' is selected and custom text field is completed we store that.
+    if ($format['format'] == 'custom' && !empty($format['custom'])) {
+      $format['format'] = $format['custom'];
+    }
+    $format['dfid'] = $dfid;
+    drupal_write_record('date_format', $format, 'dfid');
+  }
+
+  // Update the default variable.
+  variable_set('date_format_short', $form_state['values']['date_format_short_default']);
+  variable_set('date_format_medium', $form_state['values']['date_format_medium_default']);
+  variable_set('date_format_long', $form_state['values']['date_format_long_default']);
+
+  // Unset, to prevent this getting saved as a variable
+  unset($form_state['values']['date_formats']);
+}
+
+
+/**
+ * Add date format to the database.
+ */
+function date_format_add_date_time_settings_submit($form, &$form_state) {
+  foreach ($form_state['values']['date_formats'] as $dfid => $format) {
+    // If 'custom' is selected and custom text field is completed we store that.
+    if ($format['format'] == 'custom' && !empty($format['custom'])) {
+      $format['format'] = $format['custom'];
+    }
+    $format['dfid'] = 'new';
+
+    drupal_write_record('date_format', $format);
+  }
+
+  // Unset, to prevent this getting saved as a variable
+  unset($form_state['values']['date_formats']);
+}
+
+/**
+ * Menu callback; present a form for deleting a date format.
+ */
+function date_format_delete_format_form(&$form_state, $dfid) {
+  $form = array();
+  $form['dfid'] = array(
+    '#type' => 'value',
+    '#value' => $dfid,
+  );
+
+  $format = date_format_get_format($dfid);
+
+  $output = confirm_form($form,
+    t('Are you sure you want to remove the format %format?', array('%format' => $format->title)),
+    'admin/settings/date-time/formats',
+    t('This action cannot be undone.'),
+    t('Remove'), t('Cancel'),
+    'confirm'
+  );
+
+  return $output;
+}
+
+/**
+ * Delete a configured date format.
+ */
+function date_format_delete_format_form_submit($form, &$form_state) {
+  if ($form_state['values']['confirm']) {
+    $format = date_format_get_format($form_state['values']['dfid']);
+    db_query('DELETE FROM {date_format} WHERE dfid = %d', $form_state['values']['dfid']);
+    drupal_set_message(t('Removed date format %format.', array('%format' => $format->title)));
+    $form_state['redirect'] = 'admin/settings/date-time/formats';
+  }
+}
+
+/**
+ * Implementation of hook_form_alter().
+ *
+ * Add per language date settings.
+ */
+function date_format_form_locale_languages_edit_form_alter(&$form, $form_state, $form_id = 'locale_languages_edit_form') {
+  if (module_exists('locale')) {
+    $form['submit']['#weight'] = 2;
+
+    $form['date_formats'] = array(
+      '#title' => t('Date formatting'),
+      '#type' => 'fieldset',
+      '#attributes' => array('class' => 'locale-date-format-settings'),
+      '#weight' => 1,
+      '#collapsible' => TRUE,
+      '#collapsed' => FALSE,
+    );
+
+    // Get list of configured formats.
+    $formats = date_format_get_format_list();
+    $formats[''] = t('Default');
+
+    if (count($formats) > 1) {
+      // Get current settings.
+      $settings = array('short' => '', 'medium' => '', 'long' => '');
+      $result = db_query("SELECT format_type, dfid FROM {date_format_locale} WHERE language = '%s'", $form['langcode']['#value']);
+      while ($format = db_fetch_object($result)) {
+        $settings[$format->format_type] = $format->dfid;
+      }
+
+      $form['date_formats']['date_format_short'] = array(
+        '#title' => t('Short date format'),
+        '#type' => 'select',
+        '#options' => $formats,
+        '#multiple' => false,
+        '#default_value' => $settings['short'],
+      );
+
+      $form['date_formats']['date_format_medium'] = array(
+        '#title' => t('Medium date format'),
+        '#type' => 'select',
+        '#options' => $formats,
+        '#multiple' => false,
+        '#default_value' => $settings['medium'],
+      );
+
+      $form['date_formats']['date_format_long'] = array(
+        '#title' => t('Long date format'),
+        '#type' => 'select',
+        '#options' => $formats,
+        '#multiple' => false,
+        '#default_value' => $settings['long'],
+      );
+    }
+    else {
+      $form['date_formats']['message'] = array(
+        '#value' => '<p>' . t('No date formats configured.  Formats can be added <a href="@link">here</a>.', array('@link' => url('admin/settings/date-time/add-format'))) . '</p>',
+      );
+    }
+
+
+    $form['#submit'][] = 'date_format_locale_date_time_settings_submit';
+  }
+}
+
+/**
+ * Save locale date formats to the database.
+ */
+function date_format_locale_date_time_settings_submit($form, &$form_state) {
+  $primary_keys = array('language', 'format_type');
+  $langcode = $form_state['values']['langcode'];
+
+  $types = array();
+  $result = db_query("SELECT format_type FROM {date_format_locale} WHERE language = '%s'", $langcode);
+  while ($type = db_fetch_object($result)) {
+    $types[] = $type->format_type;
+  }
+
+  date_format_write_locale_record($langcode, 'short', $form_state['values']['date_format_short'], $types);
+  date_format_write_locale_record($langcode, 'medium', $form_state['values']['date_format_medium'], $types);
+  date_format_write_locale_record($langcode, 'long', $form_state['values']['date_format_long'], $types);
+
+  // Unset, to prevent this getting saved as a variable
+  unset($form_state['values']['date_formats']);
+}
+
+
+/**
+ * Write a record to the date_format_locale table.
+ *
+ * @param $langcode
+ *   Language code.
+ * @param $size
+ *   Date format size - one of 'short', 'medium', 'large'.
+ * @param $dfid
+ *   Date format id.
+ * @param $types
+ *   Array of current format sizes available for this language.
+ */
+function date_format_write_locale_record($langcode, $size, $dfid, $types) {
+  $primary_keys = array('language', 'format_type');
+
+  $format = new stdClass();
+  $format->language = $langcode;
+  $format->format_type = $size;
+  $format->dfid = $dfid;
+  if (in_array($size, $types)) {
+    drupal_write_record('date_format_locale', $format, $primary_keys);
+  }
+  else {
+    drupal_write_record('date_format_locale', $format);
+  }
+}
+
+/**
+ * Retrieve list of all available date formats for date format configuration
+ * form.
+ */
+function date_format_list() {
+  return module_invoke_all('date_format');
+}
+
+/**
+ * Implementation of hook_date_format().
+ */
+function date_format_date_format() {
+  require_once('./'. drupal_get_path('module', 'date') .'/date_admin.inc');
+  $options = date_format_options();
+  $options['custom'] = t('Custom');
+  return $options;
+}
+
+/**
+ * Select date format details from database.
+ *
+ * @param $dfid
+ *   Date format identifier.
+ */
+function date_format_get_format($dfid) {
+  $result = db_query('SELECT * FROM {date_format} WHERE dfid = %d', $dfid);
+  $format = db_fetch_object($result);
+  return $format;
+}
+
+/**
+ * Select locale date format details from database.
+ *
+ * @param $languages
+ *   An array of language codes.
+ * @return
+ *   An array of date formats.
+ */
+function date_format_get_locale_date_format($languages) {
+  $formats = array();
+
+  foreach ($languages as $language) {
+    $result = db_query("SELECT l.format_type, d.format FROM {date_format} d INNER JOIN {date_format_locale} l ON l.dfid = d.dfid WHERE l.language = '%s'", $language);
+    while ($format = db_fetch_object($result)) {
+      $formats['date_format_' . $format->format_type] = $format->format;
+    }
+    // Return on the first match.
+    return $formats;
+  }
+
+  // No locale specific formats found, so use defaults.
+  $formats['date_format_short'] = variable_get('date_format_short', 'm/d/Y - H:i');
+  $formats['date_format_medium'] = variable_get('date_format_medium', 'D, m/d/Y - H:i');
+  $formats['date_format_long'] = variable_get('date_format_long', 'l, F j, Y - H:i');
+
+  return $formats;
+}
+
+/**
+ * Select all date format details from database.
+ *
+ * @return
+ *   An array of date format objects containing dfid, title and format.
+ */
+function date_format_get_formats() {
+  $formats = array();
+  $result = db_query('SELECT * FROM {date_format}');
+  while ($format = db_fetch_object($result)) {
+    $formats[] = $format;
+  }
+  return $formats;
+}
+
+
+/**
+ * Select list of date format details from database.
+ *
+ * @return
+ *   An array of date format titles indexed by dfid.
+ */
+function date_format_get_format_list() {
+  $formats = array();
+  $result = db_query('SELECT * FROM {date_format} ORDER BY title');
+  while ($format = db_fetch_object($result)) {
+    $formats[$format->dfid] = check_plain($format->title);
+  }
+  return $formats;
+}
+
+
