¨4.0.1¨
This commit is contained in:
@@ -25,14 +25,15 @@ class ScaffoldEntityCommand extends Command
|
||||
/**
|
||||
* The instance of EntityGenerator.
|
||||
*
|
||||
* @var \FleetCart\Scaffold\Module\Generators\EntityGenerator
|
||||
* @var EntityGenerator
|
||||
*/
|
||||
private $entityGenerator;
|
||||
private EntityGenerator $entityGenerator;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @param \FleetCart\Scaffold\Module\Generators\EntityGenerator $entityGenerator
|
||||
* @param EntityGenerator $entityGenerator
|
||||
*/
|
||||
public function __construct(EntityGenerator $entityGenerator)
|
||||
{
|
||||
@@ -41,12 +42,13 @@ class ScaffoldEntityCommand extends Command
|
||||
$this->entityGenerator = $entityGenerator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): void
|
||||
{
|
||||
$this->entityGenerator
|
||||
->module($this->argument('module'))
|
||||
@@ -55,12 +57,13 @@ class ScaffoldEntityCommand extends Command
|
||||
$this->info('Entity generated.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the console command arguments.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getArguments()
|
||||
protected function getArguments(): array
|
||||
{
|
||||
return [
|
||||
['entity', InputArgument::REQUIRED, 'The name of the entity.'],
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace FleetCart\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use FleetCart\Scaffold\Module\ModuleScaffold;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
|
||||
class ScaffoldModuleCommand extends Command
|
||||
{
|
||||
@@ -24,14 +25,15 @@ class ScaffoldModuleCommand extends Command
|
||||
/**
|
||||
* The instance of ModuleScaffold.
|
||||
*
|
||||
* @var \FleetCart\Scaffold\Module\ModuleScaffold
|
||||
* @var ModuleScaffold
|
||||
*/
|
||||
private $scaffolder;
|
||||
private ModuleScaffold $scaffolder;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @param \FleetCart\Scaffold\Module\ModuleScaffold $scaffolder
|
||||
* @param ModuleScaffold $scaffolder
|
||||
*/
|
||||
public function __construct(ModuleScaffold $scaffolder)
|
||||
{
|
||||
@@ -40,12 +42,14 @@ class ScaffoldModuleCommand extends Command
|
||||
$this->scaffolder = $scaffolder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): void
|
||||
{
|
||||
$module = $this->askModuleName();
|
||||
$entities = $this->askEntities();
|
||||
@@ -55,49 +59,68 @@ class ScaffoldModuleCommand extends Command
|
||||
$this->info('Module has been generated.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ask for module name.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function askModuleName()
|
||||
private function askModuleName(): array
|
||||
{
|
||||
do {
|
||||
$moduleName = $this->ask('Please enter the module name in the following format: vendor/name');
|
||||
do {
|
||||
$moduleName = $this->ask('Please enter the module name in the following format: vendor/name');
|
||||
} while (!$this->moduleNameIsValid($moduleName));
|
||||
|
||||
list($vendor, $name) = $this->extractModuleName($moduleName);
|
||||
[$vendor, $name] = $this->extractModuleName($moduleName);
|
||||
} while ($this->moduleExists($name));
|
||||
|
||||
return compact('vendor', 'name');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate the given module name.
|
||||
*
|
||||
* @param string $moduleName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function moduleNameIsValid(string $moduleName): bool
|
||||
{
|
||||
$name = explode('/', $moduleName);
|
||||
|
||||
if (count($name) !== 2) {
|
||||
$this->error('Module name must be in the following format: vendor/name');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract the given module name.
|
||||
*
|
||||
* @param string $moduleName
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function extractModuleName($moduleName)
|
||||
private function extractModuleName(string $moduleName): array
|
||||
{
|
||||
do {
|
||||
$name = explode('/', $moduleName);
|
||||
|
||||
if (count($name) !== 2) {
|
||||
$this->error('Module name must be in the following format: vendor/name');
|
||||
|
||||
$moduleName = $this->ask('Please enter the module name in the following format: vendor/name');
|
||||
}
|
||||
} while (count($name) !== 2);
|
||||
$name = explode('/', $moduleName);
|
||||
|
||||
return [$name[0], ucfirst(camel_case($name[1]))];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the given module is exists.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
private function moduleExists($name)
|
||||
private function moduleExists($name): bool
|
||||
{
|
||||
if (is_dir(config('modules.paths.modules') . "/{$name}")) {
|
||||
$this->error("The module [$name] is already exists.");
|
||||
@@ -108,17 +131,18 @@ class ScaffoldModuleCommand extends Command
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ask for entities.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function askEntities()
|
||||
private function askEntities(): array
|
||||
{
|
||||
$entities = [];
|
||||
|
||||
do {
|
||||
$entity = $this->ask('Enter entity name. Leaving option empty will continue script', false);
|
||||
$entity = $this->ask('Enter entity name. To Continue Press Enter .', false);
|
||||
|
||||
if ($entity !== '') {
|
||||
$entities[] = ucfirst($entity);
|
||||
|
||||
@@ -17,13 +17,15 @@ class Kernel extends ConsoleKernel
|
||||
Commands\ScaffoldEntityCommand::class,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
* @param Schedule $schedule
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
protected function schedule(Schedule $schedule): void
|
||||
{
|
||||
// $schedule->command('inspire')
|
||||
// ->hourly();
|
||||
|
||||
@@ -5,8 +5,12 @@ namespace FleetCart\Exceptions;
|
||||
use Throwable;
|
||||
use Illuminate\Http\Request;
|
||||
use Swift_TransportException;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Modules\Sms\Exceptions\SmsException;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Modules\Checkout\Http\Exceptions\CheckoutException;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
@@ -32,62 +36,60 @@ class Handler extends ExceptionHandler
|
||||
'password_confirmation',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Report or log an exception.
|
||||
*
|
||||
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @param Throwable $e
|
||||
*
|
||||
* @return void
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function report(Throwable $e)
|
||||
public function report(Throwable $e): void
|
||||
{
|
||||
parent::report($e);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render an exception into an HTTP response.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Throwable $e
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param Request $request
|
||||
* @param Throwable $e
|
||||
*
|
||||
* @return Response|JsonResponse|RedirectResponse
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function render($request, Throwable $e)
|
||||
{
|
||||
if ($e instanceof Swift_TransportException) {
|
||||
return $this->handleSwiftException($request, $e);
|
||||
}
|
||||
|
||||
if ($e instanceof SmsException) {
|
||||
return $this->handleSmsException($request, $e);
|
||||
}
|
||||
|
||||
if ($e instanceof ValidationException && $request->ajax()) {
|
||||
return response()->json([
|
||||
return match (true) {
|
||||
$e instanceof Swift_TransportException => $this->handleSwiftException($request, $e),
|
||||
$e instanceof SmsException => $this->handleSmsException($request, $e),
|
||||
$e instanceof ValidationException && $request->ajax() => response()->json([
|
||||
'message' => trans('core::messages.the_given_data_was_invalid'),
|
||||
'errors' => $e->validator->getMessageBag(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
if ($this->shouldRedirectToAdminDashboard($e)) {
|
||||
return redirect()->route('admin.dashboard.index');
|
||||
}
|
||||
|
||||
if ($this->shouldShowNotFoundPage($e)) {
|
||||
return response()->view('errors.404');
|
||||
}
|
||||
|
||||
return parent::render($request, $e);
|
||||
], 422),
|
||||
$e instanceof CheckoutException => response()->json([
|
||||
'message' => $e->getMessage(),
|
||||
], Response::HTTP_FORBIDDEN),
|
||||
$this->shouldRedirectToAdminDashboard($e) => redirect()->route('admin.dashboard.index'),
|
||||
$this->shouldShowNotFoundPage($e) => response()->view('errors.404'),
|
||||
default => parent::render($request, $e),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle swift transport exception.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Swift_TransportException $e
|
||||
* @param Request $request
|
||||
* @param Swift_TransportException $e
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Swift_TransportException
|
||||
* @throws Swift_TransportException
|
||||
*/
|
||||
private function handleSwiftException(Request $request, Swift_TransportException $e)
|
||||
{
|
||||
@@ -103,14 +105,16 @@ class Handler extends ExceptionHandler
|
||||
->with('error', trans('core::messages.mail_is_not_configured'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle sms exception.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Modules\Sms\Exceptions\SmsException $e
|
||||
* @return mixed
|
||||
* @param Request $request
|
||||
* @param SmsException $e
|
||||
*
|
||||
* @throws \Modules\Sms\Exceptions\SmsException
|
||||
* @return RedirectResponse
|
||||
*
|
||||
* @throws SmsException
|
||||
*/
|
||||
private function handleSmsException(Request $request, SmsException $e)
|
||||
{
|
||||
@@ -125,28 +129,43 @@ class Handler extends ExceptionHandler
|
||||
return back()->withInput()->with('error', $e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether response should redirect to the admin dashboard.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @param Throwable $e
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldRedirectToAdminDashboard(Throwable $e)
|
||||
private function shouldRedirectToAdminDashboard(Throwable $e): bool
|
||||
{
|
||||
if (config('app.debug') || ! $this->inAdminPanel()) {
|
||||
if (config('app.debug') || !$this->inAdminPanel()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $e instanceof NotFoundHttpException || $e instanceof ModelNotFoundException;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the request is from admin panel.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function inAdminPanel(): bool
|
||||
{
|
||||
return $this->container->has('inAdminPanel') && $this->container['inAdminPanel'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the response should show not found page.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @param Throwable $e
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldShowNotFoundPage(Throwable $e)
|
||||
private function shouldShowNotFoundPage(Throwable $e): bool
|
||||
{
|
||||
if ($this->inAdminPanel()) {
|
||||
return false;
|
||||
@@ -154,14 +173,4 @@ class Handler extends ExceptionHandler
|
||||
|
||||
return $e instanceof NotFoundHttpException || $e instanceof ModelNotFoundException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request is from admin panel.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function inAdminPanel()
|
||||
{
|
||||
return $this->container->has('inAdminPanel') && $this->container['inAdminPanel'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,20 +3,22 @@
|
||||
namespace FleetCart\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use FleetCart\License;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
class InvalidLicenseException extends Exception
|
||||
{
|
||||
protected $message;
|
||||
|
||||
|
||||
public function __construct($message)
|
||||
{
|
||||
$this->message = $message;
|
||||
parent::__construct();
|
||||
|
||||
resolve(License::class)->deleteLicenseFile();
|
||||
$this->message = $message;
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
||||
public function render(): RedirectResponse
|
||||
{
|
||||
return redirect()->route('license.create')
|
||||
->with('error', $this->message);
|
||||
|
||||
@@ -9,10 +9,10 @@ class FleetCart
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '3.1.0';
|
||||
const VERSION = '4.0.1';
|
||||
|
||||
/**
|
||||
* The envato item ID.
|
||||
* The Envato item ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
||||
@@ -5,12 +5,20 @@ namespace FleetCart\Http\Controllers;
|
||||
use Exception;
|
||||
use FleetCart\Install\App;
|
||||
use FleetCart\Install\Store;
|
||||
use Illuminate\Http\Response;
|
||||
use FleetCart\Install\Database;
|
||||
use FleetCart\Install\Permission;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use FleetCart\Install\Requirement;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use FleetCart\Install\AdminAccount;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use FleetCart\Http\Requests\InstallRequest;
|
||||
use Jackiedo\DotenvEditor\Facades\DotenvEditor;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use FleetCart\Http\Middleware\RedirectIfInstalled;
|
||||
|
||||
class InstallController extends Controller
|
||||
@@ -20,50 +28,56 @@ class InstallController extends Controller
|
||||
$this->middleware(RedirectIfInstalled::class);
|
||||
}
|
||||
|
||||
public function preInstallation(Requirement $requirement)
|
||||
|
||||
public function installation(Requirement $requirement, Permission $permission): Factory|View|Application
|
||||
{
|
||||
return view('install.pre_installation', compact('requirement'));
|
||||
return view('install.install', compact('requirement', 'permission'));
|
||||
}
|
||||
|
||||
public function getConfiguration(Requirement $requirement)
|
||||
{
|
||||
if (! $requirement->satisfied()) {
|
||||
return redirect()->route('install.pre_installation');
|
||||
}
|
||||
|
||||
return view('install.configuration', compact('requirement'));
|
||||
}
|
||||
|
||||
public function postConfiguration(
|
||||
public function install(
|
||||
InstallRequest $request,
|
||||
Database $database,
|
||||
AdminAccount $admin,
|
||||
Store $store,
|
||||
App $app
|
||||
) {
|
||||
Database $database,
|
||||
AdminAccount $admin,
|
||||
Store $store,
|
||||
App $app
|
||||
): JsonResponse
|
||||
{
|
||||
@set_time_limit(0);
|
||||
|
||||
try {
|
||||
$database->setup($request->db);
|
||||
$admin->setup($request->admin);
|
||||
$store->setup($request->store);
|
||||
Artisan::call('optimize:clear');
|
||||
|
||||
$database->setup($request);
|
||||
$admin->setup($request);
|
||||
$store->setup($request);
|
||||
$app->setup();
|
||||
|
||||
DotenvEditor::setKey('APP_INSTALLED', 'true')->save();
|
||||
|
||||
Artisan::call('key:generate', ['--force' => true]);
|
||||
|
||||
$success = true;
|
||||
$message = "Congratulations! FleetCart installed successfully";
|
||||
} catch (Exception $e) {
|
||||
return back()->withInput()
|
||||
->with('error', $e->getMessage());
|
||||
$success = false;
|
||||
$message = $e->getMessage();
|
||||
|
||||
try {
|
||||
if (Schema::hasTable('migrations')) {
|
||||
Artisan::call('migrate:rollback', ['--force' => true]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$message .= '<br><br>' . $e->getMessage();
|
||||
}
|
||||
} finally {
|
||||
return response()->json(
|
||||
[
|
||||
'success' => $success,
|
||||
'message' => $message,
|
||||
],
|
||||
$success ? Response::HTTP_OK : Response::HTTP_INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
return redirect('install/complete');
|
||||
}
|
||||
|
||||
public function complete()
|
||||
{
|
||||
if (config('app.installed')) {
|
||||
return redirect()->route('home');
|
||||
}
|
||||
|
||||
DotenvEditor::setKey('APP_INSTALLED', 'true')->save();
|
||||
|
||||
return view('install.complete');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ namespace FleetCart\Http\Controllers;
|
||||
|
||||
use FleetCart\License;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use FleetCart\Http\Middleware\RedirectIfShouldNotCreateLicense;
|
||||
|
||||
class LicenseController extends Controller
|
||||
@@ -13,18 +17,23 @@ class LicenseController extends Controller
|
||||
$this->middleware(RedirectIfShouldNotCreateLicense::class);
|
||||
}
|
||||
|
||||
public function create()
|
||||
|
||||
public function create(): Factory|View|Application
|
||||
{
|
||||
return view('license.create');
|
||||
}
|
||||
|
||||
public function store(License $license)
|
||||
|
||||
public function store(License $license): RedirectResponse
|
||||
{
|
||||
request()->validate([
|
||||
'purchase_code' => 'required',
|
||||
], [
|
||||
'required' => 'The purchase code field is required.',
|
||||
]);
|
||||
request()->validate(
|
||||
[
|
||||
'purchase_code' => 'required',
|
||||
],
|
||||
[
|
||||
'required' => 'The purchase code field is required.',
|
||||
]
|
||||
);
|
||||
|
||||
$license->activate(request('purchase_code'));
|
||||
|
||||
|
||||
@@ -2,7 +2,26 @@
|
||||
|
||||
namespace FleetCart\Http;
|
||||
|
||||
use FleetCart\Http\Middleware\RunUpdater;
|
||||
use FleetCart\Http\Middleware\TrimStrings;
|
||||
use FleetCart\Http\Middleware\TrustProxies;
|
||||
use FleetCart\Http\Middleware\EncryptCookies;
|
||||
use FleetCart\Http\Middleware\VerifyCsrfToken;
|
||||
use Illuminate\Auth\Middleware\RequirePassword;
|
||||
use Illuminate\Http\Middleware\SetCacheHeaders;
|
||||
use Illuminate\Session\Middleware\StartSession;
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Routing\Middleware\ValidateSignature;
|
||||
use FleetCart\Http\Middleware\ConvertStringBooleans;
|
||||
use Illuminate\Auth\Middleware\EnsureEmailIsVerified;
|
||||
use Illuminate\Routing\Middleware\SubstituteBindings;
|
||||
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||
use FleetCart\Http\Middleware\CheckForMaintenanceMode;
|
||||
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
|
||||
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||
use FleetCart\Http\Middleware\RedirectToInstallerIfNotInstalled;
|
||||
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
|
||||
|
||||
class Kernel extends HttpKernel
|
||||
{
|
||||
@@ -14,16 +33,16 @@ class Kernel extends HttpKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [
|
||||
\FleetCart\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\FleetCart\Http\Middleware\CheckForMaintenanceMode::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
\FleetCart\Http\Middleware\TrimStrings::class,
|
||||
\FleetCart\Http\Middleware\ConvertStringBooleans::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
\FleetCart\Http\Middleware\TrustProxies::class,
|
||||
\FleetCart\Http\Middleware\RedirectToInstallerIfNotInstalled::class,
|
||||
\FleetCart\Http\Middleware\RunUpdater::class,
|
||||
EncryptCookies::class,
|
||||
StartSession::class,
|
||||
CheckForMaintenanceMode::class,
|
||||
ValidatePostSize::class,
|
||||
TrimStrings::class,
|
||||
ConvertStringBooleans::class,
|
||||
ConvertEmptyStringsToNull::class,
|
||||
TrustProxies::class,
|
||||
RedirectToInstallerIfNotInstalled::class,
|
||||
RunUpdater::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -33,10 +52,10 @@ class Kernel extends HttpKernel
|
||||
*/
|
||||
protected $middlewareGroups = [
|
||||
'web' => [
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\FleetCart\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
ShareErrorsFromSession::class,
|
||||
VerifyCsrfToken::class,
|
||||
SubstituteBindings::class,
|
||||
],
|
||||
'api' => [
|
||||
'throttle:60,1',
|
||||
@@ -52,11 +71,11 @@ class Kernel extends HttpKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $routeMiddleware = [
|
||||
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'bindings' => SubstituteBindings::class,
|
||||
'cache.headers' => SetCacheHeaders::class,
|
||||
'password.confirm' => RequirePassword::class,
|
||||
'signed' => ValidateSignature::class,
|
||||
'throttle' => ThrottleRequests::class,
|
||||
'verified' => EnsureEmailIsVerified::class,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
namespace FleetCart\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Illuminate\Foundation\Http\Exceptions\MaintenanceModeException;
|
||||
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as BaseCheckForMaintenanceMode;
|
||||
|
||||
class CheckForMaintenanceMode extends BaseCheckForMaintenanceMode
|
||||
@@ -16,17 +19,19 @@ class CheckForMaintenanceMode extends BaseCheckForMaintenanceMode
|
||||
'*/admin*',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
|
||||
* @throws \Illuminate\Foundation\Http\Exceptions\MaintenanceModeException
|
||||
* @throws HttpException
|
||||
* @throws MaintenanceModeException
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle($request, Closure $next): mixed
|
||||
{
|
||||
if (
|
||||
config('app.installed')
|
||||
|
||||
@@ -9,11 +9,12 @@ class ConvertStringBooleans extends TransformsRequest
|
||||
/**
|
||||
* Transform the given value.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param $key
|
||||
* @param $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function transform($key, $value)
|
||||
protected function transform($key, $value): mixed
|
||||
{
|
||||
if ($value === 'true' || $value === 'TRUE') {
|
||||
return true;
|
||||
|
||||
29
app/Http/Middleware/LicenseChecker.php
Normal file
29
app/Http/Middleware/LicenseChecker.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace FleetCart\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use FleetCart\License;
|
||||
|
||||
class LicenseChecker
|
||||
{
|
||||
private $license;
|
||||
|
||||
|
||||
public function __construct(License $license)
|
||||
{
|
||||
$this->license = $license;
|
||||
}
|
||||
|
||||
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if ($this->license->shouldRecheck()) {
|
||||
$this->license->recheck();
|
||||
} else if ($this->license->shouldCreateLicense()) {
|
||||
return redirect()->route('license.create');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,19 @@
|
||||
namespace FleetCart\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class RedirectIfInstalled
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle($request, Closure $next): mixed
|
||||
{
|
||||
if (config('app.installed')) {
|
||||
return redirect()->route('home');
|
||||
|
||||
@@ -4,26 +4,30 @@ namespace FleetCart\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use FleetCart\License;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class RedirectIfShouldNotCreateLicense
|
||||
{
|
||||
private $license;
|
||||
|
||||
|
||||
public function __construct(License $license)
|
||||
{
|
||||
$this->license = $license;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle($request, Closure $next): mixed
|
||||
{
|
||||
if ($this->license->valid() || ! $this->license->shouldCreateLicense()) {
|
||||
if ($this->license->valid() || !$this->license->shouldCreateLicense()) {
|
||||
return redirect()->intended('/admin');
|
||||
}
|
||||
|
||||
|
||||
@@ -3,20 +3,22 @@
|
||||
namespace FleetCart\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class RedirectToInstallerIfNotInstalled
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle($request, Closure $next): mixed
|
||||
{
|
||||
if (! config('app.installed') && ! $request->is('install/*')) {
|
||||
return redirect()->route('install.pre_installation');
|
||||
if (!config('app.installed') && !$request->is('install')) {
|
||||
return redirect()->route('install.show');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
||||
@@ -4,17 +4,19 @@ namespace FleetCart\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use FleetCart\Updater;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class RunUpdater
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next): mixed
|
||||
{
|
||||
if (config('app.installed') && file_exists(storage_path('app/update'))) {
|
||||
Updater::run();
|
||||
|
||||
@@ -12,66 +12,68 @@ class InstallRequest extends Request
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'db.host' => 'required',
|
||||
'db.port' => 'required',
|
||||
'db.username' => 'required',
|
||||
'db.password' => 'nullable',
|
||||
'db.database' => 'required',
|
||||
'admin.first_name' => 'required',
|
||||
'admin.last_name' => 'required',
|
||||
'admin.email' => 'required|email',
|
||||
'admin.phone' => 'required',
|
||||
'admin.password' => 'required|confirmed|min:6',
|
||||
'store.store_name' => 'required',
|
||||
'store.store_email' => 'required|email',
|
||||
'store.store_phone' => 'required',
|
||||
'store.search_engine' => ['required', Rule::in(['mysql', 'algolia', 'meilisearch'])],
|
||||
'store.algolia_app_id' => 'required_if:store.search_engine,algolia',
|
||||
'store.algolia_secret' => 'required_if:store.search_engine,algolia',
|
||||
'store.meilisearch_host' => 'required_if:store.search_engine,meilisearch',
|
||||
'store.meilisearch_key' => 'required_if:store.search_engine,meilisearch',
|
||||
'db_host' => 'required',
|
||||
'db_port' => 'required',
|
||||
'db_username' => 'required',
|
||||
'db_password' => 'nullable',
|
||||
'db_database' => 'required',
|
||||
'admin_first_name' => 'required',
|
||||
'admin_last_name' => 'required',
|
||||
'admin_email' => 'required|email',
|
||||
'admin_phone' => 'required',
|
||||
'admin_password' => 'required|confirmed|min:6',
|
||||
'store_name' => 'required',
|
||||
'store_email' => 'required|email',
|
||||
'store_phone' => 'required',
|
||||
'store_search_engine' => ['required', Rule::in(['mysql', 'algolia', 'meilisearch'])],
|
||||
'algolia_app_id' => 'required_if:store_search_engine,algolia',
|
||||
'algolia_secret' => 'required_if:store_search_engine,algolia',
|
||||
'meilisearch_host' => 'required_if:store_search_engine,meilisearch',
|
||||
'meilisearch_key' => 'required_if:store_search_engine,meilisearch',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes()
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'db.host' => 'host',
|
||||
'db.port' => 'port',
|
||||
'db.username' => 'username',
|
||||
'db.password' => 'password',
|
||||
'db.database' => 'datbase',
|
||||
'admin.first_name' => 'first name',
|
||||
'admin.last_name' => 'last name',
|
||||
'admin.email' => 'email',
|
||||
'admin.phone' => 'phone',
|
||||
'admin.password' => 'password',
|
||||
'store.store_name' => 'store name',
|
||||
'store.store_email' => 'store email',
|
||||
'store.store_phone' => 'store phone',
|
||||
'store.search_engine' => 'search engine',
|
||||
'store.algolia_app_id' => 'algolia application id',
|
||||
'store.algolia_secret' => 'algolia admin api key',
|
||||
'store.meilisearch_host' => 'meilisearch host',
|
||||
'store.meilisearch_key' => 'meilisearch key',
|
||||
'db_host' => 'host',
|
||||
'db_port' => 'port',
|
||||
'db_username' => 'username',
|
||||
'db_password' => 'password',
|
||||
'db_database' => 'datbase',
|
||||
'admin_first_name' => 'first name',
|
||||
'admin_last_name' => 'last name',
|
||||
'admin_email' => 'email',
|
||||
'admin_phone' => 'phone',
|
||||
'admin_password' => 'password',
|
||||
'store_name' => 'store name',
|
||||
'store_email' => 'store email',
|
||||
'store_phone' => 'store phone',
|
||||
'store_search_engine' => 'search engine',
|
||||
'algolia_app_id' => 'algolia application id',
|
||||
'algolia_secret' => 'algolia admin api key',
|
||||
'meilisearch_host' => 'meilisearch host',
|
||||
'meilisearch_key' => 'meilisearch key',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,99 +8,124 @@ use Cartalyst\Sentinel\Laravel\Facades\Activation;
|
||||
|
||||
class AdminAccount
|
||||
{
|
||||
public function setup($data)
|
||||
public function setup($request): void
|
||||
{
|
||||
$role = Role::create(['name' => 'Admin', 'permissions' => $this->getAdminRolePermissions()]);
|
||||
$adminUser = $this->createAdminUser($request);
|
||||
$this->activateAdminUser($adminUser);
|
||||
|
||||
$admin = User::create([
|
||||
'first_name' => $data['first_name'],
|
||||
'last_name' => $data['last_name'],
|
||||
'email' => $data['email'],
|
||||
'phone' => $data['phone'],
|
||||
'password' => bcrypt($data['password']),
|
||||
]);
|
||||
|
||||
$activation = Activation::create($admin);
|
||||
Activation::complete($admin, $activation->code);
|
||||
|
||||
$admin->roles()->attach($role);
|
||||
$adminRole = $this->createAdminRole();
|
||||
$adminUser->roles()->attach($adminRole);
|
||||
}
|
||||
|
||||
private function getAdminRolePermissions()
|
||||
|
||||
private function createAdminUser($request)
|
||||
{
|
||||
return User::create([
|
||||
'first_name' => $request['admin_first_name'],
|
||||
'last_name' => $request['admin_last_name'],
|
||||
'email' => $request['admin_email'],
|
||||
'phone' => $request['admin_phone'],
|
||||
'password' => bcrypt($request['admin_password']),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
private function activateAdminUser($adminUser): void
|
||||
{
|
||||
$activation = Activation::create($adminUser);
|
||||
Activation::complete($adminUser, $activation->code);
|
||||
}
|
||||
|
||||
|
||||
private function createAdminRole()
|
||||
{
|
||||
return Role::create([
|
||||
'name' => 'Admin',
|
||||
'permissions' => $this->getAdminRolePermissions(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
private function getAdminRolePermissions(): array
|
||||
{
|
||||
return [
|
||||
// users
|
||||
# users
|
||||
'admin.users.index' => true,
|
||||
'admin.users.create' => true,
|
||||
'admin.users.edit' => true,
|
||||
'admin.users.destroy' => true,
|
||||
// roles
|
||||
# roles
|
||||
'admin.roles.index' => true,
|
||||
'admin.roles.create' => true,
|
||||
'admin.roles.edit' => true,
|
||||
'admin.roles.destroy' => true,
|
||||
// products
|
||||
# products
|
||||
'admin.products.index' => true,
|
||||
'admin.products.create' => true,
|
||||
'admin.products.edit' => true,
|
||||
'admin.products.destroy' => true,
|
||||
// brands
|
||||
# brands
|
||||
'admin.brands.index' => true,
|
||||
'admin.brands.create' => true,
|
||||
'admin.brands.edit' => true,
|
||||
'admin.brands.destroy' => true,
|
||||
// attributes
|
||||
# attributes
|
||||
'admin.attributes.index' => true,
|
||||
'admin.attributes.create' => true,
|
||||
'admin.attributes.edit' => true,
|
||||
'admin.attributes.destroy' => true,
|
||||
// attribute sets
|
||||
# attribute sets
|
||||
'admin.attribute_sets.index' => true,
|
||||
'admin.attribute_sets.create' => true,
|
||||
'admin.attribute_sets.edit' => true,
|
||||
'admin.attribute_sets.destroy' => true,
|
||||
// options
|
||||
#variations
|
||||
'admin.variations.index' => true,
|
||||
'admin.variations.create' => true,
|
||||
'admin.variations.edit' => true,
|
||||
'admin.variations.destroy' => true,
|
||||
# options
|
||||
'admin.options.index' => true,
|
||||
'admin.options.create' => true,
|
||||
'admin.options.edit' => true,
|
||||
'admin.options.destroy' => true,
|
||||
// filters
|
||||
# filters
|
||||
'admin.filters.index' => true,
|
||||
'admin.filters.create' => true,
|
||||
'admin.filters.edit' => true,
|
||||
'admin.filters.destroy' => true,
|
||||
// reviews
|
||||
# reviews
|
||||
'admin.reviews.index' => true,
|
||||
'admin.reviews.create' => true,
|
||||
'admin.reviews.edit' => true,
|
||||
'admin.reviews.destroy' => true,
|
||||
// categories
|
||||
# categories
|
||||
'admin.categories.index' => true,
|
||||
'admin.categories.create' => true,
|
||||
'admin.categories.edit' => true,
|
||||
'admin.categories.destroy' => true,
|
||||
// tags
|
||||
# tags
|
||||
'admin.tags.index' => true,
|
||||
'admin.tags.create' => true,
|
||||
'admin.tags.edit' => true,
|
||||
'admin.tags.destroy' => true,
|
||||
// orders
|
||||
# orders
|
||||
'admin.orders.index' => true,
|
||||
'admin.orders.show' => true,
|
||||
'admin.orders.edit' => true,
|
||||
// flash sales
|
||||
# flash sales
|
||||
'admin.flash_sales.index' => true,
|
||||
'admin.flash_sales.create' => true,
|
||||
'admin.flash_sales.edit' => true,
|
||||
'admin.flash_sales.destroy' => true,
|
||||
// transactions
|
||||
# transactions
|
||||
'admin.transactions.index' => true,
|
||||
// coupons
|
||||
# coupons
|
||||
'admin.coupons.index' => true,
|
||||
'admin.coupons.create' => true,
|
||||
'admin.coupons.edit' => true,
|
||||
'admin.coupons.destroy' => true,
|
||||
// menus
|
||||
# menus
|
||||
'admin.menus.index' => true,
|
||||
'admin.menus.create' => true,
|
||||
'admin.menus.edit' => true,
|
||||
@@ -109,39 +134,39 @@ class AdminAccount
|
||||
'admin.menu_items.create' => true,
|
||||
'admin.menu_items.edit' => true,
|
||||
'admin.menu_items.destroy' => true,
|
||||
// Media
|
||||
# Media
|
||||
'admin.media.index' => true,
|
||||
'admin.media.create' => true,
|
||||
'admin.media.destroy' => true,
|
||||
// pages
|
||||
# pages
|
||||
'admin.pages.index' => true,
|
||||
'admin.pages.create' => true,
|
||||
'admin.pages.edit' => true,
|
||||
'admin.pages.destroy' => true,
|
||||
// currency rates
|
||||
# currency rates
|
||||
'admin.currency_rates.index' => true,
|
||||
'admin.currency_rates.edit' => true,
|
||||
// tax
|
||||
# tax
|
||||
'admin.taxes.index' => true,
|
||||
'admin.taxes.create' => true,
|
||||
'admin.taxes.edit' => true,
|
||||
'admin.taxes.destroy' => true,
|
||||
// translations
|
||||
# translations
|
||||
'admin.translations.index' => true,
|
||||
'admin.translations.edit' => true,
|
||||
// appearance
|
||||
# appearance
|
||||
'admin.sliders.index' => true,
|
||||
'admin.sliders.create' => true,
|
||||
'admin.sliders.edit' => true,
|
||||
'admin.sliders.destroy' => true,
|
||||
// import
|
||||
# import
|
||||
'admin.importer.index' => true,
|
||||
'admin.importer.create' => true,
|
||||
// reports
|
||||
# reports
|
||||
'admin.reports.index' => true,
|
||||
// settings
|
||||
# settings
|
||||
'admin.settings.edit' => true,
|
||||
// storefront
|
||||
# storefront
|
||||
'admin.storefront.edit' => true,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -4,15 +4,13 @@ namespace FleetCart\Install;
|
||||
|
||||
use Modules\User\Entities\Role;
|
||||
use Modules\Setting\Entities\Setting;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Modules\Currency\Entities\CurrencyRate;
|
||||
use Jackiedo\DotenvEditor\Facades\DotenvEditor;
|
||||
|
||||
class App
|
||||
{
|
||||
public function setup()
|
||||
public function setup(): void
|
||||
{
|
||||
$this->generateAppKey();
|
||||
$this->setEnvVariables();
|
||||
$this->createCustomerRole();
|
||||
$this->setAppSettings();
|
||||
@@ -20,12 +18,8 @@ class App
|
||||
$this->createStorageFolder();
|
||||
}
|
||||
|
||||
private function generateAppKey()
|
||||
{
|
||||
Artisan::call('key:generate', ['--force' => true]);
|
||||
}
|
||||
|
||||
private function setEnvVariables()
|
||||
private function setEnvVariables(): void
|
||||
{
|
||||
$env = DotenvEditor::load();
|
||||
|
||||
@@ -37,12 +31,14 @@ class App
|
||||
$env->save();
|
||||
}
|
||||
|
||||
private function createCustomerRole()
|
||||
|
||||
private function createCustomerRole(): void
|
||||
{
|
||||
Role::create(['name' => 'Customer']);
|
||||
}
|
||||
|
||||
private function setAppSettings()
|
||||
|
||||
private function setAppSettings(): void
|
||||
{
|
||||
Setting::setMany([
|
||||
'active_theme' => 'Storefront',
|
||||
@@ -58,7 +54,6 @@ class App
|
||||
'supported_currencies' => ['USD'],
|
||||
'default_currency' => 'USD',
|
||||
'send_order_invoice_email' => false,
|
||||
'store_email' => 'admin@fleetcart.test',
|
||||
'newsletter_enabled' => false,
|
||||
'search_engine' => 'mysql',
|
||||
'local_pickup_cost' => 0,
|
||||
@@ -97,12 +92,14 @@ class App
|
||||
]);
|
||||
}
|
||||
|
||||
private function createDefaultCurrencyRate()
|
||||
|
||||
private function createDefaultCurrencyRate(): void
|
||||
{
|
||||
CurrencyRate::create(['currency' => 'USD', 'rate' => 1]);
|
||||
}
|
||||
|
||||
private function createStorageFolder()
|
||||
|
||||
private function createStorageFolder(): void
|
||||
{
|
||||
if (!is_dir(public_path('storage'))) {
|
||||
mkdir(public_path('storage'));
|
||||
|
||||
@@ -8,47 +8,51 @@ use Jackiedo\DotenvEditor\Facades\DotenvEditor;
|
||||
|
||||
class Database
|
||||
{
|
||||
public function setup($data)
|
||||
public function setup($request): void
|
||||
{
|
||||
$this->checkDatabaseConnection($data);
|
||||
$this->setEnvVariables($data);
|
||||
$this->setupDatabaseConnection($request);
|
||||
$this->setEnvVariables($request);
|
||||
$this->migrateDatabase();
|
||||
}
|
||||
|
||||
private function checkDatabaseConnection($data)
|
||||
{
|
||||
$this->setupDatabaseConnectionConfig($data);
|
||||
|
||||
private function setupDatabaseConnection($request): void
|
||||
{
|
||||
DB::purge('mysql');
|
||||
$this->setupDatabaseConnectionConfig($request);
|
||||
DB::connection('mysql')->reconnect();
|
||||
DB::connection('mysql')->getPdo();
|
||||
}
|
||||
|
||||
private function setupDatabaseConnectionConfig($data)
|
||||
|
||||
private function setupDatabaseConnectionConfig($request): void
|
||||
{
|
||||
config([
|
||||
'database.default' => 'mysql',
|
||||
'database.connections.mysql.host' => $data['host'],
|
||||
'database.connections.mysql.port' => $data['port'],
|
||||
'database.connections.mysql.database' => $data['database'],
|
||||
'database.connections.mysql.username' => $data['username'],
|
||||
'database.connections.mysql.password' => $data['password'],
|
||||
'database.connections.mysql.host' => $request['db_host'],
|
||||
'database.connections.mysql.port' => $request['db_port'],
|
||||
'database.connections.mysql.database' => $request['db_database'],
|
||||
'database.connections.mysql.username' => $request['db_username'],
|
||||
'database.connections.mysql.password' => $request['db_password'],
|
||||
]);
|
||||
}
|
||||
|
||||
private function setEnvVariables($data)
|
||||
|
||||
private function setEnvVariables($request): void
|
||||
{
|
||||
$env = DotenvEditor::load();
|
||||
|
||||
$env->setKey('DB_HOST', $data['host']);
|
||||
$env->setKey('DB_PORT', $data['port']);
|
||||
$env->setKey('DB_DATABASE', $data['database']);
|
||||
$env->setKey('DB_USERNAME', $data['username']);
|
||||
$env->setKey('DB_PASSWORD', $data['password']);
|
||||
$env->setKey('DB_HOST', $request['db_host']);
|
||||
$env->setKey('DB_PORT', $request['db_port']);
|
||||
$env->setKey('DB_DATABASE', $request['db_database']);
|
||||
$env->setKey('DB_USERNAME', $request['db_username']);
|
||||
$env->setKey('DB_PASSWORD', $request['db_password']);
|
||||
|
||||
$env->save();
|
||||
}
|
||||
|
||||
private function migrateDatabase()
|
||||
|
||||
private function migrateDatabase(): void
|
||||
{
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
}
|
||||
|
||||
30
app/Install/Permission.php
Normal file
30
app/Install/Permission.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace FleetCart\Install;
|
||||
|
||||
class Permission
|
||||
{
|
||||
public function provided(): bool
|
||||
{
|
||||
return collect($this->files())
|
||||
->merge($this->directories())
|
||||
->every(fn ($item) => $item);
|
||||
}
|
||||
|
||||
|
||||
public function files(): array
|
||||
{
|
||||
return [
|
||||
'.env' => is_writable(base_path('.env')),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function directories(): array
|
||||
{
|
||||
return [
|
||||
'storage' => is_writable(storage_path()),
|
||||
'bootstrap/cache' => is_writable(app()->bootstrapPath('cache')),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -4,36 +4,42 @@ namespace FleetCart\Install;
|
||||
|
||||
class Requirement
|
||||
{
|
||||
public function extensions()
|
||||
private const extensions = [
|
||||
'intl' => 'Intl',
|
||||
'pdo' => 'PDO',
|
||||
'json' => 'JSON',
|
||||
'ctype' => 'Ctype',
|
||||
'xml' => 'XML',
|
||||
'tokenizer' => 'Tokenizer',
|
||||
'mbstring' => 'Mbstring',
|
||||
'openssl' => 'OpenSSL',
|
||||
];
|
||||
|
||||
|
||||
public function satisfied(): bool
|
||||
{
|
||||
return collect($this->php())
|
||||
->merge($this->extensions())
|
||||
->every(fn ($item) => $item);
|
||||
}
|
||||
|
||||
|
||||
public function php(): array
|
||||
{
|
||||
return [
|
||||
'PHP >= 8.0.2' => version_compare(phpversion(), '8.0.2'),
|
||||
'Intl PHP Extension' => extension_loaded('intl'),
|
||||
'OpenSSL PHP Extension' => extension_loaded('openssl'),
|
||||
'PDO PHP Extension' => extension_loaded('pdo'),
|
||||
'Mbstring PHP Extension' => extension_loaded('mbstring'),
|
||||
'Tokenizer PHP Extension' => extension_loaded('tokenizer'),
|
||||
'XML PHP Extension' => extension_loaded('xml'),
|
||||
'Ctype PHP Extension' => extension_loaded('ctype'),
|
||||
'JSON PHP Extension' => extension_loaded('json'),
|
||||
];
|
||||
}
|
||||
|
||||
public function directories()
|
||||
{
|
||||
return [
|
||||
'.env' => is_writable(base_path('.env')),
|
||||
'storage' => is_writable(storage_path()),
|
||||
'bootstrap/cache' => is_writable(app()->bootstrapPath('cache')),
|
||||
];
|
||||
}
|
||||
|
||||
public function satisfied()
|
||||
public function extensions(): array
|
||||
{
|
||||
return collect($this->extensions())
|
||||
->merge($this->directories())
|
||||
->every(function ($item) {
|
||||
return $item;
|
||||
});
|
||||
$extensions = [];
|
||||
|
||||
foreach (self::extensions as $extension => $name) {
|
||||
$extensions[$name . ' PHP Extension'] = extension_loaded($extension);
|
||||
}
|
||||
|
||||
return $extensions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,17 +6,19 @@ use Modules\Setting\Entities\Setting;
|
||||
|
||||
class Store
|
||||
{
|
||||
public function setup($data)
|
||||
public function setup($request): void
|
||||
{
|
||||
Setting::setMany([
|
||||
'translatable' => [
|
||||
'store_name' => $data['store_name'],
|
||||
'store_name' => $request['store_name'],
|
||||
],
|
||||
'store_email' => $data['store_email'],
|
||||
'store_phone' => $data['store_phone'],
|
||||
'search_engine' => $data['search_engine'],
|
||||
'algolia_app_id' => $data['algolia_app_id'],
|
||||
'algolia_secret' => $data['algolia_secret'],
|
||||
'store_email' => $request['store_email'],
|
||||
'store_phone' => $request['store_phone'],
|
||||
'search_engine' => $request['store_search_engine'],
|
||||
'algolia_app_id' => $request['algolia_app_id'],
|
||||
'algolia_secret' => $request['algolia_secret'],
|
||||
'meilisearch_host' => $request['meilisearch_host'],
|
||||
'meilisearch_key' => $request['meilisearch_key'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
156
app/License.php
Normal file
156
app/License.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace FleetCart;
|
||||
|
||||
use stdClass;
|
||||
use Carbon\Carbon;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use GuzzleHttp\Exception\ServerException;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use FleetCart\Exceptions\InvalidLicenseException;
|
||||
|
||||
class License
|
||||
{
|
||||
private $license;
|
||||
private string $licenseFilePath;
|
||||
private string $endpoint = 'https://license.envaysoft.com';
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->licenseFilePath = storage_path('app/license');
|
||||
}
|
||||
|
||||
|
||||
public function shouldRecheck()
|
||||
{
|
||||
if ($this->valid()) {
|
||||
return Carbon::parse($this->getLicenseFromFile()->next_check)->isPast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function valid()
|
||||
{
|
||||
return $this->getLicenseFromFile()?->valid;
|
||||
}
|
||||
|
||||
|
||||
public function shouldCreateLicense(): bool
|
||||
{
|
||||
return match (true) {
|
||||
$this->inFrontend(), $this->runningInLocal(), $this->valid() => false,
|
||||
default => true,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws InvalidLicenseException|GuzzleException
|
||||
*/
|
||||
public function recheck(): void
|
||||
{
|
||||
$this->activate(
|
||||
$this->getLicenseFromFile()->purchase_code
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws InvalidLicenseException|GuzzleException
|
||||
*/
|
||||
public function activate($purchaseCode): void
|
||||
{
|
||||
$license = new stdClass();
|
||||
$client = new Client(['base_uri' => $this->endpoint]);
|
||||
try {
|
||||
$client->post('/api/v1/licenses', [
|
||||
'form_params' => [
|
||||
'item_id' => FleetCart::ITEM_ID,
|
||||
'domain' => request()->root(),
|
||||
'purchase_code' => $purchaseCode,
|
||||
],
|
||||
]);
|
||||
|
||||
$license->valid = true;
|
||||
} catch (ClientException $e) {
|
||||
$license->valid = false;
|
||||
|
||||
$response = json_decode($e->getResponse()->getBody());
|
||||
|
||||
if ($response->status === 'success' && !$response->valid) {
|
||||
throw new InvalidLicenseException('The purchase code is invalid.');
|
||||
}
|
||||
|
||||
if ($response->status === 'error') {
|
||||
throw new InvalidLicenseException($response->message);
|
||||
}
|
||||
} catch (ConnectException|ServerException|RequestException $e) {
|
||||
$license->valid = true;
|
||||
} finally {
|
||||
$license->purchase_code = $purchaseCode;
|
||||
$license->next_check = now()->addDays(1);
|
||||
|
||||
$this->deleteLicenseFile();
|
||||
$this->storeLicenseToFile(json_encode($license));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The following function implements Singleton pattern
|
||||
* to retrieve license from file.
|
||||
*/
|
||||
private function getLicenseFromFile()
|
||||
{
|
||||
if (!is_null($this->license)) {
|
||||
return $this->license;
|
||||
}
|
||||
|
||||
if (!file_exists($this->licenseFilePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->license = json_decode(
|
||||
decrypt(
|
||||
file_get_contents(
|
||||
$this->licenseFilePath
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return $this->license;
|
||||
}
|
||||
|
||||
|
||||
private function inFrontend(): bool
|
||||
{
|
||||
if (request()->is('license')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !request()->is('*admin*');
|
||||
}
|
||||
|
||||
|
||||
private function runningInLocal(): bool
|
||||
{
|
||||
return app()->isLocal() || in_array(request()->ip(), ['127.0.0.1', '::1']);
|
||||
}
|
||||
|
||||
|
||||
private function deleteLicenseFile(): void
|
||||
{
|
||||
File::delete($this->licenseFilePath);
|
||||
}
|
||||
|
||||
|
||||
private function storeLicenseToFile($license): void
|
||||
{
|
||||
file_put_contents($this->licenseFilePath, encrypt($license));
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,21 @@ class AppServiceProvider extends ServiceProvider
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
public function boot(): void
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Configure default String length of the generated migrations
|
||||
|--------------------------------------------------------------------------
|
||||
| Laravel uses the utf8mb4 character set by default, which includes
|
||||
| support for storing "emojis" in the database. if you are running a
|
||||
| version of MySQL older than the 5.7.7 release or MariaDB older than
|
||||
| the 10.2.2 release, you need to configure the default string length
|
||||
| generated by migrations in order for MySQL to create indexes for
|
||||
| them.
|
||||
*/
|
||||
Schema::defaultStringLength(191);
|
||||
|
||||
Paginator::useBootstrap();
|
||||
|
||||
if (Request::secure()) {
|
||||
@@ -26,14 +38,15 @@ class AppServiceProvider extends ServiceProvider
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
public function register(): void
|
||||
{
|
||||
if (! config('app.installed')) {
|
||||
if (!config('app.installed')) {
|
||||
$this->app->register(DotenvEditorServiceProvider::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,16 +16,18 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected $namespace = 'FleetCart\Http\Controllers';
|
||||
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function map()
|
||||
public function map(): void
|
||||
{
|
||||
$this->mapWebRoutes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Define the "web" routes for the application.
|
||||
*
|
||||
@@ -33,7 +35,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function mapWebRoutes()
|
||||
protected function mapWebRoutes(): void
|
||||
{
|
||||
Route::middleware('web')
|
||||
->namespace($this->namespace)
|
||||
|
||||
@@ -18,14 +18,16 @@ class EntityGenerator extends Generator
|
||||
'views/shortcuts.stub' => 'Resources/views/admin/$ENTITY_NAME$/partials/shortcuts.blade.php',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Generate the given entities.
|
||||
*
|
||||
* @param array $entities
|
||||
* @param bool $generateSidebar
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function generate(array $entities, $generateSidebar = true)
|
||||
public function generate(array $entities, $generateSidebar = true): void
|
||||
{
|
||||
if (count($entities) !== 0 && $generateSidebar) {
|
||||
$this->generateSidebarExtender($entities);
|
||||
@@ -44,11 +46,13 @@ class EntityGenerator extends Generator
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate a filled sidebar view composer
|
||||
* Or an empty one of no entities.
|
||||
*
|
||||
* @param $entities
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function generateSidebarExtender($entities)
|
||||
@@ -59,10 +63,12 @@ class EntityGenerator extends Generator
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append permissions.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function appendPermissions($entity)
|
||||
@@ -75,10 +81,12 @@ class EntityGenerator extends Generator
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate migrations file for eloquent entities.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function generateMigrations($entity)
|
||||
@@ -99,6 +107,7 @@ class EntityGenerator extends Generator
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the current time with microseconds.
|
||||
*
|
||||
@@ -114,10 +123,12 @@ class EntityGenerator extends Generator
|
||||
return $date->format('Y_m_d_Hisu_');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate entity.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function generateEntity($entity)
|
||||
@@ -133,10 +144,12 @@ class EntityGenerator extends Generator
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the controller for the given entity.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function generateController($entity)
|
||||
@@ -149,10 +162,12 @@ class EntityGenerator extends Generator
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the requests for the given entity.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function generateRequests($entity)
|
||||
@@ -165,32 +180,12 @@ class EntityGenerator extends Generator
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate views for the given entity.
|
||||
*
|
||||
* @param string $entity
|
||||
* @return void
|
||||
*/
|
||||
private function generateViews($entity)
|
||||
{
|
||||
$entityName = snake_case(str_plural($entity));
|
||||
|
||||
$this->createDirectory("Resources/views/admin/{$entityName}/partials");
|
||||
|
||||
foreach ($this->views as $stub => $view) {
|
||||
$view = str_replace('$ENTITY_NAME$', $entityName, $view);
|
||||
|
||||
$this->finder->put(
|
||||
$this->getModulesPath($view),
|
||||
$this->getContentForStub($stub, $entity)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate language files for the given entity.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function generateLang($entity)
|
||||
@@ -215,10 +210,36 @@ class EntityGenerator extends Generator
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate views for the given entity.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function generateViews($entity)
|
||||
{
|
||||
$entityName = snake_case(str_plural($entity));
|
||||
|
||||
$this->createDirectory("Resources/views/admin/{$entityName}/partials");
|
||||
|
||||
foreach ($this->views as $stub => $view) {
|
||||
$view = str_replace('$ENTITY_NAME$', $entityName, $view);
|
||||
|
||||
$this->finder->put(
|
||||
$this->getModulesPath($view),
|
||||
$this->getContentForStub($stub, $entity)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append the routes for the given entity to the routes file.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function appendRoutes($entity)
|
||||
@@ -231,10 +252,12 @@ class EntityGenerator extends Generator
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append sidebar extender.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function appendSidebarExtender($entity)
|
||||
|
||||
@@ -9,10 +9,12 @@ class FilesGenerator extends Generator
|
||||
/**
|
||||
* Generate the given files.
|
||||
*
|
||||
* @param array $files
|
||||
* @param array $files
|
||||
*
|
||||
* @return void
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public function generate(array $files)
|
||||
public function generate(array $files): void
|
||||
{
|
||||
foreach ($files as $stub => $file) {
|
||||
$this->finder->put(
|
||||
@@ -22,30 +24,32 @@ class FilesGenerator extends Generator
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the base module service provider.
|
||||
*
|
||||
* @return $this
|
||||
* @return void
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public function generateModuleProvider()
|
||||
public function generateModuleServiceProvider(): void
|
||||
{
|
||||
$this->finder->put(
|
||||
$this->getModulesPath("Providers/{$this->name}ServiceProvider.php"),
|
||||
$this->getContentFor('providers/module-service-provider.stub')
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the content for the given file.
|
||||
*
|
||||
* @param string $stub
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
private function getContentFor($stub)
|
||||
private function getContentFor(string $stub): string
|
||||
{
|
||||
$stub = $this->finder->get($this->getStubPath($stub));
|
||||
|
||||
|
||||
@@ -3,101 +3,103 @@
|
||||
namespace FleetCart\Scaffold\Module\Generators;
|
||||
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
|
||||
abstract class Generator
|
||||
{
|
||||
/**
|
||||
* The instance of Filesystem.
|
||||
*
|
||||
* @var \Illuminate\Filesystem\Filesystem
|
||||
* @var Filesystem
|
||||
*/
|
||||
protected $finder;
|
||||
protected Filesystem $finder;
|
||||
|
||||
/**
|
||||
* Name of the module.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
protected string $name;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param \Illuminate\Filesystem\Filesystem $finder
|
||||
* @param Filesystem $finder
|
||||
*/
|
||||
public function __construct(Filesystem $finder)
|
||||
{
|
||||
$this->finder = $finder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the given files.
|
||||
*
|
||||
* @param array $files
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function generate(array $files);
|
||||
abstract public function generate(array $files): void;
|
||||
|
||||
|
||||
/**
|
||||
* Set the module name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function module($name)
|
||||
public function module(string $name): static
|
||||
{
|
||||
$this->name = ucfirst($name);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current module path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
protected function getModulesPath($path = '')
|
||||
{
|
||||
return config('modules.paths.modules') . "/{$this->name}/{$path}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create directory if not exists.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createDirectory($path)
|
||||
protected function createDirectory($path): string
|
||||
{
|
||||
$path = $this->getModulesPath($path);
|
||||
|
||||
if (! $this->finder->isDirectory($path)) {
|
||||
if (!$this->finder->isDirectory($path)) {
|
||||
$this->finder->makeDirectory($path, 0755, true);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get stub path for the given stub file.
|
||||
* Return the current module path.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
protected function getStubPath($filename)
|
||||
protected function getModulesPath(string $path = ''): string
|
||||
{
|
||||
return __DIR__ . "/../stubs/{$filename}";
|
||||
return config('modules.paths.modules') . "/{$this->name}/{$path}";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get content of the given stub.
|
||||
*
|
||||
* @param string $stub
|
||||
* @param string $class
|
||||
*
|
||||
* @return string
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
protected function getContentForStub($stub, $class = '')
|
||||
protected function getContentForStub(string $stub, string $class = ''): string
|
||||
{
|
||||
$stub = $this->finder->get($this->getStubPath($stub));
|
||||
|
||||
@@ -131,4 +133,17 @@ abstract class Generator
|
||||
kebab_case(str_plural($class)),
|
||||
], $stub);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get stub path for the given stub file.
|
||||
*
|
||||
* @param string $filename
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getStubPath($filename)
|
||||
{
|
||||
return __DIR__ . "/../stubs/{$filename}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use FleetCart\Scaffold\Module\Generators\FilesGenerator;
|
||||
use FleetCart\Scaffold\Module\Generators\EntityGenerator;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
|
||||
class ModuleScaffold
|
||||
{
|
||||
@@ -14,53 +15,49 @@ class ModuleScaffold
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $vendor;
|
||||
protected string $vendor;
|
||||
|
||||
/**
|
||||
* The module name which will be generated.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* The instance of Filesystem.
|
||||
*
|
||||
* @var \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
private $finder;
|
||||
|
||||
/**
|
||||
* The instance of EntityGenerator.
|
||||
*
|
||||
* @var \FleetCart\Scaffold\Module\Generators\EntityGenerator
|
||||
*/
|
||||
private $entityGenerator;
|
||||
|
||||
/**
|
||||
* The instance of FilesGenerator.
|
||||
*
|
||||
* @var \FleetCart\Scaffold\Module\Generators\FilesGenerator
|
||||
*/
|
||||
private $filesGenerator;
|
||||
|
||||
protected string $name;
|
||||
/**
|
||||
* Array of files to be generated.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $files = [
|
||||
'config/assets.stub' => 'Config/assets.php',
|
||||
protected array $stubsToFilesMap = [
|
||||
'config/permissions.stub' => 'Config/permissions.php',
|
||||
'routes/routes.stub' => 'Routes/admin.php',
|
||||
];
|
||||
/**
|
||||
* The instance of Filesystem.
|
||||
*
|
||||
* @var Filesystem
|
||||
*/
|
||||
private Filesystem $finder;
|
||||
/**
|
||||
* The instance of EntityGenerator.
|
||||
*
|
||||
* @var EntityGenerator
|
||||
*/
|
||||
private EntityGenerator $entityGenerator;
|
||||
/**
|
||||
* The instance of FilesGenerator.
|
||||
*
|
||||
* @var FilesGenerator
|
||||
*/
|
||||
private FilesGenerator $filesGenerator;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param \Illuminate\Filesystem\Filesystem $finder
|
||||
* @param \FleetCart\Scaffold\Module\Generators\EntityGenerator $entityGenerator
|
||||
* @param \FleetCart\Scaffold\Module\Generators\FilesGenerator $filesGenerator
|
||||
* @param Filesystem $finder
|
||||
* @param EntityGenerator $entityGenerator
|
||||
* @param FilesGenerator $filesGenerator
|
||||
*/
|
||||
public function __construct(Filesystem $finder, EntityGenerator $entityGenerator, FilesGenerator $filesGenerator)
|
||||
{
|
||||
@@ -69,124 +66,129 @@ class ModuleScaffold
|
||||
$this->filesGenerator = $filesGenerator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $module
|
||||
* @param array $entities
|
||||
*
|
||||
* @return void
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public function scaffold(array $module, array $entities)
|
||||
public function scaffold(array $module, array $entities): void
|
||||
{
|
||||
$this->vendor = $module['vendor'];
|
||||
$this->name = $module['name'];
|
||||
|
||||
Artisan::call('module:make', ['name' => [$this->name]]);
|
||||
|
||||
$this->generateModule();
|
||||
$this->renameVendorName();
|
||||
$this->addFolders();
|
||||
$this->removeUnneededFiles();
|
||||
$this->addDataToComposerJsonFile();
|
||||
$this->removeUnneededFilesAndFolders();
|
||||
$this->modifyComposerJsonFile();
|
||||
|
||||
$this->filesGenerator->module($this->name)
|
||||
->generateModuleProvider()
|
||||
->generate($this->files);
|
||||
$this->filesGenerator->module($this->name)->generateModuleServiceProvider();
|
||||
$this->filesGenerator->module($this->name)->generate($this->stubsToFilesMap);
|
||||
|
||||
$this->addDataToModuleJson();
|
||||
$this->modifyModuleJsonFile();
|
||||
$this->cleanupModuleJsonFile();
|
||||
|
||||
$this->entityGenerator->module($this->getName())->generate($entities);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate default module.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function generateModule(): void
|
||||
{
|
||||
Artisan::call('module:make', ['name' => [$this->name]]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get studly cased module name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return studly_case($this->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path on the module.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getModulesPath($path = '')
|
||||
{
|
||||
return config('modules.paths.modules') . "/{$this->getName()}/{$path}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the paths on the module.
|
||||
*
|
||||
* @param array $paths
|
||||
* @return array
|
||||
*/
|
||||
private function getModulesPaths(array $paths)
|
||||
{
|
||||
$list = [];
|
||||
|
||||
foreach ($paths as $path) {
|
||||
$list[] = $this->getModulesPath($path);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove vendor name from composer.json file.
|
||||
*
|
||||
* @return void
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
private function renameVendorName()
|
||||
private function renameVendorName(): void
|
||||
{
|
||||
$composerJsonContent = $this->finder->get($this->getModulesPath('composer.json'));
|
||||
$composerJsonPath = $this->getModulesPath('composer.json');
|
||||
$composerJsonContent = $this->finder->get($composerJsonPath);
|
||||
$composerJsonContent = str_replace('nwidart', $this->vendor, $composerJsonContent);
|
||||
|
||||
$this->finder->put($this->getModulesPath('composer.json'), $composerJsonContent);
|
||||
$this->finder->put($composerJsonPath, $composerJsonContent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove view files.
|
||||
* Get the path on the module.
|
||||
*
|
||||
* @return void
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function removeViewFiles()
|
||||
private function getModulesPath(string $path = ''): string
|
||||
{
|
||||
$this->finder->delete($this->getModulesPath('Resources/views/index.blade.php'));
|
||||
$this->finder->delete($this->getModulesPath('Resources/views/layouts/master.blade.php'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Resources/views/layouts'));
|
||||
return config('modules.paths.modules') . "/{$this->getName()}/{$path}";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add required folders.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addFolders()
|
||||
private function addFolders(): void
|
||||
{
|
||||
$this->finder->makeDirectory($this->getModulesPath('Sidebar'));
|
||||
$this->addSidebarFolder();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add Sidebar folder.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addSidebarFolder(): void
|
||||
{
|
||||
$directoryPath = $this->getModulesPath('Sidebar');
|
||||
$this->finder->makeDirectory($directoryPath);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove unneeded files and folders.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeUnneededFiles()
|
||||
private function removeUnneededFilesAndFolders(): void
|
||||
{
|
||||
$this->renameVendorName();
|
||||
$this->removeViewFiles();
|
||||
$this->removeUnneededFiles();
|
||||
$this->removeUnneededFolders();
|
||||
}
|
||||
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Database/factories'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Database/Seeders'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Events'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Console'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Http/Middleware'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Jobs'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Mail'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Resources/assets'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Tests'));
|
||||
|
||||
/**
|
||||
* Remove unneeded files.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeUnneededFiles(): void
|
||||
{
|
||||
$files = $this->getModulesPaths([
|
||||
'Config/.gitkeep',
|
||||
'Config/config.php',
|
||||
@@ -199,6 +201,8 @@ class ModuleScaffold
|
||||
'Providers/RouteServiceProvider.php',
|
||||
'Resources/lang/.gitkeep',
|
||||
'Resources/views/.gitkeep',
|
||||
'Resources/views/index.blade.php',
|
||||
'Resources/views/layouts/master.blade.php',
|
||||
'Routes/.gitkeep',
|
||||
'Routes/web.php',
|
||||
'Routes/api.php',
|
||||
@@ -209,12 +213,116 @@ class ModuleScaffold
|
||||
$this->finder->delete($files);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the paths on the module.
|
||||
*
|
||||
* @param array $paths
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getModulesPaths(array $paths): array
|
||||
{
|
||||
$list = [];
|
||||
|
||||
foreach ($paths as $path) {
|
||||
$list[] = $this->getModulesPath($path);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove unneeded folders.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeUnneededFolders(): void
|
||||
{
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Database/factories'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Database/Seeders'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Events'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Console'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Http/Middleware'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Jobs'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Mail'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Resources/assets'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Resources/views/layouts'));
|
||||
$this->finder->deleteDirectory($this->getModulesPath('Tests'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add data to composer.json file.
|
||||
*
|
||||
* @return void
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
private function modifyComposerJsonFile(): void
|
||||
{
|
||||
$moduleName = ucfirst($this->name);
|
||||
$composerJsonPath = $this->getModulesPath('composer.json');
|
||||
|
||||
$composerJsonFile = fopen($composerJsonPath, "r");
|
||||
|
||||
$composerJsonFileAsArray = [];
|
||||
while (!feof($composerJsonFile)) {
|
||||
$composerJsonFileAsArray[] = rtrim(fgets($composerJsonFile));
|
||||
}
|
||||
|
||||
$composerJsonText = '';
|
||||
|
||||
foreach ($composerJsonFileAsArray as $lineNumber => $textLine) {
|
||||
if ($lineNumber === 2) {
|
||||
$composerJsonText .= " \"description\": \"The FleetCart {$moduleName} Module.\"," . PHP_EOL;
|
||||
continue;
|
||||
} else if ($lineNumber >= 9 && $lineNumber <= 23) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$composerJsonText .= $textLine . PHP_EOL;
|
||||
}
|
||||
|
||||
$search = <<<JSON
|
||||
],
|
||||
JSON;
|
||||
|
||||
$replace = <<<JSON
|
||||
],
|
||||
"require": {
|
||||
"php": ">=8.0.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Modules\\\\{$moduleName}\\\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
JSON;
|
||||
|
||||
$composerJson = str_replace($search, $replace, $composerJsonText);
|
||||
|
||||
$this->finder->put($this->getModulesPath('composer.json'), $composerJson);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add data to module.json file.
|
||||
*
|
||||
* @return void
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
private function addDataToModuleJson()
|
||||
private function modifyModuleJsonFile(): void
|
||||
{
|
||||
$moduleJson = $this->finder->get($this->getModulesPath('module.json'));
|
||||
|
||||
@@ -223,22 +331,27 @@ class ModuleScaffold
|
||||
$this->finder->put($this->getModulesPath('module.json'), $moduleJson);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the module priority for composer.json file.
|
||||
*
|
||||
* @param $content
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function setModulePriority($content)
|
||||
private function setModulePriority($content): string
|
||||
{
|
||||
return str_replace('"priority": 0,', '"priority": 100,', $content);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove unneeded data from module.json file.
|
||||
*
|
||||
* @return void
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
private function cleanupModuleJsonFile()
|
||||
private function cleanupModuleJsonFile(): void
|
||||
{
|
||||
$moduleJson = $this->finder->get($this->getModulesPath('module.json'));
|
||||
|
||||
@@ -274,60 +387,4 @@ JSON;
|
||||
|
||||
$this->finder->put($this->getModulesPath('module.json'), $moduleJson);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data to composer.json file.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addDataToComposerJsonFile()
|
||||
{
|
||||
$composerJson = $this->finder->get($this->getModulesPath('composer.json'));
|
||||
|
||||
$moduleName = ucfirst($this->name);
|
||||
|
||||
$composerJsonText = '';
|
||||
|
||||
foreach (explode(PHP_EOL, $composerJson) as $lineNumber => $textLine) {
|
||||
if ($lineNumber === 2) {
|
||||
$composerJsonText .= " \"description\": \"The FleetCart {$moduleName} Module.\"," . PHP_EOL;
|
||||
|
||||
continue;
|
||||
} elseif ($lineNumber >= 9 && $lineNumber <= 23) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$composerJsonText .= $textLine . PHP_EOL;
|
||||
}
|
||||
|
||||
$search = <<<JSON
|
||||
],
|
||||
JSON;
|
||||
|
||||
$replace = <<<JSON
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Modules\\\\{$moduleName}\\\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
JSON;
|
||||
|
||||
$composerJson = str_replace($search, $replace, $composerJsonText);
|
||||
|
||||
$this->finder->put($this->getModulesPath('composer.json'), $composerJson);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
|
||||
namespace Modules\$MODULE$\Providers;
|
||||
|
||||
use Modules\Support\Traits\AddsAsset;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class $MODULE$ServiceProvider extends ServiceProvider
|
||||
{
|
||||
use AddsAsset;
|
||||
|
||||
/**
|
||||
* Bootstrap the application services.
|
||||
*
|
||||
|
||||
@@ -14,3 +14,10 @@
|
||||
@endsection
|
||||
|
||||
@include('$LOWERCASE_MODULE_NAME$::admin.$PLURAL_SNAKE_CASE_ENTITY_NAME$.partials.shortcuts')
|
||||
|
||||
@push('globals')
|
||||
@vite([
|
||||
'Modules/Variation/Resources/assets/admin/sass/main.scss',
|
||||
'Modules/Variation/Resources/assets/admin/js/main.js',
|
||||
])
|
||||
@endpush
|
||||
|
||||
@@ -16,3 +16,10 @@
|
||||
@endsection
|
||||
|
||||
@include('$LOWERCASE_MODULE_NAME$::admin.$PLURAL_SNAKE_CASE_ENTITY_NAME$.partials.shortcuts')
|
||||
|
||||
@push('globals')
|
||||
@vite([
|
||||
'Modules/Variation/Resources/assets/admin/sass/main.scss',
|
||||
'Modules/Variation/Resources/assets/admin/js/main.js',
|
||||
])
|
||||
@endpush
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
@endcomponent
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
<script type="module">
|
||||
new DataTable('#$PLURAL_SNAKE_CASE_ENTITY_NAME$-table .table', {
|
||||
columns: [
|
||||
{ data: 'checkbox', orderable: false, searchable: false, width: '3%' },
|
||||
|
||||
@@ -7,7 +7,7 @@ use Illuminate\Support\Facades\DB;
|
||||
|
||||
class V2_0_0
|
||||
{
|
||||
public function run()
|
||||
public function run(): void
|
||||
{
|
||||
if (version_compare(FleetCart::VERSION, '2.0.0', '=')) {
|
||||
DB::delete("DELETE FROM `settings` WHERE `key` LIKE 'storefront_%' AND NOT `key` = 'storefront_copyright_text'");
|
||||
|
||||
@@ -8,7 +8,7 @@ use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
class Updater
|
||||
{
|
||||
public static function run()
|
||||
public static function run(): void
|
||||
{
|
||||
@set_time_limit(0);
|
||||
|
||||
@@ -22,34 +22,40 @@ class Updater
|
||||
File::delete(storage_path('app/update'));
|
||||
}
|
||||
|
||||
private static function migrate()
|
||||
|
||||
private static function migrate(): void
|
||||
{
|
||||
if (config('app.installed')) {
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
}
|
||||
}
|
||||
|
||||
private static function clearViewCache()
|
||||
|
||||
private static function clearViewCache(): void
|
||||
{
|
||||
Artisan::call('view:clear');
|
||||
}
|
||||
|
||||
private static function clearConfigCache()
|
||||
|
||||
private static function clearConfigCache(): void
|
||||
{
|
||||
Artisan::call('config:clear');
|
||||
}
|
||||
|
||||
private static function clearRouteCache()
|
||||
|
||||
private static function clearRouteCache(): void
|
||||
{
|
||||
Artisan::call('route:trans:clear');
|
||||
}
|
||||
|
||||
private static function clearAppCache()
|
||||
|
||||
private static function clearAppCache(): void
|
||||
{
|
||||
Artisan::call('cache:clear');
|
||||
}
|
||||
|
||||
private static function runScripts()
|
||||
|
||||
private static function runScripts(): void
|
||||
{
|
||||
$previouslyRan = DB::table('updater_scripts')->get();
|
||||
|
||||
@@ -60,7 +66,7 @@ class Updater
|
||||
|
||||
$script = $file->getBasename('.php');
|
||||
|
||||
if (! $previouslyRan->contains($script)) {
|
||||
if (!$previouslyRan->contains($script)) {
|
||||
resolve("FleetCart\\Scripts\\{$script}")->run();
|
||||
|
||||
$ran[] = ['script' => $script];
|
||||
|
||||
Reference in New Issue
Block a user