menu

SFRA / Server-side JS / Source: modules/server/queryString.js

'use strict';

/**
 * Zips the pref[n|v] http query params
 *
 * The Platform allows the use of multiple preference names and values to filter search results,
 * eg.: http://<sandbox>.com/../Search-Show?prefn1=refinementColor&prefv1=Blue&prefn2=size&prefv2=16
 *
 * @param {Object} preferences - HTTP query parameters map specific to selected refinement values
 * @return {Object} Map of provided preference name/value pairs
 */
function parsePreferences(preferences) {
    var params = {};
    var count = Math.floor(Object.keys(preferences).length / 2);
    var key = '';
    var value = '';

    for (var i = 1; i < count + 1; i++) {
        key = preferences['prefn' + i];
        if (preferences['prefmin' + i]) {
            value = {
                min: preferences['prefmin' + i],
                max: preferences['prefmax' + i]
            };
        } else {
            value = preferences['prefv' + i];
        }
        params[key] = value;
    }

    return params;
}

/**
* Detect duplicate parameters and be sure to set object[key] as an array of those parameter values
*
* @param {Object} object The object to check for existing values.
* @param {string} key The key to set on object for the new value.
* @param {string} value The new value to be added to object[key].
* @return {Object} Value or array of values if object[key] has already exists.
*/
function parameterToArray(object, key, value) {
    var result = value;
    if (object[key]) {
        result = object[key];
        if (!(result instanceof Array)) {
            result = [object[key]];
        }
        result.push(value);
    }

    return result;
}

var querystring = function (raw) {
    var pair;
    var left;
    var preferences = {};

    if (raw && raw.length > 0) {
        var qs = raw.substring(raw.indexOf('?') + 1).replace(/\+/g, '%20').split('&');
        for (var i = qs.length - 1; i >= 0; i--) {
            pair = qs[i].split('=');
            left = decodeURIComponent(pair[0]);
            if (left.indexOf('dwvar_') === 0) {
                left = left.replace(/__/g, '++');
                var variableParts = left.split('_');
                if (variableParts.length >= 3) {
                    if (!this.variables) {
                        this.variables = {};
                    }
                    this.variables[variableParts.slice(2).join('_')] = {
                        id: variableParts[1].replace(/\+\+/g, '_'),
                        value: decodeURIComponent(pair[1])
                    };
                    continue; // eslint-disable-line no-continue
                }
            } else if (left.indexOf('dwopt_') === 0) {
                left = left.replace(/__/g, '++');
                var optionParts = left.split('_');
                var productId = optionParts[1].replace(/\+\+/g, '_');
                var optionId = optionParts.slice(2).join('_');
                var selectedOptionValueId = decodeURIComponent(pair[1]);
                if (optionParts.length >= 3) {
                    if (!this.options) {
                        this.options = [];
                    }
                    this.options.push({
                        optionId: optionId,
                        selectedValueId: selectedOptionValueId,
                        productId: productId
                    });
                    continue; // eslint-disable-line no-continue
                }
            } else if (left.indexOf('pref') === 0) {
                preferences[left] = decodeURIComponent(pair[1]);
                continue; // eslint-disable-line no-continue
            }

            this[left] = parameterToArray(this, left, decodeURIComponent(pair[1]));
        }
    }

    if (Object.keys(preferences).length) {
        this.preferences = parsePreferences(preferences);
    }
};

querystring.prototype.toString = function () {
    var result = [];
    var prefKeyIdx = 1;
    var preferences = {};

    Object.keys(this).forEach(function (key) {
        if (key === 'variables' && this.variables instanceof Object) {
            Object.keys(this.variables).forEach(function (variable) {
                result.push('dwvar_' +
                    this.variables[variable].id.replace(/_/g, '__') + '_' +
                    variable + '=' + encodeURIComponent(this.variables[variable].value));
            }, this);
        } else if (key === 'options' && this.options instanceof Array) {
            this.options.forEach(function (option) {
                result.push('dwopt_' +
                    option.productId.replace(/_/g, '__') + '_' +
                    option.optionId + '=' + encodeURIComponent(option.selectedValueId));
            });
        } else if (key === 'preferences' && this.preferences instanceof Object) {
            preferences = this.preferences;
            Object.keys(preferences).forEach(function (prefKey) {
                // Due to the nature of what is passed to this function this may be the literal string "undefined"
                if (prefKey !== 'undefined' && preferences[prefKey]) {
                    result.push('prefn' + prefKeyIdx + '=' + encodeURIComponent(prefKey));
                    if (preferences[prefKey].min) {
                        result.push('prefmin' + prefKeyIdx + '=' + encodeURIComponent(preferences[prefKey].min));
                        result.push('prefmax' + prefKeyIdx + '=' + encodeURIComponent(preferences[prefKey].max));
                    } else {
                        result.push('prefv' + prefKeyIdx + '=' + encodeURIComponent(preferences[prefKey]));
                    }
                } else {
                    var Logger = require('dw/system/Logger');
                    Logger.warn('We were passed a key "undefined in the preferences object in queryString.js');
                }
                prefKeyIdx++;
            });
        } else {
            result.push(encodeURIComponent(key) + '=' + encodeURIComponent(this[key]));
        }
    }, this);

    return result.sort().join('&');
};

module.exports = querystring;

X Privacy Update: We use cookies to make interactions with our websites and services easy and meaningful, to better understand how they are used. By continuing to use this site you are giving us your consent to do this. Privacy Policy.