Description

Extra Tabs Menu module that allows menu administrators to easily add new tabs to a page or group of pages. This is possible through a configuration form, context using the provided submodule, or implementing hook_extra_tabs_menu() in your own module.

An example use case

A site administrator has three pages that they would like to have visibly related to each other by using the Drupal tabs. This is not something that can easily be done using blocks and views with something like nodequeue, and in a situation where the menu admin may want to add a link to something that's not a node, or an off-site link there's not really any good solution that I'm aware of.

Installation and configuration

  1. Download and enable this module (see documentation)
  2. Navigate to the settings page as an admin (/admin/config/user-interface/extra-tabs).
  3. Add a set of paths where you'd like extra tabs to appear.
  4. Choose the menu parent whose links you'd like to have added as extra tabs on the set of pages you've chosen.
  5. Save the configuration by submitting the form.
  6. If you'd like to configure different menu parents for a different set of paths you can use the additional fields that are added after form submission to add more sets of options.

Extra Tabs Menu Context (submodule)

There's also a submodule included in this project called extra_tabs_menu_context which adds the ability to add menu links to tabs using a context reaction.

Usage instructions for this extra_tabs_menu_context:

  1. Download and enable extra_tabs_menu and extra_tabs_menu_context (see documentation)
  2. Create a new context with whatever conditions you'd like
  3. Add the "Extra Tabs Menu" reaction, and choose the menu parent whose links you'd like to appear as tabs when the conditions are met.

Project Links

Project page:

https://www.drupal.org/sandbox/jiff/2481193

PAReview:

http://pareview.sh/pareview/httpgitdrupalorgsandboxjiff2481193git

Note: There's a single pareview issue that's a false positive. It recommends the use of a lowerCamel formatting for a the options_form method for the context reaction class, but in the parent class options_form is snake_case as well, so we can't extend it using lowerCamel.

Git:

git clone --branch 7.x-1.x http://git.drupal.org/sandbox/jiff/2481193.git extra_tabs_menu
cd extra_tabs_menu

Comments

jlandfried’s picture

Status: Active » Needs review
PA robot’s picture

We are currently quite busy with all the project applications and we prefer projects with a review bonus. Please help reviewing and put yourself on the high priority list, then we will take a look at your project right away :-)

Also, you should get your friends, colleagues or other community members involved to review this application. Let them go through the review checklist and post a comment that sets this issue to "needs work" (they found some problems with the project) or "reviewed & tested by the community" (they found no major flaws).

I'm a robot and this is an automated message from Project Applications Scraper.

ajaynimbolkar’s picture

Manual Review

