Writing User Macro to list children of page limited by label - Where can I find Confluence Methods?
Asked by Alana Franklin:

I'm attempting to write a user macro that creates a table of children pages limited by a label parameter. Here's the outline that I have so far:

```
## @param Label:title=Label|type=string|desc=Label|required=true&lt;table&gt;#foreach (CHID OF THE CURRENT PAGE)	#if ($child.label == $parmlabel)		&lt;tr&gt;			&lt;td&gt;				$child.TITLE			&lt;/td&gt;			&lt;td&gt;				$child.AUTHOR			&lt;/td&gt;			&lt;td&gt;				$child.DATEMODIFIED			&lt;/td&gt;		&lt;/tr&gt;	#end#end&lt;/table&gt;
```

The stuff in caps are just placeholders, as I can't find any documentation on confluence methods that might help me loop through each child of the current page. Additionally, I'm not sure of the exact terminology to access the information for those children. I'm new to coding, so I'm excited to kind of figure it out myself... Could someone point me in the right direction?

Thanks,

Alana


Answers:
author: Rp Subhub
body: I'm not an expert but here's something I've come up with.

1. Take a look at [](https://confluence.atlassian.com/display/DOC/Guide+to+User+Macro+Templates)<https://confluence.atlassian.com/display/DOC/Guide+to+User+Macro+Templates>
2. There's $content object of type ContentEntityObject and link to API docs.
3. Traverse direct known subclasses: SpaceContentEntityObject \> AbstractPage \> Page.
4. There're getChildren() and getLabels() methods there.

This will hopefully list chidlren and labels.

```
#foreach ($child in $content.children)  &lt;p&gt;${child.title}: ${child.labels}&lt;/p&gt;#end
```

${content.children} is shortcut for ${content.getChildren()}

comments: author: Alana Franklin
body: Do you think something like this would work to filter the children by label?

```
## @param Label:title=Label|type=string|desc=Label|required=true &lt;table&gt;#foreach ($child in $content.children)	#if ($parmlabel in $child.labels)		&lt;tr&gt;			&lt;td&gt;${child.getTitle()}&lt;/td&gt;		&lt;/tr&gt;	#end#end&lt;/table&gt;
```

Also, any insight on the methods to get author and date-modified?

Thanks again!


author: Rp Subhub
body: ```
## @param label:title=Label|type=string|desc=Label|required=true&lt;table&gt;#foreach ($child in $content.children)  #foreach ($label in $child.labels)    #if ($label.name == $paramlabel)      &lt;tr&gt;        &lt;td&gt;${child.title}&lt;/td&gt;        &lt;td&gt;${child.creator.fullName}&lt;/td&gt;        &lt;td&gt;${child.lastModificationDate}&lt;/td&gt;      &lt;/tr&gt;    #end  #end#end&lt;/table&gt;
```

This may work. But I'm not an expert. I'm not sure about all the edge cases and implications like page restrictions and personal labels and so on.


author: Alana Franklin
body: Thanks! Very helpful! Now the only thing I need to figure out is how to get the title to link to the actual page and the author's name to link to their profile...


author: Rp Subhub
body: Something like this?

```
## @param label:title=Label|type=string|desc=Label|required=true&lt;table&gt;#foreach ($child in $content.children)??#foreach ($label in $child.labels)????#if ($label.name == $paramlabel)??????&lt;tr&gt;????????&lt;td&gt;&lt;ac:link&gt;&lt;ri:page ri:content-title="${generalUtil.escapeXml($child.title)}" /&gt;&lt;/ac:link&gt;&lt;/td&gt;????????&lt;td&gt;&lt;ac:link&gt;&lt;ri:user ri:username="${child.creator.name}" /&gt;&lt;/ac:link&gt;&lt;/td&gt;????????&lt;td&gt;${child.lastModificationDate}&lt;/td&gt;??????&lt;/tr&gt;????#end??#end#end&lt;/table&gt;
```


author: Tom Birch Hansen
body: I've been working on something similar lately.

My macro however uses a list in stead of a table, but this could easily be fixed.

My macro has extra parameters, so you can create a list based on another page's childpages.

It also allows to look at decendants.

```
Here is the macro:## Macro name: tbh_pagelist_by_label## Macro title: Page list by label## Macro has a body: N## Body processing: Selected body processing option## Output: Selected output option#### Developed by: Tom Birch Hansen ## Date created: 2014-04-30## Installed by:  ---## Use this to list pages from children or decendents of a page that match specified labels. ## @param Label:title=Label|type=string|required=true|desc=type label(s) to be present in child pages. Use comma to list multiple labels (pages with any of the labels will be shown)## @param page:title=Page|type=confluence-content|required=false|desc=type page to start from. Leave blank for current page.## @param from:title=From|type=enum|enumValues=decendants,children,children_sorted|required=true|desc=Show pages from## @param showicon:title=Show icon|type=boolean|desc=Show icon next to page link?## @param showspace:title=Show spacename|type=boolean|desc=Show spacename in list?## @param class:title=Class|type=string|desc=Optional formatting using a http class for the html ul element ##PROCESS THE label PARAMETER:#set($pLabelArray=$paramLabel.split(","))## PROCESS THE page PARAMETER, if empty then set to current page#if (!$parampage || $parampage=="")	#set($ppage=$content.getEntity())#else        ## get page object deducted from the page parameter	#set ($colonpos=$parampage.indexOf(":",0))	#if($colonpos==-1)		#set ($xspacekey=$content.spaceKey)		#set ($xpagename=$parampage)	#else		#set ($namepos=$colonpos+1)		#set ($xspacekey=$parampage.substring(0,$parampage.indexOf(":",0)))		#set ($xpagename=$parampage.substring($namepos))		#end	## get page manager...	#set($containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager'))	#set($getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null))	#set($containerManager=$getInstanceMethod.invoke(null,null))	#set($containerContext=$containerManager.containerContext)	#set($pageManager=$containerContext.getComponent('pageManager'))	## find page...	#if ($pageManager)		#set ($ppage= $pageManager.getPage($xspacekey, $xpagename))		#end	#end## PROCESS THE from PARAMETER:#if ($paramfrom=="children_sorted")       #set ($objfrom=$ppage.getSortedChildren())#elseif ($paramfrom=="children")       #set ($objfrom=$ppage.getChildren())#elseif ($paramfrom=="decendants")       #set ($objfrom=$ppage.getDescendents())       #end## PROCESS THE class PARAMETER. set default if empty#if (!$paramclass)	#set($pclass="content-by-label")        #end#set($count = 0)#set($showpage = 0)&lt;ul class="$pclass"&gt;    #foreach ($child in $objfrom)      #if ($count &lt; 100) ## just display the 1st 100                #set ($showpage=0)		#foreach ( $label in $child.getLabels() )			#foreach($pLabel in $pLabelArray)                            #if  ( ($label==$pLabel) )				#set ($showpage=1)			        #end                            #end                            ## END FOR EACH labelarray                        ##if  ( ($label==$pLabel) )				##set ($showpage=1)			##end		#end		## END FOR EAACH LABEL				#if ($showpage==1)		    &lt;li&gt;			##&lt;a href="$req.contextPath$child.urlPath"&gt;&lt;strong&gt;$webwork.htmlEncode($child.displayTitle)&lt;/strong&gt;&lt;/a&gt;			#contentLink2($child $paramshowicon $paramshowspace)        &lt;/li&gt;		#end        #set($count = $count + 1)      #end    #end&lt;/ul&gt;
```

comments: author: voisard
body: Hi Tom,

thank you for that handy macro. While using it (unchanged at the moment) i stumbled over a stange behaviour that I can't explain.

Wenn reporting on a page (in that case the space homepage) and all it's descendant I only get a list of some, but some are missing.

If the same thing is applied via the regular search (with same parameters, search in the space, with the space homepage as root and in all descendant pages that have a certain label) I get more results.

Do you know any occurence of that behaviour or do you have any idea where to look to fix this?

Best regards,  
Ben


author: Peter Andersen
body: Great with the examples here using plain Confluence macro code (no extra plugins needed)!

All the examples use getChildren(), getSortedChildren or getDescendants().

However, in the documentation <https://confluence.atlassian.com/doc/user-macro-template-syntax-223906130.html> Atlassian states that you should *not* use these methods due to security issues.

I can confirm in my own experiments, that using getChildren will obtain all the children of a page even though the person executing the macro does not have permission for some of the subpages.

I would like to implement behavior like the built-in Children Display macro (but with changed formatting) where pages restricted from the current user is not shown at all.

However the Atlassian documentation does not point to how to how this is done.

I have found some very elaborate code that scans over a page's permitted viewers and potentially this could be compared to the current user in the macro, but I am hoping for some simpler solution.

So: how could the built-in Children Display macro behavior be expressed in the user macro code syntax?


author: Mario G?nter
body: Hi Alana,

sorry for the late reply.

Yes. You require the "Reporting Plugin". [](https://marketplace.atlassian.com/plugins/net.customware.confluence.plugin.reporting/versions)<https://marketplace.atlassian.com/plugins/net.customware.confluence.plugin.reporting/versions>

But i am not sure, if this can display author and modified-date. Maybe you can find something in the documentation:   
[](https://docs.servicerocket.com/display/REPORT/Include+All+Child+Pages)<https://docs.servicerocket.com/display/REPORT/Include+All+Child+Pages>

The script above includes all child pages with title(+link) and expandable page content.

Cheers,

Mario


author: Alana Franklin
body: Mario,

Can you explain what's going on in that code? Does it require an additional plugin to work?

Thanks,

Alana


author: Felix Grund (Scandio)
body: Hi Alana,

I don't think what you desire can be achieved with a user macro since you don't have the required context available. Instead, you should write a Confluence Macro like described in the [official documentation](https://developer.atlassian.com/display/CONFDEV/Writing+Macros "Macro Documentation").

Regards, Felix


author: Mario G?nter
body: Hi Alana,

maybe you want something like that. You can modify it up to your requirements:

```
{report-block}  {content-filter:type=page,comment,news}  {content-reporter:scope=@self &gt; children}    {text-sort:content:title}  {content-reporter}  {report-body}h2. {report-info:content:title|link=true}    {expand:title=Show more...}        {report-info:content:body|render=wiki}    {expand}  {report-body}{report-block}
```

You should be able to get author and datemodified, but I'm not sure at the moment.

Hope this helps,

Mario


Tags: confluence-administration

documentation

label

user-macro