'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://.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;