This is a small case study that I've done during custom module development. I'd like to share it and review any comments or advices.
The main idea is to create an action that deal with node reference CCK field. This action can be useful with View Bulk Operation (VBO).
Let's suppose that we have a node type called "mynode", wich has a CCK field called "field_noderef" with unlimited values. The action performed on nodes will display a form with autocomplete widget to enter the name of referenced node.
First of all let's create the implementation of hook_action_info().
/**
* Implementation of hook_action_info().
*
*/
function MYMODULE_action_info(){
return array(
'MYMODULE_noderef_action' => array(
'description' => t('Nodereference Action'),
'type' => 'node',
'configurable' => FALSE,
)
);
}// end function MYMODULE_action_info;
MYMODULE_noderef_action the action handler will be implemented later.
This action on performed will display a form that contains autocomplete textfield, so let's implement the function that will generate the form. Note that the name of this function should be like this: action handler + "_form": MYMODULE_noderef_action_form()
function MYMODULE_noderef_action_form($context){
$form['action_noderef_text'] = array(
'#type' => 'textfield',
'#title' => t('Parent Node'),
'#size' => 60,
'#required' => TRUE,
'#autocomplete_path' => 'nodereference/autocomplete/field_noderef'
);
return $form;
}// end function MYMODULE_noderef_action_form;
If you want to validate the form:
function MYMODULE_noderef_action_validate($form, &$form_state){
//validation code goes here..
}// end function MYMODULE_noderef_action_validate;
Now we will implement the form submit. Please note that the form submit function will return an array that will be passed to the action handler MYMODULE_noderef_action.
function MYMODULE_noderef_action_submit($form, &$form_state){
return array(
'parent_name' => $form_state['values']['action_noderef_text']
);
}// end function MYMODULE_noderef_action_submit;
Finally the action handler function, which will receive the returned array from submit function:
/**
* Action handler
*
*/
function MYMODULE_noderef_action(&$node, $context = array()){
//this validation code is copied from noderefrence module..
preg_match('/^(?:\s*|(.*) )?\[\s*nid\s*:\s*(\d+)\s*\]$/', $context['parent_name'], $matches);
if (!empty($matches)) {
// Explicit [nid:n].
list(, $title, $parent_nid) = $matches;
}
// -->
$parent_found = FALSE;
foreach($node->field_noderef as $parent){
if($parent['nid'] == $parent_nid){
$parent_found = TRUE;
break;
}
}// end foreach;
if($parent_found){
drupal_set_message(t('The node is already has this parent.'), 'error');
}else{
$node->field_noderef[]['nid'] = $parent_nid;
node_save($node);
}
}// end function MYMODULE_noderef_action;
If you are looking for a good tutorial about writing actions in Drupal, see: http://drupal.org/node/172152.
Comments
awesome idea!
This is exactly what I was looking for. I'm trying to use it with VBO but the MYMODULE_noderef_action_form is not getting called.
I found that I had to change
to be
In order to get the form to be called.
--
Morris Animal Foundation
:)
Glad to help :)
Dropdown Form
Ho can this be done w/ a dropdown form?