I'm a Drupal newbie and I'm having difficulty overriding the behavior of menu items for "my blog", "my guestbook", "my inbox", "my account". I'd like to move these menu items to a submenu using NiceMenus.

"my blog" and "my account" are both locked on the menus module, and "my guestbook" and "my inbox" don't even show up. In the case of "my account", I discovered that if I create a new menu item pointing to the relative URL /user, then this causes "my account" to move a submenu of the newly created menu item, which I can deal with, but I still can't edit "my account" (e.g. to give it a mouse-hover description). Somewhat similarly, if I set a menu item to point to the same /privatemsg relative URL as "my inbox", then the the original "my inbox" menu item disappears from the Navigation menu, but the new menu item won't show the number of new messages. I thought of just creating new menu items to replace the "my blog" and "my guestbook" menu items, but I can't figure out how to specify a path for the menu item that is dependent upon the logged-in user ID.

I'm also having problems with the "create content" menu item, but it is more of annoyance issue. I don't allow anonymous users to create new content on the site I'm developing. With the default settings for "create content", the menu item itself never shows up as an option without a logged-in user. If I change the settings for the "create content" menu item in any way (move it to a different menu, change the title, change the weight), it always shows up on the menu, even if no one is logged in.

Any help would be greatly appreciated...

G^2

Comments

gsquared’s picture

This one must have been too easy for anyone to respond?!?!?! ;-)

No takers?

raspberryman’s picture

Hi gsquared,

In response to 'my account' and 'my blog' (I don't use or know about guestbook and inbox)

PHP code is the only way to create a path with the user's ID attached to it. So there are two ways I see doing this.

  1. Modify user.module and blog.module (I think this is best)
    This way, you are using Drupal's menu system, and don't have to write any code.

    The goal is to change the menu type of these menu items. The caveat is that you need to change the menu type of both the path you want to edit, AND it's parent.

    For 'my account', you'll need to change the menu type of both the /user/###, and it's parent /user/. For 'my blog', you will only need to change /blog/###/, because the parent /blog/ is already the right menu type.

    Steps:

    • In the hook_menu() for these modules, find the items in question ('my account' and 'my blog').
    • Change the menu type from MENU_DYNAMIC_ITEM to MENU_NORMAL_ITEM.
    • Remember for 'my account', you'll also need to change the menu type for the parent: /user/ (it is set as MENU_CALLBACK by default, and needs to be changed to MENU_SUGGESTED_ITEM). See my example below.
    • Note: using MENU_NORMAL_ITEM and MENU_SUGGESTED_ITEM is the difference between a default 'enabed' or default 'disabled' on your menu admin page, that's pretty much it.

    All done! Now these menu items should be modifyable in /admin/menu/.

    A big plus is that the /admin/menu/ page should now offer you a "RESET" option for these particular menu items, in case you ever make any mistakes tweaking these items.

    Example:
    Change these two items in the hook_menu() of user.module from this:
    $items[] = array('path' => 'user', 'title' => t('user account'),
    'callback' => 'user_login', 'access' => TRUE, 'type' => MENU_CALLBACK);
    
    $items[] = array('path' => 'user/'. $user->uid, 'title' => t('my account'),
    'callback' => 'user_view', 'callback arguments' => array(arg(1)), 'access' => TRUE,
    'type' => MENU_DYNAMIC_ITEM);
    

    To this:

    $items[] = array('path' => 'user', 'title' => t('user account'),
    'callback' => 'user_login', 'access' => TRUE, 'type' => MENU_SUGGESTED_ITEM);
    
    $items[] = array('path' => 'user/'. $user->uid, 'title' => t('my account'),
    'callback' => 'user_view', 'callback arguments' => array(arg(1)), 'access' => TRUE,
    'type' => MENU_NORMAL_ITEM);
    


  2. Code the menu in a custom block
    This options requires a very small and easy bit of code. See instructions at: Moving locked Navigation menu items to your custom block

Both are valid options.

As to why the developers made 'my account' and 'my blog' as locked menu items - I have no idea :)

