From 01aab6c2fbbc22d13b7e5187e829fda64661e636 Mon Sep 17 00:00:00 2001 From: Egil Moeller Date: Fri, 12 Mar 2010 21:44:29 +0100 Subject: Plugins can now provide pages --- trunk/etherpad/src/etherpad/admin/plugins.js | 35 ++++++++----- trunk/etherpad/src/etherpad/utils.js | 48 ++++++++++-------- trunk/etherpad/src/main.js | 2 +- .../plugins/testplugin/controllers/testplugin.js | 57 ++++++++++++++++++++++ trunk/etherpad/src/plugins/testplugin/main.js | 14 +++--- .../plugins/testplugin/templates/testplugin.ejs | 28 +++++++++++ 6 files changed, 145 insertions(+), 39 deletions(-) create mode 100644 trunk/etherpad/src/plugins/testplugin/controllers/testplugin.js create mode 100644 trunk/etherpad/src/plugins/testplugin/templates/testplugin.ejs diff --git a/trunk/etherpad/src/etherpad/admin/plugins.js b/trunk/etherpad/src/etherpad/admin/plugins.js index f48dbb5..af66833 100644 --- a/trunk/etherpad/src/etherpad/admin/plugins.js +++ b/trunk/etherpad/src/etherpad/admin/plugins.js @@ -157,26 +157,39 @@ function enablePlugin(pluginName) { function disablePlugin(pluginName) { loadPlugins(); - pluginModules[pluginName].uninstall(); - var pluginHooks = plugins[pluginName].map(function (x) { return x; }); // copy array + try + { + pluginModules[pluginName].uninstall(); + } catch (e) { + log.info({errorUninstallingPlugin:exceptionutils.getStackTracePlain(e)}); + } + if (plugins[pluginName] != undefined) { + var pluginHooks = plugins[pluginName].map(function (x) { return x; }); // copy array - for (pluginHook in pluginHooks) - unregisterHook(pluginName, pluginHooks[pluginHook].hookName); - delete plugins[pluginName]; - sqlobj.deleteRows("plugin", {name:pluginName}); + for (pluginHook in pluginHooks) + unregisterHook(pluginName, pluginHooks[pluginHook].hookName); + } + delete plugins[pluginName]; + sqlobj.deleteRows("plugin", {name:pluginName}); } function callHook(hookName, args) { loadPlugins(); -log.info({XYZZZZ:hooks, NANANA:hookName}); if (hooks[hookName] === undefined) return []; - return hooks[hookName].map( - function (plugin) { - return pluginModules[plugin.pluginName][plugin.originalHook || hookName](args); - }); + var res = []; + for (i = 0; i < hooks[hookName].length; i++) { + var plugin = hooks[hookName][i]; + var pluginRes = pluginModules[plugin.pluginName][plugin.originalHook || hookName](args); + if (pluginRes != undefined && pluginRes != null) + res = res.concat(pluginRes); + } + return res; } function callHookStr(hookName, args, sep, pre, post) { + if (sep == undefined) sep = ''; + if (pre == undefined) pre = ''; + if (post == undefined) post = ''; return callHook(hookName, args).map(function (x) { return pre + x + post}).join(sep || ""); } diff --git a/trunk/etherpad/src/etherpad/utils.js b/trunk/etherpad/src/etherpad/utils.js index da9972f..8e572dd 100644 --- a/trunk/etherpad/src/etherpad/utils.js +++ b/trunk/etherpad/src/etherpad/utils.js @@ -34,6 +34,7 @@ import("etherpad.pro.pro_utils"); import("etherpad.pro.pro_config"); import("etherpad.pro.pro_accounts"); import("etherpad.pro.pro_accounts.getSessionProAccount"); +import("etherpad.log"); jimport("java.lang.System.out.print"); jimport("java.lang.System.out.println"); @@ -55,11 +56,18 @@ function randomUniquePadId() { // template rendering //---------------------------------------------------------------- -function renderTemplateAsString(filename, data) { +function findTemplate(filename, plugin) { + if (plugin != undefined) + return '/plugins/' + plugin + '/templates/' + filename; + else + return '/templates/' + filename; +} + +function renderTemplateAsString(filename, data, plugin) { data = data || {}; data.helpers = helpers; // global helpers - var f = "/templates/"+filename; + var f = findTemplate(filename, plugin); //"/templates/"+filename; if (! appjet.scopeCache.ejs) { appjet.scopeCache.ejs = {}; } @@ -75,22 +83,22 @@ function renderTemplateAsString(filename, data) { return html; } -function renderTemplate(filename, data) { - response.write(renderTemplateAsString(filename, data)); +function renderTemplate(filename, data, plugin) { + response.write(renderTemplateAsString(filename, data, plugin)); if (request.acceptsGzip) { response.setGzip(true); } } -function renderHtml(bodyFileName, data) { - var bodyHtml = renderTemplateAsString(bodyFileName, data); +function renderHtml(bodyFileName, data, plugin) { + var bodyHtml = renderTemplateAsString(bodyFileName, data, plugin); response.write(renderTemplateAsString("html.ejs", {bodyHtml: bodyHtml})); if (request.acceptsGzip) { response.setGzip(true); } } -function renderFramedHtml(contentHtml) { +function renderFramedHtml(contentHtml, plugin) { var getContentHtml; if (typeof(contentHtml) == 'function') { getContentHtml = contentHtml; @@ -109,52 +117,52 @@ function renderFramedHtml(contentHtml) { getContentHtml: getContentHtml, isProDomainRequest: isProDomainRequest(), renderGlobalProNotice: pro_utils.renderGlobalProNotice - }); + }, plugin); } -function renderFramed(bodyFileName, data) { +function renderFramed(bodyFileName, data, plugin) { function _getContentHtml() { - return renderTemplateAsString(bodyFileName, data); + return renderTemplateAsString(bodyFileName, data, plugin); } renderFramedHtml(_getContentHtml); } -function renderFramedError(error) { +function renderFramedError(error, plugin) { var content = DIV({className: 'fpcontent'}, DIV({style: "padding: 2em 1em;"}, DIV({style: "padding: 1em; border: 1px solid #faa; background: #fdd;"}, B("Error: "), error))); - renderFramedHtml(content); + renderFramedHtml(content, plugin); } -function renderNotice(bodyFileName, data) { - renderNoticeString(renderTemplateAsString(bodyFileName, data)); +function renderNotice(bodyFileName, data, plugin) { + renderNoticeString(renderTemplateAsString(bodyFileName, data, plugin), plugin); } -function renderNoticeString(contentHtml) { - renderFramed("notice.ejs", {content: contentHtml}); +function renderNoticeString(contentHtml, plugin) { + renderFramed("notice.ejs", {content: contentHtml}, plugin); } -function render404(noStop) { +function render404(noStop, plugin) { response.reset(); response.setStatusCode(404); renderFramedHtml(DIV({className: "fpcontent"}, DIV({style: "padding: 2em 1em;"}, DIV({style: "border: 1px solid #aaf; background: #def; padding: 1em; font-size: 150%;"}, - "404 not found: "+request.path)))); + "404 not found: "+request.path))), plugin); if (! noStop) { response.stop(); } } -function render500(ex) { +function render500(ex, plugin) { response.reset(); response.setStatusCode(500); var trace = null; if (ex && (!isProduction())) { trace = exceptionutils.getStackTracePlain(ex); } - renderFramed("500_body.ejs", {trace: trace}); + renderFramed("500_body.ejs", {trace: trace}, plugin); } function _renderEtherpadDotComHeader(data) { diff --git a/trunk/etherpad/src/main.js b/trunk/etherpad/src/main.js index cf07829..6d79af1 100644 --- a/trunk/etherpad/src/main.js +++ b/trunk/etherpad/src/main.js @@ -374,7 +374,7 @@ function handlePath() { [DirMatcher('/ep/unit-tests/'), forward(testcontrol)], [DirMatcher('/ep/pne-manual/'), forward(pne_manual_control)], [DirMatcher('/ep/pro-help/'), forward(pro_help_control)] - ]); + ].concat(plugins.callHook('handlePath'))); var etherpadDotComDispatcher = new Dispatcher(); etherpadDotComDispatcher.addLocations([ diff --git a/trunk/etherpad/src/plugins/testplugin/controllers/testplugin.js b/trunk/etherpad/src/plugins/testplugin/controllers/testplugin.js new file mode 100644 index 0000000..0c79e06 --- /dev/null +++ b/trunk/etherpad/src/plugins/testplugin/controllers/testplugin.js @@ -0,0 +1,57 @@ +/** + * Copyright 2009 RedHog, Egil Möller + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS-IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import("faststatic"); +import("dispatch.{Dispatcher,PrefixMatcher,forward}"); + +import("etherpad.utils.*"); +import("etherpad.collab.server_utils"); +import("etherpad.globals.*"); +import("etherpad.log"); +import("etherpad.pad.padusers"); +import("etherpad.pro.pro_utils"); +import("etherpad.helpers"); +import("etherpad.pro.pro_accounts.getSessionProAccount"); +import("sqlbase.sqlbase"); +import("sqlbase.sqlcommon"); +import("sqlbase.sqlobj"); + + +function onRequest() { + var isPro = pro_utils.isProDomainRequest(); + var userId = padusers.getUserId(); + + helpers.addClientVars({ + userAgent: request.headers["User-Agent"], + debugEnabled: request.params.djs, + clientIp: request.clientAddr, + colorPalette: COLOR_PALETTE, + serverTimestamp: +(new Date), + isProPad: isPro, + userIsGuest: padusers.isGuest(userId), + userId: userId, + }); + + var isProUser = (isPro && ! padusers.isGuest(userId)); + + renderHtml("testplugin.ejs", + { + isPro: isPro, + isProAccountHolder: isProUser, + account: getSessionProAccount(), // may be falsy + }, 'testplugin'); + return true; +} diff --git a/trunk/etherpad/src/plugins/testplugin/main.js b/trunk/etherpad/src/plugins/testplugin/main.js index 589c60c..f5d736b 100644 --- a/trunk/etherpad/src/plugins/testplugin/main.js +++ b/trunk/etherpad/src/plugins/testplugin/main.js @@ -1,7 +1,9 @@ import("etherpad.log"); import("etherpad.admin.plugins"); +import("dispatch.{Dispatcher,PrefixMatcher,forward}"); +import("plugins.testplugin.controllers.testplugin"); -hooks = ['testhook', 'nahook', 'serverStartup', 'serverShutdown']; +hooks = ['serverStartup', 'serverShutdown', 'handlePath']; description = 'Test Plugin'; function install() { @@ -12,12 +14,6 @@ function uninstall() { log.info("Uninstalling testplugin"); } -function testhook () { -} - -function nahook() { -} - function serverStartup() { log.info("Server startup for testplugin"); } @@ -25,3 +21,7 @@ function serverStartup() { function serverShutdown() { log.info("Server shutdown for testplugin"); } + +function handlePath() { + return [[PrefixMatcher('/ep/testplugin/'), forward(testplugin)]]; +} \ No newline at end of file diff --git a/trunk/etherpad/src/plugins/testplugin/templates/testplugin.ejs b/trunk/etherpad/src/plugins/testplugin/templates/testplugin.ejs new file mode 100644 index 0000000..e529982 --- /dev/null +++ b/trunk/etherpad/src/plugins/testplugin/templates/testplugin.ejs @@ -0,0 +1,28 @@ +<% /* Copyright 2009 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS-IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ %> +<% + helpers.setHtmlTitle("Test plugin"); + helpers.setBodyId("padbody"); + helpers.addBodyClass("limwidth nonpropad nonprouser"); + helpers.includeCss("pad2_ejs.css"); + helpers.setRobotsPolicy({index: false, follow: false}) + helpers.includeJQuery(); + helpers.includeCometJs(); + helpers.includeJs("json2.js"); + helpers.addToHead('\n\n'); +%> + +
+ Welcome to the test plugin +
-- cgit v1.2.3