Convert all boolean table columnns to use is_ prefix
Add email template/layout system
This commit is contained in:
parent
9a923e3b98
commit
2b820a20d6
|
|
@ -1,3 +1,7 @@
|
|||
* **Build 101** (2014-06-06)
|
||||
- Added a global traceLog() helper for help with debugging.
|
||||
- New settings area added to manage Email templates and layouts.
|
||||
|
||||
* **Build 99** (2014-06-05)
|
||||
- Plugins can now be removed, refreshed and disabled via the back-end.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use BackendMenu;
|
|||
use BackendAuth;
|
||||
use Backend\Classes\WidgetManager;
|
||||
use October\Rain\Support\ModuleServiceProvider;
|
||||
use System\Models\EmailTemplate;
|
||||
|
||||
class ServiceProvider extends ModuleServiceProvider
|
||||
{
|
||||
|
|
@ -70,6 +71,16 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
'backend.manage_users' => ['label' => 'Manage other administrators', 'tab' => 'System'],
|
||||
]);
|
||||
});
|
||||
|
||||
/*
|
||||
* Register email templates
|
||||
*/
|
||||
EmailTemplate::registerCallback(function($template){
|
||||
$template->registerEmailTemplates([
|
||||
'backend::emails.invite' => 'Invitation for newly created administrators.',
|
||||
'backend::emails.restore' => 'Password reset instructions for backend-end administrators.',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7279,6 +7279,18 @@ label {
|
|||
.form-control.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
.form-preview {
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
background: white;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
.form-preview .form-group {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.form-preview > .form-group:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.form-elements:before,
|
||||
.form-tabless-fields:before,
|
||||
.form-elements:after,
|
||||
|
|
@ -7769,6 +7781,15 @@ label {
|
|||
.select2-drop .select2-results > li > div {
|
||||
padding: 5px 7px 5px;
|
||||
}
|
||||
.list-preview {
|
||||
padding: 20px 0 0;
|
||||
margin-bottom: 20px;
|
||||
background: white;
|
||||
border: 1px solid #e2e2e2;
|
||||
}
|
||||
.list-preview .control-list:last-child > table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.control-list p.no-data {
|
||||
padding: 18px 20px;
|
||||
margin: 0 20px;
|
||||
|
|
@ -8515,7 +8536,7 @@ table.table.data tr.list-tree-level-25 td.list-data-column-1 {
|
|||
.modal-body {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.modal-body p:last-child {
|
||||
.modal-body > p:last-child {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.control-popup.fade .modal-dialog {
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@
|
|||
|
||||
var e = $.Event('showing.oc.inspector')
|
||||
this.$el.trigger(e, [{callback: displayPopover}])
|
||||
if (e.isDefaultPrevented())
|
||||
if (e.isDefaultPrevented())
|
||||
return
|
||||
|
||||
if (!e.isPropagationStopped())
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@
|
|||
* - data-closable - enables the Close Tab feature
|
||||
* - data-pane-classes - a list of CSS classes to apply new pane elements
|
||||
*
|
||||
* Example with data attributes (data-control="tab"):
|
||||
* Example with data attributes (data-control="tab"):
|
||||
*
|
||||
* <div class="control-tabs master" data-control="tab" data-closable>
|
||||
* <ul class="nav nav-tabs">
|
||||
* <li class="active"><a href="#home">Home</a></li>
|
||||
* <li class="active"><a href="#home">Home</a></li>
|
||||
* </ul>
|
||||
* <div class="tab-content">
|
||||
* <div class="tab-pane active">Home</div>
|
||||
* <div class="tab-pane active">Home</div>
|
||||
* </div>
|
||||
* </div>
|
||||
*
|
||||
|
|
|
|||
|
|
@ -22,6 +22,25 @@ label {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Form containers
|
||||
//
|
||||
|
||||
.form-preview {
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
background: white;
|
||||
border: 1px solid #eee;
|
||||
|
||||
.form-group {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
>.form-group:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Nice forms
|
||||
//
|
||||
|
|
|
|||
|
|
@ -51,6 +51,26 @@
|
|||
// </table>
|
||||
// </div>
|
||||
//
|
||||
|
||||
//
|
||||
// List containers
|
||||
//
|
||||
|
||||
.list-preview {
|
||||
padding: 20px 0 0;
|
||||
margin-bottom: 20px;
|
||||
background: white;
|
||||
border: 1px solid @color-list-border;
|
||||
|
||||
.control-list:last-child > table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// List control
|
||||
//
|
||||
|
||||
.control-list {
|
||||
p.no-data {
|
||||
padding: 18px 20px;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
.modal-body {
|
||||
padding-bottom: 0;
|
||||
|
||||
p:last-child {
|
||||
> p:last-child {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,12 +128,13 @@ class FormController extends ControllerBehavior
|
|||
$this->initForm($model);
|
||||
|
||||
$this->controller->formBeforeSave($model);
|
||||
$this->controller->formBeforeCreateSave($model);
|
||||
$this->controller->formBeforeCreate($model);
|
||||
|
||||
$this->setModelAttributes($model, $this->formWidget->getSaveData());
|
||||
$model->push($this->formWidget->getSessionKey());
|
||||
|
||||
$this->controller->formAfterSave($model);
|
||||
$this->controller->formAfterCreate($model);
|
||||
|
||||
Flash::success($this->getLang('create[flash-save]', 'backend::lang.form.create_success'));
|
||||
|
||||
|
|
@ -177,12 +178,13 @@ class FormController extends ControllerBehavior
|
|||
$this->initForm($model, 'update');
|
||||
|
||||
$this->controller->formBeforeSave($model);
|
||||
$this->controller->formBeforeEditSave($model);
|
||||
$this->controller->formBeforeUpdate($model);
|
||||
|
||||
$this->setModelAttributes($model, $this->formWidget->getSaveData());
|
||||
$model->push($this->formWidget->getSessionKey());
|
||||
|
||||
$this->controller->formAfterSave($model);
|
||||
$this->controller->formAfterUpdate($model);
|
||||
|
||||
Flash::success($this->getLang('update[flash-save]', 'backend::lang.form.update_success'));
|
||||
|
||||
|
|
@ -409,16 +411,10 @@ class FormController extends ControllerBehavior
|
|||
//
|
||||
|
||||
/**
|
||||
* Called before the creation form is saved.
|
||||
* Called before the creation or updating form is saved.
|
||||
* @param Model
|
||||
*/
|
||||
public function formBeforeCreateSave($model) {}
|
||||
|
||||
/**
|
||||
* Called after the creation form is saved.
|
||||
* @param Model
|
||||
*/
|
||||
public function formAfterCreateSave($model) {}
|
||||
public function formBeforeSave($model) {}
|
||||
|
||||
/**
|
||||
* Called after the creation or updating form is saved.
|
||||
|
|
@ -426,23 +422,29 @@ class FormController extends ControllerBehavior
|
|||
*/
|
||||
public function formAfterSave($model) {}
|
||||
|
||||
/**
|
||||
* Called before the creation form is saved.
|
||||
* @param Model
|
||||
*/
|
||||
public function formBeforeCreate($model) {}
|
||||
|
||||
/**
|
||||
* Called after the creation form is saved.
|
||||
* @param Model
|
||||
*/
|
||||
public function formAfterCreate($model) {}
|
||||
|
||||
/**
|
||||
* Called before the updating form is saved.
|
||||
* @param Model
|
||||
*/
|
||||
public function formBeforeEditSave($model) {}
|
||||
|
||||
/**
|
||||
* Called before the creation or updating form is saved.
|
||||
* @param Model
|
||||
*/
|
||||
public function formBeforeSave($model) {}
|
||||
public function formBeforeUpdate($model) {}
|
||||
|
||||
/**
|
||||
* Called after the updating form is saved.
|
||||
* @param Model
|
||||
*/
|
||||
public function formAfterEditSave($model) {}
|
||||
public function formAfterUpdate($model) {}
|
||||
|
||||
/**
|
||||
* Called after the form model is deleted.
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ class NavigationManager
|
|||
$this->pluginManager = PluginManager::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the menu items from modules and plugins
|
||||
* @return void
|
||||
*/
|
||||
protected function loadItems()
|
||||
{
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@ class Index extends Controller
|
|||
BackendMenu::setContextOwner('October.Backend');
|
||||
new ReportContainer($this);
|
||||
|
||||
/* @todo Remove line if year >= 2015 */ if (\Schema::hasColumn('backend_users', 'activated')) \Schema::table('backend_users', function($table) { $table->renameColumn('activated', 'is_activated'); });
|
||||
/* @todo Remove line if year >= 2015 */ if (\Schema::hasColumn('backend_user_throttle', 'suspended')) \Schema::table('backend_user_throttle', function($table) { $table->renameColumn('suspended', 'is_suspended'); });
|
||||
/* @todo Remove line if year >= 2015 */ if (\Schema::hasColumn('backend_user_throttle', 'banned')) \Schema::table('backend_user_throttle', function($table) { $table->renameColumn('banned', 'is_banned'); });
|
||||
/* @todo Remove line if year >= 2015 */ if (\Schema::hasColumn('deferred_bindings', 'bind')) \Schema::table('deferred_bindings', function($table) { $table->renameColumn('bind', 'is_bind'); });
|
||||
/* @todo Remove line if year >= 2015 */ if (\Schema::hasColumn('system_files', 'public')) \Schema::table('system_files', function($table) { $table->renameColumn('public', 'is_public'); });
|
||||
}
|
||||
|
||||
public function index()
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class DbBackendUsers extends Migration
|
|||
$table->string('persist_code')->nullable();
|
||||
$table->string('reset_password_code')->nullable()->index();
|
||||
$table->text('permissions')->nullable();
|
||||
$table->boolean('activated')->default(0);
|
||||
$table->boolean('is_activated')->default(0);
|
||||
$table->timestamp('activated_at')->nullable();
|
||||
$table->timestamp('last_login')->nullable();
|
||||
$table->timestamps();
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ class DbBackendUserThrottle extends Migration
|
|||
$table->integer('user_id')->unsigned();
|
||||
$table->string('ip_address')->nullable();
|
||||
$table->integer('attempts')->default(0);
|
||||
$table->boolean('suspended')->default(0);
|
||||
$table->boolean('banned')->default(0);
|
||||
$table->timestamp('last_attempt_at')->nullable();
|
||||
$table->boolean('is_suspended')->default(0);
|
||||
$table->timestamp('suspended_at')->nullable();
|
||||
$table->boolean('is_banned')->default(0);
|
||||
$table->timestamp('banned_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class SeedSetupAdmin extends Seeder
|
|||
'first_name' => static::$firstName,
|
||||
'last_name' => static::$lastName,
|
||||
'permissions' => ['superuser' => 1],
|
||||
'activated' => true
|
||||
'is_activated' => true
|
||||
]);
|
||||
|
||||
$user->addGroup($group);
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ class FileUpload extends FormWidgetBase
|
|||
|
||||
$file = new File();
|
||||
$file->data = $uploadedFile;
|
||||
$file->public = $fileRelation->isPublic();
|
||||
$file->is_public = $fileRelation->isPublic();
|
||||
$file->save();
|
||||
|
||||
$fileRelation->add($file, $this->sessionKey);
|
||||
|
|
|
|||
|
|
@ -16,11 +16,18 @@ class RichEditor extends FormWidgetBase
|
|||
*/
|
||||
public $defaultAlias = 'richeditor';
|
||||
|
||||
/**
|
||||
* @var boolean Determines whether content has HEAD and HTML tags.
|
||||
*/
|
||||
public $fullPage = false;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$this->fullPage = $this->getConfig('fullPage', $this->fullPage);
|
||||
|
||||
$this->prepareVars();
|
||||
return $this->makePartial('richeditor');
|
||||
}
|
||||
|
|
@ -30,6 +37,7 @@ class RichEditor extends FormWidgetBase
|
|||
*/
|
||||
public function prepareVars()
|
||||
{
|
||||
$this->vars['fullPage'] = $this->fullPage;
|
||||
$this->vars['stretch'] = $this->formField->stretch;
|
||||
$this->vars['size'] = $this->formField->size;
|
||||
$this->vars['name'] = $this->formField->getName();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
subject = "Welcome to October CMS"
|
||||
layout = "system"
|
||||
==
|
||||
|
||||
Hi {{ name }},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
subject = "Password Reset"
|
||||
layout = "system"
|
||||
==
|
||||
|
||||
Hello {{ name }},
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
/**
|
||||
*
|
||||
* DEPRECATED WARNING: This class is deprecated and should be deleted
|
||||
* if the current year is equal to or greater than 2015 @todo.
|
||||
* if the current year is equal to or greater than 2015.
|
||||
*
|
||||
* @todo Delete this file if year >= 2015.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@
|
|||
<h4 class="modal-title">File was changed</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-warning">
|
||||
<p>The file you're editing has been changed on disk by another user. You can either reload the file and lose your changes or override the file on the disk.</p>
|
||||
</div>
|
||||
<p>The file you're editing has been changed on disk by another user. You can either reload the file and lose your changes or override the file on the disk.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -144,8 +144,9 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
*/
|
||||
BackendAuth::registerCallback(function($manager) {
|
||||
$manager->registerPermissions('October.System', [
|
||||
'system.manage_settings' => ['label' => 'Manage system settings', 'tab' => 'System'],
|
||||
'system.manage_updates' => ['label' => 'Manage software updates', 'tab' => 'System'],
|
||||
'system.manage_settings' => ['label' => 'Manage system settings', 'tab' => 'System'],
|
||||
'system.manage_updates' => ['label' => 'Manage software updates', 'tab' => 'System'],
|
||||
'system.manage_email_templates' => ['label' => 'Manage email templates', 'tab' => 'System'],
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -154,7 +155,7 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
*/
|
||||
SettingsManager::instance()->registerCallback(function($manager){
|
||||
$manager->registerSettingItems('October.System', [
|
||||
'email' => [
|
||||
'email_settings' => [
|
||||
'label' => 'system::lang.email.menu_label',
|
||||
'description' => 'system::lang.email.menu_description',
|
||||
'category' => 'System',
|
||||
|
|
@ -162,6 +163,14 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
'class' => 'System\Models\EmailSettings',
|
||||
'sort' => 100
|
||||
],
|
||||
'email_templates' => [
|
||||
'label' => 'system::lang.email_templates.menu_label',
|
||||
'description' => 'system::lang.email_templates.menu_description',
|
||||
'category' => 'System',
|
||||
'icon' => 'icon-envelope-square',
|
||||
'url' => Backend::url('system/emailtemplates'),
|
||||
'sort' => 100
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,17 @@ abstract class PluginBase extends ServiceProviderBase
|
|||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers any email templates implemented by this plugin.
|
||||
* The templates must be returned in the following format:
|
||||
* ['acme.blog::emails.welcome' => 'This is a description of the welcome template'],
|
||||
* ['acme.blog::emails.forgot_password' => 'This is a description of the forgot password template'],
|
||||
*/
|
||||
public function registerEmailTemplates()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new console (artisan) command
|
||||
* @param $key The command name
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
<?php namespace System\Controllers;
|
||||
|
||||
use Str;
|
||||
use Lang;
|
||||
use File;
|
||||
use Flash;
|
||||
use Backend;
|
||||
use Redirect;
|
||||
use BackendMenu;
|
||||
use Backend\Classes\Controller;
|
||||
use System\Classes\ApplicationException;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Email layouts controller
|
||||
*
|
||||
* @package october\system
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*
|
||||
*/
|
||||
class EmailLayouts extends Controller
|
||||
{
|
||||
|
||||
public $implement = [
|
||||
'Backend.Behaviors.FormController',
|
||||
];
|
||||
|
||||
public $requiredPermissions = ['system.manage_email_templates'];
|
||||
|
||||
public $formConfig = 'config_form.yaml';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
BackendMenu::setContext('October.System', 'system', 'settings');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php namespace System\Controllers;
|
||||
|
||||
use Str;
|
||||
use Lang;
|
||||
use File;
|
||||
use Flash;
|
||||
use Backend;
|
||||
use Redirect;
|
||||
use BackendMenu;
|
||||
use Backend\Classes\Controller;
|
||||
use System\Models\EmailTemplate;
|
||||
use System\Classes\ApplicationException;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Email templates controller
|
||||
*
|
||||
* @package october\system
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*
|
||||
*/
|
||||
class EmailTemplates extends Controller
|
||||
{
|
||||
|
||||
public $implement = [
|
||||
'Backend.Behaviors.FormController',
|
||||
'Backend.Behaviors.ListController'
|
||||
];
|
||||
|
||||
public $requiredPermissions = ['system.manage_email_templates'];
|
||||
|
||||
public $listConfig = ['templates' => 'config_templates_list.yaml', 'layouts' => 'config_layouts_list.yaml'];
|
||||
public $formConfig = 'config_form.yaml';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
BackendMenu::setContext('October.System', 'system', 'settings');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
/* @todo Remove line if year >= 2015 */ if (!\System\Models\EmailLayout::whereCode('default')->count()) { \Eloquent::unguard(); with(new \System\Database\Seeds\SeedSetupEmailLayouts)->run(); }
|
||||
|
||||
EmailTemplate::syncAll();
|
||||
$this->getClassExtension('Backend.Behaviors.ListController')->index();
|
||||
$this->bodyClass = null;
|
||||
}
|
||||
|
||||
public function formBeforeSave($model)
|
||||
{
|
||||
$model->is_custom = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -62,6 +62,9 @@ class Updates extends Controller
|
|||
return $this->getClassExtension('Backend.Behaviors.ListController')->index();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function listInjectRowClass($record, $definition = null)
|
||||
{
|
||||
if ($record->disabledByConfig)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
# ===================================
|
||||
# Form Behavior Config
|
||||
# ===================================
|
||||
|
||||
name: system::lang.email_templates.layout
|
||||
form: @/modules/system/models/emaillayout/fields.yaml
|
||||
modelClass: System\Models\EmailLayout
|
||||
defaultRedirect: system/emailtemplates
|
||||
|
||||
create:
|
||||
redirect: system/emailtemplates/update/:id
|
||||
redirectClose: system/emailtemplates
|
||||
|
||||
update:
|
||||
redirect: system/emailtemplates
|
||||
redirectClose: system/emailtemplates
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php Block::put('breadcrumb') ?>
|
||||
<ul>
|
||||
<li><a href="<?= Backend::url('system/settings') ?>"><?= e(trans('system::lang.settings.menu_label')) ?></a></li>
|
||||
<li><a href="<?= Backend::url('system/emailtemplates') ?>"><?= e(trans('system::lang.email_templates.menu_layouts_label')) ?></a></li>
|
||||
<li><?= e($this->pageTitle) ?></li>
|
||||
</ul>
|
||||
<?php Block::endPut() ?>
|
||||
|
||||
<?php if (!$this->fatalError): ?>
|
||||
|
||||
<?= Form::open(['class'=>'layout-item stretch layout-column']) ?>
|
||||
|
||||
<?= $this->formRender() ?>
|
||||
|
||||
<div class="form-buttons layout-item fix">
|
||||
<div class="loading-indicator-container">
|
||||
<button
|
||||
type="submit"
|
||||
data-request="onSave"
|
||||
data-hotkey="ctrl+s"
|
||||
data-hotkey-mac="cmd+s"
|
||||
data-load-indicator="Creating Layout..."
|
||||
class="btn btn-primary">
|
||||
Create
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-request="onSave"
|
||||
data-request-data="close:1"
|
||||
data-hotkey="ctrl+enter"
|
||||
data-hotkey-mac="cmd+enter"
|
||||
data-load-indicator="Creating Layout..."
|
||||
class="btn btn-default">
|
||||
Create and Close
|
||||
</button>
|
||||
<span class="btn-text">
|
||||
or <a href="<?= Backend::url('system/emailtemplates') ?>">Cancel</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?= Form::close() ?>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
|
||||
<p><a href="<?= Backend::url('system/emailtemplates') ?>" class="btn btn-default">Return to template list</a></p>
|
||||
|
||||
<?php endif ?>
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
<?php Block::put('breadcrumb') ?>
|
||||
<ul>
|
||||
<li><a href="<?= Backend::url('system/settings') ?>"><?= e(trans('system::lang.settings.menu_label')) ?></a></li>
|
||||
<li><a href="<?= Backend::url('system/emailtemplates') ?>"><?= e(trans('system::lang.email_templates.menu_layouts_label')) ?></a></li>
|
||||
<li><?= e($this->pageTitle) ?></li>
|
||||
</ul>
|
||||
<?php Block::endPut() ?>
|
||||
|
||||
<?php if (!$this->fatalError): ?>
|
||||
|
||||
<div class="scoreboard">
|
||||
<div data-control="toolbar">
|
||||
<div class="scoreboard-item title-value">
|
||||
<h4><?= e(trans('system::lang.email_templates.template')) ?></h4>
|
||||
<p><?= $formModel->code ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?= Form::open(['class'=>'layout-item stretch layout-column']) ?>
|
||||
|
||||
<?= $this->formRender() ?>
|
||||
|
||||
<div class="form-buttons layout-item fix">
|
||||
<div class="loading-indicator-container">
|
||||
<button
|
||||
type="submit"
|
||||
data-request="onSave"
|
||||
data-request-data="redirect:0"
|
||||
data-hotkey="ctrl+s"
|
||||
data-hotkey-mac="cmd+s"
|
||||
data-load-indicator="Saving Layout..."
|
||||
class="btn btn-primary">
|
||||
<u>S</u>ave
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-request="onSave"
|
||||
data-request-data="close:1"
|
||||
data-hotkey="ctrl+enter"
|
||||
data-hotkey-mac="cmd+enter"
|
||||
data-load-indicator="Saving Layout..."
|
||||
class="btn btn-default">
|
||||
Save and Close
|
||||
</button>
|
||||
<?php if (!$formModel->is_locked): ?>
|
||||
<button
|
||||
type="button"
|
||||
class="oc-icon-trash-o btn-icon danger pull-right"
|
||||
data-request="onDelete"
|
||||
data-load-indicator="Deleting Layout..."
|
||||
data-request-confirm="Do you really want to delete this layout?">
|
||||
</button>
|
||||
<?php endif ?>
|
||||
<span class="btn-text">
|
||||
or <a href="<?= Backend::url('system/emailtemplates') ?>">Cancel</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?= Form::close() ?>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
|
||||
<p><a href="<?= Backend::url('system/emailtemplates') ?>" class="btn btn-default">Return to template list</a></p>
|
||||
|
||||
<?php endif ?>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<div data-control="toolbar">
|
||||
<a
|
||||
href="<?= Backend::url('system/emaillayouts/create') ?>"
|
||||
class="btn btn-primary oc-icon-plus">
|
||||
<?= e(trans('system::lang.email_templates.new_layout')) ?>
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<div data-control="toolbar">
|
||||
<a
|
||||
href="<?= Backend::url('system/emailtemplates/create') ?>"
|
||||
class="btn btn-primary oc-icon-plus">
|
||||
<?= e(trans('system::lang.email_templates.new_template')) ?>
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# ===================================
|
||||
# Form Behavior Config
|
||||
# ===================================
|
||||
|
||||
name: system::lang.email_templates.template
|
||||
form: @/modules/system/models/emailtemplate/fields.yaml
|
||||
modelClass: System\Models\EmailTemplate
|
||||
defaultRedirect: system/emailtemplates
|
||||
|
||||
create:
|
||||
redirect: system/emailtemplates/update/:id
|
||||
redirectClose: system/emailtemplates
|
||||
|
||||
update:
|
||||
redirect: system/emailtemplates
|
||||
redirectClose: system/emailtemplates
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# ===================================
|
||||
# List Behavior Config
|
||||
# ===================================
|
||||
|
||||
title: system::lang.email_templates.menu_label
|
||||
list: @/modules/system/models/emaillayout/columns.yaml
|
||||
modelClass: System\Models\EmailLayout
|
||||
recordUrl: system/emaillayouts/update/:id
|
||||
noRecordsMessage: backend::lang.list.no_records
|
||||
showSetup: false
|
||||
|
||||
toolbar:
|
||||
buttons: list_layouts_toolbar
|
||||
search:
|
||||
prompt: backend::lang.list.search_prompt
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# ===================================
|
||||
# List Behavior Config
|
||||
# ===================================
|
||||
|
||||
title: system::lang.email_templates.menu_label
|
||||
list: @/modules/system/models/emailtemplate/columns.yaml
|
||||
modelClass: System\Models\EmailTemplate
|
||||
recordUrl: system/emailtemplates/update/:id
|
||||
noRecordsMessage: backend::lang.list.no_records
|
||||
recordsPerPage: 20
|
||||
showSetup: false
|
||||
|
||||
toolbar:
|
||||
buttons: list_templates_toolbar
|
||||
search:
|
||||
prompt: backend::lang.list.search_prompt
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php Block::put('breadcrumb') ?>
|
||||
<ul>
|
||||
<li><a href="<?= Backend::url('system/settings') ?>"><?= e(trans('system::lang.settings.menu_label')) ?></a></li>
|
||||
<li><a href="<?= Backend::url('system/emailtemplates') ?>"><?= e(trans('system::lang.email_templates.menu_label')) ?></a></li>
|
||||
<li><?= e($this->pageTitle) ?></li>
|
||||
</ul>
|
||||
<?php Block::endPut() ?>
|
||||
|
||||
<?php if (!$this->fatalError): ?>
|
||||
|
||||
<?= Form::open(['class'=>'layout-item stretch layout-column']) ?>
|
||||
|
||||
<?= $this->formRender() ?>
|
||||
|
||||
<div class="form-buttons layout-item fix">
|
||||
<div class="loading-indicator-container">
|
||||
<button
|
||||
type="submit"
|
||||
data-request="onSave"
|
||||
data-hotkey="ctrl+s"
|
||||
data-hotkey-mac="cmd+s"
|
||||
data-load-indicator="Creating Template..."
|
||||
class="btn btn-primary">
|
||||
Create
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-request="onSave"
|
||||
data-request-data="close:1"
|
||||
data-hotkey="ctrl+enter"
|
||||
data-hotkey-mac="cmd+enter"
|
||||
data-load-indicator="Creating Template..."
|
||||
class="btn btn-default">
|
||||
Create and Close
|
||||
</button>
|
||||
<span class="btn-text">
|
||||
or <a href="<?= Backend::url('system/emailtemplates') ?>">Cancel</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?= Form::close() ?>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
|
||||
<p><a href="<?= Backend::url('system/emailtemplates') ?>" class="btn btn-default">Return to template list</a></p>
|
||||
|
||||
<?php endif ?>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php Block::put('breadcrumb') ?>
|
||||
<ul>
|
||||
<li><a href="<?= Backend::url('system/settings') ?>"><?= e(trans('system::lang.settings.menu_label')) ?></a></li>
|
||||
<li><?= e($this->pageTitle) ?></li>
|
||||
</ul>
|
||||
<?php Block::endPut() ?>
|
||||
|
||||
|
||||
<div class="control-tabs secondary" data-control="tab">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a href="#templates"><?= e(trans('system::lang.email_templates.templates')) ?></a></li>
|
||||
<li><a href="#templates"><?= e(trans('system::lang.email_templates.layouts')) ?></a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active">
|
||||
<div class="list-preview">
|
||||
<?= $this->listRender('templates') ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane">
|
||||
<div class="list-preview">
|
||||
<?= $this->listRender('layouts') ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<?php Block::put('breadcrumb') ?>
|
||||
<ul>
|
||||
<li><a href="<?= Backend::url('system/settings') ?>"><?= e(trans('system::lang.settings.menu_label')) ?></a></li>
|
||||
<li><a href="<?= Backend::url('system/emailtemplates') ?>"><?= e(trans('system::lang.email_templates.menu_label')) ?></a></li>
|
||||
<li><?= e($this->pageTitle) ?></li>
|
||||
</ul>
|
||||
<?php Block::endPut() ?>
|
||||
|
||||
<?php if (!$this->fatalError): ?>
|
||||
|
||||
<div class="scoreboard">
|
||||
<div data-control="toolbar">
|
||||
<div class="scoreboard-item title-value">
|
||||
<h4><?= e(trans('system::lang.email_templates.template')) ?></h4>
|
||||
<p><?= $formModel->code ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?= Form::open(['class'=>'layout-item stretch layout-column']) ?>
|
||||
|
||||
<?= $this->formRender() ?>
|
||||
|
||||
<div class="form-buttons layout-item fix">
|
||||
<div class="loading-indicator-container">
|
||||
<button
|
||||
type="submit"
|
||||
data-request="onSave"
|
||||
data-request-data="redirect:0"
|
||||
data-hotkey="ctrl+s"
|
||||
data-hotkey-mac="cmd+s"
|
||||
data-load-indicator="Saving Template..."
|
||||
class="btn btn-primary">
|
||||
<u>S</u>ave
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-request="onSave"
|
||||
data-request-data="close:1"
|
||||
data-hotkey="ctrl+enter"
|
||||
data-hotkey-mac="cmd+enter"
|
||||
data-load-indicator="Saving Template..."
|
||||
class="btn btn-default">
|
||||
Save and Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="oc-icon-trash-o btn-icon danger pull-right"
|
||||
data-request="onDelete"
|
||||
data-load-indicator="Deleting Template..."
|
||||
data-request-confirm="Do you really want to delete this template?">
|
||||
</button>
|
||||
<span class="btn-text">
|
||||
or <a href="<?= Backend::url('system/emailtemplates') ?>">Cancel</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?= Form::close() ?>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
|
||||
<p><a href="<?= Backend::url('system/emailtemplates') ?>" class="btn btn-default">Return to template list</a></p>
|
||||
|
||||
<?php endif ?>
|
||||
|
|
@ -11,19 +11,23 @@
|
|||
|
||||
<p><?= e(trans('system::lang.plugins.selected_amount', ['amount'=>count($checked)])) ?></p>
|
||||
|
||||
<div class="form-group">
|
||||
<!-- Checkbox -->
|
||||
<div class="checkbox custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="disable"
|
||||
value="1"
|
||||
id="pluginDisable">
|
||||
<label for="pluginDisable">
|
||||
<?= e(trans('system::lang.plugins.disabled_label')) ?>
|
||||
</label>
|
||||
<p class="help-block"><?= e(trans('system::lang.plugins.disabled_help')) ?></p>
|
||||
<div class="form-preview">
|
||||
|
||||
<div class="form-group">
|
||||
<!-- Checkbox -->
|
||||
<div class="checkbox custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="disable"
|
||||
value="1"
|
||||
id="pluginDisable">
|
||||
<label for="pluginDisable">
|
||||
<?= e(trans('system::lang.plugins.disabled_label')) ?>
|
||||
</label>
|
||||
<p class="help-block"><?= e(trans('system::lang.plugins.disabled_help')) ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<?php foreach ($checked as $id): ?>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class DbDeferredBindings extends Migration
|
|||
$table->string('slave_type')->index();
|
||||
$table->string('slave_id')->index();
|
||||
$table->string('session_key');
|
||||
$table->boolean('bind')->default(true);
|
||||
$table->boolean('is_bind')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class DbSystemFiles extends Migration
|
|||
$table->string('field')->nullable()->index();
|
||||
$table->string('attachment_id')->index()->nullable();
|
||||
$table->string('attachment_type')->index()->nullable();
|
||||
$table->boolean('public')->default(true);
|
||||
$table->boolean('is_public')->default(true);
|
||||
$table->integer('sort_order')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class DbSystemEmailTemplates extends Migration
|
||||
{
|
||||
|
||||
public function up()
|
||||
{
|
||||
Schema::create('system_email_templates', function(Blueprint $table)
|
||||
{
|
||||
$table->engine = 'InnoDB';
|
||||
$table->increments('id');
|
||||
$table->string('code')->nullable();
|
||||
$table->string('subject')->nullable();
|
||||
$table->text('description')->nullable();
|
||||
$table->text('content_html')->nullable();
|
||||
$table->text('content_text')->nullable();
|
||||
$table->integer('layout_id')->index()->nullable();
|
||||
$table->boolean('is_custom')->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('system_email_templates');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class DbSystemEmailLayouts extends Migration
|
||||
{
|
||||
|
||||
public function up()
|
||||
{
|
||||
Schema::create('system_email_layouts', function(Blueprint $table)
|
||||
{
|
||||
$table->engine = 'InnoDB';
|
||||
$table->increments('id');
|
||||
$table->string('name')->nullable();
|
||||
$table->string('code')->nullable();
|
||||
$table->text('content_html')->nullable();
|
||||
$table->text('content_text')->nullable();
|
||||
$table->text('content_css')->nullable();
|
||||
$table->boolean('is_locked')->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('system_email_layouts');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php namespace System\Database\Seeds;
|
||||
|
||||
use Seeder;
|
||||
use Eloquent;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
Eloquent::unguard();
|
||||
|
||||
$this->call('System\Database\Seeds\SeedSetupEmailLayouts');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<?php namespace System\Database\Seeds;
|
||||
|
||||
use Seeder;
|
||||
use System\Models\EmailLayout;
|
||||
|
||||
class SeedSetupEmailLayouts extends Seeder
|
||||
{
|
||||
|
||||
public function run()
|
||||
{
|
||||
|
||||
$css = 'a, a:hover {
|
||||
text-decoration: none;
|
||||
color: #0862A2;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td, tr, th, table {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 10px 0;
|
||||
}';
|
||||
|
||||
$html = '<html>
|
||||
<head>
|
||||
<style type="text/css" media="screen">
|
||||
{{ css }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{{ message }}
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
$text = '{{message}}';
|
||||
|
||||
EmailLayout::create([
|
||||
'is_locked' => true,
|
||||
'name' => 'Default',
|
||||
'code' => 'default',
|
||||
'content_html' => $html,
|
||||
'content_css' => $css,
|
||||
'content_text' => $text,
|
||||
]);
|
||||
|
||||
$html = '<html>
|
||||
<head>
|
||||
<style type="text/css" media="screen">
|
||||
{{ css }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{{ message }}
|
||||
<hr />
|
||||
<p>This is an automatic message. Please do not reply to it.</p>
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
$text = '{{message}}
|
||||
|
||||
|
||||
---
|
||||
This is an automatic message. Please do not reply to it.
|
||||
';
|
||||
|
||||
EmailLayout::create([
|
||||
'is_locked' => true,
|
||||
'name' => 'System',
|
||||
'code' => 'system',
|
||||
'content_html' => $html,
|
||||
'content_css' => $css,
|
||||
'content_text' => $text,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -75,6 +75,27 @@ return [
|
|||
'sendmail_path' => 'Sendmail Path',
|
||||
'sendmail_path_comment' => 'Please specify the path of the sendmail program.',
|
||||
],
|
||||
'email_templates' => [
|
||||
'menu_label' => 'Email Templates',
|
||||
'menu_description' => 'Modify the email templates that are sent to users and administrators.',
|
||||
'new_template' => 'New Template',
|
||||
'new_layout' => 'New Layout',
|
||||
'template' => 'Template',
|
||||
'templates' => 'Templates',
|
||||
'menu_layouts_label' => 'Email Layouts',
|
||||
'layout' => 'Layout',
|
||||
'layouts' => 'Layouts',
|
||||
'name' => 'Name',
|
||||
'name_comment' => 'Unique name used to refer to this template',
|
||||
'code' => 'Code',
|
||||
'code_comment' => 'Unique code used to refer to this template',
|
||||
'subject' => 'Subject',
|
||||
'subject_comment' => 'Email message subject',
|
||||
'description' => 'Description',
|
||||
'content_html' => 'HTML',
|
||||
'content_css' => 'CSS',
|
||||
'content_text' => 'Plaintext',
|
||||
],
|
||||
'install' => [
|
||||
'project_label' => 'Attach to Project',
|
||||
'plugin_label' => 'Install Plugin',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
<?php namespace System\Models;
|
||||
|
||||
use Model;
|
||||
use System\Classes\ApplicationException;
|
||||
|
||||
class EmailLayout extends Model
|
||||
{
|
||||
/**
|
||||
* @var string The database table used by the model.
|
||||
*/
|
||||
protected $table = 'system_email_layouts';
|
||||
|
||||
public $rules = [
|
||||
'code' => 'required|unique:system_email_layouts',
|
||||
'name' => 'required',
|
||||
'content_html' => 'required',
|
||||
];
|
||||
|
||||
public function beforeDelete()
|
||||
{
|
||||
if ($this->is_locked)
|
||||
throw new ApplicationException('Cannot delete this template because it is locked');
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
<?php namespace System\Models;
|
||||
|
||||
use File;
|
||||
use View;
|
||||
use Model;
|
||||
use October\Rain\Mail\MailParser;
|
||||
use System\Classes\PluginManager;
|
||||
|
||||
class EmailTemplate extends Model
|
||||
{
|
||||
/**
|
||||
* @var string The database table used by the model.
|
||||
*/
|
||||
protected $table = 'system_email_templates';
|
||||
|
||||
public $rules = [
|
||||
'code' => 'required|unique:system_email_templates',
|
||||
'subject' => 'required',
|
||||
'description' => 'required',
|
||||
'content_html' => 'required',
|
||||
];
|
||||
|
||||
public $belongsTo = [
|
||||
'layout' => ['System\Models\EmailLayout']
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array Cache of registration callbacks.
|
||||
*/
|
||||
private static $callbacks = [];
|
||||
|
||||
protected static $registeredTemplates;
|
||||
|
||||
public static function syncAll()
|
||||
{
|
||||
$templates = self::make()->listRegisteredTemplates();
|
||||
$dbTemplates = self::lists('is_custom', 'code');
|
||||
$newTemplates = array_diff_key($templates, $dbTemplates);
|
||||
|
||||
/*
|
||||
* Clean up non-customized templates
|
||||
*/
|
||||
foreach ($dbTemplates as $code => $is_custom) {
|
||||
if ($is_custom)
|
||||
continue;
|
||||
|
||||
if (!array_key_exists($code, $templates))
|
||||
self::whereCode($code)->delete();
|
||||
}
|
||||
|
||||
/*
|
||||
* Create new templates
|
||||
*/
|
||||
if (count($newTemplates))
|
||||
$categories = EmailLayout::lists('id', 'code');
|
||||
|
||||
foreach ($newTemplates as $code => $description) {
|
||||
$sections = self::getTemplateSections($code);
|
||||
$layoutCode = array_get($sections, 'settings.layout', 'default');
|
||||
|
||||
$template = self::make();
|
||||
$template->code = $code;
|
||||
$template->description = $description;
|
||||
$template->is_custom = false;
|
||||
$template->layout_id = isset($categories[$layoutCode]) ? $categories[$layoutCode] : null;
|
||||
$template->forceSave();
|
||||
}
|
||||
}
|
||||
|
||||
public function afterFetch()
|
||||
{
|
||||
if (!$this->is_custom) {
|
||||
$sections = self::getTemplateSections($this->code);
|
||||
$this->content_html = $sections['html'];
|
||||
$this->content_text = $sections['text'];
|
||||
$this->subject = array_get($sections, 'settings.subject', 'No subject');
|
||||
}
|
||||
}
|
||||
|
||||
protected static function getTemplateSections($code)
|
||||
{
|
||||
return MailParser::parse(File::get(View::make($code)->getPath()));
|
||||
}
|
||||
|
||||
//
|
||||
// Registration
|
||||
//
|
||||
|
||||
/**
|
||||
* Loads registered email templates from modules and plugins
|
||||
* @return void
|
||||
*/
|
||||
public function loadRegisteredTemplates()
|
||||
{
|
||||
foreach (static::$callbacks as $callback) {
|
||||
$callback($this);
|
||||
}
|
||||
|
||||
$plugins = PluginManager::instance()->getPlugins();
|
||||
foreach ($plugins as $pluginId => $pluginObj) {
|
||||
$templates = $pluginObj->registerEmailTemplates();
|
||||
if (!is_array($templates))
|
||||
continue;
|
||||
|
||||
$this->registerEmailTemplates($templates);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the registered templates.
|
||||
* @return array
|
||||
*/
|
||||
public function listRegisteredTemplates()
|
||||
{
|
||||
if (self::$registeredTemplates === null)
|
||||
$this->loadRegisteredTemplates();
|
||||
|
||||
return self::$registeredTemplates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback function that defines email templates.
|
||||
* The callback function should register templates by calling the manager's
|
||||
* registerEmailTemplates() function. Thi instance is passed to the
|
||||
* callback function as an argument. Usage:
|
||||
* <pre>
|
||||
* EmailTemplate::registerCallback(function($template){
|
||||
* $template->registerEmailTemplates([...]);
|
||||
* });
|
||||
* </pre>
|
||||
* @param callable $callback A callable function.
|
||||
*/
|
||||
public static function registerCallback(callable $callback)
|
||||
{
|
||||
self::$callbacks[] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers email views and manageable templates.
|
||||
*/
|
||||
public function registerEmailTemplates(array $definitions)
|
||||
{
|
||||
if (!static::$registeredTemplates)
|
||||
static::$registeredTemplates = [];
|
||||
|
||||
static::$registeredTemplates = array_merge(static::$registeredTemplates, $definitions);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# ===================================
|
||||
# Column Definitions
|
||||
# ===================================
|
||||
|
||||
columns:
|
||||
|
||||
name:
|
||||
label: Name
|
||||
searchable: true
|
||||
|
||||
code:
|
||||
label: Code
|
||||
searchable: true
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# ===================================
|
||||
# Field Definitions
|
||||
# ===================================
|
||||
|
||||
fields:
|
||||
|
||||
code:
|
||||
label: system::lang.email_templates.code
|
||||
comment: system::lang.email_templates.code_comment
|
||||
span: left
|
||||
context: create
|
||||
|
||||
name:
|
||||
label: system::lang.email_templates.name
|
||||
span: right
|
||||
# context: create
|
||||
|
||||
# @todo Fix duplicate key problem
|
||||
# name:
|
||||
# label: system::lang.email_templates.name
|
||||
# context: update
|
||||
|
||||
secondaryTabs:
|
||||
fields:
|
||||
|
||||
content_html:
|
||||
type: codeeditor
|
||||
size: giant
|
||||
tab: system::lang.email_templates.content_html
|
||||
options:
|
||||
language: html
|
||||
|
||||
content_css:
|
||||
type: codeeditor
|
||||
size: giant
|
||||
tab: system::lang.email_templates.content_css
|
||||
options:
|
||||
language: css
|
||||
|
||||
content_text:
|
||||
type: textarea
|
||||
size: giant
|
||||
tab: system::lang.email_templates.content_text
|
||||
|
|
@ -3,8 +3,8 @@
|
|||
# ===================================
|
||||
|
||||
tabs:
|
||||
|
||||
fields:
|
||||
|
||||
send_mode:
|
||||
label: system::lang.email.method
|
||||
type: dropdown
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
# ===================================
|
||||
# Column Definitions
|
||||
# ===================================
|
||||
|
||||
columns:
|
||||
|
||||
code:
|
||||
label: Code
|
||||
searchable: true
|
||||
|
||||
subject:
|
||||
label: Subject
|
||||
searchable: true
|
||||
|
||||
description:
|
||||
label: Description
|
||||
searchable: true
|
||||
|
||||
layout:
|
||||
relation: layout
|
||||
select: @name
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# ===================================
|
||||
# Field Definitions
|
||||
# ===================================
|
||||
|
||||
fields:
|
||||
|
||||
layout:
|
||||
label: system::lang.email_templates.layout
|
||||
type: relation
|
||||
options:
|
||||
emptyOption: -- No layout --
|
||||
|
||||
code:
|
||||
label: system::lang.email_templates.code
|
||||
comment: system::lang.email_templates.code_comment
|
||||
span: left
|
||||
context: create
|
||||
|
||||
subject:
|
||||
label: system::lang.email_templates.subject
|
||||
comment: system::lang.email_templates.subject_comment
|
||||
span: right
|
||||
# context: create
|
||||
|
||||
# @todo Fix duplicate key problem
|
||||
# subject:
|
||||
# label: system::lang.email_templates.subject
|
||||
# context: update
|
||||
|
||||
description:
|
||||
label: system::lang.email_templates.description
|
||||
type: textarea
|
||||
size: tiny
|
||||
|
||||
secondaryTabs:
|
||||
fields:
|
||||
|
||||
content_html:
|
||||
type: richeditor
|
||||
size: huge
|
||||
tab: system::lang.email_templates.content_html
|
||||
|
||||
content_text:
|
||||
type: textarea
|
||||
size: huge
|
||||
tab: system::lang.email_templates.content_text
|
||||
|
|
@ -76,8 +76,8 @@ trait PropertyContainer
|
|||
|
||||
/**
|
||||
* Returns a defined property value or default if one is not set.
|
||||
* @param $name The property name to look for.
|
||||
* @param $default A default value to return if no name is found.
|
||||
* @param string $name The property name to look for.
|
||||
* @param string $default A default value to return if no name is found.
|
||||
* @return string The property value or the default specified.
|
||||
*/
|
||||
public function property($name, $default = null)
|
||||
|
|
|
|||
Loading…
Reference in New Issue