Posted by jonathan_hunt on July 21, 2009 at 5:06am
5 followers
| Project: | Node form columns |
| Version: | 6.x-1.6 |
| Component: | Code |
| Category: | feature request |
| Priority: | normal |
| Assigned: | Hugo Wetterberg |
| Status: | needs review |
Issue Summary
I want to define additional regions. Right now it looks like the only way to do this to change nodeformcols_form_regions() directly. It would be nicer if this could be done as a hook, perhaps even taking node type into account, so that external modules could specify additional regions for theming the node form.
Comments
#1
That's a great feature request. Will do.
#2
I'm just about to introduce some regions in the pattern [node_type]_header, [node_type]_payment etc. for some CCK-based forms. If you come up with some code, I'm happy to test a patch, or I might get around to writing a patch next week.
#3
FYI, I have some code like the following:
/**
* Introduce hook_node_form_regions(). Needs to return array of regions keyed by content type.
* e.g. 'page' => array('header' => t('Header'));
*/
function nodeformcols_form_regions($type = '') {
$node_form_region_hooks = module_invoke_all('node_form_regions');
if (!empty($type) && in_array($type, array_keys($node_form_region_hooks))) {
$regions = $node_form_region_hooks[$type];
return $regions;
}
return array(
'main' => t('Main column'),
'right' => t('Right'),
'footer' => t('Footer'),
);
}
i.e. pass content type to region definition and if a hook exists, retrieve region definitions from the hook.
Similarly, since each content type can define it's own regions, it also needs to define its own default placements.
/**
* Gets default placements for standard fields
*
* @return array
*/
function _nodeformscols_default_field_placements($type) {
$node_form_default_field_placements_hooks = module_invoke_all('default_field_placements');
if (!empty($type) && in_array($type, array_keys($node_form_default_field_placements_hooks))) {
$default_field_placements = $node_form_default_field_placements_hooks[$type];
return $default_field_placements;
}
return array(
'title' => array('region' => 'main'),
'body_field' => array('region' => 'main'),
'menu' => array('region' => 'right'),
'revision_information' => array('region' => 'right'),
'comment_settings' => array('region' => 'right'),
'path' => array('region' => 'right'),
'options' => array('region' => 'right'),
'author' => array('region' => 'right'),
'buttons' => array('region' => NODEFORMCOLS_DEFAULT_REGION, 'weight' => 100),
);
}
This isn't quite ideal as if there is no common region between two node types the fields don't show up in the Manage Form list of fields by region.
Perhaps the set of regions returned from the content type need to be merged with the base set defined by nodeformcols?
#4
Yep, but this will have to be done with a alter instead I think.
Along the lines of:
/*** Introduce hook_nodeformcols_form_regions_alter().
*/
function nodeformcols_form_regions($type) {
$regions = array(
'main' => t('Main column'),
'right' => t('Right'),
'footer' => t('Footer'),
);
drupal_alter('nodeformcols_form_regions', $regions, $type);
return $regions;
}
That way extenders can implement:
function somemodule_nodeformcols_form_regions_alter(&$regions, $type) {if ($type === 'page') {
$regions['custom'] = t('My custom region');
}
}
#5
Agreed, drupal_alter() is a more appropriate solution.
So in nodeformcols.module, I have:
/**
* Introduce hook_nodeformcols_form_regions_alter().
*/
function nodeformcols_form_regions($type = '') {
$regions = array(
'main' => t('Main column'),
'right' => t('Right'),
'footer' => t('Footer'),
);
drupal_alter('nodeformcols_form_regions', $regions, $type);
return $regions;
}
/**
* Gets default placements for standard fields
*
* @return array
*/
function _nodeformscols_default_field_placements($type = '') {
$placements = array(
'title' => array('region' => 'main'),
'body_field' => array('region' => 'main'),
'menu' => array('region' => 'right'),
'revision_information' => array('region' => 'right'),
'comment_settings' => array('region' => 'right'),
'path' => array('region' => 'right'),
'options' => array('region' => 'right'),
'author' => array('region' => 'right'),
'buttons' => array('region' => NODEFORMCOLS_DEFAULT_REGION, 'weight' => 100),
);
drupal_alter('nodeformcols_default_field_placements', $placements, $type);
return $placements;
}
and in template_preprocess_node_form(), pass type:
$form_regions = nodeformcols_form_regions($form['#node']->type);foreach ($form_regions as $name => $title) {
Also, in nodeformcols.admin.inc, pass type
Index: modules/nodeformcols/nodeformcols.admin.inc
===================================================================
--- modules/nodeformcols/nodeformcols.admin.inc (revision 14797)
+++ modules/nodeformcols/nodeformcols.admin.inc (working copy)
@@ -110,7 +110,7 @@
$placements = nodeformscols_field_placements($type, $variant);
nodeformcols_update_placements($type, $variant, $placements);
- $regions = nodeformcols_form_regions();
+ $regions = nodeformcols_form_regions($type);
$form['type'] = array(
'#type' => 'value',
@@ -197,7 +197,7 @@
drupal_add_js(drupal_get_path('module', 'nodeformcols') . '/js/nodeformcols.js');
drupal_add_css(drupal_get_path('module', 'nodeformcols') . '/css/nodeformcols.admin.css');
- $regions = nodeformcols_form_regions();
+ $regions = nodeformcols_form_regions($form['type']['#value']);
foreach ($regions as $region => $title) {
if (is_array($form['conf'][$region])) {
uasort($form['conf'][$region], "element_sort");
The main sticking point is how to pass $type into the context for nodeformcols-configuration.tpl.php? That's not something I've done before...
#6
I am very interested in this modification to the node form column module. Is this likely to be included in the next release, and might a new release forthcoming? (Alternately, a patch may suffice for my needs, which I may create using Hugo and Jonathan's code.) Thanks.
#7
subscribing
#8
Subscribing
#9
The missing piece, how to pass $type into the context for nodeformcols-configuration.tpl.php, is to add a preprocess function for the tpl.php. From there, we can get the content type from the fourth argument being passed in.
function template_preprocess_nodeformcols_configuration(&$vars){$type = str_replace('-', '_', arg(3));
$vars['regions'] = nodeformcols_form_regions($type);
}
(The url version of the content type uses hyphens, but the machine readable version uses underscores.)
This also means that the $regions variable should no longer be called from the tpl.php file.
--- a/sites/all/modules/contrib/nodeformcols/nodeformcols-configuration.tpl.php+++ b/sites/all/modules/contrib/nodeformcols/nodeformcols-configuration.tpl.php
@@ -1,12 +1,8 @@
<?php
-// $Id: nodeformcols-configuration.tpl.php,v 1.5 2009/09/21 06:09:54 hugowetterberg Exp $
-
/**
* @file
* Template for the configuration table
*/
-
-$regions = nodeformcols_form_regions();
?>
<table id="fields" class="sticky-enabled">
<thead>
You will also want to be sure to pass the content type to _nodeformscols_default_field_placements() in nodeformscols.module.
function nodeformscols_field_placements($content_type, $variant) {- $default = _nodeformscols_default_field_placements();
+ $default = _nodeformscols_default_field_placements($content_type);
if ($variant != 'default') {
And the should about do it!
#10
I've rolled all of these changes into a single patch. I'm changing the version to 6.x-1.6, since that is what the patch was built against.
I've also included in the patch a nodeformcols.api.php file, to document the various hook functions in the module.
I've also added some basic caching into the nodeformcols_form_regions() and _nodeformscols_default_field_placements() functions, so the hooks don't need to be called multiple times.