diff --git a/api/.editorconfig b/api/.editorconfig new file mode 100644 index 0000000..74d2ba1 --- /dev/null +++ b/api/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +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 = 2 diff --git a/api/.env.example b/api/.env.example new file mode 100644 index 0000000..4788833 --- /dev/null +++ b/api/.env.example @@ -0,0 +1,62 @@ +APP_NAME=入魔入佛 +APP_ENV=local +APP_KEY=base64:q3NPkuRVhdHFRkVskaqQatUEs+fXcFVgJNiDtE9nSAA= +APP_DEBUG=true +APP_URL=http://127.0.0.1:8000 + +REQUEST_LOG=true +TIMEZONE=Asia/Shanghai + +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=xxxxxxx +DB_USERNAME=xxxxxxx +DB_PASSWORD=xxxxxxx + +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=mailpit +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_APP_NAME="${APP_NAME}" +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}" diff --git a/api/.gitattributes b/api/.gitattributes new file mode 100644 index 0000000..fcb21d3 --- /dev/null +++ b/api/.gitattributes @@ -0,0 +1,11 @@ +* text=auto eol=lf + +*.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 diff --git a/api/.gitignore b/api/.gitignore new file mode 100644 index 0000000..8631525 --- /dev/null +++ b/api/.gitignore @@ -0,0 +1,36 @@ +# ---> Laravel +/vendor/ +npm-debug.log +yarn-error.log + +# Laravel 4 specific +bootstrap/compiled.php +app/storage/ + +# Laravel 5 & Lumen specific +public/storage + +# Laravel 5 & Lumen specific with changed public path +public_html/storage +public_html/hot + +storage/app/public/assets/upload +storage/app/log +storage/*.key +.env +Homestead.yaml +Homestead.json +/.vagrant +.phpunit.result.cache + +# ---> Vue +# gitignore template for Vue.js projects +# +# Recommended template: Node.gitignore + +# TODO: where does this rule come from? +docs/_book + +# TODO: where does this rule come from? +test/ + diff --git a/api/app/Console/Kernel.php b/api/app/Console/Kernel.php new file mode 100644 index 0000000..e6b9960 --- /dev/null +++ b/api/app/Console/Kernel.php @@ -0,0 +1,27 @@ +command('inspire')->hourly(); + } + + /** + * Register the commands for the application. + */ + protected function commands(): void + { + $this->load(__DIR__.'/Commands'); + + require base_path('routes/console.php'); + } +} diff --git a/api/app/Exceptions/Handler.php b/api/app/Exceptions/Handler.php new file mode 100644 index 0000000..56af264 --- /dev/null +++ b/api/app/Exceptions/Handler.php @@ -0,0 +1,30 @@ + + */ + protected $dontFlash = [ + 'current_password', + 'password', + 'password_confirmation', + ]; + + /** + * Register the exception handling callbacks for the application. + */ + public function register(): void + { + $this->reportable(function (Throwable $e) { + // + }); + } +} diff --git a/api/app/Http/Controllers/AdminAccountController.php b/api/app/Http/Controllers/AdminAccountController.php new file mode 100644 index 0000000..7da19a5 --- /dev/null +++ b/api/app/Http/Controllers/AdminAccountController.php @@ -0,0 +1,41 @@ +post('hash'); + $code = $request->post('code'); + $time = $request->post('time'); + $uuid = $request->post('uuid'); + $captcha = new ImageCaptchaController(); + $captcha_check = $captcha->check($hash, $code, $time, $uuid); + if ($captcha_check != 0) Yo::error_echo($captcha_check); + $old_password = $request->post('old_password'); + $password = $request->post('password'); + $admin_account = AdminAccount::where('admin', Login::$info->id) + ->where('type', 1) + ->where('del', 2) + ->first(); + if (!$admin_account) Yo::error_echo(100001, ['账号']); + if (!password_verify($old_password, $admin_account->secret)) Yo::error_echo(100008); + if ($old_password == $password) Yo::error_echo(100009); + $admin_account->secret = bcrypt($password); + $admin_account->save(); + if (Login::$info->initial_password == 1) { + Login::$info->initial_password = 2; + Login::$info->save(); + } + return Yo::update_echo(Login::$info->init_password); + } +} diff --git a/api/app/Http/Controllers/AdminAuthController.php b/api/app/Http/Controllers/AdminAuthController.php new file mode 100644 index 0000000..37a88ec --- /dev/null +++ b/api/app/Http/Controllers/AdminAuthController.php @@ -0,0 +1,196 @@ +name = $request->post('name'); + $admin_auth->title = $request->post('title'); + $admin_auth->icon = $request->post('icon') ?? ''; + $pid = $request->post('pid'); + $type = $request->post('type'); + if ($type == 1 && $pid != 0) Yo::error_echo(100029); + if ($type == 2 && $pid != 0) { + $p_info = AdminAuth::where('id', $pid)->where('pid', 0)->where('type', 1)->first(); + if (!$p_info) Yo::error_echo(100001, ['组路由']); + } + $admin_auth->pid = $pid; + $admin_auth->type = $type; + $admin_auth->check = $request->post('check'); + $admin_auth->show = $request->post('show'); + $admin_auth->status = $request->post('status'); + $admin_auth->message = $request->post('message') ?? ''; + $admin_auth->order = $request->post('order'); + $admin_auth->save(); + $admin_auth = AdminAuth::where('id', $admin_auth->id)->first(); + return Yo::echo([ + 'info' => $admin_auth + ]); + } + + public function update(EditAdminAuth $request) + { + Login::admin([8]); + $admin_auth = AdminAuth::where('id', $request->post('id'))->where('del', 2)->first(); + if (!$admin_auth) Yo::error_echo(100001, ['路由']); + $admin_auth->name = $request->post('name'); + $admin_auth->title = $request->post('title'); + $admin_auth->icon = $request->post('icon') ?? ''; + $pid = $request->post('pid'); + $type = $request->post('type'); + if ($type == 1 && $pid != 0) Yo::error_echo(100029); + if ($type == 2 && $pid != 0) { + $p_info = AdminAuth::where('id', $pid)->where('pid', 0)->where('type', 1)->first(); + if (!$p_info) Yo::error_echo(100001, ['组路由']); + } + $admin_auth->pid = $pid; + $admin_auth->type = $type; + $admin_auth->check = $request->post('check'); + $admin_auth->show = $request->post('show'); + $admin_auth->status = $request->post('status'); + $admin_auth->message = $request->post('message') ?? ''; + $admin_auth->order = $request->post('order'); + $admin_auth->save(); + $admin_auth = AdminAuth::where('id', $admin_auth->id)->first(); + return Yo::echo([ + 'info' => $admin_auth + ]); + } + + public function delete(Request $request) + { + Login::admin([8]); + $admin_auth = AdminAuth::where('id', $request->post('id'))->where('del', 2)->first(); + if (!$admin_auth) Yo::error_echo(100001, ['路由']); + $son_count = AdminAuth::where('pid', $admin_auth->id)->where('del', 2)->count(); + if ($son_count != 0) Yo::error_echo(100030); + $admin_auth->del = 1; + $admin_auth->save(); + return Yo::delete_echo($admin_auth->id); + } + + public function list(Request $request) + { + Login::admin([8]); + $auth_group = AdminAuth::where('pid', 0)->where('type', 1)->where('del', 2)->orderBy('order', 'desc')->get(); + $list = []; + foreach ($auth_group as $item) { + $data = [ + 'info' => $item, + ]; + $auth_group_list = AdminAuth::where('pid', $item->id)->where('type', 2)->where('check', 1)->where('del', 2)->orderBy('order', 'desc')->get(); + $data['list'] = $auth_group_list; + $list[] = $data; + } + $auth_group_single = AdminAuth::where('pid', 0)->where('type', 2)->where('check', 1)->where('del', 2)->orderBy('order', 'desc')->get()->toArray(); + return Yo::echo([ + 'list' => array_merge($list, $auth_group_single) + ]); + } + + public function select(Request $request) + { + Login::admin([8]); + $auth_group = AdminAuth::where('pid', 0)->where('type', 1)->where('del', 2)->orderBy('order', 'desc')->get(); + return Yo::echo([ + 'list' => $auth_group + ]); + } + + public function choose() + { + Login::admin(); + $auth_group = AdminAuth::where('pid', 0)->where('type', 1)->where('del', 2)->orderBy('order', 'desc')->get(); + $list = []; + foreach ($auth_group as $item) { + $data = [ + 'info' => $item, + ]; + $auth_group_list = AdminAuth::where('pid', $item->id)->where('type', 2)->where('check', 1)->where('del', 2)->orderBy('order', 'desc')->get(); + $data['list'] = $auth_group_list; + if (count($data['list']) == 0) continue; + $list[] = $data; + } + $auth_group_single = AdminAuth::where('pid', 0)->where('type', 2)->where('check', 1)->where('del', 2)->orderBy('order', 'desc')->get(); + if (count($auth_group_single) != 0) { + $list[] = [ + 'info' => [ + 'id' => 0, + 'title' => '未分组', + ], + 'list' => $auth_group_single + ]; + } + return Yo::echo([ + 'list' => $list + ]); + } + + public function menu() + { + Login::admin(); + $menu_group = AdminAuth::select('id', 'name', 'title', 'icon', 'status', 'type') + ->where('pid', 0)->where('show', 1)->where('del', 2) + ->orderBy('order', 'desc')->get(); + $list = []; + foreach ($menu_group as $item) { + if ($item->type == 2) { + $list[] = [ + "id" => $item->id, + "name" => $item->name, + "title" => $item->title, + "icon" => $item->icon, + "status" => $item->status, + "children" => [] + ]; + } else { + switch (Login::$info->admin_auth_group) { + case -1: + $auth_list = AdminAuth::select('id', 'name', 'title', 'icon', 'status')->where('pid', $item->id) + ->where('type', 2)->where('show', 1)->where('status', 1)->where('del', 2) + ->orderBy('order', 'desc')->get(); + break; + case 0: + $auth_list = AdminAuth::select('id', 'name', 'title', 'icon', 'status')->where('pid', $item->id) + ->where('type', 2)->where('check_type', 1)->where('show', 1)->where('status', 1)->where('del', 2) + ->orderBy('order', 'desc')->get(); + break; + default: + $admin_auth = AdminAuth::find(Login::$info->admin_auth_group); + $auths = json_decode($admin_auth->auths, true); + $auth_list = AdminAuth::select('id', 'name', 'title', 'icon', 'status') + ->where(function ($query) use ($auths, $item) { + $query->whereIn('id', $auths)->where('pid', $item->id)->where('type', 2)->where('check_type', 2)->where('show', 1)->where('status', 1)->where('del', 2); + }) + ->orWhere(function ($query) use ($auths, $item) { + $query->where('type', 2)->where('pid', $item->id)->where('check_type', 1)->where('show', 1)->where('status', 1)->where('del', 2); + }) + ->orderBy('order', 'desc')->get(); + } + if (count($auth_list) !== 0) { + $list[] = [ + "id" => $item->id, + "name" => $item->name, + "title" => $item->title, + "icon" => $item->icon, + "status" => $item->status, + "children" => $auth_list + ]; + } + } + } + return Yo::echo([ + 'list' => $list + ]); + } +} diff --git a/api/app/Http/Controllers/AdminAuthGroupController.php b/api/app/Http/Controllers/AdminAuthGroupController.php new file mode 100644 index 0000000..3338b8d --- /dev/null +++ b/api/app/Http/Controllers/AdminAuthGroupController.php @@ -0,0 +1,71 @@ +name = $request->post('name'); + $admin_auth_group->admin_auths = $request->post('admin_auths'); + $admin_auth_group->remark = $request->post('remark') ?? ''; + $admin_auth_group->status = $request->post('status'); + $admin_auth_group->save(); + return Yo::echo([ + 'info' => $admin_auth_group + ]); + } + + public function update(EditAdminAuthGroup $request) + { + Login::admin([4]); + $admin_auth_group = AdminAuthGroup::where('id', $request->post('id')) + ->where('del', 2)->first(); + if (!$admin_auth_group) Yo::error_echo(100001, ['权限组']); + $admin_auth_group->name = $request->post('name'); + $admin_auth_group->admin_auths = $request->post('admin_auths'); + $admin_auth_group->remark = $request->post('remark') ?? ''; + $admin_auth_group->status = $request->post('status'); + $admin_auth_group->save(); + return Yo::echo([ + 'info' => $admin_auth_group + ]); + } + + public function delete(Request $request) + { + Login::admin([4]); + $admin_auth_group = AdminAuthGroup::where('id', $request->post('id')) + ->where('del', 2)->first(); + if (!$admin_auth_group) Yo::error_echo(100001, ['权限组']); + $admin_auth_group->del = 1; + $admin_auth_group->save(); + return Yo::delete_echo($admin_auth_group->id); + } + + public function list(Request $request) + { + Login::admin(); + $admin_auth_group = AdminAuthGroup::where('del', 2)->get(); + return Yo::echo([ + 'list' => $admin_auth_group + ]); + } + + public function select(Request $request) + { + Login::admin(); + $admin_auth_group = AdminAuthGroup::where('del', 2)->get(); + return Yo::echo([ + 'list' => $admin_auth_group + ]); + } +} diff --git a/api/app/Http/Controllers/AdminController.php b/api/app/Http/Controllers/AdminController.php new file mode 100644 index 0000000..3c95859 --- /dev/null +++ b/api/app/Http/Controllers/AdminController.php @@ -0,0 +1,214 @@ +post('account'); + $admin_account = AdminAccount::where('account', $account)->where('type', 1)->where('del', 2)->first(); + if ($admin_account) Yo::error_echo(100023); + $admin = new Admin(); + $admin->nickname = $request->post('nickname'); + $admin->avatar = $request->post('avatar'); + $admin->admin_auth_group = $request->post('admin_auth_group'); + $admin->initial_password = $request->post('initial_password'); + $admin->status = $request->post('status'); + $admin->save(); + $admin_account = new AdminAccount(); + $admin_account->admin = $admin->id; + $admin_account->account = $account; + $admin_account->secret = bcrypt($request->post('password')); + $admin_account->type = 1; + $admin_account->save(); + $admin_info = Admin::select(['id', 'nickname', 'avatar', 'status', 'admin_auth_group', 'initial_password']) + ->selectRaw("IFNULL((select account from admin_accounts where admin_accounts.admin = admins.id and type = 1),'') as account") + ->selectRaw("IFNULL((select name from admin_auth_groups where admin_auth_groups.id = admins.admin_auth_group),'') as admin_auth_group_name") + ->where('id', $admin->id)->first(); + return Yo::echo([ + 'info' => $admin_info + ]); + } + + public function update(EditAdmin $request) + { + Login::admin([5]); + $id = $request->post('id'); + $account = $request->post('account'); + $admin_account = AdminAccount::where('admin', '!=', $id)->where('account', $account)->where('type', 1)->where('del', 2)->first(); + if ($admin_account) Yo::error_echo(100023); + $admin = Admin::where('id', $id)->where('del', 2)->first(); + if (!$admin) Yo::error_echo(100001, ['管理员']); + $admin_account = AdminAccount::where('admin', $id)->where('del', 2)->first(); + if (!$admin_account) Yo::error_echo(100001, ['管理员']); + $admin->nickname = $request->post('nickname'); + $admin->avatar = $request->post('avatar'); + $admin->admin_auth_group = $request->post('admin_auth_group'); + $admin->initial_password = $request->post('initial_password'); + $admin->status = $request->post('status'); + $admin->save(); + if ($admin_account->account != $account) { + $admin_account->account = $request->post('account'); + $admin_account->save(); + } + $admin_info = Admin::select(['id', 'nickname', 'avatar', 'status', 'admin_auth_group', 'initial_password']) + ->selectRaw("IFNULL((select account from admin_accounts where admin_accounts.admin = admins.id and type = 1),'') as account") + ->selectRaw("IFNULL((select name from admin_auth_groups where admin_auth_groups.id = admins.admin_auth_group),'') as admin_auth_group_name") + ->where('id', $admin->id)->first(); + return Yo::echo([ + 'info' => $admin_info + ]); + } + + public function delete(Request $request) + { + Login::admin([5]); + $id = $request->post('id'); + $admin = Admin::where('id', $id)->where('del', 2)->first(); + if (!$admin) Yo::error_echo(100001, ['管理员']); + $admin_account = AdminAccount::where('admin', $id)->where('del', 2)->first(); + if (!$admin_account) Yo::error_echo(100001, ['管理员']); + $admin->del = 1; + $admin->save(); + $admin_account->del = 1; + $admin_account->save(); + return Yo::delete_echo($admin->id); + } + + public function list(Request $request) + { + Login::admin([5]); + $status = $request->post('status'); + $search = $request->post('search'); + $admin_auth_group = $request->post('admin_auth_group'); + $initial_password = $request->post('initial_password'); + $admin_list = Admin::select(['id', 'nickname', 'avatar', 'status', 'admin_auth_group', 'initial_password']) + ->selectRaw("IFNULL((select account from admin_accounts where admin_accounts.admin = admins.id and type = 1),'') as account") + ->selectRaw("IFNULL((select name from admin_auth_groups where admin_auth_groups.id = admins.admin_auth_group),'') as admin_auth_group_name") + ->where(function ($query) use ($status) { + if ($status != 0) $query->where('status', $status); + }) + ->where(function ($query) use ($admin_auth_group) { + if ($admin_auth_group != 0) $query->where('admin_auth_group', $admin_auth_group); + }) + ->where(function ($query) use ($initial_password) { + if ($initial_password != 0) $query->where('initial_password', $initial_password); + }) + ->where(function ($query) use ($search) { + if ($search != '') $query->where('nickname', 'like', "%$search%"); + }) + ->where('del', 2) + ->paginate(20); + return Yo::echo([ + 'list' => $admin_list + ]); + } + + public function quit() + { + Login::admin_check(); + if (!!Login::$token) { + Login::$token->del = 1; + Login::$token->save(); + } + return Yo::echo(); + } + + public function update_self(UpdateAdminInfo $request) + { + Login::admin(); + $nickname = $request->post('nickname'); + $avatar = $request->post('avatar'); + Login::$info->nickname = $nickname; + Login::$info->avatar = $avatar; + Login::$info->save(); + return Yo::update_echo(Login::$info->id); + } + + public function login(Request $request) + { + $captcha_type_config = Config::where('name', '后台密码登录验证')->first(); + if (!!$captcha_type_config) { + if ($captcha_type_config->value != '0') { + $hash = $request->post('hash'); + $code = $request->post('code'); + $time = $request->post('time'); + $uuid = $request->post('uuid'); + $captcha = null; + switch ($captcha_type_config->value) { + case '1': + $captcha = new ImageCaptchaController(); + break; + } + $captcha_check = $captcha->check($hash, $code, $time, $uuid); + if ($captcha_check != 0) Yo::error_echo($captcha_check); + } + } + $account = $request->post('account'); + $password = $request->post('password'); + $type = 1; + $admin_account = AdminAccount::where('account', $account) + ->where('type', $type) + ->where('del', 2) + ->first(); + if (!$admin_account) Yo::error_echo(100007); + if (!password_verify($password, $admin_account->secret)) Yo::error_echo(100007); + $admin = Admin::where('id', $admin_account->admin) + ->where('status', 1) + ->where('del', 2) + ->first(); + if (!$admin) Yo::error_echo(100003); + Login::$info = $admin; + Login::$type = 'admin'; + $token = $this->create_token($admin, $type); + return Yo::echo([ + 'token' => $token + ]); + } + + public function status() + { + Login::admin(); + return Yo::echo(); + } + + public function info() + { + Login::admin(); + return Yo::echo([ + 'info' => [ + 'id' => Login::$info->id, + 'nickname' => Login::$info->nickname, + 'avatar' => Login::$info->avatar, + 'initial_password' => Login::$info->initial_password, + ] + ]); + } + + public function create_token($info, $type = 1): string + { + if ($info->status != 1) Yo::error_echo(100003); + if ($info->del != 2) Yo::error_echo(100003); + $token_str = Str::orderedUuid(); + $token = new AdminToken(); + $token->admin = $info->id; + $token->token = $token_str; + // $type 1-密码登录 + $token->type = $type; + $token->save(); + return $token_str; + } +} diff --git a/api/app/Http/Controllers/ConfigController.php b/api/app/Http/Controllers/ConfigController.php new file mode 100644 index 0000000..6800cc4 --- /dev/null +++ b/api/app/Http/Controllers/ConfigController.php @@ -0,0 +1,105 @@ +name = $request->post('name'); + $config->value = $request->post('value') ?? ''; + $config->type = $request->post('type'); + $config->client = $request->post('client'); + $config->login = $request->post('login'); + $config->remark = $request->post('remark') ?? ''; + $config->save(); + $config = Config::find($config->id); + if (in_array($config->type, [3, 4, 5])) $config->value = json_decode($config->value, true); + return Yo::echo([ + 'info' => $config + ]); + } + + public function update(EditConfig $request) + { + Login::admin([7]); + $config = Config::where('id', $request->post('id'))->first(); + if (!$config) Yo::error_echo(100001, ['配置']); + $config->name = $request->post('name'); + $config->value = $request->post('value'); + $config->type = $request->post('type'); + $config->client = $request->post('client'); + $config->login = $request->post('login'); + $config->remark = $request->post('remark') ?? ''; + $config->save(); + if (in_array($config->type, [3, 4, 5])) $config->value = json_decode($config->value, true); + return Yo::echo([ + 'info' => $config + ]); + } + + public function delete(Request $request) + { + Login::admin([7]); + $config = Config::where('id', $request->post('id'))->first(); + if (!$config) Yo::error_echo(100001, ['配置']); + $config->delete(); + if (in_array($config->type, [3, 4, 5])) $config->value = json_decode($config->value, true); + return Yo::delete_echo($config->id); + } + + public function list() + { + Login::admin([7]); + $config = Config::get(); + foreach ($config as $item) { + if (in_array($item->type, [3, 4, 5])) $item->value = json_decode($item->value, true); + } + return Yo::echo([ + 'list' => $config + ]); + } + + public function get(Request $request) + { + $client = $request->get('client'); + if (!$client) $client = 'public'; + $client_number = 0; + switch ($client) { + case 'admin': + $client_number = 1; + Login::admin_check(); + break; + } + $config_arr = $request->post('config_arr'); + if (!$config_arr) $config_arr = []; + $configs = $this->getConfigList($config_arr, $client_number); + return Yo::echo($configs); + } + + public function getConfigList($arr, $client) + { + $config_arr = []; + foreach ($arr as $item) $config_arr[$item] = ''; + $config_db = Config::whereIn('name', $arr); + if (!Login::$info) $config_db->where('login', 2); + if ($client != 0) $config_db->whereIn('client', [0, $client]); + $config = $config_db->get(); + foreach ($config as $item) { + $value = $item->value; + if (in_array($item->type, [3, 4, 5])) { + $value = json_decode($value, true); + } + $config_arr[$item->name] = $value; + } + return $config_arr; + } +} diff --git a/api/app/Http/Controllers/Controller.php b/api/app/Http/Controllers/Controller.php new file mode 100644 index 0000000..4a38960 --- /dev/null +++ b/api/app/Http/Controllers/Controller.php @@ -0,0 +1,18 @@ +first(); + if ($captcha) return 100005; + if (time() - $time > 60 * 3) return 100005; + if (Hash::check($code . ',Captcha,' . $uuid . ',' . $time, $hash)) { + $captcha = new ImageCaptcha(); + $captcha->uuid = $uuid; + $captcha->save(); + return 0; + } else { + return 100006; + } + } + + public function create() + { + $captcha = $this->generateCaptcha(); + $imageBase64 = $this->getImageBase64($captcha['image']); + $time = time(); + $uuid = Str::orderedUuid(); + $code = mb_strtoupper($captcha['code']); + $hash = Hash::make($code . ',Captcha,' . $uuid . ',' . $time); + $ret = [ + 'image' => $imageBase64, + 'hash' => $hash, + 'time' => $time, + 'uuid' => $uuid, + ]; + if (app()->isLocal()) { + $ret['code'] = $code; + $ret['account'] = 'admin'; + $ret['password'] = '000000'; + } + return Yo::echo($ret); + } + + private function generateCaptcha() + { + $code = $this->generateRandomCode(); + $image = $this->generateImage($code); + return [ + 'code' => $code, + 'image' => $image + ]; + } + + private function generateRandomCode() + { + $code = ''; + $characters = '34acdefhkmnprstwxyACDEFGHKMNPQRWXY'; + for ($i = 0; $i < 6; $i++) { + $code .= $characters[rand(0, strlen($characters) - 1)]; + } + return $code; + } + + private function generateImage($code) + { + $draw_width = 120; + $draw_height = 40; + $image = imagecreate($draw_width, $draw_height); + imagecolorallocate($image, 255, 255, 255); + for ($i = 0; $i < 100; $i++) { + $x = rand(0, 120); + $y = rand(0, 40); + $color = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255)); + imagesetpixel($image, $x, $y, $color); + } + for ($i = 0; $i < 5; $i++) { + $x1 = rand(0, 120); + $y1 = rand(0, 40); + $x2 = rand(0, 120); + $y2 = rand(0, 40); + $color = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255)); + imageline($image, $x1, $y1, $x2, $y2, $color); + } + $font_file = 'assets/captcha.ttf'; + $original_path = Storage::disk('public')->path($font_file); + $code_size = 26; + for ($i = 0; $i < mb_strlen($code); $i++) { + $c = mb_substr($code, $i, 1); + $r = rand(-20, 20); + $c_box = imagettfbbox($code_size, $r, $original_path, $c); + imagettftext($image, $code_size, $r, 2 + ceil((18 - $c_box[2]) / 2) + (18 * $i), ceil(($draw_height - $c_box[5]) / 2), + imagecolorallocate($image, rand(0, 200), rand(0, 200), rand(0, 200)), $original_path, $c); + } + ob_start(); + imagepng($image); + $imageData = ob_get_clean(); + return $imageData; + } + + private function getImageBase64($imageData) + { + $imageBase64 = base64_encode($imageData); + return 'data:image/png;base64,' . $imageBase64; + } +} diff --git a/api/app/Http/Controllers/RequestLogController.php b/api/app/Http/Controllers/RequestLogController.php new file mode 100644 index 0000000..8e118c6 --- /dev/null +++ b/api/app/Http/Controllers/RequestLogController.php @@ -0,0 +1,90 @@ +post('id'); + $type = $request->post('type'); + $log = DB::table('zz_request_log_' . date('ym', strtotime($request->post('created_at'))))->where('id', $id)->first(); + if (!$log) Yo::error_echo(100001, ['日志']); + $content = file_get_contents(base_path("/storage/app/$log->input")); + $sections = explode('-------------------------------', $content); + $data = '{}'; + if ($type == 'input') { + $post = self::txtClear($sections[0], 1); + $header = self::txtClear($sections[1], 1); + $data = '{ + "params":' . $log->params . ', + "input":' . $post . ', + "header":' . $header . ' +}'; + } else { + $result = self::txtClear($sections[2], 0); + $data = $result; + } + return Yo::echo([ + 'data' => $data, + ]); + } + + public function txtClear($content, $index) + { + $content_arr = explode("\n", $content); + return $content_arr[count($content_arr) - 1 - $index]; + } + + public function list(Request $request) + { + Login::admin([9]); + $search = $request->post('search'); + $time = $request->post('time'); + $method = $request->post('method'); + $code = $request->post('code'); + $start_time = !!$time[0] ? Lu::date(strtotime($time[0]), 'Y-m-d') : date('Y-m-01'); + $end_time = !!$time[1] ? Lu::date(strtotime($time[1]), 'Y-m-d') : date('Y-m-t'); + $ym_check = [ + date('Y-m', strtotime($start_time)), + date('Y-m', strtotime($end_time)), + ]; + if ($ym_check[0] !== $ym_check[1]) Yo::error_echo(100024); + $table_name = 'zz_request_log_' . date('ym', strtotime($start_time)); + $table_count = DB::select('select count(1) as c from information_schema.TABLES where table_schema = ? and table_name = ?', [env('DB_DATABASE'), $table_name])[0]; + if ($table_count->c === 0) Yo::error_echo(100001, ['日志表']); + $request_list = DB::table($table_name)->where(function ($query) use ($search) { + if ($search != '') $query->where('uuid', $search) + ->orWhere('token', $search) + ->orWhere('url', $search) + ->orWhere('ip', $search); + }) + ->where(function ($query) use ($start_time) { + if ($start_time != '') $query->where('created_at', '>=', $start_time); + }) + ->where(function ($query) use ($end_time) { + if ($end_time != '') $query->where('created_at', '<=', $end_time); + }) + ->where(function ($query) use ($method) { + if ($method != '') $query->where('method', $method); + }) + ->where(function ($query) use ($code) { + if ($code != '') $query->where('code', $code); + }) + ->orderBy('id', 'desc') + ->paginate(20); + return Yo::echo([ + 'list' => $request_list, + 'time' => [$start_time, $end_time], + ]); + } +} diff --git a/api/app/Http/Controllers/UploadController.php b/api/app/Http/Controllers/UploadController.php new file mode 100644 index 0000000..dd181b9 --- /dev/null +++ b/api/app/Http/Controllers/UploadController.php @@ -0,0 +1,110 @@ +groupBy('ext')->get(); + $from = ['AdminImage']; + return Yo::echo([ + 'ext' => $ext, + 'from' => $from, + ]); + } + + public function list(Request $request) + { + Login::admin([10]); + $search = $request->post('search'); + $time = $request->post('time'); + $start_time = !!$time[0] ? Lu::date(strtotime($time[0])) : ''; + $end_time = !!$time[1] ? Lu::date(strtotime($time[1])) : ''; + $ext = $request->post('ext'); + $from = $request->post('from'); + $from_map = [ + 'AdminImage' => '/api/Admin/Upload/image', + ]; + $from_search = ''; + if (!!$from) $from_search = $from_map[$from]; + $upload_list = Upload::where(function ($query) use ($search) { + if ($search != '') $query->where('uuid', $search) + ->orWhere('name', $search) + ->orWhere('md5', $search); + }) + ->where(function ($query) use ($start_time) { + if ($start_time != '') $query->where('created_at', '>=', $start_time); + }) + ->where(function ($query) use ($end_time) { + if ($end_time != '') $query->where('created_at', '<=', $end_time); + }) + ->where(function ($query) use ($ext) { + if ($ext != '') $query->where('ext', $ext); + }) + ->where(function ($query) use ($from_search) { + if ($from_search != '') $query->where('from', $from_search); + }) + ->orderBy('id', 'desc') + ->paginate(20); + return Yo::echo([ + 'list' => $upload_list + ]); + } + + public function delete(Request $request) + { + Login::admin([10]); + $id = $request->post('id'); + $upload = Upload::where('id', $id)->first(); + if (!$upload) Yo::error_echo(100001, ['上传文件']); + $upload->delete(); + unlink($upload->path); + return Yo::delete_echo($upload->id); + } + + public function image(Request $request) + { + $base64 = $request->post('base64'); + if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64, $result)) { + $type = ['png', 'jpeg', 'jpg', 'gif']; + if (!in_array($result[2], $type)) Yo::error_echo(100015); + $md5 = md5($base64); + $upload = Upload::where('md5', $md5)->first(); + if (!$upload) { + $disk = Storage::disk('public'); + $name = Str::orderedUuid(); + $date = date('Y/m'); + $path = "/assets/upload/image/$date/$name.$result[2]"; + $put = $disk->put($path, base64_decode(str_replace($result[1], '', $base64))); + if (!$put) Yo::error_echo(100016, ['put']); + $save = "/storage/assets/upload/image/$date/$name.$result[2]"; + $size = $disk->size($path); + $p = $disk->path($path); + $upload = new Upload(); + $upload->uuid = $name; + $upload->name = 'Base64-' . $md5; + $upload->path = $p; + $upload->url = $save; + $upload->from = explode('?', $_SERVER['REQUEST_URI'])[0]; + $upload->size = $size / 1024 / 1024; + $upload->ext = $result[2]; + $upload->md5 = $md5; + $upload->save(); + } + return Yo::echo([ + 'url' => $upload->url + ]); + } else { + Yo::error_echo(100016, ['base64']); + } + } +} diff --git a/api/app/Http/Controllers/YoController.php b/api/app/Http/Controllers/YoController.php new file mode 100644 index 0000000..557bce3 --- /dev/null +++ b/api/app/Http/Controllers/YoController.php @@ -0,0 +1,18 @@ + env('APP_NAME'), + 'datetime' => Lu::date(), + 'data' => request()->all() + ]); + } +} diff --git a/api/app/Http/Kernel.php b/api/app/Http/Kernel.php new file mode 100644 index 0000000..494c050 --- /dev/null +++ b/api/app/Http/Kernel.php @@ -0,0 +1,68 @@ + + */ + 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> + */ + 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, + \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', + \Illuminate\Routing\Middleware\SubstituteBindings::class, + ], + ]; + + /** + * The application's middleware aliases. + * + * Aliases may be used instead of class names to conveniently assign middleware to routes and groups. + * + * @var array + */ + protected $middlewareAliases = [ + '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, + 'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class, + 'signed' => \App\Http\Middleware\ValidateSignature::class, + 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, + 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + ]; +} diff --git a/api/app/Http/Middleware/Authenticate.php b/api/app/Http/Middleware/Authenticate.php new file mode 100644 index 0000000..d4ef644 --- /dev/null +++ b/api/app/Http/Middleware/Authenticate.php @@ -0,0 +1,17 @@ +expectsJson() ? null : route('login'); + } +} diff --git a/api/app/Http/Middleware/EncryptCookies.php b/api/app/Http/Middleware/EncryptCookies.php new file mode 100644 index 0000000..867695b --- /dev/null +++ b/api/app/Http/Middleware/EncryptCookies.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + // + ]; +} diff --git a/api/app/Http/Middleware/PreventRequestsDuringMaintenance.php b/api/app/Http/Middleware/PreventRequestsDuringMaintenance.php new file mode 100644 index 0000000..74cbd9a --- /dev/null +++ b/api/app/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + // + ]; +} diff --git a/api/app/Http/Middleware/RedirectIfAuthenticated.php b/api/app/Http/Middleware/RedirectIfAuthenticated.php new file mode 100644 index 0000000..afc78c4 --- /dev/null +++ b/api/app/Http/Middleware/RedirectIfAuthenticated.php @@ -0,0 +1,30 @@ +check()) { + return redirect(RouteServiceProvider::HOME); + } + } + + return $next($request); + } +} diff --git a/api/app/Http/Middleware/TrimStrings.php b/api/app/Http/Middleware/TrimStrings.php new file mode 100644 index 0000000..88cadca --- /dev/null +++ b/api/app/Http/Middleware/TrimStrings.php @@ -0,0 +1,19 @@ + + */ + protected $except = [ + 'current_password', + 'password', + 'password_confirmation', + ]; +} diff --git a/api/app/Http/Middleware/TrustHosts.php b/api/app/Http/Middleware/TrustHosts.php new file mode 100644 index 0000000..c9c58bd --- /dev/null +++ b/api/app/Http/Middleware/TrustHosts.php @@ -0,0 +1,20 @@ + + */ + public function hosts(): array + { + return [ + $this->allSubdomainsOfApplicationUrl(), + ]; + } +} diff --git a/api/app/Http/Middleware/TrustProxies.php b/api/app/Http/Middleware/TrustProxies.php new file mode 100644 index 0000000..3391630 --- /dev/null +++ b/api/app/Http/Middleware/TrustProxies.php @@ -0,0 +1,28 @@ +|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; +} diff --git a/api/app/Http/Middleware/ValidateSignature.php b/api/app/Http/Middleware/ValidateSignature.php new file mode 100644 index 0000000..093bf64 --- /dev/null +++ b/api/app/Http/Middleware/ValidateSignature.php @@ -0,0 +1,22 @@ + + */ + protected $except = [ + // 'fbclid', + // 'utm_campaign', + // 'utm_content', + // 'utm_medium', + // 'utm_source', + // 'utm_term', + ]; +} diff --git a/api/app/Http/Middleware/VerifyCsrfToken.php b/api/app/Http/Middleware/VerifyCsrfToken.php new file mode 100644 index 0000000..6f0f6c5 --- /dev/null +++ b/api/app/Http/Middleware/VerifyCsrfToken.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + '*' + ]; +} diff --git a/api/app/Http/Request/ChangeAdminPassword.php b/api/app/Http/Request/ChangeAdminPassword.php new file mode 100644 index 0000000..04a7352 --- /dev/null +++ b/api/app/Http/Request/ChangeAdminPassword.php @@ -0,0 +1,45 @@ + ['required', 'between:6,20'], + ]; + } + + public function messages() + { + return [ + 'password.required' => 100009, + 'password.between' => 100010, + ]; + } + + public function failedValidation(Validator $validator) + { + Yo::error_echo($validator->errors()->first()); + } +} diff --git a/api/app/Http/Request/EditAdmin.php b/api/app/Http/Request/EditAdmin.php new file mode 100644 index 0000000..621d8ca --- /dev/null +++ b/api/app/Http/Request/EditAdmin.php @@ -0,0 +1,53 @@ + ['required', 'between:1,50'], + 'nickname' => ['required', 'between:1,50'], + 'avatar' => ['between:0,200'], + 'password' => ['required', 'between:6,20'], + ]; + } + + public function messages() + { + return [ + 'account.required' => 100020, + 'account.between' => 100021, + 'nickname.required' => 100012, + 'nickname.between' => 100013, + 'avatar.between' => 100014, + 'password.required' => 100022, + 'password.between' => 100010, + ]; + } + + public function failedValidation(Validator $validator) + { + Yo::error_echo($validator->errors()->first()); + } +} diff --git a/api/app/Http/Request/EditAdminAuth.php b/api/app/Http/Request/EditAdminAuth.php new file mode 100644 index 0000000..5f20e22 --- /dev/null +++ b/api/app/Http/Request/EditAdminAuth.php @@ -0,0 +1,52 @@ + ['required', 'between:1,200'], + 'title' => ['required', 'between:1,20'], + 'icon' => ['between:0,100'], + 'message' => ['between:0,50'], + ]; + } + + public function messages() + { + return [ + 'name.required' => 100025, + 'name.between' => 100026, + 'title.required' => 100017, + 'title.between' => 100018, + 'icon.between' => 100027, + 'message.between' => 100028, + ]; + } + + public function failedValidation(Validator $validator) + { + Yo::error_echo($validator->errors()->first()); + } +} diff --git a/api/app/Http/Request/EditAdminAuthGroup.php b/api/app/Http/Request/EditAdminAuthGroup.php new file mode 100644 index 0000000..64c754a --- /dev/null +++ b/api/app/Http/Request/EditAdminAuthGroup.php @@ -0,0 +1,47 @@ + ['required', 'between:1,20'], + 'remark' => ['between:0,100'], + ]; + } + + public function messages() + { + return [ + 'name.required' => 100017, + 'name.between' => 100018, + 'remark.between' => 100019, + ]; + } + + public function failedValidation(Validator $validator) + { + Yo::error_echo($validator->errors()->first()); + } +} diff --git a/api/app/Http/Request/EditConfig.php b/api/app/Http/Request/EditConfig.php new file mode 100644 index 0000000..a299b2d --- /dev/null +++ b/api/app/Http/Request/EditConfig.php @@ -0,0 +1,47 @@ + ['required', 'between:1,50'], + 'remark' => ['between:0,100'], + ]; + } + + public function messages() + { + return [ + 'name.required' => 100031, + 'name.between' => 100032, + 'remark.between' => 100019, + ]; + } + + public function failedValidation(Validator $validator) + { + Yo::error_echo($validator->errors()->first()); + } +} diff --git a/api/app/Http/Request/UpdateAdminInfo.php b/api/app/Http/Request/UpdateAdminInfo.php new file mode 100644 index 0000000..f5ff42a --- /dev/null +++ b/api/app/Http/Request/UpdateAdminInfo.php @@ -0,0 +1,47 @@ + ['required', 'between:1,50'], + 'avatar' => ['between:0,200'], + ]; + } + + public function messages() + { + return [ + 'nickname.required' => 100012, + 'nickname.between' => 100013, + 'avatar.between' => 100014, + ]; + } + + public function failedValidation(Validator $validator) + { + Yo::error_echo($validator->errors()->first()); + } +} diff --git a/api/app/Libraries/Login.php b/api/app/Libraries/Login.php new file mode 100755 index 0000000..0546e56 --- /dev/null +++ b/api/app/Libraries/Login.php @@ -0,0 +1,77 @@ +id === 1) return ['code' => 0]; + if (self::$info->admin_auth_group === -1) return ['code' => 0]; + $auth = AdminAuth::where('id', $auth)->where('status', 1)->where('del', 2)->first(); + if (!$auth) return ['code' => 100004, 'message' => '权限不足']; + if (self::$info->admin_auth_group === 0) { + if ($auth->check !== 1) return ['code' => 100004, 'message' => '权限不足']; + } else { + if ($auth->check === 1) return ['code' => 0]; + $admin_auth = AdminAuthGroup::select('id') + ->where('id', self::$info->admin_auth_group) + ->where('del', 2) + ->first(); + if (!$admin_auth) return ['code' => 100004, 'message' => '权限不足']; + if ($admin_auth->status != 1) return ['code' => 100004, 'message' => !!$admin_auth->message ? $admin_auth->message : '权限不足']; + $admin_auths = json_decode($admin_auth, true); + if (!in_array((string)$auth, $admin_auths)) return ['code' => 100004, 'message' => !!$admin_auth->message ? $admin_auth->message : '权限不足']; + } + return ['code' => 0]; + } + + public static function admin_check($auths = [], $or_ids = []): array + { + if (!request()->header('Authorization')) return ['code' => 100002]; + $token_arr = explode('Bearer ', request()->header('Authorization')); + if (!isset($token_arr[1])) return ['code' => 100002]; + $token = $token_arr[1]; + if (!$token) return ['code' => 100002]; + $admin_token = AdminToken::where('token', $token)->where('del', 2)->where('updated_at', '>', Lu::date(time() - (60 * 60 * 24 * 3)))->first(); + if (!$admin_token) return ['code' => 100002]; + $admin = Admin::where('id', $admin_token->admin)->where('del', 2)->where('status', 1)->first(); + if (!$admin) return ['code' => 100003]; + self::$info = $admin; + self::$token = $admin_token; + self::$type = 'admin'; + foreach ($auths as $item) { + $auth_check_res = self::check_admin_auth($item); + if ($auth_check_res['code'] != 0) return $auth_check_res; + } + $ret = 0; + $ret_code = ['code' => 0]; + foreach ($or_ids as $item) { + $auth_check_res = self::check_admin_auth($item); + if ($auth_check_res['code'] == 0) { + $ret++; + } else { + $ret_code = $auth_check_res; + } + } + if ($ret == 0 && $ret_code != 0) return $ret_code; + $admin_token->updated_at = Lu::date(); + $admin_token->save(); + return ['code' => 0]; + } + + public static function admin($auths = [], $or_ids = []) + { + $check_res = self::admin_check($auths, $or_ids); + if ($check_res['code'] != 0) Yo::error_echo($check_res['code'], [ + isset($check_res['message']) && !!$check_res['message'] ? $check_res['message'] : '' + ]); + } +} diff --git a/api/app/Libraries/Lu.php b/api/app/Libraries/Lu.php new file mode 100644 index 0000000..5ee1292 --- /dev/null +++ b/api/app/Libraries/Lu.php @@ -0,0 +1,185 @@ +c === 0) { + Schema::create($table_name, function (Blueprint $table) { + $table->id(); + $table->string('uuid', 50); + $table->string('token', 50); + $table->string('ip', 15); + $table->string('url', 300); + $table->string('method', 10); + $table->longtext('params'); + $table->tinyInteger('type')->comment('1-文字 2-文件'); + $table->longtext('input'); + $table->longtext('header'); + $table->string('code', 10)->nullable(); + $table->text('result')->nullable(); + $table->decimal('spend', 6, 3)->nullable(); + $table->timestamps(); + }); + } + self::$request = new \App\Models\RequestLog; + self::$request->setTable($table_name); + } + + public static function RequestLog() + { + if ($_SERVER['REQUEST_METHOD'] !== 'OPTIONS' && env('REQUEST_LOG') && !self::$request) { + self::CheckTableName(); + self::$spend = self::time(); + $token = ''; + if (!!request()->header('Authorization')) { + $token_arr = explode('Bearer ', request()->header('Authorization')); + $token = $token_arr[1] ?? ''; + } + $uuid = Str::orderedUuid(); + $date = date('Y/m/d'); + self::$path = "log/$date/$uuid.txt"; + self::$request->uuid = $uuid; + self::$request->token = $token; + self::$request->ip = self::ip(); + self::$request->url = explode('?', $_SERVER['REQUEST_URI'])[0]; + self::$request->method = $_SERVER['REQUEST_METHOD']; + $type = 1; + $input_data = !!request()->post() ? json_encode(request()->post(), JSON_UNESCAPED_UNICODE) : '{}'; + $str_len = mb_strlen($input_data); + $str_size = $str_len / 1024; + if ($str_size > 40) $type = 2; + $params_data = !!$_GET ? json_encode($_GET, JSON_UNESCAPED_UNICODE) : '{}'; + $header_data = !!request()->header() ? self::transformedHeaders() : '{}'; + $str_len = mb_strlen($header_data); + $str_size = $str_len / 1024; + if ($str_size > 40) $type = 2; + self::$request->input = $input_data; + self::$request->params = $params_data; + self::$request->header = $header_data; + self::$request->type = $type; + self::$request->save(); + } + } + + public static function transformedHeaders() + { + $header_data = request()->header(); + $header = []; + foreach ($header_data as $key => $header_datum) { + if (count($header_datum) == 1) { + $header[$key] = $header_datum[0]; + } else { + $header[$key] = $header_datum; + } + } + return json_encode($header, JSON_UNESCAPED_UNICODE); + } + + public static function ip() + { + if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) { + $ip = getenv('HTTP_CLIENT_IP'); + } elseif (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) { + $ip = getenv('HTTP_X_FORWARDED_FOR'); + } elseif (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) { + $ip = getenv('REMOTE_ADDR'); + } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) { + $ip = $_SERVER['REMOTE_ADDR']; + } + $res = preg_match('/[\d\.]{7,15}/', $ip, $matches) ? $matches [0] : ''; + return $res; + } + + public static function date($time = false, $format = "Y-m-d H:i:s") + { + if (!$time) $time = time(); + return date($format, $time); + } + + public static function time() + { + return floor(microtime(true) * 1000); + } + + public static function exit($data = []) + { + $res = $data; + if ($_SERVER['REQUEST_METHOD'] !== 'OPTIONS' && env('REQUEST_LOG') && !!self::$request) { + $data_str = !!$data ? json_encode($data, JSON_UNESCAPED_UNICODE) : '{}'; + $str_len = strlen($data_str); + $str_size = $str_len / 1024; + $type = self::$request->type; + if ($str_size > 40) $type = 2; + if ($type == 2) { + $input_data = self::$request->input; + $header_data = self::$request->header; + $disk = Storage::disk('local'); + $disk->append(self::$path, "POST: +$input_data +------------------------------- +HEADER: +$header_data +------------------------------- +RESULT: +$data_str"); + self::$request->input = self::$path; + self::$request->header = self::$path; + self::$request->result = self::$path; + self::$request->type = 2; + } else { + self::$request->result = $data_str; + } + self::$request->code = (isset($data['code']) && !!$data['code']) ? $data['code'] : 0; + self::$request->spend = (self::time() - self::$spend) / 1000; + self::$request->save(); + } + return response()->json($res)->setEncodingOptions(JSON_UNESCAPED_UNICODE); + } + + public static function echo($message = '', $code = 200, $data = []) + { + $return = []; + $return['code'] = intval($code); + if ($message) $return['message'] = $message; + if ($data) $return['data'] = $data; + return self::exit($return); + } + + public static function post($url, $data, $type = 'json') + { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POST, true); + if ($type === 'data') { + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); + } + if ($type === 'json') { + $data_string = json_encode($data, JSON_UNESCAPED_UNICODE); + curl_setopt($curl, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json; charset=utf-8', + 'Content-Length: ' . strlen($data_string) + ]); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); + } + $r = curl_exec($curl); + curl_close($curl); + return $r; + } +} diff --git a/api/app/Libraries/Yo.php b/api/app/Libraries/Yo.php new file mode 100755 index 0000000..41da2b6 --- /dev/null +++ b/api/app/Libraries/Yo.php @@ -0,0 +1,39 @@ + $id]); + } + + public static function delete_echo($id = 0) + { + return Lu::echo(config('code.200.d'), 200, ['id' => $id]); + } + + public static function update_echo($id = 0) + { + return Lu::echo(config('code.200.u'), 200, ['id' => $id]); + } + + public static function error_echo($code, $replace = []) + { + $msg = config("code.{$code}"); + if (count($replace)) $msg = Str::replaceArray('?', $replace, $msg); + throw new HttpResponseException(Lu::echo($msg, $code)); + } + + public static function debug($data) + { + throw new HttpResponseException(Lu::echo('Debug', 100000, $data)); + } + + public static function echo($data = []) + { + return Lu::echo(config('code.200.r'), 200, $data); + } +} diff --git a/api/app/Models/Admin.php b/api/app/Models/Admin.php new file mode 100644 index 0000000..8626776 --- /dev/null +++ b/api/app/Models/Admin.php @@ -0,0 +1,10 @@ +format('Y-m-d H:i:s'); + } +} diff --git a/api/app/Models/RequestLog.php b/api/app/Models/RequestLog.php new file mode 100644 index 0000000..1b48c86 --- /dev/null +++ b/api/app/Models/RequestLog.php @@ -0,0 +1,10 @@ + + */ + protected $policies = [ + // + ]; + + /** + * Register any authentication / authorization services. + */ + public function boot(): void + { + // + } +} diff --git a/api/app/Providers/BroadcastServiceProvider.php b/api/app/Providers/BroadcastServiceProvider.php new file mode 100644 index 0000000..2be04f5 --- /dev/null +++ b/api/app/Providers/BroadcastServiceProvider.php @@ -0,0 +1,19 @@ +> + */ + protected $listen = [ + Registered::class => [ + SendEmailVerificationNotification::class, + ], + ]; + + /** + * Register any events for your application. + */ + public function boot(): void + { + // + } + + /** + * Determine if events and listeners should be automatically discovered. + */ + public function shouldDiscoverEvents(): bool + { + return false; + } +} diff --git a/api/app/Providers/RouteServiceProvider.php b/api/app/Providers/RouteServiceProvider.php new file mode 100644 index 0000000..1cf5f15 --- /dev/null +++ b/api/app/Providers/RouteServiceProvider.php @@ -0,0 +1,40 @@ +by($request->user()?->id ?: $request->ip()); + }); + + $this->routes(function () { + Route::middleware('api') + ->prefix('api') + ->group(base_path('routes/api.php')); + + Route::middleware('web') + ->group(base_path('routes/web.php')); + }); + } +} diff --git a/api/artisan b/api/artisan new file mode 100755 index 0000000..67a3329 --- /dev/null +++ b/api/artisan @@ -0,0 +1,53 @@ +#!/usr/bin/env php +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); diff --git a/api/bootstrap/app.php b/api/bootstrap/app.php new file mode 100644 index 0000000..037e17d --- /dev/null +++ b/api/bootstrap/app.php @@ -0,0 +1,55 @@ +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; diff --git a/api/bootstrap/cache/.gitignore b/api/bootstrap/cache/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/api/bootstrap/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/api/composer.json b/api/composer.json new file mode 100644 index 0000000..af3759d --- /dev/null +++ b/api/composer.json @@ -0,0 +1,72 @@ +{ + "name": "laravel/laravel", + "type": "project", + "description": "The skeleton application for the Laravel framework.", + "keywords": [ + "laravel", + "framework" + ], + "license": "MIT", + "require": { + "php": "^8.1", + "guzzlehttp/guzzle": "^7.2", + "laravel/framework": "^10.10", + "laravel/sanctum": "^3.2", + "laravel/tinker": "^2.8" + }, + "require-dev": { + "fakerphp/faker": "^1.9.1", + "laravel/pint": "^1.0", + "laravel/sail": "^1.18", + "mockery/mockery": "^1.4.4", + "nunomaduro/collision": "^7.0", + "phpunit/phpunit": "^10.1", + "spatie/laravel-ignition": "^2.0" + }, + "autoload": { + "classmap": [ + "app/Libraries" + ], + "psr-4": { + "App\\": "app/", + "Database\\Factories\\": "database/factories/", + "Database\\Seeders\\": "database/seeders/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + }, + "scripts": { + "post-autoload-dump": [ + "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", + "@php artisan package:discover --ansi" + ], + "post-update-cmd": [ + "@php artisan vendor:publish --tag=laravel-assets --ansi --force" + ], + "post-root-package-install": [ + "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" + ], + "post-create-project-cmd": [ + "@php artisan key:generate --ansi" + ] + }, + "extra": { + "laravel": { + "dont-discover": [] + } + }, + "config": { + "optimize-autoloader": true, + "preferred-install": "dist", + "sort-packages": true, + "allow-plugins": { + "pestphp/pest-plugin": true, + "php-http/discovery": true + } + }, + "minimum-stability": "stable", + "prefer-stable": true +} diff --git a/api/composer.lock b/api/composer.lock new file mode 100644 index 0000000..fe3a15c --- /dev/null +++ b/api/composer.lock @@ -0,0 +1,6006 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "aa322c53454393ed775cfe4807d54a50", + "packages": [ + { + "name": "brick/math", + "version": "0.11.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/brick/math/0.11.0/brick-math-0.11.0.zip", + "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^9.0", + "vimeo/psalm": "5.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "brick", + "math" + ], + "time": "2023-01-15T23:15:59+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.2", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/dflydev/dot-access-data/v3.0.2/dflydev-dot-access-data-v3.0.2.zip", + "reference": "f41715465d65213d644d3141a6a93081be5d3549", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "time": "2022-10-27T11:44:00+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.8", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/doctrine/inflector/2.0.8/doctrine-inflector-2.0.8.zip", + "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "time": "2023-06-16T13:40:37+00:00" + }, + { + "name": "doctrine/lexer", + "version": "3.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/doctrine/lexer/3.0.0/doctrine-lexer-3.0.0.zip", + "reference": "84a527db05647743d50373e0ec53a152f2cde568", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "time": "2022-12-15T16:57:16+00:00" + }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.3.2", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/dragonmantank/cron-expression/v3.3.2/dragonmantank-cron-expression-v3.3.2.zip", + "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-webmozart-assert": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "time": "2022-09-10T18:51:20+00:00" + }, + { + "name": "egulias/email-validator", + "version": "4.0.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/egulias/email-validator/4.0.1/egulias-email-validator-4.0.1.zip", + "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^4.30" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "time": "2023-01-14T14:17:03+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.2.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/fruitcake/php-cors/v1.2.0/fruitcake-php-cors-v1.2.0.zip", + "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "time": "2022-02-20T15:07:15+00:00" + }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/graham-campbell/result-type/v1.1.1/graham-campbell-result-type-v1.1.1.zip", + "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "time": "2023-02-25T20:23:15+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.7.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/guzzle/7.7.0/guzzlehttp-guzzle-7.7.0.zip", + "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "time": "2023-05-21T14:04:53+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/promises/2.0.0/guzzlehttp-promises-2.0.0.zip", + "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2023-05-21T13:50:22+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.5.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/psr7/2.5.0/guzzlehttp-psr7-2.5.0.zip", + "reference": "b635f279edd83fc275f822a1188157ffea568ff6", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2023-04-17T16:11:26+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/uri-template/v1.0.1/guzzlehttp-uri-template-v1.0.1.zip", + "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.17" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.19 || ^9.5.8", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "time": "2021-10-07T12:57:01+00:00" + }, + { + "name": "laravel/framework", + "version": "v10.16.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/laravel/framework/v10.16.1/laravel-framework-v10.16.1.zip", + "reference": "5c93d2795c393b462481179ce42dedfb30cc19b5", + "shasum": "" + }, + "require": { + "brick/math": "^0.9.3|^0.10.2|^0.11", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.3.2", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/serializable-closure": "^1.3", + "league/commonmark": "^2.2.1", + "league/flysystem": "^3.8.0", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^2.62.1", + "nunomaduro/termwind": "^1.13", + "php": "^8.1", + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^6.2", + "symfony/error-handler": "^6.2", + "symfony/finder": "^6.2", + "symfony/http-foundation": "^6.2", + "symfony/http-kernel": "^6.2", + "symfony/mailer": "^6.2", + "symfony/mime": "^6.2", + "symfony/process": "^6.2", + "symfony/routing": "^6.2", + "symfony/uid": "^6.2", + "symfony/var-dumper": "^6.2", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", + "vlucas/phpdotenv": "^5.4.1", + "voku/portable-ascii": "^2.0" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "self.version", + "illuminate/conditionable": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/macroable": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/testing": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version" + }, + "require-dev": { + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.235.5", + "doctrine/dbal": "^3.5.1", + "ext-gmp": "*", + "fakerphp/faker": "^1.21", + "guzzlehttp/guzzle": "^7.5", + "league/flysystem-aws-s3-v3": "^3.0", + "league/flysystem-ftp": "^3.0", + "league/flysystem-path-prefixing": "^3.3", + "league/flysystem-read-only": "^3.3", + "league/flysystem-sftp-v3": "^3.0", + "mockery/mockery": "^1.5.1", + "orchestra/testbench-core": "^8.4", + "pda/pheanstalk": "^4.0", + "phpstan/phpdoc-parser": "^1.15", + "phpstan/phpstan": "^1.4.7", + "phpunit/phpunit": "^10.0.7", + "predis/predis": "^2.0.2", + "symfony/cache": "^6.2", + "symfony/http-client": "^6.2.4" + }, + "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.235.5).", + "brianium/paratest": "Required to run tests in parallel (^6.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^3.5.1).", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", + "ext-ftp": "Required to use the Flysystem FTP driver.", + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "ext-memcached": "Required to use the memcache cache driver.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", + "ext-posix": "Required to use all features of the queue worker.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "guzzlehttp/guzzle": "Required to use the HTTP Client and the ping methods on schedules (^7.5).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).", + "league/flysystem-read-only": "Required to use read-only disks (^3.3)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", + "mockery/mockery": "Required to use mocking (^1.5.1).", + "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", + "phpunit/phpunit": "Required to use assertions and run tests (^9.5.8|^10.0.7).", + "predis/predis": "Required to use the predis connector (^2.0.2).", + "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^6.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^6.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^6.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "files": [ + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Support/helpers.php" + ], + "psr-4": { + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" + ] + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "time": "2023-07-26T03:30:46+00:00" + }, + { + "name": "laravel/sanctum", + "version": "v3.2.5", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/laravel/sanctum/v3.2.5/laravel-sanctum-v3.2.5.zip", + "reference": "8ebda85d59d3c414863a7f4d816ef8302faad876", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^9.21|^10.0", + "illuminate/contracts": "^9.21|^10.0", + "illuminate/database": "^9.21|^10.0", + "illuminate/support": "^9.21|^10.0", + "php": "^8.0.2" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "orchestra/testbench": "^7.0|^8.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Sanctum\\SanctumServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sanctum\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.", + "keywords": [ + "auth", + "laravel", + "sanctum" + ], + "time": "2023-05-01T19:39:51+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v1.3.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/laravel/serializable-closure/v1.3.1/laravel-serializable-closure-v1.3.1.zip", + "reference": "e5a3057a5591e1cfe8183034b0203921abe2c902", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "nesbot/carbon": "^2.61", + "pestphp/pest": "^1.21.3", + "phpstan/phpstan": "^1.8.2", + "symfony/var-dumper": "^5.4.11" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "time": "2023-07-14T13:56:28+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.8.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/laravel/tinker/v2.8.1/laravel-tinker-v2.8.1.zip", + "reference": "04a2d3bd0d650c0764f70bf49d1ee39393e4eb10", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.10.4|^0.11.1", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0" + }, + "require-dev": { + "mockery/mockery": "~1.3.3|^1.4.2", + "phpunit/phpunit": "^8.5.8|^9.3.3" + }, + "suggest": { + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "time": "2023-02-15T16:40:09+00:00" + }, + { + "name": "league/commonmark", + "version": "2.4.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/league/commonmark/2.4.0/league-commonmark-2.4.0.zip", + "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.30.0", + "commonmark/commonmark.js": "0.30.0", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\": "src" + } + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", + "keywords": [ + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" + ], + "time": "2023-03-24T15:16:10+00:00" + }, + { + "name": "league/config", + "version": "v1.2.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/league/config/v1.2.0/league-config-v1.2.0.zip", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Config\\": "src" + } + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], + "time": "2022-12-11T20:36:23+00:00" + }, + { + "name": "league/flysystem", + "version": "3.15.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/league/flysystem/3.15.1/league-flysystem-3.15.1.zip", + "reference": "a141d430414fcb8bf797a18716b09f759a385bed", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5", + "async-aws/simple-s3": "^1.1", + "aws/aws-sdk-php": "^3.220.0", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "microsoft/azure-storage-blob": "^1.1", + "phpseclib/phpseclib": "^3.0.14", + "phpstan/phpstan": "^0.12.26", + "phpunit/phpunit": "^9.5.11", + "sabre/dav": "^4.3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "time": "2023-05-04T09:04:26+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.15.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/league/flysystem-local/3.15.0/league-flysystem-local-3.15.0.zip", + "reference": "543f64c397fefdf9cfeac443ffb6beff602796b3", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "time": "2023-05-02T20:02:14+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.11.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/league/mime-type-detection/1.11.0/league-mime-type-detection-1.11.0.zip", + "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "time": "2022-04-17T13:12:02+00:00" + }, + { + "name": "monolog/monolog", + "version": "3.4.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/monolog/monolog/3.4.0/monolog-monolog-3.4.0.zip", + "reference": "e2392369686d420ca32df3803de28b5d6f76867d", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.4", + "phpunit/phpunit": "^10.1", + "predis/predis": "^1.1 || ^2", + "ruflin/elastica": "^7", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "time": "2023-06-21T08:46:11+00:00" + }, + { + "name": "nesbot/carbon", + "version": "2.68.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/nesbot/carbon/2.68.1/nesbot-carbon-2.68.1.zip", + "reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + }, + "require-dev": { + "doctrine/dbal": "^2.0 || ^3.1.4", + "doctrine/orm": "^2.7", + "friendsofphp/php-cs-fixer": "^3.0", + "kylekatarnls/multi-tester": "^2.0", + "ondrejmirtes/better-reflection": "*", + "phpmd/phpmd": "^2.9", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.99 || ^1.7.14", + "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", + "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", + "squizlabs/php_codesniffer": "^3.4" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.x-dev", + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "time": "2023-06-20T18:29:04+00:00" + }, + { + "name": "nette/schema", + "version": "v1.2.3", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/nette/schema/v1.2.3/nette-schema-v1.2.3.zip", + "reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f", + "shasum": "" + }, + "require": { + "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", + "php": ">=7.1 <8.3" + }, + "require-dev": { + "nette/tester": "^2.3 || ^2.4", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "^2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "time": "2022-10-13T01:24:26+00:00" + }, + { + "name": "nette/utils", + "version": "v4.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/nette/utils/v4.0.0/nette-utils-v4.0.0.zip", + "reference": "cacdbf5a91a657ede665c541eda28941d4b09c1e", + "shasum": "" + }, + "require": { + "php": ">=8.0 <8.3" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "dev-master", + "nette/tester": "^2.4", + "phpstan/phpstan": "^1.0", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()", + "ext-xml": "to use Strings::length() etc. when mbstring is not available" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "time": "2023-02-02T10:41:53+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.16.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/nikic/php-parser/v4.16.0/nikic-php-parser-v4.16.0.zip", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2023-06-25T14:52:30+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "v1.15.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/nunomaduro/termwind/v1.15.1/nunomaduro-termwind-v1.15.1.zip", + "reference": "8ab0b32c8caa4a2e09700ea32925441385e4a5dc", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.0", + "symfony/console": "^5.3.0|^6.0.0" + }, + "require-dev": { + "ergebnis/phpstan-rules": "^1.0.", + "illuminate/console": "^8.0|^9.0", + "illuminate/support": "^8.0|^9.0", + "laravel/pint": "^1.0.0", + "pestphp/pest": "^1.21.0", + "pestphp/pest-plugin-mock": "^1.0", + "phpstan/phpstan": "^1.4.6", + "phpstan/phpstan-strict-rules": "^1.1.0", + "symfony/var-dumper": "^5.2.7|^6.0.0", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], + "time": "2023-02-08T01:06:31+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/phpoption/phpoption/1.9.1/phpoption-phpoption-1.9.1.zip", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "time": "2023-02-25T19:38:58+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/container/2.0.2/psr-container-2.0.2.zip", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/event-dispatcher/1.0.0/psr-event-dispatcher-1.0.0.zip", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.2", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-client/1.0.2/psr-http-client-1.0.2.zip", + "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "time": "2023-04-10T20:12:12+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.2", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-factory/1.0.2/psr-http-factory-1.0.2.zip", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "time": "2023-04-10T20:10:41+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-message/2.0/psr-http-message-2.0.zip", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/log/3.0.0/psr-log-3.0.0.zip", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/simple-cache/3.0.0/psr-simple-cache-3.0.0.zip", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.11.19", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/psy/psysh/v0.11.19/psy-psysh-v0.11.19.zip", + "reference": "1724ceff278daeeac5a006744633bacbb2dc4706", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^4.0 || ^3.1", + "php": "^8.0 || ^7.0.8", + "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.11.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "time": "2023-07-15T19:42:19+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/ralouphie/getallheaders/3.0.3/ralouphie-getallheaders-3.0.3.zip", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/ramsey/collection/2.0.0/ramsey-collection-2.0.0.zip", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.28.3", + "fakerphp/faker": "^1.21", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^1.0", + "mockery/mockery": "^1.5", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcsstandards/phpcsutils": "^1.0.0-rc1", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18.4", + "ramsey/coding-standard": "^2.0.3", + "ramsey/conventional-commits": "^1.3", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "time": "2022-12-31T21:50:55+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.7.4", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/ramsey/uuid/4.7.4/ramsey-uuid-4.7.4.zip", + "reference": "60a4c63ab724854332900504274f6150ff26d286", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11", + "ext-json": "*", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^8.5 || ^9", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "time": "2023-04-15T23:01:58+00:00" + }, + { + "name": "symfony/console", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/console/v6.3.0/symfony-console-v6.3.0.zip", + "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "time": "2023-05-29T12:49:39+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/css-selector/v6.3.0/symfony-css-selector-v6.3.0.zip", + "reference": "88453e64cd86c5b60e8d2fb2c6f953bbc353ffbf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "time": "2023-03-20T16:43:42+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/deprecation-contracts/v3.3.0/symfony-deprecation-contracts-v3.3.0.zip", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "time": "2023-05-23T14:45:45+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/error-handler/v6.3.0/symfony-error-handler-v6.3.0.zip", + "reference": "99d2d814a6351461af350ead4d963bd67451236f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^5.4|^6.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/serializer": "^5.4|^6.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "time": "2023-05-10T12:03:13+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/event-dispatcher/v6.3.0/symfony-event-dispatcher-v6.3.0.zip", + "reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "time": "2023-04-21T14:41:17+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/event-dispatcher-contracts/v3.3.0/symfony-event-dispatcher-contracts-v3.3.0.zip", + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2023-05-23T14:45:45+00:00" + }, + { + "name": "symfony/finder", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/finder/v6.3.0/symfony-finder-v6.3.0.zip", + "reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "time": "2023-04-02T01:25:41+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v6.3.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/http-foundation/v6.3.1/symfony-http-foundation-v6.3.1.zip", + "reference": "e0ad0d153e1c20069250986cd9e9dd1ccebb0d66", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "symfony/cache": "<6.2" + }, + "require-dev": { + "doctrine/dbal": "^2.13.1|^3.0", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", + "symfony/mime": "^5.4|^6.0", + "symfony/rate-limiter": "^5.2|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "time": "2023-06-24T11:51:27+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v6.3.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/http-kernel/v6.3.1/symfony-http-kernel-v6.3.1.zip", + "reference": "161e16fd2e35fb4881a43bc8b383dfd5be4ac374", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.3", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/http-foundation": "^6.2.7", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<5.4", + "symfony/cache": "<5.4", + "symfony/config": "<6.1", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<6.3", + "symfony/doctrine-bridge": "<5.4", + "symfony/form": "<5.4", + "symfony/http-client": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<5.4", + "symfony/messenger": "<5.4", + "symfony/translation": "<5.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<5.4", + "symfony/validator": "<5.4", + "symfony/var-dumper": "<6.3", + "twig/twig": "<2.13" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^5.4|^6.0", + "symfony/clock": "^6.2", + "symfony/config": "^6.1", + "symfony/console": "^5.4|^6.0", + "symfony/css-selector": "^5.4|^6.0", + "symfony/dependency-injection": "^6.3", + "symfony/dom-crawler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^5.4|^6.0", + "symfony/property-access": "^5.4.5|^6.0.5", + "symfony/routing": "^5.4|^6.0", + "symfony/serializer": "^6.3", + "symfony/stopwatch": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^5.4|^6.0", + "symfony/validator": "^6.3", + "symfony/var-exporter": "^6.2", + "twig/twig": "^2.13|^3.0.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "time": "2023-06-26T06:07:32+00:00" + }, + { + "name": "symfony/mailer", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/mailer/v6.3.0/symfony-mailer-v6.3.0.zip", + "reference": "7b03d9be1dea29bfec0a6c7b603f5072a4c97435", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.1", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/mime": "^6.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/messenger": "^6.2", + "symfony/twig-bridge": "^6.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "time": "2023-05-29T12:49:39+00:00" + }, + { + "name": "symfony/mime", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/mime/v6.3.0/symfony-mime-v6.3.0.zip", + "reference": "7b5d2121858cd6efbed778abce9cfdd7ab1f62ad", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<5.4", + "symfony/serializer": "<6.2" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/property-info": "^5.4|^6.0", + "symfony/serializer": "^6.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "time": "2023-04-28T15:57:00+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-ctype/v1.27.0/symfony-polyfill-ctype-v1.27.0.zip", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-intl-grapheme/v1.27.0/symfony-polyfill-intl-grapheme-v1.27.0.zip", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.27.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-intl-idn/v1.27.0/symfony-polyfill-intl-idn-v1.27.0.zip", + "reference": "639084e360537a19f9ee352433b84ce831f3d2da", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-intl-normalizer": "^1.10", + "symfony/polyfill-php72": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.27.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-intl-normalizer/v1.27.0/symfony-polyfill-intl-normalizer-v1.27.0.zip", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-mbstring/v1.27.0/symfony-polyfill-mbstring-v1.27.0.zip", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.27.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-php72/v1.27.0/symfony-polyfill-php72-v1.27.0.zip", + "reference": "869329b1e9894268a8a61dabb69153029b7a8c97", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.27.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-php80/v1.27.0/symfony-polyfill-php80-v1.27.0.zip", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.27.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-php83/v1.27.0/symfony-polyfill-php83-v1.27.0.zip", + "reference": "508c652ba3ccf69f8c97f251534f229791b52a57", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-php80": "^1.14" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.27.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-uuid/v1.27.0/symfony-polyfill-uuid-v1.27.0.zip", + "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/process", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/process/v6.3.0/symfony-process-v6.3.0.zip", + "reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "time": "2023-05-19T08:06:44+00:00" + }, + { + "name": "symfony/routing", + "version": "v6.3.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/routing/v6.3.1/symfony-routing-v6.3.1.zip", + "reference": "d37ad1779c38b8eb71996d17dc13030dcb7f9cf5", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "conflict": { + "doctrine/annotations": "<1.12", + "symfony/config": "<6.2", + "symfony/dependency-injection": "<5.4", + "symfony/yaml": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.12|^2", + "psr/log": "^1|^2|^3", + "symfony/config": "^6.2", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2023-06-05T15:30:22+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/service-contracts/v3.3.0/symfony-service-contracts-v3.3.0.zip", + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2023-05-23T14:45:45+00:00" + }, + { + "name": "symfony/string", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/string/v6.3.0/symfony-string-v6.3.0.zip", + "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "time": "2023-03-21T21:06:29+00:00" + }, + { + "name": "symfony/translation", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/translation/v6.3.0/symfony-translation-v6.3.0.zip", + "reference": "f72b2cba8f79dd9d536f534f76874b58ad37876f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^4.13", + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "time": "2023-05-19T12:46:45+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/translation-contracts/v3.3.0/symfony-translation-contracts-v3.3.0.zip", + "reference": "02c24deb352fb0d79db5486c0c79905a85e37e86", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2023-05-30T17:17:10+00:00" + }, + { + "name": "symfony/uid", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/uid/v6.3.0/symfony-uid-v6.3.0.zip", + "reference": "01b0f20b1351d997711c56f1638f7a8c3061e384", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "time": "2023-04-08T07:25:02+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v6.3.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/var-dumper/v6.3.1/symfony-var-dumper-v6.3.1.zip", + "reference": "c81268d6960ddb47af17391a27d222bd58cf0515", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2023-06-21T12:08:28+00:00" + }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "2.2.6", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/tijsverkoyen/css-to-inline-styles/2.2.6/tijsverkoyen-css-to-inline-styles-2.2.6.zip", + "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^5.5 || ^7.0 || ^8.0", + "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^7.5 || ^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "time": "2023-01-03T09:29:04+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.5.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/vlucas/phpdotenv/v5.5.0/vlucas-phpdotenv-v5.5.0.zip", + "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.0.2", + "php": "^7.1.3 || ^8.0", + "phpoption/phpoption": "^1.8", + "symfony/polyfill-ctype": "^1.23", + "symfony/polyfill-mbstring": "^1.23.1", + "symfony/polyfill-php80": "^1.23.1" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-filter": "*", + "phpunit/phpunit": "^7.5.20 || ^8.5.30 || ^9.5.25" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "5.5-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "time": "2022-10-16T01:01:54+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/voku/portable-ascii/2.0.1/voku-portable-ascii-2.0.1.zip", + "reference": "b56450eed252f6801410d810c8e1727224ae0743", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "http://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "time": "2022-03-08T17:03:00+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/webmozart/assert/1.11.0/webmozart-assert-1.11.0.zip", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "fakerphp/faker", + "version": "v1.23.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/fakerphp/faker/v1.23.0/fakerphp-faker-v1.23.0.zip", + "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "v1.21-dev" + } + }, + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "time": "2023-06-12T08:44:38+00:00" + }, + { + "name": "filp/whoops", + "version": "2.15.3", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/filp/whoops/2.15.3/filp-whoops-2.15.3.zip", + "reference": "c83e88a30524f9360b11f585f71e6b17313b7187", + "shasum": "" + }, + "require": { + "php": "^5.5.9 || ^7.0 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^0.9 || ^1.0", + "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "time": "2023-07-13T12:00:00+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.0.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/hamcrest/hamcrest-php/v2.0.1/hamcrest-hamcrest-php-v2.0.1.zip", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "shasum": "" + }, + "require": { + "php": "^5.3|^7.0|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "time": "2020-07-09T08:09:16+00:00" + }, + { + "name": "laravel/pint", + "version": "v1.10.5", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/laravel/pint/v1.10.5/laravel-pint-v1.10.5.zip", + "reference": "a458fb057bfa2f5a09888a8aa349610be807b0c3", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "ext-xml": "*", + "php": "^8.1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.21.1", + "illuminate/view": "^10.5.1", + "laravel-zero/framework": "^10.1.1", + "mockery/mockery": "^1.5.1", + "nunomaduro/larastan": "^2.5.1", + "nunomaduro/termwind": "^1.15.1", + "pestphp/pest": "^2.4.0" + }, + "bin": [ + "builds/pint" + ], + "type": "project", + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "An opinionated code formatter for PHP.", + "homepage": "https://laravel.com", + "keywords": [ + "format", + "formatter", + "lint", + "linter", + "php" + ], + "time": "2023-07-14T10:26:01+00:00" + }, + { + "name": "laravel/sail", + "version": "v1.23.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/laravel/sail/v1.23.1/laravel-sail-v1.23.1.zip", + "reference": "62582606f80466aa81fba40b193b289106902853", + "shasum": "" + }, + "require": { + "illuminate/console": "^8.0|^9.0|^10.0", + "illuminate/contracts": "^8.0|^9.0|^10.0", + "illuminate/support": "^8.0|^9.0|^10.0", + "php": "^8.0", + "symfony/yaml": "^6.0" + }, + "require-dev": { + "orchestra/testbench": "^6.0|^7.0|^8.0", + "phpstan/phpstan": "^1.10" + }, + "bin": [ + "bin/sail" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Sail\\SailServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sail\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Docker files for running a basic Laravel application.", + "keywords": [ + "docker", + "laravel" + ], + "time": "2023-06-28T18:31:28+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.4", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/mockery/mockery/1.6.4/mockery-mockery-1.6.4.zip", + "reference": "d1413755e26fe56a63455f7753221c86cbb88f66", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.4,<8.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.3", + "psalm/plugin-phpunit": "^0.18.4", + "symplify/easy-coding-standard": "^11.5.0", + "vimeo/psalm": "^5.13.1" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "time": "2023-07-19T15:51:02+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/myclabs/deep-copy/1.11.1/myclabs-deep-copy-1.11.1.zip", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2023-03-08T13:26:56+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v7.7.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/nunomaduro/collision/v7.7.0/nunomaduro-collision-v7.7.0.zip", + "reference": "69a07197d055456d29911116fca3bc2c985f524b", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.15.2", + "nunomaduro/termwind": "^1.15.1", + "php": "^8.1.0", + "symfony/console": "^6.3.0" + }, + "conflict": { + "phpunit/phpunit": "<10.1.2" + }, + "require-dev": { + "brianium/paratest": "^7.2.2", + "laravel/framework": "^10.14.1", + "laravel/pint": "^1.10.3", + "laravel/sail": "^1.23.0", + "laravel/sanctum": "^3.2.5", + "laravel/tinker": "^2.8.1", + "nunomaduro/larastan": "^2.6.3", + "orchestra/testbench-core": "^8.5.8", + "pestphp/pest": "^2.8.1", + "phpunit/phpunit": "^10.2.2", + "sebastian/environment": "^6.0.1", + "spatie/laravel-ignition": "^2.2.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "time": "2023-06-29T09:10:16+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/phar-io/manifest/2.0.3/phar-io-manifest-2.0.3.zip", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/phar-io/version/3.2.1/phar-io-version-3.2.1.zip", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.1.2", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/phpunit/php-code-coverage/10.1.2/phpunit-php-code-coverage-10.1.2.zip", + "reference": "db1497ec8dd382e82c962f7abbe0320e4882ee4e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.15", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-text-template": "^3.0", + "sebastian/code-unit-reverse-lookup": "^3.0", + "sebastian/complexity": "^3.0", + "sebastian/environment": "^6.0", + "sebastian/lines-of-code": "^2.0", + "sebastian/version": "^4.0", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2023-05-22T09:04:27+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.0.2", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/phpunit/php-file-iterator/4.0.2/phpunit-php-file-iterator-4.0.2.zip", + "reference": "5647d65443818959172645e7ed999217360654b6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2023-05-07T09:13:23+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/phpunit/php-invoker/4.0.0/phpunit-php-invoker-4.0.0.zip", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "time": "2023-02-03T06:56:09+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/phpunit/php-text-template/3.0.0/phpunit-php-text-template-3.0.0.zip", + "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2023-02-03T06:56:46+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/phpunit/php-timer/6.0.0/phpunit-php-timer-6.0.0.zip", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2023-02-03T06:57:52+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "10.2.6", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/phpunit/phpunit/10.2.6/phpunit-phpunit-10.2.6.zip", + "reference": "1c17815c129f133f3019cc18e8d0c8622e6d9bcd", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-invoker": "^4.0", + "phpunit/php-text-template": "^3.0", + "phpunit/php-timer": "^6.0", + "sebastian/cli-parser": "^2.0", + "sebastian/code-unit": "^2.0", + "sebastian/comparator": "^5.0", + "sebastian/diff": "^5.0", + "sebastian/environment": "^6.0", + "sebastian/exporter": "^5.0", + "sebastian/global-state": "^6.0", + "sebastian/object-enumerator": "^5.0", + "sebastian/recursion-context": "^5.0", + "sebastian/type": "^4.0", + "sebastian/version": "^4.0" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.2-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2023-07-17T12:08:28+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/cli-parser/2.0.0/sebastian-cli-parser-2.0.0.zip", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "time": "2023-02-03T06:58:15+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "2.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/code-unit/2.0.0/sebastian-code-unit-2.0.0.zip", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "time": "2023-02-03T06:58:43+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/code-unit-reverse-lookup/3.0.0/sebastian-code-unit-reverse-lookup-3.0.0.zip", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2023-02-03T06:59:15+00:00" + }, + { + "name": "sebastian/comparator", + "version": "5.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/comparator/5.0.0/sebastian-comparator-5.0.0.zip", + "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2023-02-03T07:07:16+00:00" + }, + { + "name": "sebastian/complexity", + "version": "3.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/complexity/3.0.0/sebastian-complexity-3.0.0.zip", + "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "time": "2023-02-03T06:59:47+00:00" + }, + { + "name": "sebastian/diff", + "version": "5.0.3", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/diff/5.0.3/sebastian-diff-5.0.3.zip", + "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "time": "2023-05-01T07:48:21+00:00" + }, + { + "name": "sebastian/environment", + "version": "6.0.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/environment/6.0.1/sebastian-environment-6.0.1.zip", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2023-04-11T05:39:26+00:00" + }, + { + "name": "sebastian/exporter", + "version": "5.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/exporter/5.0.0/sebastian-exporter-5.0.0.zip", + "reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2023-02-03T07:06:49+00:00" + }, + { + "name": "sebastian/global-state", + "version": "6.0.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/global-state/6.0.1/sebastian-global-state-6.0.1.zip", + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2023-07-19T07:19:23+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "2.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/lines-of-code/2.0.0/sebastian-lines-of-code-2.0.0.zip", + "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "time": "2023-02-03T07:08:02+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "5.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/object-enumerator/5.0.0/sebastian-object-enumerator-5.0.0.zip", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2023-02-03T07:08:32+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "3.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/object-reflector/3.0.0/sebastian-object-reflector-3.0.0.zip", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2023-02-03T07:06:18+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "5.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/recursion-context/5.0.0/sebastian-recursion-context-5.0.0.zip", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "time": "2023-02-03T07:05:40+00:00" + }, + { + "name": "sebastian/type", + "version": "4.0.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/type/4.0.0/sebastian-type-4.0.0.zip", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "time": "2023-02-03T07:10:45+00:00" + }, + { + "name": "sebastian/version", + "version": "4.0.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/sebastian/version/4.0.1/sebastian-version-4.0.1.zip", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2023-02-07T11:34:05+00:00" + }, + { + "name": "spatie/backtrace", + "version": "1.5.3", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/spatie/backtrace/1.5.3/spatie-backtrace-1.5.3.zip", + "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "ext-json": "*", + "phpunit/phpunit": "^9.3", + "spatie/phpunit-snapshot-assertions": "^4.2", + "symfony/var-dumper": "^5.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Backtrace\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van de Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "A better backtrace", + "homepage": "https://github.com/spatie/backtrace", + "keywords": [ + "Backtrace", + "spatie" + ], + "time": "2023-06-28T12:59:17+00:00" + }, + { + "name": "spatie/flare-client-php", + "version": "1.4.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/spatie/flare-client-php/1.4.1/spatie-flare-client-php-1.4.1.zip", + "reference": "943894c6a6b00501365ac0b91ae0dce56f2226fa", + "shasum": "" + }, + "require": { + "illuminate/pipeline": "^8.0|^9.0|^10.0", + "nesbot/carbon": "^2.62.1", + "php": "^8.0", + "spatie/backtrace": "^1.5.2", + "symfony/http-foundation": "^5.0|^6.0", + "symfony/mime": "^5.2|^6.0", + "symfony/process": "^5.2|^6.0", + "symfony/var-dumper": "^5.2|^6.0" + }, + "require-dev": { + "dms/phpunit-arraysubset-asserts": "^0.3.0", + "pestphp/pest": "^1.20", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "spatie/phpunit-snapshot-assertions": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.3.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\FlareClient\\": "src" + } + }, + "license": [ + "MIT" + ], + "description": "Send PHP errors to Flare", + "homepage": "https://github.com/spatie/flare-client-php", + "keywords": [ + "exception", + "flare", + "reporting", + "spatie" + ], + "time": "2023-07-06T09:29:49+00:00" + }, + { + "name": "spatie/ignition", + "version": "1.9.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/spatie/ignition/1.9.0/spatie-ignition-1.9.0.zip", + "reference": "de24ff1e01814d5043bd6eb4ab36a5a852a04973", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.0", + "spatie/backtrace": "^1.5.3", + "spatie/flare-client-php": "^1.4.0", + "symfony/console": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "require-dev": { + "illuminate/cache": "^9.52", + "mockery/mockery": "^1.4", + "pestphp/pest": "^1.20", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "psr/simple-cache-implementation": "*", + "symfony/cache": "^6.0", + "symfony/process": "^5.4|^6.0", + "vlucas/phpdotenv": "^5.5" + }, + "suggest": { + "openai-php/client": "Require get solutions from OpenAI", + "simple-cache-implementation": "To cache solutions from OpenAI" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Spatie\\Ignition\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Spatie", + "email": "info@spatie.be", + "role": "Developer" + } + ], + "description": "A beautiful error page for PHP applications.", + "homepage": "https://flareapp.io/ignition", + "keywords": [ + "error", + "flare", + "laravel", + "page" + ], + "time": "2023-06-28T13:24:59+00:00" + }, + { + "name": "spatie/laravel-ignition", + "version": "2.2.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/spatie/laravel-ignition/2.2.0/spatie-laravel-ignition-2.2.0.zip", + "reference": "dd15fbe82ef5392798941efae93c49395a87d943", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "illuminate/support": "^10.0", + "php": "^8.1", + "spatie/flare-client-php": "^1.3.5", + "spatie/ignition": "^1.9", + "symfony/console": "^6.2.3", + "symfony/var-dumper": "^6.2.3" + }, + "require-dev": { + "livewire/livewire": "^2.11", + "mockery/mockery": "^1.5.1", + "openai-php/client": "^0.3.4", + "orchestra/testbench": "^8.0", + "pestphp/pest": "^1.22.3", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan-deprecation-rules": "^1.1.1", + "phpstan/phpstan-phpunit": "^1.3.3", + "vlucas/phpdotenv": "^5.5" + }, + "suggest": { + "openai-php/client": "Require get solutions from OpenAI", + "psr/simple-cache-implementation": "Needed to cache solutions from OpenAI" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelIgnition\\IgnitionServiceProvider" + ], + "aliases": { + "Flare": "Spatie\\LaravelIgnition\\Facades\\Flare" + } + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\LaravelIgnition\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Spatie", + "email": "info@spatie.be", + "role": "Developer" + } + ], + "description": "A beautiful error page for Laravel applications.", + "homepage": "https://flareapp.io/ignition", + "keywords": [ + "error", + "flare", + "laravel", + "page" + ], + "time": "2023-06-28T13:51:52+00:00" + }, + { + "name": "symfony/yaml", + "version": "v6.3.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/yaml/v6.3.0/symfony-yaml-v6.3.0.zip", + "reference": "a9a8337aa641ef2aa39c3e028f9107ec391e5927", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "time": "2023-04-28T13:28:14+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/theseer/tokenizer/1.2.1/theseer-tokenizer-1.2.1.zip", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2021-07-28T10:34:58+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^8.1" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/api/config/app.php b/api/config/app.php new file mode 100644 index 0000000..770f93f --- /dev/null +++ b/api/config/app.php @@ -0,0 +1,188 @@ + env('APP_NAME', 'Laravel'), + + /* + |-------------------------------------------------------------------------- + | Application Environment + |-------------------------------------------------------------------------- + | + | This value determines the "environment" your application is currently + | running in. This may determine how you prefer to configure various + | services the application utilizes. Set this in your ".env" file. + | + */ + + 'env' => env('APP_ENV', 'production'), + + /* + |-------------------------------------------------------------------------- + | Application Debug Mode + |-------------------------------------------------------------------------- + | + | When your application is in debug mode, detailed error messages with + | stack traces will be shown on every error that occurs within your + | application. If disabled, a simple generic error page is shown. + | + */ + + 'debug' => (bool)env('APP_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | Application URL + |-------------------------------------------------------------------------- + | + | This URL is used by the console to properly generate URLs when using + | the Artisan command line tool. You should set this to the root of + | your application so that it is used when running Artisan tasks. + | + */ + + 'url' => env('APP_URL', 'http://localhost'), + + 'asset_url' => env('ASSET_URL'), + + /* + |-------------------------------------------------------------------------- + | Application Timezone + |-------------------------------------------------------------------------- + | + | Here you may specify the default timezone for your application, which + | will be used by the PHP date and date-time functions. We have gone + | ahead and set this to a sensible default for you out of the box. + | + */ + + 'timezone' => env('TIMEZONE'), + + /* + |-------------------------------------------------------------------------- + | Application Locale Configuration + |-------------------------------------------------------------------------- + | + | The application locale determines the default locale that will be used + | by the translation service provider. You are free to set this value + | to any of the locales which will be supported by the application. + | + */ + + 'locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Application Fallback Locale + |-------------------------------------------------------------------------- + | + | The fallback locale determines the locale to use when the current one + | is not available. You may change the value to correspond to any of + | the language folders that are provided through your application. + | + */ + + 'fallback_locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Faker Locale + |-------------------------------------------------------------------------- + | + | This locale will be used by the Faker PHP library when generating fake + | data for your database seeds. For example, this will be used to get + | localized telephone numbers, street address information and more. + | + */ + + 'faker_locale' => 'en_US', + + /* + |-------------------------------------------------------------------------- + | Encryption Key + |-------------------------------------------------------------------------- + | + | This key is used by the Illuminate encrypter service and should be set + | to a random, 32 character string, otherwise these encrypted strings + | will not be safe. Please do this before deploying an application! + | + */ + + 'key' => env('APP_KEY'), + + 'cipher' => 'AES-256-CBC', + + /* + |-------------------------------------------------------------------------- + | Maintenance Mode Driver + |-------------------------------------------------------------------------- + | + | These configuration options determine the driver used to determine and + | manage Laravel's "maintenance mode" status. The "cache" driver will + | allow maintenance mode to be controlled across multiple machines. + | + | Supported drivers: "file", "cache" + | + */ + + 'maintenance' => [ + 'driver' => 'file', + // 'store' => 'redis', + ], + + /* + |-------------------------------------------------------------------------- + | Autoloaded Service Providers + |-------------------------------------------------------------------------- + | + | The service providers listed here will be automatically loaded on the + | request to your application. Feel free to add your own services to + | this array to grant expanded functionality to your applications. + | + */ + + 'providers' => ServiceProvider::defaultProviders()->merge([ + /* + * Package Service Providers... + */ + + /* + * Application Service Providers... + */ + App\Providers\AppServiceProvider::class, + App\Providers\AuthServiceProvider::class, + // App\Providers\BroadcastServiceProvider::class, + App\Providers\EventServiceProvider::class, + App\Providers\RouteServiceProvider::class, + ])->toArray(), + + /* + |-------------------------------------------------------------------------- + | Class Aliases + |-------------------------------------------------------------------------- + | + | This array of class aliases will be registered when this application + | is started. However, feel free to register as many as you wish as + | the aliases are "lazy" loaded so they don't hinder performance. + | + */ + + 'aliases' => Facade::defaultAliases()->merge([ + // 'Example' => App\Facades\Example::class, + ])->toArray(), + +]; diff --git a/api/config/auth.php b/api/config/auth.php new file mode 100644 index 0000000..9548c15 --- /dev/null +++ b/api/config/auth.php @@ -0,0 +1,115 @@ + [ + 'guard' => 'web', + 'passwords' => 'users', + ], + + /* + |-------------------------------------------------------------------------- + | Authentication Guards + |-------------------------------------------------------------------------- + | + | Next, you may define every authentication guard for your application. + | Of course, a great default configuration has been defined for you + | here which uses session storage and the Eloquent user provider. + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | Supported: "session" + | + */ + + 'guards' => [ + 'web' => [ + 'driver' => 'session', + 'provider' => 'users', + ], + ], + + /* + |-------------------------------------------------------------------------- + | User Providers + |-------------------------------------------------------------------------- + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | If you have multiple user tables or models you may configure multiple + | sources which represent each model / table. These sources may then + | be assigned to any extra authentication guards you have defined. + | + | Supported: "database", "eloquent" + | + */ + + 'providers' => [ + 'users' => [ + 'driver' => 'eloquent', + 'model' => App\Models\User::class, + ], + + // 'users' => [ + // 'driver' => 'database', + // 'table' => 'users', + // ], + ], + + /* + |-------------------------------------------------------------------------- + | Resetting Passwords + |-------------------------------------------------------------------------- + | + | You may specify multiple password reset configurations if you have more + | than one user table or model in the application and you want to have + | separate password reset settings based on the specific user types. + | + | The expiry time is the number of minutes that each reset token will be + | considered valid. This security feature keeps tokens short-lived so + | they have less time to be guessed. You may change this as needed. + | + | The throttle setting is the number of seconds a user must wait before + | generating more password reset tokens. This prevents the user from + | quickly generating a very large amount of password reset tokens. + | + */ + + 'passwords' => [ + 'users' => [ + 'provider' => 'users', + 'table' => 'password_reset_tokens', + 'expire' => 60, + 'throttle' => 60, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Password Confirmation Timeout + |-------------------------------------------------------------------------- + | + | Here you may define the amount of seconds before a password confirmation + | times out and the user is prompted to re-enter their password via the + | confirmation screen. By default, the timeout lasts for three hours. + | + */ + + 'password_timeout' => 10800, + +]; diff --git a/api/config/broadcasting.php b/api/config/broadcasting.php new file mode 100644 index 0000000..2410485 --- /dev/null +++ b/api/config/broadcasting.php @@ -0,0 +1,71 @@ + env('BROADCAST_DRIVER', 'null'), + + /* + |-------------------------------------------------------------------------- + | Broadcast Connections + |-------------------------------------------------------------------------- + | + | Here you may define all of the broadcast connections that will be used + | to broadcast events to other systems or over websockets. Samples of + | each available type of connection are provided inside this array. + | + */ + + 'connections' => [ + + 'pusher' => [ + 'driver' => 'pusher', + 'key' => env('PUSHER_APP_KEY'), + 'secret' => env('PUSHER_APP_SECRET'), + 'app_id' => env('PUSHER_APP_ID'), + 'options' => [ + 'cluster' => env('PUSHER_APP_CLUSTER'), + 'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com', + 'port' => env('PUSHER_PORT', 443), + 'scheme' => env('PUSHER_SCHEME', 'https'), + 'encrypted' => true, + 'useTLS' => env('PUSHER_SCHEME', 'https') === 'https', + ], + 'client_options' => [ + // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html + ], + ], + + 'ably' => [ + 'driver' => 'ably', + 'key' => env('ABLY_KEY'), + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + ], + + 'log' => [ + 'driver' => 'log', + ], + + 'null' => [ + 'driver' => 'null', + ], + + ], + +]; diff --git a/api/config/cache.php b/api/config/cache.php new file mode 100644 index 0000000..d4171e2 --- /dev/null +++ b/api/config/cache.php @@ -0,0 +1,111 @@ + env('CACHE_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Cache Stores + |-------------------------------------------------------------------------- + | + | Here you may define all of the cache "stores" for your application as + | well as their drivers. You may even define multiple stores for the + | same cache driver to group types of items stored in your caches. + | + | Supported drivers: "apc", "array", "database", "file", + | "memcached", "redis", "dynamodb", "octane", "null" + | + */ + + 'stores' => [ + + 'apc' => [ + 'driver' => 'apc', + ], + + 'array' => [ + 'driver' => 'array', + 'serialize' => false, + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'cache', + 'connection' => null, + 'lock_connection' => null, + ], + + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache/data'), + 'lock_path' => storage_path('framework/cache/data'), + ], + + 'memcached' => [ + 'driver' => 'memcached', + 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), + 'sasl' => [ + env('MEMCACHED_USERNAME'), + env('MEMCACHED_PASSWORD'), + ], + 'options' => [ + // Memcached::OPT_CONNECT_TIMEOUT => 2000, + ], + 'servers' => [ + [ + 'host' => env('MEMCACHED_HOST', '127.0.0.1'), + 'port' => env('MEMCACHED_PORT', 11211), + 'weight' => 100, + ], + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'cache', + 'lock_connection' => 'default', + ], + + 'dynamodb' => [ + 'driver' => 'dynamodb', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), + 'endpoint' => env('DYNAMODB_ENDPOINT'), + ], + + 'octane' => [ + 'driver' => 'octane', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Cache Key Prefix + |-------------------------------------------------------------------------- + | + | When utilizing the APC, database, memcached, Redis, or DynamoDB cache + | stores there might be other applications using the same cache. For + | that reason, you may prefix every cache key to avoid collisions. + | + */ + + 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'), + +]; diff --git a/api/config/code.php b/api/config/code.php new file mode 100644 index 0000000..8ed77ae --- /dev/null +++ b/api/config/code.php @@ -0,0 +1,42 @@ + [ + 'c' => '增加成功', + 'd' => '删除成功', + 'u' => '修改成功', + 'r' => '获取成功', + ], + 100000 => '?', + 100001 => '?不存在或不可用', + 100002 => '请登录', + 100003 => '账号不可用或不存在', + 100004 => '?', + 100005 => '验证码已过期', + 100006 => '验证码错误', + 100007 => '账号不存在或密码错误', + 100008 => '旧密码错误', + 100009 => '请输入新密码', + 100010 => '密码长度应在6-20位字符之间', + 100011 => '新旧密码相同', + 100012 => '请输入昵称', + 100013 => '昵称长度应在1-50位字符之间', + 100014 => '头像上传链接异常', + 100015 => '请上传规定以内的图片格式', + 100016 => '上传图片失败,[?]错误', + 100017 => '请输入权限名称', + 100018 => '权限名称长度应在1-20位字符之间', + 100019 => '备注长度应在100位字符以内', + 100020 => '请输入账号', + 100021 => '账号长度应在1-50位字符之间', + 100022 => '请输入密码', + 100023 => '账号已存在', + 100024 => '请求日志不支持跨月查询', + 100025 => '请输入权限路径', + 100026 => '路径名称长度应在1-200位字符之间', + 100027 => '图标长度应在100位字符以内', + 100028 => '提示消息长度应在50位字符以内', + 100029 => '路由组不能添加到子级', + 100030 => '请先删除该组下的子级', + 100031 => '请输入参数名称', + 100032 => '参数名称长度应在1-50位字符之间', +]; diff --git a/api/config/cors.php b/api/config/cors.php new file mode 100644 index 0000000..8a39e6d --- /dev/null +++ b/api/config/cors.php @@ -0,0 +1,34 @@ + ['api/*', 'sanctum/csrf-cookie'], + + 'allowed_methods' => ['*'], + + 'allowed_origins' => ['*'], + + 'allowed_origins_patterns' => [], + + 'allowed_headers' => ['*'], + + 'exposed_headers' => [], + + 'max_age' => 0, + + 'supports_credentials' => false, + +]; diff --git a/api/config/database.php b/api/config/database.php new file mode 100644 index 0000000..137ad18 --- /dev/null +++ b/api/config/database.php @@ -0,0 +1,151 @@ + env('DB_CONNECTION', 'mysql'), + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Here are each of the database connections setup for your application. + | Of course, examples of configuring each database platform that is + | supported by Laravel is shown below to make development simple. + | + | + | All database work in Laravel is done through the PHP PDO facilities + | so make sure you have the driver for your particular database of + | choice installed on your machine before you begin development. + | + */ + + 'connections' => [ + + 'sqlite' => [ + 'driver' => 'sqlite', + 'url' => env('DATABASE_URL'), + 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'prefix' => '', + 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), + ], + + 'mysql' => [ + 'driver' => 'mysql', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'pgsql' => [ + 'driver' => 'pgsql', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '5432'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'prefix_indexes' => true, + 'search_path' => 'public', + 'sslmode' => 'prefer', + ], + + 'sqlsrv' => [ + 'driver' => 'sqlsrv', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', '1433'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'prefix_indexes' => true, + // 'encrypt' => env('DB_ENCRYPT', 'yes'), + // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run in the database. + | + */ + + 'migrations' => 'migrations', + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer body of commands than a typical key-value system + | such as APC or Memcached. Laravel makes it easy to dig right in. + | + */ + + 'redis' => [ + + 'client' => env('REDIS_CLIENT', 'phpredis'), + + 'options' => [ + 'cluster' => env('REDIS_CLUSTER', 'redis'), + 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), + ], + + 'default' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_DB', '0'), + ], + + 'cache' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_CACHE_DB', '1'), + ], + + ], + +]; diff --git a/api/config/filesystems.php b/api/config/filesystems.php new file mode 100644 index 0000000..e9d9dbd --- /dev/null +++ b/api/config/filesystems.php @@ -0,0 +1,76 @@ + env('FILESYSTEM_DISK', 'local'), + + /* + |-------------------------------------------------------------------------- + | Filesystem Disks + |-------------------------------------------------------------------------- + | + | Here you may configure as many filesystem "disks" as you wish, and you + | may even configure multiple disks of the same driver. Defaults have + | been set up for each driver as an example of the required values. + | + | Supported Drivers: "local", "ftp", "sftp", "s3" + | + */ + + 'disks' => [ + + 'local' => [ + 'driver' => 'local', + 'root' => storage_path('app'), + 'throw' => false, + ], + + 'public' => [ + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'url' => env('APP_URL').'/storage', + 'visibility' => 'public', + 'throw' => false, + ], + + 's3' => [ + 'driver' => 's3', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION'), + 'bucket' => env('AWS_BUCKET'), + 'url' => env('AWS_URL'), + 'endpoint' => env('AWS_ENDPOINT'), + 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), + 'throw' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Symbolic Links + |-------------------------------------------------------------------------- + | + | Here you may configure the symbolic links that will be created when the + | `storage:link` Artisan command is executed. The array keys should be + | the locations of the links and the values should be their targets. + | + */ + + 'links' => [ + public_path('storage') => storage_path('app/public'), + ], + +]; diff --git a/api/config/hashing.php b/api/config/hashing.php new file mode 100644 index 0000000..bcd3be4 --- /dev/null +++ b/api/config/hashing.php @@ -0,0 +1,52 @@ + 'bcrypt', + + /* + |-------------------------------------------------------------------------- + | Bcrypt Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Bcrypt algorithm. This will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'bcrypt' => [ + 'rounds' => env('BCRYPT_ROUNDS', 10), + ], + + /* + |-------------------------------------------------------------------------- + | Argon Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Argon algorithm. These will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'argon' => [ + 'memory' => 65536, + 'threads' => 1, + 'time' => 4, + ], + +]; diff --git a/api/config/logging.php b/api/config/logging.php new file mode 100644 index 0000000..c44d276 --- /dev/null +++ b/api/config/logging.php @@ -0,0 +1,131 @@ + env('LOG_CHANNEL', 'stack'), + + /* + |-------------------------------------------------------------------------- + | Deprecations Log Channel + |-------------------------------------------------------------------------- + | + | This option controls the log channel that should be used to log warnings + | regarding deprecated PHP and library features. This allows you to get + | your application ready for upcoming major versions of dependencies. + | + */ + + 'deprecations' => [ + 'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'), + 'trace' => false, + ], + + /* + |-------------------------------------------------------------------------- + | Log Channels + |-------------------------------------------------------------------------- + | + | Here you may configure the log channels for your application. Out of + | the box, Laravel uses the Monolog PHP logging library. This gives + | you a variety of powerful log handlers / formatters to utilize. + | + | Available Drivers: "single", "daily", "slack", "syslog", + | "errorlog", "monolog", + | "custom", "stack" + | + */ + + 'channels' => [ + 'stack' => [ + 'driver' => 'stack', + 'channels' => ['single'], + 'ignore_exceptions' => false, + ], + + 'single' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'daily' => [ + 'driver' => 'daily', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'days' => 14, + 'replace_placeholders' => true, + ], + + 'slack' => [ + 'driver' => 'slack', + 'url' => env('LOG_SLACK_WEBHOOK_URL'), + 'username' => 'Laravel Log', + 'emoji' => ':boom:', + 'level' => env('LOG_LEVEL', 'critical'), + 'replace_placeholders' => true, + ], + + 'papertrail' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class), + 'handler_with' => [ + 'host' => env('PAPERTRAIL_URL'), + 'port' => env('PAPERTRAIL_PORT'), + 'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'), + ], + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'stderr' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => StreamHandler::class, + 'formatter' => env('LOG_STDERR_FORMATTER'), + 'with' => [ + 'stream' => 'php://stderr', + ], + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'syslog' => [ + 'driver' => 'syslog', + 'level' => env('LOG_LEVEL', 'debug'), + 'facility' => LOG_USER, + 'replace_placeholders' => true, + ], + + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'null' => [ + 'driver' => 'monolog', + 'handler' => NullHandler::class, + ], + + 'emergency' => [ + 'path' => storage_path('logs/laravel.log'), + ], + ], + +]; diff --git a/api/config/mail.php b/api/config/mail.php new file mode 100644 index 0000000..bd7a177 --- /dev/null +++ b/api/config/mail.php @@ -0,0 +1,125 @@ + env('MAIL_MAILER', 'smtp'), + + /* + |-------------------------------------------------------------------------- + | Mailer Configurations + |-------------------------------------------------------------------------- + | + | Here you may configure all of the mailers used by your application plus + | their respective settings. Several examples have been configured for + | you and you are free to add your own as your application requires. + | + | Laravel supports a variety of mail "transport" drivers to be used while + | sending an e-mail. You will specify which one you are using for your + | mailers below. You are free to add additional mailers as required. + | + | Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2", + | "postmark", "log", "array", "failover" + | + */ + + 'mailers' => [ + 'smtp' => [ + 'transport' => 'smtp', + 'url' => env('MAIL_URL'), + 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), + 'port' => env('MAIL_PORT', 587), + 'encryption' => env('MAIL_ENCRYPTION', 'ssl'), + 'username' => env('MAIL_USERNAME'), + 'password' => env('MAIL_PASSWORD'), + 'timeout' => null, + 'local_domain' => env('MAIL_EHLO_DOMAIN'), + ], + + 'ses' => [ + 'transport' => 'ses', + ], + + 'mailgun' => [ + 'transport' => 'mailgun', + // 'client' => [ + // 'timeout' => 5, + // ], + ], + + 'postmark' => [ + 'transport' => 'postmark', + // 'client' => [ + // 'timeout' => 5, + // ], + ], + + 'sendmail' => [ + 'transport' => 'sendmail', + 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'), + ], + + 'log' => [ + 'transport' => 'log', + 'channel' => env('MAIL_LOG_CHANNEL'), + ], + + 'array' => [ + 'transport' => 'array', + ], + + 'failover' => [ + 'transport' => 'failover', + 'mailers' => [ + 'smtp', + 'log', + ], + ], + ], + + /* + |-------------------------------------------------------------------------- + | Global "From" Address + |-------------------------------------------------------------------------- + | + | You may wish for all e-mails sent by your application to be sent from + | the same address. Here, you may specify a name and address that is + | used globally for all e-mails that are sent by your application. + | + */ + + 'from' => [ + 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), + 'name' => env('MAIL_FROM_NAME', 'Example'), + ], + + /* + |-------------------------------------------------------------------------- + | Markdown Mail Settings + |-------------------------------------------------------------------------- + | + | If you are using Markdown based email rendering, you may configure your + | theme and component paths here, allowing you to customize the design + | of the emails. Or, you may simply stick with the Laravel defaults! + | + */ + + 'markdown' => [ + 'theme' => 'default', + + 'paths' => [ + resource_path('views/vendor/mail'), + ], + ], + +]; diff --git a/api/config/queue.php b/api/config/queue.php new file mode 100644 index 0000000..01c6b05 --- /dev/null +++ b/api/config/queue.php @@ -0,0 +1,109 @@ + env('QUEUE_CONNECTION', 'sync'), + + /* + |-------------------------------------------------------------------------- + | Queue Connections + |-------------------------------------------------------------------------- + | + | Here you may configure the connection information for each server that + | is used by your application. A default configuration has been added + | for each back-end shipped with Laravel. You are free to add more. + | + | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" + | + */ + + 'connections' => [ + + 'sync' => [ + 'driver' => 'sync', + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'jobs', + 'queue' => 'default', + 'retry_after' => 90, + 'after_commit' => false, + ], + + 'beanstalkd' => [ + 'driver' => 'beanstalkd', + 'host' => 'localhost', + 'queue' => 'default', + 'retry_after' => 90, + 'block_for' => 0, + 'after_commit' => false, + ], + + 'sqs' => [ + 'driver' => 'sqs', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), + 'queue' => env('SQS_QUEUE', 'default'), + 'suffix' => env('SQS_SUFFIX'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'after_commit' => false, + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + 'queue' => env('REDIS_QUEUE', 'default'), + 'retry_after' => 90, + 'block_for' => null, + 'after_commit' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Job Batching + |-------------------------------------------------------------------------- + | + | The following options configure the database and table that store job + | batching information. These options can be updated to any database + | connection and table which has been defined by your application. + | + */ + + 'batching' => [ + 'database' => env('DB_CONNECTION', 'mysql'), + 'table' => 'job_batches', + ], + + /* + |-------------------------------------------------------------------------- + | Failed Queue Jobs + |-------------------------------------------------------------------------- + | + | These options configure the behavior of failed queue job logging so you + | can control which database and table are used to store the jobs that + | have failed. You may change them to any database / table you wish. + | + */ + + 'failed' => [ + 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), + 'database' => env('DB_CONNECTION', 'mysql'), + 'table' => 'failed_jobs', + ], + +]; diff --git a/api/config/sanctum.php b/api/config/sanctum.php new file mode 100644 index 0000000..529cfdc --- /dev/null +++ b/api/config/sanctum.php @@ -0,0 +1,67 @@ + explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( + '%s%s', + 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', + Sanctum::currentApplicationUrlWithPort() + ))), + + /* + |-------------------------------------------------------------------------- + | Sanctum Guards + |-------------------------------------------------------------------------- + | + | This array contains the authentication guards that will be checked when + | Sanctum is trying to authenticate a request. If none of these guards + | are able to authenticate the request, Sanctum will use the bearer + | token that's present on an incoming request for authentication. + | + */ + + 'guard' => ['web'], + + /* + |-------------------------------------------------------------------------- + | Expiration Minutes + |-------------------------------------------------------------------------- + | + | This value controls the number of minutes until an issued token will be + | considered expired. If this value is null, personal access tokens do + | not expire. This won't tweak the lifetime of first-party sessions. + | + */ + + 'expiration' => null, + + /* + |-------------------------------------------------------------------------- + | Sanctum Middleware + |-------------------------------------------------------------------------- + | + | When authenticating your first-party SPA with Sanctum you may need to + | customize some of the middleware Sanctum uses while processing the + | request. You may change the middleware listed below as required. + | + */ + + 'middleware' => [ + 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class, + 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class, + ], + +]; diff --git a/api/config/services.php b/api/config/services.php new file mode 100644 index 0000000..0ace530 --- /dev/null +++ b/api/config/services.php @@ -0,0 +1,34 @@ + [ + 'domain' => env('MAILGUN_DOMAIN'), + 'secret' => env('MAILGUN_SECRET'), + 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), + 'scheme' => 'https', + ], + + 'postmark' => [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + +]; diff --git a/api/config/session.php b/api/config/session.php new file mode 100644 index 0000000..8fed97c --- /dev/null +++ b/api/config/session.php @@ -0,0 +1,201 @@ + env('SESSION_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Session Lifetime + |-------------------------------------------------------------------------- + | + | Here you may specify the number of minutes that you wish the session + | to be allowed to remain idle before it expires. If you want them + | to immediately expire on the browser closing, set that option. + | + */ + + 'lifetime' => env('SESSION_LIFETIME', 120), + + 'expire_on_close' => false, + + /* + |-------------------------------------------------------------------------- + | Session Encryption + |-------------------------------------------------------------------------- + | + | This option allows you to easily specify that all of your session data + | should be encrypted before it is stored. All encryption will be run + | automatically by Laravel and you can use the Session like normal. + | + */ + + 'encrypt' => false, + + /* + |-------------------------------------------------------------------------- + | Session File Location + |-------------------------------------------------------------------------- + | + | When using the native session driver, we need a location where session + | files may be stored. A default has been set for you but a different + | location may be specified. This is only needed for file sessions. + | + */ + + 'files' => storage_path('framework/sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Database Connection + |-------------------------------------------------------------------------- + | + | When using the "database" or "redis" session drivers, you may specify a + | connection that should be used to manage these sessions. This should + | correspond to a connection in your database configuration options. + | + */ + + 'connection' => env('SESSION_CONNECTION'), + + /* + |-------------------------------------------------------------------------- + | Session Database Table + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the table we + | should use to manage the sessions. Of course, a sensible default is + | provided for you; however, you are free to change this as needed. + | + */ + + 'table' => 'sessions', + + /* + |-------------------------------------------------------------------------- + | Session Cache Store + |-------------------------------------------------------------------------- + | + | While using one of the framework's cache driven session backends you may + | list a cache store that should be used for these sessions. This value + | must match with one of the application's configured cache "stores". + | + | Affects: "apc", "dynamodb", "memcached", "redis" + | + */ + + 'store' => env('SESSION_STORE'), + + /* + |-------------------------------------------------------------------------- + | Session Sweeping Lottery + |-------------------------------------------------------------------------- + | + | Some session drivers must manually sweep their storage location to get + | rid of old sessions from storage. Here are the chances that it will + | happen on a given request. By default, the odds are 2 out of 100. + | + */ + + 'lottery' => [2, 100], + + /* + |-------------------------------------------------------------------------- + | Session Cookie Name + |-------------------------------------------------------------------------- + | + | Here you may change the name of the cookie used to identify a session + | instance by ID. The name specified here will get used every time a + | new session cookie is created by the framework for every driver. + | + */ + + 'cookie' => env( + 'SESSION_COOKIE', + Str::slug(env('APP_NAME', 'laravel'), '_').'_session' + ), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Path + |-------------------------------------------------------------------------- + | + | The session cookie path determines the path for which the cookie will + | be regarded as available. Typically, this will be the root path of + | your application but you are free to change this when necessary. + | + */ + + 'path' => '/', + + /* + |-------------------------------------------------------------------------- + | Session Cookie Domain + |-------------------------------------------------------------------------- + | + | Here you may change the domain of the cookie used to identify a session + | in your application. This will determine which domains the cookie is + | available to in your application. A sensible default has been set. + | + */ + + 'domain' => env('SESSION_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | HTTPS Only Cookies + |-------------------------------------------------------------------------- + | + | By setting this option to true, session cookies will only be sent back + | to the server if the browser has a HTTPS connection. This will keep + | the cookie from being sent to you when it can't be done securely. + | + */ + + 'secure' => env('SESSION_SECURE_COOKIE'), + + /* + |-------------------------------------------------------------------------- + | HTTP Access Only + |-------------------------------------------------------------------------- + | + | Setting this value to true will prevent JavaScript from accessing the + | value of the cookie and the cookie will only be accessible through + | the HTTP protocol. You are free to modify this option if needed. + | + */ + + 'http_only' => true, + + /* + |-------------------------------------------------------------------------- + | Same-Site Cookies + |-------------------------------------------------------------------------- + | + | This option determines how your cookies behave when cross-site requests + | take place, and can be used to mitigate CSRF attacks. By default, we + | will set this value to "lax" since this is a secure default value. + | + | Supported: "lax", "strict", "none", null + | + */ + + 'same_site' => 'lax', + +]; diff --git a/api/config/view.php b/api/config/view.php new file mode 100644 index 0000000..22b8a18 --- /dev/null +++ b/api/config/view.php @@ -0,0 +1,36 @@ + [ + resource_path('views'), + ], + + /* + |-------------------------------------------------------------------------- + | Compiled View Path + |-------------------------------------------------------------------------- + | + | This option determines where all the compiled Blade templates will be + | stored for your application. Typically, this is within the storage + | directory. However, as usual, you are free to change this value. + | + */ + + 'compiled' => env( + 'VIEW_COMPILED_PATH', + realpath(storage_path('framework/views')) + ), + +]; diff --git a/api/database/.gitignore b/api/database/.gitignore new file mode 100644 index 0000000..9b19b93 --- /dev/null +++ b/api/database/.gitignore @@ -0,0 +1 @@ +*.sqlite* diff --git a/api/database/factories/UserFactory.php b/api/database/factories/UserFactory.php new file mode 100644 index 0000000..a6ecc0a --- /dev/null +++ b/api/database/factories/UserFactory.php @@ -0,0 +1,38 @@ + + */ +class UserFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'name' => fake()->name(), + 'email' => fake()->unique()->safeEmail(), + 'email_verified_at' => now(), + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password + 'remember_token' => Str::random(10), + ]; + } + + /** + * Indicate that the model's email address should be unverified. + */ + public function unverified(): static + { + return $this->state(fn (array $attributes) => [ + 'email_verified_at' => null, + ]); + } +} diff --git a/api/database/migrations/2023_07_29_021050_create_configs_table.php b/api/database/migrations/2023_07_29_021050_create_configs_table.php new file mode 100644 index 0000000..46e6ccb --- /dev/null +++ b/api/database/migrations/2023_07_29_021050_create_configs_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('name', 50)->index(); + $table->longText('value'); + $table->tinyInteger('type')->comment('1-文字 2-图片 3-文字数组 4-图片数组 5-JSON 6-富文本 7-开关 8-颜色')->index(); + $table->tinyInteger('client')->comment('类型 0-公共 1-后台')->index(); + $table->tinyInteger('login')->comment('登录类型 1-登录获取 2-随时获取')->index(); + $table->string('remark', 100); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('configs'); + } +}; diff --git a/api/database/migrations/2023_07_29_042032_create_admins_table.php b/api/database/migrations/2023_07_29_042032_create_admins_table.php new file mode 100644 index 0000000..b9c3247 --- /dev/null +++ b/api/database/migrations/2023_07_29_042032_create_admins_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('nickname', 50)->comment('名称'); + $table->string('avatar', 200)->default('')->comment('头像'); + $table->integer('admin_auth_group')->comment('权限组ID')->index(); + $table->integer('initial_password')->default(1)->comment('1-下次登录需要修改密码 2-已经修改密码'); + $table->tinyInteger('status')->default(1)->comment('1-正常 2-禁用'); + $table->tinyInteger('del')->default(2)->comment('1-删除 2-正常'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('admins'); + } +}; diff --git a/api/database/migrations/2023_07_29_042123_create_admin_accounts_table.php b/api/database/migrations/2023_07_29_042123_create_admin_accounts_table.php new file mode 100644 index 0000000..a81a4f3 --- /dev/null +++ b/api/database/migrations/2023_07_29_042123_create_admin_accounts_table.php @@ -0,0 +1,31 @@ +id(); + $table->bigInteger('admin')->index(); + $table->string('account', 50)->index(); + $table->string('secret', 80); + $table->tinyInteger('type')->comment('1-账号密码'); + $table->tinyInteger('del')->default(2)->comment('1-删除 2-正常'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('admin_accounts'); + } +}; diff --git a/api/database/migrations/2023_07_29_042139_create_admin_auth_groups_table.php b/api/database/migrations/2023_07_29_042139_create_admin_auth_groups_table.php new file mode 100644 index 0000000..029b96a --- /dev/null +++ b/api/database/migrations/2023_07_29_042139_create_admin_auth_groups_table.php @@ -0,0 +1,31 @@ +id(); + $table->string('name', 20)->comment('名称'); + $table->string('admin_auths', 1000)->comment('权限IDS JSON'); + $table->string('remark', 100)->comment('备注'); + $table->tinyInteger('status')->default(1)->comment('1-可用 2-禁用'); + $table->tinyInteger('del')->default(2)->comment('1-删除 2-正常'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('admin_auth_groups'); + } +}; diff --git a/api/database/migrations/2023_07_29_042142_create_admin_auths_table.php b/api/database/migrations/2023_07_29_042142_create_admin_auths_table.php new file mode 100644 index 0000000..044cda1 --- /dev/null +++ b/api/database/migrations/2023_07_29_042142_create_admin_auths_table.php @@ -0,0 +1,37 @@ +id(); + $table->string('name', 200)->comment('名称'); + $table->string('title', 20)->comment('显示标题'); + $table->string('icon', 100)->default('')->comment('显示图标'); + $table->integer('pid')->comment('上级ID'); + $table->tinyInteger('type')->comment('1-分组 2-页面/接口'); + $table->tinyInteger('check')->comment('1-需要验证 2-不需要验证'); + $table->tinyInteger('show')->default(1)->comment('1-显示 2-不显示'); + $table->tinyInteger('status')->default(1)->comment('1-正常 2-禁用'); + $table->tinyInteger('del')->default(2)->comment('1-删除 2-正常'); + $table->string('message', 50)->comment('验证失败的提示信息'); + $table->integer('order')->default(0)->comment('排序'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('admin_auths'); + } +}; diff --git a/api/database/migrations/2023_07_29_042151_create_admin_tokens_table.php b/api/database/migrations/2023_07_29_042151_create_admin_tokens_table.php new file mode 100644 index 0000000..f96d67c --- /dev/null +++ b/api/database/migrations/2023_07_29_042151_create_admin_tokens_table.php @@ -0,0 +1,30 @@ +id(); + $table->bigInteger('admin')->index()->comment('账号ID'); + $table->string('token', 50)->comment('TOKEN')->index(); + $table->tinyInteger('type')->comment('1-后台'); + $table->tinyInteger('del')->default(2)->comment('1-删除 2-正常'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('admin_tokens'); + } +}; diff --git a/api/database/migrations/2023_07_29_105144_push_admin_data.php b/api/database/migrations/2023_07_29_105144_push_admin_data.php new file mode 100644 index 0000000..2cb1c01 --- /dev/null +++ b/api/database/migrations/2023_07_29_105144_push_admin_data.php @@ -0,0 +1,47 @@ + 'admin', + 'nickname' => '超级管理员', + 'password' => bcrypt('000000'), + 'admin_auth_group' => -1, + ], + ]; + foreach ($data as $datum) { + $admin = new App\Models\Admin(); + $admin->nickname = $datum['nickname']; + $admin->admin_auth_group = $datum['admin_auth_group']; + $admin->save(); + $admin_account = new App\Models\AdminAccount(); + $admin_account->admin = $admin->id; + $admin_account->account = $datum['account']; + $admin_account->secret = $datum['password']; + $admin_account->type = 1; + $admin_account->save(); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/api/database/migrations/2023_07_29_105144_push_auth_data.php b/api/database/migrations/2023_07_29_105144_push_auth_data.php new file mode 100644 index 0000000..9299adc --- /dev/null +++ b/api/database/migrations/2023_07_29_105144_push_auth_data.php @@ -0,0 +1,131 @@ + 'admin_basics', + 'title' => '后台基础接口', + 'icon' => '', + 'pid' => '0', + 'type' => '1', + 'check' => '2', + 'show' => '2', + ], [ + 'name' => 'admin_basics_login', + 'title' => '后台登录', + 'icon' => '', + 'pid' => '1', + 'type' => '2', + 'check' => '1', + 'show' => '2', + 'message' => '该账号所属权限组已被禁止登录后台' + ], [ + 'name' => 'admin', + 'title' => '管理员设置', + 'icon' => 'every-user', + 'pid' => '0', + 'type' => '1', + 'check' => '2', + 'show' => '1', + 'message' => '' + ], [ + 'name' => 'admin-auth', + 'title' => '权限管理', + 'icon' => 'personal-privacy', + 'pid' => '3', + 'type' => '2', + 'check' => '1', + 'show' => '1', + 'message' => '该账号所属权限组不能对权限分组进行设置' + ], [ + 'name' => 'admin-list', + 'title' => '管理员列表', + 'icon' => 'every-user', + 'pid' => '3', + 'type' => '2', + 'check' => '1', + 'show' => '1', + 'message' => '该账号所属权限组不能对管理员进行设置' + ], [ + 'name' => 'config', + 'title' => '后台管理', + 'icon' => 'setting', + 'pid' => '0', + 'type' => '1', + 'check' => '2', + 'show' => '1', + ], [ + 'name' => 'config-config', + 'title' => '后台配置', + 'icon' => 'setting-config', + 'pid' => '6', + 'type' => '2', + 'check' => '1', + 'show' => '1', + 'message' => '该账号所属权限组不能对参数配置进行设置' + ], [ + 'name' => 'config-router', + 'title' => '路由配置', + 'icon' => 'left-and-right-branch', + 'pid' => '6', + 'type' => '2', + 'check' => '1', + 'show' => '1', + 'message' => '该账号所属权限组不能对路由进行设置' + ], [ + 'name' => 'config-log', + 'title' => '请求日志', + 'icon' => 'log', + 'pid' => '6', + 'type' => '2', + 'check' => '1', + 'show' => '1', + 'message' => '该账号所属权限组不能查看请求日志' + ], [ + 'name' => 'config-upload', + 'title' => '上传管理', + 'icon' => 'upload', + 'pid' => '6', + 'type' => '2', + 'check' => '1', + 'show' => '1', + 'message' => '该账号所属权限组不能查看上传管理' + ]]; + foreach ($data as $datum) { + $auth = new App\Models\AdminAuth(); + $auth->name = $datum['name']; + $auth->title = $datum['title']; + $auth->icon = $datum['icon']; + $auth->pid = $datum['pid']; + $auth->type = $datum['type']; + $auth->check = $datum['check']; + $auth->show = $datum['show']; + $auth->message = $datum['message'] ?? ''; + $auth->status = 1; + $auth->del = 2; + $auth->order = 0; + $auth->save(); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/api/database/migrations/2023_07_29_143353_push_config_data.php b/api/database/migrations/2023_07_29_143353_push_config_data.php new file mode 100644 index 0000000..5f2dbd7 --- /dev/null +++ b/api/database/migrations/2023_07_29_143353_push_config_data.php @@ -0,0 +1,94 @@ + 'Logo', + 'value' => '/storage/assets/default/logo.png', + 'type' => '2', + 'client' => '0', + 'login' => '2', + ], [ + 'name' => 'Favicon', + 'value' => '/storage/assets/default/favicon.png', + 'type' => '2', + 'client' => '0', + 'login' => '2', + ], [ + 'name' => 'Login欢迎图片', + 'value' => '/storage/assets/default/login_cover.png', + 'type' => '2', + 'client' => '1', + 'login' => '2', + ], [ + 'name' => 'Login背景图', + 'value' => '/storage/assets/default/login_bg.png', + 'type' => '2', + 'client' => '1', + 'login' => '2', + ], [ + 'name' => 'Login背景色', + 'value' => '#1681fd', + 'type' => '8', + 'client' => '1', + 'login' => '2', + ], [ + 'name' => '网站名称', + 'value' => env('APP_NAME'), + 'type' => '1', + 'client' => '0', + 'login' => '2', + ], [ + 'name' => '网站介绍', + 'value' => '中后台前后端一站式解决方案', + 'type' => '1', + 'client' => '0', + 'login' => '2', + ], [ + 'name' => '后台密码登录验证', + 'value' => '1', + 'type' => '7', + 'client' => '1', + 'login' => '2', + 'remark' => '0-关闭 1-图形', + ], [ + 'name' => '后台扫码登录开关', + 'value' => '0', + 'type' => '7', + 'client' => '1', + 'login' => '2', + 'remark' => '0-关闭 1-开启', + ]]; + foreach ($data as $datum) { + $config = new App\Models\Config(); + $config->name = $datum['name']; + $config->value = $datum['value']; + $config->type = $datum['type']; + $config->client = $datum['client']; + $config->login = $datum['login']; + $config->remark = $datum['remark'] ?? ''; + $config->save(); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/api/database/migrations/2023_07_29_214939_create_image_captchas_table.php b/api/database/migrations/2023_07_29_214939_create_image_captchas_table.php new file mode 100644 index 0000000..65641c0 --- /dev/null +++ b/api/database/migrations/2023_07_29_214939_create_image_captchas_table.php @@ -0,0 +1,27 @@ +id(); + $table->string('uuid', 60)->index(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('image_captchas'); + } +}; diff --git a/api/database/migrations/2023_08_08_092916_create_uploads_table.php b/api/database/migrations/2023_08_08_092916_create_uploads_table.php new file mode 100644 index 0000000..7616651 --- /dev/null +++ b/api/database/migrations/2023_08_08_092916_create_uploads_table.php @@ -0,0 +1,34 @@ +id(); + $table->string('uuid', 80)->comment('UUID')->index(); + $table->string('name', 100)->comment('文件名')->index(); + $table->string('path', 200)->comment('路径'); + $table->string('url', 200)->comment('访问链接'); + $table->string('from', 100)->comment('上传接口')->index(); + $table->decimal('size', 20, 4)->comment('大小'); + $table->string('ext', 10)->comment('后缀')->index(); + $table->string('md5', 80)->comment('MD5')->index(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('uploads'); + } +}; diff --git a/api/database/seeders/DatabaseSeeder.php b/api/database/seeders/DatabaseSeeder.php new file mode 100644 index 0000000..a9f4519 --- /dev/null +++ b/api/database/seeders/DatabaseSeeder.php @@ -0,0 +1,22 @@ +create(); + + // \App\Models\User::factory()->create([ + // 'name' => 'Test User', + // 'email' => 'test@example.com', + // ]); + } +} diff --git a/api/public/favicon.ico b/api/public/favicon.ico new file mode 100644 index 0000000..da5f01d Binary files /dev/null and b/api/public/favicon.ico differ diff --git a/api/public/index.php b/api/public/index.php new file mode 100644 index 0000000..1d69f3a --- /dev/null +++ b/api/public/index.php @@ -0,0 +1,55 @@ +make(Kernel::class); + +$response = $kernel->handle( + $request = Request::capture() +)->send(); + +$kernel->terminate($request, $response); diff --git a/api/public/robots.txt b/api/public/robots.txt new file mode 100644 index 0000000..eb05362 --- /dev/null +++ b/api/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/api/resources/css/app.css b/api/resources/css/app.css new file mode 100644 index 0000000..e69de29 diff --git a/api/resources/js/app.js b/api/resources/js/app.js new file mode 100644 index 0000000..e59d6a0 --- /dev/null +++ b/api/resources/js/app.js @@ -0,0 +1 @@ +import './bootstrap'; diff --git a/api/resources/js/bootstrap.js b/api/resources/js/bootstrap.js new file mode 100644 index 0000000..846d350 --- /dev/null +++ b/api/resources/js/bootstrap.js @@ -0,0 +1,32 @@ +/** + * We'll load the axios HTTP library which allows us to easily issue requests + * to our Laravel back-end. This library automatically handles sending the + * CSRF token as a header based on the value of the "XSRF" token cookie. + */ + +import axios from 'axios'; +window.axios = axios; + +window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; + +/** + * Echo exposes an expressive API for subscribing to channels and listening + * for events that are broadcast by Laravel. Echo and event broadcasting + * allows your team to easily build robust real-time web applications. + */ + +// import Echo from 'laravel-echo'; + +// import Pusher from 'pusher-js'; +// window.Pusher = Pusher; + +// window.Echo = new Echo({ +// broadcaster: 'pusher', +// key: import.meta.env.VITE_PUSHER_APP_KEY, +// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1', +// wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`, +// wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80, +// wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443, +// forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https', +// enabledTransports: ['ws', 'wss'], +// }); diff --git a/api/resources/views/emails/example.blade.php b/api/resources/views/emails/example.blade.php new file mode 100644 index 0000000..cc08eef --- /dev/null +++ b/api/resources/views/emails/example.blade.php @@ -0,0 +1,16 @@ + + + + + + + Example Email + + +
+

