REFACTORING: move part of content business logic into repository

This commit is contained in:
Michal Kváček
2016-10-18 15:36:26 +02:00
parent eabbf48ee0
commit 662700b4f2
19 changed files with 504 additions and 383 deletions
@@ -0,0 +1,7 @@
<?php
namespace App\CMS\Contracts\Repositories;
interface BaseRepository {
public function getOne($id = null);
public function all();
}
@@ -0,0 +1,15 @@
<?php
namespace App\CMS\Contracts\Repositories;
interface Content extends BaseRepository
{
const STATUS_DRAFT = 'draft';
const STATUS_PROTECTED = 'protected';
const STATUS_PUBLIC = 'public';
public function getOverview($handler = null, $statuses = null);
public function getHomepage();
public function getByURL($url);
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\CMS\Contracts\Repositories;
interface Module extends BaseRepository {
public function supportsCategories();
public function getCreateContentTitle();
public function getUpdateContentTitle();
public function getOverviewTitle(\App\Models\Module $module);
}
+2 -1
View File
@@ -1,7 +1,8 @@
<?php <?php
namespace App\CMS\Enumerations; namespace App\CMS\Enumerations;
use App\Models\Content\Content;
use App\CMS\Contracts\Repositories\Content;
class ContentStatuses extends BaseEnumeration class ContentStatuses extends BaseEnumeration
{ {
+3 -3
View File
@@ -12,21 +12,21 @@ class Interaction {
* *
* @param Request $request * @param Request $request
* @param InteractionContract $interaction * @param InteractionContract $interaction
*
* @param array $parameters * @param array $parameters
* *
* @return mixed * @return mixed
* @throws ValidationFailedException * @throws ValidationFailedException
*/ */
public static function handle(Request $request, InteractionContract $interaction, ...$parameters) { public static function handle(Request $request, InteractionContract $interaction, ...$parameters) {
$validationRules = $interaction->getValidationRules($parameters);
$validator = Validator::make($request->all(), $validationRules); // validate interaction
$validator = Validator::make($request->all(), $interaction->getValidationRules($parameters));
if ($validator->fails()) { if ($validator->fails()) {
throw new ValidationFailedException($validator); throw new ValidationFailedException($validator);
} }
// handle it
return $interaction->handle($request, $parameters); return $interaction->handle($request, $parameters);
} }
} }
@@ -3,15 +3,33 @@ namespace App\Cms\Interactions\Admin\Content;
use App\CMS\Contracts\Interaction; use App\CMS\Contracts\Interaction;
use App\CMS\Helpers\CurrentTemplate; use App\CMS\Helpers\CurrentTemplate;
use App\Events\CreateNewContent;
use App\Http\Requests\Request; use App\Http\Requests\Request;
use App\Models\Content\Content; use App\Models\Content\Content;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization; use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
class NewContent implements Interaction class NewContent implements Interaction
{ {
protected $content;
public function __construct()
{
$this->content = App::make(\App\CMS\Contracts\Repositories\Content::class);
}
/**
* @param Request $request
* @param $parameters
*
* @return Content
*/
public function handle(Request $request, $parameters) public function handle(Request $request, $parameters)
{ {
list($moduleHandler) = $parameters;
// create new page // create new page
$page = new Content(); $page = new Content();
$page->template = $request->template; $page->template = $request->template;
@@ -27,7 +45,7 @@ class NewContent implements Interaction
$page->meta_description = $request->metaDescription; $page->meta_description = $request->metaDescription;
$page->content = $request->pageContent; $page->content = $request->pageContent;
$page->status = $request->status; $page->status = $request->status;
$page->module_handler = $request->handler; $page->module_handler = $moduleHandler;
$page->category_id = (int)$request->category > 0 ? $request->category : null; $page->category_id = (int)$request->category > 0 ? $request->category : null;
$page->parent_id = $request->parentPage ? $request->parentPage : null; $page->parent_id = $request->parentPage ? $request->parentPage : null;
@@ -48,6 +66,9 @@ class NewContent implements Interaction
// upload files assigned to content page // upload files assigned to content page
$page->uploadRelatedFiles($request); $page->uploadRelatedFiles($request);
Event::fire(new CreateNewContent($this));
return $page; return $page;
} }
+124
View File
@@ -0,0 +1,124 @@
<?php
namespace App\CMS\Repositories\Content;
use App\CMS\Contracts\Repositories\Content as IContent;
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
{
/**
* @var ContentModel
*/
private $model;
public function __construct(ContentModel $model)
{
$this->model = $model;
}
/**
* Getter for query with setup filter for non-deleted and non-draft pages
*/
protected function getPageQuery()
{
return ContentModel::where('status', '!=', IContent::STATUS_DRAFT)
->select('contents.*')
->with('author')
->join('modules', 'modules.handler', '=', 'contents.module_handler')
->where(function ($query) {
$query->where('published_from', '<', Carbon::now())
->orWhereNull('published_from');
})
->where(function ($query) {
$query->where('published_to', '>', Carbon::now())
->orWhereNull('published_to');
})
->where('language', LaravelLocalization::getCurrentLocale())
->where('modules.enabled', true);
}
public function all()
{
return $this->getPageQuery()
->get();
}
public function getOne($id = null)
{
if (is_null($id)) {
$page = new ContentModel();
$page->user_id = \Auth::user()->id;
$page->language = LaravelLocalization::getCurrentLocale();
$page->module_settings = [];
} else {
$page = $this->model->find($id);
$page->module_settings = json_decode($page->module_settings);
}
return $page;
}
/**
* Getter for homepage content page
* @return Content
*/
public function getHomepage()
{
return $this->getPageQuery()
->where('is_homepage', 1)
->first();
}
/**
* Getter for any page specified by its url.
*
* @param $url
*
* @return Content
*/
public function getByURL($url)
{
return $this->getPageQuery()
->where('url', $url)
->first();
}
/**
* Getter for overview of all content pages.
* These content pages may be filtered by using some handler
*
* @param bool $handler
* @param null $statuses
*
* @return
*/
public function getOverview($handler = null, $statuses = null)
{
$query = ContentModel::select('contents.*', 'modules.name AS module_name', 'modules.id AS module_id')
->join('modules', 'modules.handler', '=', 'contents.module_handler')
->join('users', 'users.id', '=', 'contents.user_id')
->addSelect(DB::raw('COALESCE(users.name, users.email) AS author_name'))
->addSelect('users.email AS author_email')
->whereNull('contents.deleted_at')
->where('contents.language', LaravelLocalization::getCurrentLocale())
->where('modules.enabled', 1)
->orderBy('contents.created_at', 'DESC');
// filter results using handler
if (!is_null($handler)) {
$query = $query->where('contents.module_handler', $handler);
}
// add filtering by status
if (is_array($statuses) && in_array($statuses, ContentStatuses::getSimple())) {
$query = $query->whereIn('contents.status', $statuses);
}
return $query->paginate(20);
}
}
+48
View File
@@ -0,0 +1,48 @@
<?php
namespace App\CMS\Repositories;
use App\CMS\Contracts\Repositories\Module as IModule;
use App\Models\Module as ModuleModel;
class Module extends Repository implements IModule
{
public function getOne($id = null) {
if (!is_null($id)) {
return ModuleModel::find($id);
} else {
return new ModuleModel();
}
}
public function supportsCategories()
{
// TODO: Implement supportsCategories() method.
}
public function getCreateContentTitle()
{
// TODO: Implement getCreateContentTitle() method.
}
public function getUpdateContentTitle()
{
// TODO: Implement getUpdateContentTitle() method.
}
public function getOverviewTitle(ModuleModel $module)
{
$pageHeading = 'admin/contents.overview';
// does user want to filter results using module?
if (!is_null($module) && is_callable([$module->handler, 'getOverviewTitle'])) {
$pageHeading = call_user_func([$module->handler, 'getOverviewTitle']);
}
return $pageHeading;
}
public function all()
{
// TODO: Implement all() method.
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace App\CMS\Repositories;
abstract class Repository
{
protected $model;
public function __call($method, $args)
{
return call_user_func_array([$this->model, $method], $args);
}
}
@@ -0,0 +1,162 @@
<?php
namespace App\Http\Controllers\Admin\Contents;
use App\CMS\Enumerations\ContentStatuses;
use App\Events\DeleteContent;
use App\Events\MakeDraftFromContent;
use App\Events\PublishContent;
use App\Events\SetHomepage;
use App\Http\Controllers\Admin\Controller;
use App\Models\Content\Content;
use Illuminate\Support\Facades\Event;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ContentActions extends Controller
{
/**
* Method for changing page status
* 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
*
* @return \Illuminate\Http\RedirectResponse
*/
public function changeStatus($id, $status)
{
// get possible statuses
$statuses = ContentStatuses::getWithTranslations();
// check if given status is valid
if (!isset($statuses[$status])) {
return redirect()
->route('content.overview')
->with('error', trans('admin/contents.invalidStatus'));
}
try {
// try to find this page
$page = Content::findOrFail($id);
} catch (NotFoundHttpException $e) {
// page not found
return redirect()
->route('content.overview')
->with('error', trans('admin/contents.invalidPage'));
}
// try to change the page
list ($revision, $changedColumns) = $page->updateWithHistory(['status' => 'status'], ['status' => $status]);
// was something changed?
if ($changedColumns == 0) {
return redirect()
->route('content.edit', ['id' => $page->id])
->with('error', trans('admin/contents.nothingToEdit'));
}
// fire events
if ($status != Content::STATUS_DRAFT) {
Event::fire(new PublishContent($page, $revision));
} else {
Event::fire(new MakeDraftFromContent($page, $revision));
}
// redirect back to overview with info for user
return redirect()
->route('content.overview')
->with('success', trans('admin/contents.statusChanged'));
}
/**
* Delete page
*
* @param $id
*
* @return \Illuminate\Http\RedirectResponse
*/
public function delete($id)
{
try {
// try to find this page
$page = Content::findOrFail($id);
} catch (NotFoundHttpException $e) {
// page not found
return redirect()
->route('content.overview')
->with('error', trans('admin/contents.invalidPage'));
}
// change url to something unique
$oldURL = $page->url;
$page->url .= uniqid('_deleted_');
$page->save();
// delete page
$page->delete();
// let module to delete some extra content created during page's life
call_user_func([$page->module_handler, 'delete'], $page);
// trigger delete event
Event::fire(new DeleteContent($page));
// redirect back to overview with info for user
return redirect()
->route('content.overview')
->with('success', trans('admin/contents.pageDeleted', [
'name' => $page->title,
'url' => $oldURL
]));
}
/**
* Sets page as homepage
*
* @param $id
*
* @return \Illuminate\Http\RedirectResponse
*/
public function setHomepage($id)
{
try {
// try to find this page
/**
* @var $page Content
*/
$page = Content::findOrFail($id);
} catch (NotFoundHttpException $e) {
// page not found
return redirect()
->back()
->with('error', trans('admin/contents.invalidPage'));
}
// disable any other existing homepage
Content::where('is_homepage', 1)
->where('language', LaravelLocalization::getCurrentLocale())
->update(['is_homepage' => 0]);
// set new homepage
list ($revision, $changedColumns) = $page->updateWithHistory(['is_homepage' => 'is_homepage'], ['is_homepage' => 1]);
// was something changed?
if ($changedColumns == 0) {
return redirect()
->back()
->with('error', trans('admin/contents.nothingToEdit'));
}
// trigger delete event
Event::fire(new SetHomepage($page, $revision));
// redirect back to overview with info for user
return redirect()
->back()
->with('success', trans('admin/contents.homepageSetup', [
'name' => $page->title,
'url' => $page->url
]));
}
}
@@ -1,53 +1,45 @@
<?php <?php
namespace App\Http\Controllers\Admin\Contents; namespace App\Http\Controllers\Admin\Contents;
use App\CMS\Contracts\Repositories\Content as IContent;
use App\CMS\Contracts\Repositories\Module as IModule;
use App\CMS\Enumerations\ContentStatuses; use App\CMS\Enumerations\ContentStatuses;
use App\Http\Controllers\Admin\Controller; use App\Http\Controllers\Admin\Controller;
use App\Models\Content\Content;
use App\Models\Module;
use Illuminate\Support\Facades\Input;
class ContentOverview extends Controller class ContentOverview extends Controller
{ {
/** /**
* @var Content * @var IContent
*/ */
private $content; private $content;
/**
* @var IModule
*/
private $module;
public function __construct(Content $content) public function __construct(IContent $content, IModule $module)
{ {
parent::__construct();
$this->content = $content; $this->content = $content;
$this->module = $module;
} }
/** /**
* Overview for all content pages. * Overview for all content pages.
* *
* @param bool|false $moduleId * @param null|int $moduleId
* @param null $status * @param null $status
* *
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/ */
public function getOverview($moduleId = false, $status = null) public function index($moduleId = null, $status = null)
{ {
$moduleFilterHandler = false; // get module settings
$perPage = Input::get('perPage') ? Input::get('perPage') : 20; $module = $this->module->getOne($moduleId);
$pageHeading = 'admin/contents.overview'; $pageHeading = $this->module->getOverviewTitle($module);
// does user want to filter results using module?
if (is_numeric($moduleId)) {
$module = Module::findOrFail($moduleId);
$moduleFilterHandler = $module->handler;
if (is_callable([$module->handler, 'getOverviewTitle'])) {
$pageHeading = call_user_func([$module->handler, 'getOverviewTitle']);
}
}
// get pages for overview // get pages for overview
$pages = $this->content->getOverview($moduleFilterHandler, $status, true, true) $handler = $module !== null ? $module->handler : null;
->paginate($perPage); $pages = $this->content->getOverview($handler, [$status]);
// get homepage - for checking if homepage is set and available // get homepage - for checking if homepage is set and available
$homepage = $this->content->getHomepage(); $homepage = $this->content->getHomepage();
@@ -1,21 +1,19 @@
<?php <?php
namespace App\Http\Controllers\Admin\Contents; namespace App\Http\Controllers\Admin\Contents;
use App\CMS\Contracts\Repositories\Content as IContent;
use App\CMS\Contracts\Repositories\Module as IModuleRepository;
use App\CMS\Enumerations\ContentStatuses; use App\CMS\Enumerations\ContentStatuses;
use App\Cms\Handlers\Interactions\Interaction; use App\Cms\Handlers\Interactions\Interaction;
use App\Cms\Interactions\Admin\Content\NewContent; use App\Cms\Interactions\Admin\Content\NewContent;
use App\Events\CreateNewContent as CreateNewContentEvent;
use App\Http\Controllers\Admin\Controller; use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\CreateNewContentRequest; use App\Http\Requests\CreateNewContentRequest;
use App\Http\Requests\Request; use App\Http\Requests\Request;
use App\Models\Content\Content;
use App\Models\FileManager\File; use App\Models\FileManager\File;
use App\Models\Module; use App\Models\Module;
use App\Models\Templates\Template; use App\Models\Templates\Template;
use Illuminate\Support\Facades\Event;
use Modules\Categories\Entities\Category; use Modules\Categories\Entities\Category;
use Pingpong\Modules\Facades\Module as ModuleInstance; use Pingpong\Modules\Facades\Module as ModuleInstance;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/** /**
* Class CreateNewContent * Class CreateNewContent
@@ -31,9 +29,13 @@ class CreateNewContent extends Controller
*/ */
private $file; private $file;
/** /**
* @var Content * @var IContent
*/ */
private $content; private $content;
/**
* @var IModuleRepository
*/
private $module;
/** /**
* CreateNewContent constructor. * CreateNewContent constructor.
@@ -42,12 +44,14 @@ class CreateNewContent extends Controller
* *
* @param File $file * @param File $file
* @param Content $content * @param Content $content
* @param IModuleRepository $module
*/ */
public function __construct(File $file, Content $content) public function __construct(File $file, IContent $content, IModuleRepository $module)
{ {
parent::__construct(); parent::__construct();
$this->file = $file; $this->file = $file;
$this->content = $content; $this->content = $content;
$this->module = $module;
} }
/** /**
@@ -57,7 +61,7 @@ class CreateNewContent extends Controller
* *
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/ */
public function getNew($moduleId) public function create($moduleId)
{ {
$module = Module::findOrFail($moduleId); $module = Module::findOrFail($moduleId);
$statuses = ContentStatuses::getWithTranslations(); $statuses = ContentStatuses::getWithTranslations();
@@ -82,7 +86,7 @@ class CreateNewContent extends Controller
} }
// create default content object // create default content object
$this->content->status = Content::STATUS_DRAFT; $this->content->status = IContent::STATUS_DRAFT;
// render view // render view
return view('admin.content.new', [ return view('admin.content.new', [
@@ -110,21 +114,12 @@ class CreateNewContent extends Controller
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function postNew(Request $request, $moduleId) public function store(Request $request, $moduleId)
{ {
try {
$module = Module::findOrFail($moduleId); $module = Module::findOrFail($moduleId);
} catch (NotFoundHttpException $e) {
return redirect()
->route('content.overview')
->withInput()
->with('error', trans('admin/contents.invalidModule'));
}
$request->handler = $module->handler;
// create new page // create new page
Interaction::handle($request, new NewContent()); Interaction::handle($request, new NewContent(), $module->handler);
return redirect() return redirect()
->route('content.overview') ->route('content.overview')
@@ -6,10 +6,6 @@ use App\Cms\Handlers\Interactions\Interaction;
use App\CMS\Helpers\CurrentTemplate; use App\CMS\Helpers\CurrentTemplate;
use App\Cms\Interactions\Admin\Content\EditContent as EditContentInteraction; use App\Cms\Interactions\Admin\Content\EditContent as EditContentInteraction;
use App\Events\AttemptToEditInvalidContent; use App\Events\AttemptToEditInvalidContent;
use App\Events\DeleteContent;
use App\Events\MakeDraftFromContent;
use App\Events\PublishContent;
use App\Events\SetHomepage;
use App\Http\Controllers\Admin\Controller; use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\EditContentRequest; use App\Http\Requests\EditContentRequest;
use App\Http\Requests\Request; use App\Http\Requests\Request;
@@ -19,7 +15,6 @@ use App\Models\FileManager\File;
use App\Models\Module; use App\Models\Module;
use App\Models\Templates\Template; use App\Models\Templates\Template;
use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Event;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Modules\Categories\Entities\Category; use Modules\Categories\Entities\Category;
use Pingpong\Modules\Facades\Module as ModuleInstance; use Pingpong\Modules\Facades\Module as ModuleInstance;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -56,7 +51,7 @@ class EditContent extends Controller
* *
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/ */
public function getEdit($id) public function edit($id)
{ {
// select all content statuses // select all content statuses
$statuses = ContentStatuses::getWithTranslations(); $statuses = ContentStatuses::getWithTranslations();
@@ -70,7 +65,7 @@ class EditContent extends Controller
->firstOrFail(); ->firstOrFail();
$pageHeading = trans('admin/contents.edit', ['name' => e($page->title)]); $pageHeading = trans('admin/contents.edit', ['name' => e($page->title)]);
if (is_callable([$module->handler, 'getCreateNewTitle'])) { if (is_callable([$module->handler, 'getEditTitle'])) {
$pageHeading = call_user_func([$module->handler, 'getEditTitle'], $page); $pageHeading = call_user_func([$module->handler, 'getEditTitle'], $page);
} }
@@ -120,7 +115,7 @@ class EditContent extends Controller
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function postEdit(Request $request, $id) public function update(Request $request, $id)
{ {
try { try {
/** /**
@@ -154,152 +149,6 @@ class EditContent extends Controller
->with('success', trans('admin/contents.successfullyEdited')); ->with('success', trans('admin/contents.successfullyEdited'));
} }
/**
* Method for changing page status
* 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
*
* @return \Illuminate\Http\RedirectResponse
*/
public function changeStatus($id, $status)
{
// get possible statuses
$statuses = ContentStatuses::getWithTranslations();
// check if given status is valid
if (!isset($statuses[$status])) {
return redirect()
->route('content.overview')
->with('error', trans('admin/contents.invalidStatus'));
}
try {
// try to find this page
$page = Content::findOrFail($id);
} catch (NotFoundHttpException $e) {
// page not found
return redirect()
->route('content.overview')
->with('error', trans('admin/contents.invalidPage'));
}
// try to change the page
list ($revision, $changedColumns) = $page->updateWithHistory(['status' => 'status'], ['status' => $status]);
// was something changed?
if ($changedColumns == 0) {
return redirect()
->route('content.edit', ['id' => $page->id])
->with('error', trans('admin/contents.nothingToEdit'));
}
// fire events
if ($status != Content::STATUS_DRAFT) {
Event::fire(new PublishContent($page, $revision));
} else {
Event::fire(new MakeDraftFromContent($page, $revision));
}
// redirect back to overview with info for user
return redirect()
->route('content.overview')
->with('success', trans('admin/contents.statusChanged'));
}
/**
* Delete page
*
* @param $id
*
* @return \Illuminate\Http\RedirectResponse
*/
public function deletePage($id)
{
try {
// try to find this page
$page = Content::findOrFail($id);
} catch (NotFoundHttpException $e) {
// page not found
return redirect()
->route('content.overview')
->with('error', trans('admin/contents.invalidPage'));
}
// change url to something unique
$oldURL = $page->url;
$page->url .= uniqid('_deleted_');
$page->save();
// delete page
$page->delete();
// let module to delete some extra content created during page's life
call_user_func([$page->module_handler, 'delete'], $page);
// trigger delete event
Event::fire(new DeleteContent($page));
// redirect back to overview with info for user
return redirect()
->route('content.overview')
->with('success', trans('admin/contents.pageDeleted', [
'name' => $page->title,
'url' => $oldURL
]));
}
/**
* Sets page as homepage
*
* @param $id
*
* @return \Illuminate\Http\RedirectResponse
*/
public function setHomepage($id)
{
try {
// try to find this page
/**
* @var $page Content
*/
$page = Content::findOrFail($id);
} catch (NotFoundHttpException $e) {
// page not found
return redirect()
->back()
->with('error', trans('admin/contents.invalidPage'));
}
// disable any other existing homepage
Content::where('is_homepage', 1)
->where('language', LaravelLocalization::getCurrentLocale())
->update(['is_homepage' => 0]);
// set new homepage
list ($revision, $changedColumns) = $page->updateWithHistory(['is_homepage' => 'is_homepage'], ['is_homepage' => 1]);
// was something changed?
if ($changedColumns == 0) {
return redirect()
->back()
->with('error', trans('admin/contents.nothingToEdit'));
}
// trigger delete event
Event::fire(new SetHomepage($page, $revision));
// redirect back to overview with info for user
return redirect()
->back()
->with('success', trans('admin/contents.homepageSetup', [
'name' => $page->title,
'url' => $page->url
]));
}
/** /**
* Convert object of all request data into array of only wanted fields * Convert object of all request data into array of only wanted fields
* *
+8 -8
View File
@@ -1,35 +1,35 @@
<?php <?php
Route::group(['namespace' => 'Contents'], function () { Route::group(['namespace' => 'Contents'], function () {
// list of all static pages // list of all static pages
Route::get('content/overview/{moduleId?}/{status?}', 'ContentOverview@getOverview') Route::get('content/overview/{moduleId?}/{status?}', 'ContentOverview@index')
->name('content.overview'); ->name('content.overview');
// form for creating new static page // form for creating new static page
Route::get('content/new/{moduleId}', 'CreateNewContent@getNew') Route::get('content/new/{moduleId}', 'CreateNewContent@create')
->name('content.new'); ->name('content.new');
// form for editing existing static page // form for editing existing static page
Route::get('content/edit/{id}', 'EditContent@getEdit') Route::get('content/edit/{id}', 'EditContent@edit')
->name('content.edit'); ->name('content.edit');
// post method for creating new static page // post method for creating new static page
Route::post('content/new/{moduleId}', 'CreateNewContent@postNew') Route::post('content/new/{moduleId}', 'CreateNewContent@store')
->name('content.newPost'); ->name('content.newPost');
// post method for creating new static page // post method for creating new static page
Route::post('content/edit/{id}', 'EditContent@postEdit') Route::post('content/edit/{id}', 'EditContent@update')
->name('content.editPost'); ->name('content.editPost');
// change status of page (protected, public or draft) // change status of page (protected, public or draft)
Route::get('content/status/{id}/{status}', 'EditContent@changeStatus') Route::get('content/status/{id}/{status}', 'ContentActions@changeStatus')
->name('content.changeStatus'); ->name('content.changeStatus');
// set homepage // set homepage
Route::get('content/homepage/{id}', 'EditContent@setHomepage') Route::get('content/homepage/{id}', 'ContentActions@setHomepage')
->name('content.setHomepage'); ->name('content.setHomepage');
// delete page // delete page
Route::get('content/delete/{id}', 'EditContent@deletePage') Route::get('content/delete/{id}', 'ContentActions@delete')
->name('content.delete'); ->name('content.delete');
// history of changes for specified page // history of changes for specified page
-55
View File
@@ -36,49 +36,6 @@ class Content extends Model
'module_settings', 'module_settings',
'status' 'status'
]; ];
const STATUS_DRAFT = 'draft';
const STATUS_PROTECTED = 'protected';
const STATUS_PUBLIC = 'public';
/**
* Is current content draft?
*
* @return bool
*/
public function isDraft()
{
return $this->status == self::STATUS_DRAFT;
}
/**
* Is current content visible for all visitors?
*
* @return bool
*/
public function isPublic()
{
return $this->status == self::STATUS_PUBLIC;
}
/**
* Is current content visible only for logged users?
*
* @return bool
*/
public function isProtected()
{
return $this->status == self::STATUS_PROTECTED;
}
/**
* Is current content visible for logged user OR for everyone?
*
* @return bool
*/
public function isVisible()
{
return $this->isPublic() || $this->isProtected();
}
/** /**
* Mark relationship with its historical records * Mark relationship with its historical records
@@ -119,16 +76,4 @@ class Content extends Model
{ {
return $this->belongsTo(Category::class); return $this->belongsTo(Category::class);
} }
public function save(array $options = [])
{
$saved = parent::save($options);
// fire event about creating new content page
if ($this->wasRecentlyCreated) {
Event::fire(new CreateNewContent($this));
}
return $saved;
}
} }
+28 -84
View File
@@ -1,24 +1,20 @@
<?php <?php
namespace App\Models\Content\ModelTraits; namespace App\Models\Content\ModelTraits;
use App\CMS\Enumerations\ContentStatuses; use App\CMS\Contracts\Repositories\Content as IContent;
use App\Http\Requests\Request; use App\Http\Requests\Request;
use App\Models\Content\ContentHasFile; use App\Models\Content\ContentHasFile;
use App\Models\Content\ContentHistory; use App\Models\Content\ContentHistory;
use App\Models\FileManager\Directory; use App\Models\FileManager\Directory;
use App\Models\FileManager\File; use App\Models\FileManager\File;
use Carbon\Carbon;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use App\Models\Content\Content as ContentModel;
trait Content { trait Content
{
/** /**
* @var File * @var File
*/ */
private $file; private $file;
protected $foundSubpages = []; protected $foundSubpages = [];
protected $subpagesInit = false; protected $subpagesInit = false;
@@ -28,49 +24,43 @@ trait Content {
} }
/** /**
* Getter for query with setup filter for non-deleted and non-draft pages * Is current content draft?
*
* @return bool
*/ */
public function getPageQuery() public function isDraft()
{ {
return ContentModel::where('status', '!=', ContentModel::STATUS_DRAFT) return $this->status == IContent::STATUS_DRAFT;
->select('contents.*')
->with('author')
->join('modules', 'modules.handler', '=', 'contents.module_handler')
->where(function ($query) {
$query->where('published_from', '<', Carbon::now())
->orWhereNull('published_from');
})
->where(function ($query) {
$query->where('published_to', '>', Carbon::now())
->orWhereNull('published_to');
})
->where('language', LaravelLocalization::getCurrentLocale())
->where('modules.enabled', true);
} }
/** /**
* Getter for homepage content page * Is current content visible for all visitors?
* @return Content *
* @return bool
*/ */
public function getHomepage() public function isPublic()
{ {
return $this->getPageQuery() return $this->status == IContent::STATUS_PUBLIC;
->where('is_homepage', 1)
->first();
} }
/** /**
* Getter for any page specified by its url. * Is current content visible only for logged users?
* *
* @param $url * @return bool
*
* @return Content
*/ */
public function getByURL($url) public function isProtected()
{ {
return $this->getPageQuery() return $this->status == IContent::STATUS_PROTECTED;
->where('url', $url) }
->first();
/**
* Is current content visible for logged user OR for everyone?
*
* @return bool
*/
public function isVisible()
{
return $this->isPublic() || $this->isProtected();
} }
/** /**
@@ -122,53 +112,6 @@ trait Content {
return $rootPages->get(); return $rootPages->get();
} }
/**
* Getter for overview of all content pages.
* These content pages may be filtered by using some handler
*
* @param bool $handler
* @param bool $status
* @param bool $joinAuthor
* @param bool $joinParent
*
* @return
*/
public function getOverview($handler = false, $status = false, $joinAuthor = false, $joinParent = false)
{
$query = DB::table('contents')
->select('contents.*', 'modules.name AS module_name', 'modules.id AS module_id')
->join('modules', 'modules.handler', '=', 'contents.module_handler')
->whereNull('contents.deleted_at')
->where('contents.language', LaravelLocalization::getCurrentLocale())
->where('modules.enabled', 1)
->orderBy('created_at', 'DESC');
// filter results using handler
if ($handler) {
$query = $query->where('contents.module_handler', $handler);
}
// join user email and user name to results when needed
if ($joinAuthor) {
$query = $query->join('users', 'users.id', '=', 'contents.user_id')
->addSelect(DB::raw('COALESCE(users.name, users.email) AS author_name'))
->addSelect('users.email AS author_email');
}
if ($joinParent) {
$query = $query->leftJoin('contents as parent', 'parent.id', '=', 'contents.parent_id')
->addSelect('parent.title AS parent_title')
->addSelect('parent.url AS parent_url');
}
// add filtering by status
if (in_array($status, ContentStatuses::getSimple())) {
$query = $query->where('contents.status', $status);
}
return $query;
}
/** /**
* Updates current model with information about changed columns * Updates current model with information about changed columns
* *
@@ -329,6 +272,7 @@ trait Content {
return count($allFiles); return count($allFiles);
} }
/** /**
* Save history entry into database * Save history entry into database
* *
+14 -11
View File
@@ -2,7 +2,8 @@
namespace App\Providers; namespace App\Providers;
use App\CMS\Handlers\Registrators\MenuExtensionRegistrator; use App\CMS\Contracts\Repositories\Content as IContent;
use App\CMS\Contracts\Repositories\Module as IModule;
use App\CMS\Handlers\Registrators\SearchEngineRegistrator; use App\CMS\Handlers\Registrators\SearchEngineRegistrator;
use App\CMS\Handlers\Registrators\SettingsExtensionRegistrator; use App\CMS\Handlers\Registrators\SettingsExtensionRegistrator;
use App\CMS\Handlers\Registrators\TemplateRegistrator; use App\CMS\Handlers\Registrators\TemplateRegistrator;
@@ -11,10 +12,15 @@ use App\CMS\Handlers\Search\Content;
use App\CMS\Handlers\Search\Files; use App\CMS\Handlers\Search\Files;
use App\CMS\Handlers\Search\Presenters\AdminContent as AdminContentPresenter; use App\CMS\Handlers\Search\Presenters\AdminContent as AdminContentPresenter;
use App\CMS\Handlers\Search\Presenters\AdminFiles; use App\CMS\Handlers\Search\Presenters\AdminFiles;
use App\CMS\Repositories\Content\Content as ContentRepository;
use App\CMS\Repositories\Module as ModuleRepository;
use App\CMS\Widgets\HtmlCode\HtmlCode; use App\CMS\Widgets\HtmlCode\HtmlCode;
use App\CMS\Widgets\Menu\Menu; use App\CMS\Widgets\Menu\Menu;
use Barryvdh\Debugbar\ServiceProvider as DebugBarServiceProvider;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Pingpong\Menus\MenusServiceProvider;
use Pingpong\Modules\ModulesServiceProvider;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
{ {
@@ -32,6 +38,9 @@ class AppServiceProvider extends ServiceProvider
$this->registerWidgets(); $this->registerWidgets();
$this->registerSettings(); $this->registerSettings();
$this->registerSearch(); $this->registerSearch();
$this->app->bind(IContent::class, ContentRepository::class);
$this->app->bind(IModule::class, ModuleRepository::class);
} }
/** /**
@@ -40,19 +49,13 @@ class AppServiceProvider extends ServiceProvider
*/ */
public function register() public function register()
{ {
if ($this->app->environment() == 'local') { if ($this->app->environment() == 'local' && class_exists(DebugBarServiceProvider::class)) {
try { $this->app->register(DebugBarServiceProvider::class);
$this->app->register('Barryvdh\Debugbar\ServiceProvider');
} catch (\Exception $e) {
// this service provider may not exist when switching from other environment than local
// until composer install is run
// just ignore this exception and when no service provider is available, do not use debugbar
}
} }
// register PingPong module extension // register PingPong module extension
$this->app->register('Pingpong\Modules\ModulesServiceProvider'); $this->app->register(ModulesServiceProvider::class);
$this->app->register('Pingpong\Menus\MenusServiceProvider'); $this->app->register(MenusServiceProvider::class);
$this->app->register(LaravelLocalizationServiceProvider::class); $this->app->register(LaravelLocalizationServiceProvider::class);
// create singletons for registering widgets // create singletons for registering widgets
@@ -3,8 +3,8 @@
@section('pageHeading', @trans(isset($pageHeading) ? $pageHeading : 'admin/contents.overview')) @section('pageHeading', @trans(isset($pageHeading) ? $pageHeading : 'admin/contents.overview'))
@section('headerButtons') @section('headerButtons')
@if($module) @if($module->exists === true)
<a href="{{route('content.new', ['moduleId' => $module->id])}}" class="btn btn-primary btn-sm rounded-s"> <a href="{{route('content.new', ['moduleId' => $module->id])}}" class="btn btn-primary btn-sm rounded">
<i class="fa fa-plus"></i> <i class="fa fa-plus"></i>
</a> </a>
@endif @endif
@@ -21,7 +21,7 @@
</div> </div>
@endif @endif
@if (count($pages)) @if (count($pages) > 0)
<div class="item-list rows-striped"> <div class="item-list rows-striped">
<div class="row bold p-tb-15"> <div class="row bold p-tb-15">
<div class="col-md-1 hidden-sm-down"></div> <div class="col-md-1 hidden-sm-down"></div>
@@ -58,8 +58,8 @@
@if($page->is_homepage) <span class="m-l-10 tag tag-primary">@lang('admin/contents.homepage')</span> @endif @if($page->is_homepage) <span class="m-l-10 tag tag-primary">@lang('admin/contents.homepage')</span> @endif
</div> </div>
<div class="col-lg-2 col-md-3 hidden-sm-down"> <div class="col-lg-2 col-md-3 hidden-sm-down">
<span class="tag @if($page->status == \App\Models\Content\Content::STATUS_PUBLIC) tag-success <span class="tag @if($page->isPublic()) tag-success
@elseif ($page->status == \App\Models\Content\Content::STATUS_DRAFT) tag-danger @elseif ($page->isDraft()) tag-danger
@else tag-warning @endif">{{$statuses[$page->status]}}</span> @else tag-warning @endif">{{$statuses[$page->status]}}</span>
</div> </div>
<div class="col-lg-2 col-md-3 hidden-sm-down"> <div class="col-lg-2 col-md-3 hidden-sm-down">
@@ -98,16 +98,16 @@
</a> </a>
</li> </li>
@if($page->status == \App\Models\Content\Content::STATUS_DRAFT) @if($page->isDraft())
<li> <li>
<a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => \App\Models\Content\Content::STATUS_PUBLIC])}}" <a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => 'public'])}}"
class="confirm" data-toggle="tooltip" class="confirm" data-toggle="tooltip"
title="@lang('admin/contents.makePublic')"> title="@lang('admin/contents.makePublic')">
<i class="fa fa-eye"></i> <i class="fa fa-eye"></i>
</a> </a>
</li> </li>
<li> <li>
<a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => \App\Models\Content\Content::STATUS_PROTECTED])}}" <a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => 'protected'])}}"
class="confirm" data-toggle="tooltip" class="confirm" data-toggle="tooltip"
title="@lang('admin/contents.makeProtected')"> title="@lang('admin/contents.makeProtected')">
<i class="fa fa-lock"></i> <i class="fa fa-lock"></i>
@@ -121,7 +121,7 @@
</a> </a>
</li> </li>
<li> <li>
<a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => \App\Models\Content\Content::STATUS_DRAFT])}}" <a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => 'draft'])}}"
class="button tiny warning confirm" data-toggle="tooltip" class="button tiny warning confirm" data-toggle="tooltip"
title="@lang('admin/contents.makeDraft')"> title="@lang('admin/contents.makeDraft')">
<i class="fa fa-eye-slash"></i> <i class="fa fa-eye-slash"></i>
@@ -136,16 +136,6 @@
class="fa fa-trash-o"></i> class="fa fa-trash-o"></i>
</a> </a>
</li> </li>
{{--<li>--}}
{{--<a class="remove" href="#" data-toggle="modal" data-target="#confirm-modal"> <i--}}
{{--class="fa fa-trash-o "></i> </a>--}}
{{--</li>--}}
{{--<li>--}}
{{--<a class="edit" href="{{route('content.edit', ['id' => $page->id])}}"> <i--}}
{{--class="fa fa-pencil"></i> </a>--}}
{{--</li>--}}
</ul> </ul>
</div> </div>
</div> </div>