Working on module CRUD

This commit is contained in:
Hillel Coren 2016-12-08 15:41:35 +02:00
parent 90d7a27985
commit 2762debd59
34 changed files with 1025 additions and 7 deletions

View File

@ -0,0 +1,68 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Nwidart\Modules\Commands\GeneratorCommand;
use Nwidart\Modules\Support\Stub;
use Nwidart\Modules\Traits\ModuleCommandTrait;
class MakeDatatable extends GeneratorCommand
{
use ModuleCommandTrait;
protected $argumentName = 'name';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $name = 'ninja:make-datatable';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create datatable stub';
protected function getArguments()
{
return [
['name', InputArgument::REQUIRED, 'The name of the datatable.'],
['module', InputArgument::OPTIONAL, 'The name of module will be used.'],
];
}
public function getTemplateContents()
{
$module = $this->laravel['modules']->findOrFail($this->getModuleName());
return (new Stub('/datatable.stub', [
'NAMESPACE' => $this->getClassNamespace($module) . "\\" . config('modules.paths.generator.datatables'),
'LOWER_NAME' => $module->getLowerName(),
'CLASS' => $this->getClass(),
]))->render();
}
public function getDestinationFilePath()
{
$path = $this->laravel['modules']->getModulePath($this->getModuleName());
$seederPath = $this->laravel['modules']->config('paths.generator.datatables');
return $path . $seederPath . '/' . $this->getFileName() . '.php';
}
/**
* @return string
*/
protected function getFileName()
{
return studly_case($this->argument('name')) . 'Datatable';
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace App\Console\Commands;
use Artisan;
use Illuminate\Console\Command;
class MakeModule extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'ninja:make-module {name} {fields?}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate Module CRUD';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$name = $this->argument('name');
$fields = $this->argument('fields');
$this->info("Creating module: {$name}");
$this->info("Fields: {$fields}");
Artisan::call('module:make', ['name' => [$name]]);
Artisan::call('module:make-migration', ['name' => "create_{$name}_table", '--fields' => $fields, 'module' => $name]);
Artisan::call('module:make-model', ['model' => $name, 'module' => $name]);
Artisan::call('ninja:make-datatable', ['name' => $name, 'module' => $name]);
}
protected function getArguments()
{
return [
['name', InputArgument::REQUIRED, 'The name of the module.'],
['fields', InputArgument::OPTIONAL, 'The fields of the module.']
];
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace $NAMESPACE$;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class $CLASS$ extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = '$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 fire()
{
//
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return [
['example', InputArgument::REQUIRED, 'An example argument.'],
];
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return [
['example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null],
];
}
}

View File

@ -0,0 +1,15 @@
{
"name": "$VENDOR$/$LOWER_NAME$",
"description": "",
"authors": [
{
"name": "$AUTHOR_NAME$",
"email": "$AUTHOR_EMAIL$"
}
],
"autoload": {
"psr-4": {
"$MODULE_NAMESPACE$\\$STUDLY_NAME$\\": ""
}
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace $CLASS_NAMESPACE$;
use Illuminate\Routing\Controller;
class $CLASS$ extends Controller
{
}

View File

@ -0,0 +1,69 @@
<?php
namespace $CLASS_NAMESPACE$;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Routing\Controller;
use App\Http\Controllers\BaseController;
use Modules\$STUDLY_NAME$\Datatables\$STUDLY_NAME$Datatable;
class $CLASS$ extends BaseController
{
/**
* Display a listing of the resource.
* @return Response
*/
public function index()
{
return view('list_wrapper', [
'entityType' => '$LOWER_NAME$',
'datatable' => new $STUDLY_NAME$Datatable(),
'title' => trans('texts.$LOWER_NAME$'),
]);
}
/**
* Show the form for creating a new resource.
* @return Response
*/
public function create()
{
return view('$LOWER_NAME$::create');
}
/**
* Store a newly created resource in storage.
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
}
/**
* Show the form for editing the specified resource.
* @return Response
*/
public function edit()
{
return view('$LOWER_NAME$::edit');
}
/**
* Update the specified resource in storage.
* @param Request $request
* @return Response
*/
public function update(Request $request)
{
}
/**
* Remove the specified resource from storage.
* @return Response
*/
public function destroy()
{
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace $NAMESPACE$;
use Utils;
use URL;
use Auth;
use App\Ninja\Datatables\EntityDatatable;
class $CLASS$Datatable extends EntityDatatable
{
public $entityType = '$LOWER_NAME$';
public $sortCol = 1;
public function columns()
{
return [
[
'created_at',
function ($model) {
return Utils::timestampToDateString(strtotime($model->created_at));
}
],
];
}
public function actions()
{
return [
[
trans('texts.edit_$LOWER_NAME$'),
function ($model) {
return URL::to("$LOWER_NAME$/{$model->public_id}/edit");
},
function ($model) {
return Auth::user()->can('editByOwner', ['$LOWER_NAME$', $model->user_id]);
}
],
];
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace $NAMESPACE$;
use Illuminate\Queue\SerializesModels;
class $CLASS$
{
use SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should be broadcast on.
*
* @return array
*/
public function broadcastOn()
{
return [];
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace $NAMESPACE$;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Bus\Queueable;
class $CLASS$ implements ShouldQueue
{
use InteractsWithQueue, SerializesModels, Queueable;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//
}
}

View File

@ -0,0 +1,16 @@
{
"name": "$STUDLY_NAME$",
"alias": "$LOWER_NAME$",
"description": "",
"keywords": [],
"active": 1,
"order": 0,
"providers": [
"$MODULE_NAMESPACE$\\$STUDLY_NAME$\\Providers\\$STUDLY_NAME$ServiceProvider"
],
"aliases":{},
"files": [
"start.php"
],
"icon": "th-large"
}

View File

@ -0,0 +1,31 @@
<?php
namespace $NAMESPACE$;
use $EVENTNAME$;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class $CLASS$
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param \$EVENTNAME$ $event
* @return void
*/
public function handle(\$EVENTNAME$ $event)
{
//
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace $NAMESPACE$;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class $CLASS$ extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('view.name');
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace $NAMESPACE$;
use Closure;
use Illuminate\Http\Request;
class $CLASS$
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
return $next($request);
}
}

View File

@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class $CLASS$ extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('$TABLE$', function (Blueprint $table) {
$FIELDS_UP$
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('$TABLE$', function (Blueprint $table) {
$FIELDS_DOWN$
});
}
}

View File

@ -0,0 +1,43 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class $CLASS$ extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('$TABLE$', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id')->index();
$table->unsignedInteger('account_id')->index();
$table->unsignedInteger('client_id')->index()->nullable();
$FIELDS$
$table->timestamps();
$table->boolean('is_deleted')->default(false);
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
$table->unsignedInteger('public_id')->index();
$table->unique( ['account_id', 'public_id'] );
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('$TABLE$');
}
}

View File

@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class $CLASS$ extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('$TABLE$', function (Blueprint $table) {
$FIELDS_UP$
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('$TABLE$', function (Blueprint $table) {
$FIELDS_DOWN$
});
}
}

View File

@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class $CLASS$ extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::dropIfExists('$TABLE$');
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::create('$TABLE$', function (Blueprint $table) {
$table->increments('id');
$FIELDS$
$table->timestamps();
});
}
}

View File

@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class $CLASS$ extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace $NAMESPACE$;
use App\Models\EntityModel;
use Laracasts\Presenter\PresentableTrait;
use Illuminate\Database\Eloquent\SoftDeletes;
class $CLASS$ extends EntityModel
{
use PresentableTrait;
use SoftDeletes;
/**
* @var string
*/
protected $presenter = 'App\Ninja\Presenters\$CLASS$Presenter';
protected $fillable = $FILLABLE$;
}

View File

@ -0,0 +1,61 @@
<?php
namespace $NAMESPACE$;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class $CLASS$ extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', 'https://laravel.com')
->line('Thank you for using our application!');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace $NAMESPACE$;
use Illuminate\Support\ServiceProvider;
class $CLASS$ extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [];
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace $NAMESPACE$;
use Illuminate\Foundation\Http\FormRequest;
class $CLASS$ extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace $MODULE_NAMESPACE$\$MODULE$\Providers;
use Illuminate\Routing\Router;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class $NAME$ extends ServiceProvider
{
/**
* The root namespace to assume when generating URLs to actions.
*
* @var string
*/
protected $rootUrlNamespace = '$MODULE_NAMESPACE$\$MODULE$\Http\Controllers';
/**
* Called before routes are registered.
*
* Register any model bindings or pattern based filters.
*
* @param Router $router
* @return void
*/
public function before(Router $router)
{
//
}
/**
* Define the routes for the application.
*
* @return void
*/
public function map(Router $router)
{
// require __DIR__ . '/../Http/routes.php';
}
}

View File

@ -0,0 +1,6 @@
<?php
Route::group(['middleware' => 'auth', 'prefix' => '$LOWER_NAME$', 'namespace' => '$MODULE_NAMESPACE$\$STUDLY_NAME$\Http\Controllers'], function()
{
Route::get('/', '$STUDLY_NAME$Controller@index');
});

View File

@ -0,0 +1,5 @@
<?php
return [
'name' => '$STUDLY_NAME$'
];

View File

@ -0,0 +1,98 @@
<?php
namespace $NAMESPACE$;
use Illuminate\Support\ServiceProvider;
class $CLASS$ extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
/**
* Boot the application events.
*
* @return void
*/
public function boot()
{
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
/**
* Register config.
*
* @return void
*/
protected function registerConfig()
{
$this->publishes([
__DIR__.'/../$PATH_CONFIG$/config.php' => config_path('$LOWER_NAME$.php'),
]);
$this->mergeConfigFrom(
__DIR__.'/../$PATH_CONFIG$/config.php', '$LOWER_NAME$'
);
}
/**
* Register views.
*
* @return void
*/
public function registerViews()
{
$viewPath = base_path('resources/views/modules/$LOWER_NAME$');
$sourcePath = __DIR__.'/../$PATH_VIEWS$';
$this->publishes([
$sourcePath => $viewPath
]);
$this->loadViewsFrom(array_merge(array_map(function ($path) {
return $path . '/modules/$LOWER_NAME$';
}, \Config::get('view.paths')), [$sourcePath]), '$LOWER_NAME$');
}
/**
* Register translations.
*
* @return void
*/
public function registerTranslations()
{
$langPath = base_path('resources/lang/modules/$LOWER_NAME$');
if (is_dir($langPath)) {
$this->loadTranslationsFrom($langPath, '$LOWER_NAME$');
} else {
$this->loadTranslationsFrom(__DIR__ .'/../$PATH_LANG$', '$LOWER_NAME$');
}
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [];
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace $NAMESPACE$\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class $NAME$ extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Model::unguard();
// $this->call("OthersTableSeeder");
}
}

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__ . '/Http/routes.php';

View File

@ -0,0 +1,9 @@
@extends('header')
@section('content')
<h1>Hello World</h1>
<p>
This view is loaded from module: {!! config('$LOWER_NAME$.name') !!}
</p>
@stop

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Module $STUDLY_NAME$</title>
</head>
<body>
@yield('content')
</body>
</html>

View File

@ -23,6 +23,8 @@ class Kernel extends ConsoleKernel
'App\Console\Commands\SendReminders',
'App\Console\Commands\GenerateResources',
'App\Console\Commands\TestOFX',
'App\Console\Commands\MakeModule',
'App\Console\Commands\MakeDatatable',
];
/**

View File

@ -29,7 +29,6 @@ class Kernel extends HttpKernel {
*/
protected $routeMiddleware = [
'auth' => 'App\Http\Middleware\Authenticate',
'web' => 'App\Http\Middleware\Authenticate',
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'permissions.required' => 'App\Http\Middleware\PermissionsRequired',
'guest' => 'App\Http\Middleware\RedirectIfAuthenticated',

View File

@ -193,6 +193,12 @@ class EntityModel extends Eloquent
*/
public static function getClassName($entityType)
{
if ( ! Utils::isNinjaProd()) {
if ($module = \Module::find($entityType)) {
return "Modules\\{$module->getName()}\\Models\\{$module->getName()}";
}
}
if ($entityType == ENTITY_QUOTE || $entityType == ENTITY_RECURRING_INVOICE) {
$entityType = ENTITY_INVOICE;
}

View File

@ -23,8 +23,8 @@ return [
*/
'stubs' => [
'enabled' => false,
'path' => base_path() . '/vendor/nwidart/laravel-modules/src/Commands/stubs',
'enabled' => true,
'path' => base_path() . '/storage/stubs',
'files' => [
'start' => 'start.php',
'routes' => 'Http/routes.php',
@ -100,7 +100,7 @@ return [
'event' => 'Events',
'listener' => 'Events/Handlers',
'migration' => 'Database/Migrations',
'model' => 'Entities',
'model' => 'Models',
'repository' => 'Repositories',
'seeder' => 'Database/Seeders',
'controller' => 'Http/Controllers',
@ -113,6 +113,7 @@ return [
'jobs' => 'Jobs',
'emails' => 'Emails',
'notifications' => 'Notifications',
'datatables' => 'Datatables',
],
],
/*
@ -141,10 +142,10 @@ return [
*/
'composer' => [
'vendor' => 'nwidart',
'vendor' => 'invoiceninja',
'author' => [
'name' => 'Nicolas Widart',
'email' => 'n.widart@gmail.com',
'name' => 'Hillel Coren',
'email' => 'contact@invoiceninja.com',
],
],
/*