diff --git a/.env.example b/.env.example index c3ed2a9..d1f8a6a 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,11 @@ -APP_NAME=Laravel +CONTAINER_NAME= + +APP_NAME=Liwo APP_ENV=local APP_KEY= APP_DEBUG=true APP_URL=http://localhost +APP_TIMEZONE="Asia/Tehran" LOG_CHANNEL=stack LOG_LEVEL=debug @@ -47,3 +50,4 @@ PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" + diff --git a/app/Console/Commands/CostCommand.php b/app/Console/Commands/CostCommand.php new file mode 100644 index 0000000..1ad1095 --- /dev/null +++ b/app/Console/Commands/CostCommand.php @@ -0,0 +1,136 @@ + 0, + 400 => 1000, + 800 => 2000, + ]; + + protected $signature = 'cost:work'; + + protected $description = 'Run the cost worker'; + + public function __construct() + { + parent::__construct(); + } + + public function handle() + { + // infinte loop + while (true) { + // to baghali ha + $recorded_month = jdate($business->calculated_at)->format("Y-m-01"); + + $calculated_at = Cache::get('calculated_at'); + if ($calculated_at === null) { + $business = Business::orderBy('calculated_at')->first()->load('users', 'cost'); + $calculated_at = $business->calculated_at; + $until_now = jdate()->getMonth() > jdate($business->calculated_at)->getMonth() + ? jdate($business->calculated_at)->toCarbon()->setTime("00", "00", "00") + : \Carbon\Carbon::now(); + + Cache::put('calculated_at', $until_now, 60); + } + + // if calculated_at less than an hour stop + if (\Carbon\Carbon::now()->diffInMinutes($until_now) <= 60) { + $this->info('nothing to cost'); + continue; + } + + try { + DB::beginTransaction(); + + // business order by last_calculated_at take first + if (!isset($business)) { + $business = Business::orderBy('calculated_at')->first()->load('users', 'cost'); + } + + $user_fee = enum('business.fee.user'); + + // get business employee + $users_cost = $business->cost + ->where('type', '=', 'users') + ->where('fee', '=', $user_fee) + ->where('month', '=', $recorded_month) + ->where('amount', '=', $business->users->count()) + ->first(); + + if ($users_cost === null) { + $business->cost()->create([ + 'type' => 'users', + 'month' => $recorded_month, + 'amount' => $business->users->count(), + 'fee' => $user_fee, + 'duration' => $duration = $until_now->diffInSeconds($calculated_at), // from the created_at time of the newset fifth user + 'additional' => $business->users->pluck('id')->toArray(), + ]); + } else { + $users_cost->update([ + 'duration' => $duration = $until_now->diffInMinutes($calculated_at), // last calc - (current month - now else last calc - end of the past month), + 'additional' => $business->users->pluck('id')->toArray(), + ]); + } + + $costs = $user_fee * $duration; + + // do the math in php + if (intdiv($business->files_volume, 200) === 0) { + $pads = 0; + } else { + $pads = intdiv($business->files_volume, 200) - 1; + } + + $file_fee = enum('business.fee.file'); + + $files = $business->cost + ->where('type', '=', 'files') + ->where('fee', '=', $file_fee) + ->where('month', '=', $recorded_month) + ->where('amount', '=', $business->files_volume) + ->first(); + + if ($files === null) { + $business->cost()->create([ + 'type' => 'files', + 'month' => $recorded_month, + 'amount' => $pads, + 'fee' => $file_fee, + 'duration' => $duration = $until_now->diffInMinutes($calculated_at), // how to determine the file?, + ]); + } else { + $files->update([ + 'duration' => $duration = $until_now->diffInMinutes($calculated_at), // last calc - (current month - now else last calc - end of the past month),, + ]); + } + + $costs += $file_fee * $duration; + + // increment and decrement of wallet in php + // deduct costs from your business wallet + // make sure save the calculated_at + $business->update([ + 'wallet' => $business->wallet - $costs, + 'calculated_at' => \Carbon\Carbon::now(), + ]); + DB::commit(); + } catch (Throwable $thr) { + DB::rollback(); + throw $thr; + continue; + } + } + } +} diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php new file mode 100644 index 0000000..6d41a8d --- /dev/null +++ b/app/Http/Controllers/AuthController.php @@ -0,0 +1,268 @@ +stateless()->redirect(); + } + + public function handleGoogleCallback(Request $request) + { + try { + + $user = Socialite::driver('google')->stateless()->user(); + $find_user = User::where('email', $user->email)->first(); + + if ($find_user) { + + $find_user->update([ + 'active' => true + ]); + + Auth::setUser($find_user); + + } else { + + $user = User::create($user->user + [ + 'password' => Hash::make('google-login-user'), + 'username' => $user->email, + 'active' => true + ]); + + Auth::setUser($user); + + } + $finger_print = $this->createFingerPrint(); + return redirect('http://localhost:3000/login?token='.$finger_print->token); + + } catch (Exception $e) { + dd($e->getMessage()); + } + } + + public function login(Request $request) + { + // todo: Logging in from a new device will result in sending a notification + $this->validate($request, [ + 'email' => 'required|email|exists:users,email', + 'password' => 'required|string|min:6' + ]); + + $user = User::where('email', $request->email)->first(); + if ($user && Hash::check($request->password, $user->password)) { + Auth::viaRequest('api', fn() => $user); + + return [ + 'auth' => $this->createFingerPrint(), + 'businesses' => Auth::user()->businesses->keyBy('id')->map(fn($b, $bid) => Business::info($bid)) + ]; + } + + return new JsonResponse([ + 'message' => trans('auth.failed'), + 'status' => Response::HTTP_NOT_FOUND, + ], Response::HTTP_NOT_FOUND); + } + + + public function register(Request $request) + { + $this->validate($request, [ + 'name' => 'required|string|max:225|min:2', + 'username' => ['required', Rule::unique('users', 'username')], + 'email' => ['required', 'email', Rule::unique('users', 'email')], + 'password' => 'required|string|min:8' + ]); + + $request->merge(['password' => Hash::make($request->password)]); + + $code_data = ['verification_code' => $this->sendVerificationCode()]; + $method_data = ['method' => 'registerMain']; + + Cache::put($request->email, $request->all() + $code_data + $method_data, 3600); // remain one hour + + return \response()->json([ + 'message' => 'Code send for user and user must be verified.'], + Response::HTTP_OK); + + } + + public function registerMain($user_info) + { + $user = User::create($user_info); + + Auth::setUser($user); + + return $this->createFingerPrint(); + } + + public function sendVerificationCode($contact_way = null) + { + $verification_code = 1234; // rand(10001, 99999) + + //send code for user with contact way + + return $verification_code; + } + + public function verification(Request $request) + { + if (!Cache::has($request->email)) { + return \response()->json(['message' => 'Code expired.'], Response::HTTP_BAD_REQUEST); + } + + $user_info = Cache::get($request->email); + + $this->validate($request, [ + 'email' => 'required|email', + 'verification_code' => 'required|string|min:4|max:4|in:'.$user_info['verification_code'] + ]); + + Cache::forget($request->email); + + return isset($user_info['method']) ? + call_user_func('self::'.$user_info['method'], $user_info) : + \response()->json(['message' => 'Code verified successfully.'], Response::HTTP_OK,); + } + + public function forgetPassword(Request $request) + { + $this->validate($request, [ + 'email' => 'required|email|exists:users,email' + ]); + + $code_data = ['verification_code' => $this->sendVerificationCode()]; + + Cache::put($request->email, $request->all() + $code_data, 3600); // remain one hour + + return \response()->json([ + 'message' => 'Code send for user and user must be verified.'], + Response::HTTP_OK); + } + + public function updatePassword(Request $request) + { + if (!Cache::has($request->email)) { + return \response()->json(['message' => 'Code expired.'], Response::HTTP_BAD_REQUEST); + } + + $this->validate($request, [ + 'email' => 'required|email', + 'password' => 'required|string|min:8|confirmed', + 'verification_code' => 'required|string|min:4|max:4|in:'.Cache::get($request->email)['verification_code'] + ]); + + $user = User::where('email', $request->email)->first(); + + $user->update([ + 'password' => Hash::make($request->password) + ]); + + Auth::setUser($user); + + return $this->createFingerPrint(); + } + + /** + * @param Request $request + * @return mixed + * @throws TokenMismatchException + */ + public function logout(Request $request) + { + $token = $request->getCurrentToken(); + if (blank($token)) { + return new JsonResponse([ + 'message' => 'Not authorized request.', + 'status' => Response::HTTP_UNAUTHORIZED + ]); + } + + /** @var Fingerprint $token */ + $token = Auth::user()->fingerprints()->firstWhere([ + 'token' => $token, + ]); + + if ($token) { + return $token->delete(); + } + + throw new TokenMismatchException('Invalid token!'); + } + + /** + * @param string $token + * @throws TokenMismatchException + */ + public function revoke(string $token) + { + /** @var Fingerprint $token */ + $token = Auth::user()->fingerprints()->firstWhere([ + 'token' => $token, + ]); + + if ($token) { + return $token->delete(); + } + + throw new TokenMismatchException(); + } + + public function auth() + { + return new UserResource(Auth::user()); + } + + public function authWithInfo() + { + return [ + 'auth' => new UserResource(Auth::user()), + 'businesses' => Auth::user()->businesses->keyBy('id') ->map(fn($b, $bid) => Business::info($bid)) + ]; + } + + public function delete(Request $request) + { + Auth::user()->fingerprints()->delete(); + unset(Auth::user()->token); + Auth::user()->delete(); + + return 'success'; + } + + public function createFingerPrint() + { + $attributes = [ + 'agent' => \request()->getAgent(), + 'ip' => \request()->getClientIp(), + 'os' => \request()->getOS(), + 'latitude' => \request()->getLocation()->getAttribute('lat'), + 'longitude' => \request()->getLocation()->getAttribute('lon'), + ]; + + $values = [ + 'token' => Str::random(60) + ]; + + return Auth::user()->fingerprints()->firstOrCreate($attributes, $attributes + $values); + } +} diff --git a/app/Http/Controllers/BusinessController.php b/app/Http/Controllers/BusinessController.php new file mode 100644 index 0000000..179837c --- /dev/null +++ b/app/Http/Controllers/BusinessController.php @@ -0,0 +1,195 @@ +user()->businesses + ->keyBy('id') + ->map(fn($b, $bid) => Business::info($bid)); + } + + public function store(Request $request) + { +// $users = []; +// foreach ($request->users ?? [] as $key => $value) { +// $users[$value] = []; +// } + +// $owner = [ +// Auth::id() => [ +// 'level' => enum('levels.owner.id'), +// ] +// ]; +// +// $users = $users + $owner; +// +// $request->merge(['users' => $users]); + + $business = Business::create($request->all()); + $business->users()->sync([Auth::id() => [ + 'level' => enum('levels.owner.id'), + ] + ], false); + + return Business::info($business->id); + } + + public function show(string $business) + { + permit('businessAccess'); + return Business::info($business); + } + + public function update(Request $request, string $business) + { + // permit('businessEdit'); + $business = Business::findOrFail($business); + $business->fill($request->all())->save(); + + return Business::info($business->id); + } + + public function setAvatar(Request $request, string $business) + { + $business = Business::findOrFail($business); + if ($request->hasFile('avatar')) { + $business->saveAsAvatar($request->file('avatar')); + } + + return Business::info($business->id); + } + + public function unSetAvatar(Request $request, string $business) + { + $business = Business::findOrFail($business); + $business->deleteAvatar(); + + return Business::info($business->id); + } + + + public function info(string $business) + { + return request('_business_info'); + } + + public function restore(string $business) + { + $business = Business::onlyTrashed()->findOrFail($business); + $business->restore(); + + return response(['message' => 'business successfully restored.']); + } + + public function storeOrUpdateUser($business, Request $request) + { + permit('businessUsers'); + $validatedData = $this->validate($request, [ + 'level' => 'required|numeric|between:0,4', + 'user_id' => 'required|numeric|not_in:'.auth()->id(), + ]); + + DB::transaction(function () use ($validatedData, $request, $business) { + $this->addUser($business, $request->user_id, $validatedData); + if (can('businessAccess', ['user_id'=> $request->user_id])) { + //update + $this->relatedUpdateChanges($request->user_id, $request->level); + } + }, 3); + + return Business::info($business, true); + } + + public function relatedUpdateChanges($user_id, $level) + { + if ($level == enum('levels.owner.id')) { + // user up level to owner + $this->removeProjectDirectRelation($user_id); + } + if ($level != enum('levels.owner.id') && + $level > request('_business_info')['info']['users'][$user_id]['level']) { + // user at least up level to $request->level + $this->updateProjectAccessLevel($level, $user_id); + } + } + + public function addUser($business, $user, $validatedData) + { + $businessModel = Business::findOrFail($business); + $businessModel->users()->sync([$user => $validatedData], false); + } + + public function removeProjectDirectRelation($user) + { + $userModel = User::findOrFail($user); + return $userModel->projects()->sync([], true); + } + + public function updateProjectAccessLevel($level, $user) + { + $ids = []; + foreach (request('_business_info')['projects'] as $project_id => $item) { + foreach ($item['members'] as $idx => $member) { + if ($member['id'] == $user && $member['level'] != enum('levels.inactive.id') && $member['level'] < $level) { + $ids[$project_id] = ['level' => $level]; + break; + } + } + } + $userModel = User::findOrFail($user); + return $userModel->projects()->sync($ids, false); + } + + public function deleteUser($business, $user) + { + permit('businessAccess'); + $this->checkDeleteUserPolicy($user); + $businessModel = Business::findOrFail($business); + + DB::transaction(function () use ($user, $businessModel) { + $this->detachUser($businessModel, $user); + $this->removeProjectDirectRelation($user); + }, 3); + + return Business::info($business, true); + } + + public function haveAnotherOwner($user) + { + foreach (request('_business_info')['info']['users'] as $id => $item) { + if ($item['level'] == enum('levels.owner.id') && $id != $user) { + return true; + } + } + return false; + } + + public function detachUser($business, $user) + { + return $business->users()->sync( + $business->users->except($user)->pluck('id')->toArray() + ); + } + + public function checkDeleteUserPolicy($user) + { + if (!can('isBusinessOwner') && auth()->id() != $user ) { + // Non owner user remove another owner + abort(405); + } + if (can('isBusinessOwner') && auth()->id() == $user && !$this->haveAnotherOwner($user)) { + // Owner remove self but business haven't another owner + abort(405); + } + } + +} diff --git a/app/Http/Controllers/CreditController.php b/app/Http/Controllers/CreditController.php new file mode 100644 index 0000000..e430404 --- /dev/null +++ b/app/Http/Controllers/CreditController.php @@ -0,0 +1,69 @@ +allowedSorts([ + 'amount', + 'succeeded', + 'created_at', + ]) + ->allowedFilters([ + AllowedFilter::exact('user_id'), + AllowedFilter::exact('succeeded'), + ]); + + return TransactionResource::collection( + $builder->paginate($request->per_page) + ); + } + + public function pay(Request $request, int $business) + { + \permit('isBusinessOwner'); + + return Transaction::create([ + 'user_id'=> Auth::id(), + 'business_id'=> $business, + 'amount'=> $request->amount, + ]); + } + + public function redirection($transaction) + { + $transaction = Transaction::findOrFail($transaction); + if ($transaction->isWentToPaymentGateway()) { + throw new \Exception("Siktir baba ye bar ghablan rafti."); + } + + return $transaction->prepare()->redirect(); + } + + public function callback(Request $request) + { + $transaction = Transaction::findByAuthority($request->get('Authority'))->verify(); + if (!$transaction->hasBeenAppliedToWallet() && $transaction->succeeded) { + $transaction->business->increment("wallet", $transaction->amount); + $transaction->amountWasAppliedToWallet(); + + return true; + } + + throw new \Exception("تراکنش تایید نشد"); + } +} diff --git a/app/Http/Controllers/FileController.php b/app/Http/Controllers/FileController.php new file mode 100644 index 0000000..b57455c --- /dev/null +++ b/app/Http/Controllers/FileController.php @@ -0,0 +1,203 @@ +indexValidation($request); + + $per_page = $request->limit > 100 ? 10 : $request->limit; + + return $this->indexFiltering($business)->paginate($per_page); + } + + public function indexValidation($request) + { + $bound = 10; + $this->validate($request, [ + 'filter.project_id' => [new maxBound($bound)] , + 'filter.user_id' => [new maxBound($bound)] , + ]); + } + + public function indexFiltering($business) + { + $query = File::where('business_id', $business); + $fileQ = QueryBuilder::for($query) + ->allowedFilters([ + AllowedFilter::exact('user_id'), + AllowedFilter::exact('project_id'), + AllowedFilter::exact('extension'), + ]); + if (\request('_business_info')['info']['users'][\auth()->id()]['level'] != enum('levels.owner.id')) { + $requested_projects = isset(\request('filter')['project_id']) ? + array_unique(explode(',',\request('filter')['project_id'] ?? null )) : + null; + $requested_projects = collect($requested_projects)->keyBy(null)->toArray(); + $project_ids = $this->myStateProjects($requested_projects); + $fileQ->where(function ($q) use ($project_ids) { + $q->whereIn('project_id', $project_ids['non_guest_ids']) + ->orWhere(function ($q) use ($project_ids) { + $q->whereIn('project_id', $project_ids['guest_ids']) + ->where('user_id', auth()->id()); + }); + }); + } + + if (request()->filled('group')) { + $fileQ->selectRaw("files.group, count(files.id) as file_count, sum(files.size) as file_size")->groupBy('group'); + } + + return $fileQ; + } + + public function myStateProjects($requested_projects) + { + $non_guest_ids = []; + $guest_ids = []; + $is_empty = empty($requested_projects); + + foreach (\request('_business_info')['info']['projects'] as $p_id => $p) { + + $level = \request('_business_info')['info']['projects'][$p_id]['members'][\auth()->id()]['level']; + + if (( $is_empty || isset($requested_projects[$p_id])) + && $level > enum('levels.guest.id')) { + array_push($non_guest_ids, $p_id); + } + if (( $is_empty || isset($requested_projects[$p_id])) + && $level == enum('levels.guest.id')) { + array_push($guest_ids, $p_id); + } + } + + return ['non_guest_ids' => $non_guest_ids, 'guest_ids' => $guest_ids]; + } + + public function store(Request $request, int $business, int $project) + { + // different size and different validation + // validate + // validate the wallet is not so much in debt + // create record in the db + // put file in s3 + // return file resource + $business = Business::findOrFail($business); + $project = Project::findOrFail($project); + + // $this->validate($request, ['file' => 'required|file',]); + + $file = $request->file('file'); + $file_extension = $file->getClientOriginalExtension(); + $file_name = Str::random(40).'.'.$file_extension; + $file->storeAs( + $business->id.\DIRECTORY_SEPARATOR.$project->id, + $file_name, + 's3' + ); + + $file_record = File::create([ + 'user_id' => Auth::id(), + 'business_id' => $business->id, + 'project_id' => $project->id, + 'disk' => 's3', // default disk + 'original_name' => $file->getClientOriginalName(), + 'extension' => $file_extension, + 'name' => $file_name, + 'mime' => $file->getClientMimeType(), + 'group' => $this->groupDetection($file), + 'size' => $file->getSize(), + 'description' => $request->description + ]); + + return new FileResource($file_record); + } + + public function groupDetection(UploadedFile $file) + { + // Media files like mp4, mp3, wma and png or jpeg + [$type, $subtype] = Str::of($file->getMimeType())->explode("/",2)->pad(2, null); + + if (in_array($type, ['audio', 'video', 'image'])) { + return $type; + } + + // Covert string to \Illuminate\Support\Stringable object + $subtype = Str::of($subtype); + + // PDF files + if ($subtype->contains(["pdf"])) { + return "pdf"; + } + + // Compressed files like zip, cab, rar, etc. + if ($subtype->contains(['compressed']) || in_array($file->getClientOriginalExtension(), ['zip', 'rar','7z','cab'])) { + return "compressed"; + } + + // Office files like xls, xlsx, doc, docx, etc. + if ($subtype->contains(['vnd.ms', 'vnd.sealed', 'officedocument', 'opendocument'])) { + return "office"; + } + + // Non of the above files + return "other"; + } + + public function download(int $business, int $project, int $file) + { + // requested file belongs to this project and this business + // check permisson + // create perma link or temp link + // return the file resource or stream it + return File::findOrFail($file)->getTemporaryLink(); + } + + public function rename(Request $request, int $business, int $project, int $file) + { + // requested file belongs to this project and this business + // check permisson + // update original name + // return the file resource + // sanitize the name for slashs and back slashes + $this->validate($request, [ + 'name' => 'required|string' + ]); + + $file = File::findOrFail($file); + + $file->update(['original_name' => $request->name.".".$file->extension]); + + return new FileResource($file); + } + + + public function delete(Request $request, int $business, int $project, int $file) + { + // requested file belongs to this project and this business + // check permisson + // check it's relations + // delete the file form File table + // delete file from s3 + $file = File::findOrFail($file); + Storage::disk('s3')->delete($file->getPath()); + return $file->delete(); + } +} diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php new file mode 100644 index 0000000..1bf3ea2 --- /dev/null +++ b/app/Http/Controllers/InvoiceController.php @@ -0,0 +1,80 @@ +selectRaw("concat_ws('-',business_id,month) as factor_id") + ->selectRaw("MIN(created_at) as begin") + ->selectRaw("MAX(updated_at) as end") + ->selectRaw("sum(cost) as cost") + ->selectRaw("sum(tax) as tax") + ->where('business_id','=',$business->id) + ->groupBy('month','factor_id'); + + $costs = QueryBuilder::for($builder) + ->allowedSorts([ + 'factor_id', + 'begin', + 'end', + 'cost', + ]) + ->allowedFilters([ + AllowedFilter::exact('month'), + AllowedFilter::exact('type'), + ]); + + return $costs->paginate($request->per_page); + } + + public function indexFiltering($business) + { + $query = File::where('business_id', $business); + $fileQ = QueryBuilder::for($query) + ->allowedFilters([ + AllowedFilter::exact('user_id'), + AllowedFilter::exact('project_id'), + AllowedFilter::exact('extension'), + ]); + if (\request('_business_info')['info']['users'][\auth()->id()]['level'] != enum('levels.owner.id')) { + $requested_projects = isset(\request('filter')['project_id']) ? + array_unique(explode(',', \request('filter')['project_id'] ?? null)) : + null; + $requested_projects = collect($requested_projects)->keyBy(null)->toArray(); + $project_ids = $this->myStateProjects($requested_projects); + $fileQ->where(function ($q) use ($project_ids) { + $q->whereIn('project_id', $project_ids['non_guest_ids']) + ->orWhere(function ($q) use ($project_ids) { + $q->whereIn('project_id', $project_ids['guest_ids']) + ->where('user_id', auth()->id()); + }); + }); + } + + if (request()->filled('group')) { + $fileQ->selectRaw("files.group, count(files.id) as file_count, sum(files.size) as file_size")->groupBy('group'); + } + + return $fileQ; + } + + public function show(Request $request, int $business, string $date) + { + return Cost::where('business_id', '=', $business) + ->where("month","=",$date) + ->get(); + } +} diff --git a/app/Http/Controllers/ProjectController.php b/app/Http/Controllers/ProjectController.php new file mode 100644 index 0000000..707625d --- /dev/null +++ b/app/Http/Controllers/ProjectController.php @@ -0,0 +1,159 @@ +get(); + } + + public function store(Request $request, string $business) + { + permit('businessProjects'); + Project::create($request->merge(['business_id' => $business])->all()); + return Business::info($request->route('business'), true); + } + + public function update(Request $request,string $project) + { + permit('projectEdit', ['project_id' => $project]); + $project = Project::findOrFail($project); + $project->update($request->except('business_id')); + return Business::info($request->route('business'), true); + } + + + public function delete(Request $request, string $project) + { + permit('businessProjects'); + $project = Project::findOrFail($project); + $project->delete(); + return Business::info($request->route('business')); + } + + public function restore(Request $request, string $project) + { + $project = Project::onlyTrashed()->findOrFail($project); + $project->restore(); + + return response(['message' => 'project successfully restored.']); + } + + public function storeOrUpdateUser($business, $project, Request $request) + { + permit('projectUsers', ['project_id' => $project]); + $validatedData = $this->validate($request, [ + 'level' => 'required|numeric|between:1,3', + 'user_id' => 'required|numeric|not_in:'.auth()->id(), + ]); + + $this->checkAddUserPolicy($request->user_id, $request->level); + + $projectModel = Project::findOrFail($project); + DB::transaction(function () use ($business, $validatedData, $request, $projectModel) { + $projectModel->members()->sync([$request->user_id => $validatedData], false); + + if (!can('businessAccess', ['user_id' => $request->user_id])) { + + // Register user to business with zero level + //User not exist in the business before + + $this->addUserWithZeroLevel($request->user_id, $business); + } + }, 3); + + return Business::info($projectModel->business_id, true); + } + + public function checkAddUserPolicy($user, $level) + { + if (can('businessAccess', ['user_id' => $user]) + && $level < request('_business_info')['info']['users'][$user]['level']) {// before in business + abort(405); + } + } + + public function addUserWithZeroLevel($user_id, $business) + { + $businessModel = Business::findOrFail($business); + return $businessModel->users()->sync([$user_id => [ + 'level' => 0, + 'user_id' => $user_id + ]], false); + } + + public function deleteUser($business, $project, $user) + { + permit('projectAccess', ['project_id' => $project]); + $this->checkDeleteUserPolicy($user, $project); + + $projectModel = Project::findOrFail($project); + + DB::transaction(function () use ($project, $business, $user, $projectModel) { + $this->detachMember($projectModel, $user); + if (!can('isActiveUser', ['user_id' => $user]) && !$this->haveOneProject($user, $project)) { + + // User level in business is zero + // And haven't another project then remove it form business + + $businessModel = Business::findOrFail($business); + $this->detachUser($businessModel, $user); + } + }, 3); + + return Business::info($projectModel->business_id, true); + } + + public function detachMember($project, $user) + { + return $project->members()->detach($user) ? true : abort(404); + } + + public function detachUser($business, $user) + { + return $business->users()->detach($user) ? true : abort(404); + } + + public function haveOneProject($user, $project) + { + foreach (request('_business_info')['info']['projects'] as $id => $item) { + if ($item['members'][$user]['level'] > enum('levels.inactive.id') && $id != $project) { + return true; + } + } + return false; + } + + public function checkDeleteUserPolicy($user, $project) + { + if (!can('isProjectOwner', ['project_id' => $project]) && (auth()->id() != $user) ) { + abort(405); + } + } + + public function setAvatar(Request $request, string $project) + { + $project = Project::findOrFail($project); + if ($request->hasFile('avatar')) { + $project->saveAsAvatar($request->file('avatar')); + } + + return $project; + } + + public function unSetAvatar(Request $request, string $project) + { + $project = Project::findOrFail($project); + $project->deleteAvatar(); + + return $project; + } +} diff --git a/app/Http/Controllers/SprintController.php b/app/Http/Controllers/SprintController.php new file mode 100644 index 0000000..7f26dcd --- /dev/null +++ b/app/Http/Controllers/SprintController.php @@ -0,0 +1,47 @@ + $project]); + + Sprint::create($request->merge( + ['business_id' => $business, 'project_id' => $project] + )->except('_business_info')); + + return Business::info($business, true); + } + + public function update($business, $project, $sprint, Request $request) + { + permit('projectSprints', ['project_id' => $project]); + + $sprint = Sprint::findOrFail($sprint); + + $sprint->update($request->except('_business_info')); + + return Business::info($business, true); + } + + public function delete($business, $project, $sprint) + { + permit('projectSprints', ['project_id' => $project]); + + $sprint = Sprint::findOrFail($sprint); + + $sprint->delete(); + + return Business::info($business, true); + } + +} diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php new file mode 100644 index 0000000..7740503 --- /dev/null +++ b/app/Http/Controllers/StatusController.php @@ -0,0 +1,37 @@ +merge(['business_id' => $business, 'workflow_id' => $workflow])->except('_business_info')); + return Business::info($business, true); + } + + public function update($business, $workflow, $status, Request $request) + { + permit('businessStatuses'); + $status = Status::findOrFail($status); + $status->update($request->except('_business_info')); + return Business::info($business, true); + } + + public function delete($business, $workflow, $status) + { + permit('businessStatuses'); + $status = Status::findOrFail($status); + $status->delete(); + return Business::info($business, true); + } +} diff --git a/app/Http/Controllers/SystemController.php b/app/Http/Controllers/SystemController.php new file mode 100644 index 0000000..aadc34b --- /dev/null +++ b/app/Http/Controllers/SystemController.php @@ -0,0 +1,40 @@ + $project]); + System::create([ + 'business_id' => $business, + 'project_id' => $project, + 'name' => $request->name + ]); + return Business::info($business, true); + } + + public function update($business, $project, $system, Request $request) + { + permit('projectSystems', ['project_id' => $project]); + $system = System::findOrFail($system); + $system->update($request->except('_business_info')); + return Business::info($business, true); + } + + + public function delete($business, $project, $system) + { + permit('projectSystems', ['project_id' => $project]); + $system = System::findOrFail($system); + $system->delete(); + return Business::info($business, true); + } + + +} diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php new file mode 100644 index 0000000..7d661ba --- /dev/null +++ b/app/Http/Controllers/TagController.php @@ -0,0 +1,37 @@ +merge(['business_id' => $business])->except('_business_info')); + return Business::info($business, true); + } + + public function update($business, $tag, Request $request) + { + permit('businessTags'); + $tag = Tag::findOrFail($tag); + $tag->update($request->except('_business_info')); + return Business::info($business, true); + } + + public function delete($business, $tag) + { + permit('businessTags'); + $tag = Tag::findOrFail($tag); + $tag->delete(); + return Business::info($business, true); + } + +} diff --git a/app/Http/Controllers/TaskFileController.php b/app/Http/Controllers/TaskFileController.php new file mode 100644 index 0000000..ab35061 --- /dev/null +++ b/app/Http/Controllers/TaskFileController.php @@ -0,0 +1,89 @@ +id !== $project->business_id + || $project->id !== $task['project_id'] +// || $task['user_id']!== Auth::id() + ) { + \abort(Response::HTTP_UNAUTHORIZED); + } + + return [$business, $project, $task]; + } + + public function index(int $business, int $project, int $task) + { + // check permissions + // owner project + // admin project + // colleague project + // guest or de active + // return files as file resource + [$business, $project, $task] = $this->checkBelonging($business, $project, $task); + return FileResource::collection($task->files); + } + + public function sync(Request $request,int $business, int $project, int $task) + { + // different size and different validation + // validate + // validate the wallet is not so much in debt + // create record in the db + // put file in s3 + // return file resource + [$business, $project, $task] = $this->checkBelonging($business,$project,$task); + + $this->validate($request, [ + 'files' => 'required|array', + 'files.*' => 'int', + ]); + + $files = File::find($request->files)->each(function (File $file) { + if ($file->user_id !== Auth::id()) { + abort(Response::HTTP_UNAUTHORIZED); + } + }); + + // sync + + return FileResource::collection($files); + } + + public function download(int $business, int $project, int $task, int $file) + { + // requested file belongs to this project and this business + // check permisson + // create perma link or temp link + // return the file resource or stream it + [$business, $project, $task] = $this->checkBelonging($business, $project, $task); + + $file = File::find($file); + if ($file->user_id !== Auth::id()) { + abort(Response::HTTP_UNAUTHORIZED); + } + + return $file->getTemporaryLink(); + } +} diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php new file mode 100644 index 0000000..fba4e8d --- /dev/null +++ b/app/Http/Controllers/UserController.php @@ -0,0 +1,69 @@ +filled('search')){ + $userQ = $userQ->where(function($query) use ($request) { + $query->where('email', 'like', '%'.$request->search.'%') + ->orWhere('username', 'like', '%'.$request->search.'%'); + }); + } + + return $userQ->where('id', '!=', auth()->id()) + ->whereNotIn('id', request('_business_info')['info']['users']->keys()) + ->select('id', 'name', 'email', 'username')->take($limit)->get(); + } + + public function index(Request $request) + { + $userQ = QueryBuilder::for(User::class) + ->allowedFilters([ + AllowedFilter::exact('id'), + ]); + return $userQ->select('id', 'name', 'email', 'username')->get(); + } + + public function show($user) + { + return User::select('id', 'name', 'email', 'username')->findOrFail($user); + } + + public function update(Request $request, string $user) + { + $user = User::findOrFail($user); + $user->update($request->all()); + + return $user; + } + + public function setAvatar(Request $request, string $user) + { + $user = User::findOrFail($user); + if ($request->hasFile('avatar')) { + $user->saveAsAvatar($request->file('avatar')); + } + + return $user; + } + + public function unSetAvatar(Request $request, string $user) + { + $user = User::findOrFail($user); + $user->deleteAvatar(); + + return $user; + } +} diff --git a/app/Http/Controllers/WorkflowController.php b/app/Http/Controllers/WorkflowController.php new file mode 100644 index 0000000..80fdc3d --- /dev/null +++ b/app/Http/Controllers/WorkflowController.php @@ -0,0 +1,71 @@ +merge(['business_id' => $business])->except('_business_info')); +// $statuses = collect($validatedData['statuses'])->map(function($status) use ($workflow, $business) { +// $status['business_id'] = $business; +// $status['workflow_id'] = $workflow->id; +// return $status; +// }); +// $statuses = $workflow->statuses()->createMany($statuses->toArray()); + return Business::info($business, true); + } + + public function update($business, $workflow, Request $request) + { + permit('businessWorkFlows'); + $workflowModel = Workflow::findOrFail($workflow); + $workflowModel->update($request->except('_business_info')); + return Business::info($business, true); + } + + public function syncStatus($business, $workflowModel) + { + $old_statuses_name = array_keys(collect(\request('_business_info')['workflows'][$workflowModel->id]['statuses'])->keyBy('name')->toArray()); + $new_statuses_name = array_keys(collect(\request('statuses'))->keyBy('name')->toArray()); + $removed_statuses_name = array_diff(array_merge($old_statuses_name, $new_statuses_name), $new_statuses_name); + + foreach ($removed_statuses_name as $status_name) { + //delete all statuses that removed name's from request->statuses + $workflowModel->statuses()->where('name', $status_name)->first()->delete(); + } + + foreach (request('statuses') as $status) { + //sync another statuses + $workflowModel->statuses() + ->updateOrCreate( + ['name' => $status['name'], 'business_id' => $business, 'workflow_id' => $workflowModel->id], + ['state' => $status['state'], 'order' => $status['order']] + ); + } + + return $workflowModel; + } + + public function delete($business, $workflow) + { + permit('businessWorkFlows'); + $workflow = Workflow::findOrFail($workflow); + foreach ($workflow->statuses as $status) { + //delete all statuses related to this workflow + $status->delete(); + } + $workflow->delete(); + return Business::info($business, true); + } + +} diff --git a/app/Http/Resources/BusinessResource.php b/app/Http/Resources/BusinessResource.php new file mode 100644 index 0000000..b448dc5 --- /dev/null +++ b/app/Http/Resources/BusinessResource.php @@ -0,0 +1,34 @@ + 'user', + '_resource' => 'businesses', + ]; + + foreach ($this->getAttributes() as $attribute => $value) { + switch ($attribute) { + case 'name': + case 'slug': + case 'wallet': + case 'files_volume': + case 'cache': + case 'calculated_at': + case 'created_at': + case 'updated_at': + case 'deleted_at': + $resource[$attribute] = $value; + break; + } + } + + return $resource; + } +} diff --git a/app/Http/Resources/FileResource.php b/app/Http/Resources/FileResource.php new file mode 100644 index 0000000..3b74fb0 --- /dev/null +++ b/app/Http/Resources/FileResource.php @@ -0,0 +1,37 @@ + 'user', + '_resource' => 'files', + ]; + + foreach ($this->getAttributes() as $attribute => $value) { + switch ($attribute) { + case 'user_id': + case 'business_id': + case 'project_id': + case 'disk': + case 'original_name': + case 'name': + case 'extension': + case 'mime': + case 'size': + case 'description': + $resource[$attribute] = $value; + break; + } + } + + return $resource; + } +} diff --git a/app/Http/Resources/FingerprintResource.php b/app/Http/Resources/FingerprintResource.php new file mode 100644 index 0000000..2c2eded --- /dev/null +++ b/app/Http/Resources/FingerprintResource.php @@ -0,0 +1,34 @@ + 'user', + '_resource' => 'fingerprints', + ]; + + foreach ($this->getAttributes() as $attribute => $value) { + switch ($attribute) { + case 'id': + case 'agent': + case 'ip': + case 'os': + case 'latitude': + case 'longitude': + case 'token': + $resource[$attribute] = $value; + break; + } + } + + return $resource; + } +} diff --git a/app/Http/Resources/ProjectResource.php b/app/Http/Resources/ProjectResource.php new file mode 100644 index 0000000..8800864 --- /dev/null +++ b/app/Http/Resources/ProjectResource.php @@ -0,0 +1,38 @@ + 'user', + '_resource' => 'project', + ]; + + foreach ($this->getAttributes() as $attribute => $value) { + switch ($attribute) { + case 'name': + case 'business_id': + case 'slug': + case 'private': + case 'budget': + case 'start': + case 'finish': + case 'created_at': + case 'updated_at': + case 'archived_at': + case 'deleted_at': + $resource[$attribute] = $value; + break; + } + } + + return $resource; + } +} diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php new file mode 100644 index 0000000..89b07df --- /dev/null +++ b/app/Http/Resources/TransactionResource.php @@ -0,0 +1,32 @@ + 'user', + '_resource' => 'transactions', + ]; + + foreach ($this->getAttributes() as $attribute => $value) { + switch ($attribute) { + case 'user_id': + case 'business_id': + case 'amount': + case 'succeeded': + case 'options': + case 'created_at': + case 'updated_at': + $resource[$attribute] = $value; + break; + } + } + + return $resource; + } +} diff --git a/app/Http/Resources/UserResource.php b/app/Http/Resources/UserResource.php new file mode 100644 index 0000000..5bf3f1f --- /dev/null +++ b/app/Http/Resources/UserResource.php @@ -0,0 +1,34 @@ + 'user', + '_resource' => 'user', + ]; + foreach ($this->getAttributes() as $attribute => $value) { + switch ($attribute) { + case 'id': + case 'name': + case 'mobile': + case 'email': + case 'created_at': + case 'updated_at': + $resource[$attribute] = $value; + break; + } + } + + + $resource['includes']['fingerprints'] = $this->whenLoaded('fingerprints', function () { + return FingerprintResource::collection($this->fingerprints); + }); + + return $resource; + } +} diff --git a/app/Models/Activity.php b/app/Models/Activity.php new file mode 100644 index 0000000..cf4c1d1 --- /dev/null +++ b/app/Models/Activity.php @@ -0,0 +1,10 @@ + 'business_user'] // relations [ name => pivot ] + ]; + + public $detach_relation = false; + + protected $casts = [ + 'has_avatar' => 'boolean', + ]; + + public function getValueOf(?string $key) + { + $values = [ + 'business_id' => $this->id, + 'workflow_id' => null, + 'project_id' => null, + 'sprint_id' => null, + 'status_id' => null, + 'system_id' => null, + 'user_id' => null, + 'task_id' => null, + 'subject_id' => $this->id, + ]; + + if ($key && isset($values, $key)) { + return $values[$key]; + } + + return $values; + } + + public function rules() + { + return [ + 'name' => 'bail|required|string|min:2|max:255', + 'color' => 'nullable|string|min:2|max:255', + 'slug' => ['bail', 'required', 'string', 'min:2', 'max:255', 'regex:/^[a-zA-Z]+[a-zA-Z\d-]*(.*[a-zA-Z\d])+$/', + Rule::unique($this->table, 'slug')->ignore($this->id)], + 'description' => 'nullable|string|min:2|max:1000', + ]; + } + + public function cost() + { + return $this->hasMany(Cost::class, 'business_id','id'); + } + + public function owners() + { + return $this->users()->wherePivot('level', '=', enum('levels.owner.id')); + } + + public function members() + { + return $this->users()->wherePivot('owner', '!=', enum('levels.owner.id')); + } + + public function users() + { + return $this->belongsToMany( + User::class, 'business_user', 'business_id', 'user_id', + 'id', 'id', __FUNCTION__ + ) + ->using(ReportableRelation::class) + ->withPivot(self::$permissions); + } + + public function tags() + { + return $this->hasMany(Tag::class, 'business_id', 'id'); + } + + public function projects() + { + return $this->hasMany(Project::class, 'business_id', 'id'); + } + + public function systems() + { + return $this->hasMany(System::class, 'business_id', 'id'); + } + + public function workflows() + { + return $this->hasMany(Workflow::class, 'business_id', 'id'); + } + public function sprints() + { + return $this->hasMany(Sprint::class, 'business_id', 'id'); + } + + public function statuses() + { + return $this->hasMany(Status::class, 'business_id', 'id'); + } + + public function files() + { + return $this->hasMany(File::class, 'user_id', 'id'); + } + + public function transactions() + { + return $this->hasMany(Transaction::class, 'business_id', 'id'); + } + + public function updateRelations() + { + // users relations + if (!empty($this->filled_relations['users']) || $this->detach_relation) { + $this->dirties['users'] = $this->users()->sync($this->filled_relations['users'], $this->detach_relation); + } + } + + + public static function info($businessId, $fresh = false) + { + + $info = []; + + $fresh = true; + if ($fresh){ + Cache::forget('business_info'.$businessId); + } + + if (Cache::has('business_info'.$businessId)) { + return Cache::get('business_info'.$businessId); + } else { + $business = self::findOrFail($businessId); + + $tags = $business->tags()->select('id', 'label', 'color')->get()->keyBy('id'); + $info['tags'] = $tags->pluck('id'); + + $workflows = $business->workflows()->select ('id', 'business_id', 'name','desc')->get()->keyBy('id') + ->load(['statuses'=> fn($q) => $q->select('id', 'business_id', 'workflow_id', 'name', 'state', 'order')]) + ->map(fn($q) => [ + 'id' => $q->id, + 'business_id' => $q->business_id, + 'name' => $q->name, + 'desc' => $q->desc, + 'statuses' => $q['statuses']->keyBy('id'), + ]); + + $info['workflows'] = $workflows->map(fn($q) => ['statuses' => $q['statuses']->pluck('id')]); + + + $users = $business->users()->select('id', 'name', 'email', 'mobile', 'username')->with('media')->get() + ->keyBy('id') + ->map(fn($u) => [ + 'id' => $u->id, + 'name' => $u->name, + 'email' => $u->email, + 'mobile' => $u->mobile, + 'username' => $u->get, + 'avatar' => $u->has_avatar, + 'level' => $u->pivot['level'], + ]); + + $info['users'] = $users->map(fn($u) => [ + 'level' => $u['level'] + ]); + + $projects = $business->projects()->get()->keyBy('id')->load([ + 'members' => fn($q) => $q->select('id', 'level'), + 'systems' => fn($q) => $q->select('id', 'project_id', 'name'), + 'sprints' => fn($q) => $q->select('id', 'project_id', 'name', 'description', 'started_at', 'ended_at', 'active'), + 'media', + ]); + + $info['projects'] = $projects->map(function($q) use($users){ + return [ + 'avatar' => $q->has_avatar, + 'systems' => $q->systems->pluck('id'), + 'sprints' => $q->sprints->pluck('id'), + 'members' => $users->keyBy('id')->map(function($u, $uid) use ($q){ + $project_user = $q->members->firstWhere('id', $uid); + return $project_user? ['level' => $project_user->pivot->level, 'is_direct' => true]: + ['level' => $q->private && $u['level'] != enum('levels.owner.id') ? enum('levels.inactive.id') : $u['level'], + 'is_direct'=> $project_user ? true : false]; + }) + ]; + }); + + $business_info = array_merge( + $business->only('id', 'name', 'slug', 'color','wallet', 'files_volume'), + ['avatar' => $business->has_avatar], + compact( + 'info', + 'tags', + 'workflows', + 'users', + 'projects' + ) + ); + + Cache::put('business_info'.$businessId , $business_info, config('app.cache_ttl')); + + return $business_info; + } + + + } + + public static function stats() + { + return [ + 'users' => [ + 10 => [ + 'statuses' => [ + 10 => 20, + 30 => 40 + ], + 'workflows' => [ + 10 => 20, + 30 => 40 + ], + 'tags' => [ + 10 => 20, + 30 => 40 + ], + 'project' => [ + 10 => 20, + 30 => 40 + ], + + 'sprints' => [ + 10 => 20, + 30 => 40 + ], + 'works' => [ + ], + '__subsystems' => [ + 10 => 20, + 30 => 40 + ], + ] + ], + 'workflows' => [ + 50 => [ + 'statuses' => [ + 20 => 50 + ], + + ] + ], + 'statuses' => [ + 10 => [ + 'users' => [ + + ], + 'projects' => [ + + ] + ] + ], + 'sprints' => [ + 10 => [ + 'statuses' => [ + 10 => [ + 10 => 1 + ] + ] + ] + ] + ]; + } + + public function reportActivity() + { + + } + + + public static function nuxtInfo($businessId) + { + if (empty($businessId)){ + return null; + } + + Cache::forget('business_nuxt_info' . $businessId); + return Cache::rememberForever('business_nuxt_info' . $businessId, function () use ($businessId) { + + $business = self::with([ + 'projects.members' => fn($q) => $q->select('id', 'name'), + 'projects', + 'tags', + 'workflows.statuses', + 'workflows', + 'statuses', + 'users', + ])->findOrFail($businessId); + + + $globals = []; + $business->users->each(function ($u) use (&$globals) { + $globals[$u->id] = $u->pivot->owner == true ? ['owner' => true] : $u->pivot->only(self::$permissions); + }); + + + $projects = []; + $business->projects->each(function ($p) use (&$projects, &$globals) { + + }); + + + $business->setRelation('projects', collect($projects)); + $business->setRelation('users', collect($globals)); + + return $business; + }); + + } + + + public static function infoOld($businessId) + { + + if (empty($businessId)) + return null; + + + Cache::forget('business_info' . $businessId); + return Cache::rememberForever('business_info' . $businessId, function () use ($businessId) { + $ob = []; + $business = self::with([ + 'projects.members' => fn($q) => $q->select('id', 'name'), + 'projects' => fn($q) => $q->select('id', 'business_id', 'private'), + 'tags' => fn($q) => $q->select('id', 'business_id', 'label'), + 'sprints' => fn($q) => $q->select('id','business_id','name', 'active'), + 'workflows.statuses' => fn($q) => $q->select('id', 'name'), + 'workflows' => fn($q) => $q->select('id', 'business_id', 'name'), + 'statuses' => fn($q) => $q->select('id', 'business_id', 'name', 'state'), + 'users' => fn($q) => $q->select('id', 'name'), + ])->findOrFail($businessId); + + + // permissions in business + $permissions = []; + $business->users->each(function ($user) use (&$permissions) { + $permissions[$user->id] = $user->pivot->only(['owner']); + $permissions[$user->id]['global_PA'] = $permissions[$user->id]['owner'] == true ? + enum('roles.manager.id') : $user->pivot->PA; + $permissions[$user->id]['global_FA'] = $permissions[$user->id]['owner'] == true ? + enum('roles.manager.id') : $user->pivot->FA; + $permissions[$user->id]['PA'] = []; + $permissions[$user->id]['FA'] = []; + }); + + + //projects + $projects = []; + $business->projects->each(function ($p) use (&$permissions, $business, &$projects) { + + $business->users->each(function ($user) use (&$permissions, $p) { + $PA = null; + $FA = null; + + if ($permissions[$user->id]['owner'] == true) { + $PA = enum('roles.manager.id'); + $FA = enum('roles.manager.id'); + } else if (!empty($project_user = $p->getPermissions($user->id))) { + $PA = $project_user->pivot->PA; + $FA = $project_user->pivot->FA; + } else if (empty($p->getPermissions($user->id))) { + $PA = $p->private == false ? $permissions[$user->id]['global_PA'] : enum('roles.hidden.id') ; + $FA = $p->private == false ? $permissions[$user->id]['global_FA'] : enum('roles.hidden.id'); + } + + + if ($PA !== null && $FA !== null) { + $permissions[$user->id]['PA'][$p->id] = $PA; + $permissions[$user->id]['FA'][$p->id] = $FA; + } + }); + + $projects[$p->id] =''; + }); + + + //workflow + $workflows = []; + $business->workflows->each(function ($w) use (&$workflows) { + $workflows[$w->id] = $w->statuses->pluck('id'); + }); + + + $ob['tags'] = $business->tags->pluck('id'); + $ob['statuses'] = $business->statuses; + $ob['sprints'] = $business->sprints; + $ob['workflows'] = $workflows; + $ob['users'] = $permissions; + $ob['projects'] = $projects; + + return collect($ob); + }); + + } + + public function registerMediaCollections(): void + { + $this->addMediaCollection(static::COLLECTION_NAME) + ->acceptsMimeTypes([ + 'image/jpeg', + 'image/png', + 'image/tiff', + 'image/gif', + ]) + ->useDisk('public') + ->singleFile(); + } + + public function registerMediaConversions(Media $media = null): void + { + $this->addMediaConversion(static::CONVERSION_NAME) + ->width(200) + ->height(200) + ->queued() + ->nonOptimized() + ->performOnCollections(static::COLLECTION_NAME); + } + + + public function saveAsAvatar(UploadedFile $avatar): void + { + $this->addMedia($avatar)->toMediaCollection(static::COLLECTION_NAME); + $this->update([ + 'has_avatar' => true, + ]); + @unlink($this->getFirstMedia(static::COLLECTION_NAME)->getPath()); + } + + public function deleteAvatar(): void + { + $path = $this->getFirstMedia(static::COLLECTION_NAME)->getPath(); + $this->getFirstMedia(static::COLLECTION_NAME)->delete(); + $this->update([ + 'has_avatar' => false, + ]); + @unlink($path); + } + + public function getAvatarUrl(): ?string + { + if ($url = $this->getFirstMediaUrl(static::COLLECTION_NAME, static::CONVERSION_NAME)) { + return $url; + } + + return null; + } +} diff --git a/app/Models/Cost.php b/app/Models/Cost.php new file mode 100644 index 0000000..9d29a26 --- /dev/null +++ b/app/Models/Cost.php @@ -0,0 +1,24 @@ + 'array', + 'tax' => 'float', + ]; + + public function business() + { + return $this->belongsTo(Business::class, 'business_id'); + } +} diff --git a/app/Models/File.php b/app/Models/File.php new file mode 100644 index 0000000..f486228 --- /dev/null +++ b/app/Models/File.php @@ -0,0 +1,75 @@ + 'required', + 'business_id' => 'required', + 'project_id' => 'required', + 'original_name' => 'required', + 'name' => 'required', + 'extension' => 'required', + 'size' => 'required', + 'description' => 'nullable', + ]; + } + + + public function user() + { + return $this->belongsTo(User::class, 'user_id','id','id',__FUNCTION__); + } + + public function business() + { + return $this->belongsTo(Business::class, 'business_id', 'id', 'id', __FUNCTION__); + } + + public function project() + { + return $this->belongsTo(Project::class, 'project_id', 'id', 'id', __FUNCTION__); + } + + public function updateRelations() + { + + } + + public function reportActivity() + { + + } + + public function getPath() + { + return $this->business->id . \DIRECTORY_SEPARATOR . $this->project->id . DIRECTORY_SEPARATOR . $this->name; + } + + public function getTemporaryLink() + { + return Storage::disk('s3')->temporaryUrl( + $this->getPath(), + \Carbon\Carbon::now()->addMinutes(15), + [ + 'Content-Type' => $this->mime, + 'Content-Disposition' => $this->original_name, + ] + ); + } +} diff --git a/app/Models/Fingerprint.php b/app/Models/Fingerprint.php new file mode 100644 index 0000000..39866c6 --- /dev/null +++ b/app/Models/Fingerprint.php @@ -0,0 +1,30 @@ +belongsTo(User::class, 'user_id', 'id', __FUNCTION__); + } + + public function rules() + { + return [ + 'user_id' => 'required|integer|exists:users,id', + 'agent' => 'required|string', + 'ip' => 'required|ip', + 'os' => 'required|string', + 'latitude' => 'required', + 'longitude' => 'required', + 'token' => 'required|string|min:60', + ]; + } +} diff --git a/app/Models/Project.php b/app/Models/Project.php new file mode 100644 index 0000000..d1cdf11 --- /dev/null +++ b/app/Models/Project.php @@ -0,0 +1,204 @@ + 'project_user'] + ]; + + protected $fillable_relations = ['members']; + + public $detach_relation = false; + + public function rules() + { + return [ + 'name' => 'required|string|min:2|max:225', + 'slug' => ['required', 'string', 'min:2', 'max:225', + Rule::unique($this->table, 'slug') + ->where('business_id', request('business_id')) + ->whereNull('deleted_at') + ->ignore($this->id)], + 'order' => 'nullable|numeric|min:0', + 'private' => 'nullable|boolean', + 'color' => 'nullable|string|min:2|max:255', + 'active' => 'nullable|boolean', + 'description' => 'nullable|string|min:2|max:1000', + // 'members' => empty($this->id) ? '' : 'required|array' + ]; + } + + protected $casts = [ + 'private' => 'boolean', + 'start' => 'date', + 'finish' => 'date', + 'has_avatar' => 'boolean', + ]; + + public function getValueOf(?string $key) + { + $values = [ + 'business_id' => $this->business_id, + 'project_id' => $this->id, + 'sprint_id' => null, + 'workflow_id' => null, + 'status_id' => null, + 'system_id' => null, + 'actor_id' => auth()->id(), + 'user_id' => null, + 'task_id' => null, + 'subject_id' => $this->id, + ]; + + if ($key && isset($values, $key)) { + return $values[$key]; + } + + return $values; + } + public function members() + { + $permissions = self::$permissions; + return $this->belongsToMany( + User::class, 'project_user', 'project_id', 'user_id', + 'id', 'id', __FUNCTION__ + )->using(ReportableRelation::class) + ->withPivot($permissions); + } + + public function tasks() + { + return $this->hasMany(Task::class, 'project_id', 'id'); + } + + public function business() + { + return $this->belongsTo(Business::class, 'business_id', 'id'); + } + + public function systems() + { + return $this->hasMany(System::class, 'project_id', 'id'); + } + + public function sprints() + { + return $this->hasMany(Sprint::class, 'project_id', 'id'); + } + + public function files() + { + return $this->hasMany(File::class, 'user_id', 'id'); + } + + public function updateRelations() + { + // members +// if (!empty($this->filled_relations['members']) || $this->detach_relation) { +// $this->dirties['members'] = $this->members()->sync($this->filled_relations['members'], $this->detach_relation); +// } + } + + public function reportActivity() + { +// foreach ($this->dirties as $name => $value) { +// return \post('task', 'task/v1/log', [ +// 'user_id' => Auth::id(), +// 'business_id' => $this->business_id, +// 'loggable_id' => $this->id, +// 'loggable_type' => $this->getTypeId(), +// 'action' => $this->getAction(), // id of the action +// 'data' => [$name => [ +// 'original' => $value['original'], +// 'diff' => $value['diff'], +// ]], +// ]); +// } + } + + public function getPermissions($user_id) + { + return $this->members->where('id',$user_id)->first(); + } + + public function registerMediaCollections(): void + { + $this->addMediaCollection(static::COLLECTION_NAME) + ->acceptsMimeTypes([ + 'image/jpeg', + 'image/png', + 'image/tiff', + 'image/gif', + ]) + ->useDisk('public') + ->singleFile(); + } + + public function registerMediaConversions(Media $media = null): void + { + $this->addMediaConversion(static::CONVERSION_NAME) + ->width(200) + ->height(200) + ->queued() + ->nonOptimized() + ->performOnCollections(static::COLLECTION_NAME); + } + + + public function saveAsAvatar(UploadedFile $avatar): void + { + $this->addMedia($avatar)->toMediaCollection(static::COLLECTION_NAME); + $this->update([ + 'has_avatar' => true, + ]); + @unlink($this->getFirstMedia(static::COLLECTION_NAME)->getPath()); + } + + public function deleteAvatar(): void + { + $path = $this->getFirstMedia(static::COLLECTION_NAME)->getPath(); + $this->getFirstMedia(static::COLLECTION_NAME)->delete(); + $this->update([ + 'has_avatar' => false, + ]); + @unlink($path); + } + + public function getAvatarUrl(): ?string + { + if ($url = $this->getFirstMediaUrl(static::COLLECTION_NAME, static::CONVERSION_NAME)) { + return $url; + } + + return null; + } +} diff --git a/app/Models/SoftDeletes.php b/app/Models/SoftDeletes.php new file mode 100644 index 0000000..53b6836 --- /dev/null +++ b/app/Models/SoftDeletes.php @@ -0,0 +1,29 @@ +forceDeleting) { + $this->exists = false; + + return $this->setKeysForSaveQuery($this->newModelQuery())->forceDelete(); + } + + $time = $this->freshTimestamp(); + + $this->{$this->getDeletedAtColumn()} = $time; + + if ($this->timestamps && !is_null($this->getUpdatedAtColumn())) { + $this->{$this->getUpdatedAtColumn()} = $time; + } + + return $this->save(); + } +} diff --git a/app/Models/Sprint.php b/app/Models/Sprint.php new file mode 100644 index 0000000..c1ad584 --- /dev/null +++ b/app/Models/Sprint.php @@ -0,0 +1,73 @@ + 'bail|required|string|min:2|max:225', + 'started_at' => 'bail|required|date|date_format:Y-m-d', + 'ended_at' => 'bail|required|date|date_format:Y-m-d|after:started_at', + 'active' => 'nullable|boolean', + 'description' => 'nullable|string|min:2|max:1000', + ]; + } + + protected $casts = [ + 'active' => 'boolean' + ]; + + public function getValueOf(?string $key) + { + $values = [ + 'business_id' => $this->business_id, + 'project_id' => $this->project_id, + 'sprint_id' => $this->id, + 'workflow_id' => null, + 'status_id' => null, + 'system_id' => null, + 'user_id' => null, + 'task_id' => null, + 'subject_id' => $this->id, + ]; + + if ($key && isset($values, $key)) { + return $values[$key]; + } + + return $values; + } + + + public function business() + { + return $this->belongsTo(Business::class, 'business_id', 'id'); + } + + public function projects() + { + return $this->belongsTo(Project::class, 'project_id', 'id'); + } + + public function tasks() + { + return $this->hasMany(Task::class, 'sprint_id', 'id'); + } + +} diff --git a/app/Models/Status.php b/app/Models/Status.php new file mode 100644 index 0000000..8c836b0 --- /dev/null +++ b/app/Models/Status.php @@ -0,0 +1,55 @@ +'required|string|min:3|max:255', + 'state' => 'nullable|between:0,3', + 'order' => 'nullable|numeric|min:0' + ]; + } + + public function getValueOf(?string $key) + { + $values = [ + 'business_id' => $this->business_id, + 'project_id' => null, + 'sprint_id' => null, + 'workflow_id' => $this->workflow_id, + 'status_id' => $this->id, + 'system_id' => null, + 'user_id' => null, + 'task_id' => null, + 'subject_id' => $this->id, + ]; + + if ($key && isset($values, $key)) { + return $values[$key]; + } + + return $values; + } + + public function workflow() + { + return $this->belongsTo(Workflow::class,'workflow_id','id'); + } +} diff --git a/app/Models/System.php b/app/Models/System.php new file mode 100644 index 0000000..0a7da6b --- /dev/null +++ b/app/Models/System.php @@ -0,0 +1,69 @@ + 'required|string|min:2|max:225', + ]; + } + + protected $casts = [ + 'private' => 'boolean' + ]; + + public function getValueOf(?string $key) + { + $values = [ + 'business_id' => $this->business_id, + 'project_id' => $this->project_id, + 'sprint_id' => null, + 'workflow_id' => null, + 'status_id' => null, + 'system_id' => $this->id, + 'user_id' => null, + 'task_id' => null, + 'subject_id' => $this->id, + ]; + + if ($key && isset($values, $key)) { + return $values[$key]; + } + + return $values; + } + + + public function business() + { + return $this->belongsTo(Business::class, 'business_id', 'id'); + } + + public function project() + { + return $this->belongsTo(Project::class, 'project_id', 'id'); + } + + + public function tasks() + { + return $this->hasMany(Task::class, 'sub_project_id', 'id'); + } + +} diff --git a/app/Models/Tag.php b/app/Models/Tag.php new file mode 100644 index 0000000..6e2c425 --- /dev/null +++ b/app/Models/Tag.php @@ -0,0 +1,58 @@ + $this->business_id, + 'project_id' => null, + 'sprint_id' => null, + 'workflow_id' => null, + 'status_id' => null, + 'system_id' => null, + 'user_id' => null, + 'task_id' => null, + 'subject_id' => $this->id, + ]; + + if ($key && isset($values, $key)) { + return $values[$key]; + } + + return $values; + } + + public function rules() + { + return [ + 'label' => 'required|string|min:3|max:225', + 'color' => 'nullable|string|min:2|max:255', + ]; + } + + public function business() + { + return $this->belongsTo(Business::class,'business_id','id',__FUNCTION__); + } + + public function task() + { + return $this->belongsToMany( + Task::class,'tag_task','tag_id','task_id', + 'id','id',__FUNCTION__ + ); + } +} diff --git a/app/Models/Task.php b/app/Models/Task.php new file mode 100644 index 0000000..f29906b --- /dev/null +++ b/app/Models/Task.php @@ -0,0 +1,25 @@ +host = 'hi-task-app'; + $this->path = 'task/v1/businesses/'.request('_business_info')['id'].'/tasks/'; + } + + public function files() + { + return $this->hasMany(File::class, 'attached_to_id', 'id') + ->where('attached_to_table', enum('tables.tasks.id')); + } +} diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php new file mode 100644 index 0000000..7cb1a4e --- /dev/null +++ b/app/Models/Transaction.php @@ -0,0 +1,164 @@ + 'array', + 'succeeded' => 'boolean', + ]; + + protected $fillable_relations = [ + 'user', 'business' + ]; + + protected $reportable = [ + 'user_id', 'business_id', 'amount', 'succeeded', 'options', // fields + ]; + + public $perPage = 12; + + public function getValueOf(?string $key) + { + $values = [ + 'business_id' => $this->business_id, + 'project_id' => null, + 'sprint_id' => null, + 'system_id' => null, + 'user_id' => $this->user_id, + 'workflow_id' => null, + 'status_id' => null, + 'task_id' => null, + 'subject_id' => $this->id, + ]; + + if ($key && isset($values, $key)) { + return $values[$key]; + } + + return $values; + } + + public function rules(): array + { + return [ + 'user_id' => 'required|', + 'business_id' => 'required', + 'amount' => 'required|integer|min:1', + ]; + } + + public function updateRelations() + { + // user relations + if (!empty($this->filled_relations['user'])) { + $this->dirties['user'] = $this->user_id; + } + + // business relations + if (!empty($this->filled_relations['business'])) { + $this->dirties['business'] = $this->business_id; + } + } + + public function reportActivity() + { + + } + + public function user() + { + return $this->belongsTo(User::class, 'user_id','id',__FUNCTION__); + } + + public function business() + { + return $this->belongsTo(Business::class, 'business_id','id',__FUNCTION__); + } + + /** + * Receive the authority key from the payment gateway + */ + public function prepare(): Transaction + { + $results = Zarinpal::request( + config('services.zarinpal.callback-url'), + $this->amount, + config('services.zarinpal.description') + ); + + $this->options = $results; + $this->save(); + + return $this; + } + + /** + * Redirect to the payment gateway + */ + public function redirect() + { + return Zarinpal::redirect(); + } + + public function verify(): Transaction + { + $results = Zarinpal::verify($this->amount, $this->options['Authority']); + if ($results['Status'] == 'verified_before') { + throw new \Exception("تراکنش قبلا تایید شده است."); + } + + if ($results['Status'] == 'success') { + $this->succeeded = true; + } else { + $this->succeeded = false; + } + + $options = array_merge($this->options, $results); + $this->options = $options; + $this->save(); + + return $this; + } + + /** + * Find a transaction via the authoriry key that psp provides us + * + * @throw ModelNotFound + */ + public static function findByAuthority(string $authority): Transaction + { + return static::where('options->Authority','=',$authority)->firstOrFail(); + } + + public function isWentToPaymentGateway(): bool + { + return !empty($this->options); + } + + public function hasBeenAppliedToWallet(): bool + { + return Arr::get($this->options,"applied", false); + } + + public function amountWasAppliedToWallet() + { + $options = $this->options; + $options['applied'] = true; + $this->options = $options; + + $this->save(); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 804799b..1a47d13 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -1,43 +1,184 @@ 'boolean', ]; - /** - * The attributes that should be cast to native types. - * - * @var array - */ - protected $casts = [ - 'email_verified_at' => 'datetime', + protected $fillable = ['name', 'email','mobile', 'username','password','active','has_avatar']; + + protected $fillable_relations = ['projects']; + + protected $reportable = [ + 'name', 'username', 'mobile', 'email', // fields + ['projects' => 'project_user'] ]; + + public $detach_relation = false; + + public function updateRelations() + { + // projects relations + if (!empty($this->filled_relations['projects']) || $this->detach_relation) { + $this->dirties['projects'] = $this->projects()->sync($this->filled_relations['projects'], $this->detach_relation); + } + } + + /** =============================== Validations ======================== */ + public function rules() + { + return [ + 'name' => 'required|string|max:225|min:2', + 'username' => ['required', Rule::unique('users', 'username')->ignore($this->id)], + 'email' => ['required', 'email', Rule::unique('users', 'email')->ignore($this->id)], + 'password' => ['required','string','min:8'] + ]; + } + /** =============================== End Validations ==================== */ + + + /** =============================== Relations ========================== */ + public function fingerprints() + { + return $this->hasMany(Fingerprint::class, 'user_id', 'id'); + } + + public function businesses() + { + return $this->belongsToMany( + Business::class, + 'business_user', + 'user_id', + 'business_id', + 'id', + 'id', + __FUNCTION__ + ); + } + + + public function tasks() + { + return $this->hasMany(Task::class, 'user_id', 'id'); + } + + public function projects() + { + return $this->belongsToMany( + Project::class, + 'project_user', + 'user_id', + 'project_id', + 'id', + 'id', + __FUNCTION__ + )->using(ReportableRelation::class); + } + + public function files() + { + return $this->hasMany(File::class, 'user_id','id'); + } + + + /** =============================== End Relations ====================== */ + + public function getValueOf(?string $key) + { + $values = [ + 'business_id' => request('_business_info')['id'] ?? null, + 'user_id' => $this->id, + 'workflow_id' => null, + 'project_id' => null, + 'sprint_id' => null, + 'system_id' => null, + 'status_id' => null, + 'task_id' => null, + 'subject_id' => $this->id, + ]; + + if ($key && isset($values, $key)) { + return $values[$key]; + } + + return $values; + } + + public function registerMediaCollections(): void + { + $this->addMediaCollection(static::COLLECTION_NAME) + ->acceptsMimeTypes([ + 'image/jpeg', + 'image/png', + 'image/tiff', + 'image/gif', + ]) + ->useDisk('public') + ->singleFile(); + } + + public function registerMediaConversions(Media $media = null): void + { + $this->addMediaConversion(static::CONVERSION_NAME) + ->width(200) + ->height(200) + ->queued() + ->nonOptimized() + ->performOnCollections(static::COLLECTION_NAME); + } + + + public function saveAsAvatar(UploadedFile $avatar): void + { + $this->addMedia($avatar)->toMediaCollection(static::COLLECTION_NAME); + $this->update([ + 'has_avatar' => true, + ]); + @unlink($this->getFirstMedia(static::COLLECTION_NAME)->getPath()); + } + + public function deleteAvatar(): void + { + $path = $this->getFirstMedia(static::COLLECTION_NAME)->getPath(); + $this->getFirstMedia(static::COLLECTION_NAME)->delete(); + $this->update([ + 'has_avatar' => false, + ]); + @unlink($path); + } + + public function getAvatarUrl(): ?string + { + if ($url = $this->getFirstMediaUrl(static::COLLECTION_NAME, static::CONVERSION_NAME)) { + return $url; + } + + return null; + } } diff --git a/app/Models/Workflow.php b/app/Models/Workflow.php new file mode 100644 index 0000000..3446f7d --- /dev/null +++ b/app/Models/Workflow.php @@ -0,0 +1,88 @@ + 'required|string|min:3|max:225', + 'desc' => 'nullable|string|min:3|max:225', + 'statuses' => 'required|array|min:2', + 'statuses.*' => 'required|array|min:2', + 'statuses.*.id' => 'nullable|numeric', + 'statuses.*.name' => 'required|string|min:3', + 'statuses.*.state' => 'required|numeric|between:0,3', + 'statuses.*.order' => 'nullable|numeric', + ]; + } + + public function getValueOf(?string $key) + { + $values = [ + 'business_id' => $this->business_id, + 'project_id' => null, + 'sprint_id' => null, + 'workflow_id' => $this->id, + 'status_id' => null, + 'system_id' => null, + 'user_id' => null, + ]; + + if ($key && isset($values, $key)) { + return $values[$key]; + } + + return $values; + } + + public function updateRelations() + { + $old_statuses_name = isset(\request('_business_info')['workflows'][$this->id]['statuses']) ? + array_keys(collect(\request('_business_info')['workflows'][$this->id]['statuses'])->toArray()) : + []; + $new_statuses_name = array_keys(collect($this->filled_relations['statuses'])->keyBy('id')->toArray()); + $removed_statuses_name = array_diff(array_merge($old_statuses_name, $new_statuses_name), $new_statuses_name); + + foreach ($removed_statuses_name as $status_name) { + //delete all statuses that removed name's from request->statuses + $this->statuses()->where('id', $status_name)->first()->delete(); + } + + foreach (request('statuses') as $status) { + //sync another statuses + $this->statuses() + ->updateOrCreate( + ['id' => $status['id'] ?? null, 'business_id' => $this->business_id, 'workflow_id' => $this->id], + ['name' => $status['name'], 'state' => $status['state'], 'order' => $status['order']] + ); + } + } + + public function business() + { + return $this->belongsTo(Business::class, 'business_id'); + } + + public function statuses() + { + return $this->hasMany(Status::class, 'workflow_id', 'id'); + } + + public function tasks() + { + return $this->hasMany(Task::class, 'workflow_id', 'id'); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index ce74491..a5cc37f 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -2,8 +2,10 @@ namespace App\Providers; +use App\Fingerprint; +use App\Utilities\RequestMixin; +use App\Utilities\BusinessInfoRequestMixin; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; -use Illuminate\Support\Facades\Gate; class AuthServiceProvider extends ServiceProvider { @@ -25,6 +27,21 @@ class AuthServiceProvider extends ServiceProvider { $this->registerPolicies(); - // + $this->app['request']->mixin(new RequestMixin); + $this->app['request']->mixin(new BusinessInfoRequestMixin); + + $this->app['auth']->viaRequest('api', function ($request) { + if ($request->bearerToken() === null) { + return null; + } + + $fingerprint = Fingerprint::where([ + 'token' => $request->bearerToken(), + 'agent' => $request->getAgent(), + 'os' => $request->getOS(), + ])->first(); + + return $fingerprint->user->setAttribute('token', $fingerprint->token); + }); } } diff --git a/app/Rules/MaxBound.php b/app/Rules/MaxBound.php new file mode 100644 index 0000000..b4a530e --- /dev/null +++ b/app/Rules/MaxBound.php @@ -0,0 +1,40 @@ +bound; + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return 'The :attribute is out of bound.'; + } +} diff --git a/app/Scopes/BusinessScope.php b/app/Scopes/BusinessScope.php new file mode 100644 index 0000000..7f99783 --- /dev/null +++ b/app/Scopes/BusinessScope.php @@ -0,0 +1,18 @@ +where('business_id', '=', request('business_id')); + } +} diff --git a/app/Utilities/Avatar/DefaultConversionFileNamer.php b/app/Utilities/Avatar/DefaultConversionFileNamer.php new file mode 100644 index 0000000..2e11692 --- /dev/null +++ b/app/Utilities/Avatar/DefaultConversionFileNamer.php @@ -0,0 +1,15 @@ +model->getKey(); + } +} diff --git a/app/Utilities/Avatar/DefaultPathGenerator.php b/app/Utilities/Avatar/DefaultPathGenerator.php new file mode 100644 index 0000000..1b21029 --- /dev/null +++ b/app/Utilities/Avatar/DefaultPathGenerator.php @@ -0,0 +1,41 @@ +model->getTable()."/"; + } + + /* + * Get the path for the given media, relative to the root storage path. + */ + public function getPath(Media $media): string + { + return $this->getBasePath($media); + } + + /* + * Get the path for conversions of the given media, relative to the root storage path. + */ + public function getPathForConversions(Media $media): string + { + return $this->getBasePath($media); + } + + /* + * Get the path for responsive images of the given media, relative to the root storage path. + */ + public function getPathForResponsiveImages(Media $media): string + { + return $this->getBasePath($media).'/responsive-images/'; + } +} diff --git a/app/Utilities/BusinessInfoRequestMixin.php b/app/Utilities/BusinessInfoRequestMixin.php new file mode 100644 index 0000000..5966ae3 --- /dev/null +++ b/app/Utilities/BusinessInfoRequestMixin.php @@ -0,0 +1,43 @@ +getFromBusinessInfo('info.users'); + }; + } + + public function isBusinessOwner() + { + return function(User $user) { + return Arr::get($this, "_business_info.info.users.{$user->id}.level") != enum('levels.owner.id'); + }; + } +} diff --git a/app/Utilities/Payload.php b/app/Utilities/Payload.php new file mode 100644 index 0000000..a845b28 --- /dev/null +++ b/app/Utilities/Payload.php @@ -0,0 +1,83 @@ +payload = $payload; + } + + public function getActor(): ?Notifiable + { + return new Notifiable(Arr::get($this->payload, "info.users." . $this['auth'])); + } + + public function getSubject(): ?Notifiable + { + return new Notifiable( + Arr::get($this->payload, "info.users." . $this['data']['original']['user_id']) + ); + } + + public function getOwners(): Collection + { + return new Collection( + Arr::where($this->payload['info']['users'], fn ($user) => $user['level'] === 4) + ); + } + + public function getTableName(): ?Stringable + { + return Str::of(Arr::get($this->payload, "data.table_name")); + } + + public function getActId() + { + return Arr::get($this->payload, "data.crud_id"); + } + + public function getTitle() + { + return Arr::get($this->payload, "info.name"); + } + + public function isPivot(): bool + { + return $this->getTableName()->contains("_"); + } + + public function offsetExists($key) + { + return isset($this->payload[$key]); + } + + public function offsetGet($key) + { + return $this->payload[$key]; + } + + public function offsetSet($key, $value) + { + if (is_null($key)) { + $this->payload[] = $value; + } else { + $this->payload[$key] = $value; + } + } + + public function offsetUnset($key) + { + unset($this->payload[$key]); + } +} diff --git a/app/Utilities/RequestMixin.php b/app/Utilities/RequestMixin.php new file mode 100644 index 0000000..c53192e --- /dev/null +++ b/app/Utilities/RequestMixin.php @@ -0,0 +1,51 @@ + $this->hasHeader('USER_AGENT') ? (new Agent())->platform() : null; + } + + /** + * Return the browser + * + * @return Closure + */ + public function getAgent() + { + return fn() => $this->hasHeader('USER_AGENT') ? (new Agent())->browser() : null; + } + + + /** + * Get the user location's based on her/his IP address + * + * @return Closure + */ + public function getLocation() + { + return fn() => geoip()->getLocation($this->getClientIp()); + } + + public function getCurrentToken() + { + // todo: how to implement ip lookup for current token + return fn() => Auth::user()->token; + } +} diff --git a/app/Utilities/Zarinpal/Drivers/DriverInterface.php b/app/Utilities/Zarinpal/Drivers/DriverInterface.php new file mode 100644 index 0000000..8227518 --- /dev/null +++ b/app/Utilities/Zarinpal/Drivers/DriverInterface.php @@ -0,0 +1,46 @@ +restCall('PaymentRequest.json', $inputs); + + if ($result['Status'] == 100) { + return ['Authority' => $result['Authority']]; + } else { + return ['error' => $result['Status']]; + } + } + + /** + * requestWithExtra driver. + * + * @param $inputs + * + * @return array + */ + public function requestWithExtra($inputs) + { + $result = $this->restCall('PaymentRequestWithExtra.json', $inputs); + + if ($result['Status'] == 100) { + return ['Authority' => $result['Authority']]; + } else { + return [ + 'Status' => 'error', + 'error' => !empty($result['Status']) ? $result['Status'] : null, + 'errorInfo' => !empty($result['errors']) ? $result['errors'] : null, + ]; + } + } + + /** + * verify driver. + * + * @param $inputs + * + * @return array + */ + public function verify($inputs) + { + $result = $this->restCall('PaymentVerification.json', $inputs); + + if ($result['Status'] == 100) { + return [ + 'Status' => 'success', + 'RefID' => $result['RefID'], + ]; + } elseif ($result['Status'] == 101) { + return [ + 'Status' => 'verified_before', + 'RefID' => $result['RefID'], + ]; + } else { + return [ + 'Status' => 'error', + 'error' => !empty($result['Status']) ? $result['Status'] : null, + 'errorInfo' => !empty($result['errors']) ? $result['errors'] : null, + ]; + } + } + + /** + * verifyWithExtra driver. + * + * @param $inputs + * + * @return array + */ + public function verifyWithExtra($inputs) + { + $result = $this->restCall('PaymentVerificationWithExtra.json', $inputs); + + if ($result['Status'] == 100) { + return [ + 'Status' => 'success', + 'RefID' => $result['RefID'], + 'ExtraDetail' => $result['ExtraDetail'], + ]; + } elseif ($result['Status'] == 101) { + return [ + 'Status' => 'verified_before', + 'RefID' => $result['RefID'], + 'ExtraDetail' => $result['ExtraDetail'], + ]; + } else { + return [ + 'Status' => 'error', + 'error' => !empty($result['Status']) ? $result['Status'] : null, + 'errorInfo' => !empty($result['errors']) ? $result['errors'] : null, + ]; + } + } + + /** + * unverifiedTransactions driver. + * + * @param $inputs + * + * @return array + */ + public function unverifiedTransactions($inputs) + { + $result = $this->restCall('UnverifiedTransactions.json', $inputs); + + if ($result['Status'] == 100) { + return ['Status' => 'success', 'Authorities' => $result['Authorities']]; + } else { + return [ + 'Status' => 'error', + 'error' => !empty($result['Status']) ? $result['Status'] : null, + 'errorInfo' => !empty($result['errors']) ? $result['errors'] : null, + ]; + } + } + + /** + * refreshAuthority driver. + * + * @param $inputs + * + * @return array + */ + public function refreshAuthority($inputs) + { + $result = $this->restCall('RefreshAuthority.json', $inputs); + + if ($result['Status'] == 100) { + return ['Status' => 'success', 'refreshed' => true]; + } else { + return ['Status' => 'error', 'error' => $result['Status']]; + } + } + + /** + * request rest and return the response. + * + * @param $uri + * @param $data + * + * @return mixed + */ + private function restCall($uri, $data) + { + try { + $client = new Client(['base_uri' => $this->baseUrl]); + $response = $client->request('POST', $uri, ['json' => $data]); + + $rawBody = $response->getBody()->getContents(); + $body = json_decode($rawBody, true); + } catch (RequestException $e) { + $response = $e->getResponse(); + $rawBody = is_null($response) ? '{"Status":-98,"message":"http connection error"}' : $response->getBody()->getContents(); + $body = json_decode($rawBody, true); + } + + if (!isset($result['Status'])) { + $result['Status'] = -99; + } + + return $body; + } + + /** + * @param mixed $baseUrl + * + * @return void + */ + public function setAddress($baseUrl) + { + $this->baseUrl = $baseUrl; + } + + public function enableSandbox() + { + $this->setAddress('https://sandbox.zarinpal.com/pg/rest/WebGate/'); + } +} diff --git a/app/Utilities/Zarinpal/Laravel/Facade/Zarinpal.php b/app/Utilities/Zarinpal/Laravel/Facade/Zarinpal.php new file mode 100644 index 0000000..921c2fb --- /dev/null +++ b/app/Utilities/Zarinpal/Laravel/Facade/Zarinpal.php @@ -0,0 +1,24 @@ +app->singleton(DriverInterface::class, function () { + return new RestDriver(); + }); + + $this->app->singleton('Zarinpal', function () { + $merchantID = config('services.zarinpal.merchantID', config('Zarinpal.merchantID', 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX')); + + $zarinpal = new Zarinpal($merchantID, $this->app->make(DriverInterface::class)); + + if (config('services.zarinpal.sandbox', false)) { + $zarinpal->enableSandbox(); + } + if (config('services.zarinpal.zarinGate', false)) { + $zarinpal->isZarinGate(); + } + + return $zarinpal; + }); + } + + /** + * Publish the plugin configuration. + */ + public function boot() + { + // + } +} diff --git a/app/Utilities/Zarinpal/Zarinpal.php b/app/Utilities/Zarinpal/Zarinpal.php new file mode 100644 index 0000000..6339b33 --- /dev/null +++ b/app/Utilities/Zarinpal/Zarinpal.php @@ -0,0 +1,130 @@ +merchantID = $merchantID; + $this->driver = $driver; + } + + /** + * send request for money to zarinpal + * and redirect if there was no error. + * + * @param string $callbackURL + * @param string $Amount + * @param string $Description + * @param string $Email + * @param string $Mobile + * @param null $additionalData + * + * @return array|@redirect + */ + public function request($callbackURL, $Amount, $Description, $Email = null, $Mobile = null, $additionalData = null) + { + $inputs = [ + 'MerchantID' => $this->merchantID, + 'CallbackURL' => $callbackURL, + 'Amount' => $Amount, + 'Description' => $Description, + ]; + if (!is_null($Email)) { + $inputs['Email'] = $Email; + } + if (!is_null($Mobile)) { + $inputs['Mobile'] = $Mobile; + } + if (!is_null($additionalData)) { + $inputs['AdditionalData'] = $additionalData; + $results = $this->driver->requestWithExtra($inputs); + } else { + $results = $this->driver->request($inputs); + } + + if (empty($results['Authority'])) { + $results['Authority'] = null; + } + $this->Authority = $results['Authority']; + + return $results; + } + + /** + * verify that the bill is paid or not + * by checking authority, amount and status. + * + * @param $amount + * @param $authority + * + * @return array + */ + public function verify($amount, $authority) + { + // backward compatibility + if (count(func_get_args()) == 3) { + $amount = func_get_arg(1); + $authority = func_get_arg(2); + } + + $inputs = [ + 'MerchantID' => $this->merchantID, + 'Authority' => $authority, + 'Amount' => $amount, + ]; + + return $this->driver->verifyWithExtra($inputs); + } + + public function redirect() + { + header('Location: ' . sprintf($this->redirectUrl, $this->Authority)); + die; + } + + /** + * @return string + */ + public function redirectUrl() + { + return sprintf($this->redirectUrl, $this->Authority); + } + + /** + * @return DriverInterface + */ + public function getDriver() + { + return $this->driver; + } + + /** + * active sandbox mod for test env. + */ + public function enableSandbox() + { + $this->redirectUrl = 'https://sandbox.zarinpal.com/pg/StartPay/%u'; + $this->getDriver()->enableSandbox(); + } + + /** + * active zarinGate mode. + */ + public function isZarinGate() + { + $this->redirectUrl = $this->redirectUrl . '/ZarinGate'; + } +} diff --git a/composer.json b/composer.json index 3795a6d..5139383 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,21 @@ "license": "MIT", "require": { "php": "^7.3|^8.0", + "ext-gd": "*", + "ext-json": "*", + "anik/amqp": "^1.3", + "illuminate/notifications": "^8.0", + "jenssegers/agent": "^2.6", + "laravel/legacy-factories": "^1", + "laravel/lumen-framework": "^8.0", + "laravel/socialite": "^5.1", + "league/flysystem-aws-s3-v3": "~1.0", + "league/flysystem-cached-adapter": "~1.0", + "morilog/jalali": "3.*", + "spatie/image": "^1.0", + "spatie/laravel-medialibrary": "^8.0", + "spatie/laravel-query-builder": "^3.3", + "torann/geoip": "^3.0", "fideloper/proxy": "^4.4", "fruitcake/laravel-cors": "^2.0", "guzzlehttp/guzzle": "^7.0.1", diff --git a/composer.lock b/composer.lock index a5ae24e..10b1f47 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,63 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4a16c3c541bd99241cab1c21ce8e83ac", + "content-hash": "990d5c126e6930062665fabddea7749a", "packages": [ + { + "name": "anik/amqp", + "version": "v1.5", + "source": { + "type": "git", + "url": "https://github.com/ssi-anik/amqp.git", + "reference": "091620674aefc6bd5666be2fd9cbbdccfded93cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ssi-anik/amqp/zipball/091620674aefc6bd5666be2fd9cbbdccfded93cc", + "reference": "091620674aefc6bd5666be2fd9cbbdccfded93cc", + "shasum": "" + }, + "require": { + "illuminate/container": "^5.8|^6.0|^7.0|^8.0", + "illuminate/pipeline": "^5.8|^6.0|^7.0|^8.0", + "illuminate/support": "^5.8|^6.0|^7.0|^8.0", + "laravel/helpers": "^1.2", + "php": ">=7.0", + "php-amqplib/php-amqplib": "^2.9 !=2.12.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Anik\\Amqp\\ServiceProviders\\AmqpServiceProvider" + ], + "aliases": { + "Amqp": "Anik\\Amqp\\Facades\\Amqp" + } + } + }, + "autoload": { + "psr-4": { + "Anik\\Amqp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Syed Sirajul Islam Anik", + "email": "sirajul.islam.anik@gmail.com" + } + ], + "description": "php-amqplib wrapper that eases the consumption of RabbitMQ. A painless way of using RabbitMQ", + "support": { + "issues": "https://github.com/ssi-anik/amqp/issues", + "source": "https://github.com/ssi-anik/amqp/tree/v1.5" + }, + "time": "2020-09-25T00:37:54+00:00" + }, { "name": "asm89/stack-cors", "version": "v2.0.2", @@ -56,8 +111,167 @@ "cors", "stack" ], + "support": { + "issues": "https://github.com/asm89/stack-cors/issues", + "source": "https://github.com/asm89/stack-cors/tree/v2.0.2" + }, "time": "2020-10-29T16:03:21+00:00" }, + { + "name": "aws/aws-sdk-php", + "version": "3.173.19", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "63c6feca49bf4083f33bf250401c0c286759e101" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/63c6feca49bf4083f33bf250401c0c286759e101", + "reference": "63c6feca49bf4083f33bf250401c0c286759e101", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^5.3.3|^6.2.1|^7.0", + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4.1", + "mtdowling/jmespath.php": "^2.5", + "php": ">=5.5" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "paragonie/random_compat": ">= 2", + "phpunit/phpunit": "^4.8.35|^5.4.3", + "psr/cache": "^1.0", + "psr/simple-cache": "^1.0", + "sebastian/comparator": "^1.2.3" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Aws\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "support": { + "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", + "issues": "https://github.com/aws/aws-sdk-php/issues", + "source": "https://github.com/aws/aws-sdk-php/tree/3.173.19" + }, + "time": "2021-03-01T19:15:59+00:00" + }, + { + "name": "beberlei/assert", + "version": "v3.3.0", + "source": { + "type": "git", + "url": "https://github.com/beberlei/assert.git", + "reference": "5367e3895976b49704ae671f75bc5f0ba1b986ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/beberlei/assert/zipball/5367e3895976b49704ae671f75bc5f0ba1b986ab", + "reference": "5367e3895976b49704ae671f75bc5f0ba1b986ab", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-intl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "php": "^7.0 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "*", + "phpstan/phpstan": "*", + "phpunit/phpunit": ">=6.0.0", + "yoast/phpunit-polyfills": "^0.1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Assert\\": "lib/Assert" + }, + "files": [ + "lib/Assert/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de", + "role": "Lead Developer" + }, + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com", + "role": "Collaborator" + } + ], + "description": "Thin assertion library for input validation in business models.", + "keywords": [ + "assert", + "assertion", + "validation" + ], + "support": { + "issues": "https://github.com/beberlei/assert/issues", + "source": "https://github.com/beberlei/assert/tree/v3.3.0" + }, + "time": "2020-11-13T20:02:54+00:00" + }, { "name": "brick/math", "version": "0.9.2", @@ -102,6 +316,10 @@ "brick", "math" ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.9.2" + }, "funding": [ { "url": "https://tidelift.com/funding/github/packagist/brick/math", @@ -141,6 +359,10 @@ "MIT" ], "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, "time": "2019-12-04T15:06:13+00:00" }, { @@ -218,6 +440,10 @@ "uppercase", "words" ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.x" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -294,6 +520,10 @@ "parser", "php" ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/1.2.1" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -359,6 +589,10 @@ "cron", "schedule" ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.1.0" + }, "funding": [ { "url": "https://github.com/dragonmantank", @@ -423,6 +657,10 @@ "validation", "validator" ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/2.1.25" + }, "funding": [ { "url": "https://github.com/egulias", @@ -483,6 +721,10 @@ "proxy", "trusted proxy" ], + "support": { + "issues": "https://github.com/fideloper/TrustedProxy/issues", + "source": "https://github.com/fideloper/TrustedProxy/tree/4.4.1" + }, "time": "2020-10-22T13:48:01+00:00" }, { @@ -550,6 +792,10 @@ "crossdomain", "laravel" ], + "support": { + "issues": "https://github.com/fruitcake/laravel-cors/issues", + "source": "https://github.com/fruitcake/laravel-cors/tree/v2.0.3" + }, "funding": [ { "url": "https://github.com/barryvdh", @@ -608,6 +854,10 @@ "Result-Type", "result" ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.0.1" + }, "funding": [ { "url": "https://github.com/GrahamCampbell", @@ -698,6 +948,10 @@ "rest", "web service" ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.2.0" + }, "funding": [ { "url": "https://github.com/GrahamCampbell", @@ -767,6 +1021,10 @@ "keywords": [ "promise" ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.4.0" + }, "time": "2020-09-30T07:37:28+00:00" }, { @@ -838,143 +1096,356 @@ "uri", "url" ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/1.7.0" + }, "time": "2020-09-30T07:37:11+00:00" }, { - "name": "laravel/framework", - "version": "v8.29.0", + "name": "intervention/image", + "version": "2.5.1", "source": { "type": "git", - "url": "https://github.com/laravel/framework.git", - "reference": "d2eba352b3b3a3c515b18c5726b373fe5026733e" + "url": "https://github.com/Intervention/image.git", + "reference": "abbf18d5ab8367f96b3205ca3c89fb2fa598c69e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/d2eba352b3b3a3c515b18c5726b373fe5026733e", - "reference": "d2eba352b3b3a3c515b18c5726b373fe5026733e", + "url": "https://api.github.com/repos/Intervention/image/zipball/abbf18d5ab8367f96b3205ca3c89fb2fa598c69e", + "reference": "abbf18d5ab8367f96b3205ca3c89fb2fa598c69e", "shasum": "" }, "require": { - "doctrine/inflector": "^1.4|^2.0", - "dragonmantank/cron-expression": "^3.0.2", - "egulias/email-validator": "^2.1.10", - "ext-json": "*", - "ext-mbstring": "*", - "ext-openssl": "*", - "league/commonmark": "^1.3", - "league/flysystem": "^1.1", - "monolog/monolog": "^2.0", - "nesbot/carbon": "^2.31", - "opis/closure": "^3.6", - "php": "^7.3|^8.0", - "psr/container": "^1.0", - "psr/simple-cache": "^1.0", - "ramsey/uuid": "^4.0", - "swiftmailer/swiftmailer": "^6.0", - "symfony/console": "^5.1.4", - "symfony/error-handler": "^5.1.4", - "symfony/finder": "^5.1.4", - "symfony/http-foundation": "^5.1.4", - "symfony/http-kernel": "^5.1.4", - "symfony/mime": "^5.1.4", - "symfony/process": "^5.1.4", - "symfony/routing": "^5.1.4", - "symfony/var-dumper": "^5.1.4", - "tijsverkoyen/css-to-inline-styles": "^2.2.2", - "vlucas/phpdotenv": "^5.2", - "voku/portable-ascii": "^1.4.8" - }, - "conflict": { - "tightenco/collect": "<5.5.33" - }, - "provide": { - "psr/container-implementation": "1.0" - }, - "replace": { - "illuminate/auth": "self.version", - "illuminate/broadcasting": "self.version", - "illuminate/bus": "self.version", - "illuminate/cache": "self.version", - "illuminate/collections": "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/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" + "ext-fileinfo": "*", + "guzzlehttp/psr7": "~1.1", + "php": ">=5.4.0" }, "require-dev": { - "aws/aws-sdk-php": "^3.155", - "doctrine/dbal": "^2.6|^3.0", - "filp/whoops": "^2.8", - "guzzlehttp/guzzle": "^6.5.5|^7.0.1", - "league/flysystem-cached-adapter": "^1.0", - "mockery/mockery": "^1.4.2", - "orchestra/testbench-core": "^6.8", - "pda/pheanstalk": "^4.0", - "phpunit/phpunit": "^8.5.8|^9.3.3", - "predis/predis": "^1.1.1", - "symfony/cache": "^5.1.4" + "mockery/mockery": "~0.9.2", + "phpunit/phpunit": "^4.8 || ^5.7" }, "suggest": { - "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.155).", - "brianium/paratest": "Required to run tests in parallel (^6.0).", - "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6|^3.0).", - "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.", - "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.8).", - "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.5.5|^7.0.1).", - "laravel/tinker": "Required to use the tinker console command (^2.0).", - "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", - "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", - "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", - "mockery/mockery": "Required to use mocking (^1.4.2).", - "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 (^8.5.8|^9.3.3).", - "predis/predis": "Required to use the predis connector (^1.1.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 (^4.0|^5.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^5.1.4).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^5.1.4).", - "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0).", - "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)." + "ext-gd": "to use GD library based image processing.", + "ext-imagick": "to use Imagick based image processing.", + "intervention/imagecache": "Caching extension for the Intervention Image library" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "2.4-dev" + }, + "laravel": { + "providers": [ + "Intervention\\Image\\ImageServiceProvider" + ], + "aliases": { + "Image": "Intervention\\Image\\Facades\\Image" + } } }, "autoload": { - "files": [ - "src/Illuminate/Collections/helpers.php", - "src/Illuminate/Events/functions.php", + "psr-4": { + "Intervention\\Image\\": "src/Intervention/Image" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Vogel", + "email": "oliver@olivervogel.com", + "homepage": "http://olivervogel.com/" + } + ], + "description": "Image handling and manipulation library with support for Laravel integration", + "homepage": "http://image.intervention.io/", + "keywords": [ + "gd", + "image", + "imagick", + "laravel", + "thumbnail", + "watermark" + ], + "support": { + "issues": "https://github.com/Intervention/image/issues", + "source": "https://github.com/Intervention/image/tree/master" + }, + "time": "2019-11-02T09:15:47+00:00" + }, + { + "name": "jaybizzle/crawler-detect", + "version": "v1.2.104", + "source": { + "type": "git", + "url": "https://github.com/JayBizzle/Crawler-Detect.git", + "reference": "a581e89a9212c4e9d18049666dc735718c29de9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/a581e89a9212c4e9d18049666dc735718c29de9c", + "reference": "a581e89a9212c4e9d18049666dc735718c29de9c", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8|^5.5|^6.5|^9.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Jaybizzle\\CrawlerDetect\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Beech", + "email": "m@rkbee.ch", + "role": "Developer" + } + ], + "description": "CrawlerDetect is a PHP class for detecting bots/crawlers/spiders via the user agent", + "homepage": "https://github.com/JayBizzle/Crawler-Detect/", + "keywords": [ + "crawler", + "crawler detect", + "crawler detector", + "crawlerdetect", + "php crawler detect" + ], + "support": { + "issues": "https://github.com/JayBizzle/Crawler-Detect/issues", + "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.2.104" + }, + "time": "2021-01-13T15:25:20+00:00" + }, + { + "name": "jenssegers/agent", + "version": "v2.6.4", + "source": { + "type": "git", + "url": "https://github.com/jenssegers/agent.git", + "reference": "daa11c43729510b3700bc34d414664966b03bffe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jenssegers/agent/zipball/daa11c43729510b3700bc34d414664966b03bffe", + "reference": "daa11c43729510b3700bc34d414664966b03bffe", + "shasum": "" + }, + "require": { + "jaybizzle/crawler-detect": "^1.2", + "mobiledetect/mobiledetectlib": "^2.7.6", + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5.0|^6.0|^7.0" + }, + "suggest": { + "illuminate/support": "Required for laravel service providers" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + }, + "laravel": { + "providers": [ + "Jenssegers\\Agent\\AgentServiceProvider" + ], + "aliases": { + "Agent": "Jenssegers\\Agent\\Facades\\Agent" + } + } + }, + "autoload": { + "psr-4": { + "Jenssegers\\Agent\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jens Segers", + "homepage": "https://jenssegers.com" + } + ], + "description": "Desktop/mobile user agent parser with support for Laravel, based on Mobiledetect", + "homepage": "https://github.com/jenssegers/agent", + "keywords": [ + "Agent", + "browser", + "desktop", + "laravel", + "mobile", + "platform", + "user agent", + "useragent" + ], + "support": { + "issues": "https://github.com/jenssegers/agent/issues", + "source": "https://github.com/jenssegers/agent/tree/v2.6.4" + }, + "funding": [ + { + "url": "https://github.com/jenssegers", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/jenssegers/agent", + "type": "tidelift" + } + ], + "time": "2020-06-13T08:05:20+00:00" + }, + { + "name": "laravel/framework", + "version": "v8.29.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "d2eba352b3b3a3c515b18c5726b373fe5026733e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/d2eba352b3b3a3c515b18c5726b373fe5026733e", + "reference": "d2eba352b3b3a3c515b18c5726b373fe5026733e", + "shasum": "" + }, + "require": { + "doctrine/inflector": "^1.4|^2.0", + "dragonmantank/cron-expression": "^3.0.2", + "egulias/email-validator": "^2.1.10", + "ext-json": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "league/commonmark": "^1.3", + "league/flysystem": "^1.1", + "monolog/monolog": "^2.0", + "nesbot/carbon": "^2.31", + "opis/closure": "^3.6", + "php": "^7.3|^8.0", + "psr/container": "^1.0", + "psr/simple-cache": "^1.0", + "ramsey/uuid": "^4.0", + "swiftmailer/swiftmailer": "^6.0", + "symfony/console": "^5.1.4", + "symfony/error-handler": "^5.1.4", + "symfony/finder": "^5.1.4", + "symfony/http-foundation": "^5.1.4", + "symfony/http-kernel": "^5.1.4", + "symfony/mime": "^5.1.4", + "symfony/process": "^5.1.4", + "symfony/routing": "^5.1.4", + "symfony/var-dumper": "^5.1.4", + "tijsverkoyen/css-to-inline-styles": "^2.2.2", + "vlucas/phpdotenv": "^5.2", + "voku/portable-ascii": "^1.4.8" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "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/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": { + "aws/aws-sdk-php": "^3.155", + "doctrine/dbal": "^2.6|^3.0", + "filp/whoops": "^2.8", + "guzzlehttp/guzzle": "^6.5.5|^7.0.1", + "league/flysystem-cached-adapter": "^1.0", + "mockery/mockery": "^1.4.2", + "orchestra/testbench-core": "^6.8", + "pda/pheanstalk": "^4.0", + "phpunit/phpunit": "^8.5.8|^9.3.3", + "predis/predis": "^1.1.1", + "symfony/cache": "^5.1.4" + }, + "suggest": { + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.155).", + "brianium/paratest": "Required to run tests in parallel (^6.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6|^3.0).", + "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.", + "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.8).", + "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.5.5|^7.0.1).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", + "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", + "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", + "mockery/mockery": "Required to use mocking (^1.4.2).", + "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 (^8.5.8|^9.3.3).", + "predis/predis": "Required to use the predis connector (^1.1.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 (^4.0|^5.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^5.1.4).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^5.1.4).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0).", + "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + } + }, + "autoload": { + "files": [ + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", "src/Illuminate/Foundation/helpers.php", "src/Illuminate/Support/helpers.php" ], @@ -992,228 +1463,1839 @@ ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2021-02-23T14:27:41+00:00" + }, + { + "name": "laravel/helpers", + "version": "v1.4.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/helpers.git", + "reference": "febb10d8daaf86123825de2cb87f789a3371f0ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/helpers/zipball/febb10d8daaf86123825de2cb87f789a3371f0ac", + "reference": "febb10d8daaf86123825de2cb87f789a3371f0ac", + "shasum": "" + }, + "require": { + "illuminate/support": "~5.8.0|^6.0|^7.0|^8.0", + "php": "^7.1.3|^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Dries Vints", + "email": "dries.vints@gmail.com" + } + ], + "description": "Provides backwards compatibility for helpers in the latest Laravel release.", + "keywords": [ + "helpers", + "laravel" + ], + "support": { + "source": "https://github.com/laravel/helpers/tree/v1.4.1" + }, + "time": "2021-02-16T15:27:11+00:00" + }, + { + "name": "laravel/legacy-factories", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/legacy-factories.git", + "reference": "5e3fe2fd5fda64e20ea5c74c831a7346294e902a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/legacy-factories/zipball/5e3fe2fd5fda64e20ea5c74c831a7346294e902a", + "reference": "5e3fe2fd5fda64e20ea5c74c831a7346294e902a", + "shasum": "" + }, + "require": { + "illuminate/macroable": "^8.0", + "php": "^7.3|^8.0", + "symfony/finder": "^3.4|^4.0|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "laravel": { + "providers": [ + "Illuminate\\Database\\Eloquent\\LegacyFactoryServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "helpers.php" + ], + "psr-4": { + "Illuminate\\Database\\Eloquent\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The legacy version of the Laravel Eloquent factories.", + "homepage": "http://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2020-10-27T14:25:32+00:00" + }, + { + "name": "laravel/lumen-framework", + "version": "v8.2.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/lumen-framework.git", + "reference": "6ed02d4d1a6e203b9e896bd105b2e838866f2951" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/lumen-framework/zipball/6ed02d4d1a6e203b9e896bd105b2e838866f2951", + "reference": "6ed02d4d1a6e203b9e896bd105b2e838866f2951", + "shasum": "" + }, + "require": { + "dragonmantank/cron-expression": "^3.0.2", + "illuminate/auth": "^8.0", + "illuminate/broadcasting": "^8.0", + "illuminate/bus": "^8.0", + "illuminate/cache": "^8.0", + "illuminate/collections": "^8.0", + "illuminate/config": "^8.0", + "illuminate/console": "^8.0", + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/database": "^8.0", + "illuminate/encryption": "^8.0", + "illuminate/events": "^8.0", + "illuminate/filesystem": "^8.0", + "illuminate/hashing": "^8.0", + "illuminate/http": "^8.0", + "illuminate/log": "^8.0", + "illuminate/macroable": "^8.0", + "illuminate/pagination": "^8.0", + "illuminate/pipeline": "^8.0", + "illuminate/queue": "^8.0", + "illuminate/support": "^8.0", + "illuminate/testing": "^8.0", + "illuminate/translation": "^8.0", + "illuminate/validation": "^8.0", + "illuminate/view": "^8.0", + "nikic/fast-route": "^1.3", + "php": "^7.3|^8.0", + "symfony/console": "^5.1", + "symfony/error-handler": "^5.1", + "symfony/http-foundation": "^5.1", + "symfony/http-kernel": "^5.1", + "symfony/mime": "^5.1", + "symfony/var-dumper": "^5.1", + "vlucas/phpdotenv": "^5.2" + }, + "require-dev": { + "mockery/mockery": "^1.4.2", + "phpunit/phpunit": "^8.5.8|^9.3.3" + }, + "suggest": { + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Lumen\\": "src/" + }, + "files": [ + "src/helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylorotwell@gmail.com" + } + ], + "description": "The Laravel Lumen Framework.", + "homepage": "https://lumen.laravel.com", + "keywords": [ + "framework", + "laravel", + "lumen" + ], + "support": { + "issues": "https://github.com/laravel/lumen-framework/issues", + "source": "https://github.com/laravel/lumen-framework" + }, + "time": "2021-02-09T16:42:36+00:00" + }, + { + "name": "laravel/socialite", + "version": "v5.2.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/socialite.git", + "reference": "8aa705d771f127317f60887515cfb2f777653ce5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/socialite/zipball/8aa705d771f127317f60887515cfb2f777653ce5", + "reference": "8aa705d771f127317f60887515cfb2f777653ce5", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "illuminate/http": "^6.0|^7.0|^8.0", + "illuminate/support": "^6.0|^7.0|^8.0", + "league/oauth1-client": "^1.0", + "php": "^7.2|^8.0" + }, + "require-dev": { + "illuminate/contracts": "^6.0|^7.0", + "mockery/mockery": "^1.0", + "orchestra/testbench": "^4.0|^5.0|^6.0", + "phpunit/phpunit": "^8.0|^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Socialite\\SocialiteServiceProvider" + ], + "aliases": { + "Socialite": "Laravel\\Socialite\\Facades\\Socialite" + } + } + }, + "autoload": { + "psr-4": { + "Laravel\\Socialite\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.", + "homepage": "https://laravel.com", + "keywords": [ + "laravel", + "oauth" + ], + "support": { + "issues": "https://github.com/laravel/socialite/issues", + "source": "https://github.com/laravel/socialite" + }, + "time": "2021-02-22T14:22:51+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.6.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "daae1c43f1300fe88c05d83db6f3d8f76677ad88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/daae1c43f1300fe88c05d83db6f3d8f76677ad88", + "reference": "daae1c43f1300fe88c05d83db6f3d8f76677ad88", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0", + "illuminate/contracts": "^6.0|^7.0|^8.0", + "illuminate/support": "^6.0|^7.0|^8.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.10.4", + "symfony/var-dumper": "^4.3.4|^5.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)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "support": { + "issues": "https://github.com/laravel/tinker/issues", + "source": "https://github.com/laravel/tinker/tree/v2.6.0" + }, + "time": "2021-01-26T20:35:18+00:00" + }, + { + "name": "league/commonmark", + "version": "1.5.7", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/11df9b36fd4f1d2b727a73bf14931d81373b9a54", + "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0" + }, + "conflict": { + "scrutinizer/ocular": "1.7.*" + }, + "require-dev": { + "cebe/markdown": "~1.0", + "commonmark/commonmark.js": "0.29.2", + "erusev/parsedown": "~1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "~1.4", + "mikehaertl/php-shellcommand": "^1.4", + "phpstan/phpstan": "^0.12", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.2", + "scrutinizer/ocular": "^1.5", + "symfony/finder": "^4.2" + }, + "bin": [ + "bin/commonmark" + ], + "type": "library", + "autoload": { + "psr-4": { + "League\\CommonMark\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "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" + ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, + "funding": [ + { + "url": "https://enjoy.gitstore.app/repositories/thephpleague/commonmark", + "type": "custom" + }, + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://www.patreon.com/colinodell", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2020-10-31T13:49:32+00:00" + }, + { + "name": "league/flysystem", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "9be3b16c877d477357c015cec057548cf9b2a14a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/9be3b16c877d477357c015cec057548cf9b2a14a", + "reference": "9be3b16c877d477357c015cec057548cf9b2a14a", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/mime-type-detection": "^1.3", + "php": "^7.2.5 || ^8.0" + }, + "conflict": { + "league/flysystem-sftp": "<1.0.6" + }, + "require-dev": { + "phpspec/prophecy": "^1.11.1", + "phpunit/phpunit": "^8.5.8" + }, + "suggest": { + "ext-fileinfo": "Required for MimeType", + "ext-ftp": "Allows you to use FTP server storage", + "ext-openssl": "Allows you to use FTPS server storage", + "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", + "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", + "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", + "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", + "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", + "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", + "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", + "league/flysystem-webdav": "Allows you to use WebDAV storage", + "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter", + "spatie/flysystem-dropbox": "Allows you to use Dropbox storage", + "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Filesystem abstraction: Many filesystems, one API.", + "keywords": [ + "Cloud Files", + "WebDAV", + "abstraction", + "aws", + "cloud", + "copy.com", + "dropbox", + "file systems", + "files", + "filesystem", + "filesystems", + "ftp", + "rackspace", + "remote", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/1.x" + }, + "funding": [ + { + "url": "https://offset.earth/frankdejonge", + "type": "other" + } + ], + "time": "2020-08-23T07:39:11+00:00" + }, + { + "name": "league/flysystem-aws-s3-v3", + "version": "1.0.29", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", + "reference": "4e25cc0582a36a786c31115e419c6e40498f6972" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/4e25cc0582a36a786c31115e419c6e40498f6972", + "reference": "4e25cc0582a36a786c31115e419c6e40498f6972", + "shasum": "" + }, + "require": { + "aws/aws-sdk-php": "^3.20.0", + "league/flysystem": "^1.0.40", + "php": ">=5.5.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "~1.0.1", + "phpspec/phpspec": "^2.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\AwsS3v3\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Flysystem adapter for the AWS S3 SDK v3.x", + "support": { + "issues": "https://github.com/thephpleague/flysystem-aws-s3-v3/issues", + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/1.0.29" + }, + "time": "2020-10-08T18:58:37+00:00" + }, + { + "name": "league/flysystem-cached-adapter", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-cached-adapter.git", + "reference": "d1925efb2207ac4be3ad0c40b8277175f99ffaff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-cached-adapter/zipball/d1925efb2207ac4be3ad0c40b8277175f99ffaff", + "reference": "d1925efb2207ac4be3ad0c40b8277175f99ffaff", + "shasum": "" + }, + "require": { + "league/flysystem": "~1.0", + "psr/cache": "^1.0.0" + }, + "require-dev": { + "mockery/mockery": "~0.9", + "phpspec/phpspec": "^3.4", + "phpunit/phpunit": "^5.7", + "predis/predis": "~1.0", + "tedivm/stash": "~0.12" + }, + "suggest": { + "ext-phpredis": "Pure C implemented extension for PHP" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Cached\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "frankdejonge", + "email": "info@frenky.net" + } + ], + "description": "An adapter decorator to enable meta-data caching.", + "support": { + "issues": "https://github.com/thephpleague/flysystem-cached-adapter/issues", + "source": "https://github.com/thephpleague/flysystem-cached-adapter/tree/master" + }, + "time": "2020-07-25T15:56:04+00:00" + }, + { + "name": "league/glide", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/glide.git", + "reference": "ae5e26700573cb678919d28e425a8b87bc71c546" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/glide/zipball/ae5e26700573cb678919d28e425a8b87bc71c546", + "reference": "ae5e26700573cb678919d28e425a8b87bc71c546", + "shasum": "" + }, + "require": { + "intervention/image": "^2.4", + "league/flysystem": "^1.0", + "php": "^7.2|^8.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^1.3.3", + "phpunit/php-token-stream": "^3.1|^4.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Glide\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Reinink", + "email": "jonathan@reinink.ca", + "homepage": "http://reinink.ca" + } + ], + "description": "Wonderfully easy on-demand image manipulation library with an HTTP based API.", + "homepage": "http://glide.thephpleague.com", + "keywords": [ + "ImageMagick", + "editing", + "gd", + "image", + "imagick", + "league", + "manipulation", + "processing" + ], + "support": { + "issues": "https://github.com/thephpleague/glide/issues", + "source": "https://github.com/thephpleague/glide/tree/1.7.0" + }, + "time": "2020-11-05T17:34:03+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3", + "reference": "3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.18", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.7.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2021-01-18T20:58:21+00:00" + }, + { + "name": "league/oauth1-client", + "version": "v1.9.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth1-client.git", + "reference": "1e7e6be2dc543bf466236fb171e5b20e1b06aee6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/1e7e6be2dc543bf466236fb171e5b20e1b06aee6", + "reference": "1e7e6be2dc543bf466236fb171e5b20e1b06aee6", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-openssl": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "php": ">=7.1||>=8.0" + }, + "require-dev": { + "ext-simplexml": "*", + "friendsofphp/php-cs-fixer": "^2.17", + "mockery/mockery": "^1.3.3", + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5||9.5" + }, + "suggest": { + "ext-simplexml": "For decoding XML-based responses." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev", + "dev-develop": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth1\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Corlett", + "email": "bencorlett@me.com", + "homepage": "http://www.webcomm.com.au", + "role": "Developer" + } + ], + "description": "OAuth 1.0 Client Library", + "keywords": [ + "Authentication", + "SSO", + "authorization", + "bitbucket", + "identity", + "idp", + "oauth", + "oauth1", + "single sign on", + "trello", + "tumblr", + "twitter" + ], + "support": { + "issues": "https://github.com/thephpleague/oauth1-client/issues", + "source": "https://github.com/thephpleague/oauth1-client/tree/v1.9.0" + }, + "time": "2021-01-20T01:40:53+00:00" + }, + { + "name": "maennchen/zipstream-php", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/maennchen/ZipStream-PHP.git", + "reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/c4c5803cc1f93df3d2448478ef79394a5981cc58", + "reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58", + "shasum": "" + }, + "require": { + "myclabs/php-enum": "^1.5", + "php": ">= 7.1", + "psr/http-message": "^1.0", + "symfony/polyfill-mbstring": "^1.0" + }, + "require-dev": { + "ext-zip": "*", + "guzzlehttp/guzzle": ">= 6.3", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": ">= 7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZipStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paul Duncan", + "email": "pabs@pablotron.org" + }, + { + "name": "Jonatan Männchen", + "email": "jonatan@maennchen.ch" + }, + { + "name": "Jesse Donat", + "email": "donatj@gmail.com" + }, + { + "name": "András Kolesár", + "email": "kolesar@kolesar.hu" + } + ], + "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", + "keywords": [ + "stream", + "zip" + ], + "support": { + "issues": "https://github.com/maennchen/ZipStream-PHP/issues", + "source": "https://github.com/maennchen/ZipStream-PHP/tree/master" + }, + "funding": [ + { + "url": "https://opencollective.com/zipstream", + "type": "open_collective" + } + ], + "time": "2020-05-30T13:11:16+00:00" + }, + { + "name": "mobiledetect/mobiledetectlib", + "version": "2.8.37", + "source": { + "type": "git", + "url": "https://github.com/serbanghita/Mobile-Detect.git", + "reference": "9841e3c46f5bd0739b53aed8ac677fa712943df7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/9841e3c46f5bd0739b53aed8ac677fa712943df7", + "reference": "9841e3c46f5bd0739b53aed8ac677fa712943df7", + "shasum": "" + }, + "require": { + "php": ">=5.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.35||~5.7" + }, + "type": "library", + "autoload": { + "classmap": [ + "Mobile_Detect.php" + ], + "psr-0": { + "Detection": "namespaced/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Serban Ghita", + "email": "serbanghita@gmail.com", + "homepage": "http://mobiledetect.net", + "role": "Developer" + } + ], + "description": "Mobile_Detect is a lightweight PHP class for detecting mobile devices. It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.", + "homepage": "https://github.com/serbanghita/Mobile-Detect", + "keywords": [ + "detect mobile devices", + "mobile", + "mobile detect", + "mobile detector", + "php mobile detect" + ], + "support": { + "issues": "https://github.com/serbanghita/Mobile-Detect/issues", + "source": "https://github.com/serbanghita/Mobile-Detect/tree/2.8.37" + }, + "funding": [ + { + "url": "https://github.com/serbanghita", + "type": "github" + } + ], + "time": "2021-02-19T21:22:57+00:00" + }, + { + "name": "monolog/monolog", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1cb1cde8e8dd0f70cc0fe51354a59acad9302084", + "reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "psr/log": "^1.0.1" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7", + "graylog2/gelf-php": "^1.4.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4", + "php-console/php-console": "^3.1.3", + "phpspec/prophecy": "^1.6.1", + "phpstan/phpstan": "^0.12.59", + "phpunit/phpunit": "^8.5", + "predis/predis": "^1.1", + "rollbar/rollbar": "^1.3", + "ruflin/elastica": ">=0.90 <7.0.1", + "swiftmailer/swiftmailer": "^5.3|^6.0" + }, + "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-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via 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", + "php-console/php-console": "Allow sending log messages to Google Chrome", + "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": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "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" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/2.2.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2020-12-14T13:15:25+00:00" + }, + { + "name": "morilog/jalali", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/morilog/jalali.git", + "reference": "7ea78b84ce3b5546b01217febb2fba4915dac5e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/morilog/jalali/zipball/7ea78b84ce3b5546b01217febb2fba4915dac5e5", + "reference": "7ea78b84ce3b5546b01217febb2fba4915dac5e5", + "shasum": "" + }, + "require": { + "beberlei/assert": "3.*", + "nesbot/carbon": "^1.21 || ^2.0", + "php": "^7.0 | ^7.1 | ^7.2 | ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Morilog\\Jalali\\": "src" + }, + "files": [ + "src/helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Milad Rey", + "email": "miladr@gmail.com" + }, + { + "name": "Morteza Parvini", + "email": "m.parvini@outlook.com" + } + ], + "description": "This Package helps developers to easily work with Jalali (Shamsi or Iranian) dates in PHP applications, based on Jalali (Shamsi) DateTime class.", + "keywords": [ + "Jalali", + "date", + "datetime", + "laravel", + "morilog" + ], + "support": { + "issues": "https://github.com/morilog/jalali/issues", + "source": "https://github.com/morilog/jalali/tree/v3.2.0" + }, + "time": "2020-12-01T21:26:31+00:00" + }, + { + "name": "mtdowling/jmespath.php", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "42dae2cbd13154083ca6d70099692fef8ca84bfb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/42dae2cbd13154083ca6d70099692fef8ca84bfb", + "reference": "42dae2cbd13154083ca6d70099692fef8ca84bfb", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.17" + }, + "require-dev": { + "composer/xdebug-handler": "^1.4", + "phpunit/phpunit": "^4.8.36 || ^7.5.15" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-4": { + "JmesPath\\": "src/" + }, + "files": [ + "src/JmesPath.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "support": { + "issues": "https://github.com/jmespath/jmespath.php/issues", + "source": "https://github.com/jmespath/jmespath.php/tree/2.6.0" + }, + "time": "2020-07-31T21:01:56+00:00" + }, + { + "name": "myclabs/php-enum", + "version": "1.8.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/php-enum.git", + "reference": "46cf3d8498b095bd33727b13fd5707263af99421" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/46cf3d8498b095bd33727b13fd5707263af99421", + "reference": "46cf3d8498b095bd33727b13fd5707263af99421", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^4.5.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "description": "PHP Enum implementation", + "homepage": "http://github.com/myclabs/php-enum", + "keywords": [ + "enum" + ], + "support": { + "issues": "https://github.com/myclabs/php-enum/issues", + "source": "https://github.com/myclabs/php-enum/tree/1.8.0" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum", + "type": "tidelift" + } + ], + "time": "2021-02-15T16:11:48+00:00" + }, + { + "name": "nesbot/carbon", + "version": "2.45.1", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "528783b188bdb853eb21239b1722831e0f000a8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/528783b188bdb853eb21239b1722831e0f000a8d", + "reference": "528783b188bdb853eb21239b1722831e0f000a8d", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation": "^3.4 || ^4.0 || ^5.0" + }, + "require-dev": { + "doctrine/orm": "^2.7", + "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", + "kylekatarnls/multi-tester": "^2.0", + "phpmd/phpmd": "^2.9", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.54", + "phpunit/phpunit": "^7.5.20 || ^8.5.14", + "squizlabs/php_codesniffer": "^3.4" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev", + "dev-3.x": "3.x-dev" + }, + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "http://nesbot.com" + }, + { + "name": "kylekatarnls", + "homepage": "http://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "http://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" + }, + "funding": [ + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2021-02-11T18:30:17+00:00" + }, + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "support": { + "issues": "https://github.com/nikic/FastRoute/issues", + "source": "https://github.com/nikic/FastRoute/tree/master" + }, + "time": "2018-02-13T20:26:39+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.10.4", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e", + "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e", + "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" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.4" + }, + "time": "2020-12-20T10:01:03+00:00" + }, + { + "name": "opis/closure", + "version": "3.6.1", + "source": { + "type": "git", + "url": "https://github.com/opis/closure.git", + "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/closure/zipball/943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5", + "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0 || ^8.0" + }, + "require-dev": { + "jeremeamia/superclosure": "^2.0", + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\Closure\\": "src/" + }, + "files": [ + "functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + }, + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + } + ], + "description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.", + "homepage": "https://opis.io/closure", + "keywords": [ + "anonymous functions", + "closure", + "function", + "serializable", + "serialization", + "serialize" + ], + "support": { + "issues": "https://github.com/opis/closure/issues", + "source": "https://github.com/opis/closure/tree/3.6.1" + }, + "time": "2020-11-07T02:01:34+00:00" + }, + { + "name": "paragonie/constant_time_encoding", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c", + "reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c", + "shasum": "" + }, + "require": { + "php": "^7|^8" + }, + "require-dev": { + "phpunit/phpunit": "^6|^7|^8|^9", + "vimeo/psalm": "^1|^2|^3|^4" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "time": "2020-12-06T15:14:20+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.100", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" + }, + "require": { + "php": ">= 7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" } ], - "description": "The Laravel Framework.", - "homepage": "https://laravel.com", + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", "keywords": [ - "framework", - "laravel" + "csprng", + "polyfill", + "pseudorandom", + "random" ], - "time": "2021-02-23T14:27:41+00:00" + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T08:29:30+00:00" }, { - "name": "laravel/tinker", - "version": "v2.6.0", + "name": "php-amqplib/php-amqplib", + "version": "v2.12.3", "source": { "type": "git", - "url": "https://github.com/laravel/tinker.git", - "reference": "daae1c43f1300fe88c05d83db6f3d8f76677ad88" + "url": "https://github.com/php-amqplib/php-amqplib.git", + "reference": "f746eb44df6d8f838173729867dd1d20b0265faa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/daae1c43f1300fe88c05d83db6f3d8f76677ad88", - "reference": "daae1c43f1300fe88c05d83db6f3d8f76677ad88", + "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/f746eb44df6d8f838173729867dd1d20b0265faa", + "reference": "f746eb44df6d8f838173729867dd1d20b0265faa", "shasum": "" }, "require": { - "illuminate/console": "^6.0|^7.0|^8.0", - "illuminate/contracts": "^6.0|^7.0|^8.0", - "illuminate/support": "^6.0|^7.0|^8.0", - "php": "^7.2.5|^8.0", - "psy/psysh": "^0.10.4", - "symfony/var-dumper": "^4.3.4|^5.0" + "ext-mbstring": "*", + "ext-sockets": "*", + "php": ">=5.6.3,<8.0", + "phpseclib/phpseclib": "^2.0|^3.0" }, - "require-dev": { - "mockery/mockery": "~1.3.3|^1.4.2", - "phpunit/phpunit": "^8.5.8|^9.3.3" + "conflict": { + "php": "7.4.0 - 7.4.1" }, - "suggest": { - "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0)." + "replace": { + "videlalvaro/php-amqplib": "self.version" + }, + "require-dev": { + "ext-curl": "*", + "nategood/httpful": "^0.2.20", + "phpunit/phpunit": "^5.7|^6.5|^7.0", + "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" - }, - "laravel": { - "providers": [ - "Laravel\\Tinker\\TinkerServiceProvider" - ] + "dev-master": "2.12-dev" } }, "autoload": { "psr-4": { - "Laravel\\Tinker\\": "src/" + "PhpAmqpLib\\": "PhpAmqpLib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "LGPL-2.1-or-later" ], "authors": [ { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" + "name": "Alvaro Videla", + "role": "Original Maintainer" + }, + { + "name": "Raúl Araya", + "email": "nubeiro@gmail.com", + "role": "Maintainer" + }, + { + "name": "Luke Bakken", + "email": "luke@bakken.io", + "role": "Maintainer" + }, + { + "name": "Ramūnas Dronga", + "email": "github@ramuno.lt", + "role": "Maintainer" } ], - "description": "Powerful REPL for the Laravel framework.", + "description": "Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.", + "homepage": "https://github.com/php-amqplib/php-amqplib/", "keywords": [ - "REPL", - "Tinker", - "laravel", - "psysh" + "message", + "queue", + "rabbitmq" ], - "time": "2021-01-26T20:35:18+00:00" + "support": { + "issues": "https://github.com/php-amqplib/php-amqplib/issues", + "source": "https://github.com/php-amqplib/php-amqplib/tree/v2.12.3" + }, + "time": "2021-03-01T12:21:31+00:00" }, { - "name": "league/commonmark", - "version": "1.5.7", + "name": "phpoption/phpoption", + "version": "1.7.5", "source": { "type": "git", - "url": "https://github.com/thephpleague/commonmark.git", - "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54" + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "994ecccd8f3283ecf5ac33254543eb0ac946d525" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/11df9b36fd4f1d2b727a73bf14931d81373b9a54", - "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/994ecccd8f3283ecf5ac33254543eb0ac946d525", + "reference": "994ecccd8f3283ecf5ac33254543eb0ac946d525", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": "^7.1 || ^8.0" - }, - "conflict": { - "scrutinizer/ocular": "1.7.*" + "php": "^5.5.9 || ^7.0 || ^8.0" }, "require-dev": { - "cebe/markdown": "~1.0", - "commonmark/commonmark.js": "0.29.2", - "erusev/parsedown": "~1.0", - "ext-json": "*", - "github/gfm": "0.29.0", - "michelf/php-markdown": "~1.4", - "mikehaertl/php-shellcommand": "^1.4", - "phpstan/phpstan": "^0.12", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.2", - "scrutinizer/ocular": "^1.5", - "symfony/finder": "^4.2" + "bamarni/composer-bin-plugin": "^1.4.1", + "phpunit/phpunit": "^4.8.35 || ^5.7.27 || ^6.5.6 || ^7.0 || ^8.0 || ^9.0" }, - "bin": [ - "bin/commonmark" - ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7-dev" + } + }, "autoload": { "psr-4": { - "League\\CommonMark\\": "src" + "PhpOption\\": "src/PhpOption/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "Apache-2.0" ], "authors": [ { - "name": "Colin O'Dell", - "email": "colinodell@gmail.com", - "homepage": "https://www.colinodell.com", - "role": "Lead Developer" + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com" } ], - "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and Github-Flavored Markdown (GFM)", - "homepage": "https://commonmark.thephpleague.com", + "description": "Option Type for PHP", "keywords": [ - "commonmark", - "flavored", - "gfm", - "github", - "github-flavored", - "markdown", - "md", - "parser" + "language", + "option", + "php", + "type" ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.7.5" + }, "funding": [ { - "url": "https://enjoy.gitstore.app/repositories/thephpleague/commonmark", - "type": "custom" - }, - { - "url": "https://www.colinodell.com/sponsor", - "type": "custom" - }, - { - "url": "https://www.paypal.me/colinpodell/10.00", - "type": "custom" - }, - { - "url": "https://github.com/colinodell", + "url": "https://github.com/GrahamCampbell", "type": "github" }, { - "url": "https://www.patreon.com/colinodell", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", "type": "tidelift" } ], - "time": "2020-10-31T13:49:32+00:00" + "time": "2020-07-20T17:29:33+00:00" }, { - "name": "league/flysystem", - "version": "1.1.3", + "name": "phpseclib/phpseclib", + "version": "3.0.5", "source": { "type": "git", - "url": "https://github.com/thephpleague/flysystem.git", - "reference": "9be3b16c877d477357c015cec057548cf9b2a14a" + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "7c751ea006577e4c2e83326d90c8b1e8c11b8ede" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/9be3b16c877d477357c015cec057548cf9b2a14a", - "reference": "9be3b16c877d477357c015cec057548cf9b2a14a", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/7c751ea006577e4c2e83326d90c8b1e8c11b8ede", + "reference": "7c751ea006577e4c2e83326d90c8b1e8c11b8ede", "shasum": "" }, "require": { - "ext-fileinfo": "*", - "league/mime-type-detection": "^1.3", - "php": "^7.2.5 || ^8.0" - }, - "conflict": { - "league/flysystem-sftp": "<1.0.6" + "paragonie/constant_time_encoding": "^1|^2", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": ">=5.6.1" }, "require-dev": { - "phpspec/prophecy": "^1.11.1", - "phpunit/phpunit": "^8.5.8" + "phing/phing": "~2.7", + "phpunit/phpunit": "^5.7|^6.0|^9.4", + "squizlabs/php_codesniffer": "~2.0" }, "suggest": { - "ext-fileinfo": "Required for MimeType", - "ext-ftp": "Allows you to use FTP server storage", - "ext-openssl": "Allows you to use FTPS server storage", - "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", - "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", - "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", - "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", - "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", - "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", - "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", - "league/flysystem-webdav": "Allows you to use WebDAV storage", - "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter", - "spatie/flysystem-dropbox": "Allows you to use Dropbox storage", - "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications" + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], "psr-4": { - "League\\Flysystem\\": "src/" + "phpseclib3\\": "phpseclib/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1222,65 +3304,98 @@ ], "authors": [ { - "name": "Frank de Jonge", - "email": "info@frenky.net" + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" } ], - "description": "Filesystem abstraction: Many filesystems, one API.", + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", "keywords": [ - "Cloud Files", - "WebDAV", - "abstraction", - "aws", - "cloud", - "copy.com", - "dropbox", - "file systems", - "files", - "filesystem", - "filesystems", - "ftp", - "rackspace", - "remote", - "s3", + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", "sftp", - "storage" + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.5" + }, "funding": [ { - "url": "https://offset.earth/frankdejonge", - "type": "other" + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" } ], - "time": "2020-08-23T07:39:11+00:00" + "time": "2021-02-12T16:18:16+00:00" }, { - "name": "league/mime-type-detection", - "version": "1.7.0", + "name": "psr/cache", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/thephpleague/mime-type-detection.git", - "reference": "3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3" + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" }, "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3", - "reference": "3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3", + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", "shasum": "" }, "require": { - "ext-fileinfo": "*", - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.18", - "phpstan/phpstan": "^0.12.68", - "phpunit/phpunit": "^8.5.8 || ^9.3" + "php": ">=5.3.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "League\\MimeTypeDetection\\": "src" + "Psr\\Cache\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1289,83 +3404,47 @@ ], "authors": [ { - "name": "Frank de Jonge", - "email": "info@frankdejonge.nl" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Mime-type detection for Flysystem", - "funding": [ - { - "url": "https://github.com/frankdejonge", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/league/flysystem", - "type": "tidelift" - } + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" ], - "time": "2021-01-18T20:58:21+00:00" + "support": { + "source": "https://github.com/php-fig/cache/tree/master" + }, + "time": "2016-08-06T20:24:11+00:00" }, { - "name": "monolog/monolog", - "version": "2.2.0", + "name": "psr/container", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/Seldaek/monolog.git", - "reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084" + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1cb1cde8e8dd0f70cc0fe51354a59acad9302084", - "reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", "shasum": "" }, "require": { - "php": ">=7.2", - "psr/log": "^1.0.1" - }, - "provide": { - "psr/log-implementation": "1.0.0" - }, - "require-dev": { - "aws/aws-sdk-php": "^2.4.9 || ^3.0", - "doctrine/couchdb": "~1.0@dev", - "elasticsearch/elasticsearch": "^7", - "graylog2/gelf-php": "^1.4.2", - "mongodb/mongodb": "^1.8", - "php-amqplib/php-amqplib": "~2.4", - "php-console/php-console": "^3.1.3", - "phpspec/prophecy": "^1.6.1", - "phpstan/phpstan": "^0.12.59", - "phpunit/phpunit": "^8.5", - "predis/predis": "^1.1", - "rollbar/rollbar": "^1.3", - "ruflin/elastica": ">=0.90 <7.0.1", - "swiftmailer/swiftmailer": "^5.3|^6.0" - }, - "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-mbstring": "Allow to work properly with unicode symbols", - "ext-mongodb": "Allow sending log messages to a MongoDB server (via 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", - "php-console/php-console": "Allow sending log messages to Google Chrome", - "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Monolog\\": "src/Monolog" + "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1374,83 +3453,51 @@ ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "https://seld.be" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "https://github.com/Seldaek/monolog", + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", "keywords": [ - "log", - "logging", - "psr-3" - ], - "funding": [ - { - "url": "https://github.com/Seldaek", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", - "type": "tidelift" - } + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" ], - "time": "2020-12-14T13:15:25+00:00" + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/master" + }, + "time": "2017-02-14T16:28:37+00:00" }, { - "name": "nesbot/carbon", - "version": "2.45.1", + "name": "psr/event-dispatcher", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "528783b188bdb853eb21239b1722831e0f000a8d" + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/528783b188bdb853eb21239b1722831e0f000a8d", - "reference": "528783b188bdb853eb21239b1722831e0f000a8d", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", "shasum": "" }, "require": { - "ext-json": "*", - "php": "^7.1.8 || ^8.0", - "symfony/polyfill-mbstring": "^1.0", - "symfony/translation": "^3.4 || ^4.0 || ^5.0" - }, - "require-dev": { - "doctrine/orm": "^2.7", - "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", - "kylekatarnls/multi-tester": "^2.0", - "phpmd/phpmd": "^2.9", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.54", - "phpunit/phpunit": "^7.5.20 || ^8.5.14", - "squizlabs/php_codesniffer": "^3.4" + "php": ">=7.2.0" }, - "bin": [ - "bin/carbon" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev", - "dev-3.x": "3.x-dev" - }, - "laravel": { - "providers": [ - "Carbon\\Laravel\\ServiceProvider" - ] - }, - "phpstan": { - "includes": [ - "extension.neon" - ] + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Carbon\\": "src/Carbon/" + "Psr\\EventDispatcher\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1459,120 +3506,101 @@ ], "authors": [ { - "name": "Brian Nesbitt", - "email": "brian@nesbot.com", - "homepage": "http://nesbot.com" - }, - { - "name": "kylekatarnls", - "homepage": "http://github.com/kylekatarnls" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "An API extension for DateTime that supports 281 different languages.", - "homepage": "http://carbon.nesbot.com", + "description": "Standard interfaces for event handling.", "keywords": [ - "date", - "datetime", - "time" - ], - "funding": [ - { - "url": "https://opencollective.com/Carbon", - "type": "open_collective" - }, - { - "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", - "type": "tidelift" - } + "events", + "psr", + "psr-14" ], - "time": "2021-02-11T18:30:17+00:00" + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" }, { - "name": "nikic/php-parser", - "version": "v4.10.4", + "name": "psr/http-client", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e" + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", "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" + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" }, - "bin": [ - "bin/php-parse" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "PhpParser\\": "lib/PhpParser" + "Psr\\Http\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Nikita Popov" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "A PHP parser written in PHP", + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", "keywords": [ - "parser", - "php" + "http", + "http-client", + "psr", + "psr-18" ], - "time": "2020-12-20T10:01:03+00:00" + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" }, { - "name": "opis/closure", - "version": "3.6.1", + "name": "psr/http-message", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/opis/closure.git", - "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5" + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opis/closure/zipball/943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5", - "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5", - "shasum": "" - }, - "require": { - "php": "^5.4 || ^7.0 || ^8.0" - }, - "require-dev": { - "jeremeamia/superclosure": "^2.0", - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.6.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Opis\\Closure\\": "src/" - }, - "files": [ - "functions.php" - ] + "Psr\\Http\\Message\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1580,103 +3608,87 @@ ], "authors": [ { - "name": "Marius Sarca", - "email": "marius.sarca@gmail.com" - }, - { - "name": "Sorin Sarca", - "email": "sarca_sorin@hotmail.com" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.", - "homepage": "https://opis.io/closure", + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ - "anonymous functions", - "closure", - "function", - "serializable", - "serialization", - "serialize" + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" ], - "time": "2020-11-07T02:01:34+00:00" + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" }, { - "name": "phpoption/phpoption", - "version": "1.7.5", + "name": "psr/log", + "version": "1.1.3", "source": { "type": "git", - "url": "https://github.com/schmittjoh/php-option.git", - "reference": "994ecccd8f3283ecf5ac33254543eb0ac946d525" + "url": "https://github.com/php-fig/log.git", + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/994ecccd8f3283ecf5ac33254543eb0ac946d525", - "reference": "994ecccd8f3283ecf5ac33254543eb0ac946d525", + "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", "shasum": "" }, "require": { - "php": "^5.5.9 || ^7.0 || ^8.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.4.1", - "phpunit/phpunit": "^4.8.35 || ^5.7.27 || ^6.5.6 || ^7.0 || ^8.0 || ^9.0" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { "psr-4": { - "PhpOption\\": "src/PhpOption/" + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache-2.0" + "MIT" ], "authors": [ { - "name": "Johannes M. Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Graham Campbell", - "email": "graham@alt-three.com" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Option Type for PHP", + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ - "language", - "option", - "php", - "type" - ], - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", - "type": "tidelift" - } + "log", + "psr", + "psr-3" ], - "time": "2020-07-20T17:29:33+00:00" + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.3" + }, + "time": "2020-03-23T09:12:05+00:00" }, { - "name": "psr/container", - "version": "1.0.0", + "name": "psr/simple-cache", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", "shasum": "" }, "require": { @@ -1690,7 +3702,7 @@ }, "autoload": { "psr-4": { - "Psr\\Container\\": "src/" + "Psr\\SimpleCache\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1703,43 +3715,68 @@ "homepage": "http://www.php-fig.org/" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "Common interfaces for simple caching", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" ], - "time": "2017-02-14T16:28:37+00:00" + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/master" + }, + "time": "2017-10-23T01:57:42+00:00" }, { - "name": "psr/event-dispatcher", - "version": "1.0.0", + "name": "psy/psysh", + "version": "v0.10.6", "source": { "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + "url": "https://github.com/bobthecow/psysh.git", + "reference": "6f990c19f91729de8b31e639d6e204ea59f19cf3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/6f990c19f91729de8b31e639d6e204ea59f19cf3", + "reference": "6f990c19f91729de8b31e639d6e204ea59f19cf3", "shasum": "" }, "require": { - "php": ">=7.2.0" + "dnoegel/php-xdg-base-dir": "0.1.*", + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "~4.0|~3.0|~2.0|~1.3", + "php": "^8.0 || ^7.0 || ^5.5.9", + "symfony/console": "~5.0|~4.0|~3.0|^2.4.2|~2.3.10", + "symfony/var-dumper": "~5.0|~4.0|~3.0|~2.7" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "hoa/console": "3.17.*" + }, + "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.", + "hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit." }, + "bin": [ + "bin/psysh" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-main": "0.10.x-dev" } }, "autoload": { + "files": [ + "src/functions.php" + ], "psr-4": { - "Psr\\EventDispatcher\\": "src/" + "Psy\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1748,46 +3785,51 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" } ], - "description": "Standard interfaces for event handling.", + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", "keywords": [ - "events", - "psr", - "psr-14" + "REPL", + "console", + "interactive", + "shell" ], - "time": "2019-01-08T18:20:26+00:00" + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.10.6" + }, + "time": "2021-01-18T15:53:43+00:00" }, { - "name": "psr/http-client", - "version": "1.0.1", + "name": "ralouphie/getallheaders", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", "shasum": "" }, "require": { - "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0" + "php": ">=5.6" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" }, + "type": "library", "autoload": { - "psr-4": { - "Psr\\Http\\Client\\": "src/" - } + "files": [ + "src/getallheaders.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1795,46 +3837,56 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" } ], - "description": "Common interface for HTTP clients", - "homepage": "https://github.com/php-fig/http-client", - "keywords": [ - "http", - "http-client", - "psr", - "psr-18" - ], - "time": "2020-06-29T06:28:15+00:00" + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" }, { - "name": "psr/http-message", - "version": "1.0.1", + "name": "ramsey/collection", + "version": "1.1.3", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/ramsey/collection.git", + "reference": "28a5c4ab2f5111db6a60b2b4ec84057e0f43b9c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/ramsey/collection/zipball/28a5c4ab2f5111db6a60b2b4ec84057e0f43b9c1", + "reference": "28a5c4ab2f5111db6a60b2b4ec84057e0f43b9c1", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.2 || ^8" + }, + "require-dev": { + "captainhook/captainhook": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "ergebnis/composer-normalize": "^2.6", + "fakerphp/faker": "^1.5", + "hamcrest/hamcrest-php": "^2", + "jangregor/phpstan-prophecy": "^0.8", + "mockery/mockery": "^1.3", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^0.12.32", + "phpstan/phpstan-mockery": "^0.12.5", + "phpstan/phpstan-phpunit": "^0.12.11", + "phpunit/phpunit": "^8.5 || ^9", + "psy/psysh": "^0.10.4", + "slevomat/coding-standard": "^6.3", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.4" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" + "Ramsey\\Collection\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1843,95 +3895,159 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", + "description": "A PHP 7.2+ library for representing and manipulating collections.", "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" + "array", + "collection", + "hash", + "map", + "queue", + "set" ], - "time": "2016-08-06T14:39:51+00:00" + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/1.1.3" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2021-01-21T17:40:04+00:00" }, { - "name": "psr/log", - "version": "1.1.3", + "name": "ramsey/uuid", + "version": "4.1.1", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + "url": "https://github.com/ramsey/uuid.git", + "reference": "cd4032040a750077205918c86049aa0f43d22947" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/cd4032040a750077205918c86049aa0f43d22947", + "reference": "cd4032040a750077205918c86049aa0f43d22947", "shasum": "" }, "require": { - "php": ">=5.3.0" + "brick/math": "^0.8 || ^0.9", + "ext-json": "*", + "php": "^7.2 || ^8", + "ramsey/collection": "^1.0", + "symfony/polyfill-ctype": "^1.8" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "codeception/aspect-mock": "^3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7.0", + "doctrine/annotations": "^1.8", + "goaop/framework": "^2", + "mockery/mockery": "^1.3", + "moontoast/math": "^1.1", + "paragonie/random-lib": "^2", + "php-mock/php-mock-mockery": "^1.3", + "php-mock/php-mock-phpunit": "^2.5", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^0.17.1", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-mockery": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^8.5", + "psy/psysh": "^0.10.0", + "slevomat/coding-standard": "^6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "3.9.4" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-ctype": "Enables faster processing of character classification using ctype functions.", + "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": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "4.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } + "Ramsey\\Uuid\\": "src/" + }, + "files": [ + "src/functions.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "homepage": "https://github.com/ramsey/uuid", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "rss": "https://github.com/ramsey/uuid/releases.atom", + "source": "https://github.com/ramsey/uuid" + }, + "funding": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "url": "https://github.com/ramsey", + "type": "github" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2020-03-23T09:12:05+00:00" + "time": "2020-08-18T17:17:46+00:00" }, { - "name": "psr/simple-cache", - "version": "1.0.1", + "name": "spatie/image", + "version": "1.10.2", "source": { "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + "url": "https://github.com/spatie/image.git", + "reference": "12662673fbe649bffcd3a24188a404dc31fa118c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "url": "https://api.github.com/repos/spatie/image/zipball/12662673fbe649bffcd3a24188a404dc31fa118c", + "reference": "12662673fbe649bffcd3a24188a404dc31fa118c", "shasum": "" }, "require": { - "php": ">=5.3.0" + "ext-exif": "*", + "ext-mbstring": "*", + "league/glide": "^1.6", + "php": "^7.2|^8.0", + "spatie/image-optimizer": "^1.1", + "spatie/temporary-directory": "^1.0", + "symfony/process": "^3.0|^4.0|^5.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "require-dev": { + "phpunit/phpunit": "^8.0|^9.0", + "symfony/var-dumper": "^4.0|^5.0" }, + "type": "library", "autoload": { "psr-4": { - "Psr\\SimpleCache\\": "src/" + "Spatie\\Image\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1940,69 +4056,62 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" } ], - "description": "Common interfaces for simple caching", + "description": "Manipulate images with an expressive API", + "homepage": "https://github.com/spatie/image", "keywords": [ - "cache", - "caching", - "psr", - "psr-16", - "simple-cache" + "image", + "spatie" ], - "time": "2017-10-23T01:57:42+00:00" + "support": { + "issues": "https://github.com/spatie/image/issues", + "source": "https://github.com/spatie/image/tree/1.10.2" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2021-01-26T07:53:19+00:00" }, { - "name": "psy/psysh", - "version": "v0.10.6", + "name": "spatie/image-optimizer", + "version": "1.3.2", "source": { "type": "git", - "url": "https://github.com/bobthecow/psysh.git", - "reference": "6f990c19f91729de8b31e639d6e204ea59f19cf3" + "url": "https://github.com/spatie/image-optimizer.git", + "reference": "6aa170eb292758553d332efee5e0c3977341080c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/6f990c19f91729de8b31e639d6e204ea59f19cf3", - "reference": "6f990c19f91729de8b31e639d6e204ea59f19cf3", + "url": "https://api.github.com/repos/spatie/image-optimizer/zipball/6aa170eb292758553d332efee5e0c3977341080c", + "reference": "6aa170eb292758553d332efee5e0c3977341080c", "shasum": "" }, "require": { - "dnoegel/php-xdg-base-dir": "0.1.*", - "ext-json": "*", - "ext-tokenizer": "*", - "nikic/php-parser": "~4.0|~3.0|~2.0|~1.3", - "php": "^8.0 || ^7.0 || ^5.5.9", - "symfony/console": "~5.0|~4.0|~3.0|^2.4.2|~2.3.10", - "symfony/var-dumper": "~5.0|~4.0|~3.0|~2.7" + "ext-fileinfo": "*", + "php": "^7.2|^8.0", + "psr/log": "^1.0", + "symfony/process": "^4.2|^5.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.2", - "hoa/console": "3.17.*" - }, - "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.", - "hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit." + "phpunit/phpunit": "^8.0|^9.0", + "symfony/var-dumper": "^4.2|^5.0" }, - "bin": [ - "bin/psysh" - ], "type": "library", - "extra": { - "branch-alias": { - "dev-main": "0.10.x-dev" - } - }, "autoload": { - "files": [ - "src/functions.php" - ], "psr-4": { - "Psy\\": "src/" + "Spatie\\ImageOptimizer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -2011,47 +4120,87 @@ ], "authors": [ { - "name": "Justin Hileman", - "email": "justin@justinhileman.info", - "homepage": "http://justinhileman.com" + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" } ], - "description": "An interactive shell for modern PHP.", - "homepage": "http://psysh.org", + "description": "Easily optimize images using PHP", + "homepage": "https://github.com/spatie/image-optimizer", "keywords": [ - "REPL", - "console", - "interactive", - "shell" + "image-optimizer", + "spatie" ], - "time": "2021-01-18T15:53:43+00:00" + "support": { + "issues": "https://github.com/spatie/image-optimizer/issues", + "source": "https://github.com/spatie/image-optimizer/tree/1.3.2" + }, + "time": "2020-11-28T12:37:58+00:00" }, { - "name": "ralouphie/getallheaders", - "version": "3.0.3", + "name": "spatie/laravel-medialibrary", + "version": "8.10.1", "source": { "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" + "url": "https://github.com/spatie/laravel-medialibrary.git", + "reference": "72b408972ba0b994eb52f39d38169621699e549b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", + "url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/72b408972ba0b994eb52f39d38169621699e549b", + "reference": "72b408972ba0b994eb52f39d38169621699e549b", "shasum": "" }, "require": { - "php": ">=5.6" + "ext-fileinfo": "*", + "ext-json": "*", + "illuminate/bus": "^6.18|^7.0|^8.0", + "illuminate/console": "^6.18|^7.0|^8.0", + "illuminate/database": "^6.18|^7.0|^8.0", + "illuminate/pipeline": "^6.18|^7.0|^8.0", + "illuminate/support": "^6.18|^7.0|^8.0", + "league/flysystem": "^1.0.64", + "maennchen/zipstream-php": "^1.0|^2.0", + "php": "^7.4", + "spatie/image": "^1.4.0", + "spatie/temporary-directory": "^1.1", + "symfony/console": "^4.4|^5.0" + }, + "conflict": { + "php-ffmpeg/php-ffmpeg": "<0.6.1" }, "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" + "aws/aws-sdk-php": "^3.133.11", + "doctrine/dbal": "^2.5.2", + "ext-pdo_sqlite": "*", + "ext-zip": "*", + "guzzlehttp/guzzle": "^6.3|^7.0", + "league/flysystem-aws-s3-v3": "^1.0.23", + "mockery/mockery": "^1.3", + "orchestra/testbench": "^4.0|^5.0|^6.0", + "php-ffmpeg/php-ffmpeg": "^0.16.0", + "phpunit/phpunit": "^9.1", + "spatie/pdf-to-image": "^2.0", + "spatie/phpunit-snapshot-assertions": "^4.0" + }, + "suggest": { + "league/flysystem-aws-s3-v3": "Required to use AWS S3 file storage", + "php-ffmpeg/php-ffmpeg": "Required for generating video thumbnails", + "spatie/pdf-to-image": "Required for generating thumbsnails of PDFs and SVGs" }, "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\MediaLibrary\\MediaLibraryServiceProvider" + ] + } + }, "autoload": { - "files": [ - "src/getallheaders.php" - ] + "psr-4": { + "Spatie\\MediaLibrary\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2059,52 +4208,78 @@ ], "authors": [ { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Associate files with Eloquent models", + "homepage": "https://github.com/spatie/laravel-medialibrary", + "keywords": [ + "cms", + "conversion", + "downloads", + "images", + "laravel", + "laravel-medialibrary", + "media", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-medialibrary/issues", + "source": "https://github.com/spatie/laravel-medialibrary/tree/8.10.1" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" } ], - "description": "A polyfill for getallheaders.", - "time": "2019-03-08T08:55:37+00:00" + "time": "2020-10-05T21:54:57+00:00" }, { - "name": "ramsey/collection", - "version": "1.1.3", + "name": "spatie/laravel-query-builder", + "version": "3.3.4", "source": { "type": "git", - "url": "https://github.com/ramsey/collection.git", - "reference": "28a5c4ab2f5111db6a60b2b4ec84057e0f43b9c1" + "url": "https://github.com/spatie/laravel-query-builder.git", + "reference": "2e131b0c8ae600b6e3aabb5a1501c721862a0b8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/28a5c4ab2f5111db6a60b2b4ec84057e0f43b9c1", - "reference": "28a5c4ab2f5111db6a60b2b4ec84057e0f43b9c1", + "url": "https://api.github.com/repos/spatie/laravel-query-builder/zipball/2e131b0c8ae600b6e3aabb5a1501c721862a0b8f", + "reference": "2e131b0c8ae600b6e3aabb5a1501c721862a0b8f", "shasum": "" }, "require": { - "php": "^7.2 || ^8" + "illuminate/database": "^6.0|^7.0|^8.0", + "illuminate/http": "^6.0|^7.0|^8.0", + "illuminate/support": "^6.0|^7.0|^8.0", + "php": "^7.3|^8.0" }, "require-dev": { - "captainhook/captainhook": "^5.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "ergebnis/composer-normalize": "^2.6", - "fakerphp/faker": "^1.5", - "hamcrest/hamcrest-php": "^2", - "jangregor/phpstan-prophecy": "^0.8", - "mockery/mockery": "^1.3", - "phpstan/extension-installer": "^1", - "phpstan/phpstan": "^0.12.32", - "phpstan/phpstan-mockery": "^0.12.5", - "phpstan/phpstan-phpunit": "^0.12.11", - "phpunit/phpunit": "^8.5 || ^9", - "psy/psysh": "^0.10.4", - "slevomat/coding-standard": "^6.3", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.4" + "ext-json": "*", + "laravel/legacy-factories": "^1.0.4", + "mockery/mockery": "^1.4", + "orchestra/testbench": "^4.9|^5.8|^6.3", + "phpunit/phpunit": "^9.0" }, "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\QueryBuilder\\QueryBuilderServiceProvider" + ] + } + }, "autoload": { "psr-4": { - "Ramsey\\Collection\\": "src/" + "Spatie\\QueryBuilder\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -2113,118 +4288,80 @@ ], "authors": [ { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" + "name": "Alex Vanderbist", + "email": "alex@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" } ], - "description": "A PHP 7.2+ library for representing and manipulating collections.", + "description": "Easily build Eloquent queries from API requests", + "homepage": "https://github.com/spatie/laravel-query-builder", "keywords": [ - "array", - "collection", - "hash", - "map", - "queue", - "set" + "laravel-query-builder", + "spatie" ], + "support": { + "issues": "https://github.com/spatie/laravel-query-builder/issues", + "source": "https://github.com/spatie/laravel-query-builder" + }, "funding": [ { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", - "type": "tidelift" + "url": "https://spatie.be/open-source/support-us", + "type": "custom" } ], - "time": "2021-01-21T17:40:04+00:00" + "time": "2020-11-26T14:51:30+00:00" }, { - "name": "ramsey/uuid", - "version": "4.1.1", + "name": "spatie/temporary-directory", + "version": "1.3.0", "source": { "type": "git", - "url": "https://github.com/ramsey/uuid.git", - "reference": "cd4032040a750077205918c86049aa0f43d22947" + "url": "https://github.com/spatie/temporary-directory.git", + "reference": "f517729b3793bca58f847c5fd383ec16f03ffec6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/cd4032040a750077205918c86049aa0f43d22947", - "reference": "cd4032040a750077205918c86049aa0f43d22947", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/f517729b3793bca58f847c5fd383ec16f03ffec6", + "reference": "f517729b3793bca58f847c5fd383ec16f03ffec6", "shasum": "" }, "require": { - "brick/math": "^0.8 || ^0.9", - "ext-json": "*", - "php": "^7.2 || ^8", - "ramsey/collection": "^1.0", - "symfony/polyfill-ctype": "^1.8" - }, - "replace": { - "rhumsaa/uuid": "self.version" + "php": "^7.2|^8.0" }, "require-dev": { - "codeception/aspect-mock": "^3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7.0", - "doctrine/annotations": "^1.8", - "goaop/framework": "^2", - "mockery/mockery": "^1.3", - "moontoast/math": "^1.1", - "paragonie/random-lib": "^2", - "php-mock/php-mock-mockery": "^1.3", - "php-mock/php-mock-phpunit": "^2.5", - "php-parallel-lint/php-parallel-lint": "^1.1", - "phpbench/phpbench": "^0.17.1", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-mockery": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^8.5", - "psy/psysh": "^0.10.0", - "slevomat/coding-standard": "^6.0", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "3.9.4" - }, - "suggest": { - "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", - "ext-ctype": "Enables faster processing of character classification using ctype functions.", - "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." + "phpunit/phpunit": "^8.0|^9.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev" - } - }, "autoload": { "psr-4": { - "Ramsey\\Uuid\\": "src/" - }, - "files": [ - "src/functions.php" - ] + "Spatie\\TemporaryDirectory\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", - "homepage": "https://github.com/ramsey/uuid", - "keywords": [ - "guid", - "identifier", - "uuid" - ], - "funding": [ + "authors": [ { - "url": "https://github.com/ramsey", - "type": "github" + "name": "Alex Vanderbist", + "email": "alex@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" } ], - "time": "2020-08-18T17:17:46+00:00" + "description": "Easily create, use and destroy temporary directories", + "homepage": "https://github.com/spatie/temporary-directory", + "keywords": [ + "php", + "spatie", + "temporary-directory" + ], + "support": { + "issues": "https://github.com/spatie/temporary-directory/issues", + "source": "https://github.com/spatie/temporary-directory/tree/1.3.0" + }, + "time": "2020-11-09T15:54:21+00:00" }, { "name": "swiftmailer/swiftmailer", @@ -2285,6 +4422,10 @@ "mail", "mailer" ], + "support": { + "issues": "https://github.com/swiftmailer/swiftmailer/issues", + "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.2.5" + }, "funding": [ { "url": "https://github.com/fabpot", @@ -2375,6 +4516,9 @@ "console", "terminal" ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -2437,6 +4581,9 @@ ], "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -2501,6 +4648,9 @@ ], "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/master" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -2567,6 +4717,9 @@ ], "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -2649,6 +4802,9 @@ ], "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -2725,6 +4881,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.2.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -2783,6 +4942,9 @@ ], "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -2859,6 +5021,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v2.3.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -2929,6 +5094,9 @@ ], "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3038,6 +5206,9 @@ ], "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3117,6 +5288,9 @@ "mime", "mime-type" ], + "support": { + "source": "https://github.com/symfony/mime/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3193,6 +5367,9 @@ "polyfill", "portable" ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3270,6 +5447,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-iconv/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3348,6 +5528,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3432,6 +5615,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3513,6 +5699,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3590,6 +5779,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3663,6 +5855,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3739,6 +5934,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3819,6 +6017,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3878,6 +6079,9 @@ ], "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3965,6 +6169,9 @@ "uri", "url" ], + "support": { + "source": "https://github.com/symfony/routing/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4041,6 +6248,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/master" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4121,6 +6331,9 @@ "utf-8", "utf8" ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4211,6 +6424,9 @@ ], "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4286,6 +6502,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v2.3.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4371,6 +6590,9 @@ "debug", "dump" ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v5.2.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4434,8 +6656,92 @@ ], "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", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.3" + }, "time": "2020-07-13T06:12:54+00:00" }, + { + "name": "torann/geoip", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/Torann/laravel-geoip.git", + "reference": "f16d5df66ecb6ba4ffaef52abef519fbc19596d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Torann/laravel-geoip/zipball/f16d5df66ecb6ba4ffaef52abef519fbc19596d3", + "reference": "f16d5df66ecb6ba4ffaef52abef519fbc19596d3", + "shasum": "" + }, + "require": { + "illuminate/cache": "^8.0", + "illuminate/console": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "geoip2/geoip2": "~2.1", + "mockery/mockery": "^1.3", + "phpstan/phpstan": "^0.12.14", + "phpunit/phpunit": "^8.0", + "squizlabs/php_codesniffer": "^3.5", + "vlucas/phpdotenv": "^5.0" + }, + "suggest": { + "geoip2/geoip2": "Required to use the MaxMind database or web service with GeoIP (~2.1).", + "monolog/monolog": "Allows for storing location not found errors to the log" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + }, + "laravel": { + "providers": [ + "Torann\\GeoIP\\GeoIPServiceProvider" + ], + "aliases": { + "GeoIP": "Torann\\GeoIP\\Facades\\GeoIP" + } + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Torann\\GeoIP\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Daniel Stainback", + "email": "torann@gmail.com" + } + ], + "description": "Support for multiple GeoIP services.", + "keywords": [ + "IP API", + "geoip", + "geolocation", + "infoDB", + "laravel", + "location", + "maxmind" + ], + "support": { + "issues": "https://github.com/Torann/laravel-geoip/issues", + "source": "https://github.com/Torann/laravel-geoip/tree/3.0.2" + }, + "time": "2020-12-21T19:12:11+00:00" + }, { "name": "vlucas/phpdotenv", "version": "v5.3.0", @@ -4500,6 +6806,10 @@ "env", "environment" ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.3.0" + }, "funding": [ { "url": "https://github.com/GrahamCampbell", @@ -4558,6 +6868,10 @@ "clean", "php" ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/1.5.6" + }, "funding": [ { "url": "https://www.paypal.me/moelleken", @@ -4629,6 +6943,10 @@ "check", "validate" ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.9.1" + }, "time": "2020-07-08T17:02:28+00:00" } ], @@ -4682,6 +7000,10 @@ "constructor", "instantiate" ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -4751,6 +7073,10 @@ "flare", "reporting" ], + "support": { + "issues": "https://github.com/facade/flare-client-php/issues", + "source": "https://github.com/facade/flare-client-php/tree/1.4.0" + }, "funding": [ { "url": "https://github.com/spatie", @@ -4828,6 +7154,12 @@ "laravel", "page" ], + "support": { + "docs": "https://flareapp.io/docs/ignition-for-laravel/introduction", + "forum": "https://twitter.com/flareappio", + "issues": "https://github.com/facade/ignition/issues", + "source": "https://github.com/facade/ignition" + }, "time": "2021-02-16T12:46:19+00:00" }, { @@ -4877,6 +7209,10 @@ "flare", "ignition" ], + "support": { + "issues": "https://github.com/facade/ignition-contracts/issues", + "source": "https://github.com/facade/ignition-contracts/tree/1.0.2" + }, "time": "2020-10-16T08:27:54+00:00" }, { @@ -4925,6 +7261,10 @@ "faker", "fixtures" ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.13.0" + }, "time": "2020-12-18T16:50:48+00:00" }, { @@ -4986,6 +7326,10 @@ "throwable", "whoops" ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.9.2" + }, "funding": [ { "url": "https://github.com/denis-sokolov", @@ -5039,6 +7383,10 @@ "keywords": [ "test" ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + }, "time": "2020-07-09T08:09:16+00:00" }, { @@ -5095,6 +7443,10 @@ "docker", "laravel" ], + "support": { + "issues": "https://github.com/laravel/sail/issues", + "source": "https://github.com/laravel/sail" + }, "time": "2021-02-24T21:20:16+00:00" }, { @@ -5163,6 +7515,10 @@ "test double", "testing" ], + "support": { + "issues": "https://github.com/mockery/mockery/issues", + "source": "https://github.com/mockery/mockery/tree/1.4.3" + }, "time": "2021-02-24T09:51:49+00:00" }, { @@ -5211,6 +7567,10 @@ "object", "object graph" ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + }, "funding": [ { "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", @@ -5287,6 +7647,10 @@ "php", "symfony" ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, "funding": [ { "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", @@ -5357,6 +7721,10 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/master" + }, "time": "2020-06-27T14:33:11+00:00" }, { @@ -5404,6 +7772,10 @@ } ], "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.1.0" + }, "time": "2021-02-23T14:00:09+00:00" }, { @@ -5453,6 +7825,10 @@ "reflection", "static analysis" ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, "time": "2020-06-27T09:03:43+00:00" }, { @@ -5505,6 +7881,10 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" + }, "time": "2020-09-03T19:13:55+00:00" }, { @@ -5550,6 +7930,10 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" + }, "time": "2020-09-17T18:55:26+00:00" }, { @@ -5613,6 +7997,10 @@ "spy", "stub" ], + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/1.12.2" + }, "time": "2020-12-19T10:15:11+00:00" }, { @@ -5680,6 +8068,10 @@ "testing", "xunit" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.5" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -5736,6 +8128,10 @@ "filesystem", "iterator" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -5795,6 +8191,10 @@ "keywords": [ "process" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -5850,6 +8250,10 @@ "keywords": [ "template" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -5905,6 +8309,10 @@ "keywords": [ "timer" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6000,6 +8408,10 @@ "testing", "xunit" ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.2" + }, "funding": [ { "url": "https://phpunit.de/donate.html", @@ -6056,6 +8468,10 @@ ], "description": "Library for parsing CLI options", "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6108,6 +8524,10 @@ ], "description": "Collection of value objects that represent the PHP code units", "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6159,6 +8579,10 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6229,6 +8653,10 @@ "compare", "equality" ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6282,6 +8710,10 @@ ], "description": "Library for calculating the complexity of PHP code units", "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6344,6 +8776,10 @@ "unidiff", "unified diff" ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6403,6 +8839,10 @@ "environment", "hhvm" ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6476,6 +8916,10 @@ "export", "exporter" ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6536,6 +8980,10 @@ "keywords": [ "global state" ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6589,6 +9037,10 @@ ], "description": "Library for counting the lines of code in PHP source code", "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6642,6 +9094,10 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6693,6 +9149,10 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6752,6 +9212,10 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6803,6 +9267,10 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6855,6 +9323,10 @@ ], "description": "Collection of value objects that represent the types of the PHP type system", "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/2.3.1" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6904,6 +9376,10 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -6950,6 +9426,10 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/master" + }, "funding": [ { "url": "https://github.com/theseer", @@ -6965,8 +9445,10 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^7.3|^8.0" + "php": "^7.3|^8.0", + "ext-gd": "*", + "ext-json": "*" }, "platform-dev": [], - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } diff --git a/config.default/app.php b/config.default/app.php new file mode 100644 index 0000000..2a2f0eb --- /dev/null +++ b/config.default/app.php @@ -0,0 +1,232 @@ + 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', null), + + /* + |-------------------------------------------------------------------------- + | 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' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | 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', + + /* + |-------------------------------------------------------------------------- + | 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' => [ + + /* + * Laravel Framework Service Providers... + */ + Illuminate\Auth\AuthServiceProvider::class, + Illuminate\Broadcasting\BroadcastServiceProvider::class, + Illuminate\Bus\BusServiceProvider::class, + Illuminate\Cache\CacheServiceProvider::class, + Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, + Illuminate\Cookie\CookieServiceProvider::class, + Illuminate\Database\DatabaseServiceProvider::class, + Illuminate\Encryption\EncryptionServiceProvider::class, + Illuminate\Filesystem\FilesystemServiceProvider::class, + Illuminate\Foundation\Providers\FoundationServiceProvider::class, + Illuminate\Hashing\HashServiceProvider::class, + Illuminate\Mail\MailServiceProvider::class, + Illuminate\Notifications\NotificationServiceProvider::class, + Illuminate\Pagination\PaginationServiceProvider::class, + Illuminate\Pipeline\PipelineServiceProvider::class, + Illuminate\Queue\QueueServiceProvider::class, + Illuminate\Redis\RedisServiceProvider::class, + Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, + Illuminate\Session\SessionServiceProvider::class, + Illuminate\Translation\TranslationServiceProvider::class, + Illuminate\Validation\ValidationServiceProvider::class, + Illuminate\View\ViewServiceProvider::class, + + /* + * 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, + + ], + + /* + |-------------------------------------------------------------------------- + | 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' => [ + + 'App' => Illuminate\Support\Facades\App::class, + 'Arr' => Illuminate\Support\Arr::class, + 'Artisan' => Illuminate\Support\Facades\Artisan::class, + 'Auth' => Illuminate\Support\Facades\Auth::class, + 'Blade' => Illuminate\Support\Facades\Blade::class, + 'Broadcast' => Illuminate\Support\Facades\Broadcast::class, + 'Bus' => Illuminate\Support\Facades\Bus::class, + 'Cache' => Illuminate\Support\Facades\Cache::class, + 'Config' => Illuminate\Support\Facades\Config::class, + 'Cookie' => Illuminate\Support\Facades\Cookie::class, + 'Crypt' => Illuminate\Support\Facades\Crypt::class, + 'DB' => Illuminate\Support\Facades\DB::class, + 'Eloquent' => Illuminate\Database\Eloquent\Model::class, + 'Event' => Illuminate\Support\Facades\Event::class, + 'File' => Illuminate\Support\Facades\File::class, + 'Gate' => Illuminate\Support\Facades\Gate::class, + 'Hash' => Illuminate\Support\Facades\Hash::class, + 'Http' => Illuminate\Support\Facades\Http::class, + 'Lang' => Illuminate\Support\Facades\Lang::class, + 'Log' => Illuminate\Support\Facades\Log::class, + 'Mail' => Illuminate\Support\Facades\Mail::class, + 'Notification' => Illuminate\Support\Facades\Notification::class, + 'Password' => Illuminate\Support\Facades\Password::class, + 'Queue' => Illuminate\Support\Facades\Queue::class, + 'Redirect' => Illuminate\Support\Facades\Redirect::class, + // 'Redis' => Illuminate\Support\Facades\Redis::class, + 'Request' => Illuminate\Support\Facades\Request::class, + 'Response' => Illuminate\Support\Facades\Response::class, + 'Route' => Illuminate\Support\Facades\Route::class, + 'Schema' => Illuminate\Support\Facades\Schema::class, + 'Session' => Illuminate\Support\Facades\Session::class, + 'Storage' => Illuminate\Support\Facades\Storage::class, + 'Str' => Illuminate\Support\Str::class, + 'URL' => Illuminate\Support\Facades\URL::class, + 'Validator' => Illuminate\Support\Facades\Validator::class, + 'View' => Illuminate\Support\Facades\View::class, + + ], + +]; diff --git a/config/auth.php b/config.default/auth.php similarity index 100% rename from config/auth.php rename to config.default/auth.php diff --git a/config/broadcasting.php b/config.default/broadcasting.php similarity index 100% rename from config/broadcasting.php rename to config.default/broadcasting.php diff --git a/config/cache.php b/config.default/cache.php similarity index 100% rename from config/cache.php rename to config.default/cache.php diff --git a/config.default/cors.php b/config.default/cors.php new file mode 100644 index 0000000..8a39e6d --- /dev/null +++ b/config.default/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/config/database.php b/config.default/database.php similarity index 100% rename from config/database.php rename to config.default/database.php diff --git a/config.default/filesystems.php b/config.default/filesystems.php new file mode 100644 index 0000000..10c9d9b --- /dev/null +++ b/config.default/filesystems.php @@ -0,0 +1,72 @@ + env('FILESYSTEM_DRIVER', '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 setup for each driver as an example of the required options. + | + | Supported Drivers: "local", "ftp", "sftp", "s3" + | + */ + + 'disks' => [ + + 'local' => [ + 'driver' => 'local', + 'root' => storage_path('app'), + ], + + 'public' => [ + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'url' => env('APP_URL').'/storage', + 'visibility' => 'public', + ], + + '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'), + ], + + ], + + /* + |-------------------------------------------------------------------------- + | 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/config/hashing.php b/config.default/hashing.php similarity index 100% rename from config/hashing.php rename to config.default/hashing.php diff --git a/config.default/logging.php b/config.default/logging.php new file mode 100644 index 0000000..6aa77fe --- /dev/null +++ b/config.default/logging.php @@ -0,0 +1,104 @@ + env('LOG_CHANNEL', 'stack'), + + /* + |-------------------------------------------------------------------------- + | 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'), + ], + + 'daily' => [ + 'driver' => 'daily', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'days' => 14, + ], + + 'slack' => [ + 'driver' => 'slack', + 'url' => env('LOG_SLACK_WEBHOOK_URL'), + 'username' => 'Laravel Log', + 'emoji' => ':boom:', + 'level' => env('LOG_LEVEL', 'critical'), + ], + + 'papertrail' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => SyslogUdpHandler::class, + 'handler_with' => [ + 'host' => env('PAPERTRAIL_URL'), + 'port' => env('PAPERTRAIL_PORT'), + ], + ], + + 'stderr' => [ + 'driver' => 'monolog', + 'handler' => StreamHandler::class, + 'formatter' => env('LOG_STDERR_FORMATTER'), + 'with' => [ + 'stream' => 'php://stderr', + ], + ], + + 'syslog' => [ + 'driver' => 'syslog', + 'level' => env('LOG_LEVEL', 'debug'), + ], + + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => env('LOG_LEVEL', 'debug'), + ], + + 'null' => [ + 'driver' => 'monolog', + 'handler' => NullHandler::class, + ], + + 'emergency' => [ + 'path' => storage_path('logs/laravel.log'), + ], + ], + +]; diff --git a/config/mail.php b/config.default/mail.php similarity index 100% rename from config/mail.php rename to config.default/mail.php diff --git a/config/queue.php b/config.default/queue.php similarity index 100% rename from config/queue.php rename to config.default/queue.php diff --git a/config.default/services.php b/config.default/services.php new file mode 100644 index 0000000..2a1d616 --- /dev/null +++ b/config.default/services.php @@ -0,0 +1,33 @@ + [ + 'domain' => env('MAILGUN_DOMAIN'), + 'secret' => env('MAILGUN_SECRET'), + 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), + ], + + '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/config/session.php b/config.default/session.php similarity index 100% rename from config/session.php rename to config.default/session.php diff --git a/config/view.php b/config.default/view.php similarity index 100% rename from config/view.php rename to config.default/view.php diff --git a/config/amqp.php b/config/amqp.php new file mode 100644 index 0000000..d0734cf --- /dev/null +++ b/config/amqp.php @@ -0,0 +1,73 @@ + env('AMQP_CONNECTION', 'rabbitmq'), + + /*Available connections*/ + 'connections' => [ + + 'rabbitmq' => [ + 'connection' => [ + 'host' => env('AMQP_HOST', 'base-rabbitmq'), + 'port' => env('AMQP_PORT', 5672), + 'username' => env('AMQP_USERNAME', 'root'), + 'password' => env('AMQP_PASSWORD', 'root'), + 'vhost' => env('AMQP_VHOST', '/'), + 'connect_options' => [], + 'ssl_options' => [], + 'ssl_protocol' => env('AMQP_SSL_PROTOCOL', 'ssl'), + ], + + 'channel_id' => null, + + 'message' => [ + 'content_type' => 'text/plain', + 'delivery_mode' => env('AMQP_MESSAGE_DELIVERY_MODE', AMQPMessage::DELIVERY_MODE_PERSISTENT), + 'content_encoding' => 'UTF-8', + ], + + 'exchange' => [ + 'name' => env('AMQP_EXCHANGE_NAME', 'activity_exchange'), + 'declare' => env('AMQP_EXCHANGE_DECLARE', false), + 'type' => env('AMQP_EXCHANGE_TYPE', 'headers'), + 'passive' => env('AMQP_EXCHANGE_PASSIVE', false), + 'durable' => env('AMQP_EXCHANGE_DURABLE', true), + 'auto_delete' => env('AMQP_EXCHANGE_AUTO_DEL', false), + 'internal' => env('AMQP_EXCHANGE_INTERNAL', false), + 'nowait' => env('AMQP_EXCHANGE_NOWAIT', false), + 'properties' => [], + ], + + 'queue' => [ + 'declare' => env('AMQP_QUEUE_DECLARE', false), + 'passive' => env('AMQP_QUEUE_PASSIVE', false), + 'durable' => env('AMQP_QUEUE_DURABLE', true), + 'exclusive' => env('AMQP_QUEUE_EXCLUSIVE', false), + 'auto_delete' => env('AMQP_QUEUE_AUTO_DEL', false), + 'nowait' => env('AMQP_QUEUE_NOWAIT', false), + 'd_properties' => [], // queue_declare properties/arguments + 'b_properties' => [], // queue_bind properties/arguments + ], + + 'consumer' => [ + 'tag' => env('AMQP_CONSUMER_TAG', ''), + 'no_local' => env('AMQP_CONSUMER_NO_LOCAL', false), + 'no_ack' => env('AMQP_CONSUMER_NO_ACK', false), + 'exclusive' => env('AMQP_CONSUMER_EXCLUSIVE', false), + 'nowait' => env('AMQP_CONSUMER_NOWAIT', false), + 'ticket' => null, + 'properties' => [], + ], + + 'qos' => [ + 'enabled' => env('AMQP_QOS_ENABLED', false), + 'qos_prefetch_size' => env('AMQP_QOS_PREF_SIZE', 0), + 'qos_prefetch_count' => env('AMQP_QOS_PREF_COUNT', 1), + 'qos_a_global' => env('AMQP_QOS_GLOBAL', false), + ], + ], + ], +]; diff --git a/config/app.php b/config/app.php index 2a2f0eb..1675900 100644 --- a/config/app.php +++ b/config/app.php @@ -1,232 +1,19 @@ 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', null), + 'timezone' => 'Asia/Tehran', - /* - |-------------------------------------------------------------------------- - | 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' => 'UTC', - - /* - |-------------------------------------------------------------------------- - | 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. - | - */ + 'locale' => 'fa', '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', - - /* - |-------------------------------------------------------------------------- - | 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' => [ - - /* - * Laravel Framework Service Providers... - */ - Illuminate\Auth\AuthServiceProvider::class, - Illuminate\Broadcasting\BroadcastServiceProvider::class, - Illuminate\Bus\BusServiceProvider::class, - Illuminate\Cache\CacheServiceProvider::class, - Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, - Illuminate\Cookie\CookieServiceProvider::class, - Illuminate\Database\DatabaseServiceProvider::class, - Illuminate\Encryption\EncryptionServiceProvider::class, - Illuminate\Filesystem\FilesystemServiceProvider::class, - Illuminate\Foundation\Providers\FoundationServiceProvider::class, - Illuminate\Hashing\HashServiceProvider::class, - Illuminate\Mail\MailServiceProvider::class, - Illuminate\Notifications\NotificationServiceProvider::class, - Illuminate\Pagination\PaginationServiceProvider::class, - Illuminate\Pipeline\PipelineServiceProvider::class, - Illuminate\Queue\QueueServiceProvider::class, - Illuminate\Redis\RedisServiceProvider::class, - Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, - Illuminate\Session\SessionServiceProvider::class, - Illuminate\Translation\TranslationServiceProvider::class, - Illuminate\Validation\ValidationServiceProvider::class, - Illuminate\View\ViewServiceProvider::class, - - /* - * 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, - - ], - - /* - |-------------------------------------------------------------------------- - | 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' => [ - - 'App' => Illuminate\Support\Facades\App::class, - 'Arr' => Illuminate\Support\Arr::class, - 'Artisan' => Illuminate\Support\Facades\Artisan::class, - 'Auth' => Illuminate\Support\Facades\Auth::class, - 'Blade' => Illuminate\Support\Facades\Blade::class, - 'Broadcast' => Illuminate\Support\Facades\Broadcast::class, - 'Bus' => Illuminate\Support\Facades\Bus::class, - 'Cache' => Illuminate\Support\Facades\Cache::class, - 'Config' => Illuminate\Support\Facades\Config::class, - 'Cookie' => Illuminate\Support\Facades\Cookie::class, - 'Crypt' => Illuminate\Support\Facades\Crypt::class, - 'DB' => Illuminate\Support\Facades\DB::class, - 'Eloquent' => Illuminate\Database\Eloquent\Model::class, - 'Event' => Illuminate\Support\Facades\Event::class, - 'File' => Illuminate\Support\Facades\File::class, - 'Gate' => Illuminate\Support\Facades\Gate::class, - 'Hash' => Illuminate\Support\Facades\Hash::class, - 'Http' => Illuminate\Support\Facades\Http::class, - 'Lang' => Illuminate\Support\Facades\Lang::class, - 'Log' => Illuminate\Support\Facades\Log::class, - 'Mail' => Illuminate\Support\Facades\Mail::class, - 'Notification' => Illuminate\Support\Facades\Notification::class, - 'Password' => Illuminate\Support\Facades\Password::class, - 'Queue' => Illuminate\Support\Facades\Queue::class, - 'Redirect' => Illuminate\Support\Facades\Redirect::class, - // 'Redis' => Illuminate\Support\Facades\Redis::class, - 'Request' => Illuminate\Support\Facades\Request::class, - 'Response' => Illuminate\Support\Facades\Response::class, - 'Route' => Illuminate\Support\Facades\Route::class, - 'Schema' => Illuminate\Support\Facades\Schema::class, - 'Session' => Illuminate\Support\Facades\Session::class, - 'Storage' => Illuminate\Support\Facades\Storage::class, - 'Str' => Illuminate\Support\Str::class, - 'URL' => Illuminate\Support\Facades\URL::class, - 'Validator' => Illuminate\Support\Facades\Validator::class, - 'View' => Illuminate\Support\Facades\View::class, - - ], + 'faker_locale' => 'fa_IR', + 'cache_ttl' => 60 ]; diff --git a/config/cors.php b/config/cors.php index 8a39e6d..c3ded3c 100644 --- a/config/cors.php +++ b/config/cors.php @@ -1,34 +1,59 @@ ['api/*', 'sanctum/csrf-cookie'], + /* + * You can enable CORS for 1 or multiple paths. + * Example: ['api/*'] + */ + 'paths' => ['/*'], + /* + * Matches the request method. `['*']` allows all methods. + */ 'allowed_methods' => ['*'], + /* + * Matches the request origin. `['*']` allows all origins. Wildcards can be used, eg `*.mydomain.com` + */ 'allowed_origins' => ['*'], - 'allowed_origins_patterns' => [], + /* + * Patterns that can be used with `preg_match` to match the origin. + */ + 'allowedOriginsPatterns' => ['Content-Type', 'X-Requested-With'], + /* + * Sets the Access-Control-Allow-Headers response header. `['*']` allows all headers. + */ 'allowed_headers' => ['*'], + /* + * Sets the Access-Control-Expose-Headers response header with these headers. + */ 'exposed_headers' => [], + /* + * Sets the Access-Control-Max-Age response header when > 0. + */ 'max_age' => 0, + /* + * Sets the Access-Control-Allow-Credentials header. + */ 'supports_credentials' => false, - ]; diff --git a/config/filesystems.php b/config/filesystems.php index 10c9d9b..e5708dc 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -15,6 +15,19 @@ return [ 'default' => env('FILESYSTEM_DRIVER', 'local'), + /* + |-------------------------------------------------------------------------- + | Default Cloud Filesystem Disk + |-------------------------------------------------------------------------- + | + | Many applications store files both locally and in the cloud. For this + | reason, you may specify a default "cloud" driver here. This driver + | will be bound as the Cloud disk implementation in the container. + | + */ + + 'cloud' => env('FILESYSTEM_CLOUD', 's3'), + /* |-------------------------------------------------------------------------- | Filesystem Disks @@ -38,7 +51,7 @@ return [ 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), - 'url' => env('APP_URL').'/storage', + 'url' => env('APP_URL') . '/storage', 'visibility' => 'public', ], @@ -46,8 +59,8 @@ return [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), - 'region' => env('AWS_DEFAULT_REGION'), - 'bucket' => env('AWS_BUCKET'), + 'region' => env('AWS_DEFAULT_REGION','us'), + 'bucket' => env('AWS_BUCKET','real-test-2'), 'url' => env('AWS_URL'), 'endpoint' => env('AWS_ENDPOINT'), ], @@ -66,7 +79,7 @@ return [ */ 'links' => [ - public_path('storage') => storage_path('app/public'), + base_path('public/storage') => storage_path('app/public'), ], ]; diff --git a/config/geoip.php b/config/geoip.php new file mode 100644 index 0000000..0c812fc --- /dev/null +++ b/config/geoip.php @@ -0,0 +1,172 @@ + false, + + /* + |-------------------------------------------------------------------------- + | Include Currency in Results + |-------------------------------------------------------------------------- + | + | When enabled the system will do it's best in deciding the user's currency + | by matching their ISO code to a preset list of currencies. + | + */ + + 'include_currency' => false, + + /* + |-------------------------------------------------------------------------- + | Default Service + |-------------------------------------------------------------------------- + | + | Here you may specify the default storage driver that should be used + | by the framework. + | + | Supported: "maxmind_database", "maxmind_api", "ipapi" + | + */ + + 'service' => 'ipapi', + + /* + |-------------------------------------------------------------------------- + | Storage Specific Configuration + |-------------------------------------------------------------------------- + | + | Here you may configure as many storage drivers as you wish. + | + */ + + 'services' => [ + + 'maxmind_database' => [ + 'class' => MaxMindDatabase::class, + 'database_path' => storage_path('app/geoip.mmdb'), + 'update_url' => sprintf('https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=%s&suffix=tar.gz', env('MAXMIND_LICENSE_KEY')), + 'locales' => ['en'], + ], + + 'maxmind_api' => [ + 'class' => MaxMindWebService::class, + 'user_id' => env('MAXMIND_USER_ID'), + 'license_key' => env('MAXMIND_LICENSE_KEY'), + 'locales' => ['en'], + ], + + 'ipapi' => [ + 'class' => IPApi::class, + 'secure' => true, + 'key' => env('IPAPI_KEY'), + 'continent_path' => storage_path('app/continents.json'), + 'lang' => 'en', + ], + + 'ipgeolocation' => [ + 'class' => IPGeoLocation::class, + 'secure' => true, + 'key' => env('IPGEOLOCATION_KEY'), + 'continent_path' => storage_path('app/continents.json'), + 'lang' => 'en', + ], + + 'ipdata' => [ + 'class' => IPData::class, + 'key' => env('IPDATA_API_KEY'), + 'secure' => true, + ], + + 'ipfinder' => [ + 'class' => IPFinder::class, + 'key' => env('IPFINDER_API_KEY'), + 'secure' => true, + 'locales' => ['en'], + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Default Cache Driver + |-------------------------------------------------------------------------- + | + | Here you may specify the type of caching that should be used + | by the package. + | + | Options: + | + | all - All location are cached + | some - Cache only the requesting user + | none - Disable cached + | + */ + + 'cache' => 'none', + + /* + |-------------------------------------------------------------------------- + | Cache Tags + |-------------------------------------------------------------------------- + | + | Cache tags are not supported when using the file or database cache + | drivers in Laravel. This is done so that only locations can be cleared. + | + */ + +// 'cache_tags' => [''], + + /* + |-------------------------------------------------------------------------- + | Cache Expiration + |-------------------------------------------------------------------------- + | + | Define how long cached location are valid. + | + */ + + 'cache_expires' => 30, + + /* + |-------------------------------------------------------------------------- + | Default Location + |-------------------------------------------------------------------------- + | + | Return when a location is not found. + | + */ + + 'default_location' => [ + 'ip' => '127.0.0.0', + 'iso_code' => 'IRN', + 'country' => 'Islamic Republic of Iran', + 'city' => 'Tehran', + 'state' => 'teh', + 'state_name' => 'Connecticut', + 'postal_code' => '513', + 'lat' => 35.6892, + 'lon' => 51.3890, + 'timezone' => 'Asia/Tehran', + 'continent' => 'Asia', + 'default' => true, + 'currency' => 'IRR', + ], + +]; diff --git a/config/logging.php b/config/logging.php index 6aa77fe..31b0dcf 100644 --- a/config/logging.php +++ b/config/logging.php @@ -1,104 +1,44 @@ env('LOG_CHANNEL', 'stack'), - /* - |-------------------------------------------------------------------------- - | 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' => [ + 'hi' => [ + 'driver' => 'custom', + 'via' => CreateCustomLogger::class, + 'handler' => AmqpHandler::class, + 'with' => [ + 'exchange' => new AMQPChannel( + new AMQPStreamConnection("base-rabbitmq", 5672, 'root', 'root') + ), + 'exchangeName' => 'log_exchange' + ], + ], + 'stack' => [ 'driver' => 'stack', - 'channels' => ['single'], + 'channels' => ['hi', 'daily',], 'ignore_exceptions' => false, ], 'single' => [ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'), - 'level' => env('LOG_LEVEL', 'debug'), + 'level' => 'debug', ], 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), - 'level' => env('LOG_LEVEL', 'debug'), + 'level' => 'debug', 'days' => 14, ], - - 'slack' => [ - 'driver' => 'slack', - 'url' => env('LOG_SLACK_WEBHOOK_URL'), - 'username' => 'Laravel Log', - 'emoji' => ':boom:', - 'level' => env('LOG_LEVEL', 'critical'), - ], - - 'papertrail' => [ - 'driver' => 'monolog', - 'level' => env('LOG_LEVEL', 'debug'), - 'handler' => SyslogUdpHandler::class, - 'handler_with' => [ - 'host' => env('PAPERTRAIL_URL'), - 'port' => env('PAPERTRAIL_PORT'), - ], - ], - - 'stderr' => [ - 'driver' => 'monolog', - 'handler' => StreamHandler::class, - 'formatter' => env('LOG_STDERR_FORMATTER'), - 'with' => [ - 'stream' => 'php://stderr', - ], - ], - - 'syslog' => [ - 'driver' => 'syslog', - 'level' => env('LOG_LEVEL', 'debug'), - ], - - 'errorlog' => [ - 'driver' => 'errorlog', - 'level' => env('LOG_LEVEL', 'debug'), - ], - - 'null' => [ - 'driver' => 'monolog', - 'handler' => NullHandler::class, - ], - - 'emergency' => [ - 'path' => storage_path('logs/laravel.log'), - ], ], - ]; diff --git a/config/media-library.php b/config/media-library.php new file mode 100644 index 0000000..6d21069 --- /dev/null +++ b/config/media-library.php @@ -0,0 +1,179 @@ + env('MEDIA_DISK', 'public'), + + /* + * The maximum file size of an item in bytes. + * Adding a larger file will result in an exception. + */ + 'max_file_size' => 1024 * 1024 * 10, + + /* + * This queue will be used to generate derived and responsive images. + * Leave empty to use the default queue. + */ + 'queue_name' => '', + + /* + * By default all conversions will be performed on a queue. + */ + 'queue_conversions_by_default' => env('QUEUE_CONVERSIONS_BY_DEFAULT', true), + + /* + * The fully qualified class name of the media model. + */ + 'media_model' => Spatie\MediaLibrary\MediaCollections\Models\Media::class, + + 'remote' => [ + /* + * Any extra headers that should be included when uploading media to + * a remote disk. Even though supported headers may vary between + * different drivers, a sensible default has been provided. + * + * Supported by S3: CacheControl, Expires, StorageClass, + * ServerSideEncryption, Metadata, ACL, ContentEncoding + */ + 'extra_headers' => [ + 'CacheControl' => 'max-age=604800', + ], + ], + + 'responsive_images' => [ + + /* + * This class is responsible for calculating the target widths of the responsive + * images. By default we optimize for filesize and create variations that each are 20% + * smaller than the previous one. More info in the documentation. + * + * https://docs.spatie.be/laravel-medialibrary/v8/advanced-usage/generating-responsive-images + */ + 'width_calculator' => Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\FileSizeOptimizedWidthCalculator::class, + + /* + * By default rendering media to a responsive image will add some javascript and a tiny placeholder. + * This ensures that the browser can already determine the correct layout. + */ + 'use_tiny_placeholders' => true, + + /* + * This class will generate the tiny placeholder used for progressive image loading. By default + * the media library will use a tiny blurred jpg image. + */ + 'tiny_placeholder_generator' => Spatie\MediaLibrary\ResponsiveImages\TinyPlaceholderGenerator\Blurred::class, + ], + + /* + * When converting Media instances to response the media library will add + * a `loading` attribute to the `img` tag. Here you can set the default + * value of that attribute. + * + * Possible values: 'lazy', 'eager', 'auto' or null if you don't want to set any loading instruction. + * + * More info: https://css-tricks.com/native-lazy-loading/ + */ + 'default_loading_attribute_value' => null, + + /* + * This is the class that is responsible for naming conversion files. By default, + * it will use the filename of the original and concatenate the conversion name to it. + */ + 'conversion_file_namer' => App\Utilities\Avatar\DefaultConversionFileNamer::class, + + /* + * The class that contains the strategy for determining a media file's path. + */ + 'path_generator' => App\Utilities\Avatar\DefaultPathGenerator::class, + + /* + * When urls to files get generated, this class will be called. Use the default + * if your files are stored locally above the site root or on s3. + */ + 'url_generator' => Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator::class, + + /* + * Whether to activate versioning when urls to files get generated. + * When activated, this attaches a ?v=xx query string to the URL. + */ + 'version_urls' => false, + + /* + * The media library will try to optimize all converted images by removing + * metadata and applying a little bit of compression. These are + * the optimizers that will be used by default. + */ + 'image_optimizers' => [ + Spatie\ImageOptimizer\Optimizers\Jpegoptim::class => [ + '--strip-all', // this strips out all text information such as comments and EXIF data + '--all-progressive', // this will make sure the resulting image is a progressive one + ], + Spatie\ImageOptimizer\Optimizers\Pngquant::class => [ + '--force', // required parameter for this package + ], + Spatie\ImageOptimizer\Optimizers\Optipng::class => [ + '-i0', // this will result in a non-interlaced, progressive scanned image + '-o2', // this set the optimization level to two (multiple IDAT compression trials) + '-quiet', // required parameter for this package + ], + Spatie\ImageOptimizer\Optimizers\Svgo::class => [ + '--disable=cleanupIDs', // disabling because it is known to cause troubles + ], + Spatie\ImageOptimizer\Optimizers\Gifsicle::class => [ + '-b', // required parameter for this package + '-O3', // this produces the slowest but best results + ], + ], + + /* + * These generators will be used to create an image of media files. + */ + 'image_generators' => [ + Spatie\MediaLibrary\Conversions\ImageGenerators\Image::class, + Spatie\MediaLibrary\Conversions\ImageGenerators\Webp::class, + Spatie\MediaLibrary\Conversions\ImageGenerators\Pdf::class, + Spatie\MediaLibrary\Conversions\ImageGenerators\Svg::class, + Spatie\MediaLibrary\Conversions\ImageGenerators\Video::class, + ], + + /* + * The engine that should perform the image conversions. + * Should be either `gd` or `imagick`. + */ + 'image_driver' => env('IMAGE_DRIVER', 'gd'), + + /* + * FFMPEG & FFProbe binaries paths, only used if you try to generate video + * thumbnails and have installed the php-ffmpeg/php-ffmpeg composer + * dependency. + */ + 'ffmpeg_path' => env('FFMPEG_PATH', '/usr/bin/ffmpeg'), + 'ffprobe_path' => env('FFPROBE_PATH', '/usr/bin/ffprobe'), + + /* + * The path where to store temporary files while performing image conversions. + * If set to null, storage_path('media-library/temp') will be used. + */ + 'temporary_directory_path' => null, + + /* + * Here you can override the class names of the jobs used by this package. Make sure + * your custom jobs extend the ones provided by the package. + */ + 'jobs' => [ + 'perform_conversions' => Spatie\MediaLibrary\Conversions\Jobs\PerformConversionsJob::class, + 'generate_responsive_images' => Spatie\MediaLibrary\ResponsiveImages\Jobs\GenerateResponsiveImagesJob::class, + ], + + /* + * When using the addMediaFromUrl method you may want to replace the default downloader. + * This is particularly useful when the url of the image is behind a firewall and + * need to add additional flags, possibly using curl. + */ + 'media_downloader' => Spatie\MediaLibrary\Downloaders\DefaultDownloader::class, + +]; diff --git a/config/query-builder.php b/config/query-builder.php new file mode 100644 index 0000000..b65680f --- /dev/null +++ b/config/query-builder.php @@ -0,0 +1,38 @@ + [ + 'include' => 'include', + + 'filter' => 'filter', + + 'sort' => 'sort', + + 'fields' => 'fields', + + 'append' => 'append', + ], + + /* + * Related model counts are included using the relationship name suffixed with this string. + * For example: GET /users?include=postsCount + */ + 'count_suffix' => 'Count', + + /* + * By default the package will throw an `InvalidFilterQuery` exception when a filter in the + * URL is not allowed in the `allowedFilters()` method. + */ + 'disable_invalid_filter_query_exception' => false, + +]; diff --git a/config/services.php b/config/services.php index 2a1d616..95b9b0a 100644 --- a/config/services.php +++ b/config/services.php @@ -1,33 +1,21 @@ [ - 'domain' => env('MAILGUN_DOMAIN'), - 'secret' => env('MAILGUN_SECRET'), - 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), + 'task' => 'hi-task-app', + 'zarinpal' => [ + 'merchant-id' => '68d337b0-4b77-11ea-8409-000c295eb8fc', + 'type' => 'zarin-gate', // Types: [zarin-gate || normal] + 'callback-url' => 'http://127.0.0.1:8000/user/v1/callback', + 'server' => 'germany', // Servers: [germany || iran || test] + 'email' => 'admin@base.com', + 'mobile' => '09123456789', + 'description' => env('APP_NAME', 'APP_NAME'), + 'sandbox' => true, ], - 'postmark' => [ - 'token' => env('POSTMARK_TOKEN'), + 'google' => [ + 'client_id' => '1002439248397-oa6hnh25n6qri3q4kst62gvb1k9ki65l.apps.googleusercontent.com', + 'client_secret' => 'tKbiyh5hOjYIcj-W1y3N8X5R', + 'redirect' => 'http://localhost:8000/user/v1/auth/google/callback', ], - - 'ses' => [ - 'key' => env('AWS_ACCESS_KEY_ID'), - 'secret' => env('AWS_SECRET_ACCESS_KEY'), - 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), - ], - ]; diff --git a/database/factories/BusinessFactory.php b/database/factories/BusinessFactory.php new file mode 100644 index 0000000..8a15574 --- /dev/null +++ b/database/factories/BusinessFactory.php @@ -0,0 +1,19 @@ +define(Business::class, function (Faker $faker) { + return [ + 'name' => $name = $faker->unique()->company, + 'slug' => Str::slug($name) . $faker->numberBetween(1, 100), + 'wallet' => random_int(111111, 999999), + 'slug' => Str::slug($name) . $faker->numberBetween(1, 100), + 'color' => $faker->colorName, + 'calculated_at' => \Carbon\Carbon::now()->subMinutes(random_int(1, 1000)), + ]; +}); diff --git a/database/factories/CostFactory.php b/database/factories/CostFactory.php new file mode 100644 index 0000000..649cc16 --- /dev/null +++ b/database/factories/CostFactory.php @@ -0,0 +1,19 @@ +define(Cost::class, function (Faker $faker) { + return [ + 'business_id' => random_int(1,5000), + 'type' => $type = $faker->boolean() ? 'users' : 'files', + 'month' => jdate(Carbon::now()->subDays(random_int(0,90)))->format("Y-m-01"), + 'amount' => random_int(1,1000), + 'fee' => $type === 'users' ? enum("business.fee.user") : enum("business.fee.file"), + 'duration' => random_int(1,60), + 'created_at' => Carbon::now()->subMinutes(random_int(1, 1000)), + ]; +}); diff --git a/database/factories/FileFactory.php b/database/factories/FileFactory.php new file mode 100644 index 0000000..c8a4620 --- /dev/null +++ b/database/factories/FileFactory.php @@ -0,0 +1,35 @@ +define(File::class, function (Faker $faker) { + $mimes = ['application/pdf', 'video/mp4', 'image/png', 'image/jpeg', 'audio/x-wav']; + $extensions = ['pdf', 'mp4', 'png', 'jpg', 'wav']; + $groups = [ + 'pdf' => 'pdf', + 'mp4' => 'video', + 'png' => 'image', + 'jpg' => 'image', + 'wav' => 'audio', + ]; + $sizes = [1, 5, 128, 256, 1024, 2048]; + $rand_type = $faker->numberBetween(0, 4); + return [ + 'user_id' => $faker->numberBetween(1, 200), + 'business_id' => $faker->numberBetween(1, 200), + 'project_id' => $faker->numberBetween(1, 200), + 'attached_to_id' => $faker->numberBetween(1, 100), + 'attached_to_table' => enum('tables.tasks.id'), + 'disk' => 's3', + 'original_name' => $faker->words(1, true), + 'name' => $faker->words(1, true), + 'extension' => $extension = $extensions[$rand_type], + 'mime' => $mimes[$rand_type], + 'group' => $groups[$extension], + 'size' => $sizes[$faker->numberBetween(0, 5)], + 'description' => $faker->text, + ]; +}); diff --git a/database/factories/FingerprintFactory.php b/database/factories/FingerprintFactory.php new file mode 100644 index 0000000..bbd8a79 --- /dev/null +++ b/database/factories/FingerprintFactory.php @@ -0,0 +1,38 @@ +define(Fingerprint::class, function () use ($faker) { + $os = [ + $faker->windowsPlatformToken, + $faker->linuxPlatformToken, + $faker->macPlatformToken + ]; + + $browsers = [ + $faker->firefox, + $faker->chrome, + $faker->opera, + $faker->safari, + ]; + + $detector = new Jenssegers\Agent\Agent(); + + return [ + 'user_id' => $faker->numberBetween(1, 1000), + 'agent' => $detector->browser(Arr::random($browsers)), + 'ip' => $faker->ipv4, + 'os' => $detector->platform(Arr::random($browsers)), + 'latitude' => $faker->latitude, + 'longitude' => $faker->longitude, + 'token' => Str::random(60), + ]; +}); diff --git a/database/factories/ProjectFactory.php b/database/factories/ProjectFactory.php new file mode 100644 index 0000000..6dd5c09 --- /dev/null +++ b/database/factories/ProjectFactory.php @@ -0,0 +1,23 @@ +define(Project::class, function (Faker $faker) { + return [ + 'business_id' => null, + 'name' => $name = $faker->words(3, true), + 'slug' => Str::slug($name), + 'private' => false, + 'budget' => 0, + 'start' => null, + 'finish' => null, + 'color' => $faker->colorName, + 'active' => rand(0, 1), + 'description' => $faker->paragraph, + ]; +}); diff --git a/database/factories/SprintflowFactory.php b/database/factories/SprintflowFactory.php new file mode 100644 index 0000000..ab520fb --- /dev/null +++ b/database/factories/SprintflowFactory.php @@ -0,0 +1,16 @@ +define(Sprint::class, function (Faker $faker) { + return [ + 'business_id' => null, + 'name' => $faker->randomElement(['scrum', 'printing', + 'agile', 'develop', 'design', 'writing', 'seo', 'sale']), + 'active' => rand(0, 1), + 'description' => $faker->paragraph, + ]; +}); diff --git a/database/factories/SystemFactory.php b/database/factories/SystemFactory.php new file mode 100644 index 0000000..0ea6223 --- /dev/null +++ b/database/factories/SystemFactory.php @@ -0,0 +1,16 @@ +define(System::class, function (Faker $faker) { + return [ + 'business_id' => null, + 'project_id' => null, + 'name' => $name = $faker->words(3, true), + ]; +}); diff --git a/database/factories/TagFactory.php b/database/factories/TagFactory.php new file mode 100644 index 0000000..d6779b4 --- /dev/null +++ b/database/factories/TagFactory.php @@ -0,0 +1,15 @@ +define(Tag::class, function () use ($faker) { + return [ + 'label' => $faker->colorName, + 'color' => $faker->colorName, + 'business_id' => null, + ]; +}); diff --git a/database/factories/TaskFactory.php b/database/factories/TaskFactory.php new file mode 100644 index 0000000..448b89e --- /dev/null +++ b/database/factories/TaskFactory.php @@ -0,0 +1,22 @@ +define(Task::class, function (Faker $faker) { + return [ + 'business_id' => null, + 'creator_id' => null, + 'project_id' => null, + 'user_id' => null, + 'workflow_id' => null, + 'name' => $faker->sentences(3, true), + 'time' => null, + 'cost' => 0, + 'completed' => false, + 'due_date' => Carbon::now()->toDateTimeString(), + ]; +}); diff --git a/database/factories/TransactionFactory.php b/database/factories/TransactionFactory.php new file mode 100644 index 0000000..a2f346b --- /dev/null +++ b/database/factories/TransactionFactory.php @@ -0,0 +1,21 @@ +define(Transaction::class, function (Faker $faker) { + $business_user = DB::selectOne('select business_id, user_id from business_user where level = 4 order by rand() limit 1'); + + return [ + 'user_id' => $business_user->user_id, + 'business_id' => $business_user->business_id, + 'amount' => random_int(1000, 9999), + 'succeeded' => $faker->boolean(), + 'options' => json_encode([]), + 'created_at' => Carbon::now()->subMinutes(random_int(1, 1000)), + ]; +}); diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 3510ed6..871ca9d 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -1,47 +1,16 @@ $this->faker->name, - 'email' => $this->faker->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. - * - * @return \Illuminate\Database\Eloquent\Factories\Factory - */ - public function unverified() - { - return $this->state(function (array $attributes) { - return [ - 'email_verified_at' => null, - ]; - }); - } -} +$factory->define(User::class, function (Faker $faker) { + return [ + 'name' => $faker->name, + 'email' => $faker->unique()->safeEmail, + 'mobile' => $faker->unique()->phoneNumber, + 'username' => $faker->unique()->userName, + 'password' => '$2y$10$l8jgLtb7RyDd7wbvxYPsuu7gjo/bLBkBYQhXnkpdmm.SVF3CT00UW', + ]; +}); diff --git a/database/factories/WorkflowFactory.php b/database/factories/WorkflowFactory.php new file mode 100644 index 0000000..72cde2f --- /dev/null +++ b/database/factories/WorkflowFactory.php @@ -0,0 +1,15 @@ +define(Workflow::class, function (Faker $faker) { + return [ + 'business_id' => null, + 'name' => $faker->randomElement(['scrum', 'printing', + 'agile', 'develop', 'design', 'writing', 'seo', 'sale']), + 'desc' => $faker->sentences(1, true), + ]; +}); diff --git a/database/factories/WorkstatusFactory.php b/database/factories/WorkstatusFactory.php new file mode 100644 index 0000000..3d2f791 --- /dev/null +++ b/database/factories/WorkstatusFactory.php @@ -0,0 +1,15 @@ +define(Status::class, function (Faker $faker) { + return [ + 'name' => $faker->randomElement(['idea', 'todo', + 'doing', 'done', 'pending', 'hold', 'logestik', 'sew']), + 'state' => rand(0, 3), + 'order' => rand(0, 10), + ]; +}); diff --git a/database/migrations/.gitkeep b/database/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/database/migrations/2019_08_19_000000_create_failed_jobs_table.php b/database/migrations/2019_08_19_000000_create_failed_jobs_table.php deleted file mode 100644 index 6aa6d74..0000000 --- a/database/migrations/2019_08_19_000000_create_failed_jobs_table.php +++ /dev/null @@ -1,36 +0,0 @@ -id(); - $table->string('uuid')->unique(); - $table->text('connection'); - $table->text('queue'); - $table->longText('payload'); - $table->longText('exception'); - $table->timestamp('failed_at')->useCurrent(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('failed_jobs'); - } -} diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2020_08_18_085016_create_users_table.php similarity index 62% rename from database/migrations/2014_10_12_000000_create_users_table.php rename to database/migrations/2020_08_18_085016_create_users_table.php index 621a24e..b656a71 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2020_08_18_085016_create_users_table.php @@ -17,10 +17,14 @@ class CreateUsersTable extends Migration $table->id(); $table->string('name'); $table->string('email')->unique(); - $table->timestamp('email_verified_at')->nullable(); + $table->string('mobile')->unique()->nullable(); + $table->string('username')->unique(); $table->string('password'); - $table->rememberToken(); - $table->timestamps(); + $table->boolean('active')->default(false); + $table->boolean('has_avatar')->default(false); + $table->timestamp('created_at')->nullable(); + $table->timestamp('updated_at')->useCurrent(); + $table->timestamp('deleted_at')->nullable(); }); } diff --git a/database/migrations/2020_08_18_085017_fingerprints.php b/database/migrations/2020_08_18_085017_fingerprints.php new file mode 100644 index 0000000..67bd1ee --- /dev/null +++ b/database/migrations/2020_08_18_085017_fingerprints.php @@ -0,0 +1,38 @@ +id(); + $table->unsignedBigInteger('user_id'); + $table->string('agent'); + $table->ipAddress('ip'); + $table->string('os'); + $table->decimal('latitude', 10, 2); + $table->decimal('longitude', 11, 2); + $table->char('token', 60)->unique(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('fingerprints'); + } +} diff --git a/database/migrations/2020_08_18_085018_create_businesses_table.php b/database/migrations/2020_08_18_085018_create_businesses_table.php new file mode 100644 index 0000000..e37d713 --- /dev/null +++ b/database/migrations/2020_08_18_085018_create_businesses_table.php @@ -0,0 +1,49 @@ +id(); + $table->string('name'); + $table->string('slug')->unique(); + $table->integer('wallet')->default(0); + $table->unsignedInteger('files_volume')->default(0); + $table->string('color')->nullable(); + $table->string('description')->nullable(); + $table->json('cache')->nullable(); + $table->boolean('has_avatar')->default(false); + $table->timestamp('calculated_at')->nullable(); + $table->timestamp('created_at')->nullable(); + $table->timestamp('updated_at')->nullable(); + $table->timestamp('deleted_at')->nullable(); + }); + + Schema::create('business_user', function (Blueprint $table) { + $table->unsignedBigInteger('business_id'); + $table->unsignedBigInteger('user_id'); + $table->tinyInteger('level')->default(0); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('businesses'); + Schema::dropIfExists('businesses_user'); + } +} diff --git a/database/migrations/2020_08_18_085046_create_projects_table.php b/database/migrations/2020_08_18_085046_create_projects_table.php new file mode 100644 index 0000000..4b40f42 --- /dev/null +++ b/database/migrations/2020_08_18_085046_create_projects_table.php @@ -0,0 +1,58 @@ +id(); + $table->unsignedBigInteger('business_id'); + $table->string('name'); + $table->string('slug'); + $table->boolean('private')->default(false); + $table->unsignedBigInteger('budget')->default(0); + $table->string('color')->nullable(); + $table->boolean('active')->nullable(); + $table->text('description')->nullable(); + $table->boolean('has_avatar')->default(false); + + $table->timestamp('start')->nullable(); + $table->timestamp('finish')->nullable(); + + $table->timestamp('created_at')->nullable(); + $table->timestamp('updated_at')->useCurrent(); + $table->timestamp('deleted_at')->nullable(); + + }); + + // Only those users that added directly to the project are stored here. + // Users who are members of the business have access to the projects of that business + // without being stored here. + Schema::create('project_user', function (Blueprint $table) { + $table->unsignedBigInteger('project_id'); + $table->unsignedBigInteger('user_id'); + $table->tinyInteger('level')->default(0); + }); + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('projects'); + Schema::dropIfExists('project_user'); + } +} diff --git a/database/migrations/2014_10_12_100000_create_password_resets_table.php b/database/migrations/2020_08_18_085054_create_workflows_table.php similarity index 53% rename from database/migrations/2014_10_12_100000_create_password_resets_table.php rename to database/migrations/2020_08_18_085054_create_workflows_table.php index 0ee0a36..d998c40 100644 --- a/database/migrations/2014_10_12_100000_create_password_resets_table.php +++ b/database/migrations/2020_08_18_085054_create_workflows_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreatePasswordResetsTable extends Migration +class CreateWorkflowsTable extends Migration { /** * Run the migrations. @@ -13,10 +13,13 @@ class CreatePasswordResetsTable extends Migration */ public function up() { - Schema::create('password_resets', function (Blueprint $table) { - $table->string('email')->index(); - $table->string('token'); + Schema::create('workflows', function (Blueprint $table) { + $table->id(); + $table->unsignedBigInteger('business_id'); + $table->string('name'); + $table->string('desc')->nullable(); $table->timestamp('created_at')->nullable(); + $table->timestamp('updated_at')->useCurrent(); }); } @@ -27,6 +30,6 @@ class CreatePasswordResetsTable extends Migration */ public function down() { - Schema::dropIfExists('password_resets'); + Schema::dropIfExists('workflows'); } } diff --git a/database/migrations/2020_08_18_085102_create_statuses_table.php b/database/migrations/2020_08_18_085102_create_statuses_table.php new file mode 100644 index 0000000..03c4203 --- /dev/null +++ b/database/migrations/2020_08_18_085102_create_statuses_table.php @@ -0,0 +1,39 @@ +id(); + $table->unsignedBigInteger('business_id'); + $table->unsignedBigInteger('workflow_id'); + $table->string('name'); + $table->string('state')->default(enum('status.states.inactive.id')); + $table->unsignedSmallInteger('order')->default(0); + $table->timestamp('created_at')->nullable(); + $table->timestamp('updated_at')->useCurrent(); + }); + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('statuses'); +// Schema::dropIfExists('status_workflow'); + } +} diff --git a/database/migrations/2020_08_18_085114_create_tags_table.php b/database/migrations/2020_08_18_085114_create_tags_table.php new file mode 100644 index 0000000..39a8e9b --- /dev/null +++ b/database/migrations/2020_08_18_085114_create_tags_table.php @@ -0,0 +1,41 @@ +id(); + $table->string('label'); + $table->string('color')->nullable(); + $table->unsignedBigInteger('business_id'); + $table->timestamp('created_at')->nullable(); + $table->timestamp('updated_at')->useCurrent(); + }); + + Schema::create('tag_task', function (Blueprint $table) { + $table->unsignedBigInteger('tag_id'); + $table->unsignedBigInteger('task_id'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('tags'); + Schema::dropIfExists('tag_task'); + } +} diff --git a/database/migrations/2020_08_28_095802_create_systems_table.php b/database/migrations/2020_08_28_095802_create_systems_table.php new file mode 100644 index 0000000..32fbb14 --- /dev/null +++ b/database/migrations/2020_08_28_095802_create_systems_table.php @@ -0,0 +1,34 @@ +id(); + $table->unsignedBigInteger('business_id'); + $table->unsignedBigInteger('project_id'); + $table->string('name'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('systems'); + } +} diff --git a/database/migrations/2020_08_28_101545_create_sprint_table.php b/database/migrations/2020_08_28_101545_create_sprint_table.php new file mode 100644 index 0000000..9a73d99 --- /dev/null +++ b/database/migrations/2020_08_28_101545_create_sprint_table.php @@ -0,0 +1,38 @@ +id(); + $table->unsignedBigInteger('business_id'); + $table->unsignedBigInteger('project_id'); + $table->string('name'); + $table->text('description')->nullable(); + $table->date('started_at'); + $table->date('ended_at'); + $table->boolean('active')->default(true); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('sprints'); + } +} diff --git a/database/migrations/2020_10_31_182018_create_transactions_table.php b/database/migrations/2020_10_31_182018_create_transactions_table.php new file mode 100644 index 0000000..5fa18e5 --- /dev/null +++ b/database/migrations/2020_10_31_182018_create_transactions_table.php @@ -0,0 +1,37 @@ +bigInteger('id', true, true); + $table->bigInteger('user_id', false, true); + $table->bigInteger('business_id', false, true); + $table->integer('amount', false, true); + $table->boolean('succeeded')->default(false); + $table->json('options')->nullable(); + $table->timestamp('created_at')->nullable(); + $table->timestamp('updated_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('transactions'); + } +} diff --git a/database/migrations/2021_09_03_085114_create_costs_table.php b/database/migrations/2021_09_03_085114_create_costs_table.php new file mode 100644 index 0000000..87768ec --- /dev/null +++ b/database/migrations/2021_09_03_085114_create_costs_table.php @@ -0,0 +1,41 @@ +id(); + $table->unsignedBigInteger('business_id'); + $table->string('type'); + $table->date('month'); + $table->unsignedInteger('amount'); + $table->unsignedInteger('fee')->default(0); + $table->unsignedInteger('duration'); + $table->unsignedInteger('cost')->storedAs('fee*duration'); + $table->unsignedFloat('tax', 8, 2)->storedAs('(cost/100)*9'); + $table->json('additional')->nullable(); + $table->timestamp('created_at')->nullable(); + $table->timestamp('updated_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('costs'); + } +} diff --git a/database/migrations/2022_10_13_085114_create_files_table.php b/database/migrations/2022_10_13_085114_create_files_table.php new file mode 100644 index 0000000..69dfec8 --- /dev/null +++ b/database/migrations/2022_10_13_085114_create_files_table.php @@ -0,0 +1,45 @@ +id(); + $table->unsignedBigInteger('user_id'); + $table->unsignedBigInteger('business_id'); + $table->unsignedBigInteger('project_id'); + $table->unsignedBigInteger('attached_to_id')->nullable(); + $table->integer('attached_to_table')->nullable(); + $table->char('disk',191); + $table->char('original_name',191); + $table->char('name',191); + $table->char('extension',4); + $table->string('mime'); + $table->string('group',255); + $table->char('size',191); + $table->text('description')->nullable(); + $table->timestamp('created_at')->nullable(); + $table->timestamp('updated_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('files'); + } +} diff --git a/database/migrations/2023_10_13_085115_create_files_relation_table.php b/database/migrations/2023_10_13_085115_create_files_relation_table.php new file mode 100644 index 0000000..8308d77 --- /dev/null +++ b/database/migrations/2023_10_13_085115_create_files_relation_table.php @@ -0,0 +1,35 @@ +id(); + $table->unsignedBigInteger('file_id'); + $table->unsignedBigInteger("resource_id"); + $table->string("resource_type"); + // the person who create this relation. eg attacher + $table->unsignedBigInteger('user_id'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('files_relation'); + } +} diff --git a/database/migrations/2023_10_14_085115_create_media_table.php.php b/database/migrations/2023_10_14_085115_create_media_table.php.php new file mode 100644 index 0000000..d0ac271 --- /dev/null +++ b/database/migrations/2023_10_14_085115_create_media_table.php.php @@ -0,0 +1,31 @@ +bigIncrements('id'); + + $table->morphs('model'); + $table->uuid('uuid')->nullable(); + $table->string('collection_name'); + $table->string('name'); + $table->string('file_name'); + $table->string('mime_type')->nullable(); + $table->string('disk'); + $table->string('conversions_disk')->nullable(); + $table->unsignedBigInteger('size'); + $table->json('manipulations'); + $table->json('custom_properties'); + $table->json('responsive_images'); + $table->unsignedInteger('order_column')->nullable(); + + $table->nullableTimestamps(); + }); + } +} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php deleted file mode 100644 index 57b73b5..0000000 --- a/database/seeders/DatabaseSeeder.php +++ /dev/null @@ -1,18 +0,0 @@ -create(); - } -} diff --git a/database/seeds/BusinessSeeder.php b/database/seeds/BusinessSeeder.php new file mode 100644 index 0000000..f622594 --- /dev/null +++ b/database/seeds/BusinessSeeder.php @@ -0,0 +1,144 @@ +raw()); + $projects = []; + $systems = []; + $business_user = []; + $project_user = []; + $project_id = 0; + for ($business_id=1; $business_id <= 2000; $business_id++) { + // distinct user ids + $user_ids = []; + $added_user = []; + for ($i=0; $i < 10; $i++) $user_ids [] = rand(1, 5000); + $user_ids = array_values(array_unique($user_ids)); + // add 1 to 7 member + for ($i=0; $i < rand(1, 8); $i++) { + $added_user[] = $user_ids[$i]; + $business_user[] = [ + 'business_id' => $business_id, + 'user_id' => $user_ids[$i], + 'level' => $i == 0? 4: rand(0, 4), + ]; + } + + $business_projects = factory(Project::class, rand(1, 3))->raw(); + foreach ($business_projects as $project) { + $project['business_id'] = $business_id; + $projects[] = $project; + $project_id++; + + for ($i=0; $i < rand(0, 2); $i++) { + if ($added_user[$i] ?? false) { + $project_user[] = [ + 'project_id' => $project_id, + 'user_id' => $added_user[$i], + 'level' => rand(0, 4), + ]; + } + } + + for ($i=0; $i < rand(1, 5); $i++) { + $systems[] = factory(System::class)->raw([ + 'project_id' => $project_id, + 'business_id' => $business_id, + ]); + } + } + + // for ($i=0; $i < rand(1, 3); $i++) { + // // $project = + // } + // $business_user[] = [ + // 'business_id' => $business_id, + // 'user_id' => 1, + // 'owner' => true, + // ]; + } + DB::table('business_user')->insert($business_user); + Project::insert($projects); + DB::table('project_user')->insert($project_user); + DB::table('systems')->insert($systems); + /** + * Every business has one or more owners, which might be the owner of other business as well + */ + // $this->insertAdmins($business_ids, $owners); + + + /** + * Every business has one or more members, which might be the member of other business as well + */ + // $this->insertMembers($business_ids); + } + + /** + * @param $business_ids + * @param Collection $owners + * @return array + */ + public function insertAdmins($business_ids, Collection $owners) + { + $relations = []; + foreach ($business_ids as $id) { + $relations[] = [ + 'business_id' => $id, + 'user_id' => $owners->random()->id, + 'owner' => true, + ]; + } + + // Specify the percentage of managers who have two or more businesses + $multiple = ceil(count($relations) / 100 * 30); + foreach (Arr::random($relations, $multiple) as $relation) { + $relations[] = [ + 'business_id' => $relation['business_id'], + 'user_id' => $owners->except($relation['user_id'])->random()->id, + 'owner' => true, + ]; + } + + DB::table('business_user')->insert($relations); + } + + /** + * @param $business_ids + */ + public function insertMembers($business_ids): void + { + /** @var Collection $member_ids */ + $member_ids = User::whereDoesntHave('businesses')->select('id')->pluck('id'); + $relations = []; + $current = []; + foreach ($member_ids as $index => $id) { + $relations[] = [ + 'business_id' => $business = $business_ids->random(), + 'user_id' => $id, + ]; + + $current[$business][] = $index; + } + + $multiple = ceil(count($relations) / 100 * 20); + foreach (Arr::random($relations, $multiple) as $relation) { + $relations[] = [ + 'business_id' => $relation['business_id'], + 'user_id' => $member_ids->except($current[$relation['business_id']])->random(), + ]; + } + + DB::table('business_user')->insert($relations); + } +} diff --git a/database/seeds/CostSeeder.php b/database/seeds/CostSeeder.php new file mode 100644 index 0000000..5513efa --- /dev/null +++ b/database/seeds/CostSeeder.php @@ -0,0 +1,14 @@ +raw() + ); + } +} diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php new file mode 100644 index 0000000..959a0d6 --- /dev/null +++ b/database/seeds/DatabaseSeeder.php @@ -0,0 +1,24 @@ +raw()); + $this->call([ + UserSeeder::class, + BusinessSeeder::class, + TagSeeder::class, + WorkflowSeeder::class, + SprintSeeder::class, + TransactionSeeder::class, + CostSeeder::class, + // ProjectSeeder::class, + // TaskSeeder::class, + // FileSeeder::class + ]); + } +} diff --git a/database/seeds/FileSeeder.php b/database/seeds/FileSeeder.php new file mode 100644 index 0000000..e5f927a --- /dev/null +++ b/database/seeds/FileSeeder.php @@ -0,0 +1,13 @@ +raw(); + } +} diff --git a/database/seeds/ProjectSeeder.php b/database/seeds/ProjectSeeder.php new file mode 100644 index 0000000..5c91c26 --- /dev/null +++ b/database/seeds/ProjectSeeder.php @@ -0,0 +1,123 @@ +pluck('id'); + + /** + * One level projects + */ + $this->insertMainProjects($businesses); + + /** + * Multi level projects + * Be careful with private projects + */ + $this->insertChildProjects(); + + $this->insertGrandChildrenProjects(); + + /** + * Assign people to the projects + * * Be careful with private projects + */ + $this->assignPeopleToProjects(); + } + + /** + * @param $businesses + * @return void + */ + public function insertMainProjects($businesses): void + { + $projects = []; + foreach ($businesses as $business) { + $projects[] = factory(Project::class, 5)->raw([ + 'business_id' => $business, + 'private' => rand(1, 100) <= 10, + ]); + } + DB::table('projects')->insertOrIgnore(Arr::collapse($projects)); + } + + /** + * @return void + */ + public function insertChildProjects(): void + { + $projects = Project::inRandomOrder()->select('id', 'business_id')->take(100)->get()->toArray(); + $child_projects = []; + foreach ($projects as $project) { + $child_projects[] = factory(Project::class)->raw([ + 'parent_id' => $project['id'], + 'business_id' => $project['business_id'], + 'private' => rand(1, 100) <= 10, + ]); + } + DB::table('projects')->insert($child_projects); + } + + public function insertGrandChildrenProjects(): void + { + $projects = Project::inRandomOrder() + ->select('id', 'business_id', 'parent_id') + ->whereNotNull('parent_id') + ->take(25)->get()->toArray(); + $grand_child_projects = []; + foreach ($projects as $project) { + $grand_child_projects[] = factory(Project::class)->raw([ + 'parent_id' => $project['id'], + 'business_id' => $project['business_id'], + 'private' => rand(1, 100) <= 10, + ]); + } + DB::table('projects')->insertOrIgnore($grand_child_projects); + } + + public function assignPeopleToProjects(): void + { + // Schema::create('') + // $table->unsignedBigInteger('project_id'); + // $table->unsignedBigInteger(''); + + $project_members = []; + $projects = Project::with('parent','children','business')->get(); + foreach ($projects as $project) { + // detect the main projects + if ($project->children->isNotEmpty()) { + continue; + } + + $business_owner = $project->business->owners->random(); + $business_members = $project->business->members->random($project->business->members->count() - 1); + $project_members[] = [ + 'project_id' => $project->id, + 'user_id' => $business_owner->id, + ]; + + foreach ($business_members as $business_member) { + $project_members[] = [ + 'project_id' => $project->id, + 'user_id' => $business_member->id, + ]; + } + + // todo : how to detect a project has sub project + // child + // grand child + } + DB::table('project_user')->insert($project_members); + } +} diff --git a/database/seeds/SprintSeeder.php b/database/seeds/SprintSeeder.php new file mode 100644 index 0000000..6094e9a --- /dev/null +++ b/database/seeds/SprintSeeder.php @@ -0,0 +1,21 @@ +raw([ + 'business_id' => $business_id, + 'project_id' => rand(1, 4027), + ]); + } + } + DB::table('sprints')->insertOrIgnore($sprints); + } +} diff --git a/database/seeds/TagSeeder.php b/database/seeds/TagSeeder.php new file mode 100644 index 0000000..c15eb0e --- /dev/null +++ b/database/seeds/TagSeeder.php @@ -0,0 +1,22 @@ +raw([ + 'business_id' => $business_id, + ]); + } + } + DB::table('tags')->insertOrIgnore($tags); + } +} diff --git a/database/seeds/TaskSeeder.php b/database/seeds/TaskSeeder.php new file mode 100644 index 0000000..9b148bd --- /dev/null +++ b/database/seeds/TaskSeeder.php @@ -0,0 +1,62 @@ +get(); + $tasks = []; + + $left = count($businesses); + $now = Carbon::now()->toDateTimeString(); + $future = Carbon::now()->addDays(10)->toDateTimeString(); + foreach ($businesses as $business) { + foreach ($business->owners as $owner) { + foreach ($business->projects as $project) { + foreach ($business->members as $member) { + for ($i = 1; $i <= 30; $i++) { + foreach ($business->workflows as $workflow) { + $status = $workflow->workstatuses->random(); + $tasks[] = [ + 'business_id' => $business->id, +// 'creator_id' => $owner->id, +// 'project_id' => $project->id, +// 'user_id' => $member->id, +// 'workflow_id' => $workflow->id, +// 'work_status_id' => $status->id, +// 'name' => 'Task #' . rand(111111, 999999), +// 'time' => "10:00:00", +// 'cost' => 10000, +// 'completed' => $status->done, +// 'due_date' => $status->done ? $now : $future, + ]; + } + } + } + } + } + + $this->command->info(--$left . " Business is left."); + } + + dd('here'); + $chunks = array_chunk($tasks, 1000); + $number = count($chunks); + foreach ($chunks as $value) { + DB::table('tasks')->insert($value); + $this->command->info(--$number . " Chunk is left."); + } + } +} diff --git a/database/seeds/TransactionSeeder.php b/database/seeds/TransactionSeeder.php new file mode 100644 index 0000000..a25d5d8 --- /dev/null +++ b/database/seeds/TransactionSeeder.php @@ -0,0 +1,14 @@ +raw() + ); + } +} diff --git a/database/seeds/UserSeeder.php b/database/seeds/UserSeeder.php new file mode 100644 index 0000000..c3e67d9 --- /dev/null +++ b/database/seeds/UserSeeder.php @@ -0,0 +1,20 @@ +raw() + ); + Fingerprint::insert( + factory(Fingerprint::class, 5000)->raw() + ); + User::where('id', 1)->update(['mobile' => '09123456789']); + } +} diff --git a/database/seeds/WorkflowSeeder.php b/database/seeds/WorkflowSeeder.php new file mode 100644 index 0000000..893b58c --- /dev/null +++ b/database/seeds/WorkflowSeeder.php @@ -0,0 +1,51 @@ +raw([ + 'business_id' => $business_id, + ]); + $business_workflows[] = ++$workflow_inc; + for ($i=0; $i < rand(1, 4); $i++) { + $statuses[] = factory(Status::class)->raw([ + 'business_id' => $business_id, + 'workflow_id' => $workflow_inc, + ]); + $status_inc++; + } + } +// for ($i=0; $i < rand(1, 4); $i++) { +// $statuses[] = factory(Status::class)->raw([ +// 'business_id' => $business_id, +// ]); +// $status_inc++; +// for ($ws=0; $ws < rand(0, count($business_workflows)); $ws++) { +// $status_workflow[] = [ +// 'status_id' => $status_inc, +// 'workflow_id' => $business_workflows[rand(0, count($business_workflows)-1)], +// 'order' => rand(0, 10) +// ]; +// } +// } + } + DB::table('workflows')->insert($workflows); + DB::table('statuses')->insert($statuses); +// DB::table('status_workflow')->insert($status_workflow); + } +} diff --git a/routes/api.php b/routes/api.php index bcb8b18..618384b 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,19 +1,165 @@ get('/user', function (Request $request) { - return $request->user(); +/** @var \Laravel\Lumen\Routing\Router $router */ + +$router->group(['prefix' => 'actions'], function () use ($router) { + $router->group(['prefix' => 'businesses'], function () use ($router) { + $router->group(['prefix' => '{business}', 'middleware' => 'bindBusiness'], function () use ($router) { + $router->get('/info', 'BusinessController@info'); + }); + }); +}); + +$router->group(['prefix' => 'auth'], function () use ($router) { + $router->get('/', 'AuthController@auth'); + $router->delete('/', 'AuthController@delete'); + $router->get('/info', 'AuthController@authWithInfo'); + $router->post('login', 'AuthController@login'); + $router->post('logout', 'AuthController@logout'); + $router->post('register', 'AuthController@register'); + $router->post('revoke/{token}', 'AuthController@revoke'); + + $router->post('forget-password', 'AuthController@forgetPassword'); + $router->post('update-password', 'AuthController@updatePassword'); + + $router->post('verification', 'AuthController@verification'); + + $router->get('google/redirect', 'AuthController@redirectToGoogle'); + $router->get('google/callback', 'AuthController@handleGoogleCallback'); +}); + + + +$router->group(['prefix' => 'businesses'], function () use ($router) { + $router->get('/', 'BusinessController@index'); + $router->post('/', 'BusinessController@store'); + + $router->group(['prefix' => '{business}', 'middleware' => 'bindBusiness'], function () use ($router) { + + + $router->put('/avatar', 'BusinessController@setAvatar'); + $router->delete('/avatar', 'BusinessController@unSetAvatar'); + + $router->get('/', 'BusinessController@show'); + $router->put('/', 'BusinessController@update'); + $router->delete('/', 'BusinessController@delete'); + $router->get('/restore', 'BusinessController@restore'); + + $router->get('/files', 'FileController@index'); + $router->get('/info', 'BusinessController@info'); + $router->get('/invoices', 'InvoiceController@index'); + $router->get('/invoices/{date}', 'InvoiceController@show'); + $router->get('/pay', 'CreditController@pay'); + $router->get('/payments', 'CreditController@payments'); + + + $router->group(['prefix' => 'projects'], function () use ($router) { + $router->get('/', 'ProjectController@index'); + $router->post('/', 'ProjectController@store'); + $router->group(['prefix' => '{project}'], function () use ($router) { + + $router->put('/avatar', 'ProjectController@setAvatar'); + $router->delete('/avatar', 'ProjectController@unSetAvatar'); + + $router->get('/', 'ProjectController@show'); + $router->put('/', 'ProjectController@update'); + $router->delete('/', 'ProjectController@delete'); + $router->group(['prefix' => 'files', 'as' => 'file.', 'middleware' => 'bindBusiness'], function () use ($router) { + // $router->get('/', ['as' => 'index', 'uses' => 'FileController@index']); + $router->post('/', ['as' => 'store', 'uses' => 'FileController@store']); + $router->group(['prefix' => '{file}'], function () use ($router) { + $router->get('/', ['as' => 'download', 'uses' => 'FileController@download']); + $router->put('/', ['as' => 'rename', 'uses' => 'FileController@rename']); + $router->delete('/', ['as' => 'delete', 'uses' => 'FileController@delete']); + }); + }); + $router->get('/restore', 'ProjectController@restore'); + + $router->group(['prefix' => 'sprints', 'as' => 'sprint.', 'middleware' => 'bindBusiness'], function () use ($router) { + $router->get('/', ['as' => 'index', 'uses' => 'SprintController@index']); + $router->post('/', ['as' => 'store', 'uses' => 'SprintController@store']); + $router->group(['prefix' => '{sprint}'], function () use ($router) { + $router->get('/', ['as' => 'show', 'uses' => 'SprintController@show']); + $router->put('/', ['as' => 'update', 'uses' => 'SprintController@update']); + $router->delete('/', ['as' => 'delete', 'uses' => 'SprintController@delete']); + }); + }); + + $router->group(['prefix' => 'systems', 'middleware' => 'bindBusiness'], function () use ($router) { + $router->get('/', 'SystemController@index'); + $router->post('/', 'SystemController@store'); + $router->group(['prefix' => '{system}'], function () use ($router) { + $router->get('/', 'SystemController@show'); + $router->put('/', 'SystemController@update'); + $router->delete('/', 'SystemController@delete'); + }); + }); + + $router->group(['prefix' => 'tasks/{task}/files', 'middleware' => 'bindBusiness'], function () use ($router) { + $router->get('/', ['uses' => 'TaskFileController@index']); + $router->post('/', ['uses' => 'TaskFileController@sync']); + $router->get('/{file}', ['uses' => 'TaskFileController@download']); + }); + + $router->group(['prefix' => 'users'], function () use ($router){ + $router->post('/', 'ProjectController@storeOrUpdateUser'); + $router->group(['prefix' => '{user}'], function () use ($router) { + $router->delete('/', 'ProjectController@deleteUser'); + }); + }); + + }); + }); + + $router->group(['prefix' => 'tags', 'as' => 'tag.', 'middleware' => 'bindBusiness'], function () use ($router) { + $router->get('/', ['as' => 'index', 'uses' => 'TagController@index']); + $router->post('/', ['as' => 'store', 'uses' => 'TagController@store']); + $router->group(['prefix' => '{tag}'], function () use ($router) { + $router->get('/', ['as' => 'show', 'uses' => 'TagController@show']); + $router->put('/', ['as' => 'update', 'uses' => 'TagController@update']); + $router->delete('/', ['as' => 'delete', 'uses' => 'TagController@delete']); + }); + }); + + $router->group(['prefix' => 'workflows', 'as' => 'workflow.', 'middleware' => 'bindBusiness'], function () use ($router) { + $router->get('/', ['as' => 'index', 'uses' => 'WorkflowController@index']); + $router->post('/', ['as' => 'store', 'uses' => 'WorkflowController@store']); + $router->group(['prefix' => '{workflow}'], function () use ($router) { + $router->get('/', ['as' => 'show', 'uses' => 'WorkflowController@show']); + $router->put('/', ['as' => 'update', 'uses' => 'WorkflowController@update']); + $router->delete('/', ['as' => 'delete', 'uses' => 'WorkflowController@delete']); + $router->group(['prefix' => 'statuses', 'middleware' => 'bindBusiness'], function () use ($router) { + $router->get('/', 'StatusController@index'); + $router->post('/', 'StatusController@store'); + $router->group(['prefix' => '{status}'], function () use ($router) { + $router->get('/', 'StatusController@show'); + $router->put('/', 'StatusController@update'); + $router->delete('/', ['as' => 'delete', 'uses' => 'StatusController@delete']); + }); + }); + }); + }); + + $router->group(['prefix' => 'users'], function () use ($router){ + $router->post('/', 'BusinessController@storeOrUpdateUser'); + $router->group(['prefix' => '{user}'], function () use ($router) { + $router->delete('/', 'BusinessController@deleteUser'); + }); + }); + }); +}); + +$router->get('/callback', 'CreditController@callback'); +$router->get('/{transaction}/redirection', 'CreditController@redirection'); + +$router->group(['prefix' => 'users'], function () use ($router) { + $router->get('/', 'UserController@index'); + $router->get('/search', 'UserController@search'); + $router->group(['prefix' => '{user}'], function () use ($router) { + $router->get('/', 'UserController@show'); + $router->put('/', 'UserController@update'); + + $router->put('/avatar', 'UserController@setAvatar'); + $router->delete('/avatar', 'UserController@unSetAvatar'); + }); });