Merge pull request #8824 from owncloud/mail_template_editing_in_webui

minimal mail template editor for administrators
This commit is contained in:
Morris Jobke 2014-06-04 18:44:44 +02:00
commit 7a20d22daa
10 changed files with 457 additions and 0 deletions

View file

@ -0,0 +1,25 @@
<?php
namespace OCA\Files_Sharing\App;
use \OCP\AppFramework\App;
use \OCA\Files_Sharing\Controller\AdminSettingsController;
class Sharing extends App {
public function __construct(array $urlParams=array()){
parent::__construct('files_sharing', $urlParams);
$container = $this->getContainer();
/**
* Controllers
*/
$container->registerService('AdminSettingsController', function($c) {
return new AdminSettingsController(
$c->query('AppName'),
$c->query('Request')
);
});
}
}

View file

@ -21,6 +21,9 @@ OCP\Util::addScript('files_sharing', 'share');
\OC_Hook::connect('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Shared_Updater', 'renameHook');
\OC_Hook::connect('OC_Appconfig', 'post_set_value', '\OCA\Files\Share\Maintainer', 'configChangeHook');
// Register settings scripts for mail template editing
OCP\App::registerAdmin('files_sharing', 'settings-admin');
OC_FileProxy::register(new OCA\Files\Share\Proxy());
\OCA\Files\App::getNavigationManager()->add(

View file

@ -5,6 +5,21 @@ $this->create('core_ajax_public_preview', '/publicpreview')->action(
require_once __DIR__ . '/../ajax/publicpreview.php';
});
use \OCA\Files_Sharing\App\Sharing;
$app = new Sharing();
$app->registerRoutes($this, array('routes' => array(
// mailTemplate settings
array('name' => 'admin_settings#render', 'url' => '/settings/mailtemplate', 'verb' => 'GET'),
array('name' => 'admin_settings#update', 'url' => '/settings/mailtemplate', 'verb' => 'POST'),
array('name' => 'admin_settings#reset', 'url' => '/settings/mailtemplate', 'verb' => 'DELETE')
)));
// OCS API
//TODO: SET: mail notification, waiting for PR #4689 to be accepted

View file

@ -0,0 +1,60 @@
<?php
namespace OCA\Files_Sharing\Controller;
use \OCP\AppFramework\ApiController;
use \OCP\IRequest;
use \OCP\AppFramework\Http\JSONResponse;
class AdminSettingsController extends ApiController {
public function __construct($appName, IRequest $request) {
parent::__construct($appName, $request);
}
/**
* @param string $theme
* @param string $template
* @return \OCA\Files_Sharing\Http\MailTemplateResponse
*/
public function render( $theme, $template ) {
try {
$template = new \OCA\Files_Sharing\MailTemplate( $theme, $template );
return $template->getResponse();
} catch (\Exception $ex) {
return new JSONResponse(array('message' => $ex->getMessage()), $ex->getCode());
}
}
/**
* @param string $theme
* @param string $template
* @param string $content
* @return JSONResponse
*/
public function update( $theme, $template, $content ) {
try {
$template = new \OCA\Files_Sharing\MailTemplate( $theme, $template );
$template->setContent( $content );
return new JSONResponse();
} catch (\Exception $ex) {
return new JSONResponse(array('message' => $ex->getMessage()), $ex->getCode());
}
}
/**
* @param string $theme
* @param string $template
* @return JSONResponse
*/
public function reset( $theme, $template ) {
try {
$template = new \OCA\Files_Sharing\MailTemplate( $theme, $template );
$template->reset();
return new JSONResponse();
} catch (\Exception $ex) {
return new JSONResponse(array('message' => $ex->getMessage()), $ex->getCode());
}
}
}

View file

@ -0,0 +1,33 @@
#mailTemplateSettings .actions div {
display: inline-block;
}
#mailTemplateSettings div label {
display: block
}
#mailTemplateSettings textarea {
box-sizing: border-box;
width: 100%;
height: 150px;
}
#mailTemplateSettings .templateEditor + .actions {
height:28px;
}
#mailTemplateSettings .actions .reset {
margin: 0;
}
#mailTemplateSettings .actions .save {
float: right;
margin: 0;
}
#mailTemplateSettings #mts-msg {
float: right;
margin: 1px 5px;
padding:3px;
}

