Name

sn_cd.cd_RefQuals

Description

API for Content Publishing tables and dictionaries.

Script

var cd_RefQuals = Class.create();
cd_RefQuals.prototype = {
  type: 'cd_RefQuals'
};

/* Limit content type based on class of current record
* Field: content_type [sn_cd_content_base]
*/
cd_RefQuals.contentType = function() {
  var query = ['active=true'];

  var table = cd_RefQuals._getCurrentContentTable();
  if (table && cd_CommonConstants.CONTENT_CATEGORY_BY_TABLE[table])
  	query.push('category=' + cd_CommonConstants.CONTENT_CATEGORY_BY_TABLE[table]);
  else {
  	var allExtensionPoints = new GlideScriptedExtensionPoint().getExtensions('sn_cd.cd_FilterCriteriaGenerator');
  	allExtensionPoints.forEach(function(ep){
  		if (ep.isContentTypeApplicable(current))
  			query.push(ep.getContentTypeFilter());
  	});
  }

  return query.join('^');
};

/* Limit portal instance to instances whose widget is in the list of associated widgets held by the content's content type
* Field: sp_instance [sn_cd_content_visibility]
*/
cd_RefQuals.spInstance = function() {
  var associatedWidgets = current.content.content_type.associated_widgets.toString();
  var spPageId = current.sp_page.toString();
  return cd_RefQuals._generateAssociatedWidgetsQuery(associatedWidgets, spPageId);
};

cd_RefQuals.spInstanceByContentTypeAndSpPage = function(contentTypeSysId, spPageId) {
  var result = '';
  var contentTypeGr = new GlideRecord('sn_cd_content_type');
  if (contentTypeGr.get(contentTypeSysId)) {
  	var associatedWidgets = contentTypeGr.associated_widgets.toString();
  	result = cd_RefQuals._generateAssociatedWidgetsQuery(associatedWidgets, spPageId);
  }
  return result;
};

cd_RefQuals._generateAssociatedWidgetsQuery = function(associatedWidgets, spPageId) {
  var query = ['active=true'];

  if (associatedWidgets)
  	query.push('sp_widgetIN' + associatedWidgets);

  if (spPageId) {
  	// Get all sp_instance records in a page
  	var spInstanceIds = [];
  	var seenColIds = {};
  	var colIds = [];
  	var queryIds = [];

  	// Find top level columns
  	var grSpColumn = new GlideRecord("sp_column");
  	grSpColumn.addQuery('sp_row.sp_container.sp_page', spPageId);
  	grSpColumn.query();
  	while (grSpColumn.next()) {
  		seenColIds[grSpColumn.getUniqueValue()] = null;
  		queryIds.push(grSpColumn.getUniqueValue());
  	}
  	colIds = colIds.concat(queryIds);

  	// Iteratively find nested columns
  	while (queryIds.length > 0) {
  		grSpColumn = new GlideRecord("sp_column");
  		grSpColumn.addQuery('sp_row.sp_column', 'IN', queryIds.toString());
  		grSpColumn.query();
  		queryIds = [];
  		while (grSpColumn.next()) {
  			if (seenColIds.hasOwnProperty(grSpColumn.getUniqueValue()))
  				continue;
  			seenColIds[grSpColumn.getUniqueValue()] = null;
  			queryIds.push(grSpColumn.getUniqueValue());
  		}
  		colIds = colIds.concat(queryIds);
  	}

  	// Find all sp_instance records in any sp_column on the sp_page
  	var grSpInstance = new GlideRecord("sp_instance");
  	grSpInstance.addActiveQuery();
  	grSpInstance.addQuery("sp_column", "IN", colIds.toString());
  	grSpInstance.query();
  	while (grSpInstance.next())
  		spInstanceIds.push(grSpInstance.getUniqueValue());

  	query.push('sys_idIN' + spInstanceIds.toString());
  }

  return query.join('^');
};

/* Limit sp_page to the page for the current sp_instance
* Field: sp_page [sn_cd_content_visibility]
*/
cd_RefQuals.spPage = function() {
  var grRow = current.sp_instance.sp_column.sp_row.getRefRecord();
  return cd_RefQuals._getSpPageQuery(grRow);
};

cd_RefQuals.spPageBySpInstance = function(sp_instance) {
  var grRow = sp_instance.sp_column.sp_row.getRefRecord();
  return cd_RefQuals._getSpPageQuery(grRow);
};

