User Macro to Search for Old Pages

Hi, I have been using JD's user macro:

to implement "wiki gardening" at my office. I have been trying to modify it so that, rather than "allPagesInSpace", it would only search the page on which I place it and all children (descendant) pages. We have some teams that share a space, and so would like to be able to create "targeted" lists of their "old pages" for them to review.

I can't seem to get the thing to work, though, always get "unable to render" or something.

Any tips?

Thx : )

4 answers

Hi Brent,

If you make changes to the code, then any errors will show up in your Confluence log file (the error messages are usually pretty clear as to what you did wrong). I also have an additional user macro that will display the Confluence log in a page, so that makes debugging easier if you don't have access to the server itself.

If I were to rewrite the macro, I would probably hijack the "content by label" macro so I could use the CQL to search dependent pages earlier than a certain date ordered by last updated date. Are you interested?

Here's something that I worked on today for displaying pages with CQL. It only really works for pages, so if you try to search for blogposts, comments, or attachments it displays strangely. You should be able to adapt it for your needs. You might use some CQL like this to get all pages in the space older than 6 months sorted with oldest pages first:

type = page and space=spaceKey() and created < now("-24w") order by lastModified asc

User macro:

## @param CQL:title=CQL Query|type=string|required=true|default=type = page and |desc=Enter CQL Query here, use pageId() to refer to current page ID and spaceKey() to refer to current space key.
#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') )
#set ( $contentEntityManager = $containerContext.getComponent('contentEntityManager') )
#set ( $long = $generalUtil.getSystemStartupTime() )
#set ( $cql = $paramCQL.replace("pageId()", $"spaceKey()", $space.key) )
#set ( $htmlString = $action.getHelper().renderConfluenceMacro("{contentbylabel:showLabels=false|showSpace=false|max=500|cql=$cql}") )
#set ( $tableListings = "" )
#set ( $displayMatch = $req.contextPath + '/display/' )
#set ( $pagesMatch = $req.contextPath + '/pages/' )
#set ( $results = 0)
#foreach ( $linkPart in $htmlString.split('href="') )
#if ( $linkPart.startsWith($displayMatch) || ($linkPart.startsWith($pagesMatch) && !$linkPart.contains('focusedCommentId=')) )
#set ( $results = $results + 1 )
#if ( $linkPart.startsWith($displayMatch) )
#foreach ( $link in $linkPart.split('"') )
#set ( $spaceAndPage = $link.replace($displayMatch, "" ) )
#foreach ( $part in $spaceAndPage.split("/") )
#set ( $spaceKey = $part )
#foreach ( $part in $spaceAndPage.split("/") )
#set ( $pageTitle = $generalUtil.urlDecode($part) )
#set ( $page = $pageManager.getPage($spaceKey, $pageTitle) )
#if ( $linkPart.startsWith($pagesMatch) )
#foreach ( $link in $linkPart.split('"') )
#foreach ( $section in $link.split('pageId=') )
#set ( $pageId = $section )
#set ( $pageId = $long.parseLong($pageId) )
#set ( $page = $contentEntityManager.getById($pageId) )
#set ( $tableListings = $tableListings + '<tr>' )
#set ( $tableListings = $tableListings + '<td><a href="' + $req.contextPath + $page.urlPath + '">' + $page.title + '</a></td>')
#set ( $tableListings = $tableListings + '<td>' + $page.creator.fullName + '</td>' )
#set ( $tableListings = $tableListings + '<td>' + $action.dateFormatter.formatDateTime($page.creationDate) + '</td>' )
#set ( $tableListings = $tableListings + '<td>' + $page.lastModifier.fullName + '</td>' )
#set ( $tableListings = $tableListings + '<td>' + $action.dateFormatter.formatDateTime($page.lastModificationDate) + '</td>' )
#set ( $tableListings = $tableListings + '</tr>' )
#set ( $page = "" )
#if ( $tableListings.contains("tr") )
<p> Found $results results: </p>
<th>Created By</th>
<th>Last Modified</th>
<th>Last Modified By</th>
<p> No results found for CQL Query $cql </p>

In case it was not clear, the original user macro works fine, it's just that whenever I make any ham-fisted changes to the code, it breaks, all on me.

Thank you, Stephen Deutsch! I reviewed your macro and then did some more researching and found another solution. I changed this line:

#set ( $allPagesInSpace = $pageManager.getPages($space, true) )

to this:

#set ( $allDescendants = $content.getDescendants() )

That now makes the user macro behave as I wish, it only searches the descendants of whatever page it is placed on. Hooray!

The next improvements I would like to make, but don't know how:

1) define a default sort for the results:

  1. created date, old>new
  2. modified date, old>new
  3. creating user, alphabetical
  4. modifying user, alphabetical

2) make #set include the parent page, i.e., the page on which the macro is placed, in the search, too.

Here is the updated user macro (updated lines are BOLDED):

## Macro title: Old Pages
## Macro has a body: Y or N (N)
## Body processing: Selected body processing option
## Output: Selected output option

## Macro to display pages that have not been updated for x days
## @param numdays:title=Number of Days|type=int|desc=Enter number of days to compare|required=true|multiple=false|default=7

#set ( $allDescendants = $content.getDescendants() )

## default value handler, set default to 7 days
#set ( $numdays = $paramnumdays )
#set ( $numdays = "7" )
#set ( $numdays = $paramnumdays )

## cast the number of days to an Integer
#set ( $Integer = 0 )
#set ( $intnumdays = $Integer.parseInt($numdays) )

## negative sign the number of days
#set ( $negativeDays = (-1 * $intnumdays) )

## get a calendar object so we can calculate the
## date we wish to compare with the page modification date
## e.g. $compareDate.add(6, -7) for pages modified over a week ago
#set ( $compareDate = $action.dateFormatter.getCalendar() )
$compareDate.add(6, $negativeDays)

<p>Pages last updated before <strong>$action.dateFormatter.format($compareDate.getTime())</strong></p>

<th>Page</th><th>Created</th><th>Created By</th><th>Last Updated</th><th>Last Updated By</th>

## loop through all the pages in the current space
#foreach($page in $allDescendants)

## get a calendar object and for each page in space set it to last modification date
#set ($pagedate = $action.dateFormatter.getCalendar())

## only display pages last modified before the compare date
#if ($pagedate.before($compareDate))
<td>#contentLink2($page true false)</td>
## end looping through pages in the current space


Suggest an answer

Log in or Sign up to answer
Community showcase
Posted Feb 06, 2019 in Confluence

Try out the new editing experience

Hi team, I’m Avinoam, a product manager on Confluence Cloud, and today I’m really excited to let the Community know that all customers can now try out the new editing experience and see some of the ...

1,363 views 97 8
Join discussion

Atlassian User Groups

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

Find a group

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

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you