2015-06-07 06:19:19 +03:00
|
|
|
import BaseValidator from './base';
|
2017-04-11 16:39:45 +03:00
|
|
|
import moment from 'moment';
|
2019-01-22 16:09:38 +03:00
|
|
|
import validator from 'validator';
|
2018-03-19 20:56:09 +03:00
|
|
|
import {isBlank, isEmpty, isPresent} from '@ember/utils';
|
2015-06-07 06:19:19 +03:00
|
|
|
|
2015-08-19 14:55:40 +03:00
|
|
|
export default BaseValidator.create({
|
2017-08-03 14:45:14 +03:00
|
|
|
properties: [
|
|
|
|
'title',
|
2018-03-13 14:17:29 +03:00
|
|
|
'authors',
|
2017-08-03 14:45:14 +03:00
|
|
|
'customExcerpt',
|
2019-03-12 13:40:07 +03:00
|
|
|
'canonicalUrl',
|
2017-08-03 14:45:14 +03:00
|
|
|
'codeinjectionHead',
|
|
|
|
'codeinjectionFoot',
|
|
|
|
'metaTitle',
|
|
|
|
'metaDescription',
|
|
|
|
'ogtitle',
|
|
|
|
'ogDescription',
|
|
|
|
'twitterTitle',
|
|
|
|
'twitterDescription',
|
|
|
|
'publishedAtBlogTime',
|
2019-11-04 09:15:13 +03:00
|
|
|
'publishedAtBlogDate',
|
2021-06-10 22:42:32 +03:00
|
|
|
'emailSubject',
|
|
|
|
'featureImageAlt'
|
2017-08-03 14:45:14 +03:00
|
|
|
],
|
2015-06-07 06:19:19 +03:00
|
|
|
|
2015-10-28 14:36:45 +03:00
|
|
|
title(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
if (isBlank(model.title)) {
|
|
|
|
model.errors.add('title', 'You must specify a title for the post.');
|
2015-06-07 06:19:19 +03:00
|
|
|
this.invalidate();
|
2014-09-21 22:56:30 +04:00
|
|
|
}
|
2015-08-29 22:02:06 +03:00
|
|
|
|
2019-03-12 13:40:07 +03:00
|
|
|
if (!validator.isLength(model.title || '', 0, 255)) {
|
|
|
|
model.errors.add('title', 'Title cannot be longer than 255 characters.');
|
2015-08-29 22:02:06 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
2015-06-07 06:19:19 +03:00
|
|
|
},
|
2014-09-21 22:56:30 +04:00
|
|
|
|
2018-03-13 14:17:29 +03:00
|
|
|
authors(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
if (isEmpty(model.authors)) {
|
|
|
|
model.errors.add('authors', 'At least one author is required.');
|
|
|
|
this.invalidate();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
canonicalUrl(model) {
|
|
|
|
let validatorOptions = {require_protocol: true};
|
|
|
|
let urlRegex = new RegExp(/^(\/|[a-zA-Z0-9-]+:)/);
|
|
|
|
let url = model.canonicalUrl;
|
2018-03-13 14:17:29 +03:00
|
|
|
|
2019-03-12 13:40:07 +03:00
|
|
|
if (isBlank(url)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (url.match(/\s/) || (!validator.isURL(url, validatorOptions) && !url.match(urlRegex))) {
|
|
|
|
model.errors.add('canonicalUrl', 'Please enter a valid URL');
|
|
|
|
this.invalidate();
|
|
|
|
} else if (!validator.isLength(model.canonicalUrl, 0, 2000)) {
|
|
|
|
model.errors.add('canonicalUrl', 'Canonical URL is too long, max 2000 chars');
|
2018-03-13 14:17:29 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-08-01 11:24:46 +03:00
|
|
|
customExcerpt(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
if (!validator.isLength(model.customExcerpt || '', 0, 300)) {
|
|
|
|
model.errors.add('customExcerpt', 'Excerpt cannot be longer than 300 characters.');
|
2017-08-01 11:24:46 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
2021-06-23 21:45:17 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
visibility(model) {
|
|
|
|
if (isBlank(model.visibility) && !model.isNew) {
|
2021-07-19 13:38:51 +03:00
|
|
|
model.errors.add('visibility', 'Please select at least one tier');
|
2021-06-23 21:45:17 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
2021-07-02 19:27:18 +03:00
|
|
|
},
|
|
|
|
|
2022-02-01 09:54:06 +03:00
|
|
|
tiers(model) {
|
|
|
|
if (model.visibility === 'tiers' && !model.isNew && isEmpty(model.tiers)) {
|
|
|
|
model.errors.add('tiers', 'Please select at least one tier');
|
2021-07-02 19:27:18 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
2017-08-01 11:24:46 +03:00
|
|
|
},
|
|
|
|
|
2017-08-02 12:32:51 +03:00
|
|
|
codeinjectionFoot(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
if (!validator.isLength(model.codeinjectionFoot || '', 0, 65535)) {
|
|
|
|
model.errors.add('codeinjectionFoot', 'Footer code cannot be longer than 65535 characters.');
|
2017-08-02 12:32:51 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
codeinjectionHead(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
if (!validator.isLength(model.codeinjectionHead || '', 0, 65535)) {
|
|
|
|
model.errors.add('codeinjectionHead', 'Header code cannot be longer than 65535 characters.');
|
2017-08-02 12:32:51 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2015-10-28 14:36:45 +03:00
|
|
|
metaTitle(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
if (!validator.isLength(model.metaTitle || '', 0, 300)) {
|
|
|
|
model.errors.add('metaTitle', 'Meta Title cannot be longer than 300 characters.');
|
2015-06-07 06:19:19 +03:00
|
|
|
this.invalidate();
|
2014-09-21 22:56:30 +04:00
|
|
|
}
|
2015-06-07 06:19:19 +03:00
|
|
|
},
|
|
|
|
|
2015-10-28 14:36:45 +03:00
|
|
|
metaDescription(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
if (!validator.isLength(model.metaDescription || '', 0, 500)) {
|
|
|
|
model.errors.add('metaDescription', 'Meta Description cannot be longer than 500 characters.');
|
2015-06-07 06:19:19 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
2017-04-11 16:39:45 +03:00
|
|
|
},
|
|
|
|
|
2017-08-03 14:45:14 +03:00
|
|
|
ogTitle(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
if (!validator.isLength(model.ogTitle || '', 0, 300)) {
|
|
|
|
model.errors.add('ogTitle', 'Facebook Title cannot be longer than 300 characters.');
|
2017-08-03 14:45:14 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
ogDescription(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
if (!validator.isLength(model.ogDescription || '', 0, 500)) {
|
|
|
|
model.errors.add('ogDescription', 'Facebook Description cannot be longer than 500 characters.');
|
2017-08-03 14:45:14 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
twitterTitle(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
if (!validator.isLength(model.twitterTitle || '', 0, 300)) {
|
|
|
|
model.errors.add('twitterTitle', 'Twitter Title cannot be longer than 300 characters.');
|
2017-08-03 14:45:14 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
twitterDescription(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
if (!validator.isLength(model.twitterDescription || '', 0, 500)) {
|
|
|
|
model.errors.add('twitterDescription', 'Twitter Description cannot be longer than 500 characters.');
|
2017-08-03 14:45:14 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
|
|
|
},
|
2019-11-04 09:15:13 +03:00
|
|
|
|
|
|
|
emailSubject(model) {
|
|
|
|
if (!validator.isLength(model.emailSubject || '', 0, 300)) {
|
|
|
|
model.errors.add('emailSubject', 'Email Subject cannot be longer than 300 characters.');
|
|
|
|
this.invalidate();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-04-11 16:39:45 +03:00
|
|
|
// for posts which haven't been published before and where the blog date/time
|
|
|
|
// is blank we should ignore the validation
|
|
|
|
_shouldValidatePublishedAtBlog(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
return isPresent(model.publishedAtUTC)
|
|
|
|
|| isPresent(model.publishedAtBlogDate)
|
|
|
|
|| isPresent(model.publishedAtBlogTime);
|
2017-04-11 16:39:45 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
// convenience method as .validate({property: 'x'}) doesn't accept multiple properties
|
|
|
|
publishedAtBlog(model) {
|
|
|
|
this.publishedAtBlogTime(model);
|
|
|
|
this.publishedAtBlogDate(model);
|
|
|
|
},
|
|
|
|
|
|
|
|
publishedAtBlogTime(model) {
|
|
|
|
let timeRegex = /^(([0-1]?[0-9])|([2][0-3])):([0-5][0-9])$/;
|
|
|
|
|
2019-03-12 13:40:07 +03:00
|
|
|
if (!timeRegex.test(model.publishedAtBlogTime) && this._shouldValidatePublishedAtBlog(model)) {
|
|
|
|
model.errors.add('publishedAtBlogTime', 'Must be in format: "15:00"');
|
2017-04-11 16:39:45 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
publishedAtBlogDate(model) {
|
2019-03-12 13:40:07 +03:00
|
|
|
let publishedAtBlogDate = model.publishedAtBlogDate;
|
|
|
|
let publishedAtBlogTime = model.publishedAtBlogTime;
|
2017-04-11 16:39:45 +03:00
|
|
|
|
|
|
|
if (!this._shouldValidatePublishedAtBlog(model)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we have a time string but no date string
|
2018-03-19 20:56:09 +03:00
|
|
|
if (isBlank(publishedAtBlogDate) && !isBlank(publishedAtBlogTime)) {
|
2019-03-12 13:40:07 +03:00
|
|
|
model.errors.add('publishedAtBlogDate', 'Can\'t be blank');
|
2017-04-11 16:39:45 +03:00
|
|
|
return this.invalidate();
|
|
|
|
}
|
|
|
|
|
|
|
|
// don't validate the date if the time format is incorrect
|
2019-03-12 13:40:07 +03:00
|
|
|
if (isEmpty(model.errors.errorsFor('publishedAtBlogTime'))) {
|
|
|
|
let status = model.statusScratch || model.status;
|
2017-04-11 16:39:45 +03:00
|
|
|
let now = moment();
|
2019-03-12 13:40:07 +03:00
|
|
|
let publishedAtBlogTZ = model.publishedAtBlogTZ;
|
2017-04-11 16:39:45 +03:00
|
|
|
let isInFuture = publishedAtBlogTZ.isSameOrAfter(now.add(2, 'minutes'));
|
|
|
|
|
|
|
|
// draft/published must be in past
|
|
|
|
if ((status === 'draft' || status === 'published') && publishedAtBlogTZ.isSameOrAfter(now)) {
|
2019-03-12 13:40:07 +03:00
|
|
|
model.errors.add('publishedAtBlogDate', 'Must be in the past');
|
2017-04-11 16:39:45 +03:00
|
|
|
this.invalidate();
|
|
|
|
|
2022-05-20 01:11:01 +03:00
|
|
|
// scheduled must be at least 2 mins in the future when first scheduling
|
|
|
|
} else if ((model.changedAttributes().status || model.changedAttributes().publishedAtUTC) && status === 'scheduled' && !isInFuture) {
|
2019-03-12 13:40:07 +03:00
|
|
|
model.errors.add('publishedAtBlogDate', 'Must be at least 2 mins in the future');
|
2017-04-11 16:39:45 +03:00
|
|
|
this.invalidate();
|
|
|
|
}
|
|
|
|
}
|
2021-06-10 22:42:32 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
featureImageAlt(model) {
|
|
|
|
if (!validator.isLength(model.featureImageAlt || '', 0, 125)) {
|
|
|
|
model.errors.add('featureImageAlt', 'Feature image alt text cannot be longer than 125 characters.');
|
|
|
|
this.invalidate();
|
|
|
|
}
|
2014-06-21 01:36:44 +04:00
|
|
|
}
|
|
|
|
});
|