Hi,
I am looking for a solution to move all documents from one space to another. I am surprised this is so difficult to achieve in XWiki, I’d expect this to be basic functionality.
However, after some Googling, I found this conversation. It is suggested to use a combination of the query module and the refactoring module.
So after some more Googling and reading documentation, I came up with this script:
{{velocity}}
#if("$!request.sourceSpaceName" == '')
{{html}}
<form action="" id="newdoc" method="post">
<div>
New location: <input type="text" name="sourceSpaceName" value="old document location" class="withTip" size="50"/>
<span class="buttonwrapper"><input type="submit" value="Lookup documents" class="button"/></span>
</div>
</form>
{{/html}}
#stop
#else
== Documents in space $request.sourceSpaceName
#end
|= name |=title|= full name |= parent
#set( $sourceSpaceName = $!request.sourceSpaceName)
#set( $sourceSpaceWebHome = $sourceSpaceName + ".WebHome")
#set( $docs = $services.query.xwql("select doc from Document as doc where doc.parent = :spaceName").bindValue('spaceName', $sourceSpaceWebHome).setLimit(200).execute() )
#foreach( $doc in $docs )
| $doc.name | $doc.title | $doc.fullName | $doc.parent
#end
#if("$!request.targetSpaceName" != '')
#set ($query = $services.query.xwql('select space from XWikiSpace as space where space.name = :spaceName'))
#set ($space = $query.bindValue('spaceName', $request.targetSpaceName).execute())
#if ($space.size() > 0)
#if ($space[0].name == $request.targetSpaceName)
#foreach ($doc in $docs)
#set ($source = $services.model.resolveSpace($doc.fullName))
* moving $doc ($source)
#set ($dest1 = $services.model.resolveDocument($request.targetSpaceName))
#set ($dest2 = $doc.fullName.replace($sourceSpaceName, ${request.targetSpaceName}).replace(".WebHome", ""))
#set ($destination = $services.model.resolveSpace($dest2))
** to $destination
#try ()
#set ($job = $services.refactoring.move($source, $destination))
#set ($result = $job.join())
#end
#if ("$!exception" != '')
#displayException('some summary to display', $exception)
#end
#end
#end
#else
(% class="box errormessage" %)
(((
Space does not exist
)))
#end
#end
{{html}}
<form action="" id="newdoc" method="post">
<div>
<input type="hidden" name="sourceSpaceName" value="$sourceSpaceName"/>
New location: <input type="text" name="targetSpaceName" value="new document location" class="withTip" size="50"/>
<span class="buttonwrapper"><input type="submit" value="Move these documents" class="button"/></span>
</div>
</form>
{{/html}}
{{/velocity}}
It does the job, however, it does have a few flaws:
- It has limited validation, thus is not fool proof;
- No rights are checked whatsoever, not really secure;
- There’s no feedback to users on progress and/or errors;
- It is not recursive. So if there are multiple levels of documents under the source space, only the top level of documents are moved, I you end up with the deeper levels still in the original space, which is a pretty weird situation.
To overcome the last thing, I tried to replace #set ($dest1 = $services.model.resolveDocument($request.targetSpaceName))
by #set ($dest1 = $services.model.resolveSpace($request.targetSpaceName))
. My idea was that when moving it as a space instead of a page, the children would be moved also. But if I do this change, nothing gets moved at all and I don’t get any error either.
The first three bullets from above are things I could add, but it seems a lot of work. Especially the feedback part, the documentation on Jobs
is not very comprehensive and it seems complicated to me.
My questions are:
- Is this the way to go? Or are there simpler ways to achieve what I want?
- If this is the way to go, can someone give me some examples on how I could add:
a. validation
b. checking of rights
c. feedback on progress
d. feedback on errors
e. recursion
I hope someone can help me.
Best regards,
Bart Kummel