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

Get incoming links with-in a user macro

Jason Hensler
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.
January 31, 2013

I'm attempting to create a macro to display the incoming link with-in a page. I've been attempting to get the velocity template. I looked at the /pages/viewinfo.vm and found the variable $helper.action.incomingLinksMap.isEmpty() but, it's not rendering from a confluence page in view mode. I am aware of the incoming-links macro from adaptavist but, its not working properly for me either.

6 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

7 votes
Answer accepted
HuseinA
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 2, 2013

I was working with Roswitha in a Support issue for this same question. Thought of sharing the outcome.

(Disclaimer: I am not a developer by trade. So my help and capability here is very limited)

So I took a peek on the source code of Page Info (/pages/viewinfo.action?pageId=), it shows something like this:
atlassian-confluence-4.3.3/confluence/pages/viewinfo.vm:80-119

...
                    #if (!$action.incomingLinksMap.isEmpty() || !$action.trackbackLinks.isEmpty())
                        <div class="basicPanelContainer">
                            <div class="basicPanelTitle">
                                $helper.getText("action.page.incoming.links")
                            </div>
                            <div class="basicPanelBody">
                                <table class="pageInfoTable">
                                    #foreach ($link in $action.incomingLinksMap.asMap().entrySet())
                                        <tr>
                                            <td>
                                                #set ($destSpace = false)
                                                #set ($destSpace = $link.key)

                                                #if ($destSpace)

                                                    <span class="smalltext">$webwork.htmlEncode($destSpace.name) ($link.value.size())</span>
                                                    <br>
                                                    #foreach ($linkedPage in $link.value)
                                                        &nbsp; &nbsp; #contentLink2($linkedPage true false)
                                                        <br>
                                                    #end
                                                #end
                                            </td>
                                        </tr>
                                    #end
                                    #if (!$action.trackbackLinks.isEmpty())
                                     <tr>
                                            <td>
                                              <span class="smalltext">$action.getText("action.page.trackback.links")</span><br>
                                                #foreach ($link in $action.trackbackLinks)
                                                  &nbsp; &nbsp; #contentIcon ($link) <a href="$link.url">$link.title</a>
                                                  <span class="smalltext">$!link.blogName<br>&nbsp; &nbsp; &nbsp; $!generalUtil.shortenString($link.excerpt,200)</span><br>
                                                #end
                                            </td>
                                        </tr>
                                    #end
                               </table>
                            </div>
                        </div>
                    #end
...

 

 

which relates to this bit from Confluence source code:
confluence-core/confluence/src/java/com/atlassian/confluence/pages/actions/PageInfoAction.java:72-96

...
    public Multimap<Space, SpaceContentEntityObject> getIncomingLinksMap()
    {
        if (incomingLinksMap == null)
        {
            Set<OutgoingLink> incomingLinksSet = new HashSet<OutgoingLink>();
            incomingLinksSet.addAll(getIncomingLinks());

            incomingLinksMap = ArrayListMultimap.create();

            for (OutgoingLink outgoingLink : incomingLinksSet)
            {
                Object sourceContent = outgoingLink.getSourceContent();
                if (sourceContent instanceof SpaceContentEntityObject)
                {
                    SpaceContentEntityObject spaceContentEntityObject = (SpaceContentEntityObject) sourceContent;
                    if (!spaceContentEntityObject.isDeleted())
                    {
                        incomingLinksMap.put(spaceContentEntityObject.getSpace(), spaceContentEntityObject);
                    }
                }
            }
        }

        return incomingLinksMap;
    }
...

 

 

From each of List<OutgoingLink>, you can extract a ContentEntityObject out of it through getSourceContent(). Once you get hold of ContentEntityObject, then you can pretty much do/extract any further information you need. For example, you can get the Space information (e.g. SpaceKey), by extending it to its subclass SpaceContentEntityObject. I made a simple user macro that should explain this and do the job you're after too:

## @noparams
#foreach ($bla in $action.getIncomingLinks())
<a href="$bla.getSourceContent().getUrlPath()">$bla.getSourceContent().getTitle()</a>
<br>
#end

 

 

That will generate all the incoming links of the page where the user macro is being used.

Jason Hensler
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 3, 2013

Husein,

That is working perfectly.

Thanks,

Jason

Gaurav Mishra
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.
April 11, 2013

Perfect. Thank You. that works for as well.

Jason Hensler June 19, 2013

I was having issues with deleted pages showing in the links from the above user macro. I added a check to make sure that isdeleted is not true.

## @noparams
#foreach ($bla in $action.getIncomingLinks())
#if(!($bla.getSourceContent().isDeleted()))
[$bla.getSourceContent().getSpaceKey():$bla.getSourceContent().getTitle()]
#end
#end