// Iteratively find the sp_page for a sp_instance
cd_RefQuals._getSpPageQuery = function(grRow) {
  var seenRowIds = {};
  var query = [];
  var unownedPages = cd_RefQuals.getUnownedPages();
  if (unownedPages.length)
  	query.push(unownedPages);
  
  while (grRow != null && grRow.isValid()) {
  	if (!grRow.sp_container.nil()) {
  		query.push('sys_id=' + grRow.sp_container.sp_page.toString());
  		break;
  	} else {
  		grRow = grRow.sp_column.sp_row.getRefRecord();
  		if (seenRowIds.hasOwnProperty(grRow.getUniqueValue()))
  			break;
  		seenRowIds[grRow.getUniqueValue()] = null;
  	}
  }
  
  return query.length ? query.join('^') : query.toString();
}

/* DEPRECATED
*
* Limit root_element to the page for the current page_element
* Field: root_element [sn_cd_content_visibility]
*/
cd_RefQuals.rootElement = function() {
  var query = ['parent=NULL'];
  if (!current || !current.getElement("page_element").toString())
  	return query.toString();

  var seenParentIds = {};

  // Iterate to find the custom root element
  var grParent = current.page_element.parent.getRefRecord();
  seenParentIds[grParent.getUniqueValue()] = null;
  while (grParent.parent.toString()) {
  	grParent = grParent.parent.getRefRecord();
  	if (seenParentIds.hasOwnProperty(grParent.getUniqueValue()))
  		break;
  	seenParentIds[grParent.getUniqueValue()] = null;
  }

  query.push("sys_id=" + grParent.getUniqueValue());

  return query.join("^");
};

/* DEPRECATED
*
* Limit page element to the current root page element
* Field: page_element [sn_cd_content_visibility]
*/
cd_RefQuals.pageElement = function() {
  var query = ['parent!=NULL'];
  if (!current || !current.getElement("root_element").toString())
  	return query.toString();

  var pageIds = [];
  var queryIds = [];
  var seenPageIds = {}; // Avoid circular loops

  // Find top level page elements
  var grPageElement = new GlideRecord("sys_ux_page_element");
  grPageElement.addQuery("parent", current.root_element.toString());
  grPageElement.query();
  while (grPageElement.next()) {
  	pageIds.push(grPageElement.getUniqueValue());
  	queryIds.push(grPageElement.getUniqueValue());
  	seenPageIds[grPageElement.getUniqueValue()] = null;
  }

  // Iteratively find nested page elements
  while (queryIds.length > 0) {
  	grPageElement = new GlideRecord("sys_ux_page_element");
  	grPageElement.addQuery("parent", "IN", queryIds.toString());
  	grPageElement.query();
  	queryIds = [];
  	while (grPageElement.next()) {
  		if (seenPageIds.hasOwnProperty(grPageElement.getUniqueValue()))
  			continue;
  		seenPageIds[grPageElement.getUniqueValue()] = null;
  		queryIds.push(grPageElement.getUniqueValue());
  	}
  	pageIds = pageIds.concat(queryIds);
  }

  query.push("sys_idIN" + pageIds.toString());

  return query.join("^");
};


/* Limit content to those whose associated widgets contains the widget associated with the portal instance
* Field: content [sn_cd_content_visibility] or [sn_ca_campaign_item]
*/
cd_RefQuals.content = function() {
  var query = 'active=true';
  var widget = current.sp_instance.sp_widget.toString();
  var hasForum = current.hasOwnProperty('forum') ? true : false;
  var isValidCommunityPostBundleTrigger = current.campaign_bundle && (current.campaign_bundle.trigger_type == 'fixed_date' || current.campaign_bundle.trigger_type == 'immediate');

  if (widget)
  	query +='^content_type.associated_widgets=NULL^ORcontent_type.associated_widgetsCONTAINS' + widget + '^sys_class_nameINSTANCEOFsn_cd_content_portal';
  else if (hasForum && !isValidCommunityPostBundleTrigger) {
  	var forumPostTypes = [];
  	for (var type in new sn_cd.cd_CommunityContentProcessor().CONTENT_TYPES)
  		forumPostTypes.push(type);

  	query += '^content_type.valueNOT IN' + forumPostTypes.join();
  }

  var allExtensionPoints = new GlideScriptedExtensionPoint().getExtensions('sn_cd.cd_FilterCriteriaGenerator');
  allExtensionPoints.forEach(function(ep){
  	if (!ep.isValidBundleTrigger(current))
  		query += '^' + ep.getContentFilter();
  });

  var delegateQuery = new sn_cd.cd_ContentDelegationUtils().getMyDelegatedContent();
  if (delegateQuery != '')
  	query += '^'+ delegateQuery;
  return query;
};

