Fix confluence_emoticon in pages

Last modified by Nikita Petrenko on 2025/02/12 12:24

cogAllows to perfrom bulk search and replace of confluence_emoticon tags with an emoji_id parameter in XWiki document contents to real emojis
TypeSnippet
CategoryOther
Developed by

Raphaƫl Jakse

Rating
0 Votes
LicenseGNU Lesser General Public License 2.1

Table of contents

Description

This script allows to perform bulk search and replace of confluence_emoticon tags with an emoji_id parameter in XWiki document contents to real emojis.

This snippet requires the Job Macro to run.

In a new page, copy-paste the following snippet :

{{velocity}}
#set ($spacePickerParams = {
  'name': 'targetSpace',
  'value': "$!{request.targetSpace}"
})
This script allows to perform bulk search and replace of confluence_emoticon tags with an emoji_id parameter in XWiki document contents to real emojis.

Programming rights are required to use this script.

{{html clean="false"}}
<form class="xform" action="#" method="post">
  <dl>
    <dt>
      <label for="targetSpace">Space</label>
      <span class="xHint">The script will look for documents containing the given search text within the following space.</span>
    </dt>
    <dd>
      #pagePicker($spacePickerParams)
    </dd>
    <dt>
        <input type="checkbox" name="allSpaces" id="allSpaces" />
        <label for="allSpaces">All spaces</label>
        <span class="xHint">The macro replace job will execute for every document in all spaces (excerpt the XWiki system space).</span>
    </dt>
    <dt>
      <input id="savePages" name="savePages" type="checkbox" value="save"/> <label for="savePages">Save pages</label>
      <span class="xHint">By default, this script will execute in dry-mode, and will not save pages.</span>
    </dt>
  </dl>
  <p>
    <span class="buttonwrapper">
      <input type="hidden" name="form_token" value="$!{services.csrf.token}"/>
      <input type="hidden" name="confirm" value="true"/>
      <input class="button" type="submit" value="Replace contents"/>
    </span>
  </p>
</form>
{{/html}}
{{/velocity}}

{{job id="bulkReplaceConfluenceEmoticon" start="{{velocity}}$!{request.confirm}{{/velocity}}"}}
{{groovy}}
  import org.apache.commons.lang3.StringUtils;

  logger = services.logging.getLogger('bulkReplaceConfluenceEmoticon');
  services.logging.setLevel('bulkReplaceConfluenceEmoticon', org.xwiki.logging.LogLevel.INFO);

  if (hasProgramming && services.csrf.isTokenValid(request.form_token)) {
    // Check if we have enough to work on
    boolean allSpaces = request.allSpaces && request.allSpaces != '0' && request.allSpaces != 'false' && request.allSpaces != 'off';
    if ((!request.targetSpace || StringUtils.isBlank(request.targetSpace)) && !allSpaces) {
        logger.error('Missing a target space. Aborting.');
        return;
    }

    def spacePrefix = "${StringUtils.removeEnd(request.targetSpace, 'WebHome')}%";

    // Get every page matching the space
    // In the following code, we split confluence_ emoticon so it doesn't match itself.
    List<String> documents = (
      allSpaces
      ? services.query
      .hql("select doc.fullName from XWikiDocument doc where doc.fullName not like 'XWiki.%' and doc.content like '%{{confluence" + "_emoticon%'")
      : services.query
      .hql("select doc.fullName from XWikiDocument doc where doc.fullName like :spacePrefix and doc.content like '%{{confluence" + "_emoticon%'")
      .bindValue('spacePrefix', spacePrefix.toString())
    ).execute();
    logger.debug('Found [{}] documents to verify', documents.size());
    documents.each { documentFullName ->
      try {
        def document = xwiki.getDocument(documentFullName);
        logger.info('Verifying document [{}]', document.getDocumentReference());
        def oldContent = document.getContent();
        def newContent = oldContent.replaceAll('\\{\\{confluence_' + 'emoticon[\s]+[^{}]*ac:emoji-id="([a-zA-Z0-9]+)"/\\}\\}') {
           Character.toString(Integer.parseInt(it[1], 16))
        }

        hasContentChanged = !(oldContent.equals(newContent));

        if (hasContentChanged && 'save'.equals(request.savePages)) {
          logger.info('Content has changed; saving document [{}]', document.getDocumentReference());
          document.setContent(newContent);
          document.save();
        } else if (hasContentChanged) {
          logger.info('Content for document [{}] has changed but will not be saved', document.getDocumentReference());
        }
      } catch (Exception e) {
        logger.error('Uncaught exception [{}]', e);
      }
    }
  } else {
    logger.error('Insufficient permissions or invalid CSRF token. Aborting.')
  }
{{/groovy}}
{{/job}}

Get Connected