2018-08-17 13:58:44 +03:00
|
|
|
const Model = require('../models/page');
|
2019-01-25 02:23:00 +03:00
|
|
|
const Alias = require('../models/alias');
|
2018-08-17 13:58:44 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @class Pages
|
|
|
|
* @classdesc Pages controller
|
|
|
|
*/
|
|
|
|
class Pages {
|
|
|
|
/**
|
|
|
|
* @static
|
|
|
|
* Fields required for page model creation
|
|
|
|
*
|
|
|
|
* @returns {['title', 'body']}
|
|
|
|
*/
|
|
|
|
static get REQUIRED_FIELDS() {
|
2018-10-04 22:08:21 +03:00
|
|
|
return [ 'body' ];
|
2018-08-17 13:58:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @static
|
|
|
|
* Find and return page model with passed id
|
|
|
|
*
|
|
|
|
* @param {string} id - page id
|
|
|
|
* @returns {Promise<Page>}
|
|
|
|
*/
|
|
|
|
static async get(id) {
|
|
|
|
const page = await Model.get(id);
|
|
|
|
|
|
|
|
if (!page._id) {
|
|
|
|
throw new Error('Page with given id does not exist');
|
|
|
|
}
|
|
|
|
|
|
|
|
return page;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return all pages
|
|
|
|
*
|
|
|
|
* @returns {Promise<Page[]>}
|
|
|
|
*/
|
|
|
|
static async getAll() {
|
|
|
|
return Model.getAll();
|
|
|
|
}
|
|
|
|
|
2019-01-14 17:53:10 +03:00
|
|
|
/**
|
|
|
|
* @static
|
|
|
|
* Return all pages without children of passed page
|
|
|
|
*
|
|
|
|
* @param {string} parent - id of current page
|
|
|
|
* @returns {Promise<Page[]>}
|
|
|
|
*/
|
|
|
|
static async getAllExceptChildrens(parent) {
|
|
|
|
let pagesAvailable = this.removeChildren(await Pages.getAll(), parent);
|
|
|
|
|
|
|
|
return pagesAvailable.filter((item) => item !== null);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @static
|
|
|
|
* Set all children elements to null
|
|
|
|
*
|
|
|
|
* @param {Page[]} [pagesAvailable] - Array of all pages
|
|
|
|
* @param {string} parent - id of parent page
|
|
|
|
* @returns {Array<?Page>}
|
|
|
|
*/
|
|
|
|
static removeChildren(pagesAvailable, parent) {
|
|
|
|
pagesAvailable.forEach(async (item, index) => {
|
|
|
|
if (item === null || item._parent !== parent) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pagesAvailable[index] = null;
|
|
|
|
pagesAvailable = Pages.removeChildren(pagesAvailable, item._id);
|
|
|
|
});
|
|
|
|
return pagesAvailable;
|
|
|
|
}
|
|
|
|
|
2018-08-17 13:58:44 +03:00
|
|
|
/**
|
|
|
|
* Create new page model and save it in the database
|
|
|
|
*
|
|
|
|
* @param {PageData} data
|
|
|
|
* @returns {Promise<Page>}
|
|
|
|
*/
|
|
|
|
static async insert(data) {
|
2018-10-04 22:08:21 +03:00
|
|
|
try {
|
|
|
|
Pages.validate(data);
|
2018-08-17 13:58:44 +03:00
|
|
|
|
2018-10-04 22:08:21 +03:00
|
|
|
const page = new Model(data);
|
2018-08-17 13:58:44 +03:00
|
|
|
|
2019-01-25 02:23:00 +03:00
|
|
|
const insertedPage = await page.save();
|
|
|
|
|
|
|
|
if (insertedPage.uri) {
|
|
|
|
const alias = new Alias({
|
|
|
|
id: insertedPage._id,
|
|
|
|
type: Alias.types.PAGE
|
|
|
|
}, insertedPage.uri);
|
|
|
|
|
|
|
|
alias.save();
|
|
|
|
}
|
|
|
|
|
|
|
|
return insertedPage;
|
2018-10-04 22:08:21 +03:00
|
|
|
} catch (validationError) {
|
|
|
|
throw new Error(validationError);
|
|
|
|
}
|
2018-08-17 13:58:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check PageData object for required fields
|
|
|
|
*
|
|
|
|
* @param {PageData} data
|
2018-10-04 22:08:21 +03:00
|
|
|
* @throws {Error} - validation error
|
2018-08-17 13:58:44 +03:00
|
|
|
*/
|
|
|
|
static validate(data) {
|
2018-10-04 22:08:21 +03:00
|
|
|
const allRequiredFields = Pages.REQUIRED_FIELDS.every(field => typeof data[field] !== 'undefined');
|
|
|
|
|
|
|
|
if (!allRequiredFields) {
|
|
|
|
throw new Error('Some of required fields is missed');
|
|
|
|
}
|
|
|
|
|
|
|
|
const hasBlocks = data.body && data.body.blocks && Array.isArray(data.body.blocks) && data.body.blocks.length > 0;
|
|
|
|
|
|
|
|
if (!hasBlocks) {
|
|
|
|
throw new Error('Page body is invalid');
|
|
|
|
}
|
|
|
|
|
|
|
|
const hasHeaderAsFirstBlock = data.body.blocks[0].type === 'header';
|
|
|
|
|
|
|
|
if (!hasHeaderAsFirstBlock) {
|
|
|
|
throw new Error('First page Block must be a Header');
|
|
|
|
}
|
|
|
|
|
|
|
|
const headerIsNotEmpty = data.body.blocks[0].data.text.replace('<br>', '').trim() !== '';
|
|
|
|
|
|
|
|
if (!headerIsNotEmpty) {
|
|
|
|
throw new Error('Please, fill page Header');
|
|
|
|
}
|
2018-08-17 13:58:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update page with given id in the database
|
|
|
|
*
|
|
|
|
* @param {string} id - page id
|
|
|
|
* @param {PageData} data
|
|
|
|
* @returns {Promise<Page>}
|
|
|
|
*/
|
|
|
|
static async update(id, data) {
|
|
|
|
const page = await Model.get(id);
|
2019-01-25 02:23:00 +03:00
|
|
|
const previousUri = page.uri;
|
2018-08-17 13:58:44 +03:00
|
|
|
|
|
|
|
if (!page._id) {
|
|
|
|
throw new Error('Page with given id does not exist');
|
|
|
|
}
|
|
|
|
|
2019-01-25 02:23:00 +03:00
|
|
|
if (data.uri && !data.uri.match(/^[a-z0-9'-]+$/i)) {
|
|
|
|
throw new Error('Uri has unexpected characters');
|
|
|
|
}
|
|
|
|
|
2018-08-17 13:58:44 +03:00
|
|
|
page.data = data;
|
2019-01-25 02:23:00 +03:00
|
|
|
const updatedPage = await page.save();
|
|
|
|
|
|
|
|
if (updatedPage.uri !== previousUri) {
|
|
|
|
if (updatedPage.uri) {
|
|
|
|
const alias = new Alias({
|
|
|
|
id: updatedPage._id,
|
|
|
|
type: Alias.types.PAGE
|
|
|
|
}, updatedPage.uri);
|
|
|
|
|
|
|
|
alias.save();
|
|
|
|
}
|
|
|
|
|
|
|
|
Alias.markAsDeprecated(previousUri);
|
|
|
|
}
|
|
|
|
|
|
|
|
return updatedPage;
|
2018-08-17 13:58:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove page with given id from the database
|
|
|
|
*
|
|
|
|
* @param {string} id - page id
|
|
|
|
* @returns {Promise<Page>}
|
|
|
|
*/
|
|
|
|
static async remove(id) {
|
|
|
|
const page = await Model.get(id);
|
|
|
|
|
|
|
|
if (!page._id) {
|
|
|
|
throw new Error('Page with given id does not exist');
|
|
|
|
}
|
|
|
|
|
2019-01-25 06:19:37 +03:00
|
|
|
const alias = await Alias.get(page.uri);
|
|
|
|
|
|
|
|
await alias.destroy();
|
|
|
|
|
2018-08-17 13:58:44 +03:00
|
|
|
return page.destroy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = Pages;
|