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

Hugo Wetterberg’s picture

Assigned:Unassigned» Hugo Wetterberg

That's a great feature request. Will do.

jonathan_hunt’s picture

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.

jonathan_hunt’s picture

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?

Hugo Wetterberg’s picture

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');
  }
}
jonathan_hunt’s picture

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...

Matt-H’s picture

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.

castawaybcn’s picture

subscribing

jvieille’s picture

Subscribing

Matt-H’s picture

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!

Matt-H’s picture

Version:6.x-1.4» 6.x-1.6
Status:Active» Needs review
StatusFileSize
new8.04 KB

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.

davexoxide’s picture

Version:6.x-1.6» 7.x-1.x-dev
StatusFileSize
new5.98 KB

I've applied these changes to D7 version. Here's a patch.

I'm not sure if nodeformcols_preprocess_nodeformcols_configuration is ever being called or even the nodeformcols-configuration.tpl.php. So this patch may still need some work

davexoxide’s picture

StatusFileSize
new5.44 KB

Here's the correct diff without my features module diff at the bottom

TwoD’s picture

Issue summary:View changes
StatusFileSize
new5.51 KB
new5.89 KB

Rerolled for 7.x-1.x and 6.x-1.7 (Only tested the D6 version since that's what I currently use it on.)

Moved the default placements hook invocation so it only overrides defaults and not the actual placements set in the GUI.

Removed the template preprocess hook implementation and made the template read the available regions from $element['nodeformcols_form_regions'] instead. I already had it working this way in a private version of the patch so I just kept it instead of adding the preprocess hook implementation. Minor benefit; no need to clear cache after applying the cache. ;)

Completely remove the $has_elements variable since it is no longer used in the previous patch. Changed the string to '#has_elements' instead of 'has_elements' since Drupal would otherwise interpret that property as a child element.