From eabbf48ee0cda679cae60ee9013aac481906e14e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kv=C3=A1=C4=8Dek?= Date: Mon, 17 Oct 2016 02:52:30 +0200 Subject: [PATCH] REFACTORING: move content update and create logic into separate interactions --- app/CMS/Contracts/Interaction.php | 9 ++ .../Validation/ValidationFailedException.php | 19 ++++ app/CMS/Handlers/Interaction.php | 32 +++++++ .../Admin/Content/EditContent.php | 86 +++++++++++++++++++ .../Interactions/Admin/Content/NewContent.php | 67 +++++++++++++++ app/Exceptions/Handler.php | 24 ++++-- .../Admin/Contents/CreateNewContent.php | 52 ++--------- .../Admin/Contents/EditContent.php | 56 ++---------- app/Http/Requests/CreateNewContentRequest.php | 15 ++-- app/Http/Requests/EditContentRequest.php | 14 +-- app/Models/Content/Content.php | 19 ++++ app/Models/Content/ModelTraits/Content.php | 6 +- app/Providers/AppServiceProvider.php | 13 --- 13 files changed, 271 insertions(+), 141 deletions(-) create mode 100644 app/CMS/Contracts/Interaction.php create mode 100644 app/CMS/Exceptions/Validation/ValidationFailedException.php create mode 100644 app/CMS/Handlers/Interaction.php create mode 100644 app/CMS/Interactions/Admin/Content/EditContent.php create mode 100644 app/CMS/Interactions/Admin/Content/NewContent.php diff --git a/app/CMS/Contracts/Interaction.php b/app/CMS/Contracts/Interaction.php new file mode 100644 index 00000000..6ae65a66 --- /dev/null +++ b/app/CMS/Contracts/Interaction.php @@ -0,0 +1,9 @@ +validator = $validator; + } + + public function getValidator(){ + return $this->validator; + } +} \ No newline at end of file diff --git a/app/CMS/Handlers/Interaction.php b/app/CMS/Handlers/Interaction.php new file mode 100644 index 00000000..722dc8ab --- /dev/null +++ b/app/CMS/Handlers/Interaction.php @@ -0,0 +1,32 @@ +getValidationRules($parameters); + + $validator = Validator::make($request->all(), $validationRules); + + if ($validator->fails()) { + throw new ValidationFailedException($validator); + } + + return $interaction->handle($request, $parameters); + } +} \ No newline at end of file diff --git a/app/CMS/Interactions/Admin/Content/EditContent.php b/app/CMS/Interactions/Admin/Content/EditContent.php new file mode 100644 index 00000000..b2d3a1de --- /dev/null +++ b/app/CMS/Interactions/Admin/Content/EditContent.php @@ -0,0 +1,86 @@ +uploadTitlePhoto($request); + + // let template to modify request and content page + call_user_func_array([CurrentTemplate::handler(), 'beforeSave'], [&$page, $request]); + + $request->url = Str::slug($request->url); + $request->parentPage = $request->parentPage ? $request->parentPage : null; + $request->publishedFrom = empty($request->publishedFrom) ? null : $request->publishedFrom; + $request->publishedTo = empty($request->publishedTo) ? null : $request->publishedTo; + + if (!$file) { + $request->titlePhotoFilename = empty($request->existingTitlePhoto) ? null : $request->existingTitlePhoto; + } else { + $request->titlePhotoFilename = $file['filename']; + } + + // array of fields in database and fields from request + $fields = [ + 'title' => 'title', + 'url' => 'url', + 'template' => 'template', + 'published_from' => 'publishedFrom', + 'published_to' => 'publishedTo', + 'meta_keywords' => 'metaKeywords', + 'meta_description' => 'metaDescription', + 'content' => 'pageContent', + 'parent_id' => 'parentPage', + 'status' => 'status', + 'title_photo' => 'titlePhotoFilename', + 'category_id' => 'category' + ]; + + // save new values with history + // todo move this method out of the controller! + $data = \App\Http\Controllers\Admin\Contents\EditContent::getFields($request, array_values($fields)); + + list($revision, $changedColumns) = $page->updateWithHistory($fields, $data); + + $changedColumns += call_user_func_array([$page->module_handler, 'edit'], [&$page, $request, $revision]); + $changedColumns += $page->uploadRelatedFiles($request, $revision); + + if ($changedColumns > 0) // fire event with + { + Event::fire(new EditContentEvent($page, $revision)); + } + + return [$page, $revision, $changedColumns]; + } + + public function getValidationRules($parameters) + { + $id = $parameters[0]->id; + + // get all available statuses + $statuses = ContentStatuses::getSimple(); + $statuses = implode(',', $statuses); + + return [ + 'title' => 'required', + 'url' => 'required|unique:contents,url,' . $id, + 'publishedFrom' => 'date', + 'publishedTo' => 'date', + 'title_photo' => 'exists:files,id', + 'status' => 'required|in:' . $statuses, + 'parentPage' => 'exists:contents,id' + ]; + } +} \ No newline at end of file diff --git a/app/CMS/Interactions/Admin/Content/NewContent.php b/app/CMS/Interactions/Admin/Content/NewContent.php new file mode 100644 index 00000000..2c108ca8 --- /dev/null +++ b/app/CMS/Interactions/Admin/Content/NewContent.php @@ -0,0 +1,67 @@ +template = $request->template; + + // setup basic info + $page->user_id = \Auth::user()->id; + $page->language = LaravelLocalization::getCurrentLocale(); + $page->title = $request->title; + $page->url = Str::slug($request->url); + $page->published_from = empty($request->publishedFrom) ? null : $request->publishedFrom; + $page->published_to = empty($request->publishedTo) ? null : $request->publishedTo; + $page->meta_keywords = $request->metaKeywords; + $page->meta_description = $request->metaDescription; + $page->content = $request->pageContent; + $page->status = $request->status; + $page->module_handler = $request->handler; + $page->category_id = (int)$request->category > 0 ? $request->category : null; + $page->parent_id = $request->parentPage ? $request->parentPage : null; + + // upload file - if provided + $file = $page->uploadTitlePhoto($request); + + $page->title_photo = $file ? $file['filename'] : null; + + // save module-specific stuff + call_user_func_array([$request->handler, 'createNew'], [&$page, $request]); + + // let template to modify request and content page + call_user_func_array([CurrentTemplate::handler(), 'beforeSave'], [&$page, $request]); + + // save content of page before (possible) uploading related files + $page->save(); + + // upload files assigned to content page + $page->uploadRelatedFiles($request); + + return $page; + } + + public function getValidationRules($parameters) + { + return [ + 'titlePhoto' => 'image', + 'title' => 'required', + 'url' => 'required|unique:contents,url', + 'status' => 'required|in:draft,protected,public', + 'title_photo' => 'exists:files,id', + 'parentPage' => 'exists:contents,id', + 'publishedFrom' => 'date', + 'publishedTo' => 'date', + ]; + } +} \ No newline at end of file diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 9a32465b..7d16af6d 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -2,13 +2,14 @@ namespace App\Exceptions; +use App\CMS\Exceptions\Validation\ValidationFailedException; use Exception; -use Illuminate\Session\TokenMismatchException; -use Illuminate\Validation\ValidationException; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Database\Eloquent\ModelNotFoundException; -use Symfony\Component\HttpKernel\Exception\HttpException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; +use Illuminate\Session\TokenMismatchException; +use Illuminate\Validation\ValidationException; +use Symfony\Component\HttpKernel\Exception\HttpException; class Handler extends ExceptionHandler { @@ -29,7 +30,8 @@ class Handler extends ExceptionHandler * * This is a great spot to send exceptions to Sentry, Bugsnag, etc. * - * @param \Exception $e + * @param \Exception $e + * * @return void */ public function report(Exception $e) @@ -40,15 +42,21 @@ class Handler extends ExceptionHandler /** * Render an exception into an HTTP response. * - * @param \Illuminate\Http\Request $request - * @param \Exception $e - * @return \Illuminate\Http\Response + * @param \Illuminate\Http\Request $request + * @param \Exception $e + * + * @return mixed */ public function render($request, Exception $e) { - if ($e instanceof TokenMismatchException){ + if ($e instanceof TokenMismatchException) { //redirect to form an example of how I handle mine return redirect($request->fullUrl())->with('error', trans('validation.csrf')); + } elseif ($e instanceof ValidationFailedException) { + return redirect() + ->back() + ->withInput() + ->withErrors($e->getValidator()); } return parent::render($request, $e); diff --git a/app/Http/Controllers/Admin/Contents/CreateNewContent.php b/app/Http/Controllers/Admin/Contents/CreateNewContent.php index 8a595663..15e5343f 100644 --- a/app/Http/Controllers/Admin/Contents/CreateNewContent.php +++ b/app/Http/Controllers/Admin/Contents/CreateNewContent.php @@ -2,17 +2,17 @@ namespace App\Http\Controllers\Admin\Contents; use App\CMS\Enumerations\ContentStatuses; +use App\Cms\Handlers\Interactions\Interaction; +use App\Cms\Interactions\Admin\Content\NewContent; use App\Events\CreateNewContent as CreateNewContentEvent; -use App\CMS\Helpers\CurrentTemplate; use App\Http\Controllers\Admin\Controller; use App\Http\Requests\CreateNewContentRequest; +use App\Http\Requests\Request; use App\Models\Content\Content; use App\Models\FileManager\File; use App\Models\Module; use App\Models\Templates\Template; use Illuminate\Support\Facades\Event; -use Illuminate\Support\Str; -use Mcamara\LaravelLocalization\Facades\LaravelLocalization; use Modules\Categories\Entities\Category; use Pingpong\Modules\Facades\Module as ModuleInstance; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -110,7 +110,7 @@ class CreateNewContent extends Controller * * @return \Illuminate\Http\RedirectResponse */ - public function postNew(CreateNewContentRequest $request, $moduleId) + public function postNew(Request $request, $moduleId) { try { $module = Module::findOrFail($moduleId); @@ -121,48 +121,10 @@ class CreateNewContent extends Controller ->with('error', trans('admin/contents.invalidModule')); } + $request->handler = $module->handler; + // create new page - $page = new Content(); - $page->template = $request->template; - - // setup basic info - $page->user_id = \Auth::user()->id; - $page->language = LaravelLocalization::getCurrentLocale(); - $page->title = $request->title; - $page->url = Str::slug($request->url); - $page->published_from = empty($request->publishedFrom) ? null : $request->publishedFrom; - $page->published_to = empty($request->publishedTo) ? null : $request->publishedTo; - $page->meta_keywords = $request->metaKeywords; - $page->meta_description = $request->metaDescription; - $page->content = $request->pageContent; - $page->status = $request->status; - $page->module_handler = $module->handler; - $page->category_id = (int)$request->category > 0 ? $request->category : null; - - // is any parent page specified? - if ($request->parentPage) { - $page->parent_id = $request->parentPage; - } - - // upload file - if provided - $file = $page->uploadTitlePhoto($request); - - $page->title_photo = $file ? $file['filename'] : null; - - // save module-specific stuff - call_user_func_array([$module->handler, 'createNew'], [&$page, $request]); - - // let template to modify request and content page - call_user_func_array([CurrentTemplate::handler(), 'beforeSave'], [&$page, $request]); - - // save content of page before (possible) uploading related files - $page->save(); - - // upload files assigned to content page - $page->uploadRelatedFiles($request); - - // fire event about creating new content page - Event::fire(new CreateNewContentEvent($page)); + Interaction::handle($request, new NewContent()); return redirect() ->route('content.overview') diff --git a/app/Http/Controllers/Admin/Contents/EditContent.php b/app/Http/Controllers/Admin/Contents/EditContent.php index 46fd73fd..81c96fe3 100644 --- a/app/Http/Controllers/Admin/Contents/EditContent.php +++ b/app/Http/Controllers/Admin/Contents/EditContent.php @@ -2,13 +2,14 @@ namespace App\Http\Controllers\Admin\Contents; 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\Events\DeleteContent; -use App\Events\EditContent as EditContentEvent; use App\Events\MakeDraftFromContent; use App\Events\PublishContent; use App\Events\SetHomepage; -use App\CMS\Helpers\CurrentTemplate; use App\Http\Controllers\Admin\Controller; use App\Http\Requests\EditContentRequest; use App\Http\Requests\Request; @@ -18,7 +19,6 @@ use App\Models\FileManager\File; use App\Models\Module; use App\Models\Templates\Template; use Illuminate\Support\Facades\Event; -use Illuminate\Support\Str; use Mcamara\LaravelLocalization\Facades\LaravelLocalization; use Modules\Categories\Entities\Category; use Pingpong\Modules\Facades\Module as ModuleInstance; @@ -120,7 +120,7 @@ class EditContent extends Controller * * @return \Illuminate\Http\RedirectResponse */ - public function postEdit(EditContentRequest $request, $id) + public function postEdit(Request $request, $id) { try { /** @@ -138,47 +138,8 @@ class EditContent extends Controller ->with('error', trans('admin/contents.invalidPage')); } - // upload file - if provided - $file = $page->uploadTitlePhoto($request); - - // let template to modify request and content page - call_user_func_array([CurrentTemplate::handler(), 'beforeSave'], [&$page, $request]); - - $request->url = Str::slug($request->url); - $request->parentPage = $request->parentPage ? $request->parentPage : null; - - $request->publishedFrom = empty($request->publishedFrom) ? null : $request->publishedFrom; - $request->publishedTo = empty($request->publishedTo) ? null : $request->publishedTo; - - if (!$file) { - $request->titlePhotoFilename = empty($request->existingTitlePhoto) ? null : $request->existingTitlePhoto; - } else { - $request->titlePhotoFilename = $file['filename']; - } - - // array of fields in database and fields from request - $fields = [ - 'title' => 'title', - 'url' => 'url', - 'template' => 'template', - 'published_from' => 'publishedFrom', - 'published_to' => 'publishedTo', - 'meta_keywords' => 'metaKeywords', - 'meta_description' => 'metaDescription', - 'content' => 'pageContent', - 'parent_id' => 'parentPage', - 'status' => 'status', - 'title_photo' => 'titlePhotoFilename', - 'category_id' => 'category' - ]; - - // save new values with history - $data = self::getFields($request, array_values($fields)); - - list($revision, $changedColumns) = $page->updateWithHistory($fields, $data); - - $changedColumns += call_user_func_array([$page->module_handler, 'edit'], [&$page, $request, $revision]); - $changedColumns += $page->uploadRelatedFiles($request, $revision); + // edit page + list($page, $revision, $changedColumns) = Interaction::handle($request, new EditContentInteraction(), $page); // was something changed? if ($changedColumns == 0) { @@ -187,9 +148,6 @@ class EditContent extends Controller ->with('error', trans('admin/contents.nothingToEdit')); } - // fire event with - Event::fire(new EditContentEvent($page, $revision)); - // something was changed, inform user return redirect() ->route('content.overview') @@ -272,7 +230,7 @@ class EditContent extends Controller // change url to something unique $oldURL = $page->url; - $page->url .= uniqid('deleted_'); + $page->url .= uniqid('_deleted_'); $page->save(); // delete page diff --git a/app/Http/Requests/CreateNewContentRequest.php b/app/Http/Requests/CreateNewContentRequest.php index c488149c..03b4c382 100644 --- a/app/Http/Requests/CreateNewContentRequest.php +++ b/app/Http/Requests/CreateNewContentRequest.php @@ -2,6 +2,8 @@ namespace App\Http\Requests; +use App\Cms\Interactions\Admin\Content\NewContent; + class CreateNewContentRequest extends Request { /** @@ -11,15 +13,8 @@ class CreateNewContentRequest extends Request */ public function rules() { - return [ - 'titlePhoto' => 'image', - 'title' => 'required', - 'url' => 'required|unique:contents,url', - 'status' => 'required|in:draft,protected,public', - 'title_photo' => 'exists:files,id', - 'parentPage' => 'exists:contents,id', - 'publishedFrom' => 'date', - 'publishedTo' => 'date', - ]; + $validator = new NewContent(); + + return $validator->getValidationRules(); } } diff --git a/app/Http/Requests/EditContentRequest.php b/app/Http/Requests/EditContentRequest.php index 89211305..2a26febe 100644 --- a/app/Http/Requests/EditContentRequest.php +++ b/app/Http/Requests/EditContentRequest.php @@ -13,18 +13,6 @@ class EditContentRequest extends Request */ public function rules() { - // get all available statuses - $statuses = ContentStatuses::getSimple(); - $statuses = implode(',', $statuses); - - return [ - 'title' => 'required', - 'url' => 'required|unique:contents,url,' . $this->id, - 'publishedFrom' => 'date', - 'publishedTo' => 'date', - 'title_photo' => 'exists:files,id', - 'status' => 'required|in:' . $statuses, - 'parentPage' => 'exists:contents,id' - ]; + return []; } } diff --git a/app/Models/Content/Content.php b/app/Models/Content/Content.php index d1806999..beebd301 100644 --- a/app/Models/Content/Content.php +++ b/app/Models/Content/Content.php @@ -2,6 +2,8 @@ namespace App\Models\Content; +use App\Events\CreateNewContent; +use App\Events\Event; use App\Models\FileManager\File; use App\Models\User; use Illuminate\Database\Eloquent\Model; @@ -108,8 +110,25 @@ class Content extends Model return $this->belongsToMany(File::class, 'contents_has_files'); } + /** + * Category of content page + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ public function category() { 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; + } } diff --git a/app/Models/Content/ModelTraits/Content.php b/app/Models/Content/ModelTraits/Content.php index ea75297d..6780e5d5 100644 --- a/app/Models/Content/ModelTraits/Content.php +++ b/app/Models/Content/ModelTraits/Content.php @@ -3,6 +3,8 @@ namespace App\Models\Content\ModelTraits; use App\CMS\Enumerations\ContentStatuses; use App\Http\Requests\Request; +use App\Models\Content\ContentHasFile; +use App\Models\Content\ContentHistory; use App\Models\FileManager\Directory; use App\Models\FileManager\File; use Carbon\Carbon; @@ -352,9 +354,7 @@ trait Content { public function view() { - $this->timestamps = false; $this->viewed++; - $this->save(); - $this->timestamps = true; + $this->save(['timestamps' => false]); } } \ No newline at end of file diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 69855239..05e764d4 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -11,15 +11,10 @@ use App\CMS\Handlers\Search\Content; use App\CMS\Handlers\Search\Files; use App\CMS\Handlers\Search\Presenters\AdminContent as AdminContentPresenter; use App\CMS\Handlers\Search\Presenters\AdminFiles; -use App\Models\Templates\Template; use App\CMS\Widgets\HtmlCode\HtmlCode; use App\CMS\Widgets\Menu\Menu; -use App\CMS\Widgets\OrbitSlider\OrbitSlider; use Illuminate\Support\Facades\App; -use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\File; use Illuminate\Support\ServiceProvider; -use Symfony\Component\Process\Exception\InvalidArgumentException; class AppServiceProvider extends ServiceProvider { @@ -65,10 +60,6 @@ class AppServiceProvider extends ServiceProvider return new WidgetRegistrator($app); }); - $this->app->singleton('registerMenuExtension', function ($app) { - return new MenuExtensionRegistrator($app); - }); - // create registrator for template directories $this->app->singleton('registerTemplateDir', function ($app) { return new TemplateRegistrator($app); @@ -96,7 +87,6 @@ class AppServiceProvider extends ServiceProvider // register all available widgets $registrator->register(HtmlCode::class); $registrator->register(Menu::class); -// $registrator->register(OrbitSlider::class); } /** @@ -109,7 +99,6 @@ class AppServiceProvider extends ServiceProvider $registrator->register('basic', 'admin/settings.basic', 'admin.settings.parts.basic'); $registrator->register('meta', 'admin/settings.meta', 'admin.settings.parts.meta'); $registrator->register('social', 'admin/settings.socialSites', 'admin.settings.parts.social'); - } /** @@ -122,6 +111,4 @@ class AppServiceProvider extends ServiceProvider $registrator->register(new Content(), new AdminContentPresenter(), SearchEngineRegistrator::ADMIN); $registrator->register(new Files(), new AdminFiles(), SearchEngineRegistrator::ADMIN); } - - }