mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
366a7be36d
refs https://github.com/TryGhost/Team/issues/1579 - When writing to the database, the header_image is tranformed to the transformReady path - When reading from the database, the transformReady path is transformed to an absolute path - Includes a test when adding a newsletter Migration: - Updates all newsletter who have a header_image to make sure it is saved in transform ready format - Down operation is required to work with the old model logic and transforms it back to an absolute format
156 lines
4.4 KiB
JavaScript
156 lines
4.4 KiB
JavaScript
const ghostBookshelf = require('./base');
|
|
const ObjectID = require('bson-objectid');
|
|
const uuid = require('uuid');
|
|
const urlUtils = require('../../shared/url-utils');
|
|
|
|
const Newsletter = ghostBookshelf.Model.extend({
|
|
tableName: 'newsletters',
|
|
|
|
defaults: function defaults() {
|
|
return {
|
|
uuid: uuid.v4(),
|
|
sender_reply_to: 'newsletter',
|
|
status: 'active',
|
|
visibility: 'members',
|
|
subscribe_on_signup: true,
|
|
sort_order: 0,
|
|
title_font_category: 'sans_serif',
|
|
title_alignment: 'center',
|
|
show_feature_image: true,
|
|
body_font_category: 'sans_serif',
|
|
show_badge: true,
|
|
show_header_icon: true,
|
|
show_header_title: true,
|
|
show_header_name: true
|
|
};
|
|
},
|
|
|
|
members() {
|
|
return this.belongsToMany('Member', 'members_newsletters', 'newsletter_id', 'member_id')
|
|
.query((qb) => {
|
|
// avoids bookshelf adding a `DISTINCT` to the query
|
|
// we know the result set will already be unique and DISTINCT hurts query performance
|
|
qb.columns('members.*');
|
|
});
|
|
},
|
|
|
|
posts() {
|
|
return this.hasMany('Post');
|
|
},
|
|
|
|
async onSaving(model, _attr, options) {
|
|
ghostBookshelf.Model.prototype.onSaving.apply(this, arguments);
|
|
|
|
if (model.get('name')) {
|
|
model.set('name', model.get('name').trim());
|
|
}
|
|
|
|
if (model.hasChanged('slug') || !model.get('slug')) {
|
|
const slug = model.get('slug') || model.get('name');
|
|
|
|
if (slug) {
|
|
const cleanSlug = await ghostBookshelf.Model.generateSlug(Newsletter, slug, {
|
|
transacting: options.transacting
|
|
});
|
|
|
|
model.set({slug: cleanSlug});
|
|
}
|
|
}
|
|
},
|
|
|
|
subscribeMembersById(memberIds, unfilteredOptions = {}) {
|
|
let pivotRows = [];
|
|
for (const memberId of memberIds) {
|
|
pivotRows.push({
|
|
id: ObjectID().toHexString(),
|
|
member_id: memberId.id,
|
|
newsletter_id: this.id
|
|
});
|
|
}
|
|
|
|
const query = ghostBookshelf.knex.batchInsert('members_newsletters', pivotRows);
|
|
|
|
if (unfilteredOptions.transacting) {
|
|
query.transacting(unfilteredOptions.transacting);
|
|
}
|
|
|
|
return query;
|
|
},
|
|
|
|
formatOnWrite(attrs) {
|
|
['header_image'].forEach((attr) => {
|
|
if (attrs[attr]) {
|
|
attrs[attr] = urlUtils.toTransformReady(attrs[attr]);
|
|
}
|
|
});
|
|
|
|
return attrs;
|
|
},
|
|
|
|
parse() {
|
|
const attrs = ghostBookshelf.Model.prototype.parse.apply(this, arguments);
|
|
|
|
['header_image'].forEach((attr) => {
|
|
if (attrs[attr]) {
|
|
attrs[attr] = urlUtils.transformReadyToAbsolute(attrs[attr]);
|
|
}
|
|
});
|
|
|
|
return attrs;
|
|
}
|
|
}, {
|
|
orderDefaultRaw: function () {
|
|
return 'sort_order ASC, created_at ASC, id ASC';
|
|
},
|
|
|
|
orderDefaultOptions: function orderDefaultOptions() {
|
|
return {
|
|
sort_order: 'ASC',
|
|
created_at: 'ASC',
|
|
id: 'ASC'
|
|
};
|
|
},
|
|
|
|
getDefaultNewsletter: async function getDefaultNewsletter(unfilteredOptions = {}) {
|
|
const options = {
|
|
filter: 'status:active',
|
|
order: this.orderDefaultRaw(),
|
|
limit: 1
|
|
};
|
|
|
|
if (unfilteredOptions.transacting) {
|
|
options.transacting = unfilteredOptions.transacting;
|
|
}
|
|
|
|
const newsletters = await this.findPage(options);
|
|
|
|
if (newsletters.data.length > 0) {
|
|
return newsletters.data[0];
|
|
}
|
|
return null;
|
|
},
|
|
|
|
getNextAvailableSortOrder: async function getNextAvailableSortOrder(unfilteredOptions = {}) {
|
|
const options = {
|
|
filter: 'status:active',
|
|
order: 'sort_order DESC', // there's no NQL syntax available here
|
|
limit: 1,
|
|
columns: ['sort_order']
|
|
};
|
|
|
|
if (unfilteredOptions.transacting) {
|
|
options.transacting = unfilteredOptions.transacting;
|
|
}
|
|
|
|
const lastNewsletter = await this.findPage(options);
|
|
|
|
if (lastNewsletter.data.length > 0) {
|
|
return lastNewsletter.data[0].get('sort_order') + 1;
|
|
}
|
|
return 0;
|
|
}
|
|
});
|
|
|
|
module.exports = {
|
|
Newsletter: ghostBookshelf.model('Newsletter', Newsletter)
|
|
};
|