jsharmony-cms
Version:
770 lines (681 loc) • 38.1 kB
JavaScript
/*
Copyright 2019 apHarmony
This file is part of jsHarmony.
jsHarmony is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
jsHarmony is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this package. If not, see <http://www.gnu.org/licenses/>.
*/
var Helper = require('jsharmony/Helper');
var HelperFS = require('jsharmony/HelperFS');
var _ = require('lodash');
var path = require('path');
var fs = require('fs');
var async = require('async');
module.exports = exports = function(module, funcs){
var exports = {};
var _t = module._t;
exports.getSitemapFile = function(sitemap_file_id){
if(!sitemap_file_id) throw new Error('Invalid sitemap_file_id');
return path.join(path.join(module.jsh.Config.datadir,'sitemap'),sitemap_file_id.toString()+'.json');
};
exports.getClientSitemap = function(sitemap, cb){
var sitemap_file_id = sitemap.sitemap_file_id;
//Load Sitemap Content from disk
module.jsh.ParseJSON(funcs.getSitemapFile(sitemap_file_id), module.name, 'Sitemap File ID#'+sitemap_file_id, function(err, sitemap_content){
if(err && !HelperFS.fileNotFound(err)) return cb(err);
sitemap_content = sitemap_content || { sitemap_items: [] };
return cb(null,sitemap_content);
}, { fatalError: false });
};
exports.getSampleSitemap = function(){
var rslt = {
'sitemap_items':[
{sitemap_item_id:'1',sitemap_item_parent_id:'',sitemap_item_path:'/1/',sitemap_item_text:'Sample Sitemap',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'1'},
{sitemap_item_id:'2',sitemap_item_parent_id:'1',sitemap_item_path:'/1/2/',sitemap_item_text:'Page A',sitemap_item_hide_menu_parents:'1',sitemap_item_hide_menu_siblings:'1',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'2'},
{sitemap_item_id:'11',sitemap_item_parent_id:'2',sitemap_item_path:'/1/2/11/',sitemap_item_text:'Subpage A-1',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'10'},
{sitemap_item_id:'3',sitemap_item_parent_id:'1',sitemap_item_path:'/1/3/',sitemap_item_text:'Page B',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'3'},
{sitemap_item_id:'4',sitemap_item_parent_id:'3',sitemap_item_path:'/1/3/4/',sitemap_item_text:'Subpage B-1',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'4'},
{sitemap_item_id:'5',sitemap_item_parent_id:'3',sitemap_item_path:'/1/3/5/',sitemap_item_text:'Subpage B-2',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'5'},
{sitemap_item_id:'12',sitemap_item_parent_id:'5',sitemap_item_path:'/1/3/5/12',sitemap_item_text:'Leaf Page B-2.a',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'21'},
{sitemap_item_id:'13',sitemap_item_parent_id:'5',sitemap_item_path:'/1/3/5/13',sitemap_item_text:'Leaf Page B-2.b',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'22'},
{sitemap_item_id:'6',sitemap_item_parent_id:'3',sitemap_item_path:'/1/3/6/',sitemap_item_text:'Subpage B-3',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'6'},
{sitemap_item_id:'7',sitemap_item_parent_id:'3',sitemap_item_path:'/1/3/7/',sitemap_item_text:'Subpage B-4',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'7'},
{sitemap_item_id:'8',sitemap_item_parent_id:'1',sitemap_item_path:'/1/8/',sitemap_item_text:'Page C',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'8'},
{sitemap_item_id:'9',sitemap_item_parent_id:'',sitemap_item_path:'/9/',sitemap_item_text:'Hidden Area',sitemap_item_exclude_from_breadcrumbs:'1',sitemap_item_exclude_from_parent_menu:'1',sitemap_item_link_type:'',sitemap_item_link_dest:''},
{sitemap_item_id:'10',sitemap_item_parent_id:'9',sitemap_item_path:'/9/10/',sitemap_item_text:'Hidden Page',sitemap_item_link_type:'PAGE',sitemap_item_link_dest:'9'}
]
};
_.each(rslt.sitemap_items, function(sitemap_item){
var defaults = {
sitemap_item_type: 'TEXT',
sitemap_item_tag: '',
sitemap_item_style: '',
sitemap_item_class: '',
sitemap_item_exclude_from_breadcrumbs: '0',
sitemap_item_exclude_from_parent_menu: '0',
sitemap_item_hide_menu_parents: '0',
sitemap_item_hide_menu_siblings: '0',
sitemap_item_hide_menu_children: '0',
sitemap_item_link_target: '',
};
for(var key in defaults) if(!(key in sitemap_item)) sitemap_item[key] = defaults[key];
});
return funcs.getPageSitemapRelatives(rslt, 4);
};
exports.sitemap = function (req, res, next) {
var verb = req.method.toLowerCase();
var Q = req.query;
var P = req.body;
var appsrv = this;
var jsh = module.jsh;
var XValidate = jsh.XValidate;
var sql = '';
var sql_ptypes = [];
var sql_params = {};
var verrors = {};
var dbtypes = appsrv.DB.types;
var validate = null;
var model = jsh.getModel(req, module.namespace + 'Sitemap_Tree');
if(!req.params || !req.params.sitemap_key) return next();
var sitemap_key = req.params.sitemap_key;
//Get sitemap
sql_ptypes = [dbtypes.BigInt];
sql_params = { 'sitemap_key': sitemap_key };
validate = new XValidate();
verrors = {};
validate.AddValidator('_obj.sitemap_key', 'Sitemap Key', 'B', [XValidate._v_IsNumeric(), XValidate._v_Required()]);
validate.AddValidator('_obj.branch_id', 'Branch ID', 'B', [XValidate._v_IsNumeric()]);
sql = 'select sitemap_key,sitemap_file_id';
if(Q.sitemap_id){
sql_ptypes.push(dbtypes.BigInt);
sql_params.sitemap_id = Q.sitemap_id;
validate.AddValidator('_obj.sitemap_id', 'Sitemap ID', 'B', [XValidate._v_IsNumeric()]);
sql += ' from {schema}.sitemap where sitemap_key=@sitemap_key and sitemap_id=@sitemap_id and site_id={schema}.my_current_site_id()';
}
else sql += ' from {schema}.v_my_sitemap where sitemap_key=@sitemap_key';
var fields = [];
var datalockstr = '';
appsrv.getDataLockSQL(req, model, fields, sql_ptypes, sql_params, verrors, function (datalockquery) { datalockstr += ' and ' + datalockquery; });
sql = Helper.ReplaceAll(sql, '%%%DATALOCKS%%%', datalockstr);
verrors = _.merge(verrors, validate.Validate('B', sql_params));
if (!_.isEmpty(verrors)) { Helper.GenError(req, res, -2, verrors[''].join('\n')); return; }
appsrv.ExecRecordset(req._DBContext, funcs.replaceSchema(sql), sql_ptypes, sql_params, function (err, rslt) {
if (err != null) { err.sql = sql; err.model = model; appsrv.AppDBError(req, res, err); return; }
if(!rslt || !rslt.length || !rslt[0] || (rslt[0].length != 1)){ return Helper.GenError(req, res, -4, 'Invalid Sitemap ID'); }
var sitemap = rslt[0][0];
if (verb == 'get'){
if (!Helper.hasModelAction(req, model, 'B')) { Helper.GenError(req, res, -11, _t('Invalid Model Access')); return; }
if (!appsrv.ParamCheck('P', P, [])) { Helper.GenError(req, res, -4, 'Invalid Parameters'); return; }
if (!appsrv.ParamCheck('Q', Q, ['|sitemap_id','|branch_id'])) { Helper.GenError(req, res, -4, 'Invalid Parameters'); return; }
//Return sitemap
funcs.getClientSitemap(sitemap, function(err, clientSitemap){
if(err) { Helper.GenError(req, res, -99999, err.toString()); return; }
var page_keys = {};
var media_keys = {};
var branch_id = null;
async.waterfall([
//Validate branch access
function(cb){
if(!Q.branch_id) return cb();
sql = "select v_my_branch_access.branch_id,branch_name,site_id from {schema}.v_my_branch_access inner join {schema}.branch_sitemap on branch_sitemap.branch_id=v_my_branch_access.branch_id where v_my_branch_access.branch_id=@branch_id and branch_access like 'R%' and (branch_sitemap.sitemap_key=@sitemap_key)";
appsrv.ExecRecordset(req._DBContext, funcs.replaceSchema(sql), [dbtypes.BigInt,dbtypes.BigInt], { sitemap_key: sitemap.sitemap_key, branch_id: Q.branch_id }, function (err, rslt) {
if (err != null) { err.sql = sql; err.model = model; appsrv.AppDBError(req, res, err); return; }
if(!rslt || !rslt.length || !rslt[0] || !rslt[0].length){ return Helper.GenError(req, res, -12, 'Could not access Site Revision or Sitemap'); }
branch_id = rslt[0][0].branch_id;
return cb();
});
},
//Get list of all page_keys
function (sitemap_cb){
var sql = 'select page.page_key,page.page_path from {schema}.page inner join {schema}.branch_page on branch_page.page_id = page.page_id where branch_id = $ifnull(@branch_id, {schema}.my_current_branch_id()) and page_file_id is not null and page_path is not null';
appsrv.ExecRecordset(req._DBContext, funcs.replaceSchema(sql), [dbtypes.BigInt], { branch_id: branch_id }, function (err, rslt) {
if (err != null) { err.sql = sql; return sitemap_cb(err); }
if(!rslt || !rslt.length || !rslt[0]){ return sitemap_cb(new Error('Error loading pages')); }
_.each(rslt[0], function(page){
page_keys[page.page_key] = page.page_path;
});
return sitemap_cb();
});
},
//Get list of all media_keys
function (sitemap_cb){
var sql = 'select media.media_key,media.media_path from {schema}.media inner join {schema}.branch_media on branch_media.media_id = media.media_id where branch_id = $ifnull(@branch_id, {schema}.my_current_branch_id()) and media_file_id is not null and media_path is not null';
appsrv.ExecRecordset(req._DBContext, funcs.replaceSchema(sql), [dbtypes.BigInt], { branch_id: branch_id }, function (err, rslt) {
if (err != null) { err.sql = sql; return sitemap_cb(err); }
if(!rslt || !rslt.length || !rslt[0]){ return sitemap_cb(new Error('Error loading media')); }
_.each(rslt[0], function(media){
media_keys[media.media_key] = media.media_path;
});
return sitemap_cb();
});
},
//Set sitemap_item_link_page for PAGE link types
//Set sitemap_item_link_media for MEDIA link types
function(sitemap_cb){
for(var i=0;i<clientSitemap.sitemap_items.length;i++){
var sitemap_item = clientSitemap.sitemap_items[i];
var sitemap_item_link_type = (sitemap_item.sitemap_item_link_type||'').toUpperCase();
if(sitemap_item_link_type=='PAGE'){
var page_key = parseInt(sitemap_item.sitemap_item_link_dest);
if(page_key in page_keys){
sitemap_item.sitemap_item_link_page = page_keys[page_key];
}
else{
sitemap_item.sitemap_item_link_page = 'PAGE :: '+page_key+' :: Not found';
}
}
else if(sitemap_item_link_type=='MEDIA'){
var media_key = parseInt(sitemap_item.sitemap_item_link_dest);
if(media_key in media_keys){
sitemap_item.sitemap_item_link_media = media_keys[media_key];
}
else {
sitemap_item.sitemap_item_link_media = 'MEDIA :: '+media_key+' :: Not found';
}
}
}
return sitemap_cb(null);
},
], function(err){
if(err) { Helper.GenError(req, res, -99999, err.toString()); return; }
res.end(JSON.stringify({
'_success': 1,
'sitemap': clientSitemap
}));
});
});
}
else if (verb == 'post'){
if (!Helper.hasModelAction(req, model, 'U')) { Helper.GenError(req, res, -11, _t('Invalid Model Access')); return; }
//Validate parameters
if (!appsrv.ParamCheck('P', P, ['&sitemap_items'])) { Helper.GenError(req, res, -4, 'Invalid Parameters'); return; }
if (!appsrv.ParamCheck('Q', Q, [])) { Helper.GenError(req, res, -4, 'Invalid Parameters'); return; }
//XValidate
var sitemap_content = P;
if (_.isString(sitemap_content.sitemap_items)){
try{
sitemap_content.sitemap_items = JSON.parse(sitemap_content.sitemap_items);
}
catch(ex){
Helper.GenError(req, res, -4, 'Invalid Parameters');
return;
}
}
if (!_.isArray(sitemap_content.sitemap_items)) sitemap_content.sitemap_items = [];
validate = new XValidate();
verrors = {};
validate.AddValidator('_obj.sitemap_item_id', 'Item ID', 'B', [XValidate._v_Required(), XValidate._v_IsNumeric(true)]);
validate.AddValidator('_obj.sitemap_item_parent_id', 'Parent Item ID', 'B', [XValidate._v_IsNumeric(true)]);
validate.AddValidator('_obj.sitemap_item_path', 'Path', 'B', [XValidate._v_Required(), XValidate._v_MaxLength(2048)]);
validate.AddValidator('_obj.sitemap_item_text', 'Text', 'B', [XValidate._v_MaxLength(2048)]);
validate.AddValidator('_obj.sitemap_item_type', 'Item Type', 'B', [XValidate._v_Required(), XValidate._v_InArray(['TEXT','HTML'])]);
validate.AddValidator('_obj.sitemap_item_tag', 'Tag', 'B', [XValidate._v_MaxLength(2048)]);
validate.AddValidator('_obj.sitemap_item_style', 'CSS Style', 'B', [XValidate._v_MaxLength(2048)]);
validate.AddValidator('_obj.sitemap_item_class', 'CSS Class', 'B', [XValidate._v_MaxLength(2048)]);
validate.AddValidator('_obj.sitemap_item_link_type', 'Link Type', 'B', [XValidate._v_InArray(['PAGE','MEDIA','URL','JS'])]);
validate.AddValidator('_obj.sitemap_item_link_dest', 'Link Destination', 'B', [XValidate._v_MaxLength(2048)]);
validate.AddValidator('_obj.sitemap_item_link_target', 'Link Target', 'B', [XValidate._v_InArray(['NEWWIN'])]);
validate.AddValidator('_obj.sitemap_item_exclude_from_breadcrumbs', 'Exclude from Breadcrumbs', 'B', [XValidate._v_IsNumeric(true),XValidate._v_InArray([0,1])]);
validate.AddValidator('_obj.sitemap_item_exclude_from_parent_menu', 'Exclude from Parent / Sibling Menus', 'B', [XValidate._v_IsNumeric(true),XValidate._v_InArray([0,1])]);
validate.AddValidator('_obj.sitemap_item_hide_menu_parents', 'Menu: Hide Parents', 'B', [XValidate._v_IsNumeric(true),XValidate._v_InArray([0,1])]);
validate.AddValidator('_obj.sitemap_item_hide_menu_siblings', 'Menu: Hide Siblings', 'B', [XValidate._v_IsNumeric(true),XValidate._v_InArray([0,1])]);
validate.AddValidator('_obj.sitemap_item_hide_menu_children', 'Menu: Hide Children', 'B', [XValidate._v_IsNumeric(true),XValidate._v_InArray([0,1])]);
for(var i=0;i<sitemap_content.sitemap_items.length;i++){
var sitemap_item = sitemap_content.sitemap_items[i];
verrors = _.merge(verrors, validate.Validate('B', sitemap_item));
if (!_.isEmpty(verrors)) { Helper.GenError(req, res, -2, 'Error on item #'+(i+1).toString()+'\n'+verrors[''].join('\n')); return; }
}
//Save to database
sql_ptypes = [dbtypes.BigInt];
sql_params = {sitemap_key: sitemap_key};
sql = 'update '+(module.schema?module.schema+'.':'')+'v_my_sitemap set sitemap_file_id=null where sitemap_key=@sitemap_key;';
sql += 'select sitemap_file_id from '+(module.schema?module.schema+'.':'')+'v_my_sitemap where sitemap_key=@sitemap_key;';
fields = [];
datalockstr = '';
verrors = {};
appsrv.getDataLockSQL(req, model, fields, sql_ptypes, sql_params, verrors, function (datalockquery) { datalockstr += ' and ' + datalockquery; });
sql = Helper.ReplaceAll(sql, '%%%DATALOCKS%%%', datalockstr);
if (!_.isEmpty(verrors)) { Helper.GenError(req, res, -2, verrors[''].join('\n')); return; }
appsrv.ExecRecordset(req._DBContext, sql, sql_ptypes, sql_params, function (err, rslt) {
if (err != null) { err.sql = sql; err.model = model; appsrv.AppDBError(req, res, err); return; }
if(!rslt || !rslt.length || !rslt[0] || !rslt[0].length || !rslt[0][0]) return Helper.GenError(req, res, -99999, 'Invalid database result');
sitemap.sitemap_file_id = rslt[0][0].sitemap_file_id;
//Save to disk
fs.writeFile(funcs.getSitemapFile(sitemap.sitemap_file_id), JSON.stringify(sitemap_content), 'utf8', function(err){
res.end(JSON.stringify({ '_success': 1 }));
});
});
return;
}
else return next();
});
};
exports.prettySitemap = function(sitemap_items, page_keys, media_keys, options){
options = _.extend({ text: true }, options);
var rslt = '[\n';
var rsltarr = [];
//Generate indexed list of sitemap items by ID
var sitemap_items_by_id = {};
for(let i=0;i<sitemap_items.length;i++){
var sitemap_item = sitemap_items[i];
sitemap_item.collection_index = i;
sitemap_items_by_id[sitemap_item.sitemap_item_id] = sitemap_item;
if(!sitemap_item.sitemap_item_parent_id){
sitemap_item.sitemap_item_path_text = '/' + Helper.StripTags(sitemap_item.sitemap_item_text).trim() + '/';
sitemap_item.sitemap_item_collection_index_array = [sitemap_item.collection_index];
}
}
//Generate text path
function getTextPath(sitemap_item){
if(!sitemap_item) return '';
if(!sitemap_item.sitemap_item_path_text){
sitemap_item.sitemap_item_parents = getTextPath(sitemap_items_by_id[sitemap_item.sitemap_item_parent_id]);
sitemap_item.sitemap_item_path_text = sitemap_item.sitemap_item_parents + Helper.StripTags(sitemap_item.sitemap_item_text).trim() + '/';
if(!sitemap_item.sitemap_item_collection_index_array){
sitemap_item.sitemap_item_collection_index_array = sitemap_items_by_id[sitemap_item.sitemap_item_parent_id].sitemap_item_collection_index_array.concat([sitemap_item.collection_index]);
}
}
return sitemap_item.sitemap_item_path_text;
}
//Clone sitemap_items
sitemap_items = JSON.parse(JSON.stringify(sitemap_items||[]));
//Get text paths
_.each(sitemap_items, function(sitemap_item){
getTextPath(sitemap_item);
});
if(options.text){
//Sort sitemap items
sitemap_items.sort(function(a,b){
for(let i=0;i<a.sitemap_item_collection_index_array.length;i++){
if(b.sitemap_item_collection_index_array.length <= i) return 1;
if(a.sitemap_item_collection_index_array[i] > b.sitemap_item_collection_index_array[i]) return 1;
if(a.sitemap_item_collection_index_array[i] < b.sitemap_item_collection_index_array[i]) return -1;
}
if(a.sitemap_item_collection_index_array.length < b.sitemap_item_collection_index_array.length) return -1;
return 0;
});
}
_.each(sitemap_items, function(sitemap_item){
//Delete non-essential info
var sitemap_item_path = sitemap_item.sitemap_item_path_text;
if(sitemap_item_path && (sitemap_item_path[sitemap_item_path.length-1]=='/')) sitemap_item_path = sitemap_item_path.substr(0, sitemap_item_path.length-1);
var print_item = {
sitemap_item: sitemap_item_path,
type: sitemap_item.sitemap_item_type,
};
var link_type = (sitemap_item.sitemap_item_link_type||'').toUpperCase();
var link_text = '';
if(link_type){
link_text = link_type + ' :: ' + sitemap_item.sitemap_item_link_dest;
if(link_type=='PAGE'){
var page_key = parseInt(sitemap_item.sitemap_item_link_dest);
if(page_key in page_keys) link_text = 'PAGE :: ' + page_keys[page_key].page_path;
}
else if(link_type=='MEDIA'){
var media_key = parseInt(sitemap_item.sitemap_item_link_dest);
if(media_key in media_keys) link_text = 'MEDIA :: ' + media_keys[media_key].media_path;
}
}
if(link_text){
print_item.link = link_text;
if(sitemap_item.sitemap_item_link_target) print_item.link_target = sitemap_item.sitemap_item_link_target;
}
if(sitemap_item.sitemap_item_tag) print_item.tag = sitemap_item.sitemap_item_tag;
if(sitemap_item.sitemap_item_style) print_item.css_style = sitemap_item.sitemap_item_style;
if(sitemap_item.sitemap_item_class) print_item.css_class = sitemap_item.sitemap_item_class;
if(sitemap_item.sitemap_item_exclude_from_breadcrumbs && (sitemap_item.sitemap_item_exclude_from_breadcrumbs!='0')) print_item.exclude_from_breadcrumbs = sitemap_item.sitemap_item_exclude_from_breadcrumbs;
if(sitemap_item.sitemap_item_exclude_from_parent_menu && (sitemap_item.sitemap_item_exclude_from_parent_menu!='0')) print_item.exclude_from_parent_menu = sitemap_item.sitemap_item_exclude_from_parent_menu;
if(sitemap_item.sitemap_item_hide_menu_parents && (sitemap_item.sitemap_item_hide_menu_parents!='0')) print_item.hide_menu_parents = sitemap_item.sitemap_item_hide_menu_parents;
if(sitemap_item.sitemap_item_hide_menu_siblings && (sitemap_item.sitemap_item_hide_menu_siblings!='0')) print_item.hide_menu_siblings = sitemap_item.sitemap_item_hide_menu_siblings;
if(sitemap_item.sitemap_item_hide_menu_children && (sitemap_item.sitemap_item_hide_menu_children!='0')) print_item.hide_menu_children = sitemap_item.sitemap_item_hide_menu_children;
//Add to array
rsltarr.push(print_item);
//Generate text
rslt += ' { ';
var first_key = true;
for(var key in print_item){
if(!first_key) rslt += ', ';
rslt += key + ': ' + JSON.stringify(print_item[key]);
first_key = false;
}
rslt += ' },\n';
});
rslt += ']';
if(options.text) return rslt;
return rsltarr;
};
exports.getPageSitemapRelatives = function(sitemap, page_key){
/*
Returns:
self
parents (hierarchy from current node to root) (+ siblings for each parent)
siblings
children
* siblings arrays include the item itself
*/
if(!sitemap) return {};
var sitemap_items = _.cloneDeep(sitemap.sitemap_items || []);
page_key = (page_key||'').toString();
function parseSitemapBool(val){
if(typeof val == 'undefined') return false;
if(val === '1') return true;
if(val === 1) return true;
if(val === true) return true;
return false;
}
var sitemap_items_by_id = {};
for(let i=0;i<sitemap_items.length;i++){
let sitemap_item = sitemap_items[i];
sitemap_item.sitemap_item_id = (sitemap_item.sitemap_item_id||'').toString();
sitemap_item.sitemap_item_link_dest = (sitemap_item.sitemap_item_link_dest||'').toString();
sitemap_item.sitemap_item_parent_id = (sitemap_item.sitemap_item_parent_id||'').toString();
sitemap_items_by_id[sitemap_item.sitemap_item_id.toString()] = sitemap_item;
sitemap_item.sitemap_item_exclude_from_breadcrumbs = parseSitemapBool(sitemap_item.sitemap_item_exclude_from_breadcrumbs);
sitemap_item.sitemap_item_exclude_from_parent_menu = parseSitemapBool(sitemap_item.sitemap_item_exclude_from_parent_menu);
sitemap_item.sitemap_item_hide_menu_parents = parseSitemapBool(sitemap_item.sitemap_item_hide_menu_parents);
sitemap_item.sitemap_item_hide_menu_siblings = parseSitemapBool(sitemap_item.sitemap_item_hide_menu_siblings);
sitemap_item.sitemap_item_hide_menu_children = parseSitemapBool(sitemap_item.sitemap_item_hide_menu_children);
}
//Get full parent hierarchy from current item to root
function getParents(sitemap_item){
var rslt = [];
var curParent = sitemap_items_by_id[sitemap_item.sitemap_item_parent_id];
while(curParent){
curParent.sitemap_item_siblings = [];
rslt.unshift(curParent);
curParent = sitemap_items_by_id[curParent.sitemap_item_parent_id];
}
return rslt;
}
//Get sitemap item
var current_item = null;
var matching_items = [];
for(let i=0;i<sitemap_items.length;i++){
let sitemap_item = sitemap_items[i];
if((sitemap_item.sitemap_item_link_type=='PAGE') && (sitemap_item.sitemap_item_link_dest==page_key)){ matching_items.push(sitemap_item); }
}
if(matching_items.length == 1){
//If one matching item with that page_key is found, use that item
current_item = matching_items[0];
}
else if(matching_items.length > 1){
//If multiple items found with the same page_key, use the lowest node of the first traversal
// -- ex. If 1st match = "About Us", and 2nd match = "About Us -> Overview", return "Overview"
// -- ex. If 1st match = "About Us", and 2nd match = "Services -> Overview", return "About Us" (since Services is not a child of About Us)
var matching_items_hierarchy = [];
for(let i=0;i<matching_items.length;i++){
var sitemap_item_parents = getParents(matching_items[i]);
var sitemap_item_hierarchy = [matching_items[i].sitemap_item_id];
_.each(sitemap_item_parents, function(parent){ sitemap_item_hierarchy.push(parent.sitemap_item_id); });
matching_items_hierarchy.push(sitemap_item_hierarchy);
}
while(
(matching_items.length > 1) &&
(matching_items[1].sitemap_item_parent_id && _.includes(matching_items_hierarchy[0], matching_items[1].sitemap_item_parent_id))
){ matching_items.shift(); matching_items_hierarchy.shift(); }
current_item = matching_items[0];
}
var parents = null;
var children = null;
var breadcrumbs = null;
//Get parents, children, and siblings of the current item
if(current_item){
current_item.sitemap_item_siblings = [];
var removeSiblings = function(sitemap_item){
sitemap_item = _.clone(sitemap_item);
delete sitemap_item.sitemap_item_siblings;
return sitemap_item;
};
//Get parents of current item
parents = getParents(current_item);
children = [];
for(let i=0;i<sitemap_items.length;i++){
let sitemap_item = sitemap_items[i];
if(!sitemap_item.sitemap_item_exclude_from_parent_menu){
//Children of current item
if(sitemap_item.sitemap_item_parent_id==current_item.sitemap_item_id){ children.push(sitemap_item); }
//Siblings of current item
if(sitemap_item.sitemap_item_parent_id==current_item.sitemap_item_parent_id){ current_item.sitemap_item_siblings.push(removeSiblings(sitemap_item)); }
//Siblings of each parent in the hierarchy from current item to root
for(var j=0;j<parents.length;j++){
if(sitemap_item.sitemap_item_parent_id==parents[j].sitemap_item_parent_id){ parents[j].sitemap_item_siblings.push(removeSiblings(sitemap_item)); }
}
}
}
//Process hide_menu_children
if(current_item.sitemap_item_hide_menu_children) children = [];
//Process hide_menu_siblings
if(current_item.sitemap_item_hide_menu_siblings || !current_item.sitemap_item_siblings.length) current_item.sitemap_item_siblings = [removeSiblings(current_item)];
for(let i=0;i<parents.length;i++){
let parent = parents[i];
if(parent.sitemap_item_hide_menu_siblings || !parent.sitemap_item_siblings.length) parent.sitemap_item_siblings = [removeSiblings(parent)];
}
//Process hide_menu_parents
breadcrumbs = [];
_.each(parents, function(parent){
if(!parent.sitemap_item_exclude_from_breadcrumbs) breadcrumbs.push(parent);
});
breadcrumbs.push(current_item);
if(current_item.sitemap_item_hide_menu_parents) parents = [];
for(let i=parents.length-1;i>=0;i--){
let parent = parents[i];
if(parent.sitemap_item_hide_menu_parents){
parents.splice(0, i);
break;
}
}
}
else if(!page_key){
return {
self: null,
parents: null,
breadcrumbs: null,
children: null,
sitemap_items: sitemap_items,
};
}
var rslt = {
self: current_item,
parents: parents,
breadcrumbs: breadcrumbs,
children: children,
};
return JSON.parse(JSON.stringify(rslt));
};
exports.getSitemapUrl = function(sitemap_item, branchData){
if((sitemap_item.sitemap_item_link_type||'').toString()=='PAGE'){
var page_key = parseInt(sitemap_item.sitemap_item_link_dest);
if(!branchData) return '#';
if(!(page_key in branchData.page_keys)) throw new Error('Sitemap item '+sitemap_item.sitemap_item_path+' :: '+sitemap_item.sitemap_item_text+' links to missing Page ID # '+page_key.toString());
return branchData.page_keys[page_key];
}
else if((sitemap_item.sitemap_item_link_type||'').toString()=='MEDIA'){
var media_key = parseInt(sitemap_item.sitemap_item_link_dest);
if(!branchData) return '#';
if(!(media_key in branchData.media_keys)) throw new Error('Sitemap item '+sitemap_item.sitemap_item_path+' :: '+sitemap_item.sitemap_item_text+' links to missing Media ID # '+media_key.toString());
return branchData.media_keys[media_key];
}
return sitemap_item.sitemap_item_link_dest;
};
exports.createSitemapTree = function(sitemap, branchData){
//Input:
// self + siblings
// parents + siblings
// children
//***Populate children, siblings, parent
//parent.siblings
//parent.children
//parent.parent
//self.siblings
//self.children
//self.parent
if(sitemap.self){
//self.parent
if(sitemap.parents && sitemap.parents.length) sitemap.self.parent = sitemap.parents[sitemap.parents.length-1];
else sitemap.self.parent = null;
//self.children
sitemap.self.children = sitemap.children || [];
//self.children.siblings
for(let i=0;i<sitemap.self.children.length;i++){
var child = sitemap.self.children[i];
child.siblings = sitemap.self.children;
child.parent = sitemap.self;
}
//self.siblings
sitemap.self.siblings = sitemap.self.sitemap_item_siblings || [sitemap.self];
for(let i=0;i<sitemap.self.siblings.length;i++){
var sibling = sitemap.self.siblings[i];
//Replace self in sitemap.self.siblings
if(sibling.sitemap_item_id == sitemap.self.sitemap_item_id) sitemap.self.siblings[i] = sitemap.self;
else{
sibling.parent = sitemap.self.parent;
sibling.children = [];
}
}
}
else if(sitemap.sitemap_items){
//Generate sitemap tree
var sitemap_item_parents = {};
_.each(sitemap.sitemap_items, function(sitemap_item){
sitemap_item_parents[(sitemap_item.sitemap_item_id||'').toString()] = sitemap_item;
sitemap_item.children = [];
});
_.each(sitemap.sitemap_items, function(sitemap_item){
var parent_id = (sitemap_item.sitemap_item_parent_id||'').toString();
if(parent_id){
sitemap_item.parent = sitemap_item_parents[parent_id];
sitemap_item.siblings = [];
if(sitemap_item.parent && !sitemap_item.sitemap_item_exclude_from_parent_menu){
sitemap_item.siblings = sitemap_item.parent.children.slice();
_.each(sitemap_item.parent.children, function(sibling){
sibling.siblings.push(sitemap_item);
});
sitemap_item.parent.children.push(sitemap_item);
}
}
});
}
//Replace self in each sitemap.parents.siblings
if(sitemap.parents){
for(let i=0;i<sitemap.parents.length;i++){
let parent = sitemap.parents[i];
//parent.parent
if(i==0) parent.parent = null;
else parent.parent = sitemap.parents[i-1];
//parent.siblings
parent.siblings = parent.sitemap_item_siblings || [parent];
for(var j=0;j<parent.siblings.length;j++){
if(parent.siblings[j].sitemap_item_id == parent.sitemap_item_id) parent.siblings[j] = parent;
}
}
for(let i=0;i<sitemap.parents.length;i++){
let parent = sitemap.parents[i];
//parent.children
if(i==(sitemap.parents.length-1)) parent.children = sitemap.self.siblings;
else parent.children = sitemap.parents[i+1].siblings;
}
}
//Generate tree and root
if(sitemap.parents && sitemap.parents.length){
sitemap.tree = [sitemap.parents[0]];
sitemap.root = sitemap.parents[0];
}
else if(sitemap.self){
sitemap.root = sitemap.self;
sitemap.tree = sitemap.self.siblings;
}
else if(sitemap.sitemap_items){
sitemap.tree = _.filter(sitemap.sitemap_items, function(sitemap_item){ return !sitemap_item.sitemap_item_parent_id && !sitemap_item.sitemap_item_exclude_from_parent_menu; });
}
else sitemap.tree = null;
//Populate allItems
sitemap.allItems = [];
if(sitemap.sitemap_items){
var addToAllItems = function(sitemap_item){
sitemap.allItems.push(sitemap_item);
_.each(sitemap_item.children, function(child_item){ addToAllItems(child_item); });
};
_.each(sitemap.tree, function(sitemap_item){ addToAllItems(sitemap_item); });
}
else {
_.each(sitemap.parents, function(parent){
_.each(parent.siblings, function(sibling){ sitemap.allItems.push(sibling); });
});
if(sitemap.self){
_.each(sitemap.self.siblings, function(sibling){ sitemap.allItems.push(sibling); });
_.each(sitemap.self.children, function(child){ sitemap.allItems.push(child); });
}
}
//Populate id and item fields
var itemsToProcess = sitemap.sitemap_items || sitemap.allItems;
_.each(sitemap.breadcrumbs, function(sitemap_item){
if(!_.includes(itemsToProcess, sitemap_item)) itemsToProcess.push(sitemap_item);
});
_.each(itemsToProcess, function(sitemap_item){
sitemap_item.id = sitemap_item.sitemap_item_id;
sitemap_item.sitemap_item_type = (sitemap_item.sitemap_item_type||'TEXT').toUpperCase();
sitemap_item.sitemap_item_link_type = (sitemap_item.sitemap_item_link_type||'').toUpperCase();
sitemap_item.sitemap_item_link_target = (sitemap_item.sitemap_item_link_target||'').toUpperCase();
//html
sitemap_item.html = sitemap_item.sitemap_item_text;
if(sitemap_item.sitemap_item_type != 'HTML') sitemap_item.html = Helper.escapeHTML(sitemap_item.html);
sitemap_item.text = Helper.StripTags(sitemap_item.html);
sitemap_item.tag = sitemap_item.sitemap_item_tag || '';
sitemap_item.sitemap_tag = sitemap.sitemap_tag || '';
sitemap_item.class = sitemap_item.sitemap_item_class || '';
sitemap_item.style = sitemap_item.sitemap_item_style || '';
sitemap_item.href = '';
sitemap_item.onclick = '';
if(sitemap_item.sitemap_item_link_type){
if(sitemap_item.sitemap_item_link_type=='JS'){
sitemap_item.href = '#';
sitemap_item.onclick = sitemap_item.sitemap_item_link_dest + '; return false;';
} else {
sitemap_item.href = funcs.getSitemapUrl(sitemap_item, branchData);
}
}
sitemap_item.target = ((sitemap_item.sitemap_item_link_type != 'JS') && (sitemap_item.sitemap_item_link_target == 'NEWWIN')) ? '_blank' : '';
sitemap_item.selected = (sitemap_item.sitemap_item_id === (sitemap.self && sitemap.self.sitemap_item_id));
});
//Populate parents, depth
function resolveParent(sitemap_item){
if(sitemap_item.parents) return;
if(!sitemap_item.parent){
sitemap_item.parents = [];
sitemap_item.depth = 1;
return;
}
if(!sitemap_item.parent.parents) resolveParent(sitemap_item.parent);
sitemap_item.parents = sitemap_item.parent.parents.concat(sitemap_item.parent);
sitemap_item.depth = sitemap_item.parent.depth + 1;
}
_.each(sitemap.allItems, function(sitemap_item){
resolveParent(sitemap_item);
sitemap_item.getSiblings = function(){
var siblings = sitemap_item.parent ? sitemap_item.parent.children : sitemap.tree;
return _.filter(siblings, function(sibling){ return sibling.id != sitemap_item.id; });
};
});
//Debugging - Render Tree
//(function renderTree(sitemap_items, prefix){
// prefix = prefix || '';
// _.each(sitemap_items, function(sitemap_item){
// console.log(prefix+(sitemap_item.selected?'*':'')+sitemap_item.sitemap_item_text);
// renderTree(sitemap_item.children, prefix + ' ');
// });
//})(sitemap.tree);
//console.log('---------');
//Aliases
sitemap.topItems = sitemap.tree;
sitemap.currentItem = sitemap.self;
sitemap.item = sitemap.self;
};
return exports;
};