Clear all cached pages with menus associated with a node on insert/update/delete

chadd - October 22, 2009 - 14:05
Project:Boost
Version:6.x-1.x-dev
Component:Caching logic
Category:feature request
Priority:normal
Assigned:Unassigned
Status:closed
Description

just wanted to throw this out there as an idea for future releases.
don't know if it is in the 6.x roadmap or not...

#1

mikeytown2 - October 22, 2009 - 16:49

Menu's are sorta like blocks, they are on every page, so your best bet is to clear the entire cache. What your asking can be done programmatically though... this is how I see it working. Find all nodes in a menu, when a node in that menu is changed or a new item is added to the menu, flush all nodes in the menu.

How do you see this working? Flush where menu is displayed (hard problem to do correctly) or Flush nodes inside menu (not as hard to do).

#2

chadd - October 22, 2009 - 18:55

flushing the entire menu would basically be flushing our entire site, so that wouldn't be any more helpful than the current clear cache.

i would want it to find what parent item the changed node has, and then flush all the pages that are under that parent.
the farther "down the line" the edited node is, the fewer other nodes would be flushed along with it.

and as an added fun bonus, just to make it a little more complex, it would only flush it's 'sibling' pages, if the menu, title or alias was edited.
that would prevent flushing other pages when all that was edited was body content or some other field that had no impact on the menu or url...

#3

mikeytown2 - October 22, 2009 - 19:04

Detecting that only the title, alias or menu has changed is a problem I don't want to solve.

Can you describe this feature request in more detail? Diagrams help.

Menu Tree
-Top
  -Middle
   -Bottom
    -Deep
     -Very Deep
  -Middle
   -Bottom
    -Deep
    -Deep
    -Deep
     -Very Deep
   -Bottom
   -Bottom
-Top

#4

chadd - October 23, 2009 - 18:31

based upon the below chart ( i added numbers to keep things straight):

example 1: if you update 'deep 1' then you would have to flush it's siblings, deep 2, deep 3, and it's children, very deep 1, and it's parent, bottom 1
example 2: if you update very deep 2, only deep 4 would be flushed
example 3: if you update bottom 2, flush the following: (parent:) middle 2, (siblings:) bottom 3, bottom 4, (children:) Deep 2, Deep 3, Deep4, Very Deep 2

Menu Tree
-Top 1
  -Middle 1
   -Bottom 1
    -Deep 1
     -Very Deep 1
  -Middle 2
   -Bottom 2
    -Deep 2
    -Deep 3
    -Deep4
     -Very Deep 2
   -Bottom 3
   -Bottom 4
-Top 2

basically, everytime you edit a page, you'd flush it's parent nodes, children nodes, and sibling nodes. (cool would be the option to choose which of these 3 to flush, for example, i only want to flush sibling and children, or only parents, etc)

having it flush *only* after menu specific changes (title, menu, alias) would be awesome, but i know that would be a huge challenge.

#5

mikeytown2 - October 23, 2009 - 21:38

example 2 Wouldn't you also flush Very Deep 1?
example 3 Bottom 1?

Help me understand why I need to flush sibling nodes. I get flushing the parent and all child, but why the siblings in another tree like example 1?

#6

chadd - October 26, 2009 - 13:58

no, those aren't siblings to the edited node because they don't have the same parent node, i would call them "cousin's"
i guess it would help if i define siblings: pages at the same level and with the same parent menu item would be "siblings"
pages at the same level but with different menu parent items i'm going to call "cousins"

i think you would have to flush siblings because they share the same "displayed menu"
for example (from above):
if you added a page called "bottom 5" and gave it the parent menu of "middle 2" then that "bottom 5" page menu item should display in the menu on the "bottom 2, 3 & 4"

#7

mikeytown2 - October 27, 2009 - 05:27
Version:6.x-1.13» 6.x-1.x-dev

ok cool, I'll add this to the roadmap. I understand the expected results now.

#8

mikeytown2 - October 28, 2009 - 11:07

Drupal menu system (Drupal 6.x)

Code to load any nodes menu items

<?php
$nid
= 12;
$node = node_load($nid);
menu_nodeapi($node, 'prepare');
echo
print_r($node, TRUE);
?>

This is the start of the rabbit trail for figuring out the parent, siblings and all children of a node in the menu system.
http://api.drupal.org/api/function/menu_secondary_links/6
http://api.drupal.org/api/function/menu_overview_form/6
http://api.drupal.org/api/function/menu_tree_all_data/6 <- Looks like a winner...

