UNPKG

keystone

Version:

Web Application Framework and Admin GUI / Content Management System built on Express.js and Mongoose

247 lines (176 loc) 4.67 kB
var _ = require('lodash'); var keystone = require('../../'); var utils = keystone.utils; /** * Content Class * * Accessed via `Keystone.content` * * @api public */ var Content = function () {}; /** * Loads page content by page key (optional). * * If page key is not provided, returns a hash of all page contents in the database. * * ####Example: * * keystone.content.fetch('home', function(err, content) { ... }); * * @param {String} key (optional) * @param {Function} callback * @api public */ Content.prototype.fetch = function (page, callback) { if (utils.isFunction(page)) { callback = page; page = null; } var content = this; if (!this.AppContent) { return callback({ error: 'invalid page', message: 'No pages have been registered.' }); } if (page) { if (!this.pages[page]) { return callback({ error: 'invalid page', message: 'The page ' + page + ' does not exist.' }); } this.AppContent.findOne({ key: page }, function (err, result) { if (err) return callback(err); return callback(null, content.pages[page].populate(result ? result.content.data : {})); }); } else { this.AppContent.find(function (err, results) { if (err) return callback(err); var data = {}; results.forEach(function (i) { if (content.pages[i.key]) { data[i.key] = content.pages[i.key].populate(i.content.data); } }); _.forEach(content.pages, function (i) { if (!data[i.key]) { data[i.key] = i.populate(); } }); return data; }); } }; /** * Sets page content by page key. * * Merges content with existing content. * * ####Example: * * keystone.content.store('home', { title: 'Welcome' }, function(err) { ... }); * * @param {String} key * @param {Object} content * @param {Function} callback * @api public */ Content.prototype.store = function (page, content, callback) { if (!this.pages[page]) { return callback({ error: 'invalid page', message: 'The page ' + page + ' does not exist.' }); } content = this.pages[page].validate(content); // TODO: Handle validation errors this.AppContent.findOne({ key: page }, function (err, doc) { if (err) return callback(err); if (doc) { if (doc.content) { doc.history.push(doc.content); } _.defaults(content, doc.content); } else { doc = new content.AppContent({ key: page }); } doc.content = { data: this.pages[page].clean(content) }; doc.lastChangeDate = Date.now(); doc.save(callback); }); }; /** * Registers a page. Should not be called directly, use Page.register() instead. * * @param {Page} page * @api private */ Content.prototype.page = function (key, page) { if (!this.pages) { this.pages = {}; } if (arguments.length === 1) { if (!this.pages[key]) { throw new Error('keystone.content.page() Error: page ' + key + ' cannot be registered more than once.'); } return this.pages[key]; } this.initModel(); if (this.pages[key]) { throw new Error('keystone.content.page() Error: page ' + key + ' cannot be registered more than once.'); } this.pages[key] = page; return page; }; /** * Ensures the Mongoose model for storing content is initialised. * * Called automatically when pages are added. * * @api private */ Content.prototype.initModel = function () { if (this.AppContent) return; var contentSchemaDef = { createdAt: { type: Date, default: Date.now }, data: { type: keystone.mongoose.Schema.Types.Mixed }, }; var ContentSchema = new keystone.mongoose.Schema(contentSchemaDef); var PageSchema = new keystone.mongoose.Schema({ page: { type: String, index: true }, lastChangeDate: { type: Date, index: true }, content: contentSchemaDef, history: [ContentSchema], }, { collection: 'app_content' }); this.AppContent = keystone.mongoose.model('App_Content', PageSchema); }; /** * Outputs client-side editable data for content management * * Called automatically when pages are added. * * @api private */ Content.prototype.editable = function (user, options) { if (!user || !user.canAccessKeystone) { return undefined; } if (options.list) { var list = keystone.list(options.list); if (!list) { return JSON.stringify({ type: 'error', err: 'list not found' }); } var data = { type: 'list', path: list.getAdminURL(), singular: list.singular, plural: list.plural, }; if (options.id) { data.id = options.id; } return JSON.stringify(data); } }; /** * The exports object is an instance of Content. * * @api public */ module.exports = new Content(); // Expose Classes exports.Page = require('./page'); exports.Types = require('./types');