I am unable to reproduce the issue with 'create content' that you are experiencing. What type of content is available when this menu appears for anonymous users? Usually this menu only appears when it has child menu items (create page, create blog entry, etc).

In any case - please reply and let us know if you fixed your issue, or with more details so we can keep debugging. Good luck, gsquared!

gsquared’s picture

Evo,

First let me thank you for your detailed response... Having been on the other side of the table, I know that it takes a lot of time to respond in a detailed fashion as you did, and I am very appreciative of the time you took in your response.

I had not found the Moving locked Navigation menu items instructions in my prior search before posting, but after reading both your post and the other thread, I immediately liked your solution best and set off in that direction. While I don't have a clue as to why I was making the changes you referenced ;-) your instructions were none-the-less very clear and I had no problems making them. After making the changes, I was able indeed able to modify their settings in /admin/menu, and as you noted, after making the changes it also gave me a "reset" option. I was able to move both menu options to the NiceMenus cascading menu, etc, just as I wanted.

Or so I thought. While the changes worked for the administration account, no other user accounts were affected, and their menu "my account" and "my blog" menu options operated as before. On closer inspection, I noted that when I edit the menu item for "my blog", for instance, that the path that is specified in the "edit menu item" page is "blog/1", and not some generic specification of "blog/$user->uid"; similarly, editing "my account" was editing path "user/1".

In regards to the issue with "create content"... Using the default settings for the "create content" menu item, the menu item behaves as expected and only appears when there are child menu items as you noted. On the site I'm trying to build, since I have only allowed anonymous users the ability to add comments, the default "create content" menu never shows up for an anonymous user. If I make any changes, however, to the menu item (e.g. simply changing the title to "Create Content" instead of "create content"), then the modified menu item displays for anonymous users. When the anonymous user then selects the menu item, a page is displayed that simply says "You are not allowed to create content."

Thanks again for your assistance,

G^2

raspberryman’s picture

Right!! I learn something new everyday! The steps in option #1 above will not work.

I'd reset hook_menu() to its original values. 'user/#' (my account) and 'blog/#' (my blog) should be both of type MENU_DYNAMIC_ITEM. 'user' (user account) should be of type MENU_CALLBACK.

What I learned: We can't have /user/# or /blog/# to be customizable menu items, because customized items are saved as-is in the database. But we don't want user/# and blog/# to be saved, because the # dynamically changes based on the user.

Your only option to having a menu item visible in your menu tree AND not save to a database is MENU_DYNAMIC_ITEM. Recall this is the default type for both /user/# and /blog/#.

raspberryman’s picture

I learned another way to achieve this goal, and it is even easier!

