summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2009-10-03 19:16:04 +0000
committerDries Buytaert <dries@buytaert.net>2009-10-03 19:16:04 +0000
commitb5447770959e9d447e53e21e63faa98fcc1db329 (patch)
tree3f38cba8adefd9108019b010cde327e68bec0ebb /includes
parentb5199f2297c7cac6d03980bea6be9a02bbdf1738 (diff)
downloadbrdo-b5447770959e9d447e53e21e63faa98fcc1db329.tar.gz
brdo-b5447770959e9d447e53e21e63faa98fcc1db329.tar.bz2
- Patch #464862 by JohnAlbin, sun, dereine | dvessel, Jacine, Zarabadoo: added drupal_css_class() to clean class names and rename form_clean_id().
Diffstat (limited to 'includes')
-rw-r--r--includes/common.inc73
-rw-r--r--includes/form.inc52
-rw-r--r--includes/theme.inc14
3 files changed, 87 insertions, 52 deletions
diff --git a/includes/common.inc b/includes/common.inc
index f2db46b28..878e8106d 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -3095,6 +3095,79 @@ function drupal_clear_css_cache() {
}
/**
+ * Prepare a string for use as a valid CSS identifier (element, class or ID selector).
+ *
+ * http://www.w3.org/TR/CSS21/syndata.html#characters shows the syntax for valid
+ * CSS identifiers (including element names, classes, and IDs in selectors.)
+ *
+ * @param $identifier
+ * The CSS identifier to clean.
+ * @param $filter
+ * An array of string replacements to use on the identifier.
+ * @return
+ * The cleaned identifier.
+ */
+function drupal_clean_css_identifier($identifier, $filter = array(' ' => '-', '_' => '-', '[' => '-', ']' => '')) {
+ // By default, we filter using Drupal's coding standards.
+ $identifier = strtr($identifier, $filter);
+
+ // Valid characters in a CSS identifier are:
+ // - the hyphen (U+002D)
+ // - a-z (U+0030 - U+0039)
+ // - A-Z (U+0041 - U+005A)
+ // - the underscore (U+005F)
+ // - 0-9 (U+0061 - U+007A)
+ // - ISO 10646 characters U+00A1 and higher
+ // We strip out any character not in the above list.
+ $identifier = preg_replace('/[^\x{002D}\x{0030}-\x{0039}\x{0041}-\x{005A}\x{005F}\x{0061}-\x{007A}\x{00A1}-\x{FFFF}]/u', '', $identifier);
+
+ return $identifier;
+}
+
+/**
+ * Prepare a string for use as a valid CSS class name.
+ *
+ * Do not pass one string containing multiple classes as they will be
+ * incorrectly concatenated with dashes, i.e. "one two" will become "one-two".
+ *
+ * @param $class
+ * The class name to clean.
+ * @return
+ * The cleaned class name.
+ */
+function drupal_css_class($class) {
+ return drupal_clean_css_identifier(drupal_strtolower($class));
+}
+
+/**
+ * Prepare a string for use as a valid HTML ID and guarantee uniqueness.
+ *
+ * @param $id
+ * The ID to clean.
+ * @return
+ * The cleaned ID.
+ */
+function drupal_css_id($id) {
+ $seen_ids = &drupal_static(__FUNCTION__, array());
+ $id = drupal_clean_css_identifier(drupal_strtolower($id));
+
+ // Ensure IDs are unique. The first occurrence is held but left alone.
+ // Subsequent occurrences get a number appended to them. This incrementing
+ // will almost certainly break code that relies on explicit HTML IDs in forms
+ // that appear more than once on the page, but the alternative is outputting
+ // duplicate IDs, which would break JS code and XHTML validity anyways. For
+ // now, it's an acceptable stopgap solution.
+ if (isset($seen_ids[$id])) {
+ $id = $id . '-' . ++$seen_ids[$id];
+ }
+ else {
+ $seen_ids[$id] = 1;
+ }
+
+ return $id;
+}
+
+/**
* Add a JavaScript file, setting or inline code to the page.
*
* The behavior of this function depends on the parameters it is called with.
diff --git a/includes/form.inc b/includes/form.inc
index 3ee8af7b7..82d84b4f8 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -547,12 +547,12 @@ function drupal_process_form($form_id, &$form, &$form_state) {
if ($form_state['process_input']) {
drupal_validate_form($form_id, $form, $form_state);
- // form_clean_id() maintains a cache of element IDs it has seen,
+ // drupal_css_id() maintains a cache of element IDs it has seen,
// so it can prevent duplicates. We want to be sure we reset that
// cache when a form is processed, so scenarios that result in
// the form being built behind the scenes and again for the
// browser don't increment all the element IDs needlessly.
- drupal_static_reset('form_clean_id');
+ drupal_static_reset('drupal_css_id');
if ($form_state['submitted'] && !form_get_errors() && !$form_state['rebuild']) {
// Execute form submit handlers.
@@ -636,7 +636,7 @@ function drupal_prepare_form($form_id, &$form, &$form_state) {
elseif (isset($user->uid) && $user->uid && !$form_state['programmed']) {
$form['#token'] = $form_id;
$form['form_token'] = array(
- '#id' => form_clean_id('edit-' . $form_id . '-form-token'),
+ '#id' => drupal_css_id('edit-' . $form_id . '-form-token'),
'#type' => 'token',
'#default_value' => drupal_get_token($form['#token']),
);
@@ -646,11 +646,11 @@ function drupal_prepare_form($form_id, &$form, &$form_state) {
$form['form_id'] = array(
'#type' => 'hidden',
'#value' => $form_id,
- '#id' => form_clean_id("edit-$form_id"),
+ '#id' => drupal_css_id("edit-$form_id"),
);
}
if (!isset($form['#id'])) {
- $form['#id'] = form_clean_id($form_id);
+ $form['#id'] = drupal_css_id($form_id);
}
$form += element_info('form');
@@ -1046,7 +1046,7 @@ function form_builder($form_id, $element, &$form_state) {
}
if (!isset($element['#id'])) {
- $element['#id'] = form_clean_id('edit-' . implode('-', $element['#parents']));
+ $element['#id'] = drupal_css_id('edit-' . implode('-', $element['#parents']));
}
// Handle input elements.
if (!empty($element['#input'])) {
@@ -1919,7 +1919,7 @@ function form_process_radios($element) {
'#default_value' => isset($element['#default_value']) ? $element['#default_value'] : NULL,
'#attributes' => $element['#attributes'],
'#parents' => $element['#parents'],
- '#id' => form_clean_id('edit-' . implode('-', $parents_for_id)),
+ '#id' => drupal_css_id('edit-' . implode('-', $parents_for_id)),
'#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
);
}
@@ -2235,7 +2235,7 @@ function form_process_tableselect($element) {
'#default_value' => ($element['#default_value'] == $key) ? $key : NULL,
'#attributes' => $element['#attributes'],
'#parents' => $element['#parents'],
- '#id' => form_clean_id('edit-' . implode('-', $parents_for_id)),
+ '#id' => drupal_css_id('edit-' . implode('-', $parents_for_id)),
'#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
);
}
@@ -2684,42 +2684,6 @@ function _form_set_class(&$element, $class = array()) {
}
/**
- * Prepare an HTML ID attribute string for a form item.
- *
- * Remove invalid characters and guarantee uniqueness.
- *
- * @param $id
- * The ID to clean.
- * @param $flush
- * If set to TRUE, the function will flush and reset the static array
- * which is built to test the uniqueness of element IDs. This is only
- * used if a form has completed the validation process. This parameter
- * should never be set to TRUE if this function is being called to
- * assign an ID to the #ID element.
- * @return
- * The cleaned ID.
- */
-function form_clean_id($id = NULL) {
- $seen_ids = &drupal_static(__FUNCTION__, array());
- $id = str_replace(array('][', '_', ' '), '-', $id);
-
- // Ensure IDs are unique. The first occurrence is held but left alone.
- // Subsequent occurrences get a number appended to them. This incrementing
- // will almost certainly break code that relies on explicit HTML IDs in
- // forms that appear more than once on the page, but the alternative is
- // outputting duplicate IDs, which would break JS code and XHTML
- // validity anyways. For now, it's an acceptable stopgap solution.
- if (isset($seen_ids[$id])) {
- $id = $id . '-' . $seen_ids[$id]++;
- }
- else {
- $seen_ids[$id] = 1;
- }
-
- return $id;
-}
-
-/**
* @} End of "defgroup form_api".
*/
diff --git a/includes/theme.inc b/includes/theme.inc
index 71fbf9ba7..ca0e533aa 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -2128,18 +2128,17 @@ function template_preprocess_html(&$variables) {
if ($suggestions = template_page_suggestions(arg(), 'page')) {
foreach ($suggestions as $suggestion) {
if ($suggestion != 'page-front') {
- // Add current suggestion to page classes to make it possible to theme the page
- // depending on the current page type (e.g. node, admin, user, etc.) as well as
- // more specific data like node-12 or node-edit. To avoid illegal characters in
- // the class, we're removing everything disallowed. We are not using 'a-z' as
- // that might leave in certain international characters (e.g. German umlauts).
- $variables['classes_array'][] = preg_replace('![^abcdefghijklmnopqrstuvwxyz0-9-_]+!s', '', form_clean_id(drupal_strtolower($suggestion)));
+ // Add current suggestion to page classes to make it possible to theme
+ // the page depending on the current page type (e.g. node, admin, user,
+ // etc.) as well as more specific data like node-12 or node-edit.
+ $variables['classes_array'][] = drupal_css_class($suggestion);
}
}
}
+ // If on an individual node page, add the node type to body classes.
if ($node = menu_get_object()) {
- $variables['classes_array'][] = 'node-type-' . form_clean_id($node->type);
+ $variables['classes_array'][] = drupal_css_class('node-type-' . $node->type);
}
// RDFa allows annotation of XHTML pages with RDF data, while GRDDL provides
@@ -2150,7 +2149,6 @@ function template_preprocess_html(&$variables) {
$variables['language'] = $GLOBALS['language'];
$variables['language']->dir = $GLOBALS['language']->direction ? 'rtl' : 'ltr';
-
// Add favicon.
if (theme_get_setting('toggle_favicon')) {
$favicon = theme_get_setting('favicon');