first commit

This commit is contained in:
JaguarJack 2022-12-05 23:01:12 +08:00
commit 0024080c28
322 changed files with 27698 additions and 0 deletions

18
.editorconfig Normal file
View File

@ -0,0 +1,18 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4

59
.env.example Normal file
View File

@ -0,0 +1,59 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
DB_PREFIX=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=mt1
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

11
.gitattributes vendored Normal file
View File

@ -0,0 +1,11 @@
* text=auto
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore
.styleci.yml export-ignore

View File

@ -0,0 +1,24 @@
# 环境
- 操作系统:
- php 版本:
- Laravel 版本:
- Mysql 版本:
- web 服务器:
# 问题
- 问题描述:
- 问题截图:
# 结果
- 实际结果:
- 预期结果:
# 分析
- 所做的尝试:
-
-
# 方案:
- 解决方案:
> 请在问题解决后关闭 issue

25
.github/issue_template.md vendored Normal file
View File

@ -0,0 +1,25 @@
# 环境
- 操作系统:
- php 版本:
- Laravel 版本:
- Mysql 版本:
- web 服务器:
# 问题
- 问题描述:
- 问题截图:
# 结果
- 实际结果:
- 预期结果:
# 分析
- 所做的尝试:
-
-
# 方案:
- 解决方案:
> 请在问题解决后关闭 issue

24
.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
/node_modules
/public/build
/public/hot
/public/storage
/storage/*.key
/vendor
/fixer
.env
.env.backup
.env.production
.phpunit.result.cache
.php-cs-fixer.cache
Homestead.json
Homestead.yaml
auth.json
npm-debug.log
yarn-error.log
yarn.lock
composer.lock
/.fleet
/.idea
/.vscode
components.d.ts
auto-imports.d.ts

101
.php-cs-fixer.dist.php Normal file
View File

@ -0,0 +1,101 @@
<?php
require_once __DIR__.DIRECTORY_SEPARATOR.'fixer'.DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'autoload.php';
use PhpCsFixer\Finder;
use PhpCsFixer\Config;
$finder = Finder::create()
// 排除目录
//->exclude('packages')
//// ->notPath('./packages/test.php')
// in 配置需要规则的目录
->in([
__DIR__.DIRECTORY_SEPARATOR.'app',
__DIR__.DIRECTORY_SEPARATOR.'catch',
__DIR__.DIRECTORY_SEPARATOR.'modules',
])
// 排除 . 开头的文件
->ignoreDotFiles(true)
// vcs 文件
->ignoreVCS(true);
$config = new Config();
return $config->setRules([
'@PSR1' => true, // psr1
'@PSR2' => true, // psr2 规范
'@PSR12' => true, // psr12 规范
'binary_operator_spaces' => true, // 二元操作符号空格 $a=1 => $a = 1;
'array_syntax' => [
'syntax' => 'short', // array('1') => ['1']
],
'no_trailing_comma_in_singleline_array' => true, // -$a = array('sample', ); => $a = array('sample');
'trim_array_spaces' => true, // array( 'a', 'b' ); => array('a', 'b')
'single_trait_insert_per_statement' => false,
'standardize_not_equals' => true, // "!=" => "<>"
'magic_constant_casing' => true, // __dir__ => __DIR__
'native_function_casing' => true, // STRLEN($str); => strlen($str);
'cast_spaces' => true, // (int)$b => (int) $b
'simplified_if_return' => true, // if ($foo) { return true; } return false; => return (bool) ($foo) ;
'no_unused_imports' => true, // use \DateTime; -use \Exception; => use \DateTime;
'not_operator_with_successor_space' => true, // if (!$bar) => if (! $bar)
/**
* // function example($b) {
if ($b) {
return;
}
- return;
*/
'no_useless_return' => true,
/**
* function a() {
- $a = 1;
- return $a;
+ return 1;
*/
'return_assignment' => true,
/**
-<?php return null;
+<?php return;
*/
'simplified_null_return' => true,
/**
* $foo = [
- 'bar' => [
- 'baz' => true,
- ],
+ 'bar' => [
+ 'baz' => true,
+ ],
*/
'array_indentation' => true,
/**
* -$sample = $b [ 'a' ] [ 'b' ];
+$sample = $b['a']['b'];
*/
'no_spaces_around_offset' => true,
'concat_space' => true, // $a.$b => $a . $b
])->setFinder($finder);

10
.prettierrc Normal file
View File

@ -0,0 +1,10 @@
{
"semi": false,
"printWidth": 200,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"arrowParens": "avoid",
"trailingComma": "all",
"bracketSpacing": true
}

35
README.md Normal file
View File

@ -0,0 +1,35 @@
## About CatchAdmin
## 安装
```shell
yarn install
yarn dev
```
```
composer install
php artisan serve
```
## 规范
### PHP
使用 fixer 进行代码检查, 具体请查看根目录下 `.php-cs-fixer.dist.php` 文件的规范,还需要进行以下两步骤
```shell
mkdir path && cd path // any path name you set
```
```shell
composer require --working-dir=path friendsofphp/php-cs-fixer
```
安装完成之后可以使用
```shell
composer cs
```
进行代码格式化,这个命令会直接修改文件完成修正,如果只需要查看格式是否正确,那么使用
```shell
composer cs-diff
```
会列出不符合的代码格式

32
app/Console/Kernel.php Normal file
View File

@ -0,0 +1,32 @@
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}

33
app/Events/Create.php Normal file
View File

@ -0,0 +1,33 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class Create
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}

33
app/Events/Test.php Normal file
View File

@ -0,0 +1,33 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class Test
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace App\Exceptions;
use Catch\Exceptions\FailedException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of exception types with their corresponding custom log levels.
*
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
*/
protected $levels = [
//
];
/**
* A list of the exception types that are not reported.
*
* @var array<int, class-string<\Throwable>>
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed to the session on validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (Throwable $e) {
//
});
}
/**
* render
*
* @param $request
* @param Throwable $e
* @return JsonResponse|Response
* @throws Throwable
*/
public function render($request, Throwable $e): JsonResponse|Response
{
$message = $e->getMessage();
if (method_exists($e, 'getStatusCode')) {
if ($e->getStatusCode() == Response::HTTP_NOT_FOUND) {
$message = '路由未找到或未注册';
}
}
$e = new FailedException($message ?: 'Server Error');
$response = parent::render($request, $e);
$response->header('Access-Control-Allow-Origin', '*');
$response->header('Access-Control-Allow-Methods', '*');
$response->header('Access-Control-Allow-Headers', '*');
return $response;
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

67
app/Http/Kernel.php Normal file
View File

@ -0,0 +1,67 @@
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array<int, class-string|string>
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array<string, class-string|string>
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array<int, string>
*/
protected $except = [
//
];
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array<int, string>
*/
protected $except = [
//
];
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @param string|null ...$guards
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array<int, string>
*/
protected $except = [
'current_password',
'password',
'password_confirmation',
];
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustHosts as Middleware;
class TrustHosts extends Middleware
{
/**
* Get the host patterns that should be trusted.
*
* @return array<int, string|null>
*/
public function hosts()
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array<int, string>|string|null
*/
protected $proxies;
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
class ValidateSignature extends Middleware
{
/**
* The names of the query string parameters that should be ignored.
*
* @var array<int, string>
*/
protected $except = [
// 'fbclid',
// 'utm_campaign',
// 'utm_content',
// 'utm_medium',
// 'utm_source',
// 'utm_term',
];
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array<int, string>
*/
protected $except = [
//
];
}

30
app/Listeners/Command.php Normal file
View File

@ -0,0 +1,30 @@
<?php
namespace App\Listeners;
use Illuminate\Console\Events\CommandFinished;
class Command
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param CommandFinished $event
* @return void
*/
public function handle(CommandFinished $event)
{
//
// dd($event->command);
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Listeners;
class RouteMatched
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle(\Illuminate\Routing\Events\RouteMatched $event)
{
//
// dd($event->route);
}
}

27
app/Listeners/test.php Normal file
View File

@ -0,0 +1,27 @@
<?php
namespace App\Listeners;
class test
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
//
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace App\Models\Modules\Users\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class CatchController extends Model
{
use HasFactory;
}

45
app/Models/User.php Normal file
View File

@ -0,0 +1,45 @@
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Providers;
// use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The model to policy mappings for the application.
*
* @var array<class-string, class-string>
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
//
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Broadcast::routes();
require base_path('routes/channels.php');
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace App\Providers;
use App\Listeners\Command;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Console\Events\CommandFinished;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Routing\Events\RouteMatched;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event to listener mappings for the application.
*
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
RouteMatched::class => [
\App\Listeners\RouteMatched::class
],
CommandFinished::class => [
Command::class
]
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
//
}
/**
* Determine if events and listeners should be automatically discovered.
*
* @return bool
*/
public function shouldDiscoverEvents()
{
return false;
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace App\Providers;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* The path to the "home" route for your application.
*
* Typically, users are redirected here after authentication.
*
* @var string
*/
public const HOME = '/home';
/**
* Define your route model bindings, pattern filters, and other route configuration.
*
* @return void
*/
public function boot()
{
$this->configureRateLimiting();
$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
Route::middleware('web')
->group(base_path('routes/web.php'));
});
}
/**
* Configure the rate limiters for the application.
*
* @return void
*/
protected function configureRateLimiting()
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
}
}

53
artisan Normal file
View File

@ -0,0 +1,53 @@
#!/usr/bin/env php
<?php
define('LARAVEL_START', microtime(true));
/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader
| for our application. We just need to utilize it! We'll require it
| into the script here so that we do not have to worry about the
| loading of any of our classes manually. It's great to relax.
|
*/
require __DIR__.'/vendor/autoload.php';
$app = require_once __DIR__.'/bootstrap/app.php';
/*
|--------------------------------------------------------------------------
| Run The Artisan Application
|--------------------------------------------------------------------------
|
| When we run the console application, the current CLI command will be
| executed in this console and the response sent back to a terminal
| or another output device for the developers. Here goes nothing!
|
*/
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$status = $kernel->handle(
$input = new Symfony\Component\Console\Input\ArgvInput,
new Symfony\Component\Console\Output\ConsoleOutput
);
/*
|--------------------------------------------------------------------------
| Shutdown The Application
|--------------------------------------------------------------------------
|
| Once Artisan has finished running, we will fire off the shutdown events
| so that any final work may be done by the application before we shut
| down the process. This is the last thing to happen to the request.
|
*/
$kernel->terminate($input, $status);
exit($status);

278
auto-imports.d.ts vendored Normal file
View File

@ -0,0 +1,278 @@
// Generated by 'unplugin-auto-import'
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const computed: typeof import('vue')['computed']
const computedAsync: typeof import('@vueuse/core')['computedAsync']
const computedEager: typeof import('@vueuse/core')['computedEager']
const computedInject: typeof import('@vueuse/core')['computedInject']
const computedWithControl: typeof import('@vueuse/core')['computedWithControl']
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
const controlledRef: typeof import('@vueuse/core')['controlledRef']
const createApp: typeof import('vue')['createApp']
const createEventHook: typeof import('@vueuse/core')['createEventHook']
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
const createPinia: typeof import('pinia')['createPinia']
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
const customRef: typeof import('vue')['customRef']
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const defineStore: typeof import('pinia')['defineStore']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getActivePinia: typeof import('pinia')['getActivePinia']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const isDefined: typeof import('@vueuse/core')['isDefined']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
const mapActions: typeof import('pinia')['mapActions']
const mapGetters: typeof import('pinia')['mapGetters']
const mapState: typeof import('pinia')['mapState']
const mapStores: typeof import('pinia')['mapStores']
const mapWritableState: typeof import('pinia')['mapWritableState']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
const onLongPress: typeof import('@vueuse/core')['onLongPress']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const provide: typeof import('vue')['provide']
const reactify: typeof import('@vueuse/core')['reactify']
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
const reactive: typeof import('vue')['reactive']
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
const reactivePick: typeof import('@vueuse/core')['reactivePick']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const refAutoReset: typeof import('@vueuse/core')['refAutoReset']
const refDebounced: typeof import('@vueuse/core')['refDebounced']
const refDefault: typeof import('@vueuse/core')['refDefault']
const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl']
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveDirective: typeof import('vue')['resolveDirective']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const setActivePinia: typeof import('pinia')['setActivePinia']
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const storeToRefs: typeof import('pinia')['storeToRefs']
const syncRef: typeof import('@vueuse/core')['syncRef']
const syncRefs: typeof import('@vueuse/core')['syncRefs']
const templateRef: typeof import('@vueuse/core')['templateRef']
const throttledRef: typeof import('@vueuse/core')['throttledRef']
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
const toRaw: typeof import('vue')['toRaw']
const toReactive: typeof import('@vueuse/core')['toReactive']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const triggerRef: typeof import('vue')['triggerRef']
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
const unref: typeof import('vue')['unref']
const unrefElement: typeof import('@vueuse/core')['unrefElement']
const until: typeof import('@vueuse/core')['until']
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery']
const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter']
const useArrayFind: typeof import('@vueuse/core')['useArrayFind']
const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex']
const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin']
const useArrayMap: typeof import('@vueuse/core')['useArrayMap']
const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce']
const useArraySome: typeof import('@vueuse/core')['useArraySome']
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs']
const useBase64: typeof import('@vueuse/core')['useBase64']
const useBattery: typeof import('@vueuse/core')['useBattery']
const useBluetooth: typeof import('@vueuse/core')['useBluetooth']
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
const useCached: typeof import('@vueuse/core')['useCached']
const useClipboard: typeof import('@vueuse/core')['useClipboard']
const useCloned: typeof import('@vueuse/core')['useCloned']
const useColorMode: typeof import('@vueuse/core')['useColorMode']
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
const useCounter: typeof import('@vueuse/core')['useCounter']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVar: typeof import('@vueuse/core')['useCssVar']
const useCssVars: typeof import('vue')['useCssVars']
const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement']
const useCycleList: typeof import('@vueuse/core')['useCycleList']
const useDark: typeof import('@vueuse/core')['useDark']
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
const useDebounce: typeof import('@vueuse/core')['useDebounce']
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useDropZone: typeof import('@vueuse/core')['useDropZone']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover']
const useElementSize: typeof import('@vueuse/core')['useElementSize']
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
const useEventBus: typeof import('@vueuse/core')['useEventBus']
const useEventListener: typeof import('@vueuse/core')['useEventListener']
const useEventSource: typeof import('@vueuse/core')['useEventSource']
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
const useFavicon: typeof import('@vueuse/core')['useFavicon']
const useFetch: typeof import('@vueuse/core')['useFetch']
const useFileDialog: typeof import('@vueuse/core')['useFileDialog']
const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess']
const useFocus: typeof import('@vueuse/core')['useFocus']
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
const useFps: typeof import('@vueuse/core')['useFps']
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
const useGamepad: typeof import('@vueuse/core')['useGamepad']
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
const useIdle: typeof import('@vueuse/core')['useIdle']
const useImage: typeof import('@vueuse/core')['useImage']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
const useInterval: typeof import('@vueuse/core')['useInterval']
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
const useLink: typeof import('vue-router')['useLink']
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
const useMemoize: typeof import('@vueuse/core')['useMemoize']
const useMemory: typeof import('@vueuse/core')['useMemory']
const useMounted: typeof import('@vueuse/core')['useMounted']
const useMouse: typeof import('@vueuse/core')['useMouse']
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
const useNetwork: typeof import('@vueuse/core')['useNetwork']
const useNow: typeof import('@vueuse/core')['useNow']
const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl']
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
const useOnline: typeof import('@vueuse/core')['useOnline']
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
const useParallax: typeof import('@vueuse/core')['useParallax']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast']
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
const useScroll: typeof import('@vueuse/core')['useScroll']
const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
const useShare: typeof import('@vueuse/core')['useShare']
const useSlots: typeof import('vue')['useSlots']
const useSorted: typeof import('@vueuse/core')['useSorted']
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
const useStepper: typeof import('@vueuse/core')['useStepper']
const useStorage: typeof import('@vueuse/core')['useStorage']
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSupported: typeof import('@vueuse/core')['useSupported']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextDirection: typeof import('@vueuse/core')['useTextDirection']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
const useThrottle: typeof import('@vueuse/core')['useThrottle']
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
const useTimeout: typeof import('@vueuse/core')['useTimeout']
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll']
const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
const useTitle: typeof import('@vueuse/core')['useTitle']
const useToNumber: typeof import('@vueuse/core')['useToNumber']
const useToString: typeof import('@vueuse/core')['useToString']
const useToggle: typeof import('@vueuse/core')['useToggle']
const useTransition: typeof import('@vueuse/core')['useTransition']
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
const useVModel: typeof import('@vueuse/core')['useVModel']
const useVModels: typeof import('@vueuse/core')['useVModels']
const useVibrate: typeof import('@vueuse/core')['useVibrate']
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
const watch: typeof import('vue')['watch']
const watchArray: typeof import('@vueuse/core')['watchArray']
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
const watchEffect: typeof import('vue')['watchEffect']
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchPausable: typeof import('@vueuse/core')['watchPausable']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
}