Individual user account
[Yes: Follows] the guidelines for individual user accounts.
No duplication
[Yes: Does not cause] module duplication and/or fragmentation.
Master Branch
[Yes: Follows] the guidelines for master branch.
Licensing
[Yes: Follows / No: Does not follow] the licensing requirements.
3rd party assets/code
[Yes: Follows ] the guidelines for 3rd party assets/code.
README.txt/README.md
[Yes: Follows] the guidelines for in-project documentation and/or the README Template.
Code long/complex enough for review
[Yes: Follows] the guidelines for project length and complexity.
Secure code
[Yes: Meets the security requirements.]
Coding style & Drupal API usage
[List of identified issues in no particular order. Use (*) and (+) to indicate an issue importance. Replace the text below by the issues themselves:
(*)I have follow the steps as given in redme.txt file and created menu as below
* Tab set 1 test 1 => node/552142
* Tab set 1 test 2 => node/552143
* Tab set 1 test 3 => node/552144
While visting "node/552142" page then other tab such as "test2" and "test3" not visible.
please guide if I did any thing wrong.
(*) drupal_valid_path(), needed dynamic_allowed variable in line no 38, you have provided path but you need to set dynamic_allowed to "TRUE" because if user added path like "test/*/*" then drupal_valid_path() return false for that we need 2nd parameter.
(*) 'title' => $menu_link['link_title'], line no 42 in extra_tabs_menu.module used t() function.
The starred items (*) are fairly big issues and warrant going back to Needs Work. Items marked with a plus sign (+) are important and should be addressed before a stable project release. The rest of the comments in the code walkthrough are recommendations.
If added, please don't remove the security tag, we keep that for statistics and to show examples of security problems.

ayesh’s picture

Hi there,
Thanks for this. Looks like a really handy module. There is a similar module, Tab Tamer, but this module clearly has a different purpose: Add new tab items!

Module looks clear and secure, and it did indeed worked the way I expected.

May I ask why you needed drupal_valid_path() (in line 36) in first place? Isn't it the menu admin form's job to validate the paths?

jlandfried’s picture

StatusFileSize
new43.6 KB

Hi Ajay and Ayesh, thanks both for the reviews.

ajayNimbolkar:

(*)I have follow the steps as given in redme.txt file and created menu as below
* Tab set 1 test 1 => node/552142
* Tab set 1 test 2 => node/552143
* Tab set 1 test 3 => node/552144
While visting "node/552142" page then other tab such as "test2" and "test3" not visible.
please guide if I did any thing wrong.

I'm curious, did you set the tabs up as branches in the menu tree (with "tab set 1 test 2" and "Tab set 1 test 3" nested under "Tab set 1 test 1"? I've attached a screenshot of how the tabs menu links should be ordered.

drupal_valid_path(), needed dynamic_allowed variable in line no 38, you have provided path but you need to set dynamic_allowed to "TRUE" because if user added path like "test/*/*" then drupal_valid_path() return false for that we need 2nd parameter.

It turns out that line is unnecessary, see my response to Ayesh's feedback below :-)

(*) 'title' => $menu_link['link_title'], line no 42 in extra_tabs_menu.module used t() function.

Sorry, I'm not seeing any spots where I'm running menu['link_title'] through t(), and line 42 is actually 'localized_options' => $menu_link['localized_options'], maybe you got the line numbers a bit confused?

Thanks for the review!

Ayesh:

May I ask why you needed drupal_valid_path() (in line 36) in first place? Isn't it the menu admin form's job to validate the paths?

Sure. First of all, it turns out that it was unnecessary, you're correct. I was originally using it because drupal_valid_path() handles validating menu paths as well as determining whether a user has access to the path. I was using it for the access check, not thinking that menu_tree_get_page_data() already filtered out links that the current user does not have access to. I've updated the codebase and removed that check, since it was unnecessary.

Thanks for the review!

ajaynimbolkar’s picture

Hi jiff,

I'm curious, did you set the tabs up as branches in the menu tree (with "tab set 1 test 2" and "Tab set 1 test 3" nested under "Tab set 1 test 1"? I've attached a screenshot of how the tabs menu links should be ordered.

I have set the order of menu as per the screen shot provided by you but also while visiting parent menu it was not showing child menu as "tab" in parent page.

Sorry, I'm not seeing any spots where I'm running menu['link_title'] through t(), and line 42 is actually 'localized_options' => $menu_link['localized_options'], maybe you got the line numbers a bit confused?

Please see below code where you have used 'title' => $menu_link['link_title'],

$data['tabs'][0]['output'][] = array(
'#theme' => 'menu_local_task',
'#link' => array(
'title' => $menu_link['link_title'],
'href' => $menu_link['link_path'],
'localized_options' => $menu_link['localized_options'],
),
);
So please used t function for title its used for translation.

jlandfried’s picture

@ajayNimbolkar:
Thanks for the quick response.

Please see below code where you have used 'title' => $menu_link['link_title'],

$data['tabs'][0]['output'][] = array(
'#theme' => 'menu_local_task',
'#link' => array(
'title' => $menu_link['link_title'],
'href' => $menu_link['link_path'],
'localized_options' => $menu_link['localized_options'],
),
);
So please used t function for title its used for translation.

I think I have to disagree here. The t() function is not meant to have user-entered text run through it, as stated in the section on translating variables in function's documentation. The function theme_menu_local_task takes care of running the link title through check_plain as well (if required), so in my opinion it's fine to use the raw value here.

I have set the order of menu as per the screen shot provided by you but also while visiting parent menu it was not showing child menu as "tab" in parent page.

Would it be possible for you to try to help with debugging this? Or finding the origin of the problem and noting it in this issue? I'd really appreciate it, since it's preventing the module from doing it's sole task, and since it doesn't sound like Ayesh ran into this, and I'm unable to replicate the issue as well.

Thanks!

rgkimball’s picture

Hi jiff,

First of all, I want to say this module is long overdue. There is currently no good solution for site builders to add local tasks, and your module solves just that. This module is functionally straightforward, and what you've started with here is lightweight and very easy to set up. I think the major limitation of the current implementation is that you can only apply a set of links to a specific node/path, rather than a section of the site or a content type (as many use cases will call for). Personally, I would like to see this as a context reaction to enable this type of configuration, but I am interested to hear what other people have to say on that point.

Code Review

I see no major security vulnerabilities introduced by your module, and your code is concise, standards compliant, and readable. The only item that caught my attention was the constant defined at line 7 of your .module, using const instead of define(), per https://www.drupal.org/coding-standards#naming. Although your usage will be the preferred implementation in Drupal 8, it is more typical in D7 to use define() or (preferably) a variable with variable_set() and variable_get(). By using a variable instead, users will be able to configure their own menu to use in place of your default if they're so inclined without having to hack your module.

jlandfried’s picture

Status: Needs review » Needs work

Hi rgkimball, thanks for the review.

I think the major limitation of the current implementation is that you can only apply a set of links to a specific node/path, rather than a section of the site or a content type (as many use cases will call for).

I definitely see your point. This project is the result of a specific use case on a client project where that flexibility wasn't needed, but for this to be useful to the community at large it seems like it's flexibility should be expanded a bit. I've got some ideas for how we can still leverage menus to add these extra tabs, but not be tied to a specific menu and its menu links for controlling visibility.

Personally, I would like to see this as a context reaction to enable this type of configuration, but I am interested to hear what other people have to say on that point.

What probably makes the most sense is for the system that determines whether the tabs get altered or not to be pluggable, so the module can provide a basic configuration form, but can also leverage context reactions or possibly some other tool without having to get too crazy.

The only item that caught my attention was the constant defined at line 7 of your .module, using const instead of define(), per https://www.drupal.org/coding-standards#naming

Noted, it was something that slipped my mind when I wrote this. I don't imagine that I'll be using the constant in the future but if it does exist for some reason I'll switch it.

I'm going to drop this issue down to "needs work", and will be making some adjustments to how the additional tab visibility gets controlled and will bump it back to needs review when those changes are incorporated.

Thanks again for the feedback!

jlandfried’s picture

Issue summary: View changes
jlandfried’s picture

Status: Needs work » Needs review

Hi all, thanks again for reviewing the module earlier. I've taken @rgkimball's feedback and made significant changes to how the module functions. I think the changes make things much more usable and flexible for site administrators and developers.

I've updated the project page, and the project application description with the changes so details can be seen there, but the gist of it is:

  • The extra_tabs_menu module provides a settings form where a user can use block-style path visibility settings to determine which pages a set of tabs will display on, and the user can choose a menu parent whose links they'd like to have displayed on the configured pages
  • A submodule has been added that adds a context reaction that allows an admin to choose a menu parent whose links will appear as tabs if the context conditions are met.
  • A hook is added that allows developers to add their own mechanisms for determining when and a menu parent's links should be added as tabs.

If any of you have some time to check this out again (or new reviewers) I'd really appreciate it!

Thanks!

daria.a’s picture

Issue summary: View changes

Hello jiff!

Automated Review:

FILE: ...iew_temp/extra_tabs_menu_context/plugins/extra_tabs_menu_reaction.inc
---------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
---------------------------------------------------------------------------
14 | ERROR | Public method name
| | "ExtraTabsMenuContextReaction::options_form" is not in
| | lowerCamel format

Manual Review:

Individual user account
Yes, follows the guidelines for individual user accounts.

No duplication
Yes, doesn't cause module duplication and/or fragmentation.

Master Branch
Yes, follows the guidelines for master branch.

Licensing
Yes, follows the licensing requirements.

3rd party assets/code
Yes, follows the guidelines for 3rd party assets/code.

README.txt/README.md
Yes, follows the guidelines for in-project documentation and/or the README Template.

Code long/complex enough for review
Yes, follows the guidelines for project length and complexity.

Coding style & Drupal API usage
Just a recommendation.
1. Move your admin page-related code to admin.inc file from your .module file.
2. It's desirable to display a confirmation message (with drupal_set_message), that module's settings were successfully altered. That confirmation should be displayed right after user have clicked "Save" button.

PA robot’s picture

Status: Needs review » Needs work

Git clone command for the sandbox is missing in the issue summary, please add it.

I'm a robot and this is an automated message from Project Applications Scraper.

jlandfried’s picture

Issue summary: View changes
jlandfried’s picture

Status: Needs work » Needs review

Thanks for the review @daria.a!

FILE: ...iew_temp/extra_tabs_menu_context/plugins/extra_tabs_menu_reaction.inc
---------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
---------------------------------------------------------------------------
14 | ERROR | Public method name
| | "ExtraTabsMenuContextReaction::options_form" is not in
| | lowerCamel format

There's not really anything that we can do about that. Since this is a context reaction extending context_reaction, that method name's already defined for us using snake_case rather than lowerCamel.

1. Move your admin page-related code to admin.inc file from your .module file.

Seems valid to me! The leaner that the .module can be the better. I've moved the admin form related code into an admin.inc file.

2. It's desirable to display a confirmation message (with drupal_set_message), that module's settings were successfully altered. That confirmation should be displayed right after user have clicked "Save" button.

Also totally valid. I've added a simple message saying that "Extra tabs menu configuration has been updated." when the user saves the form.

daria.a’s picture

Status: Needs review » Reviewed & tested by the community

jiff, I udated status.

ashish.verma85’s picture

hi, one this is missing:
hook_install(). It is recommended to always implement. Please check an example here:

jlandfried’s picture

jiff, I udated status.

Thanks daria.a!

hi, one this is missing:
hook_install(). It is recommended to always implement. Please check an example here:

Thanks for the feedback ashish.verma85. I've Implemented hook_install, as well as hook_uninstall since there was a configuration variable that wasn't getting removed.

avpaderno’s picture

Assigned: Unassigned » avpaderno
Status: Reviewed & tested by the community » Fixed

Thank you for your contribution!

I am going to update your account so you can promote this to a full project and also create new projects as either a sandbox or a "full" project.

Here are some recommended readings to help with excellent maintainership:

You can find more contributors chatting on IRC in #drupal-contribute. So, come hang out and stay involved!

Thank you, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.

Thank you to the dedicated reviewer(s) as well.

Status: Fixed » Closed (fixed)

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