Merge branch 'dev' into module_profiler

This commit is contained in:
Michal Kváček
2017-09-23 00:45:51 +02:00
711 changed files with 14073 additions and 84301 deletions
+5 -4
View File
@@ -1,3 +1,6 @@
/modules
/templates
# published files from modules
/public/modules
/public/assets
@@ -9,9 +12,6 @@
**/views/**/custom/*
!**/views/**/custom/.gitkeep
# module config - generated in ModuleManager service provider
**/module.json
# uploaded files
/public/uploads/*
!/public/uploads/.gitkeep
@@ -32,4 +32,5 @@
/public/js
/public/fonts
/bower_components
.sass-cache
.sass-cache
!/resources/views/vendor/
+1 -1
View File
@@ -10,7 +10,7 @@ interface Module extends BaseRepository
public function getUpdateContentTitle(ModuleModel $module, ContentModel $content = null);
public function getOverviewTitle(ModuleModel $module);
public function getOverviewTitle(ModuleModel $module = null);
public function getByHandler($handler);
+1 -1
View File
@@ -9,7 +9,7 @@ class UserRoles extends BaseEnumeration
{
$roles = [
User::ROLE_ADMIN => 'admin/userManagement.role_' . User::ROLE_ADMIN,
User::ROLE_EDITOR => 'admin/userManagement.role_' . User::ROLE_EDITOR,
// User::ROLE_EDITOR => 'admin/userManagement.role_' . User::ROLE_EDITOR,
User::ROLE_VISITOR => 'admin/userManagement.role_' . User::ROLE_VISITOR
];
@@ -1,19 +1,17 @@
<?php
namespace App\CMS\Handlers;
use App\CMS\Contracts\Modules\AppHandler;
use App\Http\Controllers\Controller;
use App\Models\Content\Content;
use App\Models\FileManager\File;
/**
* Class Handler
*
* Handler is a class which handles module-specific behaviour which cannot be done by module itself, resp. cannot be
* done by some abstract magic.
*
* @package App\CMS\Handlers\
*/
abstract class Handler extends BaseHandler implements AppHandler
abstract class AdminHandler extends BaseHandler implements AppHandler
{
public static function getHistoryHandler()
{
@@ -22,26 +20,38 @@ abstract class Handler extends BaseHandler implements AppHandler
public static function getExtendedFormSections()
{
return [
$formParts = [
'basicInfo' => trans('admin/contents.basicInfo'),
'meta' => trans('admin/contents.metaOptions'),
'publication' => trans('admin/contents.publicationOptions'),
'appearance' => trans('admin/contents.appearance'),
'files' => trans('admin/contents.files')
];
if (\Auth::user()->cannot('upload', File::class)) {
unset($formParts['files']);
}
return $formParts;
}
public static function getExtendedFormInputsCreate()
{
return [
$formParts = [
'basicInfo' => 'admin.content.formParts.basicInformation',
'meta' => 'admin.content.formParts.metaInformation',
'publication' => 'admin.content.formParts.publicationSetup',
'appearance' => 'admin.content.formParts.appearance',
'files' => 'admin.content.formParts.files'
];
if (\Auth::user()->cannot('upload', File::class)) {
unset($formParts['files']);
}
return $formParts;
}
public static function getExtendedFormInputsEdit()
{
return self::getExtendedFormInputsCreate();
+68 -43
View File
@@ -1,16 +1,24 @@
<?php
namespace App\CMS\Handlers;
use App\CMS\Contracts\Modules\BaseModuleHandler;
use App\CMS\Enumerations\TemplatePathsHumanReadableRootOnly;
use App\CMS\Enumerations\WidgetTypes;
use App\CMS\Repositories\Module;
use App\Models\ActionLog\ActionLog;
use App\Models\Content\Content;
use App\Models\FileManager\File;
use App\Models\Settings;
use App\Models\Templates\Template;
use App\Models\User;
use App\Models\Widgets\Widget;
use App\Models\Widgets\WidgetArea;
abstract class BaseHandler implements BaseModuleHandler
{
/**
* Register admin menu (or multiple ones)
*
* This cannot be in ServiceProvider because Session is started at middleware. And ServiceProvider is called before
* starting any middleware..
*
@@ -25,84 +33,101 @@ abstract class BaseHandler implements BaseModuleHandler
}
// create instance of main menu
\Menu::create('mainMenu', function ($menu) {
\Menu::create('mainMenu', function ($menu) use ($user) {
// $menu->route('admin.dashboard', trans('admin/mainMenu.dashboard'), [], 10, ['icon' => 'fa fa-fw fa-dashboard']);
/**
* Content pages
*
* Submenus can be registered later
*/
$menu->dropdown(trans('admin/mainMenu.contentPages'), function ($sub) {
$sub->route('content.overview', trans('admin/mainMenu.contentPageOverview'), [], 10000, ['icon' => 'fa fa-fw fa-list']);
}, 20, ['icon' => 'fa fa-fw fa-database']);
$contentModules = app(Module::class)->getContentModules();
if ($user->can('manage', Content::class) && !$contentModules->isEmpty()) {
$menu->dropdown(trans('admin/mainMenu.contentPages'), function ($sub) {
$sub->route('content.order', trans('admin/mainMenu.contentOrder'), [], 999, ['icon' => 'fa fa-fw fa-reorder']);
$sub->route('content.overview', trans('admin/mainMenu.contentPageOverview'), [], 10000, ['icon' => 'fa fa-fw fa-list']);
}, 20, ['icon' => 'fa fa-fw fa-database']);
}
/**
* File manager
*/
$menu->route('upload.overview', trans('admin/mainMenu.fileManager'), [], 40, ['icon' => 'fa fa-fw fa-folder']);
if ($user->can('manage', File::class)) {
$menu->route('upload.overview', trans('admin/mainMenu.fileManager'), [], 40, ['icon' => 'fa fa-fw fa-folder']);
}
/**
* Widgets and widget areas
*/
$menu->dropdown(trans('admin/mainMenu.widgets'), function ($sub) {
// create list of all widget types
$widgets = WidgetTypes::getWithTranslations();
if ($user->can('manage', Widget::class) || $user->can('manage', WidgetArea::class)) {
$menu->dropdown(trans('admin/mainMenu.widgets'), function ($sub) use ($user) {
// create list of all widget types
$widgets = WidgetTypes::getWithTranslations();
if (!empty($widgets)) {
$sub->dropdown(trans('admin/mainMenu.newWidget'), function ($sub) use ($widgets) {
$i = 1;
foreach ($widgets as $type => $name) {
$sub->route('widgets.new', $name, ['type' => $type], $i++);
}
}, 10, ['icon' => 'fa fa-fw fa-plus']);
}
if (!empty($widgets) && $user->can('create', Widget::class)) {
$sub->dropdown(trans('admin/mainMenu.newWidget'), function ($sub) use ($widgets) {
$i = 1;
foreach ($widgets as $type => $name) {
$sub->route('widgets.new', $name, ['type' => $type], $i++);
}
}, 10, ['icon' => 'fa fa-fw fa-plus']);
}
if ($user->can('manage', Widget::class)) {
$sub->route('widgets.overview', trans('admin/mainMenu.widgetsOverview'), [], 20, ['icon' => 'fa fa-fw fa-list']);
}
$sub->route('widgets.overview', trans('admin/mainMenu.widgetsOverview'), [], 20, ['icon' => 'fa fa-fw fa-list']);
// menu for widget areas
$sub->dropdown(trans('admin/mainMenu.widgetAreas'), function ($sub) {
$sub->route('widgetareas.new', trans('admin/mainMenu.newWidgetArea'), [], 1, ['icon' => 'fa fa-fw fa-plus']);
$sub->route('widgetareas.overview', trans('admin/mainMenu.widgetAreaOverview'), [], 2, ['icon' => 'fa fa-fw fa-list']);
}, 50, ['icon' => 'fa fa-fw fa-object-group']);
}, 50, ['icon' => 'fa fa-fw fa-puzzle-piece']);
// menu for widget areas
if ($user->can('manage', WidgetArea::class)) {
$sub->dropdown(trans('admin/mainMenu.widgetAreas'), function ($sub) use ($user) {
if ($user->can('create', WidgetArea::class)) {
$sub->route('widgetareas.new', trans('admin/mainMenu.newWidgetArea'), [], 1, ['icon' => 'fa fa-fw fa-plus']);
}
$sub->route('widgetareas.overview', trans('admin/mainMenu.widgetAreaOverview'), [], 2, ['icon' => 'fa fa-fw fa-list']);
}, 50, ['icon' => 'fa fa-fw fa-object-group']);
}
}, 50, ['icon' => 'fa fa-fw fa-puzzle-piece']);
}
/**
* Divide system entries and other links in menu
*/
$menu->addDivider(9999);
$menu->dropdown(trans('admin/mainMenu.system'), function ($sub) {
$menu->dropdown(trans('admin/mainMenu.system'), function ($sub) use ($user) {
/**
* User management
*/
$sub->dropdown(trans('admin/mainMenu.userManagement'), function ($sub) {
$sub->route('users.new', trans('admin/mainMenu.newUser'), [], 10, ['icon' => 'fa fa-fw fa-user-plus']);
$sub->route('users.overview', trans('admin/mainMenu.usersOverview'), [], 30, ['icon' => 'fa fa-fw fa-users']);
}, 20, ['icon' => 'fa fa-fw fa-users']);
if ($user->can('manage', User::class)) {
$sub->dropdown(trans('admin/mainMenu.userManagement'), function ($sub) use ($user) {
if ($user->can('create', User::class)) {
$sub->route('users.new', trans('admin/mainMenu.newUser'), [], 10, ['icon' => 'fa fa-fw fa-user-plus']);
}
$sub->route('users.overview', trans('admin/mainMenu.usersOverview'), [], 30, ['icon' => 'fa fa-fw fa-users']);
}, 20, ['icon' => 'fa fa-fw fa-users']);
}
/**
* Templates
*/
$templatePaths = TemplatePathsHumanReadableRootOnly::getWithTranslations();
if (!empty($templatePaths)) {
$sub->dropdown(trans('admin/mainMenu.templates'), function ($sub) use ($templatePaths) {
$i = 1;
foreach ($templatePaths as $id => $name) {
$sub->route('templates.overview', $name, ['id' => $id], $i++);
}
}, 60, ['icon' => 'fa fa-fw fa-file-code-o']);
if ($user->can('manage', Template::class)) {
$sub->route('templates.index', trans('admin/mainMenu.templates'), [], 70, ['icon' => 'fa fa-fw fa-file-code-o']);
}
$sub->route('log.overview', trans('admin/mainMenu.actionLog'), [], 70, ['icon' => 'fa fa-fw fa-history']);
$sub->route('settings.overview', trans('admin/mainMenu.settings'), [], 80, ['icon' => 'fa fa-fw fa-gear']);
if ($user->can('manage', ActionLog::class)) {
$sub->route('log.overview', trans('admin/mainMenu.actionLog'), [], 70, ['icon' => 'fa fa-fw fa-history']);
}
if ($user->can('manage', Settings::class)) {
$sub->route('settings.overview', trans('admin/mainMenu.settings'), [], 80, ['icon' => 'fa fa-fw fa-gear']);
$sub->route('permissions.index', trans('admin/mainMenu.permissions'), [], 90, ['icon' => 'fa fa-fw fa-key']);
}
}, 10000, ['icon' => 'fa fa-fw fa-gears']);
});
// create menu with user profile
\Menu::create('profileMenu', function ($menu) {
$menu->route('users.detail', trans('admin/userManagement.profile'), [], 10, ['icon' => 'fa fa-fw fa-user icon']);
\Menu::create('profileMenu', function ($menu) use ($user) {
$menu->route('users.detail', trans('admin/userManagement.profile'), ['user' => $user], 10, ['icon' => 'fa fa-fw fa-user icon']);
$menu->addDivider(999);
$menu->route('logout', trans('admin/common.logout'), [], 1000, ['icon' => 'fa fa-fw fa-power-off icon']);
});
+3 -4
View File
@@ -17,8 +17,7 @@ class History implements HistoryHandler
switch ($changeset->column) {
case 'pageContent':
$route = route('history.diff', [
'revision' => $changeset->edit_batch,
'id' => $changeset->id
'revision' => $changeset->id
]);
return "(<a href='" . $route . "'>" . trans('admin/history.diff') . "</a>)";
@@ -48,8 +47,8 @@ class History implements HistoryHandler
break;
default:
return trans('admin/history.changedFromTo', [
'from' => is_null($changeset->old_value) ? trans('admin/history.emptyValue') : $changeset->old_value,
'to' => is_null($changeset->new_value) ? trans('admin/history.emptyValue') : $changeset->new_value,
'from' => empty($changeset->old_value) ? trans('admin/history.emptyValue') : $changeset->old_value,
'to' => empty($changeset->new_value) ? trans('admin/history.emptyValue') : $changeset->new_value,
]);
break;
}
@@ -15,6 +15,7 @@ class SettingExtension
* @var string view used for rendering given settings part
*/
protected $view;
protected $order;
/**
* SettingExtension constructor.
@@ -23,11 +24,12 @@ class SettingExtension
* @param string $name
* @param string $view
*/
public function __construct($id, $name, $view)
public function __construct($id, $name, $view, $order)
{
$this->id = $id;
$this->name = $name;
$this->view = $view;
$this->order = $order;
}
/**
@@ -53,4 +55,14 @@ class SettingExtension
{
return $this->view;
}
/**
* @return mixed
*/
public function getOrder()
{
return $this->order;
}
}
@@ -1,7 +1,7 @@
<?php
namespace App\CMS\Handlers\Registrators;
use App\CMS\Enumerations\Exceptions\EnumerationExistsException;
use App\CMS\Exceptions\Enumerations\EnumerationExistsException;
use App\CMS\Handlers\Contracts\SearchHandler;
use App\CMS\Handlers\Contracts\SearchPresenterHandler;
use App\CMS\Handlers\Registrators\Items\SearchEngine;
@@ -1,7 +1,8 @@
<?php
namespace App\CMS\Handlers\Registrators;
use App\CMS\Enumerations\Exceptions\EnumerationExistsException;
use App\CMS\Exceptions\Enumerations\EnumerationExistsException;
use App\CMS\Handlers\Registrators\Items\SettingExtension;
class SettingsExtensionRegistrator
@@ -22,12 +23,16 @@ class SettingsExtensionRegistrator
*
* @throws EnumerationExistsException
*/
public function register($sectionId, $sectionName, $sectionView)
public function register($sectionId, $sectionName, $sectionView, $order = null)
{
$this->checkIfRegistered($sectionId);
if (is_null($order)) {
$order = count($this->settingsExtensions);
}
// register new extension
$this->settingsExtensions[$sectionId] = new SettingExtension($sectionId, $sectionName, $sectionView);
$this->settingsExtensions[$sectionId] = new SettingExtension($sectionId, $sectionName, $sectionView, $order);
}
/**
@@ -44,14 +49,15 @@ class SettingsExtensionRegistrator
/**
* Getter for all registered extensions
*
* @return array
*/
public function get()
{
// sort registered extensions by key
ksort($this->settingsExtensions);
// sort registered extensions
uasort($this->settingsExtensions, function (SettingExtension $a, SettingExtension $b) {
return $a->getOrder() - $b->getOrder();
});
return $this->settingsExtensions;
}
@@ -207,6 +207,7 @@ class TemplateRegistrator
protected function registerTemplates($path, $templatePathId)
{
$templates = File::files($path);
$registeredTemplates = Templates::getWithTranslations();
foreach ($templates as $template) {
@@ -217,7 +218,6 @@ class TemplateRegistrator
// get all templates and template name (path/to/template.blade.php -> path.to.template)
$templateName = $this->getTemplateName($template);
$registeredTemplates = Templates::getWithTranslations();
if (!in_array($templateName, $registeredTemplates)) {
$params = [
@@ -316,4 +316,14 @@ class TemplateRegistrator
return $this->namespace . trim($templateName, '.');
}
public function deleteNonExistingPaths()
{
$paths = TemplatePath::all();
foreach ($paths as $path) {
if (!is_dir(base_path($path->path)))
\File::deleteDirectory($path->path);
}
}
}
+9 -1
View File
@@ -1,7 +1,10 @@
<?php
namespace App\CMS\Handlers\Search;
use App\Models\Content\Content as ContentModel;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
class Content extends Search
{
@@ -10,10 +13,15 @@ class Content extends Search
*
* @param string $term searched word
*
* @return array list of found objects
* @return array|\Illuminate\Database\Eloquent\Collection|Collection|static[]
*/
public function search($term)
{
if (Auth::user()
->cannot('manage', ContentModel::class)) {
return new Collection();
}
$token = $this->tokenize($term);
return ContentModel::where('pageContent', 'LIKE', $token)
+7
View File
@@ -1,7 +1,9 @@
<?php
namespace App\CMS\Handlers\Search;
use App\Models\FileManager\File;
use Illuminate\Support\Collection;
class Files extends Search
{
@@ -24,6 +26,11 @@ class Files extends Search
*/
public function search($term)
{
if (\Auth::user()
->cannot('manage', File::class)) {
return new Collection();
}
$token = $this->tokenize($term);
return File::where('original_filename', 'LIKE', $token)
@@ -3,11 +3,17 @@ namespace App\CMS\Handlers\Search\Presenters;
use App\CMS\Enumerations\ContentStatuses;
use App\CMS\Handlers\Contracts\SearchPresenterHandler;
use App\Models\Content\Content;
class AdminContent implements SearchPresenterHandler
{
public function render($foundItems)
{
if (\Auth::user()
->cannot('manage', Content::class)) {
return null;
}
return view('admin.search.results.content', [
'pages' => $foundItems,
'statuses' => ContentStatuses::getWithTranslations(),
@@ -2,6 +2,7 @@
namespace App\CMS\Handlers\Search\Presenters;
use App\CMS\Handlers\Contracts\SearchPresenterHandler;
use App\Models\FileManager\File;
class AdminFiles implements SearchPresenterHandler
{
@@ -14,6 +15,11 @@ class AdminFiles implements SearchPresenterHandler
*/
public function render($foundItems)
{
if (\Auth::user()
->cannot('manage', File::class)) {
return null;
}
return view('admin.fileManager.filesTiles', ['files' => $foundItems, 'hideDelete' => true]);
}
}
+1 -8
View File
@@ -22,16 +22,9 @@ class CurrentTemplate implements TemplateHandler
{
if (!self::$initialized) {
self::$template = Cache::rememberForever('current-template', function () {
$template = Module::where('is_template', true)
return Module::where('is_template', true)
->where('enabled', true)
->first();
// todo remove after adding $casts into Module model
if ($template) {
$template->module_settings = json_decode($template->module_settings);
}
return $template;
});
-37
View File
@@ -1,37 +0,0 @@
<?php
namespace App\CMS\Helpers;
use App\CMS\Handlers\Contracts\AppHandler;
use App\Models\Content\Content;
use Webwizo\Shortcodes\Facades\Shortcode;
/**
* Class PageRenderer
*
* Simple class for rendering page for visitor
*
* @package App\CMS\Helpers
*/
class PageRenderer
{
/**
* Render page
*
* @param Content $page
*
* @return mixed
*/
public static function render(Content $page)
{
// do something template-specific
$parameters = call_user_func_array([CurrentTemplate::handler(), 'beforeRender'], [&$page]);
/**
* @var $handler AppHandler
*/
$handler = new $page->moduleHandler;
// render page
return $handler->render($page, $parameters);
}
}
+2 -2
View File
@@ -2,6 +2,7 @@
namespace App\CMS\Helpers;
use App\CMS\Repositories\Settings\Settings as SettingsRepository;
use App\Models\Settings as SettingsModel;
use Illuminate\Support\Facades\Cache;
@@ -78,8 +79,7 @@ class Settings
{
if (!self::$initialized) {
self::$settings = Cache::remember('settings', config('cache.settingCacheLifetime'), function () {
$model = new SettingsModel();
return $model->getAll();
return app(SettingsRepository::class)->getAll();
});
}
}
+17 -8
View File
@@ -1,7 +1,8 @@
<?php
namespace App\CMS\Helpers;
use App\Models\Widgets\WidgetArea;
use App\CMS\Repositories\Widgets\WidgetArea as WidgetAreaRepository;
use Illuminate\Support\Facades\Cache;
class WidgetAreas
@@ -25,15 +26,13 @@ class WidgetAreas
protected static function loadWidgetArea($uniqueCode)
{
$widgets = Cache::remember('widget-' . $uniqueCode, setting('widgetCacheLifetime', 5), function () use ($uniqueCode) {
$widgetArea = new WidgetArea();
$widgets = Cache::remember('widget-area-' . $uniqueCode, setting('widgetCacheLifetime', 5), function () use ($uniqueCode) {
$widgetArea = app(\App\CMS\Repositories\Widgets\WidgetArea::class);
return $widgetArea->getWidgets($uniqueCode)
->get();
});
WidgetArea::where('code', $uniqueCode)
->increment('viewed');
self::saveRenderedWidgetArea($widgets);
}
@@ -44,7 +43,7 @@ class WidgetAreas
}
$widgets = Cache::remember('widgets', setting('widgetCacheLifetime', 5), function () {
$widgetArea = new WidgetArea();
$widgetArea = app(WidgetAreaRepository::class);
return $widgetArea->getWidgets()
->get();
});
@@ -58,7 +57,7 @@ class WidgetAreas
*
* @param $uniqueCode
*
* @return mixed
* @return void
*/
public static function render($uniqueCode)
{
@@ -72,4 +71,14 @@ class WidgetAreas
echo isset(self::$widgetAreas[$uniqueCode]) ? self::$widgetAreas[$uniqueCode] : null;
}
/**
* Get list of loaded widgets and areas
*
* @return array
*/
public static function getLoadedWidgets()
{
return ['areas' => array_keys(self::$widgetAreas)];
}
}
@@ -31,22 +31,13 @@ class CreateDirectory implements Interaction
{
$data['parentDirectory'] = isset($data['parentDirectory']) ? $data['parentDirectory'] : null;
// todo this should probably go into validation, but we are not able to get $data in getValidationRules
// check if created folder does not exist in current directory
if ($this->repository->checkIfNameExists($data['name'], $data['parentDirectory'])) {
throw new SubdirectoryExistsInDirectory();
}
// todo use Directory::create() and rename columns/fields in request
// create new database entry
$directory = new Directory();
$directory->name = $data['name'];
$directory->parent_id = $data['parentDirectory'];
$directory->user_id = \Auth::user()->id;
$directory->description = $data['description'];
$directory->save();
return $directory;
return $this->repository->create($data);
}
/**
@@ -1,8 +1,9 @@
<?php
namespace App\CMS\MenuPresenters;
use Pingpong\Menus\MenuItem;
use Pingpong\Menus\Presenters\Presenter;
use Nwidart\Menus\MenuItem;
use Nwidart\Menus\Presenters\Presenter;
class FoundationDrilldownMenuPresenter extends Presenter
{
@@ -1,7 +1,8 @@
<?php
namespace App\CMS\MenuPresenters;
use Pingpong\Menus\Presenters\Presenter;
use Nwidart\Menus\Presenters\Presenter;
class FoundationDropdownMenuPresenter extends Presenter
{
@@ -27,7 +28,7 @@ class FoundationDropdownMenuPresenter extends Presenter
public function getMenuWithoutDropdownWrapper($item)
{
$link = '<a href="' . $item->getUrl() . '">' . $item->getIcon() . ' ' . $item->title . '</a>';
return '<li' . $this->getActiveState($item) . '>' . $link . '</li>'.PHP_EOL;
return '<li' . $this->getActiveState($item) . '>' . $link . '</li>' . PHP_EOL;
}
/**
@@ -43,7 +44,7 @@ class FoundationDropdownMenuPresenter extends Presenter
*/
public function getDividerWrapper()
{
return '<li class="divider"></li>'.PHP_EOL;
return '<li class="divider"></li>' . PHP_EOL;
}
/**
@@ -1,8 +1,9 @@
<?php
namespace App\CMS\MenuPresenters;
use Pingpong\Menus\MenuItem;
use Pingpong\Menus\Presenters\Presenter;
use Nwidart\Menus\MenuItem;
use Nwidart\Menus\Presenters\Presenter;
class MetismenuPresenter extends Presenter
{
@@ -27,6 +28,10 @@ class MetismenuPresenter extends Presenter
*/
public function getMenuWithoutDropdownWrapper($item)
{
if (!is_string($item->getUrl())) {
return null;
}
return '<li' . $this->getActiveState($item) . '><a href="' . $item->getUrl() . '">' . $item->getIcon() . ' ' . $item->title . '</a></li>' . PHP_EOL;
}
@@ -1,8 +1,9 @@
<?php
namespace App\CMS\MenuPresenters;
use Pingpong\Menus\MenuItem;
use Pingpong\Menus\Presenters\Presenter;
use Nwidart\Menus\MenuItem;
use Nwidart\Menus\Presenters\Presenter;
class ProfileMenuPresenter extends Presenter
{
+64
View File
@@ -0,0 +1,64 @@
<?php
namespace App\CMS\ModuleManager;
use App\CMS\Contracts\Modules\AppHandler;
use App\CMS\Contracts\Modules\TemplateHandler;
use App\Models\Module;
use Illuminate\Support\Facades\App;
class Installer
{
/**
* Create new module in database
*
* @param $name
* @param $alias
* @param string $description
* @param null $handler
* @param $parentModuleId
* @param array $settings
*
* @return Module
* @throws \ErrorException
*/
public static function install($name, $alias, $staticName, $description, $handler, $parentModuleId, $settings)
{
// check if user does not want to install module in runtime
if (!App::runningInConsole()) {
throw new \ErrorException('Modules can be installed only via Artisan!');
}
$managesContent = $handler ? in_array(AppHandler::class, class_implements($handler)) : false;
$isTemplate = $handler ? in_array(TemplateHandler::class, class_implements($handler)) : false;
$supportCategories = $managesContent ? call_user_func([$handler, 'supportCategories']) : false;
if ($parentModuleId) {
$parentModule = Module::findOrFail($parentModuleId);
$parentModule->has_submodules = true;
$parentModule->save();
}
// insert module into database
$module = Module::create([
'name' => $name,
'description' => $description,
'handler' => $handler,
'static_name' => $staticName,
'manages_content' => $managesContent,
'support_categories' => $supportCategories,
'alias' => $alias,
'module_settings' => $settings,
'parent_id' => $parentModuleId ? $parentModuleId : null,
'enabled' => 1,
'is_template' => $isTemplate
]);
// install something module-specific
if ($handler && is_callable([$handler, 'install'])) {
call_user_func([$handler, 'install']);
}
return $module;
}
}
@@ -0,0 +1,54 @@
<?php
namespace App\CMS\ModuleManager\Providers;
use App\CMS\Repositories\Module as ModuleRepository;
use Illuminate\Database\QueryException;
use Illuminate\Support\ServiceProvider;
class ModuleManager extends ServiceProvider
{
/**
* Bootstrap the application services.
* @return void
*/
public function boot()
{
// this service provider needs published config - config is merged right after this service provider
try {
$modules = app(ModuleRepository::class)->all();
} catch (QueryException $e) {
return;
}
// iterate over all modules and enable or disable them
foreach ($modules as $module) {
if (isset($module->module_settings['providers']) && !empty($module->module_settings['providers'])) {
foreach ($module->module_settings['providers'] as $provider) {
$this->app->register($provider);
}
}
// include files (if any)
if (isset($module->module_settings['files']) && !empty($module->module_settings['files'])) {
foreach ($module->module_settings['files'] as $file) {
$path = config('modules.paths.modules') . '/' . $module->static_name . '/' . $file;
if (!file_exists($path)) {
$path = base_path($file);
}
@include_once $path;
}
}
}
}
/**
* Register the application services.
* @return void
*/
public function register()
{
}
}
+60
View File
@@ -0,0 +1,60 @@
<?php
namespace App\CMS\ModuleManager;
use App\Models\Module;
use App\Models\Templates\TemplatePath;
use Illuminate\Support\Facades\App;
class Uninstaller {
/**
* Delete module from database and uninstall its dependencies
*
* @param Module $module
*
* @throws \ErrorException
*/
public static function uninstall(Module $module)
{
// check if user does not want to install module in runtime
if (!App::runningInConsole()) {
throw new \ErrorException('Modules can be uninstalled only via Artisan!');
}
// delete everything in /resources/views/visitor
if ($module->is_template) {
self::deleteDirectory(resource_path('views/visitor'));
self::deleteDirectory(resource_path('views/modules'));
self::deleteDirectory(public_path('assets'));
// delete all template paths
TemplatePath::getQuery()
->delete();
}
if ($module->handler && is_callable([$module->handler, 'uninstall'])) {
call_user_func([$module->handler, 'uninstall'], $module);
}
$module->delete();
}
/**
* Delete directory when uninstalling module.
*
* @param $directory
*
* @throws \ErrorException
*/
private static function deleteDirectory($directory)
{
if (!is_dir($directory)) {
return;
}
$success = \File::deleteDirectory($directory, true);
if (!$success) {
throw new \ErrorException('Cannot delete ' . $directory);
}
}
}
@@ -1,18 +1,19 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
namespace App\CMS\Modules\ServiceProviders;
abstract class ModuleServiceProvider extends ServiceProvider
use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
abstract class ServiceProvider extends LaravelServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
protected $alias = false;
protected $path = false;
protected $publishViews = true;
abstract protected function setModuleAlias();
@@ -20,7 +21,6 @@ abstract class ModuleServiceProvider extends ServiceProvider
/**
* Boot the application events.
*
* @return void
*/
public function boot()
@@ -35,7 +35,6 @@ abstract class ModuleServiceProvider extends ServiceProvider
/**
* Register config.
*
* @return void
*/
protected function registerConfig()
@@ -50,7 +49,6 @@ abstract class ModuleServiceProvider extends ServiceProvider
/**
* Register views.
*
* @return void
*/
protected function registerViews()
@@ -62,14 +60,13 @@ abstract class ModuleServiceProvider extends ServiceProvider
return $path . '/modules/' . $this->alias;
}, \Config::get('view.paths')), [$sourcePath]), $this->alias);
if (is_dir($sourcePath)) {
if (is_dir($sourcePath) && $this->publishViews) {
$this->publishes([$sourcePath => $viewPath], 'module-views');
}
}
/**
* Register translations.
*
* @return void
*/
protected function registerTranslations()
@@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class $MigrationName$ extends Migration
{
/**
* Run migration
*/
public function up()
{
Schema::create('$TableName$', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
/**
* Rollback migration
*/
public function down()
{
Schema::dropIfExists('$TableName$');
}
}
+28
View File
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class $MigrationName$ extends Migration
{
/**
* Run migration
*/
public function up()
{
Schema::table('$TableName$', function (Blueprint $table) {
});
}
/**
* Rollback migration
*/
public function down()
{
Schema::table('$TableName$', function (Blueprint $table) {
});
}
}
@@ -0,0 +1,12 @@
<?php
return [
'name' => '$Module$',
'translatedName' => '$module$::$module$.name',
'translatedDescription' => '$module$::$module$.description',
'alias' => strtolower('$Module$'),
'handler' => \Modules\$Module$\Handlers\$Module$Handler::class,
'providers' => [\Modules\$Module$\Providers\$Module$ServiceProvider::class],
'files' => ['Http/routes.php'],
'order' => 0,
];
@@ -0,0 +1,10 @@
<?php
namespace Modules\$ModuleNamespace$\Entities;
use Illuminate\Database\Eloquent\Model;
class $Entity$ extends Model {
protected $table = 'contents';
// ...
}
@@ -0,0 +1,40 @@
<?php
namespace Modules\$ModuleNamespace$\Handlers;
use App\CMS\Contracts\Content\ContentTitles;
use App\Models\Content\Content;
class $Module$ContentHandler extends $Module$Handler implements ContentTitles
{
/**
* Get translated title for pages overview of given type.
* This value is used for rendering list of all content pages of given type in administration.
* @return string
*/
public static function getOverviewTitle()
{
// TODO: Implement getOverviewTitle() method.
}
/**
* Title displayed above for for creating new content page
* @return string
*/
public static function getCreateNewTitle()
{
// TODO: Implement getCreateNewTitle() method.
}
/**
* Title for form displayed for editin content page
*
* @param Content $content
*
* @return mixed
*/
public static function getEditTitle(Content $content)
{
// TODO: Implement getEditTitle() method.
}
}
@@ -0,0 +1,38 @@
<?php
namespace Modules\$ModuleNamespace$\Handlers;
use App\CMS\Handlers\BaseHandler;
use App\Models\User;
class $Module$Handler extends BaseHandler
{
/**
* Register admin menu
*
* @param User $user
*/
public static function registerAdminMenu(User $user)
{
// register links in admin menu
$menu = \Menu::instance('mainMenu');
$menu->dropdown(trans('$module$::$module$.name'), function ($submenu) use ($user) {
$submenu->route('$module$.overview', trans('$module$::$module$.overview'), [], 20, ['icon' => 'fa fa-fw fa-list']);
$submenu->route('$module$.new', trans('$module$::$module$.new'), [], 21, ['icon' => 'fa fa-fw fa-plus']);
}, 15, ['icon' => 'fa fa-fw']);
// TODO: add admin menu entries
}
/**
* Does this module support categories?
* @return boolean
*/
public static function supportCategories()
{
return true;
}
}
@@ -0,0 +1,103 @@
<?php
namespace Modules\$ModuleNamespace$\Http\Controllers\Admin;
use App\Http\Controllers\Admin\Controller;
use Modules\$ModuleNamespace$\Http\Requests\Update$Entity$;
use Modules\$ModuleNamespace$\Http\Requests\Create$Entity$;
use Modules\$ModuleNamespace$\Repositories\$Module$Repository;
use $EntityNamespace$$Entity$ as $Entity$Entity;
class $Module$ extends Controller
{
/**
* @var $Module$Repository
*/
private $$module$Repository;
public function __construct($Module$Repository $$module$Repository)
{
$this->$module$Repository = $$module$Repository;
}
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
$items = $Entity$Entity::all();
return view('$module$::admin/index', compact('items'));
}
/**
* Display form for updating entity
*
* @param $Entity$Entity $entity
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function edit($Entity$Entity $entity)
{
return view('$module$::admin/update', compact('entity'));
}
/**
* Update existing entity
*
* @param Update$Entity$ $request
* @param $Entity$Entity $item
*
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Update$Entity$ $request, $Entity$Entity $entity)
{
// ...
$this->$module$Repository->update($entity, $request->all());
return redirect()
->back()
->with('success', trans('$module$.$module.successfullyUpdated'));
}
/**
* Display form for creating new entity
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function create() {
$entity = new $Entity$Entity();
return view('$module$::admin/create', compact('entity'));
}
/**
* Create new instance of entity
*/
public function store(Create$Entity$ $request) {
// ...
$this->$module$Repository->create($request->all());
return redirect()
->back()
->with('success', trans('$module$.$module.successfullyUpdated'));
}
/**
* Delete entity
*
* @param $Entity$ $entity
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy($Entity$ $entity) {
$entity->delete();
return redirect()
->back()
->with('success', trans('$module$.$module.successfullyDeleted'));
}
}
@@ -0,0 +1,11 @@
<?php
namespace Modules\$ModuleNamespace$\Http\Requests;
use App\Http\Requests\Request;
class Create$Entity$ extends Request {
public function rules()
{
return parent::rules();
}
}
@@ -0,0 +1,11 @@
<?php
namespace Modules\$ModuleNamespace$\Http\Requests;
use App\Http\Requests\Request;
class Update$Entity$ extends Request {
public function rules()
{
return parent::rules();
}
}
@@ -0,0 +1,25 @@
<?php
\Route::group([
'prefix' => \LaravelLocalization::setLocale() . '/admin/$module$',
'middleware' => ['admin'],
'namespace' => 'Modules\$Module$\Http\Controllers\Admin'
], function () {
Route::get('/', '$Module$@index')
->name('$module$.overview');
Route::get('/new', '$Module$@create')
->name('$module$.new');
Route::post('/new', '$Module$@store')
->name('$module$.postNew');
Route::get('/edit/{id}', '$Module$@edit')
->name('$module$.edit');
Route::post('/edit/{id}', '$Module$@update')
->name('$module$.postEdit');
Route::get('/delete/{id}', '$Module$@delete')
->name('$module$.delete');
});
@@ -0,0 +1,31 @@
<?php
namespace Modules\$Module$\Providers;
use App\CMS\Modules\ServiceProviders\ServiceProvider;
/**
* Class $Module$ServiceProvider
*
* Service provider for module $Module$
*
* @package Modules\$Module$\Providers
*/
class $Module$ServiceProvider extends ServiceProvider
{
/**
* Set module Alias
*/
protected function setModuleAlias()
{
$this->alias = strtolower('$module$');
}
/**
* Set path to module
*/
protected function setModulePath()
{
$this->path = __DIR__;
}
}
@@ -0,0 +1,24 @@
<?php
namespace Modules\$ModuleNamespace$\Repositories;
use $EntityNamespace$$Entity$ as $Entity$Entity;
class $Module$Repository {
/**
* Create new instance of entity
*
* @param $data
*/
public function create($data) {
$Entity$Entity::create($data);
}
/**
* Update entity
*
* @param $Entity$Entity $entity
*/
public function update($Entity$Entity $entity, $data) {
$entity->update($data);
}
}
@@ -0,0 +1,13 @@
<?php
return [
'name' => '$Module$',
'new' => 'Vytvořit nový',
'description' => '',
'successfullyUpdated' => 'Úspěšně upraveno.',
'successfullyCreated' => 'Úspěšně vytvořeno.',
'successfullyDeleted' => 'Úspěšně smazáno.',
'overview' => 'Přehled',
'noItems' => 'Žádná data.',
'save' => 'Uložit'
];
@@ -0,0 +1,7 @@
@extends('admin.layoutWithNavigation')
@section('pageHeading', @trans('$module$::$module$.name'))
@section('content')
@include('$module$::admin/form', ['action' => route('$module$.new')])
@endsection
@@ -0,0 +1,7 @@
@extends('admin.layoutWithNavigation')
@section('pageHeading', @trans('$module$::$module$.name'))
@section('content')
@include('$module$::admin/form', ['action' => route('$module$.update')])
@endsection
@@ -0,0 +1,6 @@
<form action="{{$action}}" method="post">
{{--...--}}
<input type="submit" class="btn btn-primary" value="@lang('$module$::$module$.save')">
</form>
@@ -0,0 +1,17 @@
@extends('admin.layoutWithNavigation')
@section('pageHeading', @trans('$module$::$module$.overview'))
@section('content')
@if (!empty($items))
<table>
@foreach($items as $item)
@endforeach
</table>
@else
<div class="alert alert-info">
<em>@trans('$module$::$module$.noItems')</em>
</div>
@endif
@endsection
@@ -1,4 +1,5 @@
<?php
namespace App\CMS\Pipeline\SavePipeline\Process;
use App\CMS\Contracts\Content\SavePipeline\Process;
@@ -19,6 +20,10 @@ class UploadRelatedFiles implements Process
*/
function handle(Content & $page, array & $input)
{
if (!isset($input['files'])) {
return;
}
$files = $input['files'];
$assignedFiles = isset($input['keepAssigned']) ? $input['keepAssigned'] : [];
+5 -4
View File
@@ -1,4 +1,5 @@
<?php
namespace App\CMS\Repositories\Content;
use App\CMS\Contracts\Repositories\Content as IContent;
@@ -6,7 +7,6 @@ use App\CMS\Enumerations\ContentStatuses;
use App\CMS\Repositories\Repository;
use App\Models\Content\Content as ContentModel;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
class Content extends Repository implements IContent
@@ -105,14 +105,15 @@ class Content extends Repository implements IContent
*/
public function getOverview($handler = null, $statuses = null)
{
$query = ContentModel::select('contents.*', 'modules.name AS module_name', 'modules.id AS module_id')
$query = ContentModel::select('contents.*')
->join('modules', 'modules.handler', '=', 'contents.moduleHandler')
->join('users', 'users.id', '=', 'contents.userId')
->addSelect(DB::raw('COALESCE(users.name, users.email) AS author_name'))
->addSelect('users.email AS author_email')
->whereNull('contents.deleted_at')
->whereNull('contents.parentId')
->where('contents.language', LaravelLocalization::getCurrentLocale())
->where('modules.enabled', 1)
->with('module', 'subpages', 'subpages.module', 'subpages.templateModel', 'templateModel')
->orderBy('contents.order')
->orderBy('contents.created_at', 'DESC');
// filter results using handler
+28 -1
View File
@@ -1,4 +1,5 @@
<?php
namespace App\CMS\Repositories\FileManager;
use App\CMS\Helpers\RootDirectory;
@@ -25,7 +26,33 @@ class Directory
return $exists->exists();
}
public function update(DirectoryModel $directory, $data) {
/**
* Create new directory
*
* @param $data
*
* @return DirectoryModel
*/
public function create($data)
{
$directory = new DirectoryModel();
$directory->name = $data['name'];
$directory->parent_id = $data['parentDirectory'];
$directory->user_id = \Auth::user()->id;
$directory->description = $data['description'];
$directory->save();
return $directory;
}
/**
* Update given directory
*
* @param DirectoryModel $directory
* @param $data
*/
public function update(DirectoryModel $directory, $data)
{
$directory->name = $data['name'];
$directory->description = $data['description'];
$directory->save();
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace App\CMS\Repositories\FileManager;
use App\Models\FileManager\File as FileModel;
class File {
/**
* Update given instance of File
*
* @param FileModel $file
* @param $data
*/
public function update(FileModel $file, $data) {
$file->update($data);
}
}
+30 -3
View File
@@ -1,9 +1,11 @@
<?php
namespace App\CMS\Repositories;
use App\CMS\Contracts\Repositories\Module as IModule;
use App\Models\Content\Content;
use App\Models\Module as ModuleModel;
use Illuminate\Support\Facades\Cache;
class Module extends Repository implements IModule
{
@@ -26,6 +28,15 @@ class Module extends Repository implements IModule
}
}
public function getContentModules()
{
return Cache::remember('enabled-content-modules', setting('cacheModules', 3600), function () {
return ModuleModel::where('enabled', true)
->where('manages_content', true)
->get();
});
}
public function getCreateContentTitle(ModuleModel $module)
{
$pageHeading = trans('admin/contents.new', ['name' => trans($module->name)]);
@@ -42,9 +53,14 @@ class Module extends Repository implements IModule
return is_null($moduleHeading) ? $pageHeading : $moduleHeading;
}
public function getOverviewTitle(ModuleModel $module)
public function getOverviewTitle(ModuleModel $module = null)
{
$pageHeading = 'admin/contents.overview';
if (is_null($module)) {
return $pageHeading;
}
$moduleHeading = $this->call($module, 'getOverviewTitle');
return is_null($moduleHeading) ? $pageHeading : $moduleHeading;
@@ -52,8 +68,19 @@ class Module extends Repository implements IModule
public function all()
{
return ModuleModel::where('enabled', true)
->get();
return Cache::remember('enabled-modules-and-template', setting('cacheModules', 3600), function () {
return ModuleModel::where('enabled', true)
->get();
});
}
public function getOnlyModules()
{
return Cache::remember('enabled-modules', setting('cacheModules', 3600), function () {
return ModuleModel::where('enabled', true)
->where('is_template', false)
->get();
});
}
public function getByHandler($handler)
@@ -0,0 +1,15 @@
<?php
namespace App\CMS\Repositories\Permissions;
use App\Models\Permissions\Permission as PermissionModel;
class Permission
{
public function getRootPermissions()
{
return PermissionModel::whereNull('parent_id')
->with('subpermissions')
->get();
}
}
@@ -1,27 +1,27 @@
<?php
namespace App\Models\ModelTraits;
namespace App\CMS\Repositories\Settings;
use App\Models\Settings as SettingsModel;
use Illuminate\Support\Facades\Cache;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
trait Settings
class Settings
{
/**
* Prepares common query for selecting settings
*
* @return mixed
*/
protected function getSettingsQuery()
{
return SettingsModel::select(['key', 'value', 'language'])
->where('language', LaravelLocalization::getCurrentLocale())
->orWhere('language', null)
->orderBy('language', 'ASC');
->where('language', LaravelLocalization::getCurrentLocale())
->orWhere('language', null)
->orderBy('language', 'ASC');
}
/**
* Load all settings
*
* @return \stdClass
*/
public function getAll()
@@ -34,7 +34,6 @@ trait Settings
/**
* Get all settings with language info
*
* @return \stdClass
*/
public function getAllWithLanguage()
@@ -55,7 +54,6 @@ trait Settings
/**
* Load only config for views
*
* @return \stdClass
*/
public function getForView()
@@ -83,4 +81,31 @@ trait Settings
return $data;
}
/**
* Save settings
*
* @param array $data
*/
public function save(array $data)
{
$commonSettings = isset($data['commonSettings']) ? $data['commonSettings'] : [];
unset($data['commonSettings']);
foreach ($data as $key => $value) {
// select language for this setting key
$language = isset($commonSettings[$key]) ? null : LaravelLocalization::getCurrentLocale();
$setting = SettingsModel::firstOrNew(['language' => $language, 'key' => $key]);
if ($setting->value == $value) {
continue;
}
// set value and save or delete
$setting->value = $value;
empty($value) ? $setting->delete() : $setting->save();
}
Cache::forget('settings');
}
}
+7 -3
View File
@@ -1,10 +1,12 @@
<?php
namespace App\Cms\Repositories\Templates;
use App\CMS\Contracts\Repositories\Template as ITemplate;
use App\CMS\Repositories\Repository;
use App\Models\Module;
use App\Models\Templates\Template as TemplateModel;
use Illuminate\Support\Facades\Cache;
class Template extends Repository implements ITemplate
{
@@ -68,8 +70,10 @@ class Template extends Repository implements ITemplate
public function getForModule(Module $module)
{
return TemplateModel::where('module_id', $module->id)
->select(['template_name', 'name', 'description'])
->get();
return Cache::remember('templates-for-module-'.$module->id, setting('cacheModules', 3600), function () use ($module) {
return TemplateModel::where('module_id', $module->id)
->select(['template_name', 'name', 'description'])
->get();
});
}
}
+65
View File
@@ -0,0 +1,65 @@
<?php
namespace App\CMS\Repositories\Users;
use App\CMS\Repositories\Repository;
use App\Models\User as UserModel;
use Illuminate\Support\Facades\Hash;
class User extends Repository {
/**
* Update given user
*
* @param UserModel $user
* @param $data
*/
public function update(UserModel $user, $data) {
// update username if set
if (isset($data['username'])) {
$user->username = $data['username'];
}
// change name (if set)
if (isset($data['name'])) {
$user->name = $data['name'];
}
if (isset($data['role'])) {
$user->role = $data['role'];
}
if (isset($data['status'])) {
$user->status = $data['status'];
}
if (isset($data['password'])) {
$user->password = Hash::make($data['password']);
}
$user->email = $data['email'];
$user->save();
}
/**
* Create new user
*
* @param $data
*
* @return UserModel
*/
public function create($data)
{
// create new user
$user = new UserModel();
$user->name = $data['name'];
$user->email = $data['email'];
$user->username = $data['username'];
$user->role = $data['role'];
$user->password = Hash::make($data['password']);
// store user into database
$user->save();
return $user;
}
}
+20 -1
View File
@@ -1,4 +1,5 @@
<?php
namespace App\CMS\Repositories\Widgets;
use App\Http\Requests\Request;
@@ -20,7 +21,7 @@ class Widget
$widget->description = $data['description'];
$widget->container_class = $data['containerClass'];
$widget->container_id = empty($data['containerId']) ? null : $data['containerId'];
$widget->settings = json_encode(call_user_func([$widgetType->handler, 'save'], $request));
$widget->settings = call_user_func([$widgetType->handler, 'save'], $request);
// save into database
$widget->save();
@@ -30,4 +31,22 @@ class Widget
return $widget;
}
public function edit(WidgetModel $widget, Request $request)
{
// update name
$widget->name = $request->name;
$widget->container_class = $request->containerClass;
$widget->container_id = empty($request->containerId) ? null : $request->containerId;
$widget->description = $request->description;
// try to save this widget
$widget->settings = call_user_func([$widget->widget_type_handler, 'save'], $request);
// save into database
$widget->save();
// fire event with editing widget
Event::fire(new \App\Events\EditWidget($widget));
}
}
@@ -0,0 +1,55 @@
<?php
namespace App\CMS\Repositories\Widgets;
use App\Events\CreateNewWidgetArea;
use App\Http\Requests\Request;
use App\Models\Widgets\Widget;
use App\Models\Widgets\WidgetArea as WidgetAreaModel;
use Illuminate\Support\Facades\Event;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
class WidgetArea
{
public function getWidgets($uniqueCode = false)
{
$widgets = Widget::select('widgets.*', 'widgets.widget_type_handler', 'widget_areas.code as widget_area_code', 'widgets.name as widget_name', 'widgets.settings')
->join('widget_in_widget_area', 'widget_in_widget_area.widget_id', '=', 'widgets.id')
->join('widget_areas', 'widget_in_widget_area.widget_area_id', '=', 'widget_areas.id')
->where('language', LaravelLocalization::getCurrentLocale())
->orderBy('widget_in_widget_area.position');
if (!$uniqueCode) {
$widgets = $widgets->where('widget_areas.viewed', '>=', setting('preloadFrequentedWidgetAreasTreshold', 10));
} else {
$widgets = $widgets->where('code', $uniqueCode);
}
return $widgets;
}
public function update(\App\Models\Widgets\WidgetArea $area, Request $request) {
$area->name = $request->name;
$area->description = $request->description;
$area->save();
// fire event with new widget area
Event::fire(new \App\Events\EditWidgetArea($area));
}
/**
* Create new instance of widget area
*
* @param Request $request
*/
public function create(Request $request)
{
$area = WidgetAreaModel::create([
'code' => $request->code,
'name' => $request->name,
'description' => $request->description
]);
// fire event with new widget area
Event::fire(new CreateNewWidgetArea($area));
}
}
+18 -14
View File
@@ -1,19 +1,21 @@
<?php
namespace App\CMS\Widgets\Menu;
use App\CMS\Contracts\Repositories\Content as IContent;
use App\CMS\Contracts\Widgets\PublicWidget;
use App\CMS\Widgets\Contracts\WidgetRenderer;
use App\CMS\Contracts\Widgets\WidgetRenderer;
use App\CMS\Widgets\Exceptions\MissingParameterException;
use App\Http\Requests\Request;
use App\Models\Content\Content;
use Illuminate\Support\Facades\Cache;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use App\CMS\Contracts\Repositories\Content as IContent;
use Modules\Blog\Article\Handlers\Article;
class Menu implements PublicWidget
{
/**
* Name getter
*
* @return string
*/
public static function getName()
@@ -23,7 +25,6 @@ class Menu implements PublicWidget
/**
* Getter for description
*
* @return string
*/
public static function getDescription()
@@ -33,7 +34,6 @@ class Menu implements PublicWidget
/**
* Getter for presenter/renderer of this widget
*
* @return WidgetRenderer
*/
public static function getPresenter()
@@ -73,15 +73,19 @@ class Menu implements PublicWidget
$allowedStatuses[] = IContent::STATUS_PROTECTED;
}
$pages = Content::where('language', LaravelLocalization::getCurrentLocale())
->whereIn('id', $ids)
->whereIn('status', $allowedStatuses)
->get();
$used = [];
foreach ($pages as $page) {
$used[$page->id] = $page;
}
return Cache::remember('widget-menu-content-pages', 5, function () use ($ids, $allowedStatuses) {
$pages = Content::where('language', LaravelLocalization::getCurrentLocale())
->whereIn('id', $ids)
->whereIn('status', $allowedStatuses)
->where('moduleHandler', '!=', Article::class)
->get();
return $used;
$used = [];
foreach ($pages as $page) {
$used[$page->id] = $page;
}
return $used;
});
}
}
+5 -6
View File
@@ -1,4 +1,5 @@
<?php
namespace App\CMS\Widgets\Menu\Presenters;
use App\CMS\Contracts\Repositories\Content as ContentContract;
@@ -81,14 +82,14 @@ class Menu implements WidgetRenderer
$content = app(ContentContract::class);
// get list of all pages
$pages = $content->getOverview();
$widget->settings = new \stdClass();
$widget->settings->links = [];
$pages = $content->getOverview()
->get();
return view('admin.widgets.menu.new', [
'type' => $type,
'widget' => $widget,
'pages' => $pages,
'links' => []
]);
}
@@ -122,8 +123,6 @@ class Menu implements WidgetRenderer
return $a->order - $b->order;
});
$widget->settings->links = (object)$links;
return view('admin.widgets.menu.edit', ['widget' => $widget, 'pages' => $pages]);
return view('admin.widgets.menu.edit', ['widget' => $widget, 'pages' => $pages, 'links' => (object)$links]);
}
}
+1 -1
View File
@@ -30,7 +30,7 @@ class ChangePassword extends Command
$email = $this->argument('email');
try {
$user = User::where(['email' => $email])
->first();
->firstOrFail();
} catch (ModelNotFoundException $e) {
$this->error('Invalid user ' . $email . '.');
return;
+9 -6
View File
@@ -13,14 +13,14 @@ class InitDatabaseSchema extends Command
*
* @var string
*/
protected $signature = 'db:init {schema.sql}';
protected $signature = 'db:init';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
protected $description = 'Init database structure';
/**
* Create a new command instance.
@@ -39,13 +39,16 @@ class InitDatabaseSchema extends Command
*/
public function handle()
{
do {
$schema = $this->ask('Path to database schema file', 'database/schema.sql');
} while (!file_exists($schema));
$schema = $this->argument('schema.sql');
if (!file_exists($schema)) throw new NotFoundHttpException('File '.$schema.' does not exist.');
DB::unprepared(file_get_contents($schema));
$this->line('Successfully imported');
$this->call('migrate');
$this->call('db:seed');
$this->line('Database successfully initialized.');
}
}
+153
View File
@@ -0,0 +1,153 @@
<?php
namespace App\Console\Commands;
use App\Models\Language;
use Illuminate\Console\Command;
use Illuminate\Database\QueryException;
class InstallCMS extends Command
{
/**
* The name and signature of the console command.
* @var string
*/
protected $signature = 'cms:install';
/**
* The console command description.
* @var string
*/
protected $description = 'Try to make installation of CMS as easy as possible';
/**
* Execute the console command.
* @return mixed
*/
public function handle()
{
// check and eventualy create .env file
if (!file_exists(base_path('.env'))) {
$this->createEnv();
$this->line('Rerun this script again, we need to load changes.');
return;
}
// install php dependencies
$parameters = env('APP_DEBUG') ? '' : '--no-dev';
exec('composer install ' . $parameters);
// init database
try {
// does exist something in laguages table? (Or event table itself?)
Language::all();
} catch (QueryException $e) {
// database is not initialized
$this->call('db:init');
}
// install npm dependencies
exec('npm install');
exec('bower install');
exec('gulp');
// change chmod of needed directories
$directories = ['bootstrap/cache', 'storage', 'public'];
foreach ($directories as $directory) {
$this->changeChmod($directory);
}
$this->line('Chmod changed');
// generate APP_KEY in .env
$this->call('key:generate');
// create user
$this->line('Creating admin user...');
do {
$email = $this->ask('E-mail for admin user');
} while (empty($email));
$this->call('user:new', compact('email'));
$this->line('All done. CMS should be prepared.');
}
/**
* Insert value into .env config file
*
* @param $envConstant
* @param $value
*/
private function setEnvConstant($envConstant, $value)
{
$content = file_get_contents(base_path('.env'));
$content = preg_replace('/' . $envConstant . '=(.*)/i', $envConstant . '=' . $value, $content);
file_put_contents(base_path('.env'), $content);
}
/**
* Create .env file with all needed constants
*/
private function createEnv()
{
\File::copy(base_path('.env.example'), base_path('.env'));
// set environment
do {
$env = $this->ask('Install environment: ', 'local');
} while (empty($env));
$this->setEnvConstant('APP_ENV', $env);
// set debugging
if ($env == 'local') {
$debug = 'true';
} else {
$debug = $this->confirm('Enable debugging?', true) ? 'true' : 'false';
}
$this->setEnvConstant('APP_DEBUG', $debug);
// setup database
$databaseFields = [
'DB_HOST' => 'Database server',
'DB_DATABASE' => 'Database name',
'DB_USERNAME' => 'Database user',
'DB_PASSWORD' => 'Password'
];
foreach ($databaseFields as $constant => $text) {
do {
$value = $this->ask($text);
} while (empty ($value));
$this->setEnvConstant($constant, $value);
}
// set app url
do {
$url = $this->ask('Application URL');
$url = trim($url, ' /');
} while (empty($url));
$this->setEnvConstant('SITE_URL', $url);
$this->setEnvConstant('UPLOAD_URL', $url . '/public/uploads');
$this->setEnvConstant('THUMBNAIL_URL', $url . '/public/uploads/thumbnails');
}
/**
* Recursively change chmod to 777 in given directory
*
* @param $directory
*/
private function changeChmod($directory)
{
@chmod($directory, 0777);
if (!is_dir($directory)) {
return;
}
$subdirectories = \File::allFiles($directory);
foreach ($subdirectories as $subdirectory) {
$this->changeChmod($subdirectory);
}
}
}
@@ -0,0 +1,106 @@
<?php
namespace App\Console\Commands\Modules;
use App\Models\Module;
use Illuminate\Console\Command;
class CreateMigration extends Command
{
/**
* The name and signature of the console command.
* @var string
*/
protected $signature = 'module:make-migration {module?} {name?} {--t|table= : Table name} {--c|create : Use template for creating new table}';
/**
* The console command description.
* @var string
*/
protected $description = 'Make new migration for given module';
protected $migrationName;
protected $tableName;
protected $moduleName;
/**
* Execute the console command.
*/
public function handle()
{
$this->moduleName = $module = $this->argument('module');
$this->migrationName = $name = $this->argument('name');
$this->tableName = trim($this->option('table'), ' =');
$modules = Module::where('enabled', true)
->get()
->pluck('static_name', 'id')
->toArray();
while (is_null($module) || !in_array($module, $modules)) {
$module = $this->anticipate('Input valid module name', $modules);
}
$selectedModule = Module::where('static_name', $module)
->first();
$basePath = $selectedModule->is_template ? config('modules.path.template') : config('modules.paths.modules');
$path = $basePath . '/' . $module . '/Database/Migrations/';
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
while (is_null($name)) {
$this->migrationName = $name = $this->ask('Input migration name');
}
$stubName = $this->option('create') ? 'create' : 'new';
$content = file_get_contents(config('modules.paths.stubs') . '/Migrations/' . $stubName . '.stub');
$content = $this->replacePlaceholders($content);
$migrationName = $path . $this->getMigrationName($name);
file_put_contents($migrationName, $content);
$this->line('Migration successfully created.', 'info');
}
/**
* Find and replace all placeholders in given content
*
* @param $content
*
* @return mixed
*/
private function replacePlaceholders($content)
{
$replace = [
'$MigrationName$' => studly_case($this->migrationName),
'$ModuleName$' => $this->moduleName,
'$TableName$' => $this->tableName
];
foreach ($replace as $what => $for) {
$content = str_replace($what, $for, $content);
}
return $content;
}
/**
* Get prefix for created migration
* @return false|string
*/
protected function getDatePrefix()
{
return date('Y_m_d_His');
}
/**
* @param $name
*
* @return string
*/
private function getMigrationName($name)
{
return $this->getDatePrefix() . '_' . snake_case($name) . '.php';
}
}
+122
View File
@@ -0,0 +1,122 @@
<?php
namespace App\Console\Commands\Modules;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
class CreateNew extends Command
{
/**
* The name and signature of the console command.
* @var string
*/
protected $signature = 'module:new
{name : module name}
{parentModule? : name of parent module}
{--entity= : entity}';
/**
* The console command description.
* @var string
*/
protected $description = 'Create new CMS module.';
protected $moduleName;
protected $moduleNamespace;
protected $entity;
protected $entityNamespace;
/**
* Execute the console command.
*/
public function handle()
{
$defaultEntityNamespace = $this->loadArguments();
$path = preg_replace('|/{2,}|i', '/', config('modules.paths.modules') . '/' . $this->moduleNamespace);
if (is_dir($path)) {
$this->error('Module already exists in ' . $path);
return;
}
if (!is_dir($path))
mkdir($path);
// copy stub files
\File::copyDirectory(config('modules.paths.stubs').'/NewModule', $path);
$files = \File::allFiles($path);
foreach ($files as $file) {
$newName = str_replace('stub', 'php', $this->replacePlaceholders($file->getPathname()));
// ignore new entity when using existing entity
if ($this->entityNamespace != $defaultEntityNamespace && Str::contains('Entities', $file)) {
\File::delete($file);
continue;
}
// rename file
\File::move($file, $newName);
// change its content
$content = file_get_contents($newName);
$content = $this->replacePlaceholders($content);
file_put_contents($newName, $content);
}
$this->info('Module successfully created.');
$this->call('module:install', ['name' => $this->moduleName]);
}
/**
* Find and replace all placeholders in given content
*
* @param $content
*
* @return mixed
*/
private function replacePlaceholders($content)
{
$replace = [
'$Module$' => $this->moduleName,
'$ModuleNamespace$' => str_replace('/', '\\', $this->moduleNamespace),
'$module$' => strtolower($this->moduleName),
'$EntityNamespace$' => $this->entityNamespace,
'$Entity$' => $this->entity
];
foreach ($replace as $what => $for) {
$content = str_replace($what, $for, $content);
}
return $content;
}
/**
* Load command arguments
* @return string
*/
private function loadArguments()
{
$parent = $this->argument('parentModule');
$this->moduleName = $moduleName = $this->argument('name');
$this->moduleNamespace = trim($parent . '/' . $moduleName, '/');
$entity = $this->option('entity');
$defaultEntityNamespace = '\\Modules\\' . str_replace('/', '\\', $this->moduleNamespace) . '\Entities\\';
if (!empty($entity)) {
$parts = explode('\\', $entity);
$this->entity = $parts[count($parts) - 1];
unset($parts[count($parts) - 1]);
$this->entityNamespace = implode('\\', $parts);
} else {
$this->entityNamespace = $defaultEntityNamespace;
$this->entity = $this->moduleName;
}
return $defaultEntityNamespace;
}
}
@@ -0,0 +1,48 @@
<?php
namespace App\Console\Commands\Modules;
use App\Models\Module;
use Illuminate\Console\Command;
class DisableModule extends Command
{
/**
* The name and signature of the console command.
* @var string
*/
protected $signature = 'module:disable {module}';
/**
* The console command description.
* @var string
*/
protected $description = 'Disable module';
/**
* Execute the console command.
* @return mixed
*/
public function handle()
{
$moduleName = $this->argument('module');
$module = Module::where('static_name', $moduleName)
->firstOrFail();
if ($module->has_submodules) {
$submodules = $module->submodules;
foreach ($submodules as $submodule) {
$this->call('module:disable', ['module' => $submodule->static_name]);
}
}
$module->enabled = false;
$module->save();
\Cache::forget('enabled-modules');
\Cache::forget('enabled-content-modules');
\Cache::forget('enabled-modules-and-template');
$this->line('Module ' . $module->static_name . ' disabled.');
}
}
@@ -0,0 +1,52 @@
<?php
namespace App\Console\Commands\Modules;
use App\Models\Module;
use Illuminate\Console\Command;
class EnableModule extends Command
{
/**
* The name and signature of the console command.
* @var string
*/
protected $signature = 'module:enable {module}';
/**
* The console command description.
* @var string
*/
protected $description = 'Enable module';
/**
* Execute the console command.
* @return mixed
*/
public function handle()
{
$moduleName = $this->argument('module');
$module = Module::where('static_name', $moduleName)
->firstOrFail();
if ($module->has_submodules) {
$submodules = $module->submodules;
foreach ($submodules as $submodule) {
$this->call('module:enable', ['module' => $submodule->static_name]);
}
}
if ($module->parent_id) {
$module->parent->update(['enabled' => true]);
}
$module->enabled = true;
$module->save();
\Cache::forget('enabled-modules');
\Cache::forget('enabled-content-modules');
\Cache::forget('enabled-modules-and-template');
$this->line('Module ' . $module->static_name . ' enabled.');
}
}
@@ -1,6 +1,6 @@
<?php
namespace App\Console\Commands;
namespace App\Console\Commands\Modules;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
@@ -12,7 +12,7 @@ class InstallAllModules extends Command
*
* @var string
*/
protected $signature = 'install-all-modules';
protected $signature = 'module:install-all';
/**
* The console command description.
*
@@ -20,16 +20,6 @@ class InstallAllModules extends Command
*/
protected $description = 'Crawl /modules directory and install all modules';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
@@ -45,7 +35,7 @@ class InstallAllModules extends Command
// try to install each module
try {
$this->call('install-module', ['name' => $moduleName]);
$this->call('module:install', ['name' => $moduleName]);
} catch (\Exception $e) {
$this->line('Module ' . $moduleName . ' already installed.');
}
@@ -1,7 +1,8 @@
<?php
namespace App\Console\Commands;
namespace App\Console\Commands\Modules;
use App\CMS\ModuleManager\Installer;
use App\Models\Module;
use Illuminate\Console\Command;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
@@ -14,13 +15,11 @@ class InstallModule extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'install-module {name} {parentModuleId?}';
protected $signature = 'module:install {name} {parentModuleId?}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Custom installation of CMS module. Name given as directory name in /modules.';
@@ -30,7 +29,6 @@ class InstallModule extends Command
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
@@ -55,8 +53,9 @@ class InstallModule extends Command
// get config
$config = $this->loadConfig();
if (empty($config))
if (empty($config)) {
return;
}
// check if it is valid
$this->checkMandatoryFields($config);
@@ -68,14 +67,15 @@ class InstallModule extends Command
Cache::forget('enabled-modules');
Cache::forget('module-handler-to-id-enumeration');
exec('composer dump-autoload');
// inform user
$this->line('Module ' . $name . ' successfuly installed');
$this->line('Module ' . $name . ' successfuly installed.');
}
/**
* Load config from Config/config.php in module files. We cannot use config() because the file have not published
* yet.
*
* @return array
* @throws FileNotFoundException
*/
@@ -84,8 +84,9 @@ class InstallModule extends Command
$basePath = $this->modulesPath . DIRECTORY_SEPARATOR . $this->moduleName . DIRECTORY_SEPARATOR;
$path = $basePath . 'Config' . DIRECTORY_SEPARATOR . 'config.php';
if (basename($basePath) == 'Database')
if (basename($basePath) == 'Database') {
return [];
}
// check if module has Config/config.php file
if (!file_exists($path)) {
@@ -120,7 +121,6 @@ class InstallModule extends Command
/**
* Installs module into database.
*
* This method calls Module::install, which handles specific installation of module. In this way we should be able
* to install any module even with some other database structures.
*
@@ -154,14 +154,12 @@ class InstallModule extends Command
if (is_null($module)) {
// insert module into database
$settings = [
'staticName' => $this->moduleName,
'providers' => $providers,
'aliases' => isset($config['aliases']) ? $config['aliases'] : [],
'order' => isset($config['order']) ? $config['order'] : 0,
'files' => isset($config['files']) ? $config['files'] : []
'providers' => $providers,
'order' => isset($config['order']) ? $config['order'] : 0,
'files' => isset($config['files']) ? $config['files'] : []
];
$module = Module::install($name, $alias, $description, $handler, $this->parentModuleId, $settings);
$module = Installer::install($name, $alias, $this->moduleName, $description, $handler, $this->parentModuleId, $settings);
}
// try to install submodules
@@ -184,7 +182,7 @@ class InstallModule extends Command
$submodule = str_replace($this->modulesPath . DIRECTORY_SEPARATOR, '', $submodulePath);
try {
$this->call('install-module', ['name' => $submodule, 'parentModuleId' => $parentModule->id]);
$this->call('module:install', ['name' => $submodule, 'parentModuleId' => $parentModule->id]);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
@@ -0,0 +1,42 @@
<?php
namespace App\Console\Commands\Modules;
use App\Models\Module;
use Illuminate\Console\Command;
class ModuleMigrate extends Command
{
/**
* The name and signature of the console command.
* @var string
*/
protected $signature = 'module:migrate {module}';
/**
* The console command description.
* @var string
*/
protected $description = 'Run migrations in specified module';
/**
* Execute the console command.
* @return mixed
*/
public function handle()
{
$moduleName = $this->argument('module');
$module = Module::where('static_name', $moduleName)
->firstOrFail();
if ($module->has_submodules) {
$submodules = $module->submodules;
foreach ($submodules as $submodule) {
$this->call('module:migrate', ['module' => $submodule->static_name]);
}
}
$this->line('Migrating ' . $module->static_name);
$this->call('migrate', ['--path' => config('modules.paths.modules').'/'.$moduleName.'/Database']);
}
}
@@ -0,0 +1,49 @@
<?php
namespace App\Console\Commands\Modules;
use App\Models\Module;
use Illuminate\Console\Command;
class RunMigrations extends Command
{
/**
* The name and signature of the console command.
* @var string
*/
protected $signature = 'module:migrate {module?} {--rollback : Rollback one migration}';
/**
* The console command description.
* @var string
*/
protected $description = 'Run migrations for all modules or for one module';
/**
* Execute the console command.
* @return mixed
*/
public function handle()
{
$modules = Module::where('enabled', true);
if (!is_null($module = $this->argument('module'))) {
$modules = $modules->where('static_name', $module);
}
$modules = $modules->get();
if ($modules->isEmpty()) {
$this->error('No valid modules.');
return;
}
$command = $this->option('rollback') ? 'migrate:rollback' : 'migrate';
foreach ($modules as $module) {
$this->info('Migrating '.$module->static_name);
$basePath = $module->is_template ? config('modules.path.templates') : config('modules.paths.modules');
$path = $basePath . '/' . $module->static_name . '/Database/Migrations/';
$path = str_replace(base_path(), '', $path);
$this->call($command, ['--path' => $path]);
}
}
}
@@ -0,0 +1,42 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class UninstallModule extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'command:name';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
//
}
}
+6 -9
View File
@@ -3,6 +3,7 @@
namespace App\Console\Commands;
use App\CMS\Enumerations\UserRoles;
use App\Events\CreateNewUser;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Hash;
@@ -11,13 +12,11 @@ class NewUser extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'user:new {email}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Creates new user';
@@ -27,13 +26,9 @@ class NewUser extends Command
*/
public function handle()
{
$email = $this->argument('email');
// check if username is really email
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->error($email . ' is not a valid e-mail!');
return;
}
do {
$email = $this->argument('email');
} while (!filter_var($email, FILTER_VALIDATE_EMAIL));
// ask for password
do {
@@ -63,6 +58,8 @@ class NewUser extends Command
$user->role = $role;
$user->save();
event(new CreateNewUser($user));
$this->info('User ' . $email . ' successfully created.');
}
}
+9 -6
View File
@@ -2,6 +2,8 @@
namespace App\Console\Commands;
use App\CMS\ModuleManager\Installer;
use App\CMS\ModuleManager\Uninstaller;
use App\Models\Module;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
@@ -43,14 +45,13 @@ class SetTemplate extends Command
$config['staticName'] = $template;
if ($current) {
$info = json_decode($current->module_settings);
$this->line('Template is already installed. Currently using template ' . trans($current->name) . ' located in /templates/' . $info->staticName . '.');
$this->line('Template is already installed. Currently using template ' . trans($current->name) . ' located in /templates/' . $current->static_name . '.');
$confirm = $this->confirm('Uninstall it and install *' . trans($config['name']) . '*? All data associated with installed template will be lost!');
if ($confirm) {
$this->line('Uninstalling ' . $current->name . '.');
$current->uninstall();
Uninstaller::uninstall($current);
} else {
$this->line('Aborting installation.');
return;
@@ -58,7 +59,7 @@ class SetTemplate extends Command
}
try {
Module::install($config['name'], $config['alias'], $config['description'], $config['handler'], false, $config);
Installer::install($config['name'], $config['alias'], $config['staticName'], $config['description'], $config['handler'], false, $config);
} catch (\Exception $e) {
$this->error('Cannot install template ' . $template . '. Message: ' . $e->getMessage());
return;
@@ -72,6 +73,8 @@ class SetTemplate extends Command
// run again artisan for publishing resources
// it cannot be done using $this->call, because we need to load different template into service providers
exec('php artisan vendor:publish');
if ($publish) {
exec('php artisan vendor:publish');
}
}
}
+17 -6
View File
@@ -2,6 +2,13 @@
namespace App\Console;
use App\Console\Commands\InstallCMS;
use App\Console\Commands\Modules\CreateMigration;
use App\Console\Commands\Modules\RunMigrations;
use App\Console\Commands\Modules\CreateNew;
use App\Console\Commands\Modules\DisableModule;
use App\Console\Commands\Modules\EnableModule;
use App\Console\Commands\Modules\ModuleMigrate;
use App\Console\Commands\PublishTemplateResources;
use App\Console\Commands\TemplateInfo;
use Illuminate\Console\Scheduling\Schedule;
@@ -11,21 +18,27 @@ class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
Commands\NewUser::class,
Commands\ChangePassword::class,
Commands\InstallModule::class,
Commands\InstallAllModules::class,
CreateNew::class,
ModuleMigrate::class,
EnableModule::class,
DisableModule::class,
Commands\Modules\InstallModule::class,
Commands\Modules\InstallAllModules::class,
Commands\TranslateDirectory::class,
Commands\TranslateAll::class,
Commands\InitDatabaseSchema::class,
Commands\SetTemplate::class,
Commands\AddLanguage::class,
PublishTemplateResources::class,
TemplateInfo::class
TemplateInfo::class,
InstallCMS::class,
CreateMigration::class,
RunMigrations::class
];
/**
@@ -37,7 +50,5 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
}
}
+1 -3
View File
@@ -2,10 +2,8 @@
namespace App\Events;
use App\Events\Event;
use App\Models\WidgetArea;
use App\Models\Widgets\WidgetArea;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class EditWidgetArea extends Event
{
+9 -13
View File
@@ -2,37 +2,33 @@
namespace App\Events;
use App\Models\FileManager\File as FileModel;
use Illuminate\Queue\SerializesModels;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class UploadFile extends Event
{
use SerializesModels;
/**
* @var UploadedFile
*/
public $uploadedFile;
/**
* @var
* @var FileModel
*/
public $id;
public $file;
/**
* Create a new event instance.
*
* @param File $uploadedFile
* @param $id
* @param FileModel $file
* @param $id
*
* @internal param File $uploadedFile
*/
public function __construct(File $uploadedFile, $id)
public function __construct(FileModel $file)
{
$this->uploadedFile = $uploadedFile;
$this->id = $id;
$this->file = $file;
}
/**
* Get the channels the event should be broadcast on.
*
* @return array
*/
public function broadcastOn()
@@ -7,6 +7,8 @@ use App\CMS\Interactions\Admin\Content\ChangeStatus;
use App\CMS\Interactions\Admin\Content\DeletePage;
use App\CMS\Interactions\Admin\Content\SetHomepage;
use App\Http\Controllers\Admin\Controller;
use App\Models\Content\Content;
use App\Models\Content\ContentHistory;
class ContentActions extends Controller
{
@@ -25,15 +27,13 @@ class ContentActions extends Controller
* This method is called in static page overview from quick actions. It checks if status is valid, if page exists
* and updates status.
*
* @param $id
* @param $status
* @param Content $page
* @param $status
*
* @return \Illuminate\Http\RedirectResponse
*/
public function changeStatus($id, $status)
public function changeStatus(Content $page, $status)
{
$page = $this->content->getOne($id);
Interaction::handle(ChangeStatus::class, ['status' => $status], $page);
// redirect back to overview with info for user
@@ -45,14 +45,12 @@ class ContentActions extends Controller
/**
* Delete page
*
* @param $id
* @param Content $page
*
* @return \Illuminate\Http\RedirectResponse
*/
public function delete($id)
public function delete(Content $page)
{
$page = $this->content->getOne($id);
Interaction::handle(DeletePage::class, [], $page);
// redirect back to overview with info for user
@@ -66,14 +64,12 @@ class ContentActions extends Controller
/**
* Sets page as homepage
*
* @param $id
* @param Content $page
*
* @return \Illuminate\Http\RedirectResponse
*/
public function setHomepage($id)
public function setHomepage(Content $page)
{
$page = $this->content->getOne($id);
Interaction::handle(SetHomepage::class, [], $page);
// redirect back to overview with info for user
@@ -5,6 +5,7 @@ use App\CMS\Contracts\Repositories\Content as IContent;
use App\CMS\Contracts\Repositories\Module as IModule;
use App\CMS\Enumerations\ContentStatuses;
use App\Http\Controllers\Admin\Controller;
use App\Models\Module;
class ContentOverview extends Controller
{
@@ -26,29 +27,32 @@ class ContentOverview extends Controller
/**
* Overview for all content pages.
*
* @param null|int $moduleId
* @param null $status
* @param Module|null $module
* @param null $status
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @internal param int|null $moduleId
*/
public function index($moduleId = null, $status = null)
public function index(Module $module, $status = null)
{
// get module settings
$module = $this->module->getOne($moduleId);
$pageHeading = $this->module->getOverviewTitle($module);
// get pages for overview
$handler = $module !== null ? $module->handler : null;
$handler = $module->exists ? $module->handler : null;
$pages = $this->content->getOverview($handler, [$status])
->paginate(setting('paginatedResults', 20));
// get homepage - for checking if homepage is set and available
$homepage = $this->content->getHomepage();
$contentModules = app(\App\CMS\Repositories\Module::class)->getContentModules();
return view('admin.content.overview', [
'pages' => $pages,
'homepage' => $homepage,
'pageHeading' => $pageHeading,
'contentModules' => $contentModules,
'statuses' => ContentStatuses::getWithTranslations(),
'module' => isset($module) ? $module : null
]);
@@ -1,4 +1,5 @@
<?php
namespace App\Http\Controllers\Admin\Contents;
use App\CMS\Contracts\Repositories\Content as IContent;
@@ -10,13 +11,13 @@ use App\Cms\Interactions\Admin\Content\NewContent;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\CreateNewContentRequest;
use App\Http\Requests\Request;
use App\Models\Module;
use Illuminate\Support\Collection;
use Modules\Categories\Contracts\Repositories\Category as ICategory;
/**
* Class CreateNewContent
*
* Controller for creating new content page.
*
* @package App\Http\Controllers\Admin\Contents
*/
class CreateNewContent extends Controller
@@ -29,10 +30,6 @@ class CreateNewContent extends Controller
* @var IModuleRepository
*/
private $module;
/**
* @var ICategory
*/
private $category;
/**
* @var ITemplate
*/
@@ -40,23 +37,20 @@ class CreateNewContent extends Controller
/**
* CreateNewContent constructor.
*
* Sets File and Content models into class variables
*
* @param IContent|Content $content
* @param IModuleRepository $module
* @param ICategory $category
*
* @param ITemplate $template
*
* @internal param File $file
*/
public function __construct(IContent $content, IModuleRepository $module, ICategory $category, ITemplate $template)
public function __construct(IContent $content, IModuleRepository $module, ITemplate $template)
{
parent::__construct();
$this->content = $content;
$this->module = $module;
$this->category = $category;
$this->template = $template;
}
@@ -67,13 +61,16 @@ class CreateNewContent extends Controller
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function create($module)
public function create(Module $module)
{
$module = $this->module->getOne($module);
$statuses = ContentStatuses::getWithTranslations();
$pageHeading = $this->module->getCreateContentTitle($module);
$templates = $this->template->getForModule($module);
$categories = $this->category->getForModule($module);
$categories = new Collection();
if (class_exists(ICategory::class)) {
$categories = app(ICategory::class)->getForModule($module);
}
$page = $this->content->getOne();
@@ -95,15 +92,14 @@ class CreateNewContent extends Controller
/**
* Save new content page
*
* @param CreateNewContentRequest $request
* @param $moduleId
* @param CreateNewContentRequest|Request $request
* @param Module $module
*
* @return \Illuminate\Http\RedirectResponse
* @internal param $moduleId
*/
public function store(Request $request, $moduleId)
public function store(Request $request, Module $module)
{
$module = $this->module->getOne($moduleId);
// create new page
Interaction::handle(NewContent::class, $request->all(), $module->handler);
@@ -1,4 +1,5 @@
<?php
namespace App\Http\Controllers\Admin\Contents;
use App\CMS\Contracts\Repositories\Content as IContent;
@@ -6,18 +7,15 @@ use App\CMS\Contracts\Repositories\Module as IModuleRepository;
use App\CMS\Contracts\Repositories\Template as ITemplate;
use App\CMS\Enumerations\ContentStatuses;
use App\Cms\Handlers\Interactions\Interaction;
use App\CMS\Helpers\CurrentTemplate;
use App\Cms\Interactions\Admin\Content\EditContent as EditContentInteraction;
use App\Events\AttemptToEditInvalidContent;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\EditContentRequest;
use App\Http\Requests\Request;
use App\Models\Content\Content;
use App\Models\Content\ContentHistory;
use App\Models\FileManager\File;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Collection;
use Modules\Categories\Contracts\Repositories\Category as ICategory;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class EditContent extends Controller
{
@@ -37,10 +35,6 @@ class EditContent extends Controller
* @var IModuleRepository
*/
private $module;
/**
* @var ICategory
*/
private $category;
/**
* @var ITemplate
*/
@@ -48,7 +42,6 @@ class EditContent extends Controller
/**
* EditContent constructor.
*
* Load ContentHistory and File into this controller
*
* @param ContentHistory $history
@@ -58,35 +51,37 @@ class EditContent extends Controller
* @param ICategory $category
* @param ITemplate $template
*/
public function __construct(ContentHistory $history, File $file, IContent $content, IModuleRepository $module, ICategory $category, ITemplate $template)
public function __construct(ContentHistory $history, File $file, IContent $content, IModuleRepository $module, ITemplate $template)
{
$this->history = $history;
$this->file = $file;
$this->content = $content;
$this->module = $module;
$this->category = $category;
$this->template = $template;
}
/**
* Display form for editing static page
*
* @param $id
* @param Content $page
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function edit($id)
public function edit(Content $page)
{
$statuses = ContentStatuses::getWithTranslations();
$page = $this->content->getOne($id);
// get module ID
$module = $this->module->getByHandler($page->moduleHandler);
$pageHeading = $this->module->getUpdateContentTitle($module, $page);
$templates = $this->template->getForModule($module);
$categories = $this->category->getForModule($module);
$history = $this->history->getStructuredHistoryOf($page);
$categories = new Collection();
if (class_exists(ICategory::class)) {
$categories = app(ICategory::class)->getForModule($module);
}
// render view
return view('admin.content.edit', [
'pageHeading' => $pageHeading,
@@ -94,7 +89,8 @@ class EditContent extends Controller
'page' => $page,
'module' => $module,
'categories' => $categories,
'rootPages' => $this->content->getOverview()->get(),
'rootPages' => $this->content->getOverview()
->get(),
'templates' => $templates,
'formSectionNames' => $this->module->call($module, 'getExtendedFormSections'),
'formSections' => $this->module->call($module, 'getExtendedFormInputsEdit'),
@@ -105,29 +101,14 @@ class EditContent extends Controller
/**
* Edit static page and save changes into history.
*
* @param EditContentRequest $request
* @param $id
* @param EditContentRequest|Request $request
* @param Content $page
*
* @return \Illuminate\Http\RedirectResponse
* @internal param $id
*/
public function update(Request $request, $id)
public function update(Request $request, Content $page)
{
try {
/**
* @var $page Content
*/
$page = $this->content->getOne($id);
} catch (NotFoundHttpException $e) {
// log attempt of invalid edit
Event::fire(new AttemptToEditInvalidContent($id));
// page for editing not found
return redirect()
->route('content.overview')
->with('error', trans('admin/contents.invalidPage'));
}
// edit page
Interaction::handle(EditContentInteraction::class, $request->all(), $page);
@@ -136,4 +117,24 @@ class EditContent extends Controller
->route('content.overview')
->with('success', trans('admin/contents.successfullyEdited'));
}
public function order() {
$pages = $this->content->getOverview()->get();
return view('admin.content.order', compact('pages'));
}
public function setOrder(Request $request) {
$data = $request->get('page');
foreach ($data as $id => $order) {
Content::where('id', $id)->update(['order' => $order]);
}
// something was changed, inform user
return redirect()
->route('content.overview')
->with('success', trans('admin/contents.orderSuccessfullySet'));
}
}
+12 -11
View File
@@ -19,30 +19,31 @@ class History extends Controller
}
/**
* @param $id
* @param Content $page
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getOverview($id)
public function getOverview(Content $page)
{
// test if given content id is static page and if exists
$content = Content::findOrFail($id);
$history = $this->history->getStructuredHistoryOf($content);
$history = $this->history->getStructuredHistoryOf($page);
return view('admin/history.overview', [
'history' => $history,
'page' => $content
'page' => $page
]);
}
public function getDiff($revision, $id)
/**
* @param ContentHistory $revision
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getDiff(ContentHistory $revision)
{
$change = $this->history->findOrFail($id);
$diff = $this->history->getDiff($change);
$diff = $this->history->getDiff($revision);
return view('admin/history.diff', [
'change' => $change,
'change' => $revision,
'diff' => $diff
]);
}
@@ -2,13 +2,22 @@
namespace App\Http\Controllers\Admin\Dashboard;
use App\CMS\Contracts\Repositories\Module;
use App\Http\Controllers\Admin\Controller;
use Illuminate\Http\Request;
use App\Models\Content\Content;
use Illuminate\Support\Facades\Auth;
class Dashboard extends Controller
{
public function index(Request $request)
public function index()
{
return redirect()->route('content.overview');
$contentModules = app(Module::class)->getContentModules();
if (\Auth::user()
->can('manage', Content::class) && !$contentModules->isEmpty()) {
return redirect()->route('content.overview');
} else {
return redirect()->route('users.detail', ['user' => Auth::user()]);
}
}
}
@@ -8,6 +8,7 @@ use App\CMS\Interactions\Admin\FileManager\CreateDirectory;
use App\CMS\Repositories\FileManager\Directory as DirectoryRepository;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests;
use App\Models\FileManager\Directory;
use Illuminate\Http\Request;
class CreateNewDirectory extends Controller
@@ -30,9 +31,10 @@ class CreateNewDirectory extends Controller
/**
* Create new directory
*
* @param Requests\CreateNewDirectoryRequest $request
* @param Requests\CreateNewDirectoryRequest|Request $request
*
* @return $this|\Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
* @internal param Directory $parentDirectory
*/
public function store(Request $request)
{
@@ -5,19 +5,20 @@ namespace App\Http\Controllers\Admin\FileManager;
use App\CMS\Repositories\FileManager\Directory as DirectoryRepository;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests;
use App\Http\Requests\EditDirectoryRequest;
use App\Models\FileManager\Directory;
class EditDirectory extends Controller
{
/**
* @param Requests\EditDirectoryRequest $request
* @param EditDirectoryRequest $request
* @param Directory $directory
*
* @return $this|\Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
* @internal param $directoryId
*
*/
public function update(Requests\EditDirectoryRequest $request, Directory $directory)
public function update(EditDirectoryRequest $request, Directory $directory)
{
$repository = app(DirectoryRepository::class);
if ($repository->checkIfNameExists($request->name, $directory->parent_id, $directory->id)) {
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Admin\FileManager;
use App\CMS\Helpers\FileManager;
use App\CMS\Helpers\RootDirectory;
use App\CMS\Repositories\FileManager\File as FileRepository;
use App\Events\EditFile;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\EditUploadedFileRequest;
@@ -14,14 +15,12 @@ class EditUploadedFile extends Controller
{
/**
* Edit form
*
* Render edit form for displaying details and updating given file
*
* @param File $file
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\View\View
* @internal param int $id file id
*
*/
public function show(File $file)
{
@@ -35,7 +34,6 @@ class EditUploadedFile extends Controller
/**
* Updates file
*
* User can change only keywords, original filename and description. Mime type, hash and other fields remain
* unchanged
*
@@ -44,16 +42,11 @@ class EditUploadedFile extends Controller
*
* @return \Illuminate\Http\RedirectResponse
* @internal param $id
*
*/
public function update(EditUploadedFileRequest $request, File $file)
{
// set values from form
$file->name = $request->name;
$file->keywords = $request->keywords;
$file->description = $request->description;
$file->directory_id = $request->directory_id;
$file->save();
$repository = app(FileRepository::class);
$repository->update($file, $request->all());
// fire action
Event::fire(new EditFile($file));
@@ -1,8 +1,8 @@
<?php
namespace App\Http\Controllers\Admin\FileManager;
use App\CMS\Helpers\Path;
use App\CMS\Helpers\Template;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\Request;
use App\Models\FileManager\File;
@@ -30,14 +30,12 @@ class UploadedFilesOverview extends Controller
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index(Directory $directory = null)
public function index(Directory $directory)
{
// include hidden directories?
$includeHidden = Input::get('hidden');
$subdirectories = $this->directoryRepository->getAllSubdirectories($directory);
if (!$includeHidden) {
if (!Input::get('hidden', true)) {
$subdirectories = $subdirectories->where('hidden', false);
}
-87
View File
@@ -1,87 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\LoginRequest;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
/**
* Class Login
*
* @package App\Http\Controllers\Admin
*
* @todo use trait ThrottlesLogins for disabling brutal-force password cracking
*/
class Login extends Controller
{
/**
* Display login form
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getLogin()
{
return view('admin.loginForm');
}
/**
* Login handler
*
* @param LoginRequest $request
*
* @return \Illuminate\Http\RedirectResponse
*/
public function postLogin(LoginRequest $request)
{
$email = $request->email;
// try to find user
$user = User::where('email', $email)
->where('role', '!=', User::ROLE_VISITOR)
->where('status', User::STATE_ACTIVE)
->first();
if (!$user) {
return $this->loginFailed();
}
// try to log in user
if (Hash::check($request->password, $user->password)) {
Auth::login($user);
$redirect = $request->redirectTo ? $request->redirectTo : route('admin.dashboard');
return redirect()->intended($redirect);
}
// login invalid, redirect and inform the user
return $this->loginFailed();
}
/**
* Logs out user
*
* @return \Illuminate\Http\RedirectResponse
*/
public function logout()
{
// remove user information
\Auth::logout();
// redirect to login form with info about successfull logout
return redirect()
->route('login')
->with('success', trans('admin/common.logoutSuccessfull'));
}
private function loginFailed()
{
return redirect()
->route('login')
->with('error', trans('auth.failed'))
->withInput();
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Request;
use App\Models\Permissions\Permission;
class Permissions extends Controller
{
/**
* Display all permissions
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
$permissions = Permission::whereNull('parent_id')->get();
return view('admin/permissions.index', compact('permissions'));
}
/**
* Setup default permissions
*
* @param Request $request
*
* @return \Illuminate\Http\RedirectResponse
*/
public function setDefault(Request $request)
{
Permission::where('default', true)
->update(['default' => false]);
$permissions = $request->permissions;
Permission::whereIn('string_id', array_keys($permissions))
->update(['default' => true]);
return redirect()
->back()
->with('success', trans('admin/permissions.defaultSuccessfullySet'));
}
}
+7 -3
View File
@@ -13,7 +13,6 @@ class Search extends Controller
{
/**
* Create form for searching
*
* @return $this|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getSearch()
@@ -37,7 +36,6 @@ class Search extends Controller
/**
* Method used for performing search.
*
* This method iterates over all registered search engines and returns results for each engine apart.
*
* @param string $term search text
@@ -60,10 +58,16 @@ class Search extends Controller
// try to find given term
$results = $search->search($term);
$content = $presenter->render($results);
if (is_null($content)) {
continue;
}
// create result object
$resultsParts[$search->getId()] = [
'name' => $search->getName(),
'content' => $presenter->render($results),
'content' => $content,
'count' => count($results)
];
}
+4 -23
View File
@@ -2,15 +2,15 @@
namespace App\Http\Controllers\Admin;
use App\CMS\Repositories\Settings\Settings as SettingsRepository;
use App\Http\Requests;
use App\Models\Settings as SettingsModel;
use Illuminate\Support\Facades\App;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
class Settings extends Controller
{
/**
* @var SettingsModel
* @var SettingsRepository
*/
protected $settings;
@@ -19,14 +19,13 @@ class Settings extends Controller
*
* @param SettingsModel $settings
*/
public function __construct(SettingsModel $settings)
public function __construct(SettingsRepository $settings)
{
$this->settings = $settings;
}
/**
* Get overview (with form) for editing settings
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getOverview()
@@ -45,7 +44,6 @@ class Settings extends Controller
/**
* Save all settings (ignore empty ones)
*
* When settings used to be non-empty string and user deletes it, key is also deleted from database
*
* @param Requests\SaveSettingsRequest $request
@@ -54,25 +52,8 @@ class Settings extends Controller
*/
public function saveSettings(Requests\SaveSettingsRequest $request)
{
$data = $request->all();
$commonSettings = isset($data['commonSettings']) ? $data['commonSettings'] : [];
// remove CSRF token field
unset($data['_token'], $data['commonSettings']);
foreach ($data as $key => $value) {
// select language for this setting key
$language = isset($commonSettings[$key]) ? null : LaravelLocalization::getCurrentLocale();
$setting = SettingsModel::firstOrNew(['language' => $language, 'key' => $key]);
if ($setting->value == $value) {
continue;
}
// set value and save or delete
$setting->value = $value;
$setting->save();
}
$this->settings->save($request->except(['_token']));
return redirect()
->route('settings.overview')
@@ -2,6 +2,7 @@
namespace App\Http\Controllers\Admin\Templates;
use App\Cms\Repositories\Templates\Template as TemplateRepository;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\CopyTemplateRequest;
use App\Models\Templates\Template;
@@ -10,7 +11,6 @@ class CopyTemplate extends Controller
{
/**
* Method for copying given template.
*
* This method is supposed to be called by POST method.
*
* @param CopyTemplateRequest $request
@@ -32,15 +32,22 @@ class CopyTemplate extends Controller
$namespace .= '::';
}
$repository = app(TemplateRepository::class);
$repository->setModel($template);
// get template absolute paths
$realTemplatePath = $template->getPathToTemplate();
$customTemplatePath = $template->getPathToTemplate(Template::CUSTOM_EDIT_DIRECTORY);
$realTemplatePath = $repository->getPathToTemplate();
$customTemplatePath = $repository->getPathToTemplate(TemplateRepository::CUSTOM_EDIT_DIRECTORY);
$path = dirname($customTemplatePath);
// create file copy
$data = file_get_contents($realTemplatePath);
$written = file_put_contents($path . DIRECTORY_SEPARATOR . $newName . Template::TEMPLATE_SUFFIX, $data);
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
$written = file_put_contents($path . DIRECTORY_SEPARATOR . $newName . TemplateRepository::TEMPLATE_SUFFIX, $data);
// were data written?
if ($written === false) {
return $this->copyFailed($request, $template);
@@ -67,7 +74,6 @@ class CopyTemplate extends Controller
* @param Template $template
*
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
*
*/
private function copyFailed(CopyTemplateRequest $request, Template $template)
{
@@ -34,13 +34,8 @@ class EditTemplate extends Controller
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getEdit($template)
public function getEdit(Template $template)
{
/**
* @var $template Template
*/
$template = Template::findOrFail($template);
$this->templateRepository->setModel($template);
// load template content
@@ -59,15 +54,13 @@ class EditTemplate extends Controller
* Save meta information about template and edited content
*
* @param EditTemplateRequest $request
* @param $templateId
* @param Template $template
*
* @return \Illuminate\Http\RedirectResponse
* @internal param $templateId
*/
public function postEdit(EditTemplateRequest $request, $templateId)
public function postEdit(EditTemplateRequest $request, Template $template)
{
// find template
$template = Template::findOrFail($templateId);
// setup meta information
$template->name = $request->name;
@@ -105,7 +98,7 @@ class EditTemplate extends Controller
// try to save content
if (!is_writable($customDir) && !is_writable($originalDir)) {
return redirect()
->route('templates.edit', ['id' => $request->id])
->route('templates.edit', ['id' => $template->id])
->withInput()
->with('warning', trans('admin/templates.cannotWriteContent'));
}
@@ -7,17 +7,28 @@ use App\Models\Templates\TemplatePath;
class TemplateOverview extends Controller
{
public function getPath($path)
public function index()
{
$path = TemplatePath::findOrFail($path);
$templatePaths = TemplatePath::with('subdirectories')
->whereNull('parent_id')
->get();
return view('admin.templates.index', compact('templatePaths'));
}
/**
* Display overview of all templates in given path
*
* @param TemplatePath $templatePath
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getPath(TemplatePath $templatePath)
{
return view('admin.templates.list', [
'directory' => $path,
'isWritable' => is_writable(base_path($path->path)),
'templates' => $path->templates()
->get(),
'subdirectories' => $path->subdirectories()
->get()
'directory' => $templatePath,
'isWritable' => is_writable(base_path($templatePath->path))
]);
}
}
@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Admin\Users;
use App\CMS\Enumerations\UserRoles;
use App\CMS\Repositories\Users\User as UserRepository;
use App\Events\CreateNewUser as CreateNewUserEvent;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\CreateNewUserRequest;
@@ -28,28 +29,21 @@ class CreateNewUser extends Controller
/**
* Create new user
*
* This method saves new user into database
*
* @param CreateNewUserRequest $request
* @param UserRepository $userRepository
*
* @return \Illuminate\Http\RedirectResponse
*/
protected function postRegistration(CreateNewUserRequest $request)
protected function postRegistration(CreateNewUserRequest $request, UserRepository $userRepository)
{
// when user did not provide any username, use his email
$username = isset($request->username) && !empty($request->username) ? $request->username : $request->email;
// create new user
$user = new User();
$user->name = $request->name;
$user->email = $request->email;
$user->username = $username;
$user->role = $request->role;
$user->password = Hash::make($request->password);
// store user into database
$user->save();
$data = $request->all();
$data['username'] = $username;
$user = $userRepository->create($data);
// fire event
Event::fire(new CreateNewUserEvent($user));
+66 -37
View File
@@ -4,26 +4,48 @@ namespace App\Http\Controllers\Admin\Users;
use App\CMS\Enumerations\UserRoles;
use App\CMS\Enumerations\UserStates;
use App\CMS\Repositories\Users\User as UserRepository;
use App\Events\EditUser as EditUserEvent;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\EditUserRequest;
use App\Http\Requests\Request;
use App\Models\Permissions\Permission;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Hash;
class EditUser extends Controller
{
public function getEditUser($id = null)
/**
* @var UserRepository
*/
private $userRepository;
/**
* EditUser constructor.
*
* @param UserRepository $userRepository
*/
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
/**
* Display form for editing user
*
* @param User|null $user
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getEditUser(User $user = null)
{
// when no user specified, lets assume we want to edit "me"
if (!$id) {
$id = Auth::user()->id;
if (!$user->exists) {
$user = Auth::user();
}
// try to find given user
$user = User::findOrFail($id);
$states = UserStates::getWithTranslations();
$roles = UserRoles::getWithTranslations();
@@ -35,49 +57,26 @@ class EditUser extends Controller
}
/**
* Edit user - store information
*
* @param EditUserRequest $request
* @param $id
* @param User $user
*
* @return \Illuminate\Http\RedirectResponse
* @internal param $id
*/
public function postEdit(EditUserRequest $request, $id)
public function postEdit(EditUserRequest $request, User $user)
{
$loggedUser = Auth::user();
$user = User::findOrFail($id);
// non-admin user is trying to edit someone else
if ($loggedUser->role != User::ROLE_ADMIN && $id != $loggedUser->id) {
if ($loggedUser->role != User::ROLE_ADMIN && $user->id != $loggedUser->id) {
return redirect()
->back()
->with('error', trans('auth.accessDenied'));
}
// update username if set
if (isset($request->username)) {
$user->username = $request->username;
}
// change name (if set)
if (isset($request->name)) {
$user->name = $request->name;
}
if (isset($request->role)) {
$user->role = $request->role;
}
if (isset($request->status)) {
$user->status = $request->status;
}
if (isset($request->password)) {
$user->password = Hash::make($request->password);
}
$user->email = $request->email;
$user->save();
$this->userRepository->update($user, $request->all());
// fire event about editing user
Event::fire(new EditUserEvent($user));
@@ -86,4 +85,34 @@ class EditUser extends Controller
->back()
->with('success', trans('admin/userManagement.userSuccessfullyEdited'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
*
* @return \Illuminate\Http\Response
*/
public function setPermissions(Request $request, User $user)
{
$permissionIds = $request->get('permissions', []);
$permissions = Permission::whereIn('string_id', array_keys($permissionIds))
->get();
DB::transaction(function () use ($user, $permissions) {
// remove all permissions
$user->permissions()
->detach();
foreach ($permissions as $permission) {
$user->permissions()
->attach($permission->id);
}
});
return redirect()
->back()
->with('success', trans('admin/permissions.successfullySet'));
}
}

Some files were not shown because too many files have changed in this diff Show More