Patrick Vanhoof
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.
August 6, 2017

Hi,

This works, but lists the pages in a row. Can there be line breaks after each page, and can it be real links to the concerned pages?Incoming links.png

Thanks,

Patrick

6 votes
Jan-Peter Rusch
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.
April 10, 2018

Great solution!

I gave it a small upgrade & tested it with Confluence 6.8.0

## Macro title: incoming-links
#set($incLinks = $action.getIncomingLinks())
#if($incLinks && $incLinks.size() > 0)
<ac:structured-macro ac:macro-id="180b25d1-981f-410d-8fc7-b979b17f8ca2" ac:name="panel" ac:schema-version="1">
<ac:parameter ac:name="title">Links to this page</ac:parameter>
<ac:rich-text-body>
<p><ul>
#foreach ($incLink in $incLinks)
#if(!($incLink.getSourceContent().isDeleted()))
<li><a href="$generalUtil.htmlEncode("${req.contextPath}$incLink.getSourceContent().getUrlPath()")">$incLink.getSourceContent().getTitle()</a><a href="$generalUtil.htmlEncode("${req.contextPath}$incLink.getSourceContent().getSpace().getBlogTabUrlPath()")"> ($incLink.getSourceContent().getSpace().getName())</a></li>
#end
#end
</ul></p>
</ac:rich-text-body>
</ac:structured-macro>
#end

My solution embeds a unsorted list in a panel macro & only shows the macro output, if incoming links are available. The incoming links are clickable, the space name is shown & linked to a page overview page which is a pretty unknown feature in Confluence.

Nils Bluemer January 10, 2019

Great solution, Thanks. However, one additional line in the header was needed to make the macro visible in our installations:

## @noparams

Like Luisa Falk likes this
Libor Šmíd March 15, 2019

Hi,

thank you too, it is great solution and very usefull for me. I have one questins. Is there a way how can I choose the space, where some links come from? For example: I have a space AAA, XXX and ZZZ. In ZZZ space is a page linked to by a link from AAA and XXX, but I want to see links only from AAA space.

How can I do this?

Thank you in advance.

Libor Šmíd March 20, 2019

Hi,

we solved our problem with selected space. So, if you want to show incoming links from specific space:

## Macro title: incoming links - selected space
## @param Space:title=Space|type=spacekey
#set($incLinks = $action.getIncomingLinks())
#if($incLinks && $incLinks.size() > 0)
<ac:structured-macro ac:macro-id="180b25d1-981f-410d-8fc7-b979b17f8ca2" ac:name="panel" ac:schema-version="1">
<ac:parameter ac:name="title">Links to this page from $paramSpace space</ac:parameter>
<ac:rich-text-body>
<p><ul>
#foreach ($incLink in $incLinks)
#if(!($incLink.getSourceContent().isDeleted()) && $incLink.getSourceContent().getSpace().getKey()==$paramSpace)
<li><a href="$generalUtil.htmlEncode("${req.contextPath}$incLink.getSourceContent().getUrlPath()")">$incLink.getSourceContent().getTitle()</a><a href="$generalUtil.htmlEncode("${req.contextPath}$incLink.getSourceContent().getSpace().getBlogTabUrlPath()")"> ($incLink.getSourceContent().getSpace().getName())</a></li>
#end
#end
</ul></p>
</ac:rich-text-body>
</ac:structured-macro>
#end

 tested it with Confluence 6.11.2

Like # people like this
0 votes
Peter Hochstrasser January 31, 2019

Great solution!

If you have confluence with a context, e.g. not confluence.yourdomain.tld, but confluence.yourdomain.tld/confluence, then you need to add this context: prepend this to the relative url:

$req.contextPath

 

The original macro works well with setting macro body processing = unrendered.

0 votes
Andrew Pidcock September 8, 2016

The macro correctly finds the incoming links, but the results are not a link.. Is there any way to have them be active links that a user could click?

I tried all four different output ooptions

0 votes
Tom Birch Hansen March 9, 2014

Do you know if the above will work for attachments? I'd like to be able to see incomming links to the attachments of a page.

0 votes
Roswitha Gartner January 31, 2013

I have a similar problem, I could get access to the incoming links ($action.getIncomingLinks()), but received OutgoingLinks as result, and so I couldn t accees the correct data.

Jason Hensler
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.
January 31, 2013

I ran into that as well. The api doc's show that it returns "List <OutgoingLink>" even in the lastest docs (http://docs.atlassian.com/atlassian-confluence/latest/com/atlassian/confluence/pages/actions/AbstractPageAction.html), perhaps this is a bug then.

Roswitha Gartner January 31, 2013

Yes, I found that in the API too,

but obviously Confluence itself uses the getIncomingLinks() for the info page, so I don t understand why it works in the info page.

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