lib/util/moboUtil.js

Summary

Maintainability
C
1 day
Test Coverage
/* jshint unused: false */

//////////////////////////////////////////
// Requirements                         //
//////////////////////////////////////////

var _     = require('lodash');
var fs     = require('fs-extra');
var path   = require('path');
var semlog     = require('semlog');
var log        = semlog.log;

var handlebars = require('./../util/handlebarsExtended');


//////////////////////////////////////////
// LOGGER FUNCTIONS                     //
//////////////////////////////////////////

/**
 * Writes the current log object to a file in the given directory
 *
 * @param dir   filepath
 */
exports.writeLogHistory = function(dir) {
    if (dir) {
        var fileName = semlog.roboDate();
        fileName = path.resolve(dir, fileName + '.json');
        fs.ensureDir(dir, function() {
            fs.outputFile(fileName, JSON.stringify(semlog.getLogHistory(), false, 4));
        });
    }
};


//////////////////////////////////////////
// MODELING HELPER                      //
//////////////////////////////////////////

/**
 * Takes an model/field/form $extend URL and returns the name of the file without extension
 *
 * @param {string} url
 * @param {string} hint
 * @returns {object|boolean}
 */
exports.resolveReference = function(url, hint) {

    /** If an error occurs, this gives a hint in which file */
    if (hint) {
        hint = ' ' + hint + ': ';
    } else {
        hint = '';
    }

    if (url.indexOf('/') > -1) {
        var ref = url.split('/');

        if (ref.length === 3) {

            // TODO: Would be more consequent to always strip the file extension
            // This does currently cause problems with .wikitext mobo_template and the queries
            // var id = ref[2].substr(0, ref[2].lastIndexOf('.'));

            var id = ref[2].replace('.json', '');
            return {
                path: url,
                type: ref[1],
                filename: ref[2],
                id: id
            };
        } else {
            log('[E]' + hint + ' Malformed "$reference" or "format" path: ' + url);
            log('[i] Do not include include subfolders in the "$extend" or "format" path!');
            return false;
        }

    } else {
        // if "format" is not a path, the name is already the id
        return {
            id: url
        };
    }

};



/**
 * Calculates the pre- or postfixed wikitext of models
 *
 * @param {string}  mode        'smw_prepend' or 'smw_append'
 * @param {object}  model
 * @param {object}  registry
 *
 * @returns {boolean|object}
 */
exports.prePostFix = function(mode, model, registry) {

    var wikitext = '';

    if (model.items) {
        model = model.items;
    }

    if (model[mode]) {

        if (_.isObject(model[mode])) {
            // Inject auto header, depending on given hierachy
            if (model[mode].header) {
                var headerLevel = '=';
                if (model[mode].header > 0 && model[mode].header < 8) {
                    headerLevel = new Array(model[mode].header + 1).join('=');
                }
                wikitext += headerLevel + model.title + headerLevel + '\n';
            }

            // Inject wikitext
            if (model[mode].wikitext) {
                wikitext += model[mode].wikitext + '\n';
            }

            // Inject already existing template
            if (model[mode].template) {
                if (!_.isArray(model[mode].template)) {
                    model[mode].template = [model[mode].template];
                }

                for (var i = 0; i < model[mode].template.length; i++) {
                    var templateName = model[mode].template[i];

                    if (registry.smw_template[templateName + '.wikitext']) {
                        wikitext += registry.smw_template[templateName + '.wikitext'];
                    } else {
                        log('[E] ' + model.$filepath + ' references to non exisiting template: ' + model[mode].template);
                    }

                }
            }
        } else if (_.isString(model[mode])) {
            wikitext += model[mode] + '\n';
        }


    }

    return wikitext;
};

//////////////////////////////////////////
// MISC HELPER FUNCTIONS                //
//////////////////////////////////////////

/**
 * Recursively add default values to a JSON Schema through an example/default object
 * @param schema
 * @param defaults
 */
exports.addDefaults = function(schema, defaults) {
    for (var propName in schema.properties) {
        var prop = schema.properties[propName];
        if (prop.properties) {
            // If it is an object, go one steep deeper (recursion)
            exports.addDefaults(prop, defaults[propName]);
        } else if (defaults.hasOwnProperty(propName)) {
            // Default found, add it to the schema
            prop.default = defaults[propName];
        }
    }
};

/**
 * Helper function that loads a handlebars-template if it hasn't been loaded yet
 *
 * @param {{}}      scope           Usually module.exports
 * @param {string}  templateFileName    name of the template including file extension
 * @param {{}}      settings
 * @param {boolean} [internalTemplate]
 *
 * @returns {*}
 */
exports.loadTemplate = function(scope, templateFileName, settings, internalTemplate) {

    handlebars.setMoboSettings(settings);

    var templateName = templateFileName.substr(0, templateFileName.lastIndexOf('.'));
    var template = scope[templateName + 'Template'];

    // If the template is not loaded already, do so:
    if (!template) {

        var filePath;

        // If it is an internal template fetch it from /lib/templates/*
        if (internalTemplate) {
            filePath = path.join(__dirname, './../templates/' + templateFileName);
        } else {
            filePath = path.join(settings.templateDir, templateFileName);
        }

        try {
            var file = fs.readFileSync(filePath).toString();
            template = handlebars.compile(file);
        } catch (e) {
            log('[E] Could not load template: ' + filePath);
        }
    }

    return template;
};