#311192: Significant refactoring of the menu system; arguments at various non-overrid... 6.x-2.0-alpha2
authorSam Boyer
Sun, 12 Oct 2008 06:03:11 +0000 (06:03 +0000)
committerSam Boyer
Sun, 12 Oct 2008 06:03:11 +0000 (06:03 +0000)
arguments/nid.inc
arguments/node_add.inc
arguments/node_edit.inc
arguments/term.inc
arguments/uid.inc
arguments/vid.inc
panels_page/panels_page.menu.inc

index ad10d6d..51181a8 100644 (file)
@@ -18,6 +18,8 @@ function panels_nid_panels_arguments() {
     'settings form submit' => 'panels_nid_settings_form_submit',
     'displays' => 'panels_nid_displays',
     'choose display' => 'panels_nid_choose_display',
+    'native path' => 'node/%node',
+    'load function' => 'node',
   );
   return $args;
 }
index ea6535e..7d58200 100644 (file)
@@ -18,6 +18,7 @@ function panels_node_add_panels_arguments() {
     'settings form submit' => 'panels_node_add_settings_form_submit',
     'displays' => 'panels_node_add_displays',
     'choose display' => 'panels_node_add_choose_display',
+    'menu builder' => 'panels_node_add_menu_builder',
   );
   return $args;
 }
@@ -152,3 +153,29 @@ function panels_node_add_displays($conf, $id) {
   return $displays;
 }
 
+function panels_node_add_menu_builder(&$items, $metadata) {
+  // Assume that this is the only argument present, as a use case where that's
+  // not true is simply beyond the pale
+  list($path_prefix, $path_suffix) = explode('%', $metadata->path);
+
+  $types = array_filter($metadata->arg_data['argument_settings']['types']);
+  $types = array_keys(empty($types) ? $metadata->arg_data['argument_settings']['types'] : $types);
+
+  foreach (node_get_types('types', NULL, TRUE) as $type) {
+    if (in_array($type->type, $types)) {
+      $type_url_str = str_replace('_', '-', $type->type);
+      $items[$path_prefix . $type_url_str . $path_suffix] = array(
+        'title' => drupal_ucfirst($type->name),
+        'title callback' => 'check_plain',
+        'page callback' => 'node_add',
+        'page arguments' => array(2),
+        'access callback' => 'node_access',
+        'access arguments' => array('create', $type->type),
+        'description' => $type->description,
+        'file' => 'node.pages.inc',
+      );
+    }
+  }
+  // Indicate that the original path should be scrubbed
+  return TRUE;
+}
index 64040dc..88f2fc3 100644 (file)
@@ -18,6 +18,8 @@ function panels_node_edit_panels_arguments() {
     'settings form submit' => 'panels_node_edit_settings_form_submit',
     'displays' => 'panels_node_edit_displays',
     'choose display' => 'panels_node_edit_choose_display',
+    'native path' => 'node/%node/edit',
+    'load function' => 'node',
   );
   return $args;
 }
index 2afc358..421c83d 100644 (file)
@@ -19,6 +19,7 @@ function panels_term_panels_arguments() {
     'title function' => 'panels_term_title',
     'displays' => 'panels_term_displays',
     'choose display' => 'panels_term_choose_display',
+    'native path' => 'taxonomy/term/%',
   );
   return $args;
 }
@@ -210,4 +211,3 @@ function panels_term_title($context) {
     return $context->page_title;
   }
 }
-
index 9e47a5e..b5b358f 100644 (file)
@@ -18,6 +18,8 @@ function panels_uid_panels_arguments() {
     'settings form submit' => 'panels_uid_settings_form_submit',
     'displays' => 'panels_uid_displays',
     'choose display' => 'panels_uid_choose_display',
+    'native path' => 'user/%user',
+    'load function' => 'user',
   );
   return $args;
 }
index 7be5e17..5068e85 100644 (file)
@@ -18,6 +18,8 @@ function panels_vid_panels_arguments() {
     'settings form submit' => 'panels_vid_settings_form_submit',
     'displays' => 'panels_vid_displays',
     'choose display' => 'panels_vid_choose_display',
+    'menu data' => 'panels_vid_menu_data',
+    'load function' => 'taxonomy_vocabulary',
   );
   return $args;
 }
