function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading) {
return;
}
var scriptHasUncommentedLines, flyoutText;
var isAdvanced = (newValue === 'true');
var origScriptVal = (g_form.getValue('script').trim());
var doesScriptExist = (!!origScriptVal);
var newScriptVal = '';
if (isAdvanced) {
//If the ACL is advanced, but is empty, then we don't need to do anything.
if (!doesScriptExist) {
return;
}
//If the ACL is advanced, make sure it doesn't contain any commented-out code.
//If it does, un-comment it.
newScriptVal = toggleACLScriptComments(origScriptVal, false);
} else {
//If the ACL is not advanced, make sure it doesn't contain any executable code.
//If it does, comment it out.
scriptHasUncommentedLines = (getUncommentedLines(origScriptVal).length > 0);
//If the script doesn't exist or is already commented out, don't do anything.
if (!doesScriptExist || !scriptHasUncommentedLines) {
return;
}
newScriptVal = toggleACLScriptComments(origScriptVal, true);
}
if (newScriptVal === origScriptVal) {
//If the script has not changed, don't do anything.
return;
}
flyoutText = '
As per KB0728012, Business Rules and ACLs ' +
'with the "Advanced" checkbox set to false will still execute any ' +
'code in the "Script" field.
' +
'This can cause performance issues and unexpected behavior that can be very ' +
'difficult to troubleshoot, so it\'s recommended to remove any code in the "Script" ' +
'field if the "Advanced" checkbox is set to false.
';
if (isAdvanced) {
flyoutText += 'In this case, since the "Advanced" checkbox has been set to ' +
'true, and the script has previously been commented out by this ' +
'functionality, the script has been un-commented.
';
} else {
flyoutText += 'In this case, since the "Advanced" checkbox has been set to ' +
'false and the script field contained come code that was not ' +
'commented out, the script has been commented out to avoid this potentially ' +
'unexpected behavior.
';
}
flyoutText += 'Original script value:
\n' +
'\n' +
'
' + origScriptVal + '
\n' +
'
';
g_form.setValue('script', newScriptVal);
g_form.clearMessages();
showExpandingFormMessage(
('The ACL\'s script has been ' + (isAdvanced ? 're-enabled' : 'commented out') +
' since the "Advanced" checkbox has been set to ' + newValue + '.
'),
flyoutText,
'More info',
'Hide info'
);
//Helper functions
/**
* Accepts some code and a boolean indicating whether the code should be commented or
* uncommented. Returns the code with the appropriate comments added or removed. If the code has
* already been commented out using this function, it will not change the code.
* @param {string} codeInput - The code to comment or uncomment
* @param {boolean} [shouldBeCommented=true] - A boolean indicating whether to comment out the
* code in the codeInput argument (true) or uncomment it (false).
* Defaults to true.
* @returns {string}
*/
function toggleACLScriptComments(codeInput, shouldBeCommented) {
var i, currentLine, linesOfCode;
var commentExplanation = '/*\n' +
'\tThis code has been disabled because this ACL\'s "Advanced" field has been set to \n' +
'\tfalse. To enable this code, set the "Advanced" field to true. If you\'re seeing \n' +
'\tthis code as disabled and the advanced field is already set to true (which \n' +
'\tshould be the only way to see this code), something has gone wrong. Please \n' +
'\trefresh this form and then disable and re-enable the Advanced checkbox or \n' +
'\tmanually un-comment this code.\n' +
'*/\n\n';
var commentPrefix = '//~Disabled~// ';
var output = [];
//Set default value of shouldBeCommented
shouldBeCommented = (typeof shouldBeCommented === 'undefined' ? true : !!shouldBeCommented);
if (shouldBeCommented && codeInput.startsWith(commentExplanation)) {
//If the code should be commented, but is already commented out, return it as-is.
return codeInput;
}
if (shouldBeCommented) {
output.push(commentExplanation);
} else {
//If the code should be uncommented, remove the comment explanation if it exists.
codeInput = codeInput.replaceAll(commentExplanation, '').trim();
}
linesOfCode = codeInput.split('\n');
for (i = 0; i < linesOfCode.length; i++) {
currentLine = linesOfCode[i];
if (shouldBeCommented) {
output.push(commentPrefix + currentLine);
} else {
output.push(currentLine.replaceAll(commentPrefix, ''));
}
}
return output.join('\n');
}
//Let's use ES6 for this cause it's easier, and why not.
function getUncommentedLines(codeToCheck) {
var uncommentedLines = [];
var isMultilineComment = false;
const lines = codeToCheck.split('\n');
lines.forEach(line => {
if (isMultilineComment) {
if (line.includes('*/')) {
isMultilineComment = false;
const remaining = line.split('*/')[1];
if (remaining.trim() !== '') {
uncommentedLines.push(remaining);
}
}
} else {
if (!line.trim() || line.trim().startsWith('//')) {
return;
}
if (line.trim().startsWith('/*')) {
isMultilineComment = true;
const remaining = line.split('/*')[0];
if (remaining.trim() !== '') {
uncommentedLines.push(remaining);
}
return;
}
uncommentedLines.push(line);
}
});
return uncommentedLines;
}
/**
* Display an expandable form message. This message will be shown at the top of whatever form
* this code is executed on. The text in firstLine will be shown, but the text in flyoutText
* will be hidden until the user clicks the 'expand' link.
*
* @param {String} firstLine - The first line of text in the message, which will be shown
* immediately when this code executes. Unlike the text in flyoutText, this text will not
* be hidden.
* @param {String|HTML_TEXT} flyoutText - This text will be hidden by default, but will be shown
* once the user clicks the 'expand' link (which you can customize by setting expandLinkText).
* @param {String} [expandLinkText="Show more"] - Optionally specify the text to be shown as
* a clickable link, which will cause the form message to expand and display the text
* specified in flyoutText.
* @param {String} [collapseLinkText="Hide details"] - Optionally specify the text to be shown
* after the user clicks the 'expand' link text (specified in expandLinkText).
* This text will be shown when the message is expanded and the text specified in flyoutText
* is shown. Upon clicking this text, the message will be collapsed, flyoutText will be hidden,
* and the link text will revert back to that specified in expandLinkText.
*
* @example
* showExpandingFormMessage(
* 'This message expands',
* flyoutListHTML,
* 'Show more',
* 'Hide details'
* );
*/
function showExpandingFormMessage(firstLine, flyoutText, expandLinkText, collapseLinkText) {
var formMsg = firstLine;
expandLinkText = (typeof expandLinkText !== 'string') ? 'Show more' : expandLinkText;
collapseLinkText = (typeof collapseLinkText !== 'string') ? 'Hide details' : collapseLinkText;
formMsg += '';
g_form.addInfoMessage(formMsg);
}
}