API Docs for: 1.0.0
Show:

File: scotts\classes\CWTKnowledgeUtil.js

var CWTKnowledgeUtil = Class.create();
/**
 * Class to help with manipulation and information retrieval from Knowledge base records and their related classes, such as Categories and Articles.
 * 
 * Example Uses:
 * + var owner = CWTKnowledgeUtil.negotiateCategoryOwnership("35669ac2dbe9bb008408d12c5e961941", gs.getProperty("knowledge_base.managers_group"));
 * 
 * @class CWTKnowledgeUtil
 * @constructor
 * @module ScriptIncludes
 * @author Alexander Anderson (cwt_alexander)
 * @see https://scottsdev.service-now.com/sys_script_include.do?sys_id=500d0b44db96b3405cacd7795e9619db
 * @param {GlideRecord} knowledge_base
 */
(function() {

	/**
	 * Ordered array indicating the order in which to try to set a field to indicate who should
	 * be considered the owner of a record.
	 * @property userFields
	 * @type Array
	 */
	var userFields = [
		"caller_id",
		"opened_by",
		"requested_for"
	];

	/**
	 * Ordered array indicating the order in which to try to set a field to indicate what group
	 * is assigned to a record or task
	 * @property groupFields
	 * @type Array
	 */
	var groupFields = [
		"assignment_group"
	];

	/**
	 * Ordered array indicating the order in which to try to set a field to indicate the summary or
	 * short description of a record or task.
	 * @property summaryFields
	 * @type Array
	 */
	var summaryFields = [
		"short_description",
		"title",
		"summary",
		"label",
		"name"
	];

	/**
	 * Ordered array indicating the order in which to try to set a field to indicate details for
	 * a record or task.
	 * @property descriptionFields
	 * @type Array
	 */
	var descriptionFields = [
		"description"
	];
	
	/**
	 * Determine if a value should be considered true.
	 * 
	 * Due to a variety of ways of true/false values being returned by service now, this
	 * method exists to level set to a JavaScript boolean value for use.
	 * @method isFalse
	 * @param {Object | String | Boolean | Number} value
	 * @return {Boolean} True if the value is considered as trying to be "true", false otherwise.
	 */
	var isTrue = CWTKnowledgeUtil.isTrue = function(value) {
		return value == "1" || value == "true" || value === "t" || value === true;
	};
	
	/**
	 * Determine if a value should be considered false.
	 * 
	 * Due to a variety of ways of true/false values being returned by service now, this
	 * method exists to level set to a JavaScript boolean value for use.
	 * @method isFalse
	 * @param {Object | String | Boolean | Number} value
	 * @return {Boolean} True if the value is considered as trying to be "false", false otherwise.
	 */
	var isFalse = CWTKnowledgeUtil.isFalse = function(value) {
		return value == "0" || value == "false" || value === "f" || value === false;
	};
	
	CWTKnowledgeUtil.prototype = Object.extendsObject(AbstractAjaxProcessor, {
	    "type": "CWTKnowledgeUtil",
	    /**
	     * Reference to the knowledge base record being used.
	     * @property knowledge_base
	     * @type GlideRecord
	     */
		"initialize": function(kb_knowledge_base) {
			this.kb = kb_knowledge_base;
		}
	});
	
	/**
	 * Used by negotiateCategoryOwnership to perform the recursive lookup.
	 * @method recurseCategoryOwner
	 * @private
	 * @param {GlideRecord} category The category to traverse looking for an active owner
	 * @param {String} [table] Optional string to specify the table against which the field value
	 *		is defined. Defaults to "sys_user".
	 * @param {String} [field] Optional string to specify the category value being searched for with
	 *		an active flag. Defaults to "u_owning user.
	 * @param {String} [field] To handle the transition from "Category" to "Knowledge Base" where field
	 *		names differ for the same class & meaning of property, this serves to indicate the field
	 *		on the kb_knowledge_base table that should be pulled from the knowledge base when reached,
	 *		if any. Defaults to "owner".
	 * @return {GlideRecord} The user record or null.
	 */
	var recurseCategoryOwner = function(category, table, field, kb_field) {
		field = field || "u_owning_user"; // This is redunant but good for a protective fallback
		var kb = new GlideRecord("kb_knowledge_base"),
			buffer = new GlideRecord("kb_category"),
			record = new GlideRecord(table);
		
		if(record.get(category.getValue(field)) && isTrue(record.getValue("active"))) {
			// Owning User exists and is active
			return record;
		} else {
			// No owner or not active
			if(buffer.get(category.getValue("parent_id"))) {
				return recurseCategoryOwner(buffer, table, field, kb_field);
			} else if(kb_field && kb.get(category.getValue("parent_id"))) {
				if(record.get(kb.getValue(kb_field)) && isTrue(record.getValue("active"))) {
					return record;
				} else {
					return null;
				}
			} else {
				return null;
			}
		}
	};
	
	
	/**
	 * If the category has an owner and that owner is active, that owner is returned. If that
	 * owner is not active, the Category's parent is checked. This active/parent check continues
	 * until an active owner is found and returned, or null is returned for no active owner
	 * could be found.
	 * 
	 * @method negotiateCategoryOwnership
	 * @static
	 * @param {GlideRecord | String} category The record or System ID of the Category to check.
	 * @param {GlideRecord | String} [notify] Indicates the group to notify, if any, when no owner
	 * 		can be determined. Uses the System Property "knowledge_base.notify_table" to determine
	 * 		what table the notification is created against.
	 * @param {String} [table] Optional string to specify the table against which the field value
	 *		is defined. Defaults to "sys_user".
	 * @param {String} [field] Optional string to specify the category value being searched for with
	 *		an active flag. Defaults to "u_owning user.
	 * @param {String} [field] To handle the transition from "Category" to "Knowledge Base" where field
	 *		names differ for the same class & meaning of property, this serves to indicate the field
	 *		on the kb_knowledge_base table that should be pulled from the knowledge base when reached,
	 *		if any. Defaults to "owner".
	 * @return {GlideRecord} Referencing the first active owner found or null if one could not be
	 * 		determined or none exists.
	 */
	CWTKnowledgeUtil.negotiateCategoryOwnership = function(id, notify, table, field, kb_field) {
		field = field || "u_owning_user";
		table = table || "sys_user";
		if(kb_field === undefined) {
			kb_field = "owner";
		}
		
		var category = new GlideRecord("kb_category"),
			buffer,
			next,
			x;
		
		category.get(id);
		if(!category.isValidField(field)) {
			// The requested field does not exist in the category table
			gs.warn("CWTKnowledgeUtil: The specified field for active flag chain check is not valid: " + field);
			return null;
		}

		// Perform Search
		buffer = recurseCategoryOwner(category, table, field, kb_field);

		if(buffer === null && notify !== undefined && notify !== null) {
			// This method attempts to arbitrarily fill the requested record type based on the fields present
			// This is to allow easy configuration at the top level of what table to use
			// Note: No need to determine assigned_to as the Knowledge Base has already been deemed inactively owned
			gs.log("Notifying " + notify + " of indeterminate category owner from CWTKnowledgeUtil");
			buffer = new GlideRecord(gs.getProperty("knowledge_base.notify_table"));

			next = true; // More logically clear than using "break"
			for(x=0; x<userFields.length && next; x++) {
				if(buffer.isValidField(userFields[x])) {
					buffer.setValue(userFields[x], gs.getUserID());
					next = false;
				}
			}

			next = true;
			for(x=0; x<groupFields.length && next; x++) {
				if(buffer.isValidField(groupFields[x])) {
					buffer.setValue(groupFields[x], notify.toString());
					next = false;
				}
			}

			next = true;
			for(x=0; x<summaryFields.length && next; x++) {
				if(buffer.isValidField(summaryFields[x])) {
					buffer.setValue(summaryFields[x], "Indeterminate owner for category \"" + category.getValue("label") + "\"");
					next = false;
				}
			}

			next = true;
			for(x=0; x<descriptionFields.length && next; x++) {
				if(buffer.isValidField(descriptionFields[x])) {
					buffer.setValue(descriptionFields[x], "An active owner could not be found for the category \"" + category.getValue("label") + "\" (sys_id: " + category.getValue("sys_id") + ")");
					next = false;
				}
			}

			buffer.insert();
			return null;
		} else {
			gs.debug("CWTKnowledgeUtil: Owner lookup finishing [" + (buffer == null) + "|" + (buffer === null) + "]");
			return buffer;
		}
	};
})();