55
bootstrap/app.php Normal file
View File

@ -0,0 +1,55 @@
<?php
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/
$app = new Illuminate\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
/*
|--------------------------------------------------------------------------
| Bind Important Interfaces
|--------------------------------------------------------------------------
|
| Next, we need to bind some important interfaces into the container so
| we will be able to resolve them when needed. The kernels serve the
| incoming requests to this application from both the web and CLI.
|
*/
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
/*
|--------------------------------------------------------------------------
| Return The Application
|--------------------------------------------------------------------------
|
| This script returns the application instance. The instance is given to
| the calling script so we can separate the building of the instances
| from the actual running of the application and sending responses.
|
*/
return $app;

49
bootstrap/cache/packages.php vendored Executable file
View File

@ -0,0 +1,49 @@
<?php return array (
'laravel/tinker' =>
array (
'providers' =>
array (
0 => 'Laravel\\Tinker\\TinkerServiceProvider',
),
),
'nesbot/carbon' =>
array (
'providers' =>
array (
0 => 'Carbon\\Laravel\\ServiceProvider',
),
),
'nunomaduro/collision' =>
array (
'providers' =>
array (
0 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
),
),
'nunomaduro/termwind' =>
array (
'providers' =>
array (
0 => 'Termwind\\Laravel\\TermwindServiceProvider',
),
),
'pestphp/pest' =>
array (
'providers' =>
array (
0 => 'Pest\\Laravel\\PestServiceProvider',
),
),
'tymon/jwt-auth' =>
array (
'aliases' =>
array (
'JWTAuth' => 'Tymon\\JWTAuth\\Facades\\JWTAuth',
'JWTFactory' => 'Tymon\\JWTAuth\\Facades\\JWTFactory',
),
'providers' =>
array (
0 => 'Tymon\\JWTAuth\\Providers\\LaravelServiceProvider',
),
),
);

237
bootstrap/cache/services.php vendored Executable file
View File

@ -0,0 +1,237 @@
<?php return array (
'providers' =>
array (
0 => 'Illuminate\\Auth\\AuthServiceProvider',
1 => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
2 => 'Illuminate\\Bus\\BusServiceProvider',
3 => 'Illuminate\\Cache\\CacheServiceProvider',
4 => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
5 => 'Illuminate\\Cookie\\CookieServiceProvider',
6 => 'Illuminate\\Database\\DatabaseServiceProvider',
7 => 'Illuminate\\Encryption\\EncryptionServiceProvider',
8 => 'Illuminate\\Filesystem\\FilesystemServiceProvider',
9 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider',
10 => 'Illuminate\\Hashing\\HashServiceProvider',
11 => 'Illuminate\\Mail\\MailServiceProvider',
12 => 'Illuminate\\Notifications\\NotificationServiceProvider',
13 => 'Illuminate\\Pagination\\PaginationServiceProvider',
14 => 'Illuminate\\Pipeline\\PipelineServiceProvider',
15 => 'Illuminate\\Queue\\QueueServiceProvider',
16 => 'Illuminate\\Redis\\RedisServiceProvider',
17 => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider',
18 => 'Illuminate\\Session\\SessionServiceProvider',
19 => 'Illuminate\\Translation\\TranslationServiceProvider',
20 => 'Illuminate\\Validation\\ValidationServiceProvider',
21 => 'Illuminate\\View\\ViewServiceProvider',
22 => 'Laravel\\Tinker\\TinkerServiceProvider',
23 => 'Carbon\\Laravel\\ServiceProvider',
24 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
25 => 'Termwind\\Laravel\\TermwindServiceProvider',
26 => 'Pest\\Laravel\\PestServiceProvider',
27 => 'Tymon\\JWTAuth\\Providers\\LaravelServiceProvider',
28 => 'Catch\\Providers\\CatchAdminServiceProvider',
29 => 'App\\Providers\\AppServiceProvider',
30 => 'App\\Providers\\AuthServiceProvider',
31 => 'App\\Providers\\EventServiceProvider',
32 => 'App\\Providers\\RouteServiceProvider',
),
'eager' =>
array (
0 => 'Illuminate\\Auth\\AuthServiceProvider',
1 => 'Illuminate\\Cookie\\CookieServiceProvider',
2 => 'Illuminate\\Database\\DatabaseServiceProvider',
3 => 'Illuminate\\Encryption\\EncryptionServiceProvider',
4 => 'Illuminate\\Filesystem\\FilesystemServiceProvider',
5 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider',
6 => 'Illuminate\\Notifications\\NotificationServiceProvider',
7 => 'Illuminate\\Pagination\\PaginationServiceProvider',
8 => 'Illuminate\\Session\\SessionServiceProvider',
9 => 'Illuminate\\View\\ViewServiceProvider',
10 => 'Carbon\\Laravel\\ServiceProvider',
11 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
12 => 'Termwind\\Laravel\\TermwindServiceProvider',
13 => 'Pest\\Laravel\\PestServiceProvider',
14 => 'Tymon\\JWTAuth\\Providers\\LaravelServiceProvider',
15 => 'Catch\\Providers\\CatchAdminServiceProvider',
16 => 'App\\Providers\\AppServiceProvider',
17 => 'App\\Providers\\AuthServiceProvider',
18 => 'App\\Providers\\EventServiceProvider',
19 => 'App\\Providers\\RouteServiceProvider',
),
'deferred' =>
array (
'Illuminate\\Broadcasting\\BroadcastManager' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
'Illuminate\\Contracts\\Broadcasting\\Factory' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
'Illuminate\\Contracts\\Broadcasting\\Broadcaster' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
'Illuminate\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider',
'Illuminate\\Contracts\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider',
'Illuminate\\Contracts\\Bus\\QueueingDispatcher' => 'Illuminate\\Bus\\BusServiceProvider',
'Illuminate\\Bus\\BatchRepository' => 'Illuminate\\Bus\\BusServiceProvider',
'Illuminate\\Bus\\DatabaseBatchRepository' => 'Illuminate\\Bus\\BusServiceProvider',
'cache' => 'Illuminate\\Cache\\CacheServiceProvider',
'cache.store' => 'Illuminate\\Cache\\CacheServiceProvider',
'cache.psr6' => 'Illuminate\\Cache\\CacheServiceProvider',
'memcached.connector' => 'Illuminate\\Cache\\CacheServiceProvider',
'Illuminate\\Cache\\RateLimiter' => 'Illuminate\\Cache\\CacheServiceProvider',
'Illuminate\\Foundation\\Console\\AboutCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Cache\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Cache\\Console\\ForgetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ClearCompiledCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Auth\\Console\\ClearResetsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ConfigCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ConfigClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\DbCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\PruneCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\ShowCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\WipeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\DownCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\EnvironmentCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\EnvironmentDecryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\EnvironmentEncryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\EventCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\EventClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\EventListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\KeyGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\OptimizeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\OptimizeClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\PackageDiscoverCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\ListFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\FlushFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\ForgetFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\ListenCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\PruneBatchesCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\PruneFailedJobsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\RestartCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\RetryCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\RetryBatchCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\WorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\RouteCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\RouteClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\RouteListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\DumpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\Seeds\\SeedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Console\\Scheduling\\ScheduleFinishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Console\\Scheduling\\ScheduleListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Console\\Scheduling\\ScheduleRunCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Console\\Scheduling\\ScheduleClearCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Console\\Scheduling\\ScheduleTestCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Console\\Scheduling\\ScheduleWorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ShowModelCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\StorageLinkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\UpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ViewCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ViewClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Cache\\Console\\CacheTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\CastMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ChannelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ComponentMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ConsoleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Routing\\Console\\ControllerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\DocsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\EventGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\EventMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ExceptionMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\Factories\\FactoryMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\JobMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ListenerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\MailMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Routing\\Console\\MiddlewareMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ModelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\NotificationMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Notifications\\Console\\NotificationTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ObserverMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\PolicyMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ProviderMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\FailedTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Queue\\Console\\BatchesTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\RequestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ResourceMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\RuleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ScopeMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\Seeds\\SeederMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Session\\Console\\SessionTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\ServeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\StubPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\TestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Foundation\\Console\\VendorPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'migrator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'migration.repository' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'migration.creator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\Migrations\\MigrateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\Migrations\\FreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\Migrations\\InstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\Migrations\\RefreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\Migrations\\ResetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\Migrations\\RollbackCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\Migrations\\StatusCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'Illuminate\\Database\\Console\\Migrations\\MigrateMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'composer' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
'hash' => 'Illuminate\\Hashing\\HashServiceProvider',
'hash.driver' => 'Illuminate\\Hashing\\HashServiceProvider',
'mail.manager' => 'Illuminate\\Mail\\MailServiceProvider',
'mailer' => 'Illuminate\\Mail\\MailServiceProvider',
'Illuminate\\Mail\\Markdown' => 'Illuminate\\Mail\\MailServiceProvider',
'Illuminate\\Contracts\\Pipeline\\Hub' => 'Illuminate\\Pipeline\\PipelineServiceProvider',
'queue' => 'Illuminate\\Queue\\QueueServiceProvider',
'queue.connection' => 'Illuminate\\Queue\\QueueServiceProvider',
'queue.failer' => 'Illuminate\\Queue\\QueueServiceProvider',
'queue.listener' => 'Illuminate\\Queue\\QueueServiceProvider',
'queue.worker' => 'Illuminate\\Queue\\QueueServiceProvider',
'redis' => 'Illuminate\\Redis\\RedisServiceProvider',
'redis.connection' => 'Illuminate\\Redis\\RedisServiceProvider',
'auth.password' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider',
'auth.password.broker' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider',
'translator' => 'Illuminate\\Translation\\TranslationServiceProvider',
'translation.loader' => 'Illuminate\\Translation\\TranslationServiceProvider',
'validator' => 'Illuminate\\Validation\\ValidationServiceProvider',
'validation.presence' => 'Illuminate\\Validation\\ValidationServiceProvider',
'command.tinker' => 'Laravel\\Tinker\\TinkerServiceProvider',
),
'when' =>
array (
'Illuminate\\Broadcasting\\BroadcastServiceProvider' =>
array (
),
'Illuminate\\Bus\\BusServiceProvider' =>
array (
),
'Illuminate\\Cache\\CacheServiceProvider' =>
array (
),
'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider' =>
array (
),
'Illuminate\\Hashing\\HashServiceProvider' =>
array (
),
'Illuminate\\Mail\\MailServiceProvider' =>
array (
),
'Illuminate\\Pipeline\\PipelineServiceProvider' =>
array (
),
'Illuminate\\Queue\\QueueServiceProvider' =>
array (
),
'Illuminate\\Redis\\RedisServiceProvider' =>
array (
),
'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider' =>
array (
),
'Illuminate\\Translation\\TranslationServiceProvider' =>
array (
),
'Illuminate\\Validation\\ValidationServiceProvider' =>
array (
),
'Laravel\\Tinker\\TinkerServiceProvider' =>
array (
),
),
);

145
catch/config/catch.php Normal file
View File

@ -0,0 +1,145 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
return [
/*
|--------------------------------------------------------------------------
| catch-admin default middleware
|--------------------------------------------------------------------------
|
| where you can set default middlewares
|
*/
'middleware_group' => [
],
/*
|--------------------------------------------------------------------------
| catch-admin catch_auth_middleware_alias
|--------------------------------------------------------------------------
|
| where you can set default middlewares
|
*/
'catch_auth_middleware_alias' => [
],
/*
|--------------------------------------------------------------------------
| catch-admin super admin id
|--------------------------------------------------------------------------
|
| where you can set super admin id
|
*/
'super_admin' => 1,
/*
|--------------------------------------------------------------------------
| catch-admin module setting
|--------------------------------------------------------------------------
|
| the root where module generate
| the namespace is module root namespace
| the default dirs is module generate default dirs
*/
'module' => [
'root' => 'modules',
'namespace' => 'Modules',
'default' => ['develop', 'user', 'permission'],
'default_dirs' => [
'Http'.DIRECTORY_SEPARATOR,
'Http'.DIRECTORY_SEPARATOR.'Requests'.DIRECTORY_SEPARATOR,
'Http'.DIRECTORY_SEPARATOR.'Controllers'.DIRECTORY_SEPARATOR,
'Models'.DIRECTORY_SEPARATOR,
'views'.DIRECTORY_SEPARATOR,
],
// storage module information
// which driver should be used?
'driver' => [
// currently, catchadmin support file and database
// the default is driver
'default' => 'file',
// use database driver
'table_name' => 'admin_modules'
]
],
/*
|--------------------------------------------------------------------------
| catch-admin response
|--------------------------------------------------------------------------
*/
'response' => [
// it's a controller middleware, it's set in CatchController
// if you not need json response, don't extend CatchController
'always_json' => \Catch\Middleware\JsonResponseMiddleware::class,
// response listener
// it listens [RequestHandled] event, if you don't need this
// you can change this config
'request_handled_listener' => \Catch\Listeners\RequestHandledListener::class
],
/*
|--------------------------------------------------------------------------
| catch-admin auth setting
|--------------------------------------------------------------------------
*/
'auth' => [
'guards' => [
'admin' => [
'driver' => 'jwt',
'provider' => 'admin_users',
],
],
'providers' => [
'admin_users' => [
'driver' => 'eloquent',
'model' => \Modules\User\Models\Users::class
]
]
],
/*
|--------------------------------------------------------------------------
| database sql log
|--------------------------------------------------------------------------
*/
'listen_db_log' => true,
/*
|--------------------------------------------------------------------------
| route config
|--------------------------------------------------------------------------
*/
'route' => [
'prefix' => 'api',
'middlewares' => [
\Catch\Middleware\AuthMiddleware::class,
\Catch\Middleware\JsonResponseMiddleware::class
]
],
];

