keystone
Version:
Web Application Framework and Admin GUI / Content Management System built on Express.js and Mongoose
185 lines (176 loc) • 5.48 kB
JavaScript
var FieldType = require('../Type');
var util = require('util');
var utils = require('keystone-utils');
var addPresenceToQuery = require('../../utils/addPresenceToQuery');
/**
* TextArray FieldType Constructor
* @extends Field
* @api public
*/
function textarray (list, path, options) {
this._nativeType = [String];
this._underscoreMethods = ['format'];
this.separator = options.separator || ' | ';
textarray.super_.call(this, list, path, options);
}
textarray.properName = 'TextArray';
util.inherits(textarray, FieldType);
/**
* Formats the field value
*/
textarray.prototype.format = function (item, separator) {
return item.get(this.path).join(separator || this.separator);
};
/**
* Add filters to a query
*
* @param {Object} filter The data from the frontend
* @param {String} filter.mode The filter mode, either one of
* "beginsWith", "endsWith", "exactly"
* or "contains"
* @param {String} [filter.presence='some'] The presence mode, either on of
* "none" and "some". Default: 'some'
* @param {String|Object} filter.value The value that is filtered for
*/
textarray.prototype.addFilterToQuery = function (filter) {
var query = {};
var presence = filter.presence || 'some';
// Filter empty/non-empty arrays
if (!filter.value) {
// "At least one element contains nothing"
// This isn't 100% accurate because this will only return arrays that
// don't have elements, not ones that have empty elements, but it works
// fine for 99% of the usecase
query[this.path] = presence === 'some' ? {
$size: 0,
// "No elements contain nothing"
} : {
$not: {
$size: 0,
},
};
return query;
}
var value = utils.escapeRegExp(filter.value);
if (filter.mode === 'beginsWith') {
value = '^' + value;
} else if (filter.mode === 'endsWith') {
value = value + '$';
} else if (filter.mode === 'exactly') {
value = '^' + value + '$';
}
value = new RegExp(value, filter.caseSensitive ? '' : 'i');
if (presence === 'none') {
query[this.path] = addPresenceToQuery(presence, value);
} else {
query[this.path] = addPresenceToQuery(presence, {
$regex: value,
});
}
return query;
};
/**
* Asynchronously confirms that the provided value is valid
*/
textarray.prototype.validateInput = function (data, callback) {
var value = this.getValueFromData(data);
var result = true;
// If the value is null, undefined or an empty string
// bail early since updateItem sanitizes that just fine
if (value !== undefined && value !== null && value !== '') {
// If the value is not an array, convert it to one
// e.g. if textarr = 'somestring' (which is valid)
if (!Array.isArray(value)) {
value = [value];
}
for (var i = 0; i < value.length; i++) {
var thisValue = value[i];
// If the current value is not a string and is neither false nor
// undefined, fail the validation
if (typeof thisValue !== 'string') {
result = false;
break;
}
}
}
utils.defer(callback, result);
};
/**
* Asynchronously confirms that the a value is present
*/
textarray.prototype.validateRequiredInput = function (item, data, callback) {
var value = this.getValueFromData(data);
var result = false;
// If the value is undefined and we have something stored already, validate
if (value === undefined) {
if (item.get(this.path) && item.get(this.path).length) {
result = true;
}
}
// If it's a string that's not empty, validate
if (typeof value === 'string') {
if (value !== '') {
result = true;
}
// If it's an array of only strings and/or strinigfy-able data, validate
} else if (Array.isArray(value)) {
var invalidContent = false;
for (var i = 0; i < value.length; i++) {
var thisValue = value[i];
// If even a single item is not a string or an empty string, invalidate
if (typeof thisValue !== 'string' || thisValue === '') {
invalidContent = true;
break;
}
}
if (invalidContent === false) {
result = true;
}
}
utils.defer(callback, result);
};
/**
* Validates that a value for this field has been provided in a data object
*
* Deprecated
*/
textarray.prototype.inputIsValid = function (data, required, item) {
var value = this.getValueFromData(data);
if (required) {
if (value === undefined && item && item.get(this.path) && item.get(this.path).length) {
return true;
}
if (value === undefined || !Array.isArray(value) || (typeof value !== 'string') || (typeof value !== 'number')) {
return false;
}
if (Array.isArray(value) && !value.length) {
return false;
}
}
return (value === undefined || Array.isArray(value) || (typeof value === 'string') || (typeof value === 'number'));
};
/**
* Updates the value for this field in the item from a data object.
* If the data object does not contain the value, then the value is set to empty array.
*/
textarray.prototype.updateItem = function (item, data, callback) {
var value = this.getValueFromData(data);
if (value === undefined || value === null || value === '') {
value = [];
}
if (!Array.isArray(value)) {
value = [value];
}
value = value.map(function (str) {
if (str && str.toString) {
str = str.toString();
}
return str;
}).filter(function (str) {
return (typeof str === 'string' && str);
});
item.set(this.path, value);
process.nextTick(callback);
};
/* Export Field Type */
module.exports = textarray;