FEATURE: move categories into own repository

This commit is contained in:
Michal Kváček
2017-08-22 14:10:50 +02:00
commit 16471b010f
27 changed files with 679 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
<?php
return [
'name' => 'Categories',
'translatedName' => 'categories::module.name',
'translatedDescription' => 'categories::module.description',
'alias' => 'categories',
'handler' => \Modules\Categories\Handlers\Categories::class,
'providers' => [\Modules\Categories\Providers\CategoriesServiceProvider::class],
'files' => ['start.php'],
'order' => 0,
];
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace Modules\Categories\Contracts\Repositories;
use App\CMS\Contracts\Repositories\BaseRepository;
use App\Models\Module;
interface Category {
public function getForModule(Module $module);
}
@@ -0,0 +1,61 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCategoriesTable extends Migration
{
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->softDeletes();
$table->integer('parent_id')
->unsigned()
->nullable();
$table->integer('position', false, true);
$table->integer('real_depth', false, true);
$table->integer('user_id')
->comment('Author of this category');
$table->integer('module_id')
->comment('ID of module, where this category is used');
$table->string('name')
->comment('Human readable name of category');
$table->string('url')
->index()
->comment('URL slug of category');
$table->text('description');
$table->unique(['url', 'module_id']);
});
Schema::table('categories', function (Blueprint $table) {
$table->foreign('parent_id')
->references('id')
->on('categories')
->onDelete('set null');
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade')
->onUpdate('cascade');
$table->foreign('module_id')
->references('id')
->on('modules')
->onDelete('cascade')
->onUpdate('cascade');
});
}
public function down()
{
Schema::table('categories', function (Blueprint $table) {
Schema::dropIfExists('categories');
});
}
}
@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCategoryClosuresTable extends Migration
{
public function up()
{
Schema::create('category_closure', function (Blueprint $table) {
$table->increments('closure_id');
$table->integer('ancestor', false, true);
$table->integer('descendant', false, true);
$table->integer('depth', false, true);
$table->foreign('ancestor')
->references('id')
->on('categories')
->onDelete('cascade');
$table->foreign('descendant')
->references('id')
->on('categories')
->onDelete('cascade');
});
}
public function down()
{
Schema::table('category_closure', function (Blueprint $table) {
Schema::dropIfExists('category_closure');
});
}
}
View File
+20
View File
@@ -0,0 +1,20 @@
<?php namespace Modules\Categories\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class CategoriesDatabaseSeeder extends Seeder {
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Model::unguard();
// $this->call("OthersTableSeeder");
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace Modules\Categories\Entities;
use App\Models\Content\Content;
use App\Models\Module;
use Franzose\ClosureTable\Models\Entity;
class Category extends Entity
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'categories';
public $timestamps = true;
/**
* ClosureTable model instance.
*
* @var categoryClosure
*/
protected $closure = 'Modules\Categories\Entities\CategoryClosure';
public function module()
{
return $this->belongsTo(Module::class);
}
public function content()
{
return $this->hasMany(Content::class, 'categoryId');
}
}
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace Modules\Categories\Entities;
use Franzose\ClosureTable\Models\ClosureTable;
class CategoryClosure extends ClosureTable
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'category_closure';
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace Modules\Categories\Handlers;
use App\CMS\Contracts\Modules\BaseModuleHandler;
use App\Models\User;
class Categories 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..
*
* @param User $user model of logged user
*/
public static function registerAdminMenu(User $user)
{
// register links in admin menu
$menu = \Menu::instance('mainMenu');
$menu->dropdown(trans('categories::categories.name'), function ($sub) {
$sub->route('categories.new', trans('categories::categories.new'), [], 10, ['icon' => 'fa fa-fw fa-plus']);
$sub->route('categories.overview', trans('categories::categories.overview'), [], 30, ['icon' => 'fa fa-fw fa-tags']);
}, 55, ['icon' => 'fa fa-fw fa-tags']);
}
}
+22
View File
@@ -0,0 +1,22 @@
<?php namespace Modules\Categories\Http\Controllers;
use App\CMS\Enumerations\ModuleNamesWithIds;
use App\Http\Controllers\Admin\Controller;
use Modules\Categories\Entities\Category;
class CategoriesOverview extends Controller
{
public function getOverview()
{
// get list of all categories
$categories = Category::getTree()
->toArray();
$modules = ModuleNamesWithIds::getWithTranslations();
return view('categories::admin.overview', [
'categories' => $categories,
'modules' => $modules
]);
}
}
+60
View File
@@ -0,0 +1,60 @@
<?php namespace Modules\Categories\Http\Controllers;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\Request;
use App\Models\Module;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Modules\Categories\Entities\Category;
class CreateNewCategory extends Controller
{
/**
* Display form for new category
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getNew()
{
// get list of all categories
$categories = Category::getTree()
->toArray();
// get list of modules which supports categories
$modules = Module::where('enabled', true)
->where('support_categories', true)
->get();
return view('categories::admin.new', [
'category' => new Category(),
'categories' => $categories,
'modules' => $modules
]);
}
/**
* Create new category
*
* @param Request $request
*
* @return \Illuminate\Http\RedirectResponse
*/
public function postNew(Request $request)
{
$category = new Category();
$category->user_id = Auth::user()->id;
$category->module_id = $request->moduleId;
$category->name = $request->name;
$category->url = Str::slug($request->url);
$category->description = $request->description;
if ((int)$request->parentCategory) {
$category->parent_id = $request->parentCategory;
}
$category->save();
return redirect()
->route('categories.overview')
->with('success', trans('categories::categories.saveSuccessfull'));
}
}
+77
View File
@@ -0,0 +1,77 @@
<?php namespace Modules\Categories\Http\Controllers;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\Request;
use App\Models\Module;
use Illuminate\Support\Str;
use Modules\Categories\Entities\Category;
class EditCategory extends Controller
{
/**
* Display form for editing category
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getEdit($id)
{
$category = Category::findOrFail($id);
// get list of all categories
$categories = Category::getTree()
->toArray();
// get list of modules which supports categories
$modules = Module::where('enabled', true)
->where('support_categories', true)
->get();
return view('categories::admin.edit', [
'category' => $category,
'categories' => $categories,
'modules' => $modules
]);
}
/**
* Create new category
*
* @param Request $request
* @param $id
*
* @return \Illuminate\Http\RedirectResponse
*/
public function postEdit(Request $request, $id)
{
$category = Category::findOrFail($id);
$category->name = $request->name;
$category->url = Str::slug($request->url);
$category->description = $request->description;
$category->save();
if ($category->parent_id !== $request->parentCategory) {
$category->parent_id = empty($request->parentCategory) ? null : $request->parentCategory;
$category->save();
if (empty($request->parentCategory)) {
$category->makeRoot($category->position);
}
}
return redirect()
->route('categories.edit', ['id' => $id])
->with('success', trans('categories::categories.saveSuccessfull'));
}
public function delete($id) {
$category = Category::findOrFail($id);
$category->delete();
return redirect()
->route('categories.overview')
->with('success', trans('categories::categories.deleteSuccessfull'));
}
}
View File
View File
+23
View File
@@ -0,0 +1,23 @@
<?php
Route::group([
'prefix' => LaravelLocalization::setLocale() . '/admin/categories',
'middleware' => ['admin'],
'namespace' => 'Modules\Categories\Http\Controllers'
], function () {
Route::get('/', 'CategoriesOverview@getOverview')
->name('categories.overview');
Route::get('/new', 'CreateNewCategory@getNew')
->name('categories.new');
Route::post('/new', 'CreateNewCategory@postNew')
->name('categories.postNew');
Route::get('/edit/{id}', 'EditCategory@getEdit')
->name('categories.edit');
Route::post('/edit/{id}', 'EditCategory@postEdit')
->name('categories.postEdit');
Route::get('/delete/{id}', 'EditCategory@delete')
->name('categories.delete');
});
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace Modules\Categories\Providers;
use App\CMS\Modules\ServiceProviders\ServiceProvider;
use Modules\Categories\Contracts\Repositories\Category as ICategory;
use Modules\Categories\Repositories\Category as Category;
class CategoriesServiceProvider extends ServiceProvider
{
protected function setModuleAlias()
{
$this->alias = 'categories';
}
public function boot()
{
parent::boot();
$this->app->bind(ICategory::class, Category::class);
}
protected function setModulePath()
{
$this->path = __DIR__;
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace Modules\Categories\Repositories;
use App\Models\Module;
use Modules\Categories\Entities\Category as CategoryModel;
use Modules\Categories\Contracts\Repositories\Category as ICategory;
class Category implements ICategory
{
public function getForModule(Module $module)
{
$categoryModule = Module::where('alias', 'categories')->first();
$categories = [];
if ($module->support_categories && !is_null($categoryModule) && $categoryModule->enabled) {
$categories = CategoryModel::where('module_id', $module->id)
->get();
}
return $categories;
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php
return [
"actions" => "Akce",
"deleteSuccessfull" => "Kategorie úspěšně smazána",
"description" => "Modul pro správu a kategorizaci obsahu.",
"edit" => "Úprava kategorie",
"fields" => ["description" => "Popis",
"module" => "Modul",
"name" => "Jméno",
"parentCategory" => "Rodičovská kategorie",
"save" => "Uložit",
"url" => "URL",
],
"module" => "Modul",
"name" => "Kategorie",
"new" => "Nová kategorie",
"noCategories" => "Žádná vytvořená kategorie.",
"overview" => "Všechny kategorie",
"saveSuccessfull" => "Kategorie úspěšně uložena",
];
+21
View File
@@ -0,0 +1,21 @@
<?php
return [
'name' => 'Categories',
'description' => 'Module for category management and content categorization.',
'new' => 'New category',
'overview' => 'All categories',
'fields' => [
'name' => 'Name',
'description' => 'Description',
'url' => 'URL',
'module' => 'Module',
'parentCategory' => 'Parent category',
'save' => 'Save category'
],
'edit' => 'Edit category',
'saveSuccessfull' => 'Category successfully saved',
'deleteSuccessfull' => 'Category successfully deleted',
'module' => 'Module',
'actions' => 'Actions',
'noCategories' => 'No categories available'
];
+20
View File
@@ -0,0 +1,20 @@
<?php
return [
"actions" => "Akcie",
"deleteSuccessfull" => "Kategória úspešne zmazaná.",
"description" => "Modul pre správu kategórií a kategorizovanie obsahu",
"edit" => "Upraviť kategóriu",
"fields" => ["description" => "Popis",
"module" => "Modul",
"name" => "Názov",
"parentCategory" => "Rodičovská kategória",
"save" => "Uložiť kategóriu",
"url" => "URL",
],
"module" => "Modul",
"name" => "Kategórie",
"new" => "Nová kategória",
"noCategories" => "Žiadne kategórie nie sú dostupné.",
"overview" => "Všetky kategórie",
"saveSuccessfull" => "Kategória úspešne uložená.",
];
+7
View File
@@ -0,0 +1,7 @@
@extends('admin.layoutWithNavigation')
@section('pageHeading', trans('categories::categories.edit'))
@section('content')
@include('categories::admin.form', ['action' => route('categories.postEdit', ['id' => $category->id])])
@endsection
+67
View File
@@ -0,0 +1,67 @@
<form action="{{$action}}" method="post">
{!! csrf_field() !!}
<div class="row">
<div class="col-lg-5">
<label class="label-control">
@lang('categories::categories.fields.name')
</label>
<input type="text" name="name" class="form-control slug-source" value="{{old('name', $category->name)}}">
</div>
<div class="col-lg-5">
<label>
@lang('categories::categories.fields.url')
</label>
<input type="text" name="url" class="form-control slug-target" value="{{old('url', $category->url)}}">
</div>
<div class="col-lg-2 text-center">
<div>
<label>
<input class="checkbox" value="1" id="lockUrl"
@if(old('lockUrl') || ($category->id > 0 && \Illuminate\Support\Str::slug($category->name) != $category->url)) checked
@endif name="lockUrl" type="checkbox">
<span>@lang('admin/contents.lockUrl')</span>
</label>
</div>
</div>
</div>
<label class="label-control">
@lang('categories::categories.fields.description')
</label>
<textarea class="form-control" name="description">{{old('description', $category->description)}}</textarea>
<div class="row">
<div class="col-lg-6">
<label class="label-control">
@lang('categories::categories.fields.module')
</label>
<select class="form-control" name="moduleId" @if($category->id) disabled @endif>
@foreach($modules as $module)
<option @if($module->id == $category->module_id) selected
@endif value="{{$module->id}}">{{trans($module->name)}}</option>
@endforeach
</select>
</div>
<div class="col-lg-6">
@if(count($categories))
<label class="label-control">
@lang('categories::categories.fields.parentCategory')
</label>
<select class="form-control" name="parentCategory">
<option value="">@lang('admin/contents.noCategory')</option>
@foreach($categories as $parentCategory)
@include('categories::admin.snippets.optionParentCategories', ['level' => 0, 'selectedCategory' => $category, 'currentCategory' => $parentCategory])
@endforeach
</select>
@endif
</div>
</div>
<button type="submit" class="btn btn-primary">@lang('categories::categories.fields.save')</button>
</form>
+7
View File
@@ -0,0 +1,7 @@
@extends('admin.layoutWithNavigation')
@section('pageHeading', trans('categories::categories.new'))
@section('content')
@include('categories::admin.form', ['action' => route('categories.postNew')])
@endsection
+35
View File
@@ -0,0 +1,35 @@
@extends('admin.layoutWithNavigation')
@section('pageHeading', trans('categories::categories.overview'))
@section('content')
<div class="card items">
<div class="card-block">
@if(count($categories))
<div class="item-list striped rows-striped">
<table class="table table-striped">
<thead>
<tr>
<th>@lang('categories::categories.name')</th>
<th>@lang('categories::categories.module')</th>
<th>@lang('categories::categories.actions')</th>
</tr>
</thead>
<tbody>
@foreach($categories as $category)
@include('categories::admin.snippets.overviewRow', ['level' => 0, 'currentCategory' => $category])
@endforeach
</tbody>
</table>
</div>
@else
<div class="alert alert-info">
@lang('categories::categories.noCategories')
</div>
@endif
</div>
</div>
@stop
@@ -0,0 +1,9 @@
<option @if($currentCategory['id'] == $selectedCategory->parent_id) selected @endif value="{{$currentCategory['id']}}">
{{str_repeat('-', $level)}} {{$currentCategory['name']}}
</option>
@if(isset($currentCategory['children']))
@foreach($currentCategory['children'] as $category)
@include('categories::admin.snippets.optionParentCategories', ['selectedCategory' => $selectedCategory, 'currentCategory' => $category, 'level' => $level+1])
@endforeach
@endif
@@ -0,0 +1,39 @@
<tr>
<td>
{{str_repeat('-', $level)}} <a href="{{route('categories.edit', ['id' => $currentCategory['id']])}}">{{$currentCategory['name']}}</a>
</td>
<td>@lang($modules[$currentCategory['module_id']])</td>
<td>
<div class="item-actions-dropdown">
<a class="item-actions-toggle-btn">
<span class="inactive">
<i class="fa fa-cog"></i>
</span>
<span class="active">
<i class="fa fa-chevron-circle-right"></i>
</span>
</a>
<div class="item-actions-block">
<ul class="item-actions-list">
<li>
<a href="{{route('categories.edit', ['id' => $currentCategory['id']])}}"><i
class="fa fa-fw fa-pencil"></i></a>
</li>
<li>
<a class="confirm remove"
href="{{route('categories.delete', ['id' => $currentCategory['id']])}}"><i
class="fa fa-fw fa-trash"></i></a>
</li>
</ul>
</div>
</div>
</td>
</tr>
@if(isset($currentCategory['children']))
@foreach($currentCategory['children'] as $category)
@include('categories::admin.snippets.overviewRow', ['currentCategory' => $category, 'level' => $level+1])
@endforeach
@endif
Executable
+15
View File
@@ -0,0 +1,15 @@
<?php
/*
|--------------------------------------------------------------------------
| Register Namespaces And Routes
|--------------------------------------------------------------------------
|
| When a module starting, this file will executed automatically. This helps
| to register some namespaces like translator or view. Also this file
| will load the routes file for each module. You may also modify
| this file as you want.
|
*/
require __DIR__ . DIRECTORY_SEPARATOR.'Http'.DIRECTORY_SEPARATOR.'routes.php';