#9

mikeytown2 - October 28, 2009 - 12:18

Test case is node/12

<?php
require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

$nid = 12;
$node = node_load($nid);
menu_nodeapi($node, 'prepare');
$output = $node->menu['menu_name'];
$menu = menu_tree_all_data($output);

echo
"\n\n";
$out = build_menu_structure($menu);
echo
print_r($out, TRUE);

function
build_menu_structure($menu) {
  foreach (
$menu as $item) {
    if (!empty(
$item['below'])) {
     
$str[$item['link']['link_path']] = build_menu_structure($item['below']);
    }
    else {
     
$str[$item['link']['link_path']] = '';
    }
  }
  return
$str;
}
?>

Output

Array
(
    [node/3] => Array
        (
            [node/10] => Array
                (
                    [node/21] =>
                    [node/12] => Array
                        (
                            [node/13] => Array
                                (
                                    [node/14] => Array
                                        (
                                            [node/15] => Array
                                                (
                                                    [node/16] => Array
                                                        (
                                                            [node/17] => Array
                                                                (
                                                                    [node/18] =>
                                                                    [node/19] =>
                                                                )

                                                        )

                                                )

                                        )

                                )

                        )

                    [node/20] =>
                )

            [node/4] =>
            [node/8] =>
            [node/9] =>
            [node/11] =>
        )

    [node/1] =>
    [node/2] =>
    [node/7] =>
)

With this I need to expire
Self: node/12
Parent: node/10
Siblings: node/21, node/20
Children: node/13, node/14, node/15, node/16, node/17, node/18, node/19

<?php
require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

$nid = 12;
$node = node_load($nid);
menu_nodeapi($node, 'prepare');
$output = $node->menu['menu_name'];
$menu = menu_tree_all_data($output);

echo
"\n\n";
$out = build_menu_structure($menu, 'node/12');
//print_r($out);
$GLOBALS['_test'] = array_unique($GLOBALS['_test']);
sort($GLOBALS['_test']);
print_r($GLOBALS['_test']);


function
build_menu_structure($menu, $needle, $found = FALSE) {
 
$GLOBALS['_test_found'] = FALSE;
  foreach (
$menu as $item) {
    if (
$item['link']['link_path'] == $needle || $found) {
     
$GLOBALS['_test'][] = $item['link']['link_path'];
     
$found = TRUE;
    }
  }
  foreach (
$menu as $item) {
    if (
$item['link']['link_path'] == $needle || $found) {
     
$GLOBALS['_test'][] = $item['link']['link_path'];
     
$found = TRUE;
    }
    if (!empty(
$item['below'])) {
     
$str[$item['link']['link_path']] = build_menu_structure($item['below'], $needle, $found);
      if (
$GLOBALS['_test_found']) {
       
$GLOBALS['_test'][] = $item['link']['link_path'];
      }
    }
    else {
     
$str[$item['link']['link_path']] = '';
    }
  }
 
$str = array_unique($str);
 
$GLOBALS['_test_found'] = $found;
  return
$str;
}
?>

Outputs what I need

Array
(
    [0] => node/10
    [1] => node/12
    [2] => node/13
    [3] => node/14
    [4] => node/15
    [5] => node/16
    [6] => node/17
    [7] => node/18
    [8] => node/19
    [9] => node/20
    [10] => node/21
)

#10

mikeytown2 - October 29, 2009 - 10:41

Make this a radio option. Your desired effect or clear all items in the menu if using something like DHTML Menu.

#11

mikeytown2 - November 1, 2009 - 10:19
Status:active» needs review

I got Parent, Sibling, Children done. Well At least I think I did, I need some sleep. I should also Place these into a relationship fieldset or something like that.

AttachmentSize
boost-611700.patch 9.47 KB

#12

mikeytown2 - November 2, 2009 - 10:52

This is still ugly code, no more global variables though... it works too!

AttachmentSize
boost-611700.patch 8.71 KB

#13

mikeytown2 - November 2, 2009 - 10:55
Status:needs review» fixed

committed

#14

System Message - November 16, 2009 - 11:00
Status:fixed» closed

Automatically closed -- issue fixed for 2 weeks with no activity.

 
 

Drupal is a registered trademark of Dries Buytaert.