From 80ff5109a774a69473e2a9d74a49b8dc4da03e8f Mon Sep 17 00:00:00 2001
From: Dries Buytaert
Date: Sun, 29 Jul 2007 17:28:23 +0000
Subject: [PATCH] - Patch #162708 by Eaton and Earl: add support for image
buttons to FAPI3.
This is a small form API extension (doesn't break existing code) that
facilitates the Drupal 6 upgrade of the Views module. A good example
of why it can be beneficial to start upgrading your modules early on in
the code freeze. ;)
---
includes/bootstrap.inc | 2 +-
includes/common.inc | 3 +
includes/form.inc | 147 +++++++++++++++++++-------
modules/forum/forum-submitted.tpl.php | 6 +-
modules/forum/forums.tpl.php | 2 +-
modules/menu/menu.module | 2 +-
modules/system/system.module | 3 +-
7 files changed, 121 insertions(+), 44 deletions(-)
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index c5792998223..52bfc5fa5c9 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -1101,6 +1101,6 @@ function ip_address() {
$remote_ip = $ip_array[0];
}
}
-
+
return $remote_ip;
}
diff --git a/includes/common.inc b/includes/common.inc
index 98b65431686..c07fc1bee59 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -2774,6 +2774,9 @@ function drupal_common_themes() {
'button' => array(
'arguments' => array('element' => NULL),
),
+ 'image_button' => array(
+ 'arguments' => array('element' => NULL),
+ ),
'hidden' => array(
'arguments' => array('element' => NULL),
),
diff --git a/includes/form.inc b/includes/form.inc
index 865c1fecdee..5ab3d885f49 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -44,7 +44,6 @@
*/
function drupal_get_form($form_id) {
$form_state = array('storage' => NULL, 'submitted' => FALSE);
- $expire = max(ini_get('session.cookie_lifetime'), 86400);
$args = func_get_args();
@@ -62,12 +61,7 @@ function drupal_get_form($form_id) {
// form_state data from a previous step, we'll retrieve it so it can
// be passed on to the form processing code.
if (isset($_POST['form_id']) && $_POST['form_id'] == $form_id && !empty($_POST['form_build_id'])) {
- if ($cached = cache_get('form_'. $_POST['form_build_id'], 'cache_form')) {
- $form = $cached->data;
- if ($cached = cache_get('storage_'. $_POST['form_build_id'], 'cache_form')) {
- $form_state['storage'] = $cached->data;
- }
- }
+ $form = form_get_cache($_POST['form_build_id'], $form_state);
}
// If the previous bit of code didn't result in a populated $form
@@ -84,7 +78,9 @@ function drupal_get_form($form_id) {
$form['#build_id'] = $form_build_id;
drupal_prepare_form($form_id, $form, $form_state);
if (!empty($form['#cache'])) {
- cache_set('form_'. $form_build_id, $form, 'cache_form', $expire);
+ // By not sending the form state, we avoid storing the storage which
+ // won't have been touched yet.
+ form_set_cache($form_build_id, $form, NULL);
}
unset($form_state['post']);
}
@@ -126,10 +122,7 @@ function drupal_get_form($form_id) {
// Now, we cache the form structure so it can be retrieved later for
// validation. If $form_state['storage'] is populated, we'll also cache
// it so that it can be used to resume complex multi-step processes.
- cache_set('form_'. $form_build_id, $form, 'cache_form', $expire);
- if (!empty($form_state['storage'])) {
- cache_set('storage_'. $form_build_id, $form_state['storage'], 'cache_form', $expire);
- }
+ form_set_cache($form_build_id, $form, $form_state);
// Clear out all post data, as we don't want the previous step's
// data to pollute this one and trigger validate/submit handling,
@@ -144,6 +137,31 @@ function drupal_get_form($form_id) {
return drupal_render_form($form_id, $form);
}
+/**
+ * Fetch a form from cache.
+ */
+function form_get_cache($form_build_id, &$form_state) {
+ if ($cached = cache_get('form_'. $form_build_id, 'cache_form')) {
+ $form = $cached->data;
+ if ($cached = cache_get('storage_'. $form_build_id, 'cache_form')) {
+ $form_state['storage'] = $cached->data;
+ }
+ return $form;
+ }
+}
+
+/**
+ * Store a form in the cache
+ */
+function form_set_cache($form_build_id, $form, $form_state) {
+ $expire = max(ini_get('session.cookie_lifetime'), 86400);
+
+ cache_set('form_'. $form_build_id, $form, 'cache_form', $expire);
+ if (!empty($form_state['storage'])) {
+ cache_set('storage_'. $form_build_id, $form_state['storage'], 'cache_form', $expire);
+ }
+}
+
/**
* Retrieves a form using a form_id, populates it with $form_state['values'],
* processes it, and returns any validation errors encountered. This
@@ -840,13 +858,7 @@ function _form_builder_handle_input_element($form_id, &$form, &$form_state) {
$button_type = $form['#executes_submit_callback'] ? 'submit' : 'button';
$form_state['buttons'][$button_type][] = $form;
- // See if a submit button was clicked. In Internet Explorer, if ONLY
- // one submit button is present, AND the enter key is used to submit
- // the form, no form value is sent for it and we'll never detect a
- // match. In most cases, though, the following code will properly handle
- // finding the clicked button and storing any custom validate and
- // submit handlers it has defined.
- if (isset($form['#post'][$form['#name']]) && $form['#post'][$form['#name']] == $form['#value']) {
+ if (_form_button_was_clicked($form)) {
$form_state['submitted'] = $form_state['submitted'] || $form['#executes_submit_callback'];
// In most cases, we want to use form_set_value() to manipulate
@@ -877,6 +889,64 @@ function _form_builder_handle_input_element($form_id, &$form, &$form_state) {
form_set_value($form, $form['#value'], $form_state);
}
+/**
+ * Helper function to handle the sometimes-convoluted logic of button
+ * click detection.
+ *
+ * In Internet Explorer, if ONLY one submit button is present, AND the
+ * enter key is used to submit the form, no form value is sent for it
+ * and we'll never detect a match. That special case is handled by
+ * _form_builder_ie_cleanup().
+ */
+function _form_button_was_clicked($form) {
+ // First detect normal 'vanilla' button clicks. Traditionally, all
+ // standard buttons on a form share the same name (usually 'op'),
+ // and the specific return value is used to determine which was
+ // clicked. This ONLY works as long as $form['#name'] puts the
+ // value at the top level of the tree of $_POST data.
+ if (isset($form['#post'][$form['#name']]) && $form['#post'][$form['#name']] == $form['#value']) {
+ return TRUE;
+ }
+ // When image buttons are clicked, browsers do NOT pass the form element
+ // value in $_POST. Instead they pass an integer representing the
+ // coordinates of the click on the button image. This means that image
+ // buttons MUST have unique $form['#name'] values, but the details of
+ // their $_POST data should be ignored.
+ elseif (!empty($form['#has_garbage_value']) && isset($form['#value']) && $form['#value'] !== '') {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * In IE, if only one submit button is present, AND the enter key is
+ * used to submit the form, no form value is sent for it and our normal
+ * button detection code will never detect a match. We call this
+ * function after all other button-detection is complete to check
+ * for the proper conditions, and treat the single button on the form
+ * as 'clicked' if they are met.
+ */
+function _form_builder_ie_cleanup($form, &$form_state) {
+ // Quick check to make sure we're always looking at the full form
+ // and not a sub-element.
+ if (!empty($form['#type']) && $form['#type'] == 'form') {
+ // If we haven't recognized a submission yet, and there's a single
+ // submit button, we know that we've hit the right conditions. Grab
+ // the first one and treat it as the clicked button.
+ if (empty($form_state['submitted']) && !empty($form_state['buttons']['submit']) && empty($form_state['buttons']['button'])) {
+ $button = $form_state['buttons']['submit'][0];
+
+ // Set up all the $form_state information that would have been
+ // populated had the button been recognized earlier.
+ $form_state['submitted'] = TRUE;
+ $form_state['submit_handlers'] = empty($button['#submit']) ? NULL : $button['#submit'];
+ $form_state['validate_handlers'] = empty($button['#validate']) ? NULL : $button['#validate'];
+ $form_state['values'][$button['#name']] = $button['#value'];
+ $form_state['clicked_button'] = $button;
+ }
+ }
+}
+
/**
* Helper function to determine the value for a checkbox form element.
*
@@ -999,24 +1069,6 @@ function form_type_token_value($form, $edit = FALSE) {
}
}
-/**
- * Handle the special Internet Explorer one-button-form hit-enter-
- * instead-of-clicking scenario.
- */
-function _form_builder_ie_cleanup($form, &$form_state) {
- if (!empty($form['#type']) && $form['#type'] == 'form') {
- // If the 'submitted' flag isn't tripped, but there is only one submit button...
- if (empty($form_state['submitted']) && !empty($form_state['buttons']['submit']) && empty($form_state['buttons']['button'])) {
- $button = $form_state['buttons']['submit'][0];
- $form_state['submitted'] = TRUE;
- $form_state['submit_handlers'] = empty($button['#submit']) ? NULL : $button['#submit'];
- $form_state['validate_handlers'] = empty($button['#validate']) ? NULL : $button['#validate'];
- $form_state['values'][$button['#name']] = $button['#value'];
- $form_state['clicked_button'] = $button;
- }
- }
-}
-
/**
* Use this function to make changes to form values in the form validate
* phase, so they will be available in the submit phase in $form_state.
@@ -1598,6 +1650,27 @@ function theme_button($element) {
return '\n";
}
+/**
+ * Theme an image button.
+ */
+function theme_image_button($element) {
+ // Make sure not to overwrite classes.
+ if (isset($element['#attributes']['class'])) {
+ $element['#attributes']['class'] = 'form-'. $element['#button_type'] .' '. $element['#attributes']['class'];
+ }
+ else {
+ $element['#attributes']['class'] = 'form-'. $element['#button_type'];
+ }
+
+ return '\n";
+}
+
/**
* Format a hidden form field.
*
diff --git a/modules/forum/forum-submitted.tpl.php b/modules/forum/forum-submitted.tpl.php
index 79580c3aa3a..747cf83752b 100644
--- a/modules/forum/forum-submitted.tpl.php
+++ b/modules/forum/forum-submitted.tpl.php
@@ -1,10 +1,10 @@
-
by !author', array(
- '@time' => $time,
+ '@time' => $time,
'!author' => $author,
)); ?>
diff --git a/modules/forum/forums.tpl.php b/modules/forum/forums.tpl.php
index 1b8264a72e3..0b8e1dfb690 100644
--- a/modules/forum/forums.tpl.php
+++ b/modules/forum/forums.tpl.php
@@ -1,4 +1,4 @@
-'. format_plural($num_links, 'Warning: There is currently 1 menu item in %title. It will be deleted (system-defined items will be reset).', 'Warning: There are currently @count menu items in %title. They will be deleted (system-defined items will be reset).', array('%title' => $menu['title'])) .'