/* Sets default value for content type if there only exists one applicable content type for content record
* If there are more than one, check Constants to determine if there is a predefined default and use it if it exists
* Field: content_type [sn_cd_content_base]
*/
cd_RefQuals.defaultContentType = function() {
  var grContentType = new GlideRecord("sn_cd_content_type");
  grContentType.addEncodedQuery(cd_RefQuals.contentType());
  grContentType.setLimit(2);
  grContentType.query();
  if (grContentType.getRowCount() == 1 && grContentType.hasNext()) {
  	// There is only one valid content type, use it as default
  	grContentType.next();
  	return grContentType.getUniqueValue();
  } else if (grContentType.hasNext()) {
  	// There are multiple content types, check if we have defined a default for it, and return it
  	var table = cd_RefQuals._getCurrentContentTable();
  	if (table &&
  		cd_CommonConstants.CONTENT_CATEGORY_BY_TABLE[table] &&
  		cd_CommonConstants.DEFAULT_CONTENT_TYPES_BY_CATEGORY[cd_CommonConstants.CONTENT_CATEGORY_BY_TABLE[table]] &&
  		grContentType.get(cd_CommonConstants.DEFAULT_CONTENT_TYPES_BY_CATEGORY[cd_CommonConstants.CONTENT_CATEGORY_BY_TABLE[table]])
  	)
  		return cd_CommonConstants.DEFAULT_CONTENT_TYPES_BY_CATEGORY[cd_CommonConstants.CONTENT_CATEGORY_BY_TABLE[table]];
  }

  gs.warn('Content Publishing - cd_RefQuals - No default defined for table: ' + cd_RefQuals._getCurrentContentTable());
  return '';
};

/* Limit url_asset based on content type for To-do Content
* Field: url_asset [sn_cd_content_todo]
*/
cd_RefQuals.urlAssetTodo = function() {
  var query = 'type!=todo';
  var value = current.content_type.value.toString();
  if (value === 'play_video')
  	query = 'type=video';

  var delegateQuery = new sn_cd.cd_ContentDelegationUtils().getMyDelegatedLinkContent();
  if (delegateQuery != '')
  	query = query + '^' + delegateQuery;

  return query;
};

/* Limit url_asset based on content type for Portal Content
* Field: url_asset [sn_cd_content_portal]
*/
cd_RefQuals.urlAssetPortal = function(type) {
  var query = '';
  if(!gs.nil(type))
  	query = 'type='+type;
  else {
  	var portalContentType = current.content_type.value.toString();
  	if (portalContentType == 'video')
  		query = 'type=video';
  	else if (portalContentType == 'image_based_link')
  		query = 'type=link';
  	else if (portalContentType == 'banner' || portalContentType == 'styled-content')
  		query = 'type=link^ORtype=todo';
  }

  if (query == '')
  	query = 'type!=video^type!=todo';

  var delegateQuery = new sn_cd.cd_ContentDelegationUtils().getMyDelegatedLinkContent();
  if (delegateQuery != '')
  	query+= '^'+delegateQuery;

  return query;
};

/* Limit video_link based on content type for Portal Content
* Field: video_link [sn_cd_content_portal]
*/
cd_RefQuals.videoLinkPortal = function(type) {
  const videoType = 'video';
  const styleContentType = 'styled-content';

  var query = '';
  if(!gs.nil(type))
  	query = 'type='+type;
  else {
  	var portalContentType = current.content_type.value.toString();
  	var currentStyleContentType = current.type.toString();
  	if ((portalContentType == styleContentType) && (currentStyleContentType == videoType))
  		query = 'type=video';
  }
  var delegateQuery = new sn_cd.cd_ContentDelegationUtils().getMyDelegatedLinkContent();
  if (delegateQuery != '')
  	query+= '^'+delegateQuery;

  return query;
};

