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