View File

@ -0,0 +1,47 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
Schema::create(config('catch.module.table_name'), function (Blueprint $table) {
$table->increments('id');
$table->string('name')->comment('模块名称');
$table->string('path', 20)->comment('模块目录');
$table->string('description')->comment('模块描述');
$table->string('keywords')->comment('模块关键字');
$table->string('version', 20)->comment('模块版本号')->default('1.0.0');
$table->boolean('status')->comment('模块状态')->default(1);
$table->unsignedInteger('created_at')->comment('创建时间')->default(0);
$table->unsignedInteger('updated_at')->comment('更新时间')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
Schema::dropIfExists(config('catch.module.table_name'));
}
};

View File

@ -0,0 +1,34 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Base;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Auth;
/**
* base catch controller
*/
abstract class CatchController extends Controller
{
/**
* @param $guard
* @return Authenticatable
*/
protected function getLoginUser($guard = null): Authenticatable
{
return Auth::guard($guard ?: getGuardName())->user();
}
}

View File

@ -0,0 +1,89 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Base;
use Catch\Support\DB\SoftDelete;
use Catch\Traits\DB\BaseOperate;
use Catch\Traits\DB\ScopeTrait;
use Catch\Traits\DB\Trans;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder;
/**
*
* @mixin Builder
* @mixin \Illuminate\Database\Eloquent\Builder
*/
abstract class CatchModel extends Model
{
use BaseOperate, Trans, SoftDeletes, ScopeTrait;
/**
* unix timestamp
*
* @var string
*/
protected $dateFormat = 'U';
/**
* paginate limit
*/
protected $perPage = 10;
/**
* @var string[]
*/
protected $hidden = ['deleted_at'];
/**
* @var string[]
*/
protected $casts = [
'created_at' => 'datetime:Y-m-d H:i:s',
'updated_at' => 'datetime:Y-m-d H:i:s',
'deleted_at' => 'datetime:Y-m-d H:i:s'
];
/**
* @var array
*/
protected array $fieldsInList = ['*'];
/**
* @var bool
*/
protected bool $isPaginate = true;
/**
* @var array $searchable
*/
public array $searchable = [];
/**
* soft delete
*
* @time 2021年08月09日
* @return void
*/
public static function bootSoftDeletes(): void
{
static::addGlobalScope(new SoftDelete());
}
}

363
catch/src/CatchAdmin.php Normal file
View File

@ -0,0 +1,363 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017 ~ now https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class CatchAdmin
{
public const VERSION = '0.1.0';
/**
* version
*
*/
public static function version(): string
{
return static::VERSION;
}
/**
* module root path
*
* @return string
*/
public static function moduleRootPath(): string
{
return self::makeDir(base_path(config('catch.module.root')).DIRECTORY_SEPARATOR);
}
/**
* make dir
*
* @param string $dir
* @return string
*/
public static function makeDir(string $dir): string
{
if (! File::isDirectory($dir) && ! File::makeDirectory($dir, 0777, true)) {
throw new \RuntimeException(sprintf('Directory %s created Failed', $dir));
}
return $dir;
}
/**
* module dir
*
* @param string $module
* @param bool $make
* @return string
*/
public static function getModulePath(string $module, bool $make = true): string
{
if ($make) {
return self::makeDir(self::moduleRootPath().ucfirst($module).DIRECTORY_SEPARATOR);
}
return self::moduleRootPath().ucfirst($module).DIRECTORY_SEPARATOR;
}
/**
* delete module path
*
* @param string $module
* @return bool
*/
public static function deleteModulePath(string $module): bool
{
if (self::isModulePathExist($module)) {
File::deleteDirectory(self::getModulePath($module));
}
return true;
}
/**
* module path exists
*
* @param string $module
* @return bool
*/
public static function isModulePathExist(string $module): bool
{
return File::isDirectory(self::moduleRootPath().ucfirst($module).DIRECTORY_SEPARATOR);
}
/**
* module migration dir
*
* @param string $module
* @return string
*/
public static function getModuleMigrationPath(string $module): string
{
return self::makeDir(self::getModulePath($module).'database'.DIRECTORY_SEPARATOR.'migrations'.DIRECTORY_SEPARATOR);
}
/**
* module seeder dir
*
* @param string $module
* @return string
*/
public static function getModuleSeederPath(string $module): string
{
return self::makeDir(self::getModulePath($module).'database'.DIRECTORY_SEPARATOR.'seeder'.DIRECTORY_SEPARATOR);
}
/**
* get modules dir
*
* @return array
*/
public static function getModulesPath(): array
{
return File::directories(self::moduleRootPath());
}
/**
* get module root namespace
*
* @return string
*/
public static function getModuleRootNamespace(): string
{
return config('catch.module.namespace').'\\';
}
/**
* get module root namespace
*
* @param $moduleName
* @return string
*/
public static function getModuleNamespace($moduleName): string
{
return self::getModuleRootNamespace().ucfirst($moduleName).'\\';
}
/**
* model namespace
*
* @param $moduleName
* @return string
*/
public static function getModuleModelNamespace($moduleName): string
{
return self::getModuleNamespace($moduleName).'Models\\';
}
/**
* getServiceProviders
*
* @param $moduleName
* @return string
*/
public static function getModuleServiceProviderNamespace($moduleName): string
{
return self::getModuleNamespace($moduleName).'Providers\\';
}
/**
*
* @param $moduleName
* @return string
*/
public static function getModuleServiceProvider($moduleName): string
{
return self::getModuleServiceProviderNamespace($moduleName).ucfirst($moduleName).'ServiceProvider';
}
/**
* controller namespace
*
* @param $moduleName
* @return string
*/
public static function getModuleControllerNamespace($moduleName): string
{
return self::getModuleNamespace($moduleName).'Http\\Controllers\\';
}
/**
* getModuleRequestNamespace
*
* @param $moduleName
* @return string
*/
public static function getModuleRequestNamespace($moduleName): string
{
return self::getModuleNamespace($moduleName).'Http\\Requests\\';
}
/**
* getModuleRequestNamespace
*
* @param $moduleName
* @return string
*/
public static function getModuleEventsNamespace($moduleName): string
{
return self::getModuleNamespace($moduleName).'Events\\';
}
/**
* getModuleRequestNamespace
*
* @param $moduleName
* @return string
*/
public static function getModuleListenersNamespace($moduleName): string
{
return self::getModuleNamespace($moduleName).'Listeners\\';
}
/**
* module provider dir
*
* @param string $module
* @return string
*/
public static function getModuleProviderPath(string $module): string
{
return self::makeDir(self::getModulePath($module).'Providers'.DIRECTORY_SEPARATOR);
}
/**
* module model dir
*
* @param string $module
* @return string
*/
public static function getModuleModelPath(string $module): string
{
return self::makeDir(self::getModulePath($module).'Models'.DIRECTORY_SEPARATOR);
}
/**
* module controller dir
*
* @param string $module
* @return string
*/
public static function getModuleControllerPath(string $module): string
{
return self::makeDir(self::getModulePath($module).'Http'.DIRECTORY_SEPARATOR.'Controllers'.DIRECTORY_SEPARATOR);
}
/**
* module request dir
*
* @param string $module
* @return string
*/
public static function getModuleRequestPath(string $module): string
{
return self::makeDir(self::getModulePath($module).'Http'.DIRECTORY_SEPARATOR.'Requests'.DIRECTORY_SEPARATOR);
}
/**
* module request dir
*
* @param string $module
* @return string
*/
public static function getModuleEventPath(string $module): string
{
return self::makeDir(self::getModulePath($module).'Events'.DIRECTORY_SEPARATOR);
}
/**
* module request dir
*
* @param string $module
* @return string
*/
public static function getModuleListenersPath(string $module): string
{
return self::makeDir(self::getModulePath($module).'Listeners'.DIRECTORY_SEPARATOR);
}
/**
* commands path
*
* @param string $module
* @return string
*/
public static function getCommandsPath(string $module): string
{
return self::makeDir(self::getModulePath($module).'Commands'.DIRECTORY_SEPARATOR);
}
/**
* commands namespace
*
* @param string $module
* @return string
*/
public static function getCommandsNamespace(string $module): string
{
return self::getModuleNamespace($module).'Commands\\';
}
/**
* module route
*
* @param string $module
* @param string $routeName
* @return string
*/
public static function getModuleRoutePath(string $module, string $routeName = 'route.php'): string
{
return self::getModulePath($module).$routeName;
}
/**
* module route.php exists
*
* @param string $module
* @return bool
*/
public static function isModuleRouteExists(string $module): bool
{
return File::exists(self::getModuleRoutePath($module));
}
/**
* module views path
*
* @param string $module
* @return string
*/
public static function getModuleViewsPath(string $module): string
{
return self::makeDir(self::getModulePath($module).'views'.DIRECTORY_SEPARATOR);
}
/**
* relative path
*
* @param $path
* @return string
*/
public static function getModuleRelativePath($path): string
{
return Str::replaceFirst(base_path(), '.', $path);
}
}

View File

@ -0,0 +1,141 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017 ~ now https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Catch\Facade\Module;
use function Termwind\ask;
use function Termwind\render;
abstract class CatchCommand extends Command
{
/**
* @var string
*/
protected $name;
public function __construct()
{
parent::__construct();
if (! property_exists($this, 'signature')
&& property_exists($this, 'name')
&& $this->name
) {
$this->signature = $this->name.' {module}';
}
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return void
*/
protected function initialize(InputInterface $input, OutputInterface $output): void
{
if ($input->hasArgument('module')
&& ! Module::all()->pluck('name')->merge(Collection::make(config('catch.module.default')))->contains(lcfirst($input->getArgument('module')))
) {
$this->error(sprintf('Module [%s] Not Found', $input->getArgument('module')));
exit;
}
}
/**
*
* @param string $question
* @param null $default
* @param bool $isChoice
* @return string|int|null
*/
public function askFor(string $question, $default = null, bool $isChoice = false): string|null|int
{
$_default = $default ? "<em class='pl-1 text-rose-600'>[$default]</em>" : '';
$choice = $isChoice ? '<em class="bg-indigo-600 w-5 pl-1 ml-1 mr-1">Yes</em>OR<em class="bg-rose-600 w-4 pl-1 ml-1">No</em>' : '';
$answer = ask(
<<<HTML
<div>
<div class="px-1 bg-indigo-700">CatchAdmin</div>
<em class="ml-1">
<em class="text-green-700">$question</em>
$_default
$choice
<em class="ml-1">:</em><em class="ml-1"></em>
</em>
</div>
HTML
);
$this->newLine();
if ($default && ! $answer) {
return $default;
}
return $answer;
}
/**
* info
*
* @param $string
* @param null $verbosity
* @return void
*/
public function info($string, $verbosity = null): void
{
render(
<<<HTML
<div>
<div class="px-1 bg-indigo-700">CatchAdmin</div>
<em class="ml-1">
<em class="text-green-700">$string</em>
</em>
</div>
HTML
);
}
/**
* error
*
* @param $string
* @param null $verbosity
* @return void
*/
public function error($string, $verbosity = null): void
{
render(
<<<HTML
<div>
<div class="px-1 bg-indigo-700">CatchAdmin</div>
<em class="ml-1">
<em class="text-rose-700">$string</em>
</em>
</div>
HTML
);
}
}

View File

@ -0,0 +1,100 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Commands\Create;
use Catch\CatchAdmin;
use Catch\Commands\CatchCommand;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
;
class Controller extends CatchCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'catch:make:controller {module} {name}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'create catch controller';
public function handle()
{
$controllerPath = CatchAdmin::getModuleControllerPath($this->argument('module'));
$file = $controllerPath.$this->getControllerFile();
if (File::exists($file)) {
$answer = $this->ask($file.' already exists, Did you want replace it?', 'Y');
if (! Str::of($answer)->lower()->exactly('y')) {
exit;
}
}
File::put($file, Str::of($this->getStubContent())->replace([
'{namespace}', '{controller}'
], [trim(CatchAdmin::getModuleControllerNamespace($this->argument('module')), '\\'), $this->getControllerName()])->toString());
if (File::exists($file)) {
$this->info($file.' has been created');
} else {
$this->error($file.' create failed');
}
}
/**
*
*
* @return string
*/
protected function getControllerFile(): string
{
return $this->getControllerName().'.php';
}
/**
*
*
* @return string
*/
protected function getControllerName(): string
{
return Str::of($this->argument('name'))
->whenContains('Controller', function ($str) {
return $str;
}, function ($str) {
return $str->append('Controller');
})->ucfirst()->toString();
}
/**
* get stub content
*
* @return string
*/
protected function getStubContent(): string
{
return File::get(dirname(__DIR__).DIRECTORY_SEPARATOR.'stubs'.DIRECTORY_SEPARATOR.'controller.stub');
}
}

View File

@ -0,0 +1,100 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Commands\Create;
use Catch\CatchAdmin;
use Catch\Commands\CatchCommand;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
;
class Event extends CatchCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'catch:make:event {module} {name}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'create catch module event';
public function handle()
{
$eventPath = CatchAdmin::getModuleEventPath($this->argument('module'));
$file = $eventPath.$this->getEventFile();
if (File::exists($file)) {
$answer = $this->ask($file.' already exists, Did you want replace it?', 'Y');
if (! Str::of($answer)->lower()->exactly('y')) {
exit;
}
}
File::put($file, Str::of($this->getStubContent())->replace([
'{namespace}', '{event}'
], [trim(CatchAdmin::getModuleEventsNamespace($this->argument('module')), '\\'), $this->getEventName()])->toString());
if (File::exists($file)) {
$this->info($file.' has been created');
} else {
$this->error($file.' create failed');
}
}
/**
*
*
* @return string
*/
protected function getEventFile(): string
{
return $this->getEventName().'.php';
}
/**
*
*
* @return string
*/
protected function getEventName(): string
{
return Str::of($this->argument('name'))
->whenContains('Event', function ($str) {
return $str;
}, function ($str) {
return $str->append('Event');
})->ucfirst()->toString();
}
/**
* get stub content
*
* @return string
*/
protected function getStubContent(): string
{
return File::get(dirname(__DIR__).DIRECTORY_SEPARATOR.'stubs'.DIRECTORY_SEPARATOR.'event.stub');
}
}

