From 04d0ef5c8ce2646aeb3879f656e34a3836110ff2 Mon Sep 17 00:00:00 2001 From: Dries Buytaert Date: Tue, 13 Oct 2009 21:34:15 +0000 Subject: =?UTF-8?q?-=20Patch=20#11623=20by=20sun,=20stella,=20G=C3=A1bor?= =?UTF-8?q?=20Hojtsy,=20Pancho:=20add=20ability=20to=20localize=20date=20f?= =?UTF-8?q?ormats.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/system/system.admin.inc | 470 +++++++++++++++++++++++++++++++--------- modules/system/system.api.php | 104 +++++++++ modules/system/system.install | 179 +++++++++++++++ modules/system/system.js | 26 +-- modules/system/system.module | 446 +++++++++++++++++++++++++++++++++++++- modules/system/system.test | 80 +++++++ 6 files changed, 1187 insertions(+), 118 deletions(-) (limited to 'modules/system') diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc index 190128b4a..dbc02b607 100644 --- a/modules/system/system.admin.inc +++ b/modules/system/system.admin.inc @@ -1592,16 +1592,13 @@ function system_rss_feeds_settings() { } /** - * Form builder; Configure the site date and time settings. + * Form builder; Configure the site regional settings. * * @ingroup forms * @see system_settings_form() * @see system_regional_settings_submit() */ function system_regional_settings() { - drupal_add_js(drupal_get_path('module', 'system') . '/system.js'); - drupal_add_js(array('dateTime' => array('lookup' => url('admin/config/regional/settings/lookup'))), 'setting'); - include_once DRUPAL_ROOT . '/includes/locale.inc'; $countries = country_get_list(); // Add a 'No default country' option to the start of the list. @@ -1610,31 +1607,6 @@ function system_regional_settings() { // Date settings: $zones = system_time_zones(); - // Date settings: possible date formats - $date_short = array('Y-m-d H:i', 'm/d/Y - H:i', 'd/m/Y - H:i', 'Y/m/d - H:i', - 'd.m.Y - H:i', 'm/d/Y - g:ia', 'd/m/Y - g:ia', 'Y/m/d - g:ia', - 'M j Y - H:i', 'j M Y - H:i', 'Y M j - H:i', - 'M j Y - g:ia', 'j M Y - g:ia', 'Y M j - g:ia'); - $date_medium = array('D, Y-m-d H:i', 'D, m/d/Y - H:i', 'D, d/m/Y - H:i', - 'D, Y/m/d - H:i', 'F j, Y - H:i', 'j F, Y - H:i', 'Y, F j - H:i', - 'D, m/d/Y - g:ia', 'D, d/m/Y - g:ia', 'D, Y/m/d - g:ia', - 'F j, Y - g:ia', 'j F Y - g:ia', 'Y, F j - g:ia', 'j. F Y - G:i'); - $date_long = array('l, F j, Y - H:i', 'l, j F, Y - H:i', 'l, Y, F j - H:i', - 'l, F j, Y - g:ia', 'l, j F Y - g:ia', 'l, Y, F j - g:ia', 'l, j. F Y - G:i'); - - // Date settings: construct choices for user - foreach ($date_short as $f) { - $date_short_choices[$f] = format_date(REQUEST_TIME, 'custom', $f); - } - foreach ($date_medium as $f) { - $date_medium_choices[$f] = format_date(REQUEST_TIME, 'custom', $f); - } - foreach ($date_long as $f) { - $date_long_choices[$f] = format_date(REQUEST_TIME, 'custom', $f); - } - - $date_long_choices['custom'] = $date_medium_choices['custom'] = $date_short_choices['custom'] = t('Custom format'); - $form['locale'] = array( '#type' => 'fieldset', '#title' => t('Locale'), @@ -1699,97 +1671,214 @@ function system_regional_settings() { '#description' => t('Only applied if users may set their own time zone.') ); - $form['date_formats'] = array( - '#type' => 'fieldset', - '#title' => t('Date formats'), - ); + return system_settings_form($form, FALSE); +} - $date_format_short = variable_get('date_format_short', $date_short[1]); - $form['date_formats']['date_format_short'] = array( - '#prefix' => '
', - '#suffix' => '
', - '#type' => 'select', - '#title' => t('Short date format'), - '#attributes' => array('class' => array('date-format')), - '#default_value' => (isset($date_short_choices[$date_format_short]) ? $date_format_short : 'custom'), - '#options' => $date_short_choices, - ); +/** + * Form builder; Configure the site date and time settings. + * + * @ingroup forms + * @see system_settings_form() + */ +function system_date_time_settings() { + // Get list of all available date types. + drupal_static_reset('system_get_date_types'); + $format_types = system_get_date_types(); + + // Get list of all available date formats. + $all_formats = array(); + drupal_static_reset('system_get_date_formats'); + $date_formats = system_get_date_formats(); // Call this to rebuild the list, and to have default list. + foreach ($date_formats as $type => $format_info) { + $all_formats = array_merge($all_formats, $format_info); + } + $custom_formats = system_get_date_formats('custom'); + if (!empty($format_types)) { + foreach ($format_types as $type => $type_info) { + // If a system type, only show the available formats for that type and + // custom ones. + if ($type_info['locked'] == 1) { + $formats = system_get_date_formats($type); + if (empty($formats)) { + $formats = $all_formats; + } + elseif (!empty($custom_formats)) { + $formats = array_merge($formats, $custom_formats); + } + } + // If a user configured type, show all available date formats. + else { + $formats = $all_formats; + } - $default_short_custom = variable_get('date_format_short_custom', (isset($date_short_choices[$date_format_short]) ? $date_format_short : '')); - $form['date_formats']['date_format_short_custom'] = array( - '#prefix' => '
', - '#suffix' => '
', - '#type' => 'textfield', - '#title' => t('Custom short date format'), - '#attributes' => array('class' => array('custom-format')), - '#default_value' => $default_short_custom, - '#description' => t('A user-defined short date format. See the PHP manual for available options. This format is currently set to display as %date.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(REQUEST_TIME, 'custom', $default_short_custom))), - ); + $choices = array(); + foreach ($formats as $f => $format) { + $choices[$f] = format_date(REQUEST_TIME, 'custom', $f); + } + $default = variable_get('date_format_' . $type, array_shift(array_keys($formats))); + + // Get date type info for this date type. + $type_info = system_get_date_types($type); + $form['formats']['#theme'] = 'system_date_time_settings'; + + // Show date format select list. + $form['formats']['format']['date_format_' . $type] = array( + '#type' => 'select', + '#title' => check_plain($type_info['title']), + '#attributes' => array('class' => array('date-format')), + '#default_value' => (isset($choices[$default]) ? $default : 'custom'), + '#options' => $choices, + ); - $date_format_medium = variable_get('date_format_medium', $date_medium[1]); - $form['date_formats']['date_format_medium'] = array( - '#prefix' => '
', - '#suffix' => '
', - '#type' => 'select', - '#title' => t('Medium date format'), - '#attributes' => array('class' => array('date-format')), - '#default_value' => (isset($date_medium_choices[$date_format_medium]) ? $date_format_medium : 'custom'), - '#options' => $date_medium_choices, + // If this isn't a system provided type, allow the user to remove it from + // the system. + if ($type_info['locked'] == 0) { + $form['formats']['delete']['date_format_' . $type . '_delete'] = array( + '#markup' => l(t('delete'), 'admin/config/regional/date-time/types/' . $type . '/delete'), + ); + } + } + } + + // Display a message if no date types configured. + $form['#empty_text'] = t('No date types available. Add date type.', array('@link' => url('admin/config/regional/date-time/types/add'))); + + return system_settings_form($form, FALSE); +} + +/** + * Theme function for date settings form. + * + * @ingroup themeable + */ +function theme_system_date_time_settings($variables) { + $form = $variables['form']; + $header = array( + t('Date type'), + t('Format'), + t('Operations'), ); - $default_medium_custom = variable_get('date_format_medium_custom', (isset($date_medium_choices[$date_format_medium]) ? $date_format_medium : '')); - $form['date_formats']['date_format_medium_custom'] = array( - '#prefix' => '
', - '#suffix' => '
', + foreach (element_children($form['format']) as $key) { + $delete_key = $key . '_delete'; + $row = array(); + $row[] = $form['format'][$key]['#title']; + unset($form['format'][$key]['#title']); + $row[] = array('data' => drupal_render($form['format'][$key])); + $row[] = array('data' => drupal_render($form['delete'][$delete_key])); + $rows[] = $row; + } + + $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'system-date-types'))); + $output .= drupal_render_children($form); + + return $output; +} + + +/** + * Add new date type. + * + * @ingroup forms + * @ingroup system_add_date_format_type_form_validate() + * @ingroup system_add_date_format_type_form_submit() + */ +function system_add_date_format_type_form($form, &$form_state) { + $form['date_type'] = array( + '#title' => t('Date type'), '#type' => 'textfield', - '#title' => t('Custom medium date format'), - '#attributes' => array('class' => array('custom-format')), - '#default_value' => $default_medium_custom, - '#description' => t('A user-defined medium date format. See the PHP manual for available options. This format is currently set to display as %date.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(REQUEST_TIME, 'custom', $default_medium_custom))), + '#required' => TRUE, + '#field_suffix' => '  ', + ); + $js_settings = array( + 'type' => 'setting', + 'data' => array( + 'machineReadableValue' => array( + 'date-type' => array( + 'text' => t('Machine name'), + 'target' => 'machine-name', + 'searchPattern' => '[^a-z0-9]+', + 'replaceToken' => '_', + ), + ), + ), + ); + $form['machine_name'] = array( + '#title' => t('Machine readable name'), + '#description' => t('The unique machine readable name for this date type, can only contain lowercase letters, numbers and underscores.'), + '#type' => 'textfield', + '#required' => TRUE, + '#attached' => array( + 'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings), + ), ); - $date_format_long = variable_get('date_format_long', $date_long[0]); - $form['date_formats']['date_format_long'] = array( - '#prefix' => '
', - '#suffix' => '
', + // Get list of all available date formats. + $formats = array(); + drupal_static_reset('system_get_date_formats'); + $date_formats = system_get_date_formats(); // Call this to rebuild the list, and to have default list. + foreach ($date_formats as $type => $format_info) { + $formats = array_merge($formats, $format_info); + } + $custom_formats = system_get_date_formats('custom'); + if (!empty($custom_formats)) { + $formats = array_merge($formats, $custom_formats); + } + $choices = array(); + foreach ($formats as $f => $format) { + $choices[$f] = format_date(REQUEST_TIME, 'custom', $f); + } + // Show date format select list. + $form['date_format'] = array( '#type' => 'select', - '#title' => t('Long date format'), + '#title' => t('Date format'), '#attributes' => array('class' => array('date-format')), - '#default_value' => (isset($date_long_choices[$date_format_long]) ? $date_format_long : 'custom'), - '#options' => $date_long_choices, + '#options' => $choices, + '#required' => TRUE, ); - $default_long_custom = variable_get('date_format_long_custom', (isset($date_long_choices[$date_format_long]) ? $date_format_long : '')); - $form['date_formats']['date_format_long_custom'] = array( - '#prefix' => '
', - '#suffix' => '
', - '#type' => 'textfield', - '#title' => t('Custom long date format'), - '#attributes' => array('class' => array('custom-format')), - '#default_value' => $default_long_custom, - '#description' => t('A user-defined long date format. See the PHP manual for available options. This format is currently set to display as %date.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(REQUEST_TIME, 'custom', $default_long_custom))), + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Add date type'), ); - $form = system_settings_form($form, FALSE); - // We will call system_settings_form_submit() manually, so remove it for now. - unset($form['#submit']); + $form['#validate'][] = 'system_add_date_format_type_form_validate'; + $form['#submit'][] = 'system_add_date_format_type_form_submit'; + return $form; } /** - * Process system_regional_settings form submissions. + * Validate system_add_date_format_type form submissions. */ -function system_regional_settings_submit($form, &$form_state) { - if ($form_state['values']['date_format_short'] == 'custom') { - $form_state['values']['date_format_short'] = $form_state['values']['date_format_short_custom']; - } - if ($form_state['values']['date_format_medium'] == 'custom') { - $form_state['values']['date_format_medium'] = $form_state['values']['date_format_medium_custom']; - } - if ($form_state['values']['date_format_long'] == 'custom') { - $form_state['values']['date_format_long'] = $form_state['values']['date_format_long_custom']; +function system_add_date_format_type_form_validate($form, &$form_state) { + if (!empty($form_state['values']['machine_name']) && !empty($form_state['values']['date_type'])) { + if (!preg_match("/^[a-zA-Z0-9_]+$/", trim($form_state['values']['machine_name']))) { + form_set_error('machine_name', t('The date type must contain only alphanumeric characters and underscores.')); + } + $types = system_get_date_types(); + if (in_array(trim($form_state['values']['machine_name']), array_keys($types))) { + form_set_error('machine_name', t('This date type already exists. Please enter a unique type.')); + } } - return system_settings_form_submit($form, $form_state); +} + +/** + * Process system_add_date_format_type form submissions. + */ +function system_add_date_format_type_form_submit($form, &$form_state) { + $machine_name = trim($form_state['values']['machine_name']); + + $format_type = array(); + $format_type['title'] = trim($form_state['values']['date_type']); + $format_type['type'] = $machine_name; + $format_type['locked'] = 0; + $format_type['is_new'] = 1; + system_date_format_type_save($format_type); + variable_set('date_format_' . $machine_name, $form_state['values']['date_format']); + + drupal_set_message(t('New date type added successfully.')); + $form_state['redirect'] = 'admin/config/regional/date-time'; } /** @@ -1931,7 +2020,7 @@ function system_php() { function system_batch_page() { require_once DRUPAL_ROOT . '/includes/batch.inc'; $output = _batch_page(); - + // Use the same theme that the page that started the batch. $batch = &batch_get(); $GLOBALS['custom_theme'] = $batch['theme']; @@ -2340,6 +2429,185 @@ function theme_system_themes_form($variables) { return $output; } +/** + * Menu callback; present a form for deleting a date format. + */ +function system_date_delete_format_form($form, &$form_state, $dfid) { + $form['dfid'] = array( + '#type' => 'value', + '#value' => $dfid, + ); + $format = system_get_date_format($dfid); + + $output = confirm_form($form, + t('Are you sure you want to remove the format %format?', array('%format' => format_date(REQUEST_TIME, 'custom', $format->format))), + 'admin/config/regional/date-time/formats', + t('This action cannot be undone.'), + t('Remove'), t('Cancel'), + 'confirm' + ); + + return $output; +} + +/** + * Delete a configured date format. + */ +function system_date_delete_format_form_submit($form, &$form_state) { + if ($form_state['values']['confirm']) { + $format = system_get_date_format($form_state['values']['dfid']); + system_date_format_delete($form_state['values']['dfid']); + drupal_set_message(t('Removed date format %format.', array('%format' => format_date(REQUEST_TIME, 'custom', $format->format)))); + $form_state['redirect'] = 'admin/config/regional/date-time/formats'; + } +} + +/** + * Menu callback; present a form for deleting a date type. + */ +function system_delete_date_format_type_form($form, &$form_state, $format_type) { + $form['format_type'] = array( + '#type' => 'value', + '#value' => $format_type, + ); + $type_info = system_get_date_types($format_type); + + $output = confirm_form($form, + t('Are you sure you want to remove the date type %type?', array('%type' => $type_info['title'])), + 'admin/config/regional/date-time', + t('This action cannot be undone.'), + t('Remove'), t('Cancel'), + 'confirm' + ); + + return $output; +} + +/** + * Delete a configured date type. + */ +function system_delete_date_format_type_form_submit($form, &$form_state) { + if ($form_state['values']['confirm']) { + $type_info = system_get_date_types($form_state['values']['format_type']); + system_date_format_type_delete($form_state['values']['format_type']); + drupal_set_message(t('Removed date type %type.', array('%type' => $type_info['title']))); + $form_state['redirect'] = 'admin/config/regional/date-time'; + } +} + + +/** + * Displays the date format strings overview page. + */ +function system_date_time_formats() { + $header = array(t('Format'), array('data' => t('Operations'), 'colspan' => '2')); + $rows = array(); + + drupal_static_reset('system_get_date_formats'); + $formats = system_get_date_formats('custom'); + if (!empty($formats)) { + foreach ($formats as $format) { + $row = array(); + $row[] = array('data' => format_date(REQUEST_TIME, 'custom', $format['format'])); + $row[] = array('data' => l(t('edit'), 'admin/config/regional/date-time/formats/' . $format['dfid'] . '/edit')); + $row[] = array('data' => l(t('delete'), 'admin/config/regional/date-time/formats/' . $format['dfid'] . '/delete')); + $rows[] = $row; + } + } + + if (empty($rows)) { + $rows[] = array(array('data' => t('No custom date formats available. Add date format.', array('@link' => url('admin/config/regional/date-time/formats/add'))), 'colspan' => '5', 'class' => array('message'))); + } + + $build['date_formats_table'] = array( + '#theme' => 'table', + '#header' => $header, + '#rows' => $rows, + ); + + return $build; +} + +/** + * Allow users to add additional date formats. + */ +function system_configure_date_formats_form($form, &$form_state, $dfid = 0) { + $js_settings = array( + 'type' => 'setting', + 'data' => array( + 'dateTime' => array( + 'date-format' => array( + 'text' => t('Displayed as'), + 'lookup' => url('admin/config/regional/date-time/formats/lookup'), + ), + ), + ), + ); + + if ($dfid) { + $form['dfid'] = array( + '#type' => 'value', + '#value' => $dfid, + ); + $format = system_get_date_format($dfid); + } + + $now = ($dfid ? t('Displayed as %date', array('%date' => format_date(REQUEST_TIME, 'custom', $format->format))) : ''); + + $form['date_format'] = array( + '#type' => 'textfield', + '#title' => t('Format string'), + '#description' => t('A user-defined date format. See the PHP manual for available options.', array('@url' => 'http://php.net/manual/function.date.php')), + '#default_value' => ($dfid ? $format->format : ''), + '#field_suffix' => ' ' . $now . '', + '#attached' => array( + 'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings), + ), + ); + + $form['update'] = array( + '#type' => 'submit', + '#value' => ($dfid ? t('Save format') : t('Add format')), + ); + + $form['#validate'][] = 'system_add_date_formats_form_validate'; + $form['#submit'][] = 'system_add_date_formats_form_submit'; + + return $form; +} + +/** + * Validate new date format string submission. + */ +function system_add_date_formats_form_validate($form, &$form_state) { + $formats = system_get_date_formats('custom'); + $format = trim($form_state['values']['date_format']); + if (!empty($formats) && in_array($format, array_keys($formats)) && (!isset($form_state['values']['dfid']) || $form_state['values']['dfid'] != $formats[$format]['dfid'])) { + form_set_error('date_format', t('This format already exists. Please enter a unique format string.')); + } +} + +/** + * Process new date format string submission. + */ +function system_add_date_formats_form_submit($form, &$form_state) { + $format = array(); + $format['format'] = trim($form_state['values']['date_format']); + $format['type'] = 'custom'; + $format['locked'] = 0; + if (!empty($form_state['values']['dfid'])) { + system_date_format_save($format, $form_state['values']['dfid']); + drupal_set_message(t('Custom date format updated.')); + } + else { + $format['is_new'] = 1; + system_date_format_save($format); + drupal_set_message(t('Custom date format added.')); + } + + $form_state['redirect'] = 'admin/config/regional/date-time/formats'; +} + /** * Menu callback; Displays an overview of available and configured actions. */ diff --git a/modules/system/system.api.php b/modules/system/system.api.php index 1c5094704..09812c9bb 100644 --- a/modules/system/system.api.php +++ b/modules/system/system.api.php @@ -2376,6 +2376,110 @@ function hook_action_info_alter(&$actions) { $actions['node_unpublish_action']['label'] = t('Unpublish and remove from public view.'); } +/** + * Defines additional date types. + * + * Next to the 'long', 'medium' and 'short' date types defined in core, any + * module can define additional types that can be used when displaying dates. A + * date type is a key which can be passed to format_date() to return a date in + * the configured display format. + * + * To avoid namespace collisions with date types defined by other modules, it is + * recommended that each date type starts with the module name. A date type + * can consist of letters, numbers and underscores. + * + * @see hook_date_formats() + * @see format_date() + * + * @return + * A list of date types in 'key' => 'label' format. + */ +function hook_date_format_types() { + return array( + 'long' => t('Long'), + 'medium' => t('Medium'), + 'short' => t('Short'), + ); +} + +/** + * Defines additional date formats. + * + * Next to the 'long', 'medium' and 'short' date types defined in core, any + * module can define additional types that can be used when displaying dates. A + * date type is a key which can be passed to format_date() to return a date in + * the configured displayed format. A date format is a string defining the date + * and time elements to use. For example, a date type could be + * 'mymodule_extra_long', while a date format is like 'Y-m-d'. + * + * New date types must first be declared using hook_date_format_types(). It is + * then possible to define one or more date formats for each. + * + * A module may also extend the list date formats defined for a date type + * provided by another module. + * + * There may be more than one format for the same locale. For example d/m/Y and + * Y/m/d work equally well in some locales. It may also be necessary to define + * multiple versions of the same date format, for example, one using AM, one + * with PM and one without the time at all. + * + * However at the same time you may wish to define some additional date formats + * that aren't specific to any one locale, for example, "Y m". For these cases + * the locales field should be omitted. + * + * @see hook_date_format_types() + * + * @return + * A list of date formats. Each date format is a keyed array + * consisting of three elements: + * - 'type': the date type is a key used to identify which date format to + * display. It consists of letters, numbers and underscores, e.g. 'long', + * 'short', 'mymodule_extra_long'. It must first be declared in + * hook_date_format_types() unless extending a type provided by another + * module. + * - 'format': a string defining the date and time elements to use. It + * can contain any of the formatting options described at + * http://php.net/manual/en/function.date.php + * - 'locales': (optional) an array of 2 and 5 character language codes, for + * example, 'en', 'en-us'. The language codes are used to determine which + * date format to display for the user's current language. If more than one + * date format is suggested for the same date type and locale, then the + * first one will be used unless overridden via + * admin/config/regional/date-time/locale. If your date format is not + * language specific, leave this field empty. + */ +function hook_date_formats() { + return array( + array( + 'type' => 'mymodule_extra_long', + 'format' => 'l jS F Y H:i:s e', + 'locales' => array('en-ie'), + ), + array( + 'type' => 'mymodule_extra_long', + 'format' => 'l jS F Y h:i:sa', + 'locales' => array('en', 'en-us'), + ), + array( + 'type' => 'short', + 'format' => 'F Y', + 'locales' => array(), + ), + ); +} + +/** + * Alters date types and formats declared by another module. + * + * Called by _system_date_format_types_build() to allow modules to alter the + * return values from implementations of hook_date_formats(). + */ +function hook_date_formats_alter(&$formats) { + foreach ($formats as $id => $format) { + $formats[$id]['locales'][] = 'en-ca'; + } +} + /** * @} End of "addtogroup hooks". */ diff --git a/modules/system/system.install b/modules/system/system.install index 08ecacd5e..6564e0235 100644 --- a/modules/system/system.install +++ b/modules/system/system.install @@ -741,6 +741,92 @@ function system_schema() { $schema['cache_registry'] = $schema['cache']; $schema['cache_registry']['description'] = 'Cache table for the code registry system to remember what code files need to be loaded on any given page.'; + $schema['date_format_type'] = array( + 'description' => 'Stores configured date format types.', + 'fields' => array( + 'type' => array( + 'description' => 'The date format type, e.g. medium.', + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + ), + 'title' => array( + 'description' => 'The human readable name of the format type.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + ), + 'locked' => array( + 'description' => 'Whether or not this is a system provided format.', + 'type' => 'int', + 'size' => 'tiny', + 'default' => 0, + 'not null' => TRUE, + ), + ), + 'primary key' => array('type'), + ); + + // This table's name is plural as some versions of MySQL can't create a + // table named 'date_format'. + $schema['date_formats'] = array( + 'description' => 'Stores configured date formats.', + 'fields' => array( + 'dfid' => array( + 'description' => 'The date format identifier.', + 'type' => 'serial', + 'not null' => TRUE, + 'unsigned' => TRUE, + ), + 'format' => array( + 'description' => 'The date format string.', + 'type' => 'varchar', + 'length' => 100, + 'not null' => TRUE, + ), + 'type' => array( + 'description' => 'The date format type, e.g. medium.', + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + ), + 'locked' => array( + 'description' => 'Whether or not this format can be modified.', + 'type' => 'int', + 'size' => 'tiny', + 'default' => 0, + 'not null' => TRUE, + ), + ), + 'primary key' => array('dfid'), + 'unique keys' => array('formats' => array('format', 'type')), + ); + + $schema['date_format_locale'] = array( + 'description' => 'Stores configured date formats for each locale.', + 'fields' => array( + 'format' => array( + 'description' => 'The date format string.', + 'type' => 'varchar', + 'length' => 100, + 'not null' => TRUE, + ), + 'type' => array( + 'description' => 'The date format type, e.g. medium.', + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + ), + 'language' => array( + 'description' => 'A {languages}.language for this format to be used with.', + 'type' => 'varchar', + 'length' => 12, + 'not null' => TRUE, + ), + ), + 'primary key' => array('type', 'language'), + ); + $schema['file'] = array( 'description' => 'Stores information for uploaded files.', 'fields' => array( @@ -2546,6 +2632,99 @@ function system_update_7039() { db_add_field('menu_router', 'theme_arguments', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '')); } +/** + * Create new date format tables. + */ +function system_update_7040() { + $schema['date_format_type'] = array( + 'description' => 'Stores configured date format types.', + 'fields' => array( + 'type' => array( + 'description' => 'The date format type, e.g. medium.', + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + ), + 'title' => array( + 'description' => 'The human readable name of the format type.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + ), + 'locked' => array( + 'description' => 'Whether or not this is a system provided format.', + 'type' => 'int', + 'size' => 'tiny', + 'default' => 0, + 'not null' => TRUE, + ), + ), + 'primary key' => array('type'), + ); + + $schema['date_formats'] = array( + 'description' => 'Stores configured date formats.', + 'fields' => array( + 'dfid' => array( + 'description' => 'The date format identifier.', + 'type' => 'serial', + 'not null' => TRUE, + 'unsigned' => TRUE, + ), + 'format' => array( + 'description' => 'The date format string.', + 'type' => 'varchar', + 'length' => 100, + 'not null' => TRUE, + ), + 'type' => array( + 'description' => 'The date format type, e.g. medium.', + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + ), + 'locked' => array( + 'description' => 'Whether or not this format can be modified.', + 'type' => 'int', + 'size' => 'tiny', + 'default' => 0, + 'not null' => TRUE, + ), + ), + 'primary key' => array('dfid'), + 'unique keys' => array('formats' => array('format', 'type')), + ); + + $schema['date_format_locale'] = array( + 'description' => 'Stores configured date formats for each locale.', + 'fields' => array( + 'format' => array( + 'description' => 'The date format string.', + 'type' => 'varchar', + 'length' => 100, + 'not null' => TRUE, + ), + 'type' => array( + 'description' => 'The date format type, e.g. medium.', + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + ), + 'language' => array( + 'description' => 'A {languages}.language for this format to be used with.', + 'type' => 'varchar', + 'length' => 12, + 'not null' => TRUE, + ), + ), + 'primary key' => array('type', 'language'), + ); + + db_create_table('date_format_type', $schema['date_format_type']); + db_create_table('date_formats', $schema['date_formats']); + db_create_table('date_format_locale', $schema['date_format_locale']); +} + /** * @} End of "defgroup updates-6.x-to-7.x" * The next series of updates should start at 8000. diff --git a/modules/system/system.js b/modules/system/system.js index 7df037283..83a0c81db 100644 --- a/modules/system/system.js +++ b/modules/system/system.js @@ -97,22 +97,20 @@ Drupal.behaviors.copyFieldValue = { */ Drupal.behaviors.dateTime = { attach: function (context, settings) { - // Show/hide custom format depending on the select's value. - $('select.date-format', context).once('date-time').change(function () { - $(this).parents('div.date-container').children('div.custom-container')[$(this).val() == 'custom' ? 'show' : 'hide'](); - }); + for (var value in settings.dateTime) { + var settings = settings.dateTime[value]; + var source = '#edit-' + value; + var suffix = source + '-suffix'; - // Attach keyup handler to custom format inputs. - $('input.custom-format', context).once('date-time').keyup(function () { - var input = $(this); - var url = settings.dateTime.lookup + (settings.dateTime.lookup.match(/\?q=/) ? '&format=' : '?format=') + encodeURIComponent(input.val()); - $.getJSON(url, function (data) { - $('div.description span', input.parent()).html(data); + // Attach keyup handler to custom format inputs. + $('input' + source, context).once('date-time').keyup(function () { + var input = $(this); + var url = settings.lookup + (settings.lookup.match(/\?q=/) ? '&format=' : '?format=') + encodeURIComponent(input.val()); + $.getJSON(url, function (data) { + $(suffix).empty().append(' ' + settings.text + ': ' + data + ''); + }); }); - }); - - // Trigger the event handler to show the form input if necessary. - $('select.date-format', context).trigger('change'); + } } }; diff --git a/modules/system/system.module b/modules/system/system.module index 996894419..b6c25134b 100644 --- a/modules/system/system.module +++ b/modules/system/system.module @@ -101,7 +101,7 @@ function system_help($path, $arg) { $output .= '
  • ' . t('support for enabling and disabling themes, which determine the design and presentation of your site. Drupal comes packaged with several core themes and additional contributed themes are available at the Drupal.org theme page.', array('@themes' => url('admin/appearance'), '@drupal-themes' => 'http://drupal.org/project/themes')) . '
  • '; $output .= '
  • ' . t('a robust caching system that allows the efficient re-use of previously-constructed web pages and web page components. Drupal stores the pages requested by anonymous users in a compressed format; depending on your site configuration and the amount of your web traffic tied to anonymous visitors, Drupal\'s caching system may significantly increase the speed of your site.', array('@cache-settings' => url('admin/config/development/performance'))) . '
  • '; $output .= '
  • ' . t('a set of routine administrative operations that rely on a correctly-configured cron maintenance task to run automatically. A number of other modules, including the feed aggregator, and search also rely on cron maintenance tasks. For more information, see the online handbook entry for configuring cron jobs.', array('@cron' => url('admin/reports/status'), '@handbook' => 'http://drupal.org/cron')) . '
  • '; - $output .= '
  • ' . t('basic configuration options for your site, including date and time settings, file system settings, clean URL support, site name and other information, and a maintenance mode for taking your site temporarily offline.', array('@regional-settings' => url('admin/config/regional/settings'), '@file-system' => url('admin/config/media/file-system'), '@clean-url' => url('admin/config/search/clean-urls'), '@site-info' => url('admin/config/system/site-information'), '@maintenance-mode' => url('admin/config/development/maintenance'))) . '
  • '; + $output .= '
  • ' . t('basic configuration options for your site, including date and time settings, file system settings, clean URL support, site name and other information, and a maintenance mode for taking your site temporarily offline.', array('@date-time-settings' => url('admin/config/regional/date-time'), '@file-system' => url('admin/config/media/file-system'), '@clean-url' => url('admin/config/search/clean-urls'), '@site-info' => url('admin/config/system/site-information'), '@maintenance-mode' => url('admin/config/development/maintenance'))) . '
  • '; $output .= '

    ' . t('For more information, see the online handbook entry for System module.', array('@system' => 'http://drupal.org/handbook/modules/system/')) . '

    '; return $output; case 'admin/by-module': @@ -204,6 +204,10 @@ function system_theme() { 'system_run_cron_image' => array( 'arguments' => array('image_path' => NULL), ), + 'system_date_time_settings' => array( + 'arguments' => array('form' => NULL), + 'file' => 'system.admin.inc', + ), )); } @@ -781,6 +785,8 @@ function system_menu() { 'access arguments' => array('administer site configuration'), 'file' => 'system.admin.inc', ); + + // Regional and date settings. $items['admin/config/regional'] = array( 'title' => 'Regional and language', 'description' => 'Regional settings, localization and translation.', @@ -792,20 +798,96 @@ function system_menu() { ); $items['admin/config/regional/settings'] = array( 'title' => 'Regional settings', - 'description' => "Settings for how Drupal displays date and time, as well as the system's default time zone.", + 'description' => "Settings for the site's default time zone and country.", 'page callback' => 'drupal_get_form', 'page arguments' => array('system_regional_settings'), 'access arguments' => array('administer site configuration'), 'weight' => -10, 'file' => 'system.admin.inc', ); - $items['admin/config/regional/settings/lookup'] = array( + $items['admin/config/regional/date-time'] = array( + 'title' => 'Date and time', + 'description' => 'Configure display formats for date and time.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('system_date_time_settings'), + 'access arguments' => array('administer site configuration'), + 'weight' => -9, + 'file' => 'system.admin.inc', + ); + $items['admin/config/regional/date-time/types'] = array( + 'title' => 'Types', + 'description' => 'Configure display formats for date and time.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('system_date_time_settings'), + 'access arguments' => array('administer site configuration'), + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + 'file' => 'system.admin.inc', + ); + $items['admin/config/regional/date-time/types/add'] = array( + 'title' => 'Add date type', + 'description' => 'Add new date type.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('system_add_date_format_type_form'), + 'access arguments' => array('administer site configuration'), + 'type' => MENU_LOCAL_ACTION, + 'weight' => -10, + 'file' => 'system.admin.inc', + ); + $items['admin/config/regional/date-time/types/%/delete'] = array( + 'title' => 'Delete date type', + 'description' => 'Allow users to delete a configured date type.', + 'type' => MENU_CALLBACK, + 'page callback' => 'drupal_get_form', + 'page arguments' => array('system_delete_date_format_type_form', 5), + 'access arguments' => array('administer site configuration'), + 'file' => 'system.admin.inc', + ); + $items['admin/config/regional/date-time/formats'] = array( + 'title' => 'Formats', + 'description' => 'Configure display format strings for date and time.', + 'page callback' => 'system_date_time_formats', + 'access arguments' => array('administer site configuration'), + 'type' => MENU_LOCAL_TASK, + 'weight' => -9, + 'file' => 'system.admin.inc', + ); + $items['admin/config/regional/date-time/formats/add'] = array( + 'title' => 'Add format', + 'description' => 'Allow users to add additional date formats.', + 'type' => MENU_LOCAL_ACTION, + 'page callback' => 'drupal_get_form', + 'page arguments' => array('system_configure_date_formats_form'), + 'access arguments' => array('administer site configuration'), + 'weight' => -10, + 'file' => 'system.admin.inc', + ); + $items['admin/config/regional/date-time/formats/%/edit'] = array( + 'title' => 'Edit date format', + 'description' => 'Allow users to edit a configured date format.', + 'type' => MENU_CALLBACK, + 'page callback' => 'drupal_get_form', + 'page arguments' => array('system_configure_date_formats_form', 5), + 'access arguments' => array('administer site configuration'), + 'file' => 'system.admin.inc', + ); + $items['admin/config/regional/date-time/formats/%/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('system_date_delete_format_form', 5), + 'access arguments' => array('administer site configuration'), + 'file' => 'system.admin.inc', + ); + $items['admin/config/regional/date-time/formats/lookup'] = array( 'title' => 'Date and time lookup', 'type' => MENU_CALLBACK, 'page callback' => 'system_date_time_lookup', 'access arguments' => array('administer site configuration'), 'file' => 'system.admin.inc', ); + $items['admin/config/search'] = array( 'title' => 'Search and metadata', 'description' => 'Local site search, metadata and SEO.', @@ -2453,6 +2535,14 @@ function system_cron() { ->execute(); } +/** + * Implements hook_flush_caches(). + */ +function system_flush_caches() { + // Rebuild list of date formats. + system_date_formats_rebuild(); +} + /** * Implement hook_action_info(). */ @@ -2921,3 +3011,353 @@ function theme_system_run_cron_image($variables) { return ''; } +/** + * Get the list of available date types and attributes. + * + * @param $type + * The date type, e.g. 'short', 'medium', 'long', 'custom'. If empty, then + * all attributes for that type will be returned. + * @return + * Array of date types. + */ +function system_get_date_types($type = NULL) { + $date_format_types = &drupal_static(__FUNCTION__); + + if (!isset($date_format_types)) { + $date_format_types = _system_date_format_types_build(); + } + + return $type ? (isset($date_format_types[$type]) ? $date_format_types[$type] : FALSE) : $date_format_types; +} + +/** + * Implements hook_date_format_types(). + */ +function system_date_format_types() { + return array( + 'long' => t('Long'), + 'medium' => t('Medium'), + 'short' => t('Short'), + ); +} + +/** + * Implements hook_date_formats(). + * + * @return + * An array of date formats with attributes 'type' (short, medium or long), + * 'format' (the format string) and 'locales'. The 'locales' attribute is an + * array of locales, which can include both 2 character language codes like + * 'en', 'fr', but also 5 character language codes like 'en-gb' and 'en-us'. + */ +function system_date_formats() { + include_once DRUPAL_ROOT . '/includes/date.inc'; + return system_default_date_formats(); +} + +/** + * Get the list of date formats for a particular format length. + * + * @param $type + * The date type: 'short', 'medium', 'long', 'custom'. If empty, then all + * available types will be returned. + * @return + * Array of date formats. + */ +function system_get_date_formats($type = NULL) { + $date_formats = &drupal_static(__FUNCTION__); + + if (!isset($date_formats)) { + $date_formats = _system_date_formats_build(); + } + + return $type ? (isset($date_formats[$type]) ? $date_formats[$type] : FALSE) : $date_formats; +} + +/** + * Get the format details for a particular id. + * + * @param $dfid + * Identifier of a date format string. + * @return + * Array of date format details. + */ +function system_get_date_format($dfid) { + return db_query('SELECT df.dfid, df.format, df.type, df.locked FROM {date_formats} df WHERE df.dfid = :dfid', array(':dfid' => $dfid))->fetch(); +} + +/** + * Resets the database cache of date formats and saves all new formats. + */ +function system_date_formats_rebuild() { + drupal_static_reset('system_get_date_formats'); + $date_formats = system_get_date_formats(NULL); + + foreach ($date_formats as $format_type => $formats) { + foreach ($formats as $format => $info) { + system_date_format_save($info); + } + } + + // Rebuild configured date formats locale list. + drupal_static_reset('system_date_format_locale'); + system_date_format_locale(); + + _system_date_formats_build(); +} + +/** + * Get the appropriate date format for a type and locale. + * + * @param $langcode + * Language code for the current locale. This can be a 2 character language + * code like 'en', 'fr', or a longer 5 character code like 'en-gb'. + * @param $type + * Date type: short, medium, long, custom. + * @return + * The format string, or NULL if no matching format found. + */ +function system_date_format_locale($langcode = NULL, $type = NULL) { + $formats = &drupal_static(__FUNCTION__); + + if (empty($formats)) { + $formats = array(); + $result = db_query("SELECT format, type, language FROM {date_format_locale}"); + foreach ($result as $record) { + if (!isset($formats[$record->language])) { + $formats[$record->language] = array(); + } + $formats[$record->language][$record->type] = $record->format; + } + } + + if ($type && $langcode && !empty($formats[$langcode][$type])) { + return $formats[$langcode][$type]; + } + elseif ($langcode && !empty($formats[$langcode])) { + return $formats[$langcode]; + } + + return FALSE; +} + +/** + * Builds and returns the list of available date types. + * + * @return + * Array of date types. + */ +function _system_date_format_types_build() { + $types = array(); + + // Get list of modules which implement hook_date_format_types(). + $modules = module_implements('date_format_types'); + + foreach ($modules as $module) { + $module_types = module_invoke($module, 'date_format_types'); + foreach ($module_types as $module_type => $type_title) { + $type = array(); + $type['module'] = $module; + $type['type'] = $module_type; + $type['title'] = $type_title; + $type['locked'] = 1; + $type['is_new'] = TRUE; // Will be over-ridden later if in the db. + $types[$module_type] = $type; + } + } + + // Get custom formats added to the database by the end user. + $result = db_query('SELECT dft.type, dft.title, dft.locked FROM {date_format_type} dft ORDER BY dft.title'); + foreach ($result as $record) { + if (!in_array($record->type, $types)) { + $type = array(); + $type['is_new'] = FALSE; + $type['module'] = ''; + $type['type'] = $record->type; + $type['title'] = $record->title; + $type['locked'] = $record->locked; + $types[$record->type] = $type; + } + else { + $type = array(); + $type['is_new'] = FALSE; // Over-riding previous setting. + $types[$record->type] = array_merge($types[$record->type], $type); + } + } + + // Allow other modules to modify these date types. + drupal_alter('date_format_types', $types); + + return $types; +} + +/** + * Builds and returns the list of available date formats. + * + * @return + * Array of date formats. + */ +function _system_date_formats_build() { + $date_formats = array(); + + // First handle hook_date_format_types(). + $types = _system_date_format_types_build(); + foreach ($types as $type => $info) { + system_date_format_type_save($info); + } + + // Get formats supplied by various contrib modules. + $module_formats = module_invoke_all('date_formats'); + + foreach ($module_formats as $module_format) { + $module_format['locked'] = 1; // System types are locked. + // If no date type is specified, assign 'custom'. + if (!isset($module_format['type'])) { + $module_format['type'] = 'custom'; + } + if (!in_array($module_format['type'], array_keys($types))) { + continue; + } + if (!isset($date_formats[$module_format['type']])) { + $date_formats[$module_format['type']] = array(); + } + + // If another module already set this format, merge in the new settings. + if (isset($date_formats[$module_format['type']][$module_format['format']])) { + $date_formats[$module_format['type']][$module_format['format']] = array_merge_recursive($date_formats[$module_format['type']][$module_format['format']], $format); + } + else { + // This setting will be overridden later if it already exists in the db. + $module_format['is_new'] = TRUE; + $date_formats[$module_format['type']][$module_format['format']] = $module_format; + } + } + + // Get custom formats added to the database by the end user. + $result = db_query('SELECT df.dfid, df.format, df.type, df.locked, dfl.language FROM {date_formats} df LEFT JOIN {date_format_type} dft ON df.type = dft.type LEFT JOIN {date_format_locale} dfl ON df.format = dfl.format AND df.type = dfl.type ORDER BY df.type, df.format'); + foreach ($result as $record) { + // If this date type isn't set, initialise the array. + if (!isset($date_formats[$record->type])) { + $date_formats[$record->type] = array(); + } + $format = (array) $record; + $format['is_new'] = FALSE; // It's in the db, so override this setting. + // If this format not already present, add it to the array. + if (!isset($date_formats[$record->type][$record->format])) { + $format['module'] = ''; + $format['locales'] = array($record->language); + $date_formats[$record->type][$record->format] = $format; + } + // Format already present, so merge in settings. + else { + if (!empty($record->language)) { + $format['locales'] = array_merge($date_formats[$record->type][$record->format]['locales'], array($record->language)); + } + $date_formats[$record->type][$record->format] = array_merge($date_formats[$record->type][$record->format], $format); + } + } + + // Allow other modules to modify these formats. + drupal_alter('date_formats', $date_formats); + + return $date_formats; +} + +/** + * Save a date type to the database. + * + * @param $date_format_type + * An array of attributes for a date type. + */ +function system_date_format_type_save($date_format_type) { + $type = array(); + $type['type'] = $date_format_type['type']; + $type['title'] = $date_format_type['title']; + $type['locked'] = $date_format_type['locked']; + + // Update date_format table. + if (!empty($date_format_type['is_new'])) { + drupal_write_record('date_format_type', $type); + } + else { + drupal_write_record('date_format_type', $type, 'type'); + } +} + +/** + * Delete a date type from the database. + * + * @param $date_format_type + * The date type name. + */ +function system_date_format_type_delete($date_format_type) { + db_delete('date_formats') + ->condition('type', $date_format_type) + ->execute(); + db_delete('date_format_type') + ->condition('type', $date_format_type) + ->execute(); + db_delete('date_format_locale') + ->condition('type', $date_format_type) + ->execute(); +} + +/** + * Save a date format to the database. + * + * @param $date_format + * An array of attributes for a date format. + * @param $dfid + * If set, replace an existing date format with a new string using this + * identifier. + */ +function system_date_format_save($date_format, $dfid = 0) { + $format = array(); + $format['dfid'] = $dfid; + $format['type'] = $date_format['type']; + $format['format'] = $date_format['format']; + $format['locked'] = $date_format['locked']; + + // Update date_format table. + if (!empty($date_format['is_new'])) { + drupal_write_record('date_formats', $format); + } + else { + $keys = ($dfid ? array('dfid') : array('format', 'type')); + drupal_write_record('date_formats', $format, $keys); + } + + $languages = language_list('enabled'); + $languages = $languages[1]; + + $locale_format = array(); + $locale_format['type'] = $date_format['type']; + $locale_format['format'] = $date_format['format']; + + // Check if the suggested language codes are configured and enabled. + if (!empty($date_format['locales'])) { + foreach ($date_format['locales'] as $langcode) { + // Only proceed if language is enabled. + if (in_array($langcode, $languages)) { + $is_existing = (bool) db_query_range('SELECT 1 FROM {date_format_locale} WHERE type = :type AND language = :language', 0, 1, array(':type' => $date_format['type'], ':language' => $langcode))->fetchField(); + if (!$is_existing) { + $locale_format['language'] = $langcode; + drupal_write_record('date_format_locale', $locale_format); + } + } + } + } +} + +/** + * Delete a date format from the database. + * + * @param $date_format_id + * The date format string identifier. + */ +function system_date_format_delete($dfid) { + db_delete('date_formats') + ->condition('dfid', $dfid) + ->execute(); +} + diff --git a/modules/system/system.test b/modules/system/system.test index 78bece99a..226adff0f 100644 --- a/modules/system/system.test +++ b/modules/system/system.test @@ -718,6 +718,15 @@ class DateTimeFunctionalTest extends DrupalWebTestCase { ); } + function setUp() { + parent::setUp(); + + // Create admin user and log in admin user. + $this->admin_user = $this->drupalCreateUser(array('administer site configuration')); + $this->drupalLogin($this->admin_user); + } + + /** * Test time zones and DST handling. */ @@ -748,6 +757,77 @@ class DateTimeFunctionalTest extends DrupalWebTestCase { $this->drupalGet("node/$node2->nid"); $this->assertText('2007-08-01 00:00:00 -0700', t('Date should be three hours ahead, with GMT offset of -7 hours.')); } + + /** + * Test date type configuration. + */ + function testDateTypeConfiguration() { + // Confirm system date types appear. + $this->drupalGet('admin/config/regional/date-time'); + $this->assertText(t('Medium'), 'System date types appear in date type list.'); + $this->assertNoRaw('href="/admin/config/regional/date-time/types/medium/delete"', 'No delete link appear for system date types.'); + + // Add custom date type. + $this->clickLink(t('Add date type')); + $date_type = $this->randomName(8); + $machine_name = 'machine_' . $date_type; + $date_format = 'd.m.Y - H:i'; + $edit = array( + 'date_type' => $date_type, + 'machine_name' => $machine_name, + 'date_format' => $date_format, + ); + $this->drupalPost('admin/config/regional/date-time/types/add', $edit, t('Add date type')); + $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time', array('absolute' => TRUE)), t('Correct page redirection.')); + $this->assertText(t('New date type added successfully.'), 'Date type added confirmation message appears.'); + $this->assertText($date_type, 'Custom date type appears in the date type list.'); + $this->assertText(t('delete'), 'Delete link for custom date type appears.'); + + // Delete custom date type. + $this->clickLink(t('delete')); + $this->drupalPost('admin/config/regional/date-time/types/' . $machine_name . '/delete', array(), t('Remove')); + $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time', array('absolute' => TRUE)), t('Correct page redirection.')); + $this->assertText(t('Removed date type ' . $date_type), 'Custom date type removed.'); + } + + /** + * Test date format configuration. + */ + function testDateFormatConfiguration() { + // Confirm 'no custom date formats available' message appears. + $this->drupalGet('admin/config/regional/date-time/formats'); + $this->assertText(t('No custom date formats available.'), 'No custom date formats message appears.'); + + // Add custom date format. + $this->clickLink(t('Add format')); + $edit = array( + 'date_format' => 'Y', + ); + $this->drupalPost('admin/config/regional/date-time/formats/add', $edit, t('Add format')); + $this->assertEqual($this->getUrl(), url('admin/config/regional/date-time/formats', array('absolute' => TRUE)), t('Correct page redirection.')); + $this->assertNoText(t('No custom date formats available.'), 'No custom date formats message does not appear.'); + $this->assertText(t('Custom date format added.'), 'Custom date format added.'); + + // Ensure custom date format appears in date type configuration options. + $this->drupalGet('admin/config/regional/date-time'); + $this->assertRaw('