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

Next challenges

Recent achievements

  • Global
  • Personal

Recognition

  • Give kudos
  • Received
  • Given

Leaderboard

  • Global

Trophy case

Kudos (beta program)

Kudos logo

You've been invited into the Kudos (beta program) private group. Chat with others in the program, or give feedback to Atlassian.

View group

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Get incoming links with-in a user macro

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

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.

Husein,

That is working perfectly.

Thanks,

Jason

Perfect. Thank You. that works for as well.

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

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

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.

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

## @noparams

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.

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

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.

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.

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.

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.

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

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.

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

TAGS
Community showcase
Published in Marketplace Apps & Integrations

Happy New Year and Welcome New Marketplace Partner Program Partners!

Happy New Year! We hope you all had a safe and restful holiday season. 2020 was a unique year full of unforeseen events; however, as we enter the new year of 2021, we’re optimistic for the light at t...

435 views 5 16
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you