View file

@ -0,0 +1,55 @@
<?php
/**
* ownCloud - App Framework
*
* @author Jörn Dreyer
* @copyright 2014 Jörn Dreyer <jfd@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Files_Sharing\Http;
/**
* Prompts the user to download the a file
*/
class MailTemplateResponse extends \OCP\AppFramework\Http\Response {
private $filename;
private $contentType;
/**
* Creates a response that prompts the user to download the file
* @param string $filename the name that the downloaded file should have
* @param string $contentType the mimetype that the downloaded file should have
*/
public function __construct($filename, $contentType = 'text/php') {
$this->filename = $filename;
$this->contentType = $contentType;
$this->addHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
$this->addHeader('Content-Type', $contentType);
}
/**
* Returns the raw template content
* @return string the file
*/
public function render(){
return file_get_contents($this->filename);
}
}

View file

@ -0,0 +1,78 @@
$(document).ready(function() {
var loadTemplate = function (theme, template) {
$.get(
OC.generateUrl('apps/files_sharing/settings/mailtemplate'),
{ theme: theme, template: template }
).done(function( result ) {
$( '#mailTemplateSettings textarea' ).val(result);
}).fail(function( result ) {
OC.dialogs.alert(result.message, t('files_sharing', 'Could not load template'));
});
};
// load default template
var theme = $( '#mts-theme' ).val();
var template = $( '#mts-template' ).val();
loadTemplate(theme, template);
$( '#mts-template' ).change(
function() {
var theme = $( '#mts-theme' ).val();
var template = $( this ).val();
loadTemplate(theme, template);
}
);
$( '#mts-theme' ).change(
function() {
var theme = $( this ).val();
var template = $( '#mts-template' ).val();
loadTemplate(theme, template);
}
);
$( '#mailTemplateSettings .actions' ).on('click', '.save',
function() {
var theme = $( '#mts-theme' ).val();
var template = $( '#mts-template' ).val();
var content = $( '#mailTemplateSettings textarea' ).val();
OC.msg.startSaving('#mts-msg');
$.post(
OC.generateUrl('apps/files_sharing/settings/mailtemplate'),
{ theme: theme, template: template, content: content }
).done(function() {
var data = { status:'success', data:{message:t('files_sharing', 'Saved')} };
OC.msg.finishedSaving('#mts-msg', data);
}).fail(function(result) {
var data = { status: 'error', data:{message:result.responseJSON.message} };
OC.msg.finishedSaving('#mts-msg', data);
});
}
);
$( '#mailTemplateSettings .actions' ).on('click', '.reset',
function() {
var theme = $( '#mts-theme' ).val();
var template = $( '#mts-template' ).val();
OC.msg.startSaving('#mts-msg');
$.ajax({
type: "DELETE",
url: OC.generateUrl('apps/files_sharing/settings/mailtemplate'),
data: { theme: theme, template: template }
}).done(function() {
var data = { status:'success', data:{message:t('files_sharing', 'Reset')} };
OC.msg.finishedSaving('#mts-msg', data);
// load default template
var theme = $( '#mts-theme' ).val();
var template = $( '#mts-template' ).val();
loadTemplate(theme, template);
}).fail(function(result) {
var data = { status: 'error', data:{message:result.responseJSON.message} };
OC.msg.finishedSaving('#mts-msg', data);
});
}
);
});

View file

