diff -urN composite-6.x-1.0-beta7/composite.module composite/composite.module --- composite-6.x-1.0-beta7/composite.module 2009-01-15 11:41:13.000000000 +0900 +++ composite/composite.module 2009-08-11 14:04:45.000000000 +0800 @@ -122,9 +122,20 @@ static $layouts_select = array(); if (!$layouts) { - // Would like to make layouts pluggable, but doesn't quite work - // because of inability to specify template files from other modules. - $layouts = module_invoke_all('composite_layouts'); + + // Retrieve layout definitions. We can't do module_invoke_all() because we need to fill in ['module'] + foreach (module_implements('composite_layouts') as $module) { + $data = module_invoke($module, 'composite_layouts'); + + // Poke in module if not defined + foreach ($data as $key => $v) { + if (!isset($data[$key]['module'])) { + $data[$key]['module'] = $module; + } + } + + $layouts = array_merge_recursive($layouts, $data); + } // Do some defaults and path processing // Construct a select list for convenience @@ -133,8 +144,9 @@ if (!$layouts[$key]['template']) { $layouts[$key]['template'] = 'composite-layout-' . $key_dashed; } + if (!$layouts[$key]['path']) { - $layouts[$key]['path'] = drupal_get_path('module', 'composite') . '/theme'; + $layouts[$key]['path'] = drupal_get_path('module', $layouts[$key]['module']); } $css = $layouts[$key]['css'] ? $layouts[$key]['css'] : 'composite-layout-' . $key_dashed . '.css'; @@ -447,7 +459,30 @@ foreach ($node->composite_content as $zone => $zone_item) { $node->composite_content[$zone] = drupal_render($zone_item); } - $node->body = theme('composite_content', $layout, $node->composite_content); + + // Add this layout's css, if any + if ($layout['css']) { + drupal_add_css($layout['css']); + } + + // Call the appropriate theme('composite_layout...', ...) function. + // However, because the number of arguments depends on the number + // of zones in the layout layout, we have to use call_user_func_array + + // Add in the theme hook name and the first two arguments + $args = array( + 'composite_layout_' . $layout['key'], // theme hook + $layout, // layout + $node->composite_content // composite_content + ); + + // Now add an argument for the contents of each zone + foreach ($layout['zones'] as $zone => $unused) { + $args[] = $node->composite_content[$zone]; + } + + // And call it + $node->body = call_user_func_array('theme', $args); } } break; @@ -673,7 +708,7 @@ $element[$key]['#suffix'] = ''; if ($layouts[$key]['icon']) { - $element[$key]['#prefix'] .= theme('composite_layout_icon', $layouts[$key]['icon']); + $element[$key]['#prefix'] .= theme('composite_layout_icon', $layouts[$key]['icon'], $layouts[$key]); } } else if (is_numeric($key)) { @@ -704,12 +739,12 @@ * Implementation of hook_theme() */ function composite_theme() { - return array( + $data = array( 'composite_layout_radios' => array( 'arguments' => array('element' => NULL), ), 'composite_layout_icon' => array( - 'arguments' => array('file' => NULL), + 'arguments' => array('file' => NULL, 'layout' => NULL), ), 'composite_zones_form' => array( 'template' => 'composite-zones-form', @@ -719,23 +754,41 @@ 'composite_zones_preview' => array( 'arguments' => array('node' => NULL), ), - 'composite_content' => array( - 'template' => 'composite-content', - 'path' => drupal_get_path('module', 'composite') . '/theme', - 'arguments' => array('layout' => array(), 'composite_content' => array()), - ), 'composite_node_title' => array( 'arguments' => array('title' => ''), ), ); + + // Add in theme hooks on behalf of each layout + $layouts = composite_get_layouts(); + foreach ($layouts as $key => $layout) { + $hook = 'composite_layout_' . $key; + $data[$hook] = array( + 'template' => $layout['template'], + 'path' => $layout['path'], + 'arguments' => array('layout' => array(), 'composite_content' => array()), + ); + + // Append a layout's zones to 'arguments'. We do this so we can inject a zone's contents into $variables of the callee + foreach ($layout['zones'] as $zone => $unused) { + $data[$hook]['arguments'][$zone] = ''; + } + + // Optional 'file' if specified by layout + if (isset($layout['file'])) { + $data[$hook]['file'] = $layout['file']; + } + } + + return $data; } function theme_composite_layout_radios($element) { return theme('radios', $element); } -function theme_composite_layout_icon($file) { - return ''; +function theme_composite_layout_icon($file, $layout) { + return ''; } function theme_composite_zones_preview($node) { @@ -745,34 +798,6 @@ } } -function template_preprocess_composite_content(&$variables) { - $layout = $variables['layout']; - $composite_content = $variables['composite_content']; - $key = strtr($layout['key'], '_', '-'); - - // Always include the default template - $variables['template_files'][] = 'composite-content'; - $variables['template_files'][] = $layout['template']; - - if ($layout['css']) { - drupal_add_css($layout['css']); - } - - // Extract out composite_content into separate variables - $variables['content'] = $composite_content['content']; - foreach ($layout['zones'] as $zone => $unused) { - $variables[$zone] = $composite_content[$zone]; - } - - // Call a preprocess callback if defined - if (isset($layout['preprocess callback'])) { - $function = $layout['preprocess callback']; - if (function_exists($function)) { - $function($variables); - } - } -} - function theme_composite_node_title($title) { return '