List page children based on the reference hierarchy

Last modified by slauriere on 2026/06/02 17:54

cogList the children of a given page using the reference hierarchy (as opposed to the one based on the parent field)
TypeSnippet
CategoryOther
Developed by

slauriere

Rating
0 Votes
LicenseGNU Lesser General Public License 2.1

Description

Using Solr

#set ($wikiId = $services.wiki.getCurrentWikiDescriptor().getId())
#set ($query = $services.query.createQuery('*', 'solr'))
#set ($fq = ['type:DOCUMENT', "wiki:$wikiId"])
#set ($rootSpaceName = 'Sandbox')
#set ($rootSpaceReference = $services.model.resolveSpace($rootSpaceName))
#set ($referenceChain = $rootSpaceReference.getReversedReferenceChain())
#set ($depth = $referenceChain.size())
#set ($depth = $mathtool.sub($depth, 2))
#set ($defaultPageName = $services.model.getEntityReference('DOCUMENT', 'default').name)
#if ($depth >= 0)
  #set ($discard = $fq.add("space_facet:$depth/${rootSpaceName}."))
  #set ($discard = $query.bindValue('fq', $fq))
  #set ($discard = $query.bindValue('sort', 'title_sort asc'))
  #set ($discard = $query.setLimit(1000))
  #set ($searchResponse = $query.execute()[0])
  #foreach ($result in $searchResponse.results)
    #set ($reference = $services.model.resolveDocument($result.fullname))
    #set ($name = $reference.name)
    #if ($name == $defaultPageName)
      ## Page is not terminal
      #set ($isDirectChild = $reference.getParent().getParent().equals($rootSpaceReference))
    #else
      ## Page is terminal
      #set ($isDirectChild = $reference.getParent().equals($rootSpaceReference))
    #end
    #if ($isDirectChild)
      * [[$result.title_>>$result.fullname]]
    #end
  #end
#end

Remarks:

  • TODO: the rootSpaceName should be escaped
  • The limit parameter should be adjusted if needed.
  • Use $fq = ['hidden:false', 'type:DOCUMENT'] to retrieve only visible pages.
  • The list of fields that can be retrieved from a Solr Document is listed on the Solr Schema page.

Using the REST API

There are 2 REST resources that you can use to fetch the child pages:

  • for top level pages: /wikis/{wikiName}/children
  • for nested pages: /wikis/{wikiName}/spaces/{spaceName}[/spaces/{nestedSpaceName}]*/pages/{pageName}/children?hierarchy=nestedpages

See the REST API documentation for more information.

Using the PageHierarchy component

@Inject
@Named("nestedpages")
private PageHierarchy nestedPageHierarchy;

    ...
    List<DocumentReference> topLevelPages = this.nestedPageHierarchy
        .getChildren(wikiReference)
        .withOffset(offset)
        .withLimit(limit)
        .matching(search)
        .getDocumentReferences();

    ...
    List<DocumentReference> childPages = this.nestedPageHierarchy
        .getChildren(parentReference)
        .withOffset(offset)
        .withLimit(limit)
        .matching(search)
        .getDocumentReferences();

Using the tree.nestedPages Component

In Velocity

#set ($id = $services.model.serialize($doc.documentReference))
#set ($count = $services.tree.nestedPages.getChildCount("document:${id}"))
#set ($children = $services.tree.nestedPages.getChildren("document:${id}", 0, $count))

In Java

The sample code below can be used from a Component:

@Inject
@Named("nestedPages")
private org.xwiki.tree.Tree tree;

@Inject
@Named("entityTreeNodeId")
private org.xwiki.properties.converter.Converter<EntityReference> entityTreeNodeIdConverter;

public List<DocumentReference> getChildren(EntityReference reference) {
  String name = entityTreeNodeIdConverter.convert(String.class, reference);
  int childrenCount = tree.getChildCount(name);
  List<String> children = tree.getChildren(name, 0, childrenCount);
  List<DocumentReference> childReferences = new ArrayList<>();
  for (String childNodeId : children) {
    // FIXME: see how to convert a TreeNode id to a DocumentReference including for nested pages
    // EntityReference childReference = entityTreeNodeIdConverter.convert(EntityReference.class, childName);
    String childName = childNodeId.replace("document:", "");
    DocumentReference childReference = documentReferenceResolver.resolve(childName);
    childReferences.add(childReference);
  }
  return childReferences;
}

Get Connected