/*
* Limit to non user specific blocks for certain content tables
* Field: block [sn_cd_content_base]
*/
cd_RefQuals.block = function() {
  var query = '';
  var tables = ['sn_cd_content_community', 'sn_cd_content_notification', 'sn_cd_content_todo'];
  if (tables.indexOf(current.getRecordClassName()) > -1)
  	query += "user_specific=false";

  var delegateQuery = new sn_cd.cd_ContentDelegationUtils().getMyDelegatedBlockContent();
  if (delegateQuery != '')
  	query = query ==='' ? delegateQuery : query+'^'+delegateQuery;

  return query;
};

/*
* Limit approvers to users with role sn_cd.content_manager
* Field: approvers [sn_cd_content_visibility]
*/
cd_RefQuals.approvers = function(role) {
  var approvers = [];
  var gr = new GlideRecord('sys_user_has_role');
  gr.addQuery('role.name', role);
  gr.query();
  while (gr.next()) {
  	approvers.push(gr.user.toString());
  }
  return 'sys_idIN' + approvers.join(',');
};

/*
* Limit topics to only those within a selected taxonomy
* If Topic Ownership is enabled, also filter by authorized topics
* Field: topic [sn_cd_content_visibility]
*/
cd_RefQuals.topics = function() {
  var taxonomy = current.taxonomy.toString();
  var qual = cd_RefQuals.topicsByTaxonomySysId(taxonomy);
  // Check template field availability for backward support
  var topicRecord = new GlideRecord('topic');
  if (topicRecord.isValidField('template')){
  	var templateId = current.sp_page.toString();
  	if(!templateId) {
  		var spInstanceGr = new GlideRecord('sp_instance');
  		if (spInstanceGr.get(current.sp_instance.toString()))
  			templateId = spInstanceGr.sp_column.sp_row.sp_container.sp_page.toString();
  	}
  	qual = cd_RefQuals.topicsByTemplateSysId(qual, templateId);
  }

  return cd_RefQuals.getUnownedTopics(qual) + '^active=true';
};

/*
* Helper function, ANDs a condition to the qual string requiring topics to
* be associated to the currently selected template
*/
cd_RefQuals.topicsByTemplateSysId = function(qual, templateSysId) {
  if (templateSysId)
  	return qual + '^template=' + templateSysId;
  else
  	return qual + '^sys_idISEMPTY'
}

/*
* Helper function, ANDs a list of topic sys_ids to filter out from the qual
* string. The topics are ones that a user does not have access to via the topic ownership
* related lists sn_cd_content_authoring_user and sn_cd_content_authoring_group
*/
cd_RefQuals.getUnownedTopics = function(qual) {
  if (!gs.getProperty('sn_cd.activate_topic_ownership', null))
  	return qual;
  var unauthorizedTopics = cd_RefQuals.getUnauthorizedTopics();
  if (unauthorizedTopics.length)
  	qual += '^sys_idNOT IN' + unauthorizedTopics.join(',');
  return qual;
};

/*
* Helper function, returns a list of topic sys_ids a user does NOT have access to
* according to topic ownership
*/
cd_RefQuals.getUnauthorizedTopics = function() {
  // If a user is a Content Admin, they are authorized to post to all topics
  if (gs.hasRole("sn_cd.content_admin"))
  	return [];
  // Need to remove topics our user is actually authorized to post to at the end,
  // while also only adding topics that have at least one entry in either of the Content Auth tables
  var unauthTopicsObj = {};
  var authTopicsObj = {};
  // Query sn_cd_content_authoring_user table
  var userSysId = gs.getUserID();
  var authUserGr = new GlideRecord('sn_cd_content_authoring_user');
  authUserGr.addNotNullQuery('topic');
  authUserGr.query();
  while (authUserGr.next())
  	if (authUserGr.user.toString() === userSysId)
  		authTopicsObj[authUserGr.topic.toString()] = true;
  	else
  		unauthTopicsObj[authUserGr.topic.toString()] = true;
  // Query sn_cd_content_authoring_group table
  var userObject = gs.getUser();
  var authGroupGr = new GlideRecord('sn_cd_content_authoring_group');
  authGroupGr.addNotNullQuery('topic');
  authGroupGr.query();
  while (authGroupGr.next())
  	if (userObject.isMemberOf(authGroupGr.group.toString()))
  		authTopicsObj[authGroupGr.topic.toString()] = true;
  	else
  		unauthTopicsObj[authGroupGr.topic.toString()] = true;
  // Create final unauthorized topic list, removing topics we specifically have access to
  return Object.keys(unauthTopicsObj).filter(function(topic) { return !authTopicsObj[topic] });
}

