diff --git a/.env.example b/.env.example index de63021933422..2d1db72861cca 100644 --- a/.env.example +++ b/.env.example @@ -81,3 +81,6 @@ WEPAY_FEE_PAYER=payee WEPAY_APP_FEE_MULTIPLIER=0.002 WEPAY_APP_FEE_FIXED=0 WEPAY_THEME='{"name":"Invoice Ninja","primary_color":"0b4d78","secondary_color":"0b4d78","background_color":"f8f8f8","button_color":"33b753"}' # See https://www.wepay.com/developer/reference/structures#theme + +BLUEVINE_PARTNER_UNIQUE_ID= +BLUEVINE_PARTNER_TOKEN= diff --git a/.gitignore b/.gitignore index eba40da49d7d9..0b0536378eb08 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ Thumbs.db /error_log /auth.json /public/error_log +/Modules /ninja.sublime-project /ninja.sublime-workspace diff --git a/app/Console/Commands/CheckData.php b/app/Console/Commands/CheckData.php index 17484c8f6aefe..9b5bbad58eefd 100644 --- a/app/Console/Commands/CheckData.php +++ b/app/Console/Commands/CheckData.php @@ -73,12 +73,16 @@ class CheckData extends Command { $this->logMessage('Done'); $errorEmail = env('ERROR_EMAIL'); - if ( ! $this->isValid && $errorEmail) { - Mail::raw($this->log, function ($message) use ($errorEmail) { - $message->to($errorEmail) - ->from(CONTACT_EMAIL) - ->subject('Check-Data'); - }); + if ( ! $this->isValid) { + if ($errorEmail) { + Mail::raw($this->log, function ($message) use ($errorEmail) { + $message->to($errorEmail) + ->from(CONTACT_EMAIL) + ->subject('Check-Data'); + }); + } else { + $this->info($this->log); + } } } @@ -209,6 +213,7 @@ class CheckData extends Command { ->where('accounts.id', '!=', 20432) ->where('clients.is_deleted', '=', 0) ->where('invoices.is_deleted', '=', 0) + ->where('invoices.is_public', '=', 1) ->where('invoices.invoice_type_id', '=', INVOICE_TYPE_STANDARD) ->where('invoices.is_recurring', '=', 0) ->havingRaw('abs(clients.balance - sum(invoices.balance)) > .01 and clients.balance != 999999999.9999'); diff --git a/app/Console/Commands/MakeClass.php b/app/Console/Commands/MakeClass.php new file mode 100644 index 0000000000000..83b99fa62b300 --- /dev/null +++ b/app/Console/Commands/MakeClass.php @@ -0,0 +1,174 @@ +laravel['modules']->findOrFail($this->getModuleName()); + $path = str_replace('/', '\\', config('modules.paths.generator.' . $this->argument('class'))); + + return (new Stub('/' . $this->argument('prefix') . $this->argument('class') . '.stub', [ + 'NAMESPACE' => $this->getClassNamespace($module) . "\\" . $path, + 'LOWER_NAME' => $module->getLowerName(), + 'CLASS' => $this->getClass(), + 'STUDLY_NAME' => Str::studly($module->getLowerName()), + 'DATATABLE_COLUMNS' => $this->getColumns(), + 'FORM_FIELDS' => $this->getFormFields(), + 'DATABASE_FIELDS' => $this->getDatabaseFields($module), + 'TRANSFORMER_FIELDS' => $this->getTransformerFields($module), + ]))->render(); + } + + public function getDestinationFilePath() + { + $path = $this->laravel['modules']->getModulePath($this->getModuleName()); + $seederPath = $this->laravel['modules']->config('paths.generator.' . $this->argument('class')); + + return $path . $seederPath . '/' . $this->getFileName() . '.php'; + } + + /** + * @return string + */ + protected function getFileName() + { + if ($this->option('filename')) { + return $this->option('filename'); + } + return studly_case($this->argument('prefix')) . studly_case($this->argument('name')) . Str::studly($this->argument('class')); + } + + protected function getColumns() + { + $fields = $this->option('fields'); + $fields = explode(',', $fields); + $str = ''; + + foreach ($fields as $field) { + if ( ! $field) { + continue; + } + $field = explode(':', $field)[0]; + $str .= '[ + \''. $field . '\', + function ($model) { + return $model->' . $field . '; + } + ],'; + } + + return $str; + } + + protected function getFormFields() + { + $fields = $this->option('fields'); + $fields = explode(',', $fields); + $str = ''; + + foreach ($fields as $field) { + if ( ! $field) { + continue; + } + $parts = explode(':', $field); + $field = $parts[0]; + $type = $parts[1]; + + if ($type == 'text') { + $str .= "{!! Former::textarea('" . $field . "') !!}\n"; + } else { + $str .= "{!! Former::text('" . $field . "') !!}\n"; + } + } + + return $str; + } + + protected function getDatabaseFields($module) + { + $fields = $this->option('fields'); + $fields = explode(',', $fields); + $str = ''; + + foreach ($fields as $field) { + if ( ! $field) { + continue; + } + $field = explode(':', $field)[0]; + $str .= "'" . $module->getLowerName() . ".{$field}', "; + } + + return $str; + } + + protected function getTransformerFields($module) + { + $fields = $this->option('fields'); + $fields = explode(',', $fields); + $str = ''; + + foreach ($fields as $field) { + if ( ! $field) { + continue; + } + $field = explode(':', $field)[0]; + $str .= "'{$field}' => $" . $module->getLowerName() . "->$field,\n "; + } + + return rtrim($str); + + } +} diff --git a/app/Console/Commands/MakeModule.php b/app/Console/Commands/MakeModule.php new file mode 100644 index 0000000000000..b96cb9ea76745 --- /dev/null +++ b/app/Console/Commands/MakeModule.php @@ -0,0 +1,98 @@ +argument('name'); + $fields = $this->argument('fields'); + $migrate = $this->option('migrate'); + $lower = strtolower($name); + + // convert 'name:string,description:text' to 'name,description' + $fillable = explode(',', $fields); + $fillable = array_map(function($item) { + return explode(':', $item)[0]; + }, $fillable); + $fillable = join(',', $fillable); + + $this->info("Creating module: {$name}..."); + + Artisan::call('module:make', ['name' => [$name]]); + Artisan::call('module:make-migration', ['name' => "create_{$lower}_table", '--fields' => $fields, 'module' => $name]); + Artisan::call('module:make-model', ['model' => $name, 'module' => $name, '--fillable' => $fillable]); + + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'views', '--fields' => $fields, '--filename' => 'edit.blade']); + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'datatable', '--fields' => $fields]); + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'repository', '--fields' => $fields]); + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'policy']); + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'auth-provider']); + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'presenter']); + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'request']); + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'request', 'prefix' => 'create']); + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'request', 'prefix' => 'update']); + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'api-controller']); + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'transformer', '--fields' => $fields]); + Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'lang', '--filename' => 'texts']); + + if ($migrate == 'false') { + $this->info("Use the following command to run the migrations:\nphp artisan module:migrate $name"); + } else { + Artisan::call('module:migrate', ['module' => $name]); + } + + Artisan::call('module:dump'); + + $this->info("Done"); + } + + protected function getArguments() + { + return [ + ['name', InputArgument::REQUIRED, 'The name of the module.'], + ['fields', InputArgument::OPTIONAL, 'The fields of the module.'] + ]; + } + + protected function getOptions() + { + return array( + array('migrate', null, InputOption::VALUE_OPTIONAL, 'The model attributes.', null), + ); + } + +} diff --git a/app/Console/Commands/SendRecurringInvoices.php b/app/Console/Commands/SendRecurringInvoices.php index 89e08bf582bae..3a546f187edf8 100644 --- a/app/Console/Commands/SendRecurringInvoices.php +++ b/app/Console/Commands/SendRecurringInvoices.php @@ -58,7 +58,7 @@ class SendRecurringInvoices extends Command $today = new DateTime(); $invoices = Invoice::with('account.timezone', 'invoice_items', 'client', 'user') - ->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND is_recurring IS TRUE AND frequency_id > 0 AND start_date <= ? AND (end_date IS NULL OR end_date >= ?)', [$today, $today]) + ->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND is_recurring IS TRUE AND is_public IS TRUE AND frequency_id > 0 AND start_date <= ? AND (end_date IS NULL OR end_date >= ?)', [$today, $today]) ->orderBy('id', 'asc') ->get(); $this->info(count($invoices).' recurring invoice(s) found'); @@ -81,7 +81,7 @@ class SendRecurringInvoices extends Command } $delayedAutoBillInvoices = Invoice::with('account.timezone', 'recurring_invoice', 'invoice_items', 'client', 'user') - ->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND is_recurring IS FALSE + ->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND is_recurring IS FALSE AND is_public IS TRUE AND balance > 0 AND due_date = ? AND recurring_invoice_id IS NOT NULL', [$today->format('Y-m-d')]) ->orderBy('invoices.id', 'asc') diff --git a/app/Console/Commands/stubs/api-controller.stub b/app/Console/Commands/stubs/api-controller.stub new file mode 100644 index 0000000000000..8a047352ca8d3 --- /dev/null +++ b/app/Console/Commands/stubs/api-controller.stub @@ -0,0 +1,164 @@ +$LOWER_NAME$Repo = $$LOWER_NAME$Repo; + } + + /** + * @SWG\Get( + * path="/$LOWER_NAME$", + * summary="List of $LOWER_NAME$", + * tags={"$LOWER_NAME$"}, + * @SWG\Response( + * response=200, + * description="A list with $LOWER_NAME$", + * @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/$STUDLY_NAME$")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ + public function index() + { + $data = $this->$LOWER_NAME$Repo->all(); + + return $this->listResponse($data); + } + + /** + * @SWG\Get( + * path="/$LOWER_NAME$/{$LOWER_NAME$_id}", + * summary="Individual $STUDLY_NAME$", + * tags={"$LOWER_NAME$"}, + * @SWG\Response( + * response=200, + * description="A single $LOWER_NAME$", + * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/$STUDLY_NAME$")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ + + public function show($STUDLY_NAME$Request $request) + { + return $this->itemResponse($request->entity()); + } + + + + + /** + * @SWG\Post( + * path="/$LOWER_NAME$", + * tags={"$LOWER_NAME$"}, + * summary="Create a $LOWER_NAME$", + * @SWG\Parameter( + * in="body", + * name="body", + * @SWG\Schema(ref="#/definitions/$STUDLY_NAME$") + * ), + * @SWG\Response( + * response=200, + * description="New $LOWER_NAME$", + * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/$STUDLY_NAME$")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ + public function store(Create$STUDLY_NAME$Request $request) + { + $$LOWER_NAME$ = $this->$LOWER_NAME$Repo->save($request->input()); + + return $this->itemResponse($$LOWER_NAME$); + } + + /** + * @SWG\Put( + * path="/$LOWER_NAME$/{$LOWER_NAME$_id}", + * tags={"$LOWER_NAME$"}, + * summary="Update a $LOWER_NAME$", + * @SWG\Parameter( + * in="body", + * name="body", + * @SWG\Schema(ref="#/definitions/$STUDLY_NAME$") + * ), + * @SWG\Response( + * response=200, + * description="Update $LOWER_NAME$", + * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/$STUDLY_NAME$")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ + + public function update(Update$STUDLY_NAME$Request $request, $publicId) + { + if ($request->action) { + return $this->handleAction($request); + } + + $$LOWER_NAME$ = $this->$LOWER_NAME$Repo->save($request->input(), $request->entity()); + + return $this->itemResponse($$LOWER_NAME$); + } + + + /** + * @SWG\Delete( + * path="/$LOWER_NAME$/{$LOWER_NAME$_id}", + * tags={"$LOWER_NAME$"}, + * summary="Delete a $LOWER_NAME$", + * @SWG\Parameter( + * in="body", + * name="body", + * @SWG\Schema(ref="#/definitions/$STUDLY_NAME$") + * ), + * @SWG\Response( + * response=200, + * description="Delete $LOWER_NAME$", + * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/$STUDLY_NAME$")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ + + public function destroy(Update$STUDLY_NAME$Request $request) + { + $$LOWER_NAME$ = $request->entity(); + + $this->$LOWER_NAME$Repo->delete($$LOWER_NAME$); + + return $this->itemResponse($$LOWER_NAME$); + } + +} diff --git a/app/Console/Commands/stubs/auth-provider.stub b/app/Console/Commands/stubs/auth-provider.stub new file mode 100644 index 0000000000000..465c2dc96ef52 --- /dev/null +++ b/app/Console/Commands/stubs/auth-provider.stub @@ -0,0 +1,17 @@ + \Modules\$STUDLY_NAME$\Policies\$STUDLY_NAME$Policy::class, + ]; +} diff --git a/app/Console/Commands/stubs/command.stub b/app/Console/Commands/stubs/command.stub new file mode 100755 index 0000000000000..1537601329820 --- /dev/null +++ b/app/Console/Commands/stubs/command.stub @@ -0,0 +1,68 @@ +$LOWER_NAME$Repo = $$LOWER_NAME$Repo; + } + + /** + * Display a listing of the resource. + * @return Response + */ + public function index() + { + return view('list_wrapper', [ + 'entityType' => '$LOWER_NAME$', + 'datatable' => new $STUDLY_NAME$Datatable(), + 'title' => mtrans('$LOWER_NAME$', '$LOWER_NAME$_list'), + ]); + } + + public function datatable(DatatableService $datatableService) + { + $search = request()->input('test'); + $userId = Auth::user()->filterId(); + + $datatable = new $STUDLY_NAME$Datatable(); + $query = $this->$LOWER_NAME$Repo->find($search, $userId); + + return $datatableService->createDatatable($datatable, $query); + } + + /** + * Show the form for creating a new resource. + * @return Response + */ + public function create($STUDLY_NAME$Request $request) + { + $data = [ + '$LOWER_NAME$' => null, + 'method' => 'POST', + 'url' => '$LOWER_NAME$', + 'title' => mtrans('$LOWER_NAME$', 'new_$LOWER_NAME$'), + ]; + + return view('$LOWER_NAME$::edit', $data); + } + + /** + * Store a newly created resource in storage. + * @param Request $request + * @return Response + */ + public function store(Create$STUDLY_NAME$Request $request) + { + $$LOWER_NAME$ = $this->$LOWER_NAME$Repo->save($request->input()); + + return redirect()->to($$LOWER_NAME$->present()->editUrl) + ->with('message', mtrans('$LOWER_NAME$', 'created_$LOWER_NAME$')); + } + + /** + * Show the form for editing the specified resource. + * @return Response + */ + public function edit($STUDLY_NAME$Request $request) + { + $$LOWER_NAME$ = $request->entity(); + + $data = [ + '$LOWER_NAME$' => $$LOWER_NAME$, + 'method' => 'PUT', + 'url' => '$LOWER_NAME$/' . $$LOWER_NAME$->public_id, + 'title' => mtrans('$LOWER_NAME$', 'edit_$LOWER_NAME$'), + ]; + + return view('$LOWER_NAME$::edit', $data); + } + + /** + * Show the form for editing a resource. + * @return Response + */ + public function show($STUDLY_NAME$Request $request) + { + return redirect()->to("$LOWER_NAME$/{$request->$LOWER_NAME$}/edit"); + } + + /** + * Update the specified resource in storage. + * @param Request $request + * @return Response + */ + public function update(Update$STUDLY_NAME$Request $request) + { + $$LOWER_NAME$ = $this->$LOWER_NAME$Repo->save($request->input(), $request->entity()); + + return redirect()->to($$LOWER_NAME$->present()->editUrl) + ->with('message', mtrans('$LOWER_NAME$', 'updated_$LOWER_NAME$')); + } + + /** + * Update multiple resources + */ + public function bulk() + { + $action = request()->input('action'); + $ids = request()->input('public_id') ?: request()->input('ids'); + $count = $this->$LOWER_NAME$Repo->bulk($ids, $action); + + return redirect()->to('$LOWER_NAME$') + ->with('message', mtrans('$LOWER_NAME$', $action . '_$LOWER_NAME$_complete')); + } +} diff --git a/app/Console/Commands/stubs/createrequest.stub b/app/Console/Commands/stubs/createrequest.stub new file mode 100644 index 0000000000000..d8ad07cfb0a80 --- /dev/null +++ b/app/Console/Commands/stubs/createrequest.stub @@ -0,0 +1,28 @@ +user()->can('create', '$LOWER_NAME$'); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + + ]; + } +} diff --git a/app/Console/Commands/stubs/datatable.stub b/app/Console/Commands/stubs/datatable.stub new file mode 100644 index 0000000000000..f9983b806e14d --- /dev/null +++ b/app/Console/Commands/stubs/datatable.stub @@ -0,0 +1,43 @@ +created_at); + } + ], + ]; + } + + public function actions() + { + return [ + [ + mtrans('$LOWER_NAME$', '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]); + } + ], + ]; + } + +} diff --git a/app/Console/Commands/stubs/event.stub b/app/Console/Commands/stubs/event.stub new file mode 100755 index 0000000000000..ad1cb696699c2 --- /dev/null +++ b/app/Console/Commands/stubs/event.stub @@ -0,0 +1,30 @@ + '$STUDLY_NAME$', + '$LOWER_NAME$_list' => '$STUDLY_NAME$ List', + 'archive_$LOWER_NAME$' => 'Archive $STUDLY_NAME$', + 'delete_$LOWER_NAME$' => 'Delete $STUDLY_NAME$', + 'edit_$LOWER_NAME$' => 'Edit $STUDLY_NAME$', + 'restore_$LOWER_NAME$' => 'Restore $STUDLY_NAME$', + 'new_$LOWER_NAME$' => 'New $STUDLY_NAME$', + 'created_$LOWER_NAME$' => 'Successfully created $LOWER_NAME$', + 'updated_$LOWER_NAME$' => 'Successfully updated $LOWER_NAME$', + +); + +return $LANG; + +?> diff --git a/app/Console/Commands/stubs/listener.stub b/app/Console/Commands/stubs/listener.stub new file mode 100755 index 0000000000000..5637af194df83 --- /dev/null +++ b/app/Console/Commands/stubs/listener.stub @@ -0,0 +1,31 @@ +view('view.name'); + } +} diff --git a/app/Console/Commands/stubs/middleware.stub b/app/Console/Commands/stubs/middleware.stub new file mode 100755 index 0000000000000..954583ed4cf59 --- /dev/null +++ b/app/Console/Commands/stubs/middleware.stub @@ -0,0 +1,21 @@ +increments('id'); + $table->unsignedInteger('user_id')->index(); + $table->unsignedInteger('account_id')->index(); + $table->unsignedInteger('client_id')->index()->nullable(); + +$FIELDS$ + $table->timestamps(); + $table->softDeletes(); + $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(strtolower('$TABLE$')); + } +} diff --git a/app/Console/Commands/stubs/migration/delete.stub b/app/Console/Commands/stubs/migration/delete.stub new file mode 100755 index 0000000000000..c145a2f5466b3 --- /dev/null +++ b/app/Console/Commands/stubs/migration/delete.stub @@ -0,0 +1,31 @@ +increments('id'); +$FIELDS$ + $table->timestamps(); + }); + } +} diff --git a/app/Console/Commands/stubs/migration/plain.stub b/app/Console/Commands/stubs/migration/plain.stub new file mode 100755 index 0000000000000..73565c28e5d9a --- /dev/null +++ b/app/Console/Commands/stubs/migration/plain.stub @@ -0,0 +1,27 @@ +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 [ + // + ]; + } +} diff --git a/app/Console/Commands/stubs/policy.stub b/app/Console/Commands/stubs/policy.stub new file mode 100644 index 0000000000000..fdb0f5a884a6e --- /dev/null +++ b/app/Console/Commands/stubs/policy.stub @@ -0,0 +1,10 @@ + \Modules\$STUDLY_NAME$\Policies\$STUDLY_NAME$Policy::class, + ]; + + /** + * Register the service provider. + * + * @return void + */ + public function register() + { + // + } + + /** + * Get the services provided by the provider. + * + * @return array + */ + public function provides() + { + return []; + } +} diff --git a/app/Console/Commands/stubs/repository.stub b/app/Console/Commands/stubs/repository.stub new file mode 100644 index 0000000000000..208172251ecff --- /dev/null +++ b/app/Console/Commands/stubs/repository.stub @@ -0,0 +1,71 @@ +orderBy('created_at', 'desc') + ->withTrashed(); + } + + public function find($filter = null, $userId = false) + { + $query = DB::table('$LOWER_NAME$') + ->where('$LOWER_NAME$.account_id', '=', \Auth::user()->account_id) + ->select( + $DATABASE_FIELDS$ + '$LOWER_NAME$.public_id', + '$LOWER_NAME$.deleted_at', + '$LOWER_NAME$.created_at', + '$LOWER_NAME$.is_deleted', + '$LOWER_NAME$.user_id' + ); + + $this->applyFilters($query, '$LOWER_NAME$'); + + if ($userId) { + $query->where('clients.user_id', '=', $userId); + } + + /* + if ($filter) { + $query->where(); + } + */ + + return $query; + } + + public function save($data, $$LOWER_NAME$ = null) + { + $entity = $$LOWER_NAME$ ?: $STUDLY_NAME$::createNew(); + + $entity->fill($data); + $entity->save(); + + /* + if (!$publicId || $publicId == '-1') { + event(new ClientWasCreated($client)); + } else { + event(new ClientWasUpdated($client)); + } + */ + + return $entity; + } + +} diff --git a/app/Console/Commands/stubs/request.stub b/app/Console/Commands/stubs/request.stub new file mode 100755 index 0000000000000..4bf64c64eb896 --- /dev/null +++ b/app/Console/Commands/stubs/request.stub @@ -0,0 +1,10 @@ + 'auth', 'namespace' => '$MODULE_NAMESPACE$\$STUDLY_NAME$\Http\Controllers'], function() +{ + Route::resource('$LOWER_NAME$', '$STUDLY_NAME$Controller'); + Route::post('$LOWER_NAME$/bulk', '$STUDLY_NAME$Controller@bulk'); + Route::get('api/$LOWER_NAME$', '$STUDLY_NAME$Controller@datatable'); +}); + +Route::group(['middleware' => 'api', 'namespace' => '$MODULE_NAMESPACE$\$STUDLY_NAME$\Http\ApiControllers', 'prefix' => 'api/v1'], function() +{ + Route::resource('$LOWER_NAME$', '$STUDLY_NAME$ApiController'); +}); diff --git a/app/Console/Commands/stubs/scaffold/config.stub b/app/Console/Commands/stubs/scaffold/config.stub new file mode 100755 index 0000000000000..74c3001c9c1e9 --- /dev/null +++ b/app/Console/Commands/stubs/scaffold/config.stub @@ -0,0 +1,5 @@ + '$STUDLY_NAME$' +]; diff --git a/app/Console/Commands/stubs/scaffold/provider.stub b/app/Console/Commands/stubs/scaffold/provider.stub new file mode 100755 index 0000000000000..048eaddf70a63 --- /dev/null +++ b/app/Console/Commands/stubs/scaffold/provider.stub @@ -0,0 +1,110 @@ + \Modules\$STUDLY_NAME$\Policies\$STUDLY_NAME$Policy::class, + ]; + + /** + * Boot the application events. + * + * @return void + */ + public function boot(GateContract $gate) + { + parent::boot($gate); + + $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 []; + } +} diff --git a/app/Console/Commands/stubs/seeder.stub b/app/Console/Commands/stubs/seeder.stub new file mode 100755 index 0000000000000..dd4349080a871 --- /dev/null +++ b/app/Console/Commands/stubs/seeder.stub @@ -0,0 +1,21 @@ +call("OthersTableSeeder"); + } +} diff --git a/app/Console/Commands/stubs/start.stub b/app/Console/Commands/stubs/start.stub new file mode 100755 index 0000000000000..7be329cbe4652 --- /dev/null +++ b/app/Console/Commands/stubs/start.stub @@ -0,0 +1,15 @@ +getDefaults($$LOWER_NAME$), [ + $TRANSFORMER_FIELDS$ + 'id' => (int) $$LOWER_NAME$->public_id, + 'updated_at' => $this->getTimestamp($$LOWER_NAME$->updated_at), + 'archived_at' => $this->getTimestamp($$LOWER_NAME$->deleted_at), + ]); + } +} diff --git a/app/Console/Commands/stubs/updaterequest.stub b/app/Console/Commands/stubs/updaterequest.stub new file mode 100644 index 0000000000000..99bf461f00a6b --- /dev/null +++ b/app/Console/Commands/stubs/updaterequest.stub @@ -0,0 +1,28 @@ +user()->can('edit', $this->entity()); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + + ]; + } +} diff --git a/app/Console/Commands/stubs/views.stub b/app/Console/Commands/stubs/views.stub new file mode 100755 index 0000000000000..01c29a682920f --- /dev/null +++ b/app/Console/Commands/stubs/views.stub @@ -0,0 +1,57 @@ +@extends('header') + +@section('content') + + {!! Former::open($url) + ->addClass('col-md-10 col-md-offset-1 warn-on-exit') + ->method($method) + ->rules([]) !!} + + @if ($$LOWER_NAME$) + {!! Former::populate($$LOWER_NAME$) !!} +
+ @endif + +| t |
p,v=i.minHeight&&i.minHeight>f;i.grid=c,b&&(p+=l),v&&(f+=u),m&&(p-=l),g&&(f-=u),/^(se|s|e)$/.test(a)?(n.size.width=p,n.size.height=f):/^(ne)$/.test(a)?(n.size.width=p,n.size.height=f,n.position.top=s.top-d):/^(sw)$/.test(a)?(n.size.width=p,n.size.height=f,n.position.left=s.left-h):((f-u<=0||p-l<=0)&&(e=n._getPaddingPlusBorderDimensions(this)),f-u>0?(n.size.height=f,n.position.top=s.top-d):(f=u-e.height,n.size.height=f,n.position.top=s.top+r.height-f),p-l>0?(n.size.width=p,n.position.left=s.left-h):(p=u-e.height,n.size.width=p,n.position.left=s.left+r.width-p))}});t.ui.resizable,t.widget("ui.dialog",{version:"1.11.2",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"Close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(e){var n=t(this).css(e).offset().top;n<0&&t(this).css("top",e.top-n)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},sizeRelatedOptions:{buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},resizableRelatedOptions:{maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&t.fn.draggable&&this._makeDraggable(),this.options.resizable&&t.fn.resizable&&this._makeResizable(),this._isOpen=!1,this._trackFocus()},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var e=this.options.appendTo;return e&&(e.jquery||e.nodeType)?t(e):this.document.find(e||"body").eq(0)},_destroy:function(){var t,e=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),t=e.parent.children().eq(e.index),t.length&&t[0]!==this.element[0]?t.before(this.element):e.parent.append(this.element)},widget:function(){return this.uiDialog},disable:t.noop,enable:t.noop,close:function(e){var n,i=this;if(this._isOpen&&this._trigger("beforeClose",e)!==!1){if(this._isOpen=!1,this._focusedElement=null,this._destroyOverlay(),this._untrackInstance(),!this.opener.filter(":focusable").focus().length)try{n=this.document[0].activeElement,n&&"body"!==n.nodeName.toLowerCase()&&t(n).blur()}catch(o){}this._hide(this.uiDialog,this.options.hide,function(){i._trigger("close",e)})}},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(e,n){var i=!1,o=this.uiDialog.siblings(".ui-front:visible").map(function(){return+t(this).css("z-index")}).get(),r=Math.max.apply(null,o);return r>=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",r+1),i=!0),i&&!n&&this._trigger("focus",e),i},open:function(){var e=this;return this._isOpen?void(this._moveToTop()&&this._focusTabbable()):(this._isOpen=!0,this.opener=t(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css("z-index",this.uiDialog.css("z-index")-1),this._show(this.uiDialog,this.options.show,function(){e._focusTabbable(),e._trigger("focus")}),this._makeFocusTarget(),void this._trigger("open"))},_focusTabbable:function(){var t=this._focusedElement;t||(t=this.element.find("[autofocus]")),t.length||(t=this.element.find(":tabbable")),t.length||(t=this.uiDialogButtonPane.find(":tabbable")),t.length||(t=this.uiDialogTitlebarClose.filter(":tabbable")),t.length||(t=this.uiDialog),t.eq(0).focus()},_keepFocus:function(e){function n(){var e=this.document[0].activeElement,n=this.uiDialog[0]===e||t.contains(this.uiDialog[0],e);n||this._focusTabbable()}e.preventDefault(),n.call(this),this._delay(n)},_createWrapper:function(){this.uiDialog=t("
1&&M.splice.apply(M,[1,0].concat(M.splice(y,f+1))),s.dequeue()},t.effects.effect.clip=function(e,n){var i,o,r,s=t(this),a=["position","top","bottom","left","right","height","width"],c=t.effects.setMode(s,e.mode||"hide"),l="show"===c,u=e.direction||"vertical",h="vertical"===u,d=h?"height":"width",p=h?"top":"left",f={};t.effects.save(s,a),s.show(),i=t.effects.createWrapper(s).css({overflow:"hidden"}),o="IMG"===s[0].tagName?i:s,r=o[d](),l&&(o.css(d,0),o.css(p,r/2)),f[d]=l?r:0,f[p]=l?0:r/2,o.animate(f,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){l||s.hide(),t.effects.restore(s,a),t.effects.removeWrapper(s),n()}})},t.effects.effect.drop=function(e,n){var i,o=t(this),r=["position","top","bottom","left","right","opacity","height","width"],s=t.effects.setMode(o,e.mode||"hide"),a="show"===s,c=e.direction||"left",l="up"===c||"down"===c?"top":"left",u="up"===c||"left"===c?"pos":"neg",h={opacity:a?1:0};t.effects.save(o,r),o.show(),t.effects.createWrapper(o),i=e.distance||o["top"===l?"outerHeight":"outerWidth"](!0)/2,a&&o.css("opacity",0).css(l,"pos"===u?-i:i),h[l]=(a?"pos"===u?"+=":"-=":"pos"===u?"-=":"+=")+i,o.animate(h,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===s&&o.hide(),t.effects.restore(o,r),t.effects.removeWrapper(o),n()}})},t.effects.effect.explode=function(e,n){function i(){M.push(this),M.length===h*d&&o()}function o(){p.css({visibility:"visible"}),t(M).remove(),m||p.hide(),n()}var r,s,a,c,l,u,h=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=h,p=t(this),f=t.effects.setMode(p,e.mode||"hide"),m="show"===f,g=p.show().css("visibility","hidden").offset(),b=Math.ceil(p.outerWidth()/d),v=Math.ceil(p.outerHeight()/h),M=[];for(r=0;r
t<"F"ip>'),x.renderer?i.isPlainObject(x.renderer)&&!x.renderer.header&&(x.renderer.header="jqueryui"):x.renderer="jqueryui"):i.extend(C,Yt.ext.classes,m.oClasses),i(this).addClass(C.sTable),""===x.oScroll.sX&&""===x.oScroll.sY||(x.oScroll.iBarWidth=Tt()),x.oScroll.sX===!0&&(x.oScroll.sX="100%"),x.iInitDisplayStart===n&&(x.iInitDisplayStart=m.iDisplayStart,x._iDisplayStart=m.iDisplayStart),null!==m.iDeferLoading){x.bDeferLoading=!0;var S=i.isArray(m.iDeferLoading);x._iRecordsDisplay=S?m.iDeferLoading[0]:m.iDeferLoading,x._iRecordsTotal=S?m.iDeferLoading[1]:m.iDeferLoading}var O=x.oLanguage;i.extend(!0,O,m.oLanguage),""!==O.sUrl&&(i.ajax({dataType:"json",url:O.sUrl,success:function(t){s(t),r(w.oLanguage,t),i.extend(!0,O,t),at(x)},error:function(){at(x)}}),v=!0),null===m.asStripeClasses&&(x.asStripeClasses=[C.sStripeOdd,C.sStripeEven]);var N=x.asStripeClasses,L=i("tbody tr:eq(0)",this);i.inArray(!0,i.map(N,function(t,e){return L.hasClass(t)}))!==-1&&(i("tbody tr",this).removeClass(N.join(" ")),x.asDestroyStripes=N.slice());var k,q=[],W=this.getElementsByTagName("thead");if(0!==W.length&&(X(x.aoHeader,W[0]),q=F(x)),null===m.aoColumns)for(k=[],g=0,p=q.length;g
").appendTo(this)),x.nTHead=R[0];var H=i(this).children("tbody");0===H.length&&(H=i("
").appendTo(this)),x.nTBody=H[0];var j=i(this).children("tfoot");if(0===j.length&&P.length>0&&(""!==x.oScroll.sX||""!==x.oScroll.sY)&&(j=i("").appendTo(this)),0===j.length||0===j.children().length?i(this).addClass(C.sNoFooter):j.length>0&&(x.nTFoot=j[0],X(x.aoFooter,x.nTFoot)),m.aaData)for(g=0;g