Posted by ohmstor on March 24, 2009 at 8:40am
Jump to:
| Project: | AHAH helper |
| Version: | 6.x-2.0 |
| Component: | Code |
| Category: | bug report |
| Priority: | critical |
| Assigned: | Unassigned |
| Status: | active |
Issue Summary
When I use the AHAH Helper Module with a custom node, more precisely when I call the function ahah_helper_register() provided in the AHAH Helper Module I cannot delete posted nodes.
Below is an example code with which I can hit the error. I noticed that I can solve the problem by calling unset($form_state['storage']), however I do not know where I can call it from (after the delete button was pressed).
Any input would be greatly appreciated!
Thanks.
<?php
function testmodule_node_info()
{
return array(
'testmodule' => array(
'name' => t('testmodule'),
'module' => 'testmodule',
'description' => t('Node for testing'),
'has_title' => TRUE,
'title_label' => t('Title'),
'has_body' => TRUE,
'body_label' => t('Description'),
'min_word_count' => 0,
'locked' => TRUE
)
);
}
function testmodule_form_alter(&$form, &$form_state, $form_id)
{
if ($form_id =='testmodule_node_form')
{
ahah_helper_register($form, $form_state);
testmodule_theform(&$form, $form_state);
}
}
function testmodule_theform(&$form, $form_state)
{
if (!isset($form_state['storage']['billing_info']['usage']))
{
$usage_default_value = 'company';
}
else
{
$usage_default_value = $form_state['storage']['billing_info']['usage'];
}
$form['billing_info'] = array(
'#type' => 'fieldset',
'#title' => t('Billing information'),
'#prefix' => '<div id="billing-info-wrapper">', // This is our wrapper div.
'#suffix' => '</div>',
'#tree' => TRUE, // Don't forget to set #tree!
);
$form['billing_info']['usage'] = array(
'#type' => 'select',
'#title' => t('Usage'),
'#options' => array(
'private' => t('Private'),
'company' => t('Company'),
),
'#default_value' => $usage_default_value,
'#ahah' => array(
'event' => 'change',
// This is the "magical path". Note that the parameter is an array of
// the parents of the form item of the wrapper div!
'path' => ahah_helper_path(array('billing_info')),
'wrapper' => 'billing-info-wrapper',
),
);
$form['billing_info']['update_usage'] = array(
'#type' => 'submit',
'#value' => t('Update usage'),
// Note that we can simply use the generic submit callback provided by the
// ahah_helper module here!
// All it does, is set $form_state['rebuild'] = TRUE.
'#submit' => array('ahah_helper_generic_submit'),
// We set the 'no-js' class, which means this submit button will be hidden
// automatically by Drupal if JS is enabled.
'#attributes' => array('class' => 'no-js'),
);
// If 'company' is selected, then these two form items will be displayed.
if ($usage_default_value == 'company')
{
$form['billing_info']['company_name'] = array(
'#type' => 'textfield',
'#title' => t('Company name'),
'#required' => TRUE,
'#size' => 20,
'#maxlength' => 255,
// If the user switched to Private usage and back to Company usage, we
// remembered his company's name!
'#default_value' => $form_state['storage']['billing_info']['company_name'],
);
$form['billing_info']['vat'] = array(
'#type' => 'textfield',
'#title' => t('VAT number'),
'#description' => t('Please enter a Belgian VAT number, the format is: <em>BE0999999999</em>.'),
'#size' => 20,
'#maxlength' => 255,
// If the user switched to Private usage and back to Company usage, we
// remembered his VAT number!
'#default_value' => $form_state['storage']['billing_info']['vat'],
'#ahah' => array(
'event' => 'blur',
'path' => ahah_helper_path(array('billing_info', 'vat')),
'wrapper' => 'edit-billing-info-vat-wrapper',
'effect' => 'none',
'method' => 'replace',
),
);
// Provide instantaneous (#ahah-powered) feedback to the user about the
// VAT number he entered.
if (isset($form_state['storage']['billing_info']['vat']) && strlen($form_state['storage']['billing_info']['vat']) > 0)
{
$form['billing_info']['vat']['#field_suffix'] = theme('image', (preg_match('/^BE0\d{9}$/', $form_state['storage']['billing_info']['vat'])) ? 'misc/watchdog-ok.png' : 'misc/watchdog-error.png');
}
}
// And if 'private' is selected, then these two form items will be displayed.
else
{
$form['billing_info']['first_name'] = array(
'#type' => 'textfield',
'#title' => t('First name'),
'#required' => TRUE,
'#size' => 20,
'#maxlength' => 255,
// If the user switched to Company usage and back to Private usage, we
// remembered his first name!
'#default_value' => $form_state['storage']['billing_info']['first_name'],
);
$form['billing_info']['last_name'] = array(
'#type' => 'textfield',
'#title' => t('Last name'),
'#required' => TRUE,
'#size' => 20,
'#maxlength' => 255,
// If the user switched to Company usage and back to Private usage, we
// remembered his last name!
'#default_value' => $form_state['storage']['billing_info']['last_name'],
);
}
$form['billing_info']['address'] = array(
'#type' => 'textfield',
'#title' => t('Address'),
'#required' => TRUE,
'#size' => 20,
'#maxlength' => 255,
// Always set #default_value, even if it's not a dynamically added form item!
'#default_value' => $form_state['storage']['billing_info']['address'],
);
$form['billing_info']['country'] = array(
'#type' => 'textfield',
'#title' => t('Country'),
'#size' => 20,
'#maxlength' => 255,
// Always set #default_value, even if it's not a dynamically added form item!
'#default_value' => $form_state['storage']['billing_info']['country'],
);
}
?>
Comments
#1
I changed the priority to critical to get some attention to the fact that it's severe issue. A major functionality in drupal stops work (not being able to delete a node).
#2
I have the exact same problem, and tracked it down a little bit, so maybe this will help. Update: Oops, I misspoke. The code I posted only works on the 2nd press of the Delete button, as I had commingled a few different hacks together. I think i'm on the right track but it'll take some more time to get a proper workaround.
Apparently node_form_delete_submit in node.pages.inc runs, but if hook_form_alter or anything populates form_state['storage'], it does not run the redirect placed there by node_form_delete_submit.
One place that populates form_state['storage'] even on the first request is this bit in ahah_helper_register:
<?php79 // Register the file.
80 if (!isset($form_state['storage']['#ahah_helper']['file'])) {
81 $menu_item = menu_get_item();
82 if ($menu_item['file']) {
83 $form_state['storage']['#ahah_helper']['file'] = $menu_item['file'];
84 }
85 }
?>
This ends up setting form_state['storage'] which prevents the redirect from happening even on initial form load. This explains why calling ahah_helper_register() from within hook_form_alter will block node delete buttons from redirecting properly. If this part is commented out, it will work on the initial node form load. However, it appears that running through AHAH requests that set up form_state['storage'] also prevent subsequent presses of the Delete button.
A workaround that seems to work is to explicitly test for presses of the Delete button within hook_form_alter AFTER calling ahah_helper_register, and wipe out form_state['storage'] if it was pressed, as follows:
<?phpfunction modulename_form_alter(&$form, $form_state, $form_id) {
//...
ahah_helper_register($form, $form_state);
// ...
if ($form_state['values']['op'] == t('Delete')) {
// Clear out storage to allow for redirect to still happen.
$form_state['storage'] = NULL;
}
//...
}
?>
As such, I am not sure if this is a bug within ahah_helper, or if it is something that anyone who runs AHAH elements inside hook_form_alter should be aware of.
#3
I just ended up looking for Delete key presses and running a drupal_goto the node delete page. It sucks as a workaround, but I couldn't figure out what was causing Drupal to ignore the $form_state['redirect'] set within the node delete button handler.
#4
anyone? this seems like a big issue to me!
#5
I'm having the same troubles. I'm interested in the solution gelucky found - where where you looking for delete key presses? In hook_update()?
#6
For anyone who needs to do this, here is the solution I came up with. First, make sure that in hook_form, you are declaring both the $node and the $form_state, then add the code I will show below at the very top of your form definition:
<?phphook_form($node, $form_state)
{
if(isset($form_state['values']['op']) && $form_state['values']['op'] == $form_state['values']['delete'])
{
drupal_goto('node/' . $node->nid . '/delete');
}
}
?>
Seems to work for me now, though I haven't done much testing of it yet.
#7
This is one of the problems fixed by this patch:
#688210: patch to fix bugs using ahah_helper in a CCK widget