summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2010-10-13 13:43:21 +0000
committerDries Buytaert <dries@buytaert.net>2010-10-13 13:43:21 +0000
commit284f2b11a48b893cbd13d5429ad68d207488e4e6 (patch)
tree84b9bd1672ec7d9f585c2e4019d2f1f3b508afe1 /modules
parent3e6b9b5ea35dfb32e3c30a4d012f67c1d268a570 (diff)
downloadbrdo-284f2b11a48b893cbd13d5429ad68d207488e4e6.tar.gz
brdo-284f2b11a48b893cbd13d5429ad68d207488e4e6.tar.bz2
- Patch #902644 by sun, tobiasb: machine names are too hard to implement. Date types and menu names are not validated.
This patch fixes a bug, but is also a last minute clean-up that will help with better distribution support. We discussed this in http://drupal.org/node/933846.
Diffstat (limited to 'modules')
-rw-r--r--modules/menu/menu.admin.inc114
-rw-r--r--modules/menu/menu.test12
-rw-r--r--modules/node/content_types.inc51
-rw-r--r--modules/system/system.admin.css10
-rw-r--r--modules/system/system.admin.inc24
-rw-r--r--modules/system/system.js74
-rw-r--r--modules/system/system.module12
-rw-r--r--modules/system/system.test2
-rw-r--r--modules/taxonomy/taxonomy.admin.inc53
-rw-r--r--modules/taxonomy/taxonomy.test2
10 files changed, 101 insertions, 253 deletions
diff --git a/modules/menu/menu.admin.inc b/modules/menu/menu.admin.inc
index 622df38ab..e4dc02951 100644
--- a/modules/menu/menu.admin.inc
+++ b/modules/menu/menu.admin.inc
@@ -419,57 +419,45 @@ function menu_edit_item_submit($form, &$form_state) {
*/
function menu_edit_menu($form, &$form_state, $type, $menu = array()) {
$system_menus = menu_list_system_menus();
- $menu += array('menu_name' => '', 'old_name' => '', 'title' => '', 'description' => '');
- if (!empty($menu['menu_name'])) {
- $menu['old_name'] = $menu['menu_name'];
- }
- $form['old_name'] = array('#type' => 'value', '#value' => $menu['old_name']);
+ $menu += array(
+ 'menu_name' => '',
+ 'old_name' => !empty($menu['menu_name']) ? $menu['menu_name'] : '',
+ 'title' => '',
+ 'description' => '',
+ );
+ // Allow menu_edit_menu_submit() and other form submit handlers to determine
+ // whether the menu already exists.
+ $form['#insert'] = empty($menu['old_name']);
+ $form['old_name'] = array(
+ '#type' => 'value',
+ '#value' => $menu['old_name'],
+ );
- // The title of a system menu cannot be altered.
- if (isset($system_menus[$menu['menu_name']])) {
- $form['title'] = array('#type' => 'value', '#value' => $menu['title']);
- }
- else {
- $form['title'] = array(
- '#type' => 'textfield',
- '#title' => t('Title'),
- '#default_value' => $menu['title'],
- '#required' => TRUE,
- '#field_suffix' => ' <small id="edit-title-suffix">&nbsp;</small>',
- );
- }
+ $form['title'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Title'),
+ '#default_value' => $menu['title'],
+ '#required' => TRUE,
+ // The title of a system menu cannot be altered.
+ '#access' => !isset($system_menus[$menu['menu_name']]),
+ );
- // The internal menu name can only be defined during initial menu creation.
- if (!empty($menu['old_name'])) {
- $form['#insert'] = FALSE;
- $form['menu_name'] = array('#type' => 'value', '#value' => $menu['menu_name']);
- }
- else {
- $form['#insert'] = TRUE;
- $js_settings = array(
- 'type' => 'setting',
- 'data' => array(
- 'machineReadableValue' => array(
- 'title' => array(
- 'text' => t('URL path'),
- 'target' => 'menu-name',
- 'searchPattern' => '[^a-z0-9]+',
- 'replaceToken' => '-',
- ),
- ),
- ),
- );
- $form['menu_name'] = array(
- '#type' => 'textfield',
- '#title' => t('Menu name'),
- '#maxsize' => MENU_MAX_MENU_NAME_LENGTH_UI,
- '#description' => t('This text will be used to construct the URL for the menu. The name must contain only lowercase letters, numbers and hyphens, and must be unique.'),
- '#required' => TRUE,
- '#attached' => array(
- 'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
- ),
- );
- }
+ $form['menu_name'] = array(
+ '#type' => 'machine_name',
+ '#title' => t('Menu name'),
+ '#default_value' => $menu['menu_name'],
+ '#maxlength' => MENU_MAX_MENU_NAME_LENGTH_UI,
+ '#description' => t('A unique name to construct the URL for the menu. It must only contain lowercase letters, numbers and hyphens.'),
+ '#machine_name' => array(
+ 'exists' => 'menu_edit_menu_name_exists',
+ 'source' => array('title'),
+ 'label' => t('URL path'),
+ 'replace_pattern' => '[^a-z0-9-]+',
+ 'replace' => '-',
+ ),
+ // A menu's machine name cannot be changed.
+ '#disabled' => !empty($menu['old_name']) || isset($system_menus[$menu['menu_name']]),
+ );
$form['description'] = array(
'#type' => 'textarea',
@@ -560,26 +548,18 @@ function menu_delete_menu_confirm_submit($form, &$form_state) {
}
/**
- * Validates the human and machine-readable names when adding or editing a menu.
+ * Returns whether a menu name already exists.
+ *
+ * @see menu_edit_menu()
+ * @see form_validate_machine_name()
*/
-function menu_edit_menu_validate($form, &$form_state) {
- $item = $form_state['values'];
- if (preg_match('/[^a-z0-9-]/', $item['menu_name'])) {
- form_set_error('menu_name', t('The menu name may only consist of lowercase letters, numbers, and hyphens.'));
- }
- if ($form['#insert']) {
- if (strlen($item['menu_name']) > MENU_MAX_MENU_NAME_LENGTH_UI) {
- form_set_error('menu_name', format_plural(MENU_MAX_MENU_NAME_LENGTH_UI, "The menu name can't be longer than 1 character.", "The menu name can't be longer than @count characters."));
- }
+function menu_edit_menu_name_exists($value) {
+ // 'menu-' is added to the menu name to avoid name-space conflicts.
+ $value = 'menu-' . $value;
+ $custom_exists = db_query_range('SELECT 1 FROM {menu_custom} WHERE menu_name = :menu', 0, 1, array(':menu' => $value))->fetchField();
+ $link_exists = db_query_range("SELECT 1 FROM {menu_links} WHERE menu_name = :menu", 0, 1, array(':menu' => $value))->fetchField();
- // We will add 'menu-' to the menu name to help avoid name-space conflicts.
- $item['menu_name'] = 'menu-' . $item['menu_name'];
- $custom_exists = db_query_range('SELECT 1 FROM {menu_custom} WHERE menu_name = :menu', 0, 1, array(':menu' => $item['menu_name']))->fetchField();
- $link_exists = db_query_range("SELECT 1 FROM {menu_links} WHERE menu_name = :menu", 0, 1, array(':menu' => $item['menu_name']))->fetchField();
- if ($custom_exists || $link_exists) {
- form_set_error('menu_name', t('The menu already exists.'));
- }
- }
+ return $custom_exists || $link_exists;
}
/**
diff --git a/modules/menu/menu.test b/modules/menu/menu.test
index 2c5900181..a90fbfb28 100644
--- a/modules/menu/menu.test
+++ b/modules/menu/menu.test
@@ -140,7 +140,11 @@ class MenuTestCase extends DrupalWebTestCase {
$this->drupalPost('admin/structure/menu/add', $edit, t('Save'));
// Verify that using a menu_name that is too long results in a validation message.
- $this->assertText(format_plural(MENU_MAX_MENU_NAME_LENGTH_UI, "The menu name can't be longer than 1 character.", "The menu name can't be longer than @count characters."), t('Validation failed when menu name is too long.'));
+ $this->assertRaw(t('!name cannot be longer than %max characters but is currently %length characters long.', array(
+ '!name' => t('Menu name'),
+ '%max' => MENU_MAX_MENU_NAME_LENGTH_UI,
+ '%length' => drupal_strlen($menu_name),
+ )));
// Change the menu_name so it no longer exceeds the maximum length.
$menu_name = substr(hash('sha256', $this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI);
@@ -148,7 +152,11 @@ class MenuTestCase extends DrupalWebTestCase {
$this->drupalPost('admin/structure/menu/add', $edit, t('Save'));
// Verify that no validation error is given for menu_name length.
- $this->assertNoText(format_plural(MENU_MAX_MENU_NAME_LENGTH_UI, "The menu name can't be longer than 1 character.", "The menu name can't be longer than @count characters."), t('Validation failed when menu name is too long.'));
+ $this->assertNoRaw(t('!name cannot be longer than %max characters but is currently %length characters long.', array(
+ '!name' => t('Menu name'),
+ '%max' => MENU_MAX_MENU_NAME_LENGTH_UI,
+ '%length' => drupal_strlen($menu_name),
+ )));
// Unlike most other modules, there is no confirmation message displayed.
$this->drupalGet('admin/structure/menu');
diff --git a/modules/node/content_types.inc b/modules/node/content_types.inc
index 23565ce24..d31becb0d 100644
--- a/modules/node/content_types.inc
+++ b/modules/node/content_types.inc
@@ -94,41 +94,20 @@ function node_type_form($form, &$form_state, $type = NULL) {
'#description' => t('The human-readable name of this content type. This text will be displayed as part of the list on the <em>Add new content</em> page. It is recommended that this name begin with a capital letter and contain only letters, numbers, and spaces. This name must be unique.'),
'#required' => TRUE,
'#size' => 30,
- '#field_suffix' => ' <small id="edit-name-suffix">' . ($type->locked ? t('Machine name: @name', array('@name' => $type->type)) : '&nbsp;') . '</small>',
);
- if (!$type->locked) {
- $js_settings = array(
- 'type' => 'setting',
- 'data' => array(
- 'machineReadableValue' => array(
- 'name' => array(
- 'text' => t('Machine name'),
- 'target' => 'type',
- 'searchPattern' => '[^a-z0-9]+',
- 'replaceToken' => '_',
- ),
- ),
- ),
- );
- $form['type'] = array(
- '#title' => t('Machine name'),
- '#type' => 'textfield',
- '#default_value' => $type->type,
- '#maxlength' => 32,
- '#required' => TRUE,
- '#description' => t('The machine-readable name of this content type. This text will be used for constructing the URL of the <em>add new content</em> page for this content type. This name must contain only lowercase letters, numbers, and underscores. Underscores will be converted into hyphens when constructing the URL of the <em>add new content</em> page. This name must be unique.'),
- '#attached' => array(
- 'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
- ),
- );
- }
- else {
- $form['type'] = array(
- '#type' => 'value',
- '#value' => $type->type,
- );
- }
+ $form['type'] = array(
+ '#type' => 'machine_name',
+ '#default_value' => $type->type,
+ '#maxlength' => 32,
+ '#disabled' => $type->locked,
+ '#machine_name' => array(
+ 'exists' => 'node_type_load',
+ ),
+ '#description' => t('A unique machine-readable name for this content type. It must only contain lowercase letters, numbers, and underscores. This name will be used for constructing the URL of the %node-add page, in which underscores will be converted into hyphens.', array(
+ '%node-add' => t('Add new content'),
+ )),
+ );
$form['description'] = array(
'#title' => t('Description'),
@@ -276,12 +255,6 @@ function node_type_form_validate($form, &$form_state) {
$types = node_type_get_names();
if (!$form_state['values']['locked']) {
- if (isset($types[$type->type]) && $type->type != $old_type) {
- form_set_error('type', t('The machine-readable name %type is already taken.', array('%type' => $type->type)));
- }
- if (!preg_match('!^[a-z0-9_]+$!', $type->type)) {
- form_set_error('type', t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
- }
// 'theme' conflicts with theme_node_form().
// '0' is invalid, since elsewhere we check it using empty().
if (in_array($type->type, array('0', 'theme'))) {
diff --git a/modules/system/system.admin.css b/modules/system/system.admin.css
index 1d3882669..adcc369fd 100644
--- a/modules/system/system.admin.css
+++ b/modules/system/system.admin.css
@@ -46,6 +46,16 @@ div.admin .expert-link {
}
/**
+ * Quick inline admin links.
+ */
+small .admin-link:before {
+ content: '[';
+}
+small .admin-link:after {
+ content: ']';
+}
+
+/**
* Modules page.
*/
#system-modules div.incompatible {
diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc
index b2f5ee240..431a41242 100644
--- a/modules/system/system.admin.inc
+++ b/modules/system/system.admin.inc
@@ -2068,28 +2068,12 @@ function system_add_date_format_type_form($form, &$form_state) {
'#title' => t('Date type'),
'#type' => 'textfield',
'#required' => TRUE,
- '#field_suffix' => ' <small id="edit-date-type-suffix">&nbsp;</small>',
- );
- $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),
+ '#type' => 'machine_name',
+ '#machine_name' => array(
+ 'exists' => 'system_get_date_types',
+ 'source' => array('date_type'),
),
);
diff --git a/modules/system/system.js b/modules/system/system.js
index 07c2eb64f..3cee79f30 100644
--- a/modules/system/system.js
+++ b/modules/system/system.js
@@ -148,78 +148,4 @@ Drupal.behaviors.pageCache = {
}
};
-/**
- * Attach the auto machine readable name behavior.
- *
- * Settings are expected to be an object of elements to process, where the key
- * defines the source element in the form and the value is an object defining
- * the following properties:
- * - text: The label to display before the auto-generated value.
- * - target: The target form element name.
- * - searchPattern: A regular expression (without modifiers) matching disallowed
- * characters in the machine readable name, f.e. '[^a-z0-9]+'.
- * - replaceToken: A replacement string to replace disallowed characters, f.e.
- * '-' or '_'.
- *
- * @see menu_edit_menu()
- */
-Drupal.behaviors.machineReadableValue = {
- attach: function () {
- var self = this;
-
- for (var value in Drupal.settings.machineReadableValue) {
- var settings = Drupal.settings.machineReadableValue[value];
-
- // Build selector for the source name entered by a user.
- var source = '#edit-' + value;
- var suffix = source + '-suffix';
- // Build selector for the machine readable name.
- var target = '#edit-' + settings.target;
- // Build selector for the wrapper element around the target field.
- var wrapper = '.form-item-' + settings.target;
-
- // Do not process the element if we got an error or the given name and the
- // machine readable name are identical or the machine readable name is
- // empty.
- if (!$(target).hasClass('error') && ($(target).val() == '' || $(target).val() == self.transliterate($(source).val(), settings))) {
- // Hide wrapper element.
- $(wrapper).hide();
- // Bind keyup event to source element.
- $(source).keyup(function () {
- var machine = self.transliterate($(this).val(), settings);
- if (machine != '_' && machine != '') {
- // Set machine readable name to the user entered value.
- $(target).val(machine);
- // Append the machine readable name and a link to edit it to the source field.
- $(suffix).empty().append(' ' + settings.text + ': ' + machine + ' [').append($('<a href="#">' + Drupal.t('Edit') + '</a>').click(function () {
- $(wrapper).show();
- $(target).focus();
- $(suffix).hide();
- $(source).unbind('keyup');
- return false;
- })).append(']');
- }
- else {
- $(target).val(machine);
- $(suffix).text('');
- }
- });
- // Call keyup event on source element.
- $(source).keyup();
- }
- }
- },
-
- /**
- * Transliterate a human-readable name to a machine name.
- *
- * The result should not contain any character matching settings.searchPattern,
- * invalid characters are typically replaced with settings.replaceToken.
- */
- transliterate: function (source, settings) {
- var searchPattern = new RegExp(settings.searchPattern, 'g');
- return source.toLowerCase().replace(searchPattern, settings.replaceToken);
- }
-};
-
})(jQuery);
diff --git a/modules/system/system.module b/modules/system/system.module
index 7466480c4..88c9c94c7 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -347,6 +347,18 @@ function system_element_info() {
'#theme' => 'textfield',
'#theme_wrappers' => array('form_element'),
);
+ $types['machine_name'] = array(
+ '#input' => TRUE,
+ '#default_value' => NULL,
+ '#required' => TRUE,
+ '#maxlength' => 64,
+ '#size' => 60,
+ '#autocomplete_path' => FALSE,
+ '#process' => array('form_process_machine_name', 'ajax_process_form'),
+ '#element_validate' => array('form_validate_machine_name'),
+ '#theme' => 'textfield',
+ '#theme_wrappers' => array('form_element'),
+ );
$types['password'] = array(
'#input' => TRUE,
'#size' => 60,
diff --git a/modules/system/system.test b/modules/system/system.test
index bc5f5593f..e6db7a13c 100644
--- a/modules/system/system.test
+++ b/modules/system/system.test
@@ -948,7 +948,7 @@ class DateTimeFunctionalTest extends DrupalWebTestCase {
// Add custom date type.
$this->clickLink(t('Add date type'));
- $date_type = $this->randomName(8);
+ $date_type = strtolower($this->randomName(8));
$machine_name = 'machine_' . $date_type;
$date_format = 'd.m.Y - H:i';
$edit = array(
diff --git a/modules/taxonomy/taxonomy.admin.inc b/modules/taxonomy/taxonomy.admin.inc
index 7b81db26d..7d314634a 100644
--- a/modules/taxonomy/taxonomy.admin.inc
+++ b/modules/taxonomy/taxonomy.admin.inc
@@ -137,30 +137,13 @@ function taxonomy_form_vocabulary($form, &$form_state, $edit = array()) {
'#default_value' => $vocabulary->name,
'#maxlength' => 255,
'#required' => TRUE,
- '#field_suffix' => ' <small id="edit-name-suffix">&nbsp;</small>',
- );
- $js_settings = array(
- 'type' => 'setting',
- 'data' => array(
- 'machineReadableValue' => array(
- 'name' => array(
- 'text' => t('Machine name'),
- 'target' => 'machine-name',
- 'searchPattern' => '[^a-z0-9]+',
- 'replaceToken' => '_',
- ),
- ),
- ),
);
$form['machine_name'] = array(
- '#type' => 'textfield',
- '#title' => t('Machine-readable name'),
+ '#type' => 'machine_name',
'#default_value' => $vocabulary->machine_name,
- '#maxlength' => 255,
- '#description' => t('The unique machine-readable name for this vocabulary, used for theme templates. Can only contain lowercase letters, numbers, and underscores.'),
- '#required' => TRUE,
- '#attached' => array(
- 'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
+ '#maxlength' => 21,
+ '#machine_name' => array(
+ 'exists' => 'taxonomy_vocabulary_machine_name_load',
),
);
$form['old_machine_name'] = array(
@@ -190,34 +173,6 @@ function taxonomy_form_vocabulary($form, &$form_state, $edit = array()) {
}
/**
- * Validation handler for the vocabulary form.
- *
- * @see taxonomy_form_vocabulary()
- */
-function taxonomy_form_vocabulary_validate($form, &$form_state) {
- if ($form_state['clicked_button']['#value'] != t('Delete') && isset($form_state['values']['machine_name'])) {
-
- // Restrict machine names to appropriate characters.
- $machine_name = $form_state['values']['machine_name'];
- if (!preg_match('!^[a-z0-9_]+$!', $form_state['values']['machine_name'])) {
- form_set_error('machine_name', t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
- }
- // Restrict machine names to 21 characters to avoid exceeding the limit
- // for field names.
- if (drupal_strlen($machine_name) > 21) {
- form_set_error('machine_name', t('The machine-readable name must not exceed 21 characters.'));
- }
-
- // Do not allow duplicate machine names.
- $vocabularies = taxonomy_get_vocabularies();
- foreach ($vocabularies as $vocabulary) {
- if ($machine_name == $vocabulary->machine_name && (!isset($form_state['values']['vid']) || $vocabulary->vid != $form_state['values']['vid'])) {
- form_set_error('machine_name', t('This machine-readable name is already in use by another vocabulary and must be unique.'));
- }
- }
- }
-}
-/**
* Accept the form submission for a vocabulary and save the results.
*/
function taxonomy_form_vocabulary_submit($form, &$form_state) {
diff --git a/modules/taxonomy/taxonomy.test b/modules/taxonomy/taxonomy.test
index 174e258ac..0a08c1bde 100644
--- a/modules/taxonomy/taxonomy.test
+++ b/modules/taxonomy/taxonomy.test
@@ -92,7 +92,7 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
// Try to submit a vocabulary with a duplicate machine name.
$edit['machine_name'] = $machine_name;
$this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save'));
- $this->assertText(t('This machine-readable name is already in use by another vocabulary and must be unique.'), t('Duplicate machine name validation was successful'));
+ $this->assertText(t('The machine-readable name is already in use. It must be unique.'));
// Try to submit an invalid machine name.
$edit['machine_name'] = '!&^%';