View File

@ -0,0 +1,103 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Commands\Create;
use Catch\CatchAdmin;
use Catch\Commands\CatchCommand;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
;
class Listener extends CatchCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'catch:make:listener {module} {name}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'create catch module event';
public function handle()
{
$eventPath = CatchAdmin::getModuleListenersPath($this->argument('module'));
$file = $eventPath.$this->getListenerFile();
if (File::exists($file)) {
$answer = $this->ask($file.' already exists, Did you want replace it?', 'Y');
if (! Str::of($answer)->lower()->exactly('y')) {
exit;
}
}
File::put($file, Str::of($this->getStubContent())->replace([
'{namespace}', '{listener}'
], [
trim(CatchAdmin::getModuleListenersNamespace($this->argument('module')), '\\'),
$this->getListenerName()])->toString());
if (File::exists($file)) {
$this->info($file.' has been created');
} else {
$this->error($file.' create failed');
}
}
/**
*
*
* @return string
*/
protected function getListenerFile(): string
{
return $this->getListenerName().'.php';
}
/**
*
*
* @return string
*/
protected function getListenerName(): string
{
return Str::of($this->argument('name'))
->whenContains('Listener', function ($str) {
return $str;
}, function ($str) {
return $str->append('Listener');
})->ucfirst()->toString();
}
/**
* get stub content
*
* @return string
*/
protected function getStubContent(): string
{
return File::get(dirname(__DIR__).DIRECTORY_SEPARATOR.'stubs'.DIRECTORY_SEPARATOR.'listener.stub');
}
}

View File

@ -0,0 +1,174 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Commands\Create;
use Catch\CatchAdmin;
use Catch\Commands\CatchCommand;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
class Model extends CatchCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'catch:make:model {module} {model} {--t= : the model of table name}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'create catch module';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
if (! Schema::hasTable($this->getTableName())) {
$this->error('Schema ['.$this->getTableName().'] not found');
exit;
}
$modelPath = CatchAdmin::getModuleModelPath($this->argument('module'));
$file = $modelPath.$this->getModelFile();
if (File::exists($file)) {
$answer = $this->ask($file.' already exists, Did you want replace it?', 'Y');
if (! Str::of($answer)->lower()->exactly('y')) {
exit;
}
}
File::put($file, $this->getModelContent());
if (File::exists($file)) {
$this->info($file.' has been created');
} else {
$this->error($file.' create failed');
}
}
/**
*
*
* @return string
*/
protected function getModelFile(): string
{
return $this->getModelName().'.php';
}
/**
*
*
* @return string
*/
protected function getModelName(): string
{
return Str::of($this->argument('model'))->ucfirst()->toString();
}
/**
* get stub content
*
* @return string
*/
protected function getStubContent(): string
{
return File::get(dirname(__DIR__).DIRECTORY_SEPARATOR.'stubs'.DIRECTORY_SEPARATOR.'model.stub');
}
/**
* get model content
*
* @return string
*/
protected function getModelContent(): string
{
return Str::of($this->getStubContent())
->replace(
[
'{namespace}', '{model}', '{table}', '{fillable}'
],
[
$this->getModelNamespace(), $this->getModelName(),
$this->getTableName(), $this->getFillable()
]
)->toString();
}
/**
* get namespace
*
* @return string
*/
protected function getModelNamespace(): string
{
return trim(CatchAdmin::getModuleModelNamespace($this->argument('module')), '\\');
}
/**
* get table name
*
* @return string
*/
protected function getTableName(): string
{
return $this->option('t') ? $this->option('t') :
Str::of($this->argument('model'))
->snake()->lcfirst()->toString();
}
/**
*
*
* @return string
*/
protected function getFillable(): string
{
$fillable = Str::of('');
foreach (getTableColumns($this->getTableName()) as $column) {
$fillable = $fillable->append("'{$column}', ");
}
return $fillable->trim(',')->toString();
}
}

View File

