'image_button', '#title' => t('My button'), '#return_value' => 'my_data', '#src' => 'my/image/path.jpg', ); */ /* TODO Change 'Submit' to 'Save' on buttons It has been agreed on that the description 'Submit' for a button is not a good choice since it does not indicate what actually happens. While for example on node editing forms, 'Preview' and 'Delete' describe exactly what will happen when the user clicks on the button, 'Submit' only gives a vague idea. When labelling your buttons, make sure that it is clear what this button does when the user clicks on it. */ /* TODO Node previews and adding form fields to the node form. There is a subtle but important difference in the way node previews (and other such operations) are carried out when adding or editing a node. With the new Forms API, the node form is handled as a multi-step form. When the node form is previewed, all the form values are submitted, and the form is rebuilt with those form values put into $form['#node']. Thus, form elements that are added to the node form will lose any user input unless they set their '#default_value' elements using this embedded node object. */ /* TODO New user_mail_tokens() method may be useful. user.module now provides a user_mail_tokens() function to return an array of the tokens available for the email notification messages it sends when accounts are created, activated, blocked, etc. Contributed modules that wish to make use of the same tokens for their own needs are encouraged to use this function. */ /* TODO There is a new hook_watchdog in core. This means that contributed modules can implement hook_watchdog to log Drupal events to custom destinations. Two core modules are included, dblog.module (formerly known as watchdog.module), and syslog.module. Other modules in contrib include an emaillog.module, included in the logging_alerts module. See syslog or emaillog for an example on how to implement hook_watchdog. function example_watchdog($log = array()) { if ($log['severity'] == WATCHDOG_ALERT) { mysms_send($log['user']->uid, $log['type'], $log['message'], $log['variables'], $log['severity'], $log['referer'], $log['ip'], format_date($log['timestamp'])); } } */ function editablefields_theme() { return array( 'editablefields_formatter_editable' => array( 'arguments' => array('element' => NULL), ), /* 'views_editablefields_handle_field' => array( 'file' => 'editablefields.module', 'arguments' => array( 'fields' => NULL, 'field' => NULL, 'data' => NULL, ), ), 'views_editablefields_view_list' => array( 'file' => 'editablefields.module', 'arguments' => array( 'view' => NULL, 'nodes' => NULL, 'type' => NULL, ), ), 'views_editablefields_view_table' => array( 'file' => 'editablefields.module', 'arguments' => array( 'view' => NULL, 'nodes' => NULL, 'type' => NULL, ), ), 'views_editablefields_view_list_noform' => array( 'file' => 'editablefields.module', 'arguments' => array( 'view' => NULL, 'nodes' => NULL, 'type' => NULL, ), ), 'views_editablefields_view_table_noform' => array( 'file' => 'editablefields.module', 'arguments' => array( 'view' => NULL, 'nodes' => NULL, 'type' => NULL, ), ), */ ); }; /* TODO An argument for replacements has been added to format_plural(), escaping and/or theming the values just as done with t().*/ /* TODO You may want to take advantage of new form-specific alter hooks. The hook_form_alter() is complemented by hook_form_$form-id_alter(). Optionally, modules can implement form-specific alteration functions rather than a single hook_form_alter() with many conditional switch statements. This is optional, and is most useful for tidying the code of modules that alter many forms to customize a site's operations. The new function names are built using the following format: [your-module-name]_form_[$form_id]_alter. */ function editablefields_views_style_plugins() { $result = array( 'editablefields_table' => array( 'name' => t('Editablefields - table'), 'theme' => 'views_editablefields_view_table', 'needs_fields' => true, 'needs_table_header' => true, 'even_empty' => true, ), 'editablefields_list' => array( 'name' => t('Editablefields - list'), 'theme' => 'views_editablefields_view_list', 'needs_fields' => true, 'needs_table_header' => true, 'even_empty' => true, ), 'ef_table_noform' => array( 'name' => t('Editablefields - table - no form'), 'theme' => 'views_editablefields_view_table_noform', 'needs_fields' => true, 'needs_table_header' => true, 'even_empty' => true, ), 'ef_list_noform' => array( 'name' => t('Editablefields - list - no form'), 'theme' => 'views_editablefields_view_list_noform', 'needs_fields' => true, 'needs_table_header' => true, 'even_empty' => true, ), ); return $result; } function editablefields_field_formatter_info() { return array( 'editable' => array( 'label' => 'Editable', 'field types' => array_keys(_content_field_types()), )); } function theme_editablefields_formatter_editable($element) { $field_name=$element['#field_name']; $field = content_fields($field_name); $node=$element['#node']; // See if access to this form element is restricted, // if so, skip widget processing and just set the value. $access = TRUE; $field_access = module_invoke_all('field_access', 'edit', $field); foreach ($field_access as $value) { if (empty($value)) { $access = FALSE; } } if (!$access) { // can't edit $formatter_name = 'default'; if ($formatter = _content_get_formatter($formatter_name, $field['type'])) { $theme = $formatter['module'] .'_formatter_'. $formatter_name; return theme($theme,$element); } } else { $formatter_name = 'default'; if ($formatter = _content_get_formatter($formatter_name, $field['type'])) { $theme = $formatter['module'] .'_formatter_'. $formatter_name; return '
'. theme($theme,$element). '
'; } } } function _editablefields_create_form($node,$field_name) { $field = content_fields($field_name); $fname="editablefields_tmp_form_".$node->nid."_".$field_name; // drupal_set_message($field_name." ". $field['field_name']); $form = array('#node' => $node); $form_state = array('values' => array($field['field_name'] => $default_value)); module_load_include('inc', 'content', 'includes/content.node_form'); $form['#field_info'] = array($field['field_name'] => $field); $form = content_field_form($form, $form_state, $field, 0); unset($form[$field_name]['#title']); $form['#type'] = 'form'; $form['#field_info'] = array($field['field_name'] => $field); // drupal_set_message(str_replace(" "," ",str_replace("\n","
",print_r($form,TRUE)))); $form=form_builder($fname,$form, $form_state); return drupal_render($form); } /** * handle editable field forms, and return back if there are editable fields */ function _editablefields_node_load_and_update($nid,$oldnode=NULL) { $node=node_load($nid); if (node_access("update",$node)) { $nodeupdate=FALSE; if ($_POST['op']) { foreach ($_POST as $post => $value) { if (sscanf($post, "editablefield_%d_%s",$nid,$fieldname) == 2) { if ($nid == $node->nid) { if ($node->$fieldname != $value) { $node->$fieldname=$oldnode?$oldnode->$fieldname:$value; $nodeupdate=TRUE; } } } } } } return $nodeupdate? $node : NULL; } function _handle_editablefield_form_input($view, $nodes) { // it's really hard to check for each field, as we would have to decode the info // data, I guess we could, but I dont see the harm, we will revent people from // writing to nodes they are not allowed to below anyway. $editable=false; foreach ($view->field as $field) { if ($field['options'] == 'editable') { $editable=true; } } /* if ($editable) { // we dont need to be THIS zealous $editable=FALSE; foreach ($nodes as $node) { if (node_access("update",$node)) { $editable=TRUE; } } } */ if ($editable) { foreach ($nodes as $node) { if ($node=_editablefields_node_load_and_update($node->nid)) { global $viewfield_stack; $tmp=$viewfield_stack; $viewfield_stack=array(); node_validate($node,array('title'=>array('#parents'=>array('title')))); if (! form_get_errors()) { $node=_editablefields_node_load_and_update($node->nid); $node=node_submit($node); // this will ensure that we do not touch ANY fields, appart from the // ones we are aloud to touch $node=_editablefields_node_load_and_update($node->nid,$node); //This implements auto_nodetitle actualization if (variable_get('ant_'. $node->type, 0)) { auto_nodetitle_set_title($node); } node_save($node); } $viewfield_stack=$tmp; } } } return $editable; } function _editablefields_make_form_ids_unique($form, $nid) { // much of this code is from form_builder. we set input elements' #id to a // unique id by postpending -$nid. if ((!empty($form['#type'])) && ($info = _element_info($form['#type']))) { // overlay $info onto $form, retaining preexisting keys in $form $form += $info; } if (isset($form['#input']) && $form['#input']) { $form['#id'] = (isset($form['#id'])) ? $form['#id'] : 'edit-' . implode('-', $form['#parents']); $form['#id'] .= '-' . $nid; } // recurse through sub-elements foreach (element_children($form) as $key) { // don't squash an existing tree value if (!isset($form[$key]['#tree'])) { $form[$key]['#tree'] = $form['#tree']; } // don't squash existing parents value if (!isset($form[$key]['#parents'])) { // Check to see if a tree of child elements is present. If so, continue down the tree if required. $form[$key]['#parents'] = $form[$key]['#tree'] && $form['#tree'] ? array_merge($form['#parents'], array($key)) : array($key); } $form[$key] = _editablefields_make_form_ids_unique($form[$key], $nid); } return $form; } function _editablefields_content_form_field(&$node, $fieldname) { $form = array(); $type_name = is_string($node) ? $node : (is_array($node) ? $node['type'] : $node->type); $types = content_types($type_name); $field=$types['fields'][$fieldname]; $widget_types = _content_widget_types(); // Set form parameters so we can accept file uploads. if (count($type['fields'])) { $form['#attributes'] = array("enctype" => "multipart/form-data"); } _editablefields_content_widget_invoke_field('prepare form values', $node,$field,$widget_types); $form = array_merge($form,_editablefields_content_widget_invoke_field('form',$node,$field,$widget_types)); return $form; } /** * Invoke a widget hook for one field. */ function _editablefields_content_widget_invoke_field($op, &$node, $field, $widget_types) { $return = array(); $node_field = isset($node->$field['field_name']) ? $node->$field['field_name'] : array(); $module = $widget_types[$field['widget']['type']]['module']; $function = $module .'_widget'; if (function_exists($function)) { // If we're building a node creation form, pre-fill with default values if ($op == 'prepare form values' && empty($node->nid)) { $node_field = array_merge($node_field, content_default_value($node, $field, $node_field)); } $result = $function($op, $node, $field, $node_field); if (is_array($result) && $op == 'form') { $result[$field['field_name']]['#weight'] = $field['widget']['weight']; } if (is_array($result)) { $return = array_merge($return, $result); } else if (isset($result)) { $return[] = $result; } } // test for values in $node_field in case modules added items if (is_object($node) && (isset($node->$field['field_name']) || count($node_field))) { $node->$field['field_name'] = $node_field; } return $return; } /** * Themeable function to handle displaying a specific field. */ function theme_views_editablefields_handle_field($fields, $field, $data) { $info = $fields[$field['fullname']]; if ($field['options'] == 'editable') { $node=node_load($data->nid); if (node_access("update",$node)) { if ($info['content_field']['field_name']) { $form=array(); global $viewfield_stack; $tmp=$viewfield_stack; $viewfield_stack=array(); $form=_editablefields_content_form_field($node, $info['content_field']['field_name']); $viewfield_stack=$tmp; foreach (element_children($form) as $key) { $form["editablefield_".$data->nid."_".$key]=$form[$key]; unset($form[$key]); } $form=_editablefields_make_form_ids_unique($form,$data->nid); /* TODO form_builder() now accepts a form_state parameter. */ $form_state = array(); $form=form_builder('editableviewfield',$form, $form_state); return $form="
nid."\" field=\"".$info['content_field']['field_name']."\">".drupal_render_form('editableviewfield',$form)."
"; } // no access, so silently just print field out. else if (!empty($info['form_parents'])){ $form = array(); $node_form = node_invoke($node, 'form'); foreach (explode('][', $info['form_parents']) as $key){ $node_form = $node_form[$key]; } if (is_array($node_form)){ $form['editablefield_'. $data->nid .'_'. $field['field']] = $node_form; } $form = _editablefields_make_form_ids_unique($form, $data->nid); /* TODO form_builder() now accepts a form_state parameter. */ $form_state = array(); $form = form_builder('editableviewfield', $form, $form_state); return $form = drupal_render_form('editableviewfield', $form); } } else { // drupal_set_message("enable CCK if you wish to edit fields"); } } if ($field['handler'] && function_exists($field['handler'])) { return $field['handler']($info, $field, $data->$field['queryname'], $data); } if ($info['handler'] && is_string($info['handler']) && function_exists($info['handler'])) { return $info['handler']($info, $field, $data->$field['queryname'], $data); } return check_plain($data->$field['queryname']); } /** * Display the nodes of a view as a list. */ function theme_views_editablefields_view_list($view, $nodes, $type) { $fields = _views_get_fields(); $editable=_handle_editablefield_form_input($view, $nodes); foreach ($nodes as $node) { $item = ''; foreach ($view->field as $field) { if (!isset($fields[$field['id']]['visible']) && $fields[$field['id']]['visible'] !== FALSE) { if ($field['label']) { $item .= "
" . $field['label'] . "
"; } $item .= "
" . views_theme_field('views_editablefields_handle_field', $field['queryname'], $fields, $field, $node, $view) . "
"; } } $items[] = "
name) ."'>$item
\n"; // l($node->title, "node/$node->nid"); } $html=theme('item_list', $items); if ($editable) { $newentry_form=_editablefields_entry_form($view); if ($nodes) { $form['editablefields-a-'.$view->name]['submit']= array('#type' => 'submit', '#value' => t('Update')); $form['editablefields-a-'.$view->name]['#value']=$html; drupal_process_form('editablefields-a-'.$view->name,$form); $eform=drupal_render($form); return $eform.$newentry_form; } else { return $newentry_form; } } else { return $html; } } /** * Display the nodes of a view as a table. */ function theme_views_editablefields_view_table($view, $nodes, $type) { $fields = _views_get_fields(); $editable=_handle_editablefield_form_input($view, $nodes); foreach ($nodes as $node) { $row = array(); foreach ($view->field as $field) { if ($fields[$field['id']]['visible'] !== FALSE) { $cell['data'] = views_theme_field('views_editablefields_handle_field', $field['queryname'], $fields, $field, $node, $view); $cell['class'] = "view-field ". views_css_safe('view-field-'. $field['queryname']); $row[] = $cell; } } $rows[] = $row; } $html=theme('table', $view->table_header, $rows ); if ($editable) { $newentry_form=""._editablefields_entry_form($view)."
"; //$newentry_form=_editablefields_entry_form($view); if ($nodes) { $form['editablefields-b-'.$view->name]['submit']= array('#type' => 'submit', '#value' => t('Update')); $form['editablefields-b-'.$view->name]['#value']=$html; drupal_process_form('editablefields-b-'.$view->name,$form); $eform=drupal_render($form); return $eform.$newentry_form; } else { return $newentry_form; } } else { return $html; } } /** * Display the nodes of a view as a list. */ function theme_views_editablefields_view_list_noform($view, $nodes, $type) { $fields = _views_get_fields(); $editable=_handle_editablefield_form_input($view, $nodes); foreach ($nodes as $node) { $item = ''; foreach ($view->field as $field) { if (!isset($fields[$field['id']]['visible']) && $fields[$field['id']]['visible'] !== FALSE) { if ($field['label']) { $item .= "
" . $field['label'] . "
"; } $item .= "
" . views_theme_field('views_editablefields_handle_field', $field['queryname'], $fields, $field, $node, $view) . "
"; } } $items[] = "
name) ."'>$item
\n"; // l($node->title, "node/$node->nid"); } $html=theme('item_list', $items); if ($editable) { if ($nodes) { $form['editablefields-c-'.$view->name]['submit']= array('#type' => 'submit', '#value' => t('Update')); $form['editablefields-c-'.$view->name]['#value']=$html; drupal_process_form('editablefields-c-'.$view->name,$form); $eform=drupal_render($form); return $eform; } } return $html; } /** * Display the nodes of a view as a table. */ function theme_views_editablefields_view_table_noform($view, $nodes, $type) { $fields = _views_get_fields(); $editable=_handle_editablefield_form_input($view, $nodes); foreach ($nodes as $node) { $row = array(); foreach ($view->field as $field) { if ($fields[$field['id']]['visible'] !== FALSE) { $cell['data'] = views_theme_field('views_editablefields_handle_field', $field['queryname'], $fields, $field, $node, $view); $cell['class'] = "view-field ". views_css_safe('view-field-'. $field['queryname']); $row[] = $cell; } } $rows[] = $row; } $html=theme('table', $view->table_header, $rows ); if ($editable) { if ($nodes) { $form['editablefields-d-'.$view->name]['submit']= array('#type' => 'submit', '#value' => t('Update')); $form['editablefields-d-'.$view->name]['#value']=$html; drupal_process_form('editablefields-d-'.$view->name,$form); $eform=drupal_render($form); return $eform; } } return $html; } function _editablefields_node_type($view) { $editable=false; foreach ($view->field as $field) { if ($field['options'] == 'editable') { $editable=true; } } $type = false; if ($editable) { foreach ($view->filter as $filter) { if ($filter['field'] == 'node.type') { $type = $filter['value'][0]; break; } } } return $type; } function _editablefields_entry_form($view) { $type=_editablefields_node_type($view); if (!$type) { return ''; } global $user; $types = node_get_types(); $type = isset($type) ? str_replace('-', '_', $type) : NULL; // If a node type has been specified, validate its existence. if (isset($types[$type]) && node_access('create', $type)) { // Initialize settings: $node = array('uid' => $user->uid, 'name' => $user->name, 'type' => $type, 'language' => ''); $form = _editablefields_drupal_get_form(false,$type,$view); $output = drupal_render_form($type.'_node_form',$form); } return ''; } function editablefields_views_pre_query(&$view) { if ($_POST['editablefields_addnew_form']) { $type=_editablefields_node_type($view); if (!$type) { return; } unset ($_POST['editablefields_addnew_form']); _editablefields_drupal_get_form(true,$type,$view); } } function _editablefields_drupal_get_form($process=false, $type,$view) { global $viewfield_stack; $tmp=$viewfield_stack; $viewfield_stack=array(); global $user; $form_id=$type.'_node_form'; $node = array('uid' => $user->uid, 'name' => $user->name, 'type' => $type, 'language' => ''); $form_state = array('storage' => NULL, 'submitted' => FALSE); $form_state['post'] = $_POST; /* TODO drupal_retrieve_form() now accepts a form_state parameter. */ $form=drupal_retrieve_form($form_id,$node, $form_state); drupal_prepare_form($form_id, $form, $form_state); $form_build_id = 'form-'. md5(mt_rand()); $form['#build_id'] = $form_build_id; $form['editablefields_addnew_form']=array('#type' => 'hidden', '#value' => $type); foreach ($view->argument as $id => $arg) { if (preg_match('/^content: (field_.*)$/',$arg['type'],$matches)) { $fieldname=$matches[1]; if (is_array($view->args[$id])) { $form['editablefieldsfiltervalue_'.$fieldname]=array('#type'=>'value','#value'=>$view->args[$id]); } else { $form['editablefieldsfiltervalue_'.$fieldname]=array('#type'=>'value','#value'=>array($view->args[$id])); } } } foreach ($view->filter as $filter) { if (preg_match('/^node_data_(.*)\.\1_(.*)$/',$filter['field'], $matches)) { $fieldname=$matches[1]; $valuename=$matches[2]; $form['editablefieldsfiltervalue_'.$fieldname]=array('#type'=>'value','#value'=>$filter['value']); } } unset ($form['preview']); // preview really gets in the way of this functionality drupal_prepare_form($form_id, $form, $form_state); $colspan=0; foreach ($view->field as $vf=>$vfield) { $colspan++; foreach ($form as $fn=>$fi) { if ($vfield['field']==$fn."_value") { $form[$fn]['#prefix']=''; $form[$fn]['#suffix']=''; $colspan=0; } } } $newform=array(); // $newform['form_editablefield_row']=array('#type' => 'fieldset', '#prefix' => '', '#suffix' => '', '#weight' =>0); // $newform['form_editablefield_other']=array('#type' => 'fieldset', '#prefix' => '', '#suffix' => '','#weight' =>10); $newform['form_editablefield_row']=array('#type' => 'fieldset', '#prefix' => '', '#suffix' => ''); $newform['form_editablefield_other']=array('#type' => 'fieldset', '#collapsible'=>'TRUE', '#collapsed'=>'TRUE', '#prefix' => '', '#suffix' => ''); foreach ($form as $fn=>$fi) { if (is_array($form[$fn]) && strncmp($fn,'#',1)!=0) { $inview=0; foreach ($view->field as $vf=>$vfield) { if (strncmp($fn."_",$vfield['field'],strlen($fn)+1)==0) { $inview++; } } if ($inview) { $newform['form_editablefield_row'][$fn]=$form[$fn]; } else { $newform['form_editablefield_other'][$fn]=$form[$fn]; } // unset($form[$fn]); } else { $newform[$fn]=$fi; } } $form=$newform; // print_r($form); //if (!empty($form['#cache'])) { // 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']); $form['#post'] = $_POST; if ($process) { drupal_process_form($form_id, $form, $form_state); } $viewfield_stack=$tmp; return $form; } function editablefields_form_alter(&$form, &$form_state, $form_id) { foreach ($form as $key=>$f) { if (preg_match('/^editablefieldsfiltervalue_(.*)$/',$key, $matches)) { $fieldname=$matches[1]; foreach ($form[$fieldname] as $element=>$val) { if (is_array($val) && is_array($val['#default_value'])) { $form[$fieldname][$element]['#default_value']=$f['#value']; if (!$form[$fieldname][$element]['#options'][$f['#value'][0]]) { $form[$fieldname][$element]['#options'][$f['#value'][0]]=t('-- this --'); } } } } } } ?>