Two ways to edit menu items that are 'locked' (title, description, parent, etc) - using Drupal's hook_menu() or custom code in a block:

  1. Use Drupal's hook_menu() (I think this is best)
    This way, you are using Drupal's menu system, and don't have to write any code.

    In the the documentation for hook_menu(), you see many options to set for a menu item. But you'll notice this list is missing the 'parent' and 'description' options; which are options in administer menu's page (/admin/menu/item/edit/).

    But they are actually present in hook_menu(). To set a parent, you need to add the menu ID of the parent to an attribute called 'pid' the hook_menu() menu item, using the same syntax as the other menu attributes (path, title, weight, access, etc). Description is simply the 'description' attribute.

    STEPS:

    • Find the menu ID of the item you wish to be parent.
      Easiest way is to edit the menu item on /admin/menu/ page. In the URL, the number after /admin/menu/item/edit/ is your menu ID number. Alternatively, you could just look in the 'mid' column in the 'menu' table in your database.
    • Add pid => menu id number to the menu item you wish to change. Also change the title, if you wish, and add 'description'.



    EXAMPLE:
    I have a menu item named 'Personal'. I want to add 'my account' and 'my blog' as children to that menu item. I also want to rename these to 'my data' and 'my journal', and add descriptions for each (note that descriptions end up being the mouseover tips on links)
    1. I go to /admin/menu/, and edit the menu item 'Personal'. I see in the URL that this is menu item 50 (the actual number is at the end of your url /admin/menu/item/edit/#here#)
    2. I change the hook_menu() in user.module and blog.module to reflect the title/description changes, and the parent changes. I change from this:
      // user.module hook_menu()
      $items[] = array('path' => 'user/'. $user->uid, 'title' => t('my account'),
      'callback' => 'user_view', 'callback arguments' => array(arg(1)), 'access' => TRUE,
      'type' => MENU_DYNAMIC_ITEM);
      
      // blog.module hook_menu()
      $items[] = array('path' => 'blog/'. $user->uid, 'title' => t('my blog'),
      'access' => user_access('edit own blog'),
      'type' => MENU_DYNAMIC_ITEM);
      

      to this:

      // user.module hook_menu()
      $items[] = array('path' => 'user/'. $user->uid, 'title' => t('my data'),
      'callback' => 'user_view', 'callback arguments' => array(arg(1)), 'access' => TRUE,
      'description' => t('edit my data'),
      'pid' => 50, 
      'type' => MENU_DYNAMIC_ITEM);
      
      // blog.module hook_menu()
      $items[] = array('path' => 'blog/'. $user->uid, 'title' => t('my journal'),
      'access' => user_access('edit own blog'),
      'description' => t('view my journal'),
      'pid' => 50, 
      'type' => MENU_DYNAMIC_ITEM);
      


  2. Code the menu in a custom block
    This options requires a very small and easy bit of code. See instructions at: Moving locked Navigation menu items to your custom block

Please reply and let us know how things work out! Good luck, gsquared!

gsquared’s picture

Evo,

Thanks again! Your tweak worked like a charm this time. Using this approach I was able to modify not only "my account" and "my blog", but also "my guestbook" and "my inbox" like I wanted to. I have to admit that I was initially stumped... I started off changing "my blog" and after making the specified changes everything remained the same. After double-checking the changes, I noticed that the "my blog" entry on /admin/menu was still unlocked and still provided a "reset" option. I finally realized that although I had changed the code back to the original version, THEN added the new changes, the original modified menu item had been saved directly in the database and was overriding everything. Resetting the item cleared everything to the "new" original state (of the modified code), and from that point on everything worked like a charm...

The only downside to all of this is that every time I upgrade Drupal core, I'll have to reapply the hacks but under the circumstances that would appear unavoidable...

Thanks again evo for your assistance,

G^2

gsquared’s picture

In between evo's original response to my query and his final solution, I found a 3rd, albeit less attractive (at least for me), solution. To close things out, I'll post it here for anyone interested. The 3rd approach was to create a special page that uses php code to access the user ID and provide the desired data. For "my blog", I created a new menu item "My Blog" hooked into my NiceMenu in the desired spot, and set the path for that menu item to /my_blog, which was the path alias for a page with the following code:

<?php
global $user;
if ($user->uid == 0) {
   print "You must <a href=\"/user\">log in</a> to view/edit your blog!"; //Handle the case of an anonymous user
}
else {
   $_GET['q'] = drupal_get_normal_path("blog/" . $user->uid);  //Force the path to the desired location blog/UID
   print menu_execute_active_handler();                        // Drupal function responsible for printing the contents of the path after the q=
}
?>

A similar page was created for "my guestbook", but instead of the $_GET['q'] assignment and menu_execute_active_handler(), I was able to use the guestbook module's own function for returning the guestbook page guestbook_page($user->uid).

The downside of this approach for me was that these menus show up for an anonymous user, and I don't allow anonymous users to create content except for comments; under the original core / evo's mods, these menu items will not appear for the anonymous user (assuming the proper access controls have been set).

G^2

tadashi-1’s picture

Hey, thanks for all the useful info.

However I still don't understand how I can get rid of the "my guestbook" menu item, which is all I want to do right now.

Can anyone walk me through it?!

Cheers!

Coeus’s picture

This is an old thread, but I have similar problems.

The default setting of the Guestbook menu items is to show "Guestbooks" with a sub-item called "my guestbook (new comments)".

I want to disable/remove the link to "guestbook", so that only the links to individual guestbooks show up.
Of course this is easy to achieve with 'me' aliases, but with that, the (2) with new guestbook entries will not show up.

Hope you understand and that someone can help.