欢迎 {{ $data['name'] }}!

+

{{ $data['date'] }}

+
+ + diff --git a/api/resources/views/welcome.blade.php b/api/resources/views/welcome.blade.php new file mode 100644 index 0000000..638ec96 --- /dev/null +++ b/api/resources/views/welcome.blade.php @@ -0,0 +1,140 @@ + + + + + + + Laravel + + + + + + + + + + + + diff --git a/api/routes/api.php b/api/routes/api.php new file mode 100644 index 0000000..889937e --- /dev/null +++ b/api/routes/api.php @@ -0,0 +1,19 @@ +get('/user', function (Request $request) { + return $request->user(); +}); diff --git a/api/routes/channels.php b/api/routes/channels.php new file mode 100644 index 0000000..5d451e1 --- /dev/null +++ b/api/routes/channels.php @@ -0,0 +1,18 @@ +id === (int) $id; +}); diff --git a/api/routes/console.php b/api/routes/console.php new file mode 100644 index 0000000..e05f4c9 --- /dev/null +++ b/api/routes/console.php @@ -0,0 +1,19 @@ +comment(Inspiring::quote()); +})->purpose('Display an inspiring quote'); diff --git a/api/routes/web.php b/api/routes/web.php new file mode 100644 index 0000000..d60aceb --- /dev/null +++ b/api/routes/web.php @@ -0,0 +1,65 @@ +