/*
* Helper function that limits topics to only those within a selected taxonomy
* Field: topic [sn_cd_content_visibility]
*/
cd_RefQuals.topicsByTaxonomySysId = function(taxonomySysId) {
   if (taxonomySysId)
       return 'taxonomy=' + taxonomySysId;
   else
       return 'sys_idISEMPTY';
};

/*
* Limit taxonomy to only those within a selected topic
* Field: topic [sn_cd_content_visibility]
*/
cd_RefQuals.taxonomy = function() {
  var topics = current.topic.toString();
  if(topics != '') {
  	var taxonomy = '';
  	var gr = new GlideRecord('topic');
  	gr.addQuery('sys_id','IN',topics);
  	gr.addActiveQuery();
  	gr.query();
  	if(gr.next()) {
  		taxonomy = gr.taxonomy.toString();
  	}
  	return 'sys_id=' + taxonomy;
  }
  else {
  	return 'active=true';
  }
};

/*
* Identifies unowned pages.
* If Page Ownership is enabled, filter by authorized pages
* Helper function getUnauthorizedPages ANDs a list of page sys_ids to filter out from the qual
* string. The pages are ones that a user does not have access to via the page ownership
* related lists sn_cd_content_authoring_user and sn_cd_content_authoring_group
*/
cd_RefQuals.getUnownedPages = function() {
  if (gs.getProperty('sn_cd.activate_page_ownership', false)) {
      var unauthorizedPages = cd_RefQuals.getUnauthorizedPages();
      if (unauthorizedPages.length)
          return 'sys_idNOT IN' + unauthorizedPages.join(',');
  }
  return '';
};

/*
* Helper function, returns a list of page sys_ids a user does NOT have access to
* according to page ownership
*/
cd_RefQuals.getUnauthorizedPages = function() {
  // If a user is a Content Admin, they are authorized to post to all pages
  if (gs.hasRole("sn_cd.content_admin"))
  	return [];
  
  // Need to remove pages our user is actually authorized to post to at the end,
  // while also only adding pages that have at least one entry in either of the Content Auth tables
  var unauthPagesObj = {};
  var authPagesObj = {};
  
  // Query sn_cd_content_authoring_user table
  var userSysId = gs.getUserID();
  var authUserGr = new GlideRecord('sn_cd_content_authoring_user');
  authUserGr.addNotNullQuery('page');
  authUserGr.query();
  while (authUserGr.next())
  	if (authUserGr.user.toString() === userSysId)
  		authPagesObj[authUserGr.page.toString()] = true;
  	else
  		unauthPagesObj[authUserGr.page.toString()] = true;
  
  // Query sn_cd_content_authoring_group table
  var userObject = gs.getUser();
  var authGroupGr = new GlideRecord('sn_cd_content_authoring_group');
  authGroupGr.addNotNullQuery('page');
  authGroupGr.query();
  while (authGroupGr.next())
  	if (userObject.isMemberOf(authGroupGr.group.toString()))
  		authPagesObj[authGroupGr.page.toString()] = true;
  	else
  		unauthPagesObj[authGroupGr.page.toString()] = true;
  
  // Create final unauthorized page list, removing pages we specifically have access to
  return Object.keys(unauthPagesObj).filter(function(page) { return !authPagesObj[page] });
};

/*
* Helper function, gets table we're on if there's a match in Constants
*/
cd_RefQuals._getCurrentContentTable = function() {
  var tables = new GlideTableHierarchy(current.getRecordClassName()).getTables();

  var tablesToCheck = Object.keys(cd_CommonConstants.CONTENT_CATEGORY_BY_TABLE);
  for (var i = 0; i < tablesToCheck.length; i++) {
  	if (tables.indexOf(tablesToCheck[i]) > -1)
  		return tablesToCheck[i];
  }
  return null;
};

Sys ID

ef588ec33b230300d901655593efc4b3

Offical Documentation

Official Docs: