function combineQueryParameters(q1, q2, preserveQueryParameters) {
  if (!preserveQueryParameters) {
    return combine(q1, q2);
  }

  const result = clone(q1, true);
  for (const param in q2) {
    if (q2.hasOwnProperty(param)) {
      let value = result[param];
      const q2Value = q2[param];
      if (defined(value)) {
        if (!Array.isArray(value)) {
          value = result[param] = [value];
        }

        result[param] = value.concat(q2Value);
      } else {
        result[param] = Array.isArray(q2Value) ? q2Value.slice() : q2Value;
      }
    }
  }

  return result;
}
This combines a map of query parameters.

@param {object} q1 The first map of query parameters. Values in this map will take precedence if preserveQueryParameters is false.
@param {object} q2 The second map of query parameters.
@param {boolean} preserveQueryParameters If true duplicate parameters will be concatenated into an array. If false, keys in q1 will take precedence.

@returns {object} The combined map of query parameters.

@example
const q1 = {
  a: 1,
  b: 2
};
const q2 = {
  a: 3,
  c: 4
};
const q3 = {
  b: [5, 6],
  d: 7
}

// Returns
// {
//   a: [1, 3],
//   b: 2,
//   c: 4
// };
combineQueryParameters(q1, q2, true);

// Returns
// {
//   a: 1,
//   b: 2,
//   c: 4
// };
combineQueryParameters(q1, q2, false);

// Returns
// {
//   a: 1,
//   b: [2, 5, 6],
//   d: 7
// };
combineQueryParameters(q1, q3, true);

// Returns
// {
//   a: 1,
//   b: 2,
//   d: 7
// };
combineQueryParameters(q1, q3, false);

@private