mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Merge pull request #1996 from JohnONolan/plugins-to-apps
Rename 'plugins' to 'apps'
This commit is contained in:
commit
0dd06f7938
18 changed files with 193 additions and 193 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -43,7 +43,7 @@ projectFilesBackup
|
|||
/_site
|
||||
/content/tmp/*
|
||||
/content/data/*
|
||||
/content/plugins/**/*
|
||||
/content/apps/**/*
|
||||
/content/themes/**/*
|
||||
/content/images/**/*
|
||||
!/content/themes/casper/**
|
||||
|
|
|
@ -23,8 +23,8 @@ var path = require('path'),
|
|||
'content/images/README.md',
|
||||
'!content/themes/**',
|
||||
'content/themes/casper/**',
|
||||
'!content/plugins/**',
|
||||
'content/plugins/README.md',
|
||||
'!content/apps/**',
|
||||
'content/apps/README.md',
|
||||
'!node_modules/**',
|
||||
'!core/test/**',
|
||||
'!core/client/assets/sass/**',
|
||||
|
|
3
content/apps/README.md
Normal file
3
content/apps/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Content / Apps
|
||||
|
||||
Coming soon, Ghost apps will appear here.
|
|
@ -1,3 +0,0 @@
|
|||
# Content / Plugins
|
||||
|
||||
Coming soon, Ghost plugins will appear here.
|
92
core/server/apps/index.js
Normal file
92
core/server/apps/index.js
Normal file
|
@ -0,0 +1,92 @@
|
|||
|
||||
var _ = require('underscore'),
|
||||
when = require('when'),
|
||||
errors = require('../errorHandling'),
|
||||
api = require('../api'),
|
||||
loader = require('./loader'),
|
||||
// Holds the available apps
|
||||
availableApps = {};
|
||||
|
||||
|
||||
function getInstalledApps() {
|
||||
return api.settings.read('installedApps').then(function (installed) {
|
||||
installed.value = installed.value || '[]';
|
||||
|
||||
try {
|
||||
installed = JSON.parse(installed.value);
|
||||
} catch (e) {
|
||||
return when.reject(e);
|
||||
}
|
||||
|
||||
return installed;
|
||||
});
|
||||
}
|
||||
|
||||
function saveInstalledApps(installedApps) {
|
||||
return getInstalledApps().then(function (currentInstalledApps) {
|
||||
var updatedAppsInstalled = _.uniq(installedApps.concat(currentInstalledApps));
|
||||
|
||||
return api.settings.edit('installedApps', updatedAppsInstalled);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function () {
|
||||
var appsToLoad;
|
||||
|
||||
try {
|
||||
// We have to parse the value because it's a string
|
||||
api.settings.read('activeApps').then(function (aApps) {
|
||||
appsToLoad = JSON.parse(aApps.value) || [];
|
||||
});
|
||||
} catch (e) {
|
||||
errors.logError(
|
||||
'Failed to parse activeApps setting value: ' + e.message,
|
||||
'Your apps will not be loaded.',
|
||||
'Check your settings table for typos in the activeApps value. It should look like: ["app-1", "app2"] (double quotes required).'
|
||||
);
|
||||
return when.resolve();
|
||||
}
|
||||
|
||||
// Grab all installed apps, install any not already installed that are in appsToLoad.
|
||||
return getInstalledApps().then(function (installedApps) {
|
||||
var loadedApps = {},
|
||||
recordLoadedApp = function (name, loadedApp) {
|
||||
// After loading the app, add it to our hash of loaded apps
|
||||
loadedApps[name] = loadedApp;
|
||||
|
||||
return when.resolve(loadedApp);
|
||||
},
|
||||
loadPromises = _.map(appsToLoad, function (app) {
|
||||
// If already installed, just activate the app
|
||||
if (_.contains(installedApps, app)) {
|
||||
return loader.activateAppByName(app).then(function (loadedApp) {
|
||||
return recordLoadedApp(app, loadedApp);
|
||||
});
|
||||
}
|
||||
|
||||
// Install, then activate the app
|
||||
return loader.installAppByName(app).then(function () {
|
||||
return loader.activateAppByName(app);
|
||||
}).then(function (loadedApp) {
|
||||
return recordLoadedApp(app, loadedApp);
|
||||
});
|
||||
});
|
||||
|
||||
return when.all(loadPromises).then(function () {
|
||||
// Save our installed apps to settings
|
||||
return saveInstalledApps(_.keys(loadedApps));
|
||||
}).then(function () {
|
||||
// Extend the loadedApps onto the available apps
|
||||
_.extend(availableApps, loadedApps);
|
||||
}).otherwise(function (err) {
|
||||
errors.logError(
|
||||
err.message || err,
|
||||
'The app will not be loaded',
|
||||
'Check with the app creator, or read the app documentation for more details on app requirements'
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
availableApps: availableApps
|
||||
};
|
70
core/server/apps/loader.js
Normal file
70
core/server/apps/loader.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
|
||||
var path = require('path'),
|
||||
_ = require('underscore'),
|
||||
when = require('when'),
|
||||
appProxy = require('./proxy'),
|
||||
config = require('../config'),
|
||||
loader;
|
||||
|
||||
|
||||
|
||||
// Get a relative path to the given apps root, defaults
|
||||
// to be relative to __dirname
|
||||
function getAppRelativePath(name, relativeTo) {
|
||||
relativeTo = relativeTo || __dirname;
|
||||
|
||||
return path.relative(relativeTo, path.join(config.paths().appPath, name));
|
||||
}
|
||||
|
||||
|
||||
function getAppByName(name) {
|
||||
// Grab the app class to instantiate
|
||||
var AppClass = require(getAppRelativePath(name)),
|
||||
app;
|
||||
|
||||
// Check for an actual class, otherwise just use whatever was returned
|
||||
if (_.isFunction(AppClass)) {
|
||||
app = new AppClass(appProxy);
|
||||
} else {
|
||||
app = AppClass;
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
// The loader is responsible for loading apps
|
||||
loader = {
|
||||
// Load a app and return the instantiated app
|
||||
installAppByName: function (name) {
|
||||
var app = getAppByName(name);
|
||||
|
||||
// Check for an install() method on the app.
|
||||
if (!_.isFunction(app.install)) {
|
||||
return when.reject(new Error("Error loading app named " + name + "; no install() method defined."));
|
||||
}
|
||||
|
||||
// Wrapping the install() with a when because it's possible
|
||||
// to not return a promise from it.
|
||||
return when(app.install(appProxy)).then(function () {
|
||||
return when.resolve(app);
|
||||
});
|
||||
},
|
||||
|
||||
// Activate a app and return it
|
||||
activateAppByName: function (name) {
|
||||
var app = getAppByName(name);
|
||||
|
||||
// Check for an activate() method on the app.
|
||||
if (!_.isFunction(app.activate)) {
|
||||
return when.reject(new Error("Error loading app named " + name + "; no activate() method defined."));
|
||||
}
|
||||
|
||||
// Wrapping the activate() with a when because it's possible
|
||||
// to not return a promise from it.
|
||||
return when(app.activate(appProxy)).then(function () {
|
||||
return when.resolve(app);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = loader;
|
|
@ -11,14 +11,14 @@ var moment = require('moment'),
|
|||
corePath = path.resolve(appRoot, 'core/'),
|
||||
contentPath = path.resolve(appRoot, 'content/'),
|
||||
themePath = path.resolve(contentPath + '/themes'),
|
||||
pluginPath = path.resolve(contentPath + '/plugins'),
|
||||
appPath = path.resolve(contentPath + '/apps'),
|
||||
themeDirectories = requireTree(themePath),
|
||||
pluginDirectories = requireTree(pluginPath),
|
||||
appDirectories = requireTree(appPath),
|
||||
localPath = '',
|
||||
configUrl = '',
|
||||
|
||||
availableThemes,
|
||||
availablePlugins;
|
||||
availableApps;
|
||||
|
||||
|
||||
function paths() {
|
||||
|
@ -32,7 +32,7 @@ function paths() {
|
|||
'contentPath': contentPath,
|
||||
'corePath': corePath,
|
||||
'themePath': themePath,
|
||||
'pluginPath': pluginPath,
|
||||
'appPath': appPath,
|
||||
'imagesPath': path.resolve(contentPath, 'images/'),
|
||||
'imagesRelPath': 'content/images',
|
||||
'adminViews': path.join(corePath, '/server/views/'),
|
||||
|
@ -41,7 +41,7 @@ function paths() {
|
|||
'lang': path.join(corePath, '/shared/lang/'),
|
||||
'debugPath': subdir + '/ghost/debug/',
|
||||
'availableThemes': availableThemes,
|
||||
'availablePlugins': availablePlugins
|
||||
'availableApps': availableApps
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -56,9 +56,9 @@ function update(configURL) {
|
|||
localPath = localPath.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
return when.all([themeDirectories, pluginDirectories]).then(function (paths) {
|
||||
return when.all([themeDirectories, appDirectories]).then(function (paths) {
|
||||
availableThemes = paths[0];
|
||||
availablePlugins = paths[1];
|
||||
availableApps = paths[1];
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -68,11 +68,11 @@
|
|||
"defaultValue": "casper"
|
||||
}
|
||||
},
|
||||
"plugin": {
|
||||
"activePlugins": {
|
||||
"app": {
|
||||
"activeApps": {
|
||||
"defaultValue": "[]"
|
||||
},
|
||||
"installedPlugins": {
|
||||
"installedApps": {
|
||||
"defaultValue": "[]"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ var crypto = require('crypto'),
|
|||
middleware = require('./middleware'),
|
||||
models = require('./models'),
|
||||
permissions = require('./permissions'),
|
||||
plugins = require('./plugins'),
|
||||
apps = require('./apps'),
|
||||
routes = require('./routes'),
|
||||
packageInfo = require('../../package.json'),
|
||||
|
||||
|
@ -71,7 +71,7 @@ function initDbHashAndFirstRun() {
|
|||
}
|
||||
|
||||
// Sets up the express server instance.
|
||||
// Instantiates the ghost singleton, helpers, routes, middleware, and plugins.
|
||||
// Instantiates the ghost singleton, helpers, routes, middleware, and apps.
|
||||
// Finally it starts the http server.
|
||||
function setup(server) {
|
||||
|
||||
|
@ -200,8 +200,8 @@ function setup(server) {
|
|||
|
||||
}
|
||||
|
||||
// Initialize plugins then start the server
|
||||
plugins.init().then(function () {
|
||||
// Initialize apps then start the server
|
||||
apps.init().then(function () {
|
||||
|
||||
// ## Start Ghost App
|
||||
if (getSocket()) {
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
|
||||
var _ = require('underscore'),
|
||||
when = require('when'),
|
||||
errors = require('../errorHandling'),
|
||||
api = require('../api'),
|
||||
loader = require('./loader'),
|
||||
// Holds the available plugins
|
||||
availablePlugins = {};
|
||||
|
||||
|
||||
function getInstalledPlugins() {
|
||||
return api.settings.read('installedPlugins').then(function (installed) {
|
||||
installed.value = installed.value || '[]';
|
||||
|
||||
try {
|
||||
installed = JSON.parse(installed.value);
|
||||
} catch (e) {
|
||||
return when.reject(e);
|
||||
}
|
||||
|
||||
return installed;
|
||||
});
|
||||
}
|
||||
|
||||
function saveInstalledPlugins(installedPlugins) {
|
||||
return getInstalledPlugins().then(function (currentInstalledPlugins) {
|
||||
var updatedPluginsInstalled = _.uniq(installedPlugins.concat(currentInstalledPlugins));
|
||||
|
||||
return api.settings.edit('installedPlugins', updatedPluginsInstalled);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function () {
|
||||
var pluginsToLoad;
|
||||
|
||||
try {
|
||||
// We have to parse the value because it's a string
|
||||
api.settings.read('activePlugins').then(function (aPlugins) {
|
||||
pluginsToLoad = JSON.parse(aPlugins.value) || [];
|
||||
});
|
||||
} catch (e) {
|
||||
errors.logError(
|
||||
'Failed to parse activePlugins setting value: ' + e.message,
|
||||
'Your plugins will not be loaded.',
|
||||
'Check your settings table for typos in the activePlugins value. It should look like: ["plugin-1", "plugin2"] (double quotes required).'
|
||||
);
|
||||
return when.resolve();
|
||||
}
|
||||
|
||||
// Grab all installed plugins, install any not already installed that are in pluginsToLoad.
|
||||
return getInstalledPlugins().then(function (installedPlugins) {
|
||||
var loadedPlugins = {},
|
||||
recordLoadedPlugin = function (name, loadedPlugin) {
|
||||
// After loading the plugin, add it to our hash of loaded plugins
|
||||
loadedPlugins[name] = loadedPlugin;
|
||||
|
||||
return when.resolve(loadedPlugin);
|
||||
},
|
||||
loadPromises = _.map(pluginsToLoad, function (plugin) {
|
||||
// If already installed, just activate the plugin
|
||||
if (_.contains(installedPlugins, plugin)) {
|
||||
return loader.activatePluginByName(plugin).then(function (loadedPlugin) {
|
||||
return recordLoadedPlugin(plugin, loadedPlugin);
|
||||
});
|
||||
}
|
||||
|
||||
// Install, then activate the plugin
|
||||
return loader.installPluginByName(plugin).then(function () {
|
||||
return loader.activatePluginByName(plugin);
|
||||
}).then(function (loadedPlugin) {
|
||||
return recordLoadedPlugin(plugin, loadedPlugin);
|
||||
});
|
||||
});
|
||||
|
||||
return when.all(loadPromises).then(function () {
|
||||
// Save our installed plugins to settings
|
||||
return saveInstalledPlugins(_.keys(loadedPlugins));
|
||||
}).then(function () {
|
||||
// Extend the loadedPlugins onto the available plugins
|
||||
_.extend(availablePlugins, loadedPlugins);
|
||||
}).otherwise(function (err) {
|
||||
errors.logError(
|
||||
err.message || err,
|
||||
'The plugin will not be loaded',
|
||||
'Check with the plugin creator, or read the plugin documentation for more details on plugin requirements'
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
availablePlugins: availablePlugins
|
||||
};
|
|
@ -1,70 +0,0 @@
|
|||
|
||||
var path = require('path'),
|
||||
_ = require('underscore'),
|
||||
when = require('when'),
|
||||
appProxy = require('./proxy'),
|
||||
config = require('../config'),
|
||||
loader;
|
||||
|
||||
|
||||
|
||||
// Get a relative path to the given plugins root, defaults
|
||||
// to be relative to __dirname
|
||||
function getPluginRelativePath(name, relativeTo) {
|
||||
relativeTo = relativeTo || __dirname;
|
||||
|
||||
return path.relative(relativeTo, path.join(config.paths().pluginPath, name));
|
||||
}
|
||||
|
||||
|
||||
function getPluginByName(name) {
|
||||
// Grab the plugin class to instantiate
|
||||
var PluginClass = require(getPluginRelativePath(name)),
|
||||
plugin;
|
||||
|
||||
// Check for an actual class, otherwise just use whatever was returned
|
||||
if (_.isFunction(PluginClass)) {
|
||||
plugin = new PluginClass(appProxy);
|
||||
} else {
|
||||
plugin = PluginClass;
|
||||
}
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
// The loader is responsible for loading plugins
|
||||
loader = {
|
||||
// Load a plugin and return the instantiated plugin
|
||||
installPluginByName: function (name) {
|
||||
var plugin = getPluginByName(name);
|
||||
|
||||
// Check for an install() method on the plugin.
|
||||
if (!_.isFunction(plugin.install)) {
|
||||
return when.reject(new Error("Error loading plugin named " + name + "; no install() method defined."));
|
||||
}
|
||||
|
||||
// Wrapping the install() with a when because it's possible
|
||||
// to not return a promise from it.
|
||||
return when(plugin.install(appProxy)).then(function () {
|
||||
return when.resolve(plugin);
|
||||
});
|
||||
},
|
||||
|
||||
// Activate a plugin and return it
|
||||
activatePluginByName: function (name) {
|
||||
var plugin = getPluginByName(name);
|
||||
|
||||
// Check for an activate() method on the plugin.
|
||||
if (!_.isFunction(plugin.activate)) {
|
||||
return when.reject(new Error("Error loading plugin named " + name + "; no activate() method defined."));
|
||||
}
|
||||
|
||||
// Wrapping the activate() with a when because it's possible
|
||||
// to not return a promise from it.
|
||||
return when(plugin.activate(appProxy)).then(function () {
|
||||
return when.resolve(plugin);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = loader;
|
|
@ -2,7 +2,7 @@ var errors = require('../errorHandling'),
|
|||
storage;
|
||||
|
||||
function get_storage() {
|
||||
// TODO: this is where the check for storage plugins should go
|
||||
// TODO: this is where the check for storage apps should go
|
||||
// Local file system is the default
|
||||
var storageChoice = 'localfilesystem';
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
// - post count - total number of posts
|
||||
// - user count - total number of users
|
||||
// - theme - name of the currently active theme
|
||||
// - apps - names of any active plugins
|
||||
// - apps - names of any active apps
|
||||
|
||||
var crypto = require('crypto'),
|
||||
exec = require('child_process').exec,
|
||||
|
@ -51,7 +51,7 @@ function updateCheckData() {
|
|||
|
||||
ops.push(api.settings.read('dbHash').otherwise(errors.rejectError));
|
||||
ops.push(api.settings.read('activeTheme').otherwise(errors.rejectError));
|
||||
ops.push(api.settings.read('activePlugins')
|
||||
ops.push(api.settings.read('activeApps')
|
||||
.then(function (apps) {
|
||||
try {
|
||||
apps = JSON.parse(apps.value);
|
||||
|
|
|
@ -6,7 +6,7 @@ var should = require('should'),
|
|||
filters = require('../../server/filters'),
|
||||
|
||||
// Stuff we are testing
|
||||
appProxy = require('../../server/plugins/proxy');
|
||||
appProxy = require('../../server/apps/proxy');
|
||||
|
||||
describe('App Proxy', function () {
|
||||
|
|
@ -294,7 +294,7 @@ describe('Config', function () {
|
|||
'contentPath',
|
||||
'corePath',
|
||||
'themePath',
|
||||
'pluginPath',
|
||||
'appPath',
|
||||
'imagesPath',
|
||||
'imagesRelPath',
|
||||
'adminViews',
|
||||
|
@ -303,7 +303,7 @@ describe('Config', function () {
|
|||
'lang',
|
||||
'debugPath',
|
||||
'availableThemes',
|
||||
'availablePlugins'
|
||||
'availableApps'
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ var _ = require('underscore'),
|
|||
'updated_by', 'published_at', 'published_by', 'page', 'author', 'user', 'tags'],
|
||||
// TODO: remove databaseVersion, dbHash
|
||||
settings: ['databaseVersion', 'dbHash', 'title', 'description', 'email', 'logo', 'cover', 'defaultLang',
|
||||
"permalinks", 'postsPerPage', 'forceI18n', 'activeTheme', 'activePlugins', 'installedPlugins',
|
||||
"permalinks", 'postsPerPage', 'forceI18n', 'activeTheme', 'activeApps', 'installedApps',
|
||||
'availableThemes', 'nextUpdateCheck', 'displayUpdateNotification'],
|
||||
tag: ['id', 'uuid', 'name', 'slug', 'description', 'parent_id',
|
||||
'meta_title', 'meta_description', 'created_at', 'created_by', 'updated_at', 'updated_by'],
|
||||
|
|
|
@ -284,9 +284,9 @@
|
|||
{
|
||||
"id": 13,
|
||||
"uuid": "f3afce35-5166-453e-86c3-50dfff74dca7",
|
||||
"key": "activePlugins",
|
||||
"key": "activeApps",
|
||||
"value": "[]",
|
||||
"type": "plugin",
|
||||
"type": "app",
|
||||
"created_at": 1388318310831,
|
||||
"created_by": 1,
|
||||
"updated_at": 1388318310831,
|
||||
|
@ -295,9 +295,9 @@
|
|||
{
|
||||
"id": 14,
|
||||
"uuid": "2ea560a3-2304-449d-a62b-f7b622987510",
|
||||
"key": "installedPlugins",
|
||||
"key": "installedApps",
|
||||
"value": "[]",
|
||||
"type": "plugin",
|
||||
"type": "app",
|
||||
"created_at": 1388318310831,
|
||||
"created_by": 1,
|
||||
"updated_at": 1388318310831,
|
||||
|
|
Loading…
Add table
Reference in a new issue