How to move Pages/Documents to sub-spaces with macro?

We have a space which contains over 900 archived documents. For better organization, we decided to move them to sub-spaces by year and/or city. I’ll spare the business logic here.

So basically, there is a space space1.space2.space3 which includes all sorts of documents. Depending on attached xObjects and info there, it might be moved to space1.space2.${city}.space3, space1.space2.space3.${year} or space1.space2.${city}.space3.${year}.

I have tried different approaches, splitting the spaces with split('\.') or using .documentReference.getSpaceReferences() to manipulate the spaces. Sadly none really gave me the desired result. I may add, the issue has always been with special characters like . and : which will be escaped in the string representation.

What I really would like is a way to convert a space into an array of strings, then manipulate that and create a space-reference from that string array.

  #set($data = $services.query.xwql("some query")execute())
  #foreach ($page in $data)
    #set($currentDoc = $xwiki.getDocument($page))  ## or maybe use `$services.model.resolveDocument`?
    #set($spacesList = $someMethodToSplitTheSpacesIntoArrays($currentDoc))   ## This should now be ['space1', 'space2', 'space3']
    #set($theYear = $datetool.getYear($currentDoc.getValue('theDate')))
    #set($theCity = $datetool.getYear($currentDoc.getValue('theCity')))

    #if ($condition1)
      #set ($ignore = $spacesList.add("${theYear}-Something"))
    #end
    #if ($condition2)
      #set ($ignore = $spacesList.add(2, "${theCity}"))
    #end

    #set ($newSpace = SomeSerializerMethod($spacesList))
    #set ($destination = $services.model.createSpaceReference($currentDoc.getName(), $newSpace))
    #set ($res = $services.refactoring.move($source, $destination).join())
  #end

Obviously, someMethodToSplitTheSpacesIntoArrays and SomeSerializerMethod don’t exists, but I’m having trouble writing them in a reliable way. As mentioned above, whenever there is a . or :, it doesn’t behave as expected.

I could reproduce the behaviour quite reliably with manually creating a page named Some page 1. and : for example.
I have tried the operational wiki with 16.4.6 and in a local docker image with 17.1.0 - same result.

Can anyone help?

Hello @Ramzi,

It seems like you are trying to parse document references yourself.

  1. XWiki already provides APIs to do that, see https://extensions.xwiki.org/xwiki/bin/view/Extension/Model%20Module#HScriptServiceAPI
  2. you can also call getDocumentReference on $currentDoc to get a DocumentReference that you can then manipulate to create the document reference of the new page safely. You can then directly pass those document references as parameters of $services.refactoring.move

Hopes that help.

Thanks for the answer. I read the link and it is interesting, but I couldn’t figure out how to use it.
Also the getDocumentReference is giving me all sorts of nice features, but nothing to manipulate it safely.
All my attempts ended with my doing string operations like split which cause the same issues I was facing before.

My best guess for now is, using the getSpaceReferences (which gives me a list with different sub-spaces) and generating what I need by using the difference between one string and the next one. But this is again just some string manipulation which is not ideal.

Did I miss something? Any other ideas?

May be this helps:

{{velocity}}

#set ($sourcename="Sandbox.a11.WebHome")

#set ($theSpaces=$sourcename.split("(?<!\\)\."))

## do something with the space name (first index = 0)
## e.g. append "-xxx"

#set ($theSpaces[1]="${theSpaces[1]}-xxx")

## simulate join ...
#set ($targetname="")
#foreach($space in $theSpaces)
  #if ($velocityCount>1)
   #set ($targetname="$targetname.$space")
  #else
   #set ($targetname=$space)
  #end
#end

#set ($source = $services.model.resolveDocument($sourcename))
#set ($target = $services.model.resolveDocument($targetname))
#set ($moveRequest = $services.refactoring.requestFactory.createMoveRequest($source, $target)) 
#set ($discard = $moveRequest.setAutoRedirect(false))
#set ($discard = $moveRequest.setUpdateLinks(true))
$services.refactoring.move($moveRequest).join()
{{/velocity}}