page_white_deleteDelete empty document versions that take up space and make the document history hard to read
TypeXAR
CategoryApplication
Developed by

Eduard Moraru

Rating
Rate!
0 Votes
LicenseGNU Lesser General Public License 2.1
Installable with the Extension Manager

Description

Just by pressing the Save button in edit mode, even with no change, XWiki creates an entry in the document history and a new version. Either you have users that create a lot of empty versions or some script you have executed landed you with hundreds or thousands of empty document versions, you might want to clean up once in a while.

To do that, you can use this application which allows you to display all the documents that have empty versions and then to clean them.

Note: Requires Programming Rights to function.

deleteEmptyDocumentVersions-options.png

You can write your own custom query to select exactly what you want and you can limit the results and set an offset to work in small batches (in case there are many versions to delete).

Pressing "Check" will show the list of checked documents and their status, together with the detected empty versions, if any:

deleteEmptyDocumentVersions-check.png

Pressing "Delete" will delete any detected empty versions and show the report:

deleteEmptyDocumentVersions-delete.png

Note that the execution is very slow when encountering documents with many versions for both checking and/or deleting. You should use the limit and offset fields to run it in small batches, otherwise you might not be able to read the output because it will timeout. It will still be executing in the background and it will eventually finish, but you will not see the report of the result.

Source

In case you just want this as a snippet and can't/won't install it with Extension Manager or with XAR import, you can examine the source below:

{{velocity}}
#set ($displayQuery = "SELECT DISTINCT doc.fullName FROM XWikiDocument doc WHERE doc.fullName='Sandbox.WebHome'")
#if ("$!request.query" != '')
 #set ($displayQuery = $request.query)
#end
##
#set ($displayLimit = "100")
#if ("$!request.limit" != '')
 #set ($displayLimit = $request.limit)
#end
##
#set ($displayOffset = "0")
#if ("$!request.offset" != '')
 #set ($displayOffset = $request.offset)
#end
{{html}}
<form action="" class="xform">
  <dl>
    <dt>
      <label for="query">Query</label>
    </dt>
    <dd>
      <textarea id="query" name="query">$displayQuery</textarea>
    </dd>

    <dt>
      <label for="offset">Offset</label>
    </dt>
    <dd>
      <input id="offset" name="offset" value="$displayOffset">
    </dd>

    <dt>
      <label for="limit">Limit</label>
    </dt>
    <dd>
      <input id="limit" name="limit" value="$displayLimit">
    </dd>
  </dl>
  <p>
    <input type="hidden" name="confirm" value="true" />
    <input type="submit" name="check" value="Check" />
    <input type="submit" name="delete" value="Delete" />
  </p>
</form>
{{/html}}

#if ($request.confirm == 'true')
 #if ($request.check == 'Check')
   #set ($report = true)
 #end
 #set ($zeroChangeMetaDataFields = ["date", "version"])
 #set ($docNames = $services.query.hql($!{request.query}).setLimit($numbertool.toNumber($request.limit)).setOffset($numbertool.toNumber($request.offset)).execute())
  Documents to check: $docNames.size()
 #foreach ($docName in $docNames)
    * Checking document [[$docName>>$docName||queryString="viewer=history&showminor=true"]]...
   ## Start with the latest version of the document.
   #set ($document = $xwiki.getDocument($docName))
   #set ($documentArchive = $document.documentArchive)
   #set ($archiveNeedsSaving = false)
   #set ($zeroChangeVersions = [])
   #set ($versions = $document.revisions)
   ## Convert the array to List so we can reverse it with $collectionstool.
   #set ($versions = $versions.subList(0, $versions.size()))
   ## Go in reverse order, from latest to first.
   #set ($discard = $collectionstool.reverse($versions))
   ## Remove the latest versions since we don't want to start comparing it to itself.
   #set ($versions = $versions.subList(1, $versions.size()))
   ## Go through each version and compare it with the previous one.
   #foreach ($version in $versions)
     #set ($previousDocument = $document.getDocumentRevision($version))
     ##
     #set ($isZeroChange = true)
     ##
     ## Metadata changes need special handling since some fields always change and
     ## we need to determine which change is valuable.
     #set ($metaChanges = $doc.getMetaDataDiff($previousDocument, $document))
     #foreach ($metaChange in $metaChanges)
       ## Determine if the changed field is important.
       #if (!$zeroChangeMetaDataFields.contains($metaChange.field))
         ## If it is, then the change is valuable and we keep it.
         #set ($isZeroChange = false)
         #break
       #end
     #end
     ##
     ## Look at the other types of possible changes.
     #if ($isZeroChange)
       #set ($isZeroChange = $doc.getContentDiff($previousDocument, $document).size() == 0 &&
          $doc.getObjectDiff($previousDocument, $document).size() == 0 &&
          $doc.getClassDiff($previousDocument, $document).size() == 0 &&
          $doc.getAttachmentDiff($previousDocument, $document).size() == 0)
     #end
     ##
     #if ($isZeroChange)
       #if ($report)
         #set ($discard = $zeroChangeVersions.add($document.version))
       #else
         #set ($discard = $documentArchive.removeVersions($document.rCSVersion, $document.rCSVersion, $xcontext.context))
          ** Deleted revision $document.version
         #set ($archiveNeedsSaving = true)
       #end
     #end
     ##
     #set ($document = $previousDocument)
   #end
   ##
   #if ($archiveNeedsSaving)
     #set ($discard = $xwiki.getXWiki().getVersioningStore().saveXWikiDocArchive($documentArchive, true, $xcontext.context))
      ** Saved updated document archive.
   #elseif ($report)
     #if ($zeroChangeVersions.size() > 0)
        ** (!) Versions to cleanup: $zeroChangeVersions.size()
        ** #foreach ($version in $zeroChangeVersions) [[$version>>$docName||queryString="viewer=changes&rev2=$version"]] #end

     #else
        ** (/) Clean
     #end
   #end
 #end
#end
{{/velocity}}

Prerequisites & Installation Instructions

We recommend using the Extension Manager to install this extension (Make sure that the text "Installable with the Extension Manager" is displayed at the top right location on this page to know if this extension can be installed with the Extension Manager). Note that installing Extensions when being offline is currently not supported and you'd need to use some complex manual method.

You can also use the following manual method, which is useful if this extension cannot be installed with the Extension Manager or if you're using an old version of XWiki that doesn't have the Extension Manager:

  1. Log in the wiki with a user having Administration rights
  2. Go to the Administration page and select the Import category
  3. Follow the on-screen instructions to upload the downloaded XAR
  4. Click on the uploaded XAR and follow the instructions
  5. You'll also need to install all dependent Extensions that are not already installed in your wiki
Tags:
Created by Eduard Moraru on 2017/09/29 18:20
    

Get Connected