diff --git a/lib-es5/utils/index.js b/lib-es5/utils/index.js index 6a5e59e2..5b0bd22c 100644 --- a/lib-es5/utils/index.js +++ b/lib-es5/utils/index.js @@ -347,16 +347,53 @@ function encode_key_value(arg) { }).join('|'); } -function encode_context(arg) { - if (!isObject(arg)) { - return arg; +/** + * @description Escape = and | with two backslashes \\ + * @param {string|number} value + * @return {string} + */ +function escapeMetadataValue(value) { + return value.toString().replace(/([=|])/g, '\\$&'); +} + +/** + * + * @description Encode metadata fields based on incoming value. + * If array, escape as color_id=[\"green\",\"red\"] + * If string/number, escape as in_stock_id=50 + * + * Joins resulting values with a pipe: + * in_stock_id=50|color_id=[\"green\",\"red\"] + * + * = and | and escaped by default (this can't be turned off) + * + * @param metadataObj + * @return {string} + */ +function encode_context(metadataObj) { + if (!isObject(metadataObj)) { + return metadataObj; } - return entries(arg).map(function (_ref3) { - var _ref4 = _slicedToArray(_ref3, 2), - k = _ref4[0], - v = _ref4[1]; - return `${k}=${v.replace(/([=|])/g, '\\$&')}`; + return entries(metadataObj).map(function (_ref3) { + var _ref4 = _slicedToArray(_ref3, 2), + key = _ref4[0], + value = _ref4[1]; + + // if string, simply parse the value and move on + if (isString(value)) { + return `${key}=${escapeMetadataValue(value)}`; + + // If array, parse each item individually + } else if (isArray(value)) { + var values = value.map(function (innerVal) { + return `\"${escapeMetadataValue(innerVal)}\"`; + }).join(','); + return `${key}=[${values}]`; + // if unknown, return the value as string + } else { + return value.toString(); + } }).join('|'); } diff --git a/lib/utils/index.js b/lib/utils/index.js index 940d7f84..d121c3c5 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -320,9 +320,50 @@ function encode_key_value(arg) { return entries(arg).map(([k, v]) => `${k}=${v}`).join('|'); } -function encode_context(arg) { - if (!isObject(arg)) { return arg; } - return entries(arg).map(([k, v]) => `${k}=${v.replace(/([=|])/g, '\\$&')}`).join('|'); + +/** + * @description Escape = and | with two backslashes \\ + * @param {string|number} value + * @return {string} + */ +function escapeMetadataValue(value) { + return value.toString().replace(/([=|])/g, '\\$&'); +} + + +/** + * + * @description Encode metadata fields based on incoming value. + * If array, escape as color_id=[\"green\",\"red\"] + * If string/number, escape as in_stock_id=50 + * + * Joins resulting values with a pipe: + * in_stock_id=50|color_id=[\"green\",\"red\"] + * + * = and | and escaped by default (this can't be turned off) + * + * @param metadataObj + * @return {string} + */ +function encode_context(metadataObj) { + if (!isObject(metadataObj)) { return metadataObj; } + + return entries(metadataObj).map(([key, value]) => { + // if string, simply parse the value and move on + if (isString(value)) { + return `${key}=${escapeMetadataValue(value)}`; + + // If array, parse each item individually + } else if (isArray(value)) { + let values = value.map((innerVal) => { + return `\"${escapeMetadataValue(innerVal)}\"` + }).join(','); + return `${key}=[${values}]` + // if unknown, return the value as string + } else { + return value.toString(); + } + }).join('|'); } function build_eager(transformations) { diff --git a/test/integration/api/admin/structured_metadata_spec.js b/test/integration/api/admin/structured_metadata_spec.js index aaf50688..3dd5bafb 100644 --- a/test/integration/api/admin/structured_metadata_spec.js +++ b/test/integration/api/admin/structured_metadata_spec.js @@ -15,6 +15,7 @@ const EXTERNAL_ID_ENUM_2 = 'metadata_external_id_enum_2_' + TEST_ID; const EXTERNAL_ID_SET = 'metadata_external_id_set_' + TEST_ID; const EXTERNAL_ID_SET_2 = 'metadata_external_id_set_2_' + TEST_ID; const EXTERNAL_ID_SET_3 = 'metadata_external_id_set_3_' + TEST_ID; +const EXTERNAL_ID_SET_4 = 'metadata_external_id_set_4_' + TEST_ID; const EXTERNAL_ID_DELETE = 'metadata_deletion_' + TEST_ID; const EXTERNAL_ID_DELETE_2 = 'metadata_deletion_2_' + TEST_ID; const EXTERNAL_ID_DATE_VALIDATION = 'metadata_date_validation_' + TEST_ID; @@ -414,4 +415,29 @@ describe("structured metadata api", function () { }); }); }); + + it('Should update an metadata field that is an array', (done) => { + let metadata = { + "external_id": EXTERNAL_ID_SET_4, + "label": EXTERNAL_ID_SET_4, + "type": "set", + "datasource": { + "values": [ + { + "external_id": "1", + "value": "Email", + "state": "active" + } + ] + } + }; + + api.add_metadata_field(metadata, (res, res2) => { + cloudinary.v2.uploader.update_metadata({[EXTERNAL_ID_SET_4]: [1]}, ['sample'], (err, res) => { + expect(typeof err).to.be('undefined'); + expect(res.public_ids[0]).to.equal('sample'); + done(); + }) + }); + }); });