Fix confluence_emoticon in pages
Last modified by Nikita Petrenko on 2025/02/12 12:24
![]() | Allows to perfrom bulk search and replace of confluence_emoticon tags with an emoji_id parameter in XWiki document contents to real emojis |
Type | Snippet |
Category | Other |
Developed by | |
Rating | |
License | GNU 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}}