@ -0,0 +1,126 @@
<?php
namespace OCA\Files_Sharing;
use \OCP\Files\NotPermittedException;
use \OC\AppFramework\Middleware\Security\SecurityException;
use OCA\Files_Sharing\Http\MailTemplateResponse;
class MailTemplate extends \OC_Template {
private $path;
private $theme;
private $editableThemes;
private $editableTemplates;
public function __construct($theme, $path) {
$this->theme = $theme;
$this->path = $path;
//determine valid theme names
$this->editableThemes = self::getEditableThemes();
//for now hard code the valid mail template paths
$this->editableTemplates = self::getEditableTemplates();
}
/**
*
* @return \OCA\Files_Sharing\Http\MailTemplateResponse
*/
public function getResponse() {
if($this->isEditable()) {
list($app, $filename) = explode('/templates/', $this->path, 2);
$name = substr($filename, 0, -4);
list($path, $template) = $this->findTemplate($this->theme, $app, $name, '');
return new MailTemplateResponse($template);
}
throw new SecurityException('Template not editable.', 403);
}
public function renderContent() {
if($this->isEditable()) {
list($app, $filename) = explode('/templates/', $this->path, 2);
$name = substr($filename, 0, -4);
list($path, $template) = $this->findTemplate($this->theme, $app, $name, '');
\OC_Response::sendFile($template);
} else {
throw new SecurityException('Template not editable.', 403);
}
}
public function isEditable() {
if ($this->editableThemes[$this->theme]
&& $this->editableTemplates[$this->path]
) {
return true;
}
return false;
}
public function setContent($data) {
if($this->isEditable()) {
//save default templates in default folder to overwrite core template
$absolutePath = \OC::$SERVERROOT.'/themes/'.$this->theme.'/'.$this->path;
$parent = dirname($absolutePath);
if ( ! is_dir($parent) ) {
if ( ! mkdir(dirname($absolutePath), 0777, true) ){
throw new \Exception('Could not create directory.', 500);
}
}
if ( $this->theme !== 'default' && is_file($absolutePath) ) {
if ( ! copy($absolutePath, $absolutePath.'.bak') ){
throw new \Exception('Could not overwrite template.', 500);
}
}
//overwrite theme templates? versioning?
return file_put_contents($absolutePath, $data);
}
throw new SecurityException('Template not editable.', 403);
}
public function reset(){
if($this->isEditable()) {
$absolutePath = \OC::$SERVERROOT.'/themes/'.$this->theme.'/'.$this->path;
if ($this->theme === 'default') {
//templates can simply be deleted in the themes folder
if (unlink($absolutePath)) {
return true;
}
} else {
//if a bak file exists overwrite the template with it
if (is_file($absolutePath.'.bak')) {
if (rename($absolutePath.'.bak', $absolutePath)) {
return true;
}
}
}
return false;
}
throw new NotPermittedException('Template not editable.', 403);
}
public static function getEditableThemes() {
$themes = array(
'default' => true
);
if ($handle = opendir(\OC::$SERVERROOT.'/themes')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != '.' && $entry != '..' && $entry != 'default') {
if (is_dir(\OC::$SERVERROOT.'/themes/'.$entry)) {
$themes[$entry] = true;
}
}
}
closedir($handle);
}
return $themes;
}
public static function getEditableTemplates() {
return array(
'core/templates/mail.php' => true,
'core/templates/altmail.php' => true,
'core/lostpassword/templates/email.php' => true,
);
}
}

View file

@ -0,0 +1,21 @@
<?php
/**
* Copyright (c) 2011 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
\OC_Util::checkAdminUser();
\OCP\Util::addStyle('files_sharing', 'settings-admin');
\OCP\Util::addScript('files_sharing', 'settings-admin');
$themes = \OCA\Files_Sharing\MailTemplate::getEditableThemes();
$editableTemplates = \OCA\Files_Sharing\MailTemplate::getEditableTemplates();
$tmpl = new OCP\Template('files_sharing', 'settings-admin');
$tmpl->assign('themes', $themes);
$tmpl->assign('editableTemplates', $editableTemplates);
return $tmpl->fetchPage();

View file

@ -0,0 +1,41 @@
<div class="section" id="mailTemplateSettings" >
<h2><?php p($l->t('Mail templates'));?></h2>
<div class="actions">
<div>
<label for="mts-theme"><?php p($l->t('Theme'));?></label>
<select id="mts-theme">
<?php foreach($_['themes'] as $theme => $editable): ?>
<option><?php p($theme); ?></option>
<?php endforeach; ?>
</select>
</div>
<div>
<label for="mts-template"><?php p($l->t('Template'));?></label>
<select id="mts-template">
<?php foreach($_['editableTemplates'] as $template => $editable): ?>
<option><?php p($template); ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="templateEditor">
<textarea></textarea>
</div>
<div class="actions">
<button class="reset"><?php p($l->t('Reset'));?></button>
<button class="save"><?php p($l->t('Save'));?></button>
<span id="mts-msg" class="msg"></span>
</div>
</div>