Merge branch 'settings' into dev

This commit is contained in:
Michal Kváček
2016-03-14 00:53:48 +01:00
22 changed files with 484 additions and 31 deletions
+1 -1
View File
@@ -123,7 +123,7 @@ abstract class Handler implements AppHandler
$sub->route('customfields.overview', trans('admin/mainMenu.customFieldsOverview'), [], 50, ['icon' => 'fa fa-code-fork']);
}, 30, ['icon' => 'fa fa-code']);
$menu->route('log.overview', trans('admin/mainMenu.actionLog'), [], 40, ['icon' => 'fa fa-history']);
$menu->url('#', trans('admin/mainMenu.settings'), 50, ['icon' => 'fa fa-gear']);
$menu->route('settings.overview', trans('admin/mainMenu.settings'), [], 50, ['icon' => 'fa fa-gear']);
});
// order
@@ -0,0 +1,56 @@
<?php
namespace App\Handlers\Registrators\Items;
class SettingExtension
{
/**
* @var string human readable ID of settings section (used e.g. as ID parameter in html)
*/
protected $id;
/**
* @var string translations string used for describing briefly settings section
*/
protected $name;
/**
* @var string view used for rendering given settings part
*/
protected $view;
/**
* SettingExtension constructor.
*
* @param string $id
* @param string $name
* @param string $view
*/
public function __construct($id, $name, $view)
{
$this->id = $id;
$this->name = $name;
$this->view = $view;
}
/**
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return string
*/
public function getView()
{
return $this->view;
}
}
@@ -0,0 +1,68 @@
<?php
namespace App\Handlers\Registrators;
use App\Enumerations\Exceptions\EnumerationExistsException;
use App\Handlers\Registrators\Items\SettingExtension;
class SettingsExtensionRegistrator
{
protected $settingsExtensions;
function __construct($app)
{
$this->settingsExtensions = [];
}
/**
* Method for registering new settings extensions/parts
*
* @param $sectionId
* @param $sectionName
* @param $sectionView
*
* @throws EnumerationExistsException
*/
public function register($sectionId, $sectionName, $sectionView)
{
$this->checkIfRegistered($sectionId);
// register new extension
$this->settingsExtensions[$sectionId] = new SettingExtension($sectionId, $sectionName, $sectionView);
}
/**
* Registers new setting part - only as SettingExtension directly
*
* @param SettingExtension $extension
*/
public function registerObject(SettingExtension $extension)
{
$this->checkIfRegistered($extension->getId());
$this->settingsExtensions[$extension->getId()] = $extension;
}
/**
* Getter for all registered extensions
*
* @return array
*/
public function get()
{
return $this->settingsExtensions;
}
/**
* Checks if this section is not already defined
*
* @param $sectionId
*
* @throws EnumerationExistsException
*/
private function checkIfRegistered($sectionId)
{
if (isset($this->settingsExtensions[$sectionId])) {
throw new EnumerationExistsException('Already existing key ' . $sectionId);
}
}
}
+60
View File
@@ -0,0 +1,60 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests;
use Illuminate\Support\Facades\App;
class Settings extends Controller
{
/**
* @var \App\Models\Settings
*/
protected $settings;
/**
* Settings constructor.
*
* @param \App\Models\Settings $settings
*/
public function __construct(\App\Models\Settings $settings)
{
$this->settings = $settings;
}
public function getOverview()
{
$sections = App::make('registerSettingsExtension')
->get();
$settings = $this->settings->getAll();
return view('admin.settings.overview', [
'formSections' => $sections,
'settings' => $settings
]);
}
public function saveSettings(Requests\SaveSettingsRequest $request)
{
$data = $request->all();
// remove CSRF token field
unset($data['_token']);
$settings = $this->settings->getAll();
$updated = 0;
foreach($data as $key => $value) {
if ($settings->$key != $value) {
$updated ++;
\App\Models\Settings::where('key', $key)->update(['value' => $value]);
}
}
if ($updated > 0) {
return redirect()->route('settings.overview')->with('success', trans('admin/settings.successfullySaved'));
} else {
return redirect()->route('settings.overview')->with('error', trans('admin/settings.nothingToSave'));
}
}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace App\Http\Requests;
class SaveSettingsRequest extends Request
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'pageName' => 'required',
];
}
}
+7
View File
@@ -215,6 +215,13 @@ Route::group([
Route::post('upload/image', 'UploadFile@postImage')
->name('upload.postImage');
// form with settings
Route::get('settings', 'Settings@getOverview')
->name('settings.overview');
Route::post('settings', 'Settings@saveSettings')
->name('settings.save');
// custom fields
// ------------------------------
+56
View File
@@ -0,0 +1,56 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Settings extends Model
{
protected $table = 'settings';
public $timestamps = false;
protected $fillable = ['key', 'value'];
/**
* Load all settings
*
* @return \stdClass
*/
public function getAll()
{
$settings = Settings::select(['key', 'value'])
->get();
return $this->returnPairs($settings);
}
/**
* Load only config for views
*
* @return \stdClass
*/
public function getForView()
{
$settings = Settings::select(['key', 'value'])
->where('load_into_views', 1)
->get();
return $this->returnPairs($settings);
}
/**
* From pair <key, value> create object key => value
*
* @param $settings
*
* @return \stdClass
*/
private function returnPairs($settings)
{
$data = new \stdClass();
foreach ($settings as $conf) {
$data->{$conf->key} = $conf->value;
}
return $data;
}
}
+17
View File
@@ -2,6 +2,7 @@
namespace App\Providers;
use App\Handlers\Registrators\SettingsExtensionRegistrator;
use App\Handlers\Registrators\TemplateRegistrator;
use App\Handlers\Registrators\WidgetRegistrator;
use App\Widgets\HtmlCode\HtmlCode;
@@ -18,6 +19,7 @@ class AppServiceProvider extends ServiceProvider
{
$this->registerWidgets();
$this->registerTemplates();
$this->registerSettings();
}
/**
@@ -45,6 +47,10 @@ class AppServiceProvider extends ServiceProvider
$this->app->singleton('registerTemplateDir', function ($app) {
return new TemplateRegistrator($app);
});
$this->app->singleton('registerSettingsExtension', function ($app) {
return new SettingsExtensionRegistrator($app);
});
}
/**
@@ -74,4 +80,15 @@ class AppServiceProvider extends ServiceProvider
$registrator->register(config('app.theme'), 'admin/templates.core');
}
/**
* Register setting sections
*/
private function registerSettings()
{
$registrator = $this->app->make('registerSettingsExtension');
$registrator->register('basic', 'admin/settings.basic', 'admin.settings.parts.basic');
$registrator->register('meta', 'admin/settings.meta', 'admin.settings.parts.meta');
}
}
+36 -23
View File
@@ -2,6 +2,7 @@
namespace App\Providers;
use App\Models\Settings;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
@@ -14,8 +15,42 @@ class GlobalViewDataProvider extends ServiceProvider
*/
public function boot()
{
view()->share('vendorName', 'ja s.r.o.');
$settings = new Settings();
foreach ($settings->getForView() as $key => $value) {
view()->share($key, $value);
}
$this->extendBlade();
}
/**
* Creates pattern for matching Blade directives
*
* @param $function
*
* @return string
*/
private function createPattern($function)
{
return '/(?<!\w)(\s*)@' . $function . '\(\s*(.*)\)/';
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Create new Blade directives
*/
private function extendBlade()
{
// extend Blade "@extends" macro - with this macro allows to use "hierarchy" in templates
Blade::extend(function ($view) {
$pattern = $this->createPattern('extendVisitor');
@@ -48,26 +83,4 @@ class GlobalViewDataProvider extends ServiceProvider
return preg_replace($pattern, $code, $view);
});
}
/**
* Creates pattern for matching Blade directives
*
* @param $function
*
* @return string
*/
private function createPattern($function)
{
return '/(?<!\w)(\s*)@' . $function . '\(\s*(.*)\)/';
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
//
}
}
@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateSettingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->integer('id', true);
$table->string('key', 64)
->unique()
->comment('User readable key for accessing value of this config. Config will be available under this key also in views.');
$table->text('value')
->comment('Value of config.');
$table->boolean('load_into_views')
->default(true)
->comment('Use in views directly?')
->index();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('settings');
}
}
+1
View File
@@ -15,5 +15,6 @@ class DatabaseSeeder extends Seeder
$this->call(SeedCustomFieldTypes::class);
$this->call(SeedCustomFieldResources::class);
$this->call(SeedActionLogTypes::class);
$this->call(SeedSettings::class);
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Seeder;
class SeedSettings extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$types = [
['key' => 'pageName', 'value' => ''],
['key' => 'author', 'value' => ''],
['key' => 'metaKeywords', 'value' => ''],
['key' => 'metaDescription', 'value' => ''],
['key' => 'googleAnalyticsCode', 'value' => ''],
];
foreach ($types as $type) {
\DB::table('settings')
->insert($type);
}
}
}
+14
View File
@@ -0,0 +1,14 @@
<?php
return [
'overview' => 'All available settings',
'basic' => 'Basic information',
'save' => 'Save',
'pageName' => 'Page name',
'metaKeywords' => 'Web keywords',
'metaDescription' => 'Web description',
'googleAnalyticsCode' => 'Google Analytics code',
'author' => 'Page owner',
'successfullySaved' => 'Settings successfully saved',
'nothingToSave' => 'You have submitted unchanged form. Try to change some attribute first.',
'meta' => 'Meta information'
];
+2 -2
View File
@@ -5,7 +5,7 @@
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@yield('head_meta')
<title>@yield('pageName', @trans('admin/common.admin')) | {{$vendorName}}</title>
<title>@yield('pageName', @trans('admin/common.admin')) | {{$pageName}}</title>
<link rel="stylesheet" href="{{asset('../resources/assets/css/foundation.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/font-awesome.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/admin.css')}}" />
@@ -48,7 +48,7 @@
</div>
<footer class="row text-center">
&copy; {{$vendorName}} {{date('Y')}}
&copy; {{$pageName}} {{date('Y')}}
</footer>
</div>
<script src="{{asset('../resources/assets/js/vendor/jquery.min.js')}}"></script>
@@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@lang('admin/loginForm.login') | {{$vendorName}}</title>
<title>@lang('admin/loginForm.login') | {{$pageName}}</title>
<link rel="stylesheet" href="{{asset('../resources/assets/css/foundation.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/admin.css')}}" />
</head>
@@ -0,0 +1,50 @@
@extends('admin.layout')
@section('pageName', @trans('admin/settings.overview'))
@section('content')
<div class="row">
<h2>@lang('admin/settings.overview')</h2>
</div>
@if (session('success'))
<div data-alert class="callout success">
<strong>{{ session('success') }}</strong>
</div>
@endif
@if (session('error'))
<div data-alert class="callout alert">
<strong>{{ session('error') }}</strong>
</div>
@endif
<div class="row">
<ul class="tabs" data-tabs id="static-page-controls">
@foreach($formSections as $id => $section)
<li class="tabs-title @if($section->getId() == reset($formSections)->getId()) is-active @endif">
<a href="#{{$id}}" @if($section->getId() == reset($formSections)->getId()) aria-selected="true" @endif>
{{trans($section->getName())}}
</a>
</li>
@endforeach
</ul>
<form action="{{route('settings.save')}}" method="POST">
{!! csrf_field() !!}
<div class="tabs-content" data-tabs-content="static-page-controls">
@foreach($formSections as $id => $section)
<div class="tabs-panel @if($id == reset($formSections)->getId()) is-active @endif" id="{{$section->getId()}}">
@include($section->getView())
</div>
@endforeach
</div>
<div class="row">
<div class="columns large-12">
<button type="submit" class="button success">@lang('admin/settings.save')</button>
</div>
</div>
</form>
</div>
@stop
@@ -0,0 +1,17 @@
<label>
@lang('admin/settings.pageName')
<input type="text" name="pageName" value="{{old('pageName', $settings->pageName)}}" />
</label>
<label>
@lang('admin/settings.author')
<input type="text" name="author" value="{{old('author', $settings->author)}}" />
</label>
<label>
@lang('admin/settings.googleAnalyticsCode')
<input type="text" name="googleAnalyticsCode" value="{{old('googleAnalyticsCode', $settings->googleAnalyticsCode)}}" />
</label>
@@ -0,0 +1,11 @@
<label>
@lang('admin/settings.metaKeywords')
<input type="text" name="metaKeywords" value="{{old('metaKeywords', $settings->metaKeywords)}}" />
</label>
<label>
@lang('admin/settings.metaDescription')
<textarea name="metaDescription" rows="3">{{old('metaDescription', $settings->metaDescription)}}</textarea>
</label>
@@ -5,7 +5,7 @@
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@yield('head_meta')
<title>@yield('pageName', @trans('visitor/common.welcome')) | {{$vendorName}}</title>
<title>@yield('pageName', @trans('visitor/common.welcome')) | {{$pageName}}</title>
<link rel="stylesheet" href="{{asset('../resources/assets/css/foundation.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/font-awesome.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/admin.css')}}" />
@@ -5,7 +5,7 @@
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@yield('head_meta')
<title>@yield('pageName', @trans('visitor/common.welcome')) | {{$vendorName}}</title>
<title>@yield('pageName', @trans('visitor/common.welcome')) | {{$pageName}}</title>
<link rel="stylesheet" href="{{asset('../resources/assets/css/foundation.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/font-awesome.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/admin.css')}}" />
@@ -5,7 +5,7 @@
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@yield('head_meta')
<title>@yield('pageName', @trans('visitor/common.welcome')) | {{$vendorName}}</title>
<title>@yield('pageName', @trans('visitor/common.welcome')) | {{$pageName}}</title>
<link rel="stylesheet" href="{{asset('../resources/assets/css/foundation.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/font-awesome.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/admin.css')}}" />
+1 -1
View File
@@ -5,7 +5,7 @@
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@yield('head_meta')
<title>@yield('pageName', @trans('visitor/common.welcome')) | {{$vendorName}}</title>
<title>@yield('pageName', @trans('visitor/common.welcome')) | {{$pageName}}</title>
<link rel="stylesheet" href="{{asset('../resources/assets/css/foundation.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/font-awesome.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/admin.css')}}" />