Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

How to ignore a user macro call found on an included page?

Fred Bunting February 26, 2015

I have a velocity User Macro that displays a navbar on a page.  A page author can add the macro to a page, and use its parameters to alter the navbar contents.

The only problem I have is when the page contains an include to another page that also has the navbar macro.

I would like the User Macro to do nothing if it is on an included page. 

Is there a way to detect, from inside the macro, whether it is being called on an included page, rather than the main page being rendered?

An alternative approach I tried is to edit the Page Layout decorator to find the macro (if it exists) on the main page source, and then parse its parameters, and then call the macro with a special "doit" parameter to actually build the navbar.  (The macro would do nothing if the "doit" parameter is absent.)  However, I also found no elegant way to parse the body, alter the macro call, and then call it.  Any ideas?

4 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

0 votes
Answer accepted
Fred Bunting March 5, 2015

I found a solution that appears to work! smile

Inside the macro, you can get the current HttpServletRequest object $req, that has access to the URI for the page being rendered.  (See Confluence Objects Accessible From Velocity.) If the macro is on an included page, then the page title of the $req and $content objects will be different.

The call $req.getParameter("title") gets the title found in the URL being rendered. And $content.getDisplayTitle() gets the title of the content page.  If they are different, then the content is an include.

The only tricky part is that if the the title of the page contains non-displayable character (like ampersands), then $req.getParameter("title") returns nothing. So in that case you need to compare pageIDs instead ... using $req.getParameter("pageID") compared to $content.getIdAsString().

So this appears to work:

#set ($doit = true)
#set ($TitleOfPageBeingRendered = $req.getParameter("title"))
#if ($TitleOfPageBeingRendered) ## We found title in URL
    #if ($TitleOfPageBeingRendered != $content.getDisplayTitle())
        #set ($doit = false)    ## Titles didn't match.
    #end
#else   ## If we can't find title in URL, then compare pageIDs.
    #set ($IdOfPageBeingRendered = $req.getParameter("pageId"))
    #if (!$IdOfPageBeingRendered)
        #set ($doit = false)	## Couldn't find title or pageID.
    #elseif ($IdOfPageBeingRendered != $content.getIdAsString())
        #set ($doit = false)    ## pageIDs didn't match.
    #end
#end
#if ($doit)     ## I.e., this is not an 'include'.
    ## Rest of macro code goes here.
#end

If anybody sees any gotchas with this, please let me know.  But it appears to work.

0 votes
Stephen Deutsch
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 5, 2015

Hi Fred,

A bit late in replying, but I did figure out a way to do this, although it's really hacky.

You can access the HttpServletResponse item in velocity (although it's not recommended) as $res.

If you add some sort of HTTP header at the end of your user macro, like $res.addHeader("NAVBAR","") and then add a check at the beginning of your user macro, like #if ( !$res.containsHeader("NAVBAR") ), then you can ensure that your user macro will only be run once on the page.

Fred Bunting March 5, 2015

Thanks Stephen! I ended up finding a solution before I saw yours, and came here to post it when I saw your suggestion. My solution is similar to yours. The HttpServletResponse item is indeed accessible in the $req object (not $res). You don't need to add anything to the page ... just compare the pageTitle (or pageID) in the $req object, to that in the $content object. They will be different on an included page. I have written this up below.

Fred Bunting March 5, 2015

Correction: $req is the HttpServletRequest object, not the HttpServletResponse object.

0 votes
Volodymyr Krupach
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 26, 2015

I guess that by default velocity variables are global. Not very elegant but working approach could be to set some global variable inside of your macro (something like "rendered") and then check it in the same macro and do nothing when it's set.

Fred Bunting February 27, 2015

Thanks Volodymyr ... I tried that, and confirmed that velocity variables are _not_ global in that sense. I.e., one cannot set a variable inside of a User Macro that then can be checked in a later call to the macro.

0 votes
Alejandro Conde Carrillo
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 26, 2015

You could use the excerpt include macro to include the page and leave the macro out of the excerpt in the included page.

Fred Bunting February 27, 2015

Interesting idea ... but then the author of the included page would have to remember to wrap all of the page in an *excerpt* macro, except for the navbar User Macro. Not something we can ask authors to remember (and it would prevent them from using the *excerpt* macro for other purposes).

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

TAGS
AUG Leaders

Atlassian Community Events