@@ -121,3 +123,11 @@ function panels_vid_choose_display($conf, $context) {
   return;
 }
 
+function panels_vid_menu_data() {
+  return array(
+    'native path'      => FALSE,
+    'loader'           => 'taxonomy_vocabulary',
+    // FIXME This is a toughie. How do we safely figure out access from here?
+    // 'access arguments' => array('administer taxonomy'),
+  );
+}
index a16bb28..a1bf8e5 100644 (file)
@@ -8,6 +8,9 @@
  * overriding system.
  */
 
+/**
+ * Define and return all the static administrative pages for hook_menu().
+ */
 function panels_page_admin_static_menu_items() {
   $items = array();
   $admin = array(
@@ -155,7 +158,7 @@ function panels_page_create_menu_structure($new_items = NULL) {
  * Workhorse function for hook_menu_alter(); separated out here to reduce code
  * weight.
  *
- * @param $callbacks
+ * @param array $callbacks
  */
 function _panels_page_menu_alter(&$callbacks) {
   $panels_items = panels_page_create_menu_structure();
@@ -164,38 +167,80 @@ function _panels_page_menu_alter(&$callbacks) {
     return;
   }
 
+  // Build up an array with ONLY the items with args on native paths (overrides)
+  $overrides = array_keys(array_filter($panels_items['metadata'], '_panels_page_menu_item_filter'));
+
   $matches = array();
-  while (list($path, $item) = each($callbacks)) {
-    if (strpos($path, '%') === FALSE) {
+  foreach ($panels_items['metadata'] as $raw_path => $metadata) {
+    // Skip static panel_pages.
+    if (!($metadata->load_flags & PANELS_IS_DYNAMIC)) {
       continue;
     }
-    $raw_path = panels_page_get_raw_path($path);
-    if (isset($panels_items['menu items'][$raw_path])) {
-      $panels_items['menu items'][$path] = array_merge($item, $panels_items['menu items'][$raw_path]);
-      $matches[$path] = TRUE;
-      // TODO this is another point that hardcodes one item per path.
-      // Only unset if the raw path is different (e.g. taxonomy isn't)
+    // Ensure that the path var is properly initialized on each iteration.
+    $path = $raw_path;
+
+    // Presence of a native path indicates that there are menu item properties
+    // that need to be inherited.
+    if (isset($metadata->native_path)) {
+      if (in_array($raw_path, $overrides)) {
+        // Use the native path because it will always match the overridden path
+        // exactly (that is, it will always include the load function name).
+        $path = $metadata->native_path;
+        $matches[$path] = TRUE;
+      }
+      else {
+        $map = explode('/', $raw_path);
+        foreach ($map as $i => $arg) {
+          if ($arg === '%') {
+            $map[$i] = '%' . array_shift($metadata->load_functions);
+          }
+        }
+        $path = implode('/', $map);
+      }
+      $panels_items['menu items'][$path] = array_merge($callbacks[$metadata->native_path], $panels_items['menu items'][$raw_path]);
+      $panels_items['metadata'][$path] = $panels_items['metadata'][$raw_path];
+      // Only unset if the original path  is different (e.g. taxonomy isn't)
       if ($raw_path != $path) {
-        unset($panels_items['menu items'][$raw_path]);
+        unset($panels_items['menu items'][$raw_path], $panels_items['metadata'][$raw_path]);
+      }
+    }
+    // Update the load flags to reflect the status of a fallback router. It's
+    // fine that static panel_pages miss this, they never have fallback routers.
+    $metadata->load_flags |= (!empty($matches[$path])) ? PANELS_HAS_FALLBACK_ROUTER : 0;
+    db_query('UPDATE {panels_page} SET load_flags = %d WHERE pid = %d', $metadata->load_flags, $metadata->pid);
+
+    // If a special menu builder function has been defined, fire it. Mostly an
+    // edge case atm, node/add is the only existing argument plugin using this
+    if (isset($metadata->menu_builder)) {
+      $builder_items = array();
+      $func = $metadata->menu_builder;
+      if ($func($builder_items, $metadata)) {
+        unset($panels_items['menu items'][$metadata->path]);
+      }
+      while (list($key,) = each($builder_items)) {
+        $builder_items[$key]['module'] = 'panels_page';
       }
+      $panels_items['menu items'] = array_merge($builder_items, $panels_items['menu items']);
     }
   }
-  // Insert all the overridden routers into our separate table.
+
+  // Insert all overridden routers into our separate router storage table, merge
+  // all the panels menu items into the callback stack, then tuck the menu data
+  // back into the static cache for hook_menu_link_alter() to get at later.
   _panels_page_menu_router_build($callbacks, $matches);
-  // Replace all the overridden routers with our own.
   $callbacks = array_merge($callbacks, $panels_items['menu items']);
+  panels_page_create_menu_structure($panels_items);
+}
 
-  foreach ($panels_items['menu items'] as $path => $item) {
-    $raw_path = panels_page_get_raw_path($path);
-    // Only save a router quickref if the item has metadata
-    if (!empty($panels_items['metadata'][$raw_path])) {
-      $metadata = &$panels_items['metadata'][$raw_path];
-      $metadata->load_flags |= isset($matches[$path]) ? PANELS_HAS_FALLBACK_ROUTER : 0;
-      db_query('UPDATE {panels_page} SET load_flags = %d WHERE pid = %d', $metadata->load_flags, $metadata->pid);
-    }
+function _panels_page_menu_item_filter($metadata) {
+  if (!isset($metadata->native_path)) {
+    return FALSE;
   }
-  // Re-call our helper function and store updated items into the static cache.
-  panels_page_create_menu_structure($panels_items);
+
+  if ($metadata->path == panels_page_get_raw_path($metadata->native_path)) {
+    return TRUE;
+  }
+  return FALSE;
 }
 
 function _panels_page_create_menu_structure() {
@@ -219,6 +264,7 @@ function _panels_page_create_menu_structure() {
 function panels_page_construct_dynamic_menu_link(&$items, $panel_page, $map) {
   $type = _panels_page_menu_type($panel_page);
   $primary_wildcard = array_search('%', $map);
+  // panels_page_construct_menu_item_metadata($items, $panel_page, PANELS_IS_DYNAMIC | $panel_page->load_flags);
   panels_page_construct_menu_item_metadata($items, $panel_page, PANELS_IS_DYNAMIC);
   $page_args = array($panel_page->name, $primary_wildcard);
 
@@ -269,12 +315,31 @@ function panels_page_construct_static_menu_link(&$items, $panel_page, $map) {
 
 function panels_page_construct_menu_item_metadata(&$items, $panel_page, $load_flags = 0) {
   $metadata = new stdClass();
-  $metadata->pid   = $panel_page->pid;
-  $metadata->name  = $panel_page->name;
-  $metadata->type  = _panels_page_menu_type($panel_page);
-  $metadata->path  = $panel_page->path;
+  $metadata->pid        = $panel_page->pid;
+  $metadata->name       = $panel_page->name;
+  $metadata->type       = _panels_page_menu_type($panel_page);
+  $metadata->path       = $panel_page->path;
   $metadata->load_flags = $load_flags;
 
+  if (!empty($panel_page->arguments)) {
+    $metadata->load_functions = array();
+    // @TODO This code assumes that the first argument in the stack is the one
+    // we want to inherit from. This may or may not be a valid assumption.
+    while (list($i, $arg_data) = each($panel_page->arguments)) {
+      if ($i == 0) {
+        $argument = panels_get_argument($arg_data['name']);
+        if (!empty($argument['native path'])) {
+          $metadata->native_path = $argument['native path'];
+        }
+        if ($function = panels_plugin_get_function('arguments', $argument['name'], 'menu builder')) {
+          $metadata->menu_builder = $function;
+          $metadata->arg_data = $arg_data;
+        }
+      }
+      $metadata->load_functions[] = !empty($argument['load function']) ? $argument['load function'] : '';
+    }
+  }
+
   $items['metadata'][$panel_page->path] = $metadata;
 }