Heine

  • home
  • drupal
  • drupal core commits
  • about
Home › Drupal Core Commits

Commit 75092 by dries

- 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      2007/07/26 21:42:51     1.177
+++ includes/bootstrap.inc      2007/07/29 17:28:23     1.178
@@ -1,5 +1,5 @@
 <?php
-// $Id: bootstrap.inc,v 1.177 2007/07/26 21:42:51 unconed Exp $
+// $Id: bootstrap.inc,v 1.178 2007/07/29 17:28:23 dries Exp $
 
 /**
  * @file
@@ -1101,6 +1101,6 @@
       $remote_ip = $ip_array[0];
     }
   }
-  
+
   return $remote_ip;
 }
--- includes/common.inc 2007/07/13 20:07:14     1.674
+++ includes/common.inc 2007/07/29 17:28:23     1.675
@@ -1,5 +1,5 @@
 <?php
-// $Id: common.inc,v 1.674 2007/07/13 20:07:14 goba Exp $
+// $Id: common.inc,v 1.675 2007/07/29 17:28:23 dries Exp $
 
 /**
  * @file
@@ -2774,6 +2774,9 @@
     'button' => array(
       'arguments' => array('element' => NULL),
     ),
+    'image_button' => array(
+      'arguments' => array('element' => NULL),
+    ),
     'hidden' => array(
       'arguments' => array('element' => NULL),
     ),
--- includes/form.inc   2007/07/20 05:44:13     1.217
+++ includes/form.inc   2007/07/29 17:28:23     1.218
@@ -1,5 +1,5 @@
 <?php
-// $Id: form.inc,v 1.217 2007/07/20 05:44:13 dries Exp $
+// $Id: form.inc,v 1.218 2007/07/29 17:28:23 dries Exp $
 
 /**
  * @defgroup form Form generation
@@ -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 @@
     // 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 @@
       $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 @@
     // 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,
@@ -145,6 +138,31 @@
 }
 
 /**
+ * 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
  * function is the programmatic counterpart to drupal_get_form().
@@ -840,13 +858,7 @@
     $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
@@ -878,6 +890,64 @@
 }
 
 /**
+ * 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.
  *
  * @param $form
@@ -1000,24 +1070,6 @@
 }
 
 /**
- * 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.
  *
@@ -1599,6 +1651,27 @@
 }
 
 /**
+ * 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 '<input type="image" name="'. $element['#name'] .'" ' .
+    (!empty($element['#value']) ? ('value="'. check_plain($element['#value']) .'" ') : '') .
+    'id="' . $element['#id'] . '" ' .
+    drupal_attributes($element['#attributes']) .
+    ' src="' . base_path() . $element['#image'] . '" ' .
+    (!empty($element['#title']) ? 'alt="' . check_plain($element['#title']) . '" title="' . check_plain($element['#title']) . '" ' : '' ).
+    "/>\n";
+}
+
+/**
  * Format a hidden form field.
  *
  * @param $element
--- modules/forum/forum-submitted.tpl.php       2007/07/26 06:48:03     1.1
+++ modules/forum/forum-submitted.tpl.php       2007/07/29 17:28:23     1.2
@@ -1,10 +1,10 @@
-<?php
-// $Id: forum-submitted.tpl.php,v 1.1 2007/07/26 06:48:03 dries Exp $
+<?php
+// $Id: forum-submitted.tpl.php,v 1.2 2007/07/29 17:28:23 dries Exp $
 /**
  * @file forum-submitted.tpl.php
  * Default theme implementation to format a simple string indicated when and
  * by whom a topic was submitted.
- *
+ *
  * Available variables:
  *
  * - $author: The author of the post.
@@ -19,7 +19,7 @@
 <?php if ($time): ?>
   <?php print t(
   '@time ago<br />by !author', array(
-    '@time' => $time,
+    '@time' => $time,
     '!author' => $author,
     )); ?>
 <?php else: ?>
--- modules/forum/forums.tpl.php        2007/07/26 06:48:03     1.1
+++ modules/forum/forums.tpl.php        2007/07/29 17:28:23     1.2
@@ -1,4 +1,4 @@
-<?php // $Id: forums.tpl.php,v 1.1 2007/07/26 06:48:03 dries Exp $
+<?php // $Id: forums.tpl.php,v 1.2 2007/07/29 17:28:23 dries Exp $
 /**
  * @file forums.tpl.php
  * Default theme implementation to display a forum, which may contain forum
--- modules/menu/menu.module    2007/07/25 14:44:03     1.131
+++ modules/menu/menu.module    2007/07/29 17:28:23     1.132
@@ -1,5 +1,5 @@
 <?php
-// $Id: menu.module,v 1.131 2007/07/25 14:44:03 goba Exp $
+// $Id: menu.module,v 1.132 2007/07/29 17:28:23 dries Exp $
 
 /**
  * @file
@@ -478,7 +478,7 @@
   if ($num_links) {
     $caption .= '<p>'. format_plural($num_links, '<strong>Warning:</strong> There is currently 1 menu item in %title. It will be deleted (system-defined items will be reset).', '<strong>Warning:</strong> There are currently @count menu items in %title. They will be deleted (system-defined items will be reset).', array('%title' => $menu['title'])) .'</p>';
   }
-  $caption .= '<p>'. t('This action cannot be undone.') .'</p>';  
+  $caption .= '<p>'. t('This action cannot be undone.') .'</p>';
   return confirm_form($form, t('Are you sure you want to delete the custom menu %title?', array('%title' => $menu['title'])), 'admin/build/menu-customize/'. $menu['menu_name'], $caption, t('Delete'));
 }
 
--- modules/system/system.module        2007/07/20 05:44:13     1.511
+++ modules/system/system.module        2007/07/29 17:28:23     1.512
@@ -1,5 +1,5 @@
 <?php
-// $Id: system.module,v 1.511 2007/07/20 05:44:13 dries Exp $
+// $Id: system.module,v 1.512 2007/07/29 17:28:23 dries Exp $
 
 /**
  * @file
@@ -105,6 +105,7 @@
   // Inputs
   $type['submit'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => TRUE, '#ahah_event' => 'submit', '#process' => array('form_expand_ahah'));
   $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => FALSE, '#ahah_event' => 'submit', '#process' => array('form_expand_ahah'));
+  $type['image_button'] = array('#input' => TRUE, '#button_type' => 'submit','#executes_submit_callback' => TRUE, '#ahah_event' => 'submit', '#process' => array('form_expand_ahah'), '#has_garbage_value' => TRUE, '#image' => NULL);
   $type['textfield'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#autocomplete_path' => FALSE);
   $type['password'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128);
   $type['password_confirm'] = array('#input' => TRUE, '#process' => array('expand_password_confirm'));
@@ -3126,4 +3127,4 @@
 
 function system_goto_action($object, $context) {
   drupal_goto($context['url']);
-}
\ No newline at end of file
+}

No votes yet
  • Drupal Core
  • Download patch

Recent posts

  • Upgraded from 6.14 to 6.15, but Drupal still thinks it's 6.14?
  • Google Friendconnect Drupal module not recommended (yet)
  • The OpenID 2.0 Compliance Crusade - Part I
  • Using <embed> for XSS
  • Bugfix woes for Drupal 6
more

Security reviews

  • Afraid custom code makes your site vulnerable?
  • You don't really trust that module you just downloaded from Drupal.org?

Sleep better after a security review.

Tags

Captcha CSRF DOH! Drupal embed Input Format modx OpenID Performance Planet Drupal Security Varnish
more tags
  • home
  • drupal
  • drupal core commits
  • about

Copyright © 2010 by Heine Deelstra. All rights reserved.