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 += '
'; formMsg += '

' + expandLinkText + '

'; formMsg += '
'; formMsg += flyoutText; formMsg += '
'; formMsg += '
'; g_form.addInfoMessage(formMsg); } }