@ -0,0 +1,316 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017 ~ now https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace Catch\Commands;
use Catch\CatchAdmin;
use Illuminate\Console\Application;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Database\Connectors\ConnectionFactory;
use Illuminate\Foundation\Bootstrap\LoadConfiguration;
use Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Catch\Support\Composer;
class InstallCommand extends CatchCommand
{
protected $signature = 'catch:install';
protected $description = 'install catch admin';
/**
* @var array|string[]
*/
private array $defaultExtensions = ['BCMath', 'Ctype', 'DOM', 'Fileinfo', 'JSON', 'Mbstring', 'OpenSSL', 'PCRE', 'PDO', 'Tokenizer', 'XML'];
/**
* handle
*
* @return void
*/
public function handle(): void
{
try {
$this->detectionEnvironment();
$this->copyEnvFile();
$this->askForCreatingDatabase();
$this->publishConfig();
$this->installed();
} catch (\Throwable $e) {
File::delete(app()->environmentFilePath());
$this->error($e->getMessage());
}
}
/**
* 环境检测
*
* @return void
*/
protected function detectionEnvironment(): void
{
$this->checkPHPVersion();
$this->checkExtensions();
}
/**
* check needed php extensions
*/
private function checkExtensions()
{
/* @var Collection $loadedExtensions */
$loadedExtensions = Collection::make(get_loaded_extensions())->map(function ($item) {
return strtolower($item);
});
Collection::make($this->defaultExtensions)
->each(function ($extension) use ($loadedExtensions, &$continue) {
$extension = strtolower($extension);
if (! $loadedExtensions->contains($extension)) {
$this->error("$extension extension 未安装");
}
});
}
/**
* check php version
*/
private function checkPHPVersion()
{
if (version_compare(PHP_VERSION, '8.1.0', '<')) {
// $this->error('php version should >= 8.1');
}
}
/**
* create database
*
* @param string $databaseName
* @return void
* @throws BindingResolutionException
*/
private function createDatabase(string $databaseName): void
{
$databaseConfig = config('database.connections.'.DB::getDefaultConnection());
$databaseConfig['database'] = null;
app(ConnectionFactory::class)->make($databaseConfig)->select(sprintf("create database if not exists $databaseName default charset %s collate %s", 'utf8mb4', 'utf8mb4_general_ci'));
}
/**
* copy .env
*
* @return void
*/
protected function copyEnvFile(): void
{
if (! File::exists(app()->environmentFilePath())) {
File::copy(app()->environmentFilePath().'.example', app()->environmentFilePath());
}
if (! File::exists(app()->environmentFilePath())) {
$this->error('【.env】创建失败, 请重新尝试或者手动创建!');
}
File::put(app()->environmentFile(), implode("\n", explode("\n", $this->getEnvFileContent())));
}
/**
* get env file content
*
* @return string
*/
protected function getEnvFileContent(): string
{
return File::get(app()->environmentFile());
}
/**
* publish config
*
* @return void
*/
protected function publishConfig(): void
{
// can't use Artisan::call, it will block the process, no reason found, just block!!!
exec(Application::formatCommandString('key:generate'));
exec(Application::formatCommandString('vendor:publish --tag=catch-config'));
exec(Application::formatCommandString('vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"'));
exec(Application::formatCommandString('jwt:secret'));
}
/**
* create database
*/
protected function askForCreatingDatabase()
{
$appUrl = $this->askFor('请配置应用的 URL');
if ($appUrl && ! Str::contains($appUrl, 'http://') && ! Str::contains($appUrl, 'https://')) {
$appUrl = 'http://'.$appUrl;
}
$databaseName = $this->askFor('请输入数据库名称');
$prefix = $this->askFor('请输入数据库表前缀', '');
$dbHost = $this->askFor('请输入数据库主机地址', '127.0.0.1');
$dbPort = $this->askFor('请输入数据的端口号', 3306);
$dbUsername = $this->askFor('请输入数据的用户名', 'root');
$dbPassword = $this->askFor('请输入数据库密码');
if (! $dbPassword) {
$dbPassword = $this->askFor('确认数据库密码为空吗?');
}
// set env
$env = explode("\n", $this->getEnvFileContent());
foreach ($env as &$value) {
foreach ([
'APP_URL' => $appUrl,
'DB_HOST' => $dbHost,
'DB_PORT' => $dbPort,
'DB_DATABASE' => $databaseName,
'DB_USERNAME' => $dbUsername,
'DB_PASSWORD' => $dbPassword,
'DB_PREFIX' => $prefix
] as $key => $newValue) {
if (Str::contains($value, $key)) {
$value = $this->resetEnvValue($value, $newValue);
}
}
}
// add vite config
$env[] = 'VITE_BASE_URL=${APP_URL}/api/';
File::put(app()->environmentFile(), implode("\n", $env));
app()->bootstrapWith([
LoadEnvironmentVariables::class,
LoadConfiguration::class
]);
$this->info("正在创建数据库[$databaseName]...");
$this->createDatabase($databaseName);
$this->info("创建数据库[$databaseName] 成功");
}
/**
* @param $originValue
* @param $newValue
* @return string
*/
protected function resetEnvValue($originValue, $newValue): string
{
if (Str::contains($originValue, '=')) {
$originValue = explode('=', $originValue);
$originValue[1] = $newValue;
return implode('=', $originValue);
}
return $originValue;
}
/**
* add prs4 autoload
*/
protected function addPsr4Autoload()
{
$composerFile = base_path().DIRECTORY_SEPARATOR.'composer.json';
$composerJson = json_decode(File::get(base_path().DIRECTORY_SEPARATOR.'composer.json'), true);
$composerJson['autoload']['psr-4'][CatchAdmin::getModuleRootNamespace()] = str_replace('\\', '/', config('catch.module.root'));
File::put($composerFile, json_encode($composerJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$this->info('composer dump autoload..., 请耐心等待');
app(Composer::class)->dumpAutoloads();
}
/**
* admin installed
*/
public function installed()
{
$this->addPsr4Autoload();
$this->info('🎉 CatchAdmin 已安装, 欢迎!');
$this->output->info(sprintf('
/------------------------ welcome ----------------------------\
| __ __ ___ __ _ |
| _________ _/ /______/ /_ / | ____/ /___ ___ (_)___ |
| / ___/ __ `/ __/ ___/ __ \ / /| |/ __ / __ `__ \/ / __ \ |
| / /__/ /_/ / /_/ /__/ / / / / ___ / /_/ / / / / / / / / / / |
| \___/\__,_/\__/\___/_/ /_/ /_/ |_\__,_/_/ /_/ /_/_/_/ /_/ |
| |
\ __ __ __ __ _ __ _ __ enjoy it ! _ __ __ __ __ __ __ ___ _ @
版本: %s
初始账号: catch@admin.com
初始密码: catchadmin', CatchAdmin::VERSION));
$this->support();
}
/**
* support
*
* @return void
*/
protected function support(): void
{
$answer = $this->askFor('支持我们! 感谢在 Github 上 star 该项目', 'yes', true);
if (in_array(strtolower($answer), ['yes', 'y'])) {
if (PHP_OS_FAMILY == 'Darwin') {
exec('open https://github.com/JaguarJack/catch-admin');
}
if (PHP_OS_FAMILY == 'Windows') {
exec('start https://github.com/JaguarJack/catch-admin');
}
if (PHP_OS_FAMILY == 'Linux') {
exec('xdg-open https://github.com/JaguarJack/catch-admin');
}
}
$this->info('支 持: https://github.com/jaguarjack/catchadmin');
$this->info('文 档: https://catchadmin.com/docs/3.0/intro');
$this->info('官 网: https://catchadmin.com');
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace Catch\Commands\Migrate;
use Catch\CatchAdmin;
use Catch\Commands\CatchCommand;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\File;
class MigrateFresh extends CatchCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'catch:migrate:fresh {module} {--force}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'catch migrate fresh';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle(): void
{
$module = $this->argument('module');
if (! File::isDirectory(CatchAdmin::getModuleMigrationPath($module))) {
Artisan::call('migration:fresh', [
'--path' => CatchAdmin::getModuleRelativePath(CatchAdmin::getModuleMigrationPath($module)),
'--force' => $this->option('force')
]);
} else {
$this->error('No migration files in module');
}
}
}

View File

@ -0,0 +1,91 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace Catch\Commands\Migrate;
use Catch\CatchAdmin;
use Catch\Commands\CatchCommand;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class MigrateMake extends CatchCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'catch:make:migration {module : The module of the migration created at}
{table : The name of the table to migration}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'create module migration';
/**
*
*
* @return void
*/
public function handle(): void
{
$migrationPath = CatchAdmin::getModuleMigrationPath($this->argument('module'));
$file = $migrationPath.$this->getMigrationFile();
File::put($file, Str::of($this->getStubContent())->replace(
'{table}',
$this->getTable()
)->toString());
if (File::exists($file)) {
$this->info($file.' has been created');
} else {
$this->error($file.' create failed');
}
}
/**
*
*
* @return string
*/
protected function getMigrationFile(): string
{
return date('Y_m_d_His').'_create_'.$this->getTable().'.php';
}
/**
*
*
* @return string
*/
protected function getTable(): string
{
return Str::of($this->argument('table'))->ucfirst()->snake()->lower()->toString();
}
/**
* get stub content
*
* @return string
*/
protected function getStubContent(): string
{
return File::get(dirname(__DIR__).DIRECTORY_SEPARATOR.'stubs'.DIRECTORY_SEPARATOR.'migration.stub');
}
}

View File

@ -0,0 +1,74 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace Catch\Commands\Migrate;
use Catch\CatchAdmin;
use Catch\Commands\CatchCommand;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class MigrateRun extends CatchCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'catch:migrate {module} {--force}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'migrate catch module';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle(): void
{
$module = $this->argument('module');
if (File::isDirectory(CatchAdmin::getModuleMigrationPath($module))) {
foreach (File::files(CatchAdmin::getModuleMigrationPath($module)) as $file) {
$path = Str::of(CatchAdmin::getModuleRelativePath(CatchAdmin::getModuleMigrationPath($module)))
->remove('.')->append($file->getFilename());
Artisan::call('migrate', [
'--path' => $path,
'--force' => $this->option('force')
]);
}
$this->info("Module [$module] migrate success");
} else {
$this->error('No migration files in module');
}
}
}

View File

@ -0,0 +1,65 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace Catch\Commands\Migrate;
use Catch\CatchAdmin;
use Catch\Commands\CatchCommand;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\File;
class MigrationRollback extends CatchCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'catch:migrate:rollback {module} {--force}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'rollback module tables';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle(): void
{
$module = $this->argument('module');
if (! File::isDirectory(CatchAdmin::getModuleMigrationPath($module))) {
Artisan::call('migration:rollback', [
'--path' => CatchAdmin::getModuleRelativePath(CatchAdmin::getModuleMigrationPath($module)),
'--force' => $this->option('force')
]);
} else {
$this->error('No migration files in module');
}
}
}

View File

@ -0,0 +1,88 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace Catch\Commands\Migrate;
use Catch\CatchAdmin;
use Catch\Commands\CatchCommand;
use Illuminate\Support\Facades\File;
class SeedRun extends CatchCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'catch:db:seed {module} {--class=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'catch db seed';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle(): void
{
$classes = $this->loadModuleSeeders();
if ($class = $this->option('class')) {
(new $class())->run();
} else {
foreach ($classes as $class) {
$class = new $class();
if (method_exists($class, 'run')) {
$class->run();
}
}
}
$this->info('Seed run successfully');
}
/**
*
* @time 2021年07月31日
* @return array
*/
protected function loadModuleSeeders(): array
{
$files = File::allFiles(CatchAdmin::getModuleSeederPath($this->argument('module')));
$fileNames = [];
foreach ($files as $file) {
require_once $file->getRealPath();
$fileNames[] = pathinfo($file->getBasename(), PATHINFO_FILENAME);
}
return $fileNames;
}
}

View File

@ -0,0 +1,88 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace Catch\Commands\Migrate;
use Catch\CatchAdmin;
use Catch\Commands\CatchCommand;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use PhpParser\Node\Name;
class SeederMake extends CatchCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'catch:make:seeder {module} {name}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'make module seeder';
/**
*
* @return void
* @throws \Exception
* @author CatchAdmin
* @time 2021年08月01日
*/
public function handle(): void
{
$seederPath = CatchAdmin::getModuleSeederPath($this->argument('module'));
$file = $seederPath.$this->getSeederName().'.php';
if (File::exists($file)) {
$answer = $this->ask($file.' already exists, Did you want replace it?', 'Y');
if (! Str::of($answer)->lower()->exactly('y')) {
exit;
}
}
File::put($file, $this->getSeederContent());
if (File::exists($file)) {
$this->info($file.' has been created');
} else {
$this->error($file.' create failed');
}
}
/**
* seeder content
*
* @return string
* @throws \Exception
*/
protected function getSeederContent(): string
{
return File::get(dirname(__DIR__).DIRECTORY_SEPARATOR.'stubs'.DIRECTORY_SEPARATOR.'seeder.stub');
}
/**
* seeder name
*
* @return string
*/
protected function getSeederName(): string
{
return Str::of($this->argument('name'))->ucfirst()->toString();
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace {namespace};
use Catch\Base\CatchController;
use Illuminate\Http\Request;
class {controller} extends CatchController
{
public function index(Request $request)
{
}
public function store(Request $request)
{
}
public function show($id)
{
}
public function update($id, Request $request)
{
}
public function destroy($id)
{
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace {namespace};
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class {event}
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(): void
{
//
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}

View File

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

View File

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

View File

@ -0,0 +1,16 @@
<?php
namespace {namespace};
use Catch\Base\CatchModel as Model;
class {model} extends Model
{
protected $table = '{table}';
protected $fillable = [
{fillable}
];
}

View File

@ -0,0 +1,18 @@
<?php
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
return new class extends Seeder
{
/**
* Run the seeder.
*
* @return void
*/
public function run(): void
{
}
};

View File

@ -0,0 +1,35 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Contracts;
use Illuminate\Support\Collection;
interface ModuleRepositoryInterface
{
public function all(array $search): Collection;
public function create(array $module): bool|int;
public function show(string $name): Collection;
public function update(string $name, array $module): bool|int;
public function delete(string $name): bool|int;
public function disOrEnable(string $name): bool|int;
public function getEnabled(): Collection;
}

79
catch/src/Enums/Code.php Normal file
View File

@ -0,0 +1,79 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace Catch\Enums;
enum Code: int implements Enum
{
case SUCCESS = 10000; // 成功
case LOST_LOGIN = 10001; // 登录失效
case VALIDATE_FAILED = 10002; // 验证错误
case PERMISSION_FORBIDDEN = 10003; // 权限禁止
case LOGIN_FAILED = 10004; // 登录失败
case FAILED = 10005; // 操作失败
case LOGIN_EXPIRED = 10006; // 登录失效
case LOGIN_BLACKLIST = 10007; // 黑名单
case USER_FORBIDDEN = 10008; // 账户被禁
case WECHAT_RESPONSE_ERROR = 40000;
/**
* message
*
*/
public function message(): string
{
return $this->name();
}
/**
* get value
*
* @return int
*/
public function value(): int
{
return match ($this) {
Code::SUCCESS => 10000,
Code::LOST_LOGIN => 10001,
Code::VALIDATE_FAILED => 10002,
Code::PERMISSION_FORBIDDEN => 10003,
Code::LOGIN_FAILED => 10004,
Code::FAILED => 10005,
Code::LOGIN_EXPIRED => 10006,
Code::LOGIN_BLACKLIST => 10007,
Code::USER_FORBIDDEN => 10008,
Code::WECHAT_RESPONSE_ERROR => 40000,
};
}
/**
* name
*
* @return string
*/
public function name(): string
{
return match ($this) {
self::SUCCESS => '操作成功',
self::LOST_LOGIN => '登陆失效',
self::VALIDATE_FAILED => '验证失败',
self::PERMISSION_FORBIDDEN => '权限禁止',
self::LOGIN_FAILED => '登陆失败',
self::FAILED => '操作失败',
self::LOGIN_EXPIRED => '登陆过期',
self::LOGIN_BLACKLIST => '已被加入黑名单',
self::USER_FORBIDDEN => '账户被禁用',
self::WECHAT_RESPONSE_ERROR => '微信响应错误'
};
}
}

10
catch/src/Enums/Enum.php Normal file
View File

@ -0,0 +1,10 @@
<?php
namespace Catch\Enums;
interface Enum
{
public function value(): int;
public function name(): string;
}

View File

@ -0,0 +1,49 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Enums;
enum Status: int implements Enum
{
case Enable = 1;
case Disable = 2;
/**
* @desc name
*
*/
public function name(): string
{
return match ($this) {
Status::Enable => '启用',
Status::Disable => '禁用'
};
}
/**
* get value
*
* @return int
*/
public function value(): int
{
return match ($this) {
Status::Enable => 1,
Status::Disable => 2,
};
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Catch\Events\Module;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class Created
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(public array $module)
{
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Catch\Events\Module;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class Creating
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(public array $module)
{
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace Catch\Events\Module;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
class Deleted
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(public Collection $module)
{
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Catch\Events\Module;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class Updated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(public string $originName, public array $module)
{
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Catch\Events\Module;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class Updating
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(public string $originName, public array $module)
{
}
}

27
catch/src/Events/User.php Normal file
View File

@ -0,0 +1,27 @@
<?php
namespace Catch\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class User
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public Authenticatable|Model $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Authenticatable|Model $user)
{
//
$this->user = $user;
}
}

View File

@ -0,0 +1,65 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Exceptions;
use Catch\Enums\Enum;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Catch\Enums\Code;
abstract class CatchException extends HttpException
{
protected $code = 0;
/**
* @param string $message
* @param int|Code $code
*/
public function __construct(string $message = '', int|Code $code = 0)
{
if ($code instanceof Enum) {
$code = $code->value();
}
if ($this->code instanceof Enum && ! $code) {
$code = $this->code->value();
}
parent::__construct($this->statusCode(), $message ?: $this->message, null, [], $code);
}
/**
* status code
*
* @return int
*/
public function statusCode(): int
{
return 500;
}
/**
* render
*
* @return array
*/
public function render(): array
{
return [
'code' => $this->code,
'message' => $this->message
];
}
}

View File

@ -0,0 +1,22 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Exceptions;
use Catch\Enums\Code;
class FailedException extends CatchException
{
protected $code = Code::FAILED;
}

View File

@ -0,0 +1,34 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
/**
* register
*
* @return void
*/
public function register(): void
{
if (config('catch')) {
$this->dontReport = config('catch.exception.dont_report');
$this->dontFlash = config('catch.exception.dont_flash');
}
}
}

View File

@ -0,0 +1,22 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Exceptions;
use Catch\Enums\Code;
class UnMatchedTokenException extends CatchException
{
protected $code = Code::FAILED;
}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace Catch\Facade;
use Illuminate\Support\Facades\Facade;
/**
* @method static all()
* @method static create(array $module)
* @method static update(string $name, array $module)
* @method static delete(string $name)
* @method static disOrEnable(string $name)
*
* @see ModuleRepository
* Class Module
*/
class Module extends Facade
{
public static function getFacadeAccessor(): string
{
return 'module';
}
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Catch\Facade;
use Illuminate\Support\Facades\Facade;
use Catch\Support\Zip\Zipper as Zip;
/**
* @method static Zip make(string $pathToFile)
* @method static Zip zip(string $pathToFile)
* @method static Zip phar(string $pathToFile)
*
* @see Zipper
* Class Module
*/
class Zipper extends Facade
{
public static function getFacadeAccessor(): string
{
return Zip::class;
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace Catch\Listeners;
use Catch\Enums\Code;
use Illuminate\Foundation\Http\Events\RequestHandled;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
use Illuminate\Http\JsonResponse;
class RequestHandledListener
{
/**
* Handle the event.
*
* @param RequestHandled $event
* @return void
*/
public function handle(RequestHandled $event): void
{
$response = $event->response;
if ($response instanceof JsonResponse) {
$exception = $response->exception;
if ($response->getStatusCode() == SymfonyResponse::HTTP_OK && ! $exception) {
$response->setData($this->formatData($response->getData()));
}
}
}
/**
* @param mixed $data
* @return array
*/
protected function formatData(mixed $data): array
{
$responseData = [
'code' => Code::SUCCESS->value(),
'message' => Code::SUCCESS->message(),
];
if (is_object($data) && property_exists($data, 'per_page')
&& property_exists($data, 'total')
&& property_exists($data, 'current_page')) {
$responseData['data'] = $data->data;
$responseData['total'] = $data->total;
$responseData['limit'] = $data->per_page;
$responseData['page'] = $data->current_page;
return $responseData;
}
$responseData['data'] = $data;
return $responseData;
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace Catch\Middleware;
use Catch\Enums\Code;
use Catch\Events\User as UserEvent;
use Catch\Exceptions\FailedException;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Event;
use Throwable;
use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
class AuthMiddleware
{
public function handle(Request $request, \Closure $next)
{
try {
$guardName = getGuardName();
if (Auth::guard($guardName)->check()) {
$user = Auth::guard($guardName)->user();
Event::dispatch(new UserEvent($user));
}
} catch (Exception|Throwable $e) {
if ($e instanceof TokenExpiredException) {
throw new FailedException(Code::LOGIN_EXPIRED->message(), Code::LOGIN_EXPIRED);
}
if ($e instanceof TokenBlacklistedException) {
throw new FailedException(Code::LOGIN_BLACKLIST->message(), Code::LOGIN_BLACKLIST);
}
throw new FailedException(Code::LOST_LOGIN->message().":{$e->getMessage()}", Code::LOST_LOGIN);
} finally {
return $next($request);
}
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Catch\Middleware;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class JsonResponseMiddleware
{
public function handle(Request $request, \Closure $next)
{
$response = $next($request);
if ($response instanceof Response) {
return new JsonResponse($response->getContent());
}
return $response;
}
}

View File

@ -0,0 +1,229 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017 ~ now https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace Catch\Providers;
use Catch\CatchAdmin;
use Catch\Contracts\ModuleRepositoryInterface;
use Catch\Exceptions\Handler;
use Catch\Support\DB\Query;
use Catch\Support\Module\ModuleManager;
use Illuminate\Container\Container;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Foundation\Http\Events\RequestHandled;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use ReflectionException;
use Catch\Support\Macros\Register as MacrosRegister;
/**
* CatchAmin Service Provider
*/
class CatchAdminServiceProvider extends ServiceProvider
{
/**
* boot
*
* @return void
* @throws NotFoundExceptionInterface
* @throws ContainerExceptionInterface
*/
public function boot(): void
{
$this->bootDefaultModuleProviders();
$this->bootModuleProviders();
$this->registerEvents();
$this->listenDBLog();
$this->mergeAuthConfig();
// $this->registerExceptionHandler();
MacrosRegister::boot();
}
/**
* register
*
* @return void
* @throws ReflectionException
*/
public function register(): void
{
$this->registerCommands();
$this->registerModuleRepository();
$this->publishConfig();
$this->publishModuleMigration();
}
/**
* register commands
*
* @return void
* @throws ReflectionException
*/
protected function registerCommands(): void
{
loadCommands(dirname(__DIR__).DIRECTORY_SEPARATOR.'Commands', 'Catch\\');
}
/**
* register exception handler
*
* @return void
*/
protected function registerExceptionHandler(): void
{
$this->app->singleton(
ExceptionHandler::class,
Handler::class
);
}
/**
* bind module repository
*
* @return void
*/
protected function registerModuleRepository(): void
{
// register module manager
$this->app->singleton(ModuleManager::class, function () {
return new ModuleManager(fn () => Container::getInstance());
});
// register module repository
$this->app->singleton(ModuleRepositoryInterface::class, function () {
return $this->app->make(ModuleManager::class)->driver();
});
$this->app->alias(ModuleRepositoryInterface::class, 'module');
}
/**
* register events
*
* @return void
*/
protected function registerEvents(): void
{
Event::listen(RequestHandled::class, config('catch.response.request_handled_listener'));
}
/**
* publish config
*
* @return void
*/
protected function publishConfig(): void
{
if ($this->app->runningInConsole()) {
$from = dirname(__DIR__, 2).DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'catch.php';
$to = config_path('catch.php');
$this->publishes([$from => $to], 'catch-config');
}
}
/**
* publish module migration
*
* @return void
*/
protected function publishModuleMigration(): void
{
if ($this->app->runningInConsole()) {
$form = dirname(__DIR__, 2).DIRECTORY_SEPARATOR.'database'.DIRECTORY_SEPARATOR.'migrations'.DIRECTORY_SEPARATOR.'2022_11_14_034127_module.php';
$to = database_path('migrations').DIRECTORY_SEPARATOR.'2022_11_14_034127_module.php';
$this->publishes([$form => $to], 'catch-module');
}
}
/**
*
* @return void
* @throws NotFoundExceptionInterface
* @throws ContainerExceptionInterface
*/
protected function bootDefaultModuleProviders(): void
{
foreach ($this->app['config']->get('catch.module.default') as $module) {
$provider = CatchAdmin::getModuleServiceProvider($module);
if (class_exists($provider)) {
$this->app->register($provider);
}
}
}
/**
* boot module
*
* @throws BindingResolutionException
*/
protected function bootModuleProviders()
{
foreach ($this->app->make(ModuleRepositoryInterface::class)->getEnabled() as $module) {
if (class_exists($module['service'])) {
$this->app->register($module['service']);
}
}
}
/**
* listen db log
*
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @return void
*/
protected function listenDBLog(): void
{
if ($this->app['config']->get('catch.listen_db_log')) {
Query::listen();
$this->app->terminating(function () {
Query::log();
});
}
}
/**
* merge auth config
*
* @throws BindingResolutionException
* @return void
*/
protected function mergeAuthConfig(): void
{
if (! $this->app->configurationIsCached()) {
$config = $this->app->make('config');
$config->set('auth', array_merge_recursive(
$config->get('catch.auth', []),
$config->get('auth', [])
));
}
}
}

View File

@ -0,0 +1,63 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017 ~ now https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace Catch\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
abstract class CatchModuleServiceProvider extends ServiceProvider
{
protected array $events = [];
/**
* register
*
* @return void
* @throws NotFoundExceptionInterface
* @throws ContainerExceptionInterface
*/
public function boot(): void
{
$this->registerModuleRoute();
foreach ($this->events as $event => $listener) {
Event::listen($event, $listener);
}
}
/**
* load module router
*
* @return void
* @throws NotFoundExceptionInterface
* @throws ContainerExceptionInterface
*/
protected function registerModuleRoute(): void
{
$route = $this->app['config']->get('catch.route');
Route::prefix($route['prefix'])
->middleware($route['middlewares'])
->group($this->routePath());
}
/**
* route path
*
* @return string|array
*/
abstract protected function routePath(): string | array;
}

View File

@ -0,0 +1,108 @@
<?php
namespace Catch\Support;
use Illuminate\Support\Composer as LaravelComposer;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\File;
use Laravel\SerializableClosure\Exceptions\PhpVersionNotSupportedException;
class Composer extends LaravelComposer
{
protected bool $ignorePlatformReqs = false;
/**
* require package
* @param string $package
* @return string
* @throws PhpVersionNotSupportedException
*/
public function require(string $package): string
{
$this->checkPHPVersion();
$command = ['require', $package];
return $this->runCommand($command);
}
/**
* require dev-package
*
* @param string $package
* @return string
* @throws PhpVersionNotSupportedException
*/
public function requireDev(string $package): string
{
$this->checkPHPVersion();
$command = ['require', '--dev', $package];
return $this->runCommand($command);
}
/**
* remove
*
* @param string $package
*/
public function remove(string $package)
{
$this->runCommand([
'remove', $package
]);
}
/**
*
* @param array $command
* @return string
*/
protected function runCommand(array $command): string
{
$command = array_merge($this->findComposer(), $command);
if ($this->ignorePlatformReqs) {
$command[] = '--ignore-platform-reqs';
}
$process = $this->getProcess($command);
$process->run();
return $process->getOutput();
}
/**
*
* @throws PhpVersionNotSupportedException
* @return void
*/
protected function checkPHPVersion(): void
{
$composerJson = json_decode(File::get(base_path().DIRECTORY_SEPARATOR.'composer.json'), true);
$phpVersion = PHP_VERSION;
$needPHPVersion = Str::of($composerJson['require']['php'])->remove('^');
if (version_compare($phpVersion, $needPHPVersion, '<') && ! $this->ignorePlatformReqs) {
throw new PhpVersionNotSupportedException("PHP $phpVersion 版本太低, 需要 PHP {$needPHPVersion}!如果想忽略版本要求, s可使用 {ignorePlatFormReqs} 方法然后安装");
}
}
/**
*
* @return $this
*/
public function ignorePlatFormReqs(): static
{
$this->ignorePlatformReqs = true;
return $this;
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace Catch\Support\DB;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
class Query
{
/**
* @var string|null
*/
protected static string|null $log = null;
/**
* @return void
*/
public static function listen(): void
{
DB::listen(function ($query) {
$sql = str_replace(
'?',
'%s',
sprintf('[%s] '.$query->sql.' | %s ms'.PHP_EOL, date('Y-m-d H:i'), $query->time)
);
static::$log .= vsprintf($sql, $query->bindings);
});
}
/**
* @return void
*/
public static function log(): void
{
if (static::$log) {
$sqlLogPath = storage_path('logs'.DIRECTORY_SEPARATOR.'query'.DIRECTORY_SEPARATOR);
if (! File::isDirectory($sqlLogPath)) {
File::makeDirectory($sqlLogPath, 0777, true);
}
$logFile = $sqlLogPath.date('Ymd').'.log';
if (! File::exists($logFile)) {
File::put($logFile, '', true);
}
file_put_contents($logFile, static::$log.PHP_EOL, LOCK_EX | FILE_APPEND);
static::$log = null;
}
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Catch\Support\DB;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class SoftDelete extends SoftDeletingScope
{
/**
* @param Builder $builder
* @param Model $model
*/
public function apply(Builder $builder, Model $model)
{
$builder->where($model->getQualifiedDeletedAtColumn(), '=', 0);
}
}

View File

@ -0,0 +1,140 @@
<?php
declare(strict_types=1);
namespace Catch\Support\Macros;
use Illuminate\Database\Schema\Blueprint as LaravelBlueprint;
class Blueprint
{
/**
* boot;
*/
public static function boot(): void
{
$bluePrint = new static();
$bluePrint->createdAt();
$bluePrint->updatedAt();
$bluePrint->deletedAt();
$bluePrint->status();
$bluePrint->creatorId();
$bluePrint->unixTimestamp();
$bluePrint->parentId();
$bluePrint->sort();
}
/**
* created unix timestamp
*
* @return void
*/
public function createdAt(): void
{
LaravelBlueprint::macro(__FUNCTION__, function () {
$this->unsignedInteger('created_at')->default(0)->comment('created time');
});
}
/**
* update unix timestamp
*
* @return void
*/
public function updatedAt(): void
{
LaravelBlueprint::macro(__FUNCTION__, function () {
$this->unsignedInteger('updated_at')->default(0)->comment('updated time');
});
}
/**
* soft delete
*
* @return void
*/
public function deletedAt(): void
{
LaravelBlueprint::macro(__FUNCTION__, function () {
$this->unsignedInteger('deleted_at')->default(0)->comment('delete time');
});
}
/**
* unix timestamp
*
* @param bool $softDeleted
* @return void
*/
public function unixTimestamp(bool $softDeleted = true): void
{
LaravelBlueprint::macro(__FUNCTION__, function () use ($softDeleted) {
$this->createdAt();
$this->updatedAt();
if ($softDeleted) {
$this->deletedAt();
}
});
}
/**
* creator id
*
* @return void
*/
public function creatorId(): void
{
LaravelBlueprint::macro(__FUNCTION__, function () {
$this->unsignedInteger('creator_id')->default(0)->comment('creator id');
});
}
/**
* parent ID
*
* @return void
*/
public function parentId(): void
{
LaravelBlueprint::macro(__FUNCTION__, function () {
$this->unsignedInteger('parent_id')->default(0)->comment('parent id');
});
}
/**
* status
*
* @return void
*/
public function status(): void
{
LaravelBlueprint::macro(__FUNCTION__, function ($default = 1) {
$this->tinyInteger('status')->default($default)->comment('1:normal 2: forbidden');
});
}
/**
* sort
*
* @param int $default
* @return void
*/
public function sort(int $default = 1): void
{
LaravelBlueprint::macro(__FUNCTION__, function () use ($default) {
$this->integer('sort')->comment('sort')->default($default);
});
}
}

View File

@ -0,0 +1,107 @@
<?php
declare(strict_types=1);
namespace Catch\Support\Macros;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Builder as LaravelBuilder;
class Builder
{
/**
* boot
*/
public static function boot(): void
{
$builder = new static();
$builder->whereLike();
$builder->quickSearch();
$builder->tree();
}
/**
* where like
*
* @return void
*/
public function whereLike(): void
{
LaravelBuilder::macro(__FUNCTION__, function ($filed, $value) {
return $this->where($filed, 'like', "%$value%");
});
}
/**
* quick search
*
* @return void
*/
public function quickSearch(): void
{
LaravelBuilder::macro(__FUNCTION__, function (array $params = []) {
$params = array_merge(request()->all(), $params);
if (! property_exists($this->model, 'searchable')) {
return $this;
}
// filter null & empty string
$params = array_filter($params, function ($value) {
return (is_string($value) && strlen($value)) || is_numeric($value);
});
$wheres = [];
if (! empty($this->model->searchable)) {
foreach ($this->model->searchable as $field => $op) {
// 临时变量
$_field = $field;
// contains alias
if (str_contains($field, '.')) {
[, $_field] = explode('.', $field);
}
if (isset($params[$_field])) {
$opString = Str::of($op)->lower();
if ($opString->exactly('op')) {
$value = implode(',', $params[$_field]);
} elseif ($opString->exactly('like')) {
$value = "%{$params[$_field]}%";
} elseif ($opString->exactly('rlike')) {
$value = "{$params[$_field]}%";
} elseif ($opString->exactly('llike')) {
$value = "%{$params[$_field]}";
} else {
$value = $params[$_field];
}
$wheres[] = [$field, $op, $value];
}
}
}
$this->where($wheres);
return $this;
});
}
/**
* where like
*
* @time 2021年08月06日
* @return void
*/
public function tree(): void
{
LaravelBuilder::macro(__FUNCTION__, function (string $id, string $parentId, ...$fields) {
$fields = array_merge([$id, $parentId], $fields);
return $this->get($fields)->toTree(0, $parentId);
});
}
}

View File

@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
namespace Catch\Support\Macros;
use Catch\Support\Tree;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Collection as LaravelCollection;
class Collection
{
/**
* boot
*/
public static function boot(): void
{
$collection = new static();
$collection->toOptions();
$collection->toTree();
}
/**
* collection to tree
*
* @return void
*/
public function toTree(): void
{
LaravelCollection::macro(__FUNCTION__, function (int $pid = 0, string $pidField = 'parent_id', string $child = 'children') {
return Tree::done($this->all(), $pid, $pidField, $child);
});
}
/**
* toOptions
*
* @return void
*/
public function toOptions(): void
{
LaravelCollection::macro(__FUNCTION__, function () {
return $this->transform(function ($item, $key) use (&$options) {
if ($item instanceof Arrayable) {
$item = $item->toArray();
}
if (is_array($item)) {
$item = array_values($item);
return [
'value' => $item[0],
'label' => $item[1]
];
} else {
return [
'value' => $key,
'label' => $item
];
}
})->values();
});
}
}

View File

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace Catch\Support\Macros;
/**
* boot
*/
class Register
{
/**
* macros boot
*/
public static function boot(): void
{
Blueprint::boot();
Collection::boot();
Builder::boot();
}
}

View File

@ -0,0 +1,171 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Support\Module\Driver;
use Catch\CatchAdmin;
use Catch\Contracts\ModuleRepositoryInterface;
use Catch\Enums\Status;
use Catch\Exceptions\FailedException;
use Illuminate\Container\Container;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
/**
* DatabaseDriver
*/
class DatabaseDriver implements ModuleRepositoryInterface
{
protected Model $model;
public function __construct()
{
$this->model = $this->createModuleModel();
}
/**
* all
*
* @param array $search
* @return Collection
*/
public function all(array $search): Collection
{
return $this->model::query()
->when($search['name'] ?? false, function ($query) use ($search) {
$query->where('name', 'like', '%'.$search['name'].'%');
})->get();
}
/**
* create module json
*
* @param array $module
* @return bool|int
*/
public function create(array $module): bool|int
{
$this->hasSameModule($module);
return $this->model->save([
'name' => $module['name'],
'path' => $module['path'],
'description' => $module['desc'],
'keywords' => $module['keywords'],
'service' => sprintf('\\%s%s', CatchAdmin::getModuleNamespace($module['name']), ucfirst($module['name']).'ServiceProvider'),
]);
}
/**
* module info
*
* @param string $name
* @return Collection
*/
public function show(string $name): Collection
{
return $this->model->where('name', $name)->first();
}
/**
* update module json
*
* @param string $name
* @param array $module
* @return bool|int
*/
public function update(string $name, array $module): bool|int
{
return $this->model->where('name', $name)
->update([
'name' => $module['name'],
'alias' => $module['alias'],
'description' => $module['desc'],
'keywords' => $module['keywords'],
]);
}
/**
* delete module json
*
* @param string $name
* @return bool|int
*/
public function delete(string $name): bool|int
{
return $this->model->where('name', $name)->delete();
}
/**
* disable or enable
*
* @param $name
* @return bool|int
*/
public function disOrEnable($name): bool|int
{
$module = $this->show($name);
$module->status = (int) $module->status;
return $module->save();
}
/**
* get enabled
*
* @return Collection
*/
public function getEnabled(): Collection
{
// TODO: Implement getEnabled() method.
return $this->model->where('status', Status::Enable->value())->get();
}
/**
*
* @param array $module
* @return void
*/
protected function hasSameModule(array $module): void
{
if ($this->model->where('name', $module['name'])->first()) {
throw new FailedException(sprintf('Module [%s] has been created', $module['name']));
}
if ($this->model->where('alias', $module['alias'])->first()) {
throw new FailedException(sprintf('Module Alias [%s] has been exised', $module['alias']));
}
}
/**
* create model
* @return Model
*/
protected function createModuleModel(): Model
{
return new class () extends Model {
protected $table;
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
$this->table = Container::getInstance()->make('config')->get('catch.module.driver.table_name');
}
};
}
}

View File

@ -0,0 +1,193 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Support\Module\Driver;
use Catch\CatchAdmin;
use Catch\Contracts\ModuleRepositoryInterface;
use Catch\Exceptions\FailedException;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
/**
* FileDriver
*/
class FileDriver implements ModuleRepositoryInterface
{
protected string $moduleJson;
/**
* construct
*/
public function __construct()
{
$this->moduleJson = storage_path('app').DIRECTORY_SEPARATOR.'modules.json';
}
/**
* all
*
* @param array $search
* @return Collection
*/
public function all(array $search = []): Collection
{
if (! File::exists($this->moduleJson)) {
return Collection::make([]);
}
if (! Str::length(File::get($this->moduleJson))) {
return Collection::make([]);
}
$modules = Collection::make(\json_decode(File::get($this->moduleJson), true))->values();
$name = $search['name'] ?? '';
if (! $name) {
return $modules;
}
return $modules->filter(function ($module) use ($name) {
return Str::of($module['name'])->contains($name);
});
}
/**
* create module json
*
* @param array $module
* @return bool
*/
public function create(array $module): bool
{
$modules = $this->all();
$this->hasSameModule($module, $modules);
$module['service'] = sprintf('\\%s', CatchAdmin::getModuleServiceProvider($module['path']));
$module['version'] = '1.0.0';
$module['enable'] = true;
File::put($this->moduleJson, $modules->push($module)->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
return true;
}
/**
* module info
*
* @param string $name
* @return Collection
*/
public function show(string $name): Collection
{
foreach ($this->all() as $module) {
if (Str::of($module['name'])->exactly($name)) {
return Collection::make($module);
}
}
throw new FailedException("Module [$name] not Found");
}
/**
* update module json
*
* @param string $name
* @param array $module
* @return bool
*/
public function update(string $name, array $module): bool
{
File::put($this->moduleJson, $this->all()->map(function ($m) use ($module, $name) {
if (Str::of($name)->exactly($m['name'])) {
$m['path'] = $module['path'];
$m['name'] = $module['name'];
$m['description'] = $module['description'] ?? '';
$m['keywords'] = $module['keywords'] ?? '';
$m['enable'] = $module['enable'];
}
return $m;
})->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
return true;
}
/**
* delete module json
*
* @param string $name
* @return bool
*/
public function delete(string $name): bool
{
File::put($this->moduleJson, $this->all()->filter(function ($module) use ($name) {
if (! Str::of($name)->exactly($module['name'])) {
return $module;
}
})->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
return true;
}
/**
* disable or enable
*
* @param $name
* @return bool|int
*/
public function disOrEnable($name): bool|int
{
return File::put($this->moduleJson, $this->all()->map(function ($module) use ($name) {
if (Str::of($module['name'])->exactly($name)) {
$module['enable'] = ! $module['enable'];
}
return $module;
})->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
}
/**
* get enabled
*
* @return Collection
*/
public function getEnabled(): Collection
{
// TODO: Implement getEnabled() method.
return $this->all()->where('enable', true)->values();
}
/**
*
* @param array $module
* @param Collection $modules
* @return void
*/
protected function hasSameModule(array $module, Collection $modules): void
{
if ($modules->count()) {
if ($modules->pluck('name')->contains($module['name'])) {
throw new FailedException(sprintf('Module [%s] has been created', $module['name']));
}
if ($modules->pluck('path')->contains($module['path'])) {
throw new FailedException(sprintf('Module path [%s] has been existed', $module['path']));
}
}
}
}

View File

@ -0,0 +1,97 @@
<?php
namespace Catch\Support\Module;
use Catch\Contracts\ModuleRepositoryInterface;
use Catch\Support\Composer;
/**
* installer
*/
abstract class Installer
{
/**
* construct
*
* @param ModuleRepositoryInterface $moduleRepository
*/
public function __construct(protected ModuleRepositoryInterface $moduleRepository)
{
}
/**
* module info
*
* @return array
*/
abstract protected function info(): array;
/**
* migration
*
* @return string
*/
abstract protected function migration(): string;
/**
* seed
*
* @return string
*/
abstract protected function seeder(): string;
/**
* require packages
*
* @return void
*/
abstract protected function requirePackages(): void;
/**
* remove packages
*
* @return void
*/
abstract protected function removePackages(): void;
/**
* uninstall
*
* @return void
*/
public function uninstall(): void
{
$this->moduleRepository->delete($this->info()['name']);
$this->removePackages();
}
/**
* invoke
*
* @return void
*/
public function __invoke(): void
{
// TODO: Implement __invoke() method.
$this->moduleRepository->create($this->info());
// migration
// seed
$this->requirePackages();
}
/**
* composer installer
*
* @return Composer
*/
protected function composer(): Composer
{
return app(Composer::class);
}
}

View File

@ -0,0 +1,63 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Support\Module;
use Catch\Support\Module\Driver\DatabaseDriver;
use Catch\Support\Module\Driver\FileDriver;
use Illuminate\Contracts\Container\Container;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Manager;
class ModuleManager extends Manager
{
public function __construct(Container|\Closure $container)
{
if ($container instanceof \Closure) {
$container = $container();
}
parent::__construct($container);
}
/**
* @return string
*/
public function getDefaultDriver(): string
{
// TODO: Implement getDefaultDriver() method.
return $this->config->get('catch.module.driver.default');
}
/**
* create file driver
*
* @return FileDriver
*/
public function createFileDriver(): FileDriver
{
return new FileDriver();
}
/**
* create database driver
*
* @return DatabaseDriver
*/
public function createDatabaseDriver(): DatabaseDriver
{
return new DatabaseDriver();
}
}

View File

@ -0,0 +1,144 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Support\Module;
use Catch\Contracts\ModuleRepositoryInterface;
use Catch\Events\Module\Created;
use Catch\Events\Module\Creating;
use Catch\Events\Module\Deleted;
use Catch\Events\Module\Updated;
use Catch\Events\Module\Updating;
use Exception;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Event;
/**
* FileDriver
*/
class ModuleRepository
{
protected ModuleRepositoryInterface $moduleRepository;
/**
* construct
*/
public function __construct(ModuleRepositoryInterface $moduleRepository)
{
$this->moduleRepository = $moduleRepository;
}
/**
* all
*
* @param array $search
* @return Collection
*/
public function all(array $search): Collection
{
return $this->moduleRepository->all($search);
}
/**
* create module json
*
* @param array $module
* @return bool
*/
public function create(array $module): bool
{
Event::dispatch(new Creating($module));
$this->moduleRepository->create($module);
Event::dispatch(new Created($module));
return true;
}
/**
* module info
*
* @param string $name
* @return Collection
* @throws Exception
*/
public function show(string $name): Collection
{
try {
return $this->moduleRepository->show($name);
} catch (Exception $e) {
throw new $e();
}
}
/**
* update module json
*
* @param string $name
* @param array $module
* @return bool
*/
public function update(string $name, array $module): bool
{
Event::dispatch(new Updating($name, $module));
$this->moduleRepository->update($name, $module);
Event::dispatch(new Updated($name, $module));
return true;
}
/**
* delete module json
*
* @param string $name
* @return bool
* @throws Exception
*/
public function delete(string $name): bool
{
$module = $this->show($name);
$this->moduleRepository->delete($name);
Event::dispatch(new Deleted($module));
return true;
}
/**
* disable or enable
*
* @param string $name
* @return bool|int
*/
public function disOrEnable(string $name): bool|int
{
return $this->moduleRepository->disOrEnable($name);
}
/**
* get enabled
*
* @return Collection
*/
public function getEnabled(): Collection
{
// TODO: Implement getEnabled() method.
return $this->moduleRepository->getEnabled();
}
}

View File

@ -0,0 +1,61 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Support;
class Tree
{
protected static string $pk = 'id';
/**
*
* @param string $pk
* @return Tree
*/
public static function setPk(string $pk): Tree
{
self::$pk = $pk;
return new self();
}
/**
* return done
*
* @param array $items
* @param int $pid
* @param string $pidField
* @param string $child
* @return array
*/
public static function done(array $items, int $pid = 0, string $pidField = 'parent_id', string $child = 'children'): array
{
$tree = [];
foreach ($items as $item) {
if ($item[$pidField] == $pid) {
$children = self::done($items, $item[self::$pk], $pidField, $child);
if (count($children)) {
$item[$child] = $children;
}
$tree[] = $item;
}
}
return $tree;
}
}

View File

@ -0,0 +1,200 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Support\Zip;
use Exception;
use ZipArchive;
class ZipRepository
{
private mixed $archive;
/**
* Construct with a given path
*
* @param $filePath
* @param bool $create
* @param $archive
*
* @return void
* @throws Exception
*
*/
public function __construct($filePath, bool $create, $archive = null)
{
//Check if ZipArchive is available
if (! class_exists('ZipArchive')) {
throw new Exception('Error: Your PHP version is not compiled with zip support');
}
$this->archive = $archive ? $archive : new ZipArchive();
$res = $this->archive->open($filePath, ($create ? ZipArchive::CREATE : 0));
if ($res !== true) {
throw new Exception("Error: Failed to open $filePath! Error: ".$this->getErrorMessage($res));
}
}
/**
* Add a file to the opened Archive
*
* @param $pathToFile
* @param $pathInArchive
*/
public function addFile($pathToFile, $pathInArchive): void
{
$this->archive->addFile($pathToFile, $pathInArchive);
}
/**
* Add an empty directory
*
* @param $dirName
*/
public function addEmptyDir($dirName): void
{
$this->archive->addEmptyDir($dirName);
}
/**
* Add a file to the opened Archive using its contents
*
* @param string $name
* @param $content
*/
public function addFromString(string $name, $content): void
{
$this->archive->addFromString($name, $content);
}
/**
* Remove a file permanently from the Archive
*
* @param string $pathInArchive
*/
public function removeFile(string $pathInArchive): void
{
$this->archive->deleteName($pathInArchive);
}
/**
* Get the content of a file
*
* @param string $pathInArchive
*
* @return string
*/
public function getFileContent(string $pathInArchive): string
{
return $this->archive->getFromName($pathInArchive);
}
/**
* Get the stream of a file
*
* @param string $pathInArchive
*
* @return bool
*/
public function getFileStream(string $pathInArchive): bool
{
return $this->archive->getStream($pathInArchive);
}
/**
* Will loop over every item in the archive and will execute the callback on them
* Will provide the filename for every item
*
* @param $callback
*/
public function each($callback): void
{
for ($i = 0; $i < $this->archive->numFiles; ++$i) {
//skip if folder
$stats = $this->archive->statIndex($i);
if ($stats['size'] === 0 && $stats['crc'] === 0) {
continue;
}
call_user_func_array($callback, [
'file' => $this->archive->getNameIndex($i),
'stats' => $this->archive->statIndex($i)
]);
}
}
/**
* Checks whether the file is in the archive
*
* @param $fileInArchive
*
* @return bool
*/
public function fileExists($fileInArchive): bool
{
return $this->archive->locateName($fileInArchive) !== false;
}
/**
* Sets the password to be used for decompressing
* function named usePassword for clarity
*
* @param $password
*
* @return bool
*/
public function usePassword($password): bool
{
return $this->archive->setPassword($password);
}
/**
* Returns the status of the archive as a string
*
* @return string
*/
public function getStatus(): string
{
return $this->archive->getStatusString();
}
/**
* Closes the archive and saves it
*/
public function close(): void
{
@$this->archive->close();
}
/**
* get error message
*
* @param $resultCode
* @return string
*/
private function getErrorMessage($resultCode): string
{
return match ($resultCode) {
ZipArchive::ER_EXISTS => 'ZipArchive::ER_EXISTS - File already exists.',
ZipArchive::ER_INCONS => 'ZipArchive::ER_INCONS - Zip archive inconsistent.',
ZipArchive::ER_MEMORY => 'ZipArchive::ER_MEMORY - Malloc failure.',
ZipArchive::ER_NOENT => 'ZipArchive::ER_NOENT - No such file.',
ZipArchive::ER_NOZIP => 'ZipArchive::ER_NOZIP - Not a zip archive.',
ZipArchive::ER_OPEN => 'ZipArchive::ER_OPEN - Can\'t open file.',
ZipArchive::ER_READ => 'ZipArchive::ER_READ - Read error.',
ZipArchive::ER_SEEK => 'ZipArchive::ER_SEEK - Seek error.',
default => "An unknown error [$resultCode] has occurred.",
};
}
}

View File

@ -0,0 +1,626 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Support\Zip;
use Exception;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;
use InvalidArgumentException;
use RuntimeException;
/**
* This Zipper class is a wrapper around the ZipArchive methods with some handy functions
*
* Class Zipper
*
*/
class Zipper
{
/**
* Constant for extracting
*/
public const WHITELIST = 1;
/**
* Constant for extracting
*/
public const BLACKLIST = 2;
/**
* Constant for matching only strictly equal file names
*/
public const EXACT_MATCH = 4;
/**
* @var string Represents the current location in the archive
*/
private string $currentFolder = '';
/**
* @var Filesystem Handler to the file system
*/
private Filesystem $file;
/**
* @var ZipRepository|null Handler to the archive
*/
private ?ZipRepository $repository;
/**
* @var string The path to the current zip file
*/
private string $filePath;
/**
* Constructor
*
* @param Filesystem|null $fs
*/
public function __construct(Filesystem $fs = null)
{
$this->file = $fs ? $fs : new Filesystem();
}
/**
* Destructor
*/
public function __destruct()
{
if (is_object($this->repository)) {
$this->repository->close();
}
}
/**
* Create a new zip Archive if the file does not exists
* opens a zip archive if the file exists
*
* @param $pathToFile string The file to open
* @return $this Zipper instance
* @throws Exception
*/
public function make(string $pathToFile): Zipper
{
$new = $this->createArchiveFile($pathToFile);
$this->repository = new ZipRepository($pathToFile, $new);
$this->filePath = $pathToFile;
return $this;
}
/**
* Create a new zip archive or open an existing one
*
* @param $pathToFile
*
* @return $this
* @throws Exception
*
*/
public function zip($pathToFile): Zipper
{
$this->make($pathToFile);
return $this;
}
/**
* Create a new phar file or open one
*
* @param $pathToFile
*
* @return $this
* @throws Exception
*
*/
public function phar($pathToFile): Zipper
{
$this->make($pathToFile, 'phar');
return $this;
}
/**
* Create a new rar file or open one
*
* @param $pathToFile
*
* @return $this
* @throws Exception
*
*/
public function rar($pathToFile): Zipper
{
$this->make($pathToFile, 'rar');
return $this;
}
/**
* Extracts the opened zip archive to the specified location <br/>
* you can provide an array of files and folders and define if they should be a white list
* or a black list to extract. By default this method compares file names using "string starts with" logic
*
* @param $path string The path to extract to
* @param array $files An array of files
* @param int $methodFlags The Method the files should be treated
*
* @throws Exception
*/
public function extractTo(string $path, array $files = [], int $methodFlags = self::BLACKLIST): void
{
if (! $this->file->exists($path) && ! $this->file->makeDirectory($path, 0755, true)) {
throw new RuntimeException('Failed to create folder');
}
if ($methodFlags & self::EXACT_MATCH) {
$matchingMethod = function ($haystack) use ($files) {
return in_array($haystack, $files, true);
};
} else {
$matchingMethod = function ($haystack) use ($files) {
return Str::startsWith($haystack, $files);
};
}
if ($methodFlags & self::WHITELIST) {
$this->extractFilesInternal($path, $matchingMethod);
} else {
// blacklist - extract files that do not match with $matchingMethod
$this->extractFilesInternal($path, function ($filename) use ($matchingMethod) {
return ! $matchingMethod($filename);
});
}
}
/**
* Extracts matching files/folders from the opened zip archive to the specified location.
*
* @param string $extractToPath The path to extract to
* @param string $regex regular expression used to match files. See @link http://php.net/manual/en/reference.pcre.pattern.syntax.php
*
* @throws InvalidArgumentException
* @throws RuntimeException
*/
public function extractMatchingRegex(string $extractToPath, string $regex): void
{
if (empty($regex)) {
throw new InvalidArgumentException('Missing pass valid regex parameter');
}
$this->extractFilesInternal($extractToPath, function ($filename) use ($regex) {
$match = preg_match($regex, $filename);
if ($match === 1) {
return true;
} elseif ($match === false) {
//invalid pattern for preg_match raises E_WARNING and returns FALSE
//so if you have custom error_handler set to catch and throw E_WARNINGs you never end up here
//but if you have not - this will throw exception
throw new RuntimeException("regular expression match on '$filename' failed with error. Please check if pattern is valid regular expression.");
}
return false;
});
}
/**
* Gets the content of a single file if available
*
* @param $filePath string The full path (including all folders) of the file in the zip
*
* @return string returns the content or throws an exception
* @throws Exception
*
*/
public function getFileContent(string $filePath): string
{
if ($this->repository->fileExists($filePath) === false) {
throw new Exception(sprintf('The file "%s" cannot be found', $filePath));
}
return $this->repository->getFileContent($filePath);
}
/**
* Add one or multiple files to the zip.
*
* @param $pathToAdd array|string An array or string of files and folders to add
* @param mixed|null $fileName
*
* @return $this Zipper instance
*/
public function add(array|string $pathToAdd, mixed $fileName = null): Zipper
{
if (is_array($pathToAdd)) {
foreach ($pathToAdd as $key => $dir) {
if (! is_int($key)) {
$this->add($dir, $key);
} else {
$this->add($dir);
}
}
} elseif ($this->file->isFile($pathToAdd)) {
if ($fileName) {
$this->addFile($pathToAdd, $fileName);
} else {
$this->addFile($pathToAdd);
}
} else {
$this->addDir($pathToAdd);
}
return $this;
}
/**
* Add an empty directory
*
* @param $dirName
*
* @return Zipper
*/
public function addEmptyDir($dirName): Zipper
{
$this->repository->addEmptyDir($dirName);
return $this;
}
/**
* Add a file to the zip using its contents
*
* @param $filename string The name of the file to create
* @param $content string The file contents
*
* @return $this Zipper instance
*/
public function addString(string $filename, string $content): Zipper
{
$this->addFromString($filename, $content);
return $this;
}
/**
* Gets the status of the zip.
*
* @return string The status of the internal zip file
*/
public function getStatus(): string
{
return $this->repository->getStatus();
}
/**
* Remove a file or array of files and folders from the zip archive
*
* @param $fileToRemove array|string The path/array to the files in the zip
*
* @return $this Zipper instance
*/
public function remove(array|string $fileToRemove): Zipper
{
if (is_array($fileToRemove)) {
$self = $this;
$this->repository->each(function ($file) use ($fileToRemove, $self) {
if (Str::startsWith($file, $fileToRemove)) {
$self->getRepository()->removeFile($file);
}
});
} else {
$this->repository->removeFile($fileToRemove);
}
return $this;
}
/**
* Returns the path of the current zip file if there is one.
*
* @return string The path to the file
*/
public function getFilePath(): string
{
return $this->filePath;
}
/**
* Sets the password to be used for decompressing
*
* @param $password
*
* @return bool
*/
public function usePassword($password): bool
{
return $this->repository->usePassword($password);
}
/**
* Closes the zip file and frees all handles
*/
public function close(): void
{
if (null !== $this->repository) {
$this->repository->close();
}
$this->filePath = '';
}
/**
* Sets the internal folder to the given path.<br/>
* Useful for extracting only a segment of a zip file.
*
* @param string $path
*
* @return $this
*/
public function folder(string $path): Zipper
{
$this->currentFolder = $path;
return $this;
}
/**
* Resets the internal folder to the root of the zip file.
*
* @return $this
*/
public function home(): Zipper
{
$this->currentFolder = '';
return $this;
}
/**
* Deletes the archive file
*/
public function delete(): void
{
if (null !== $this->repository) {
$this->repository->close();
}
$this->file->delete($this->filePath);
$this->filePath = '';
}
/**
* Get the type of the Archive
*
* @return string
*/
public function getArchiveType(): string
{
return get_class($this->repository);
}
/**
* Get the current internal folder pointer
*
* @return string
*/
public function getCurrentFolderPath(): string
{
return $this->currentFolder;
}
/**
* Checks if a file is present in the archive
*
* @param $fileInArchive
*
* @return bool
*/
public function contains($fileInArchive): bool
{
return $this->repository->fileExists($fileInArchive);
}
/**
* @return ZipRepository
*/
public function getRepository(): ZipRepository
{
return $this->repository;
}
/**
* @return Filesystem
*/
public function getFileHandler(): Filesystem
{
return $this->file;
}
/**
* Gets the path to the internal folder
*
* @return string
*/
public function getInternalPath(): string
{
return empty($this->currentFolder) ? '' : $this->currentFolder.'/';
}
/**
* List all files that are within the archive
*
* @param string|null $regexFilter regular expression to filter returned files/folders. See @link http://php.net/manual/en/reference.pcre.pattern.syntax.php
*
* @throws RuntimeException
*
* @return array
*/
public function listFiles(string $regexFilter = null): array
{
$filesList = [];
if ($regexFilter) {
$filter = function ($file) use (&$filesList, $regexFilter) {
// push/pop an error handler here to to make sure no error/exception thrown if $expected is not a regex
set_error_handler(function () {
});
$match = preg_match($regexFilter, $file);
restore_error_handler();
if ($match === 1) {
$filesList[] = $file;
} elseif ($match === false) {
throw new RuntimeException("regular expression match on '$file' failed with error. Please check if pattern is valid regular expression.");
}
};
} else {
$filter = function ($file) use (&$filesList) {
$filesList[] = $file;
};
}
$this->repository->each($filter);
return $filesList;
}
private function getCurrentFolderWithTrailingSlash(): string
{
if (empty($this->currentFolder)) {
return '';
}
$lastChar = mb_substr($this->currentFolder, -1);
if ($lastChar !== '/' || $lastChar !== '\\') {
return $this->currentFolder.'/';
}
return $this->currentFolder;
}
//---------------------PRIVATE FUNCTIONS-------------
/**
* @param $pathToZip
*
* @return bool
* @throws Exception
*
*/
private function createArchiveFile($pathToZip): bool
{
if (! $this->file->exists($pathToZip)) {
$dirname = dirname($pathToZip);
if (! $this->file->exists($dirname) && ! $this->file->makeDirectory($dirname, 0755, true)) {
throw new RuntimeException('Failed to create folder');
} elseif (! $this->file->isWritable($dirname)) {
throw new Exception(sprintf('The path "%s" is not writeable', $pathToZip));
}
return true;
}
return false;
}
/**
* @param $pathToDir
*/
private function addDir($pathToDir): void
{
// First go over the files in this directory and add them to the repository.
foreach ($this->file->files($pathToDir) as $file) {
$this->addFile($pathToDir.'/'.basename($file));
}
// Now let's visit the subdirectories and add them, too.
foreach ($this->file->directories($pathToDir) as $dir) {
$old_folder = $this->currentFolder;
$this->currentFolder = empty($this->currentFolder) ? basename($dir) : $this->currentFolder.'/'.basename($dir);
$this->addDir($pathToDir.'/'.basename($dir));
$this->currentFolder = $old_folder;
}
}
/**
* Add the file to the zip
*
* @param string $pathToAdd
* @param string|null $fileName
*/
private function addFile(string $pathToAdd, string $fileName = null): void
{
if (! $fileName) {
$info = pathinfo($pathToAdd);
$fileName = isset($info['extension']) ?
$info['filename'].'.'.$info['extension'] :
$info['filename'];
}
$this->repository->addFile($pathToAdd, $this->getInternalPath().$fileName);
}
/**
* Add the file to the zip from content
*
* @param $filename
* @param $content
*/
private function addFromString($filename, $content): void
{
$this->repository->addFromString($this->getInternalPath().$filename, $content);
}
private function extractFilesInternal($path, callable $matchingMethod): void
{
$self = $this;
$this->repository->each(function ($fileName) use ($path, $matchingMethod, $self) {
$currentPath = $self->getCurrentFolderWithTrailingSlash();
if (! empty($currentPath) && ! Str::startsWith($fileName, $currentPath)) {
return;
}
$filename = str_replace($self->getInternalPath(), '', $fileName);
if ($matchingMethod($filename)) {
$self->extractOneFileInternal($fileName, $path);
}
});
}
/**
* @param $fileName
* @param $path
*
* @throws RuntimeException
*/
private function extractOneFileInternal($fileName, $path): void
{
$tmpPath = str_replace($this->getInternalPath(), '', $fileName);
//Prevent Zip traversal attacks
if (str_contains($fileName, '../') || str_contains($fileName, '..\\')) {
throw new RuntimeException('Special characters found within filenames');
}
// We need to create the directory first in case it doesn't exist
$dir = pathinfo($path.DIRECTORY_SEPARATOR.$tmpPath, PATHINFO_DIRNAME);
if (! $this->file->exists($dir) && ! $this->file->makeDirectory($dir, 0755, true, true)) {
throw new RuntimeException('Failed to create folders');
}
$toPath = $path.DIRECTORY_SEPARATOR.$tmpPath;
$fileStream = $this->getRepository()->getFileStream($fileName);
$this->getFileHandler()->put($toPath, $fileStream);
}
}

View File

@ -0,0 +1,122 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
use Illuminate\Console\Application as Artisan;
use Illuminate\Console\Command;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Symfony\Component\Finder\Finder;
use Symfony\Component\VarDumper\VarDumper;
/**
* load commands
*/
if (! function_exists('loadCommands')) {
/**
* @throws ReflectionException
*/
function loadCommands($paths, $namespace, $searchPath = null): void
{
if (! $searchPath) {
$searchPath = dirname($paths).DIRECTORY_SEPARATOR;
}
$paths = Collection::make(Arr::wrap($paths))->unique()->filter(function ($path) {
return is_dir($path);
});
if ($paths->isEmpty()) {
return;
}
foreach ((new Finder())->in($paths->toArray())->files() as $command) {
$command = $namespace.str_replace(['/', '.php'], ['\\', ''], Str::after($command->getRealPath(), $searchPath));
if (is_subclass_of($command, Command::class) &&
! (new ReflectionClass($command))->isAbstract()) {
Artisan::starting(function ($artisan) use ($command) {
$artisan->resolve($command);
});
}
}
}
}
/**
* table prefix
*/
if (! function_exists('withTablePrefix')) {
function withTablePrefix(string $table): string
{
return DB::connection()->getTablePrefix().$table;
}
}
/**
* get guard name
*/
if (! function_exists('getGuardName')) {
function getGuardName(): string
{
$guardKeys = array_keys(config('catch.auth.guards'));
if (count($guardKeys)) {
return $guardKeys[0];
}
return 'admin';
}
}
/**
* get table columns
*/
if (! function_exists('getTableColumns')) {
function getTableColumns(string $table): array
{
$SQL = 'desc '.withTablePrefix($table);
$columns = [];
foreach (DB::select($SQL) as $column) {
$columns[] = $column->Field;
}
return $columns;
}
}
if (! function_exists('dd_')) {
/**
* @param mixed ...$vars
* @return never
*/
function dd_(...$vars): never
{
if (! in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && ! headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Headers: *');
foreach ($vars as $v) {
VarDumper::dump($v);
}
exit(1);
}
}

View File

@ -0,0 +1,239 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/JaguarJack/catchadmin-laravel/blob/master/LICENSE.md )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace Catch\Traits\DB;
use Catch\Enums\Status;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Request;
/**
* base operate
*/
trait BaseOperate
{
/**
*
*
* @return void
*/
public function initializeBaseOperate(): void
{
if (property_exists($this, 'mergeCasts')) {
$this->mergeCasts($this->mergeCasts);
}
if (property_exists($this, 'mergeHidden')) {
$this->makeHidden($this->mergeHidden);
}
}
/**
* @return mixed
*/
public function getList(): mixed
{
$queryBuilder = self::query()->select($this->fieldsInList)->quickSearch();
if ($this->isPaginate) {
return $queryBuilder->paginate(Request::get('limit', $this->perPage));
}
return $queryBuilder->get();
}
/**
* save
*
* @param array $data
* @return false|mixed
*/
public function storeBy(array $data): mixed
{
if ($this->fill($this->filterData($data))->save()) {
return $this->getKey();
}
return false;
}
/**
* create
*
* @param array $data
* @return false|mixed
*/
public function createBy(array $data): mixed
{
$model = $this->newInstance();
if ($model->fill($this->filterData($data))->save()) {
return $model->getKey();
}
return false;
}
/**
* update
*
* @param $id
* @param array $data
* @return mixed
*/
public function updateBy($id, array $data): mixed
{
return $this->where($this->getKeyName(), $id)->update($this->filterData($data));
}
/**
* filter data/ remove null && empty string
*
* @param array $data
* @return array
*/
protected function filterData(array $data): array
{
// 表单保存的数据集合
$form = property_exists($this, 'form') ? $this->form : [];
foreach ($data as $k => $val) {
if (is_null($val) || (is_string($val) && ! $val)) {
unset($data[$k]);
}
if (! empty($form) && ! in_array($k, $form)) {
unset($data[$k]);
}
}
return $data;
}
/**
* get first by ID
*
* @param $id
* @param string[] $columns
* @return ?Model
*/
public function firstBy($id, array $columns = ['*']): ?Model
{
return static::where($this->getKeyName(), $id)->first($columns);
}
/**
* delete model
*
* @param $id
* @param bool $force
* @return bool|null
*/
public function deleteBy($id, bool $force = false): ?bool
{
/* @var Model $model */
$model = self::find($id);
if ($force) {
return $model->forceDelete();
}
return $model->delete();
}
/**
* disable or enable
*
* @param $id
* @param string $field
* @return bool
*/
public function disOrEnable($id, string $field = 'status'): bool
{
$model = self::firstBy($id);
$model->{$field} = $model->{$field} == Status::Enable->value() ? Status::Disable->value() : Status::Enable->value();
return $model->save();
}
/**
* alias field
*
* @param string|array $fields
* @return string|array
*/
public function aliasField(string|array $fields): string|array
{
$table = $this->getTable();
if (is_string($fields)) {
return "{$table}.{$fields}";
}
foreach ($fields as &$field) {
$field = "{$table}.{$field}";
}
return $fields;
}
/**
* get updated at column
*
* @return string|null
*/
public function getUpdatedAtColumn(): ?string
{
$updatedAtColumn = parent::getUpdatedAtColumn();
if (! in_array(parent::getUpdatedAtColumn(), $this->getFillable())) {
$updatedAtColumn = null;
}
return $updatedAtColumn;
}
/**
* get created at column
*
* @return string|null
*/
public function getCreatedAtColumn(): ?string
{
$createdAtColumn = parent::getCreatedAtColumn();
if (! in_array(parent::getUpdatedAtColumn(), $this->getFillable())) {
$createdAtColumn = null;
}
return $createdAtColumn;
}
/**
* whit form data
*
* @return $this
*/
public function withoutForm(): static
{
if (property_exists($this, 'form') && ! empty($this->form)) {
$this->form = [];
}
return $this;
}
}

Some files were not shown because too many files have changed in this diff Show More