diff --git a/.env.example b/.env.example index 89de920f8..442eb81f4 100644 --- a/.env.example +++ b/.env.example @@ -68,6 +68,8 @@ PREVENT_ACCESSING_MISSING_ATTRIBUTES=false PRINT_COST_ONESIDED=8 PRINT_COST_TWOSIDED=12 PRINTER_NAME=NemUjBela +PRINTER_IP= +PRINTER_PORT= NETREG=1000 KKT=2000 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..9dc6b4df6 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,48 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Listen for Xdebug", + "type": "php", + "request": "launch", + "port": 9003 + }, + { + "name": "Launch currently open script", + "type": "php", + "request": "launch", + "program": "${file}", + "cwd": "${fileDirname}", + "port": 0, + "runtimeArgs": [ + "-dxdebug.start_with_request=yes" + ], + "env": { + "XDEBUG_MODE": "debug,develop", + "XDEBUG_CONFIG": "client_port=${port}" + } + }, + { + "name": "Launch Built-in web server", + "type": "php", + "request": "launch", + "runtimeArgs": [ + "-dxdebug.mode=debug", + "-dxdebug.start_with_request=yes", + "-S", + "localhost:0" + ], + "program": "", + "cwd": "${workspaceRoot}", + "port": 9003, + "serverReadyAction": { + "pattern": "Development Server \\(http://localhost:([0-9]+)\\) started", + "uriFormat": "http://localhost:%s", + "action": "openExternally" + } + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..942c363bc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "julia.environmentPath": "c:\\Users\\sszajbely\\mars" +} \ No newline at end of file diff --git a/app/Console/Commands.php b/app/Console/Commands.php index 6af3de083..fe993f36c 100644 --- a/app/Console/Commands.php +++ b/app/Console/Commands.php @@ -3,6 +3,7 @@ namespace App\Console; use Illuminate\Support\Facades\Log; +use Symfony\Component\Process\Process; /** * Collection of exec commands. @@ -15,65 +16,15 @@ private static function isDebugMode() return config('app.debug'); } - public static function getCompletedPrintingJobs() - { - $command = "lpstat -W completed -o " . config('print.printer_name') . " | awk '{print $1}'"; - if (self::isDebugMode()) { - $result = [0]; - } else { - $result = []; - exec($command, $result); - } - Log::info([$command, $result]); - return $result; - } - - public static function print($command) - { - if (self::isDebugMode()) { - $job_id = 0; - $result = "request id is " . config('print.printer_name') . "-" . $job_id . " (1 file(s))"; - } else { - $result = exec($command); - } - Log::info([$command, $result]); - return $result; - } - - public static function cancelPrintJob(string $jobID) - { - $command = "cancel " . $jobID; - if (self::isDebugMode()) { - // cancel(1) exits with status code 0 if it succeeds - $result = ['output' => '', 'exit_code' => 0]; - } else { - $output = exec($command, $result, $exit_code); - $result = ['output' => $output, 'exit_code' => $exit_code]; - } - Log::info([$command, $result]); - return $result; - } - - public static function getPages($path) - { - $command = "pdfinfo " . $path . " | grep '^Pages' | awk '{print $2}' 2>&1"; - if (self::isDebugMode()) { - $result = rand(1, 10); - } else { - $result = exec($command); - } - Log::info([$command, $result]); - return $result; - } - public static function pingRouter($router) { if (self::isDebugMode()) { $result = rand(1, 10) > 9 ? "error" : ''; } else { // This happens too often to log. - $command = "ping " . $router->ip . " -c 1 | grep 'error\|unreachable'"; - $result = exec($command); + $process = new Process(['ping', $router->ip, '-c', '1', '|', 'grep', "'error\|unreachable'"]); + $process->run(); + $result = $process->getOutput(); } return $result; } @@ -83,9 +34,9 @@ public static function latexToPdf($path, $outputDir) if (self::isDebugMode()) { $result = "ok"; } else { - $command = "pdflatex " . "-interaction=nonstopmode -output-dir " . $outputDir . " " . $path . " 2>&1"; - Log::info($command); - $result = exec($command); + $process = new Process(['pdflatex', '-interaction=nonstopmode', '-output-dir', $outputDir, $path]); + $process->run(); + $result = $process->getOutput(); } return $result; } diff --git a/app/Enums/PrintJobStatus.php b/app/Enums/PrintJobStatus.php new file mode 100644 index 000000000..e64d38d0b --- /dev/null +++ b/app/Enums/PrintJobStatus.php @@ -0,0 +1,10 @@ + $data['email'], 'password' => Hash::make($data['password']), ]); - - $user->roles()->attach(Role::firstWhere('name', Role::PRINTER)->id); $user->roles()->attach(Role::firstWhere('name', $data['user_type'])->id); if ($data['user_type'] == Role::TENANT) { diff --git a/app/Http/Controllers/Dormitory/PrintController.php b/app/Http/Controllers/Dormitory/PrintController.php deleted file mode 100644 index 94efac942..000000000 --- a/app/Http/Controllers/Dormitory/PrintController.php +++ /dev/null @@ -1,323 +0,0 @@ -middleware('can:use,App\Models\PrintAccount'); - } - - public function index() - { - return view('dormitory.print.app', [ - "users" => User::printers(), - "free_pages" => user()->sumOfActiveFreePages() - ]); - } - - public function noPaper() - { - $reporterName = user()->name; - $admins = User::withRole(Role::SYS_ADMIN)->get(); - foreach ($admins as $admin) { - Mail::to($admin)->send(new NoPaper($admin->name, $reporterName)); - } - Cache::put('print.no-paper', now(), 3600); - return redirect()->back()->with('message', __('mail.email_sent')); - } - - public function addedPaper() - { - $this->authorize('handleAny', PrintAccount::class); - - Cache::forget('print.no-paper'); - return redirect()->back()->with('message', __('general.successful_modification')); - } - - public function admin() - { - $this->authorize('handleAny', PrintAccount::class); - - return view('dormitory.print.manage.app', ["users" => User::printers()]); - } - - public function print(Request $request) - { - $validator = Validator::make($request->all(), [ - 'file_to_upload' => 'required|file|mimes:pdf|max:' . config('print.pdf_size_limit'), - 'number_of_copies' => 'required|integer|min:1' - ]); - $validator->validate(); - - $is_two_sided = $request->has('two_sided'); - $number_of_copies = $request->number_of_copies; - $use_free_pages = $request->use_free_pages; - $file = $request->file_to_upload; - $filename = $file->getClientOriginalName(); - $path = $this->storeFile($file); - - $printer = new Printer($filename, $path, $use_free_pages, $is_two_sided, $number_of_copies); - - return $printer->print(); - } - - public function transferBalance(Request $request) - { - $validator = Validator::make($request->all(), [ - 'balance' => 'required|integer|min:1', - 'user_to_send' => 'required|integer|exists:users,id' - ]); - $validator->validate(); - - $balance = $request->balance; - $user = User::find($request->user_to_send); - $from_account = user()->printAccount; - $to_account = $user->printAccount; - - if (!$from_account->hasEnoughMoney($balance)) { - return $this->handleNoBalance(); - } - $to_account->update(['last_modified_by' => user()->id]); - $from_account->update(['last_modified_by' => user()->id]); - - $from_account->decrement('balance', $balance); - $to_account->increment('balance', $balance); - - // Send notification mail - Mail::to($user)->queue(new ChangedPrintBalance($user, $balance, user()->name)); - - return redirect()->back()->with('message', __('general.successful_transaction')); - } - - public function modifyBalance(Request $request) - { - $validator = Validator::make($request->all(), [ - 'user_id_modify' => 'required|integer|exists:users,id', - 'balance' => 'required|integer', - ]); - $validator->validate(); - - $balance = $request->balance; - $user = User::find($request->user_id_modify); - $print_account = $user->printAccount; - - $this->authorize('modify', $print_account); - - if ($balance < 0 && !$print_account->hasEnoughMoney($balance)) { - return $this->handleNoBalance(); - } - $print_account->update(['last_modified_by' => user()->id]); - $print_account->increment('balance', $balance); - - $admin_checkout = Checkout::admin(); - Transaction::create([ - 'checkout_id' => $admin_checkout->id, - 'receiver_id' => user()->id, - 'payer_id' => $user->id, - 'semester_id' => Semester::current()->id, - 'amount' => $request->balance, - 'payment_type_id' => PaymentType::print()->id, - 'comment' => null, - 'moved_to_checkout' => null, - ]); - - // Send notification mail - Mail::to($user)->queue(new ChangedPrintBalance($user, $balance, user()->name)); - - return redirect()->back()->with('message', __('general.successful_modification')); - } - - public function addFreePages(Request $request) - { - $validator = Validator::make($request->all(), [ - 'user_id_free' => 'required|integer|exists:users,id', - 'free_pages' => 'required|integer|min:1', - 'deadline' => 'required|date|after:now', - ]); - $validator->validate(); - - $this->authorize('create', FreePages::class); - - FreePages::create([ - 'user_id' => $request->user_id_free, - 'amount' => $request->free_pages, - 'deadline' => $request->deadline, - 'last_modified_by' => user()->id, - 'comment' => $request->comment, - ]); - - return redirect()->back()->with('message', __('general.successfully_added')); - } - - public function listAllPrintJobs() - { - $this->authorize('viewAny', PrintJob::class); - - $this->updateCompletedPrintingJobs(); - - $columns = ['created_at', 'filename', 'cost', 'state', 'user.name']; - $printJobs = PrintJob::join('users as user', 'user.id', '=', 'user_id') - ->select('print_jobs.*') - ->with('user') - ->orderby('print_jobs.created_at', 'desc'); - - return $this->printJobsPaginator($printJobs, $columns); - } - - public function listPrintJobs() - { - $this->authorize('viewSelf', PrintJob::class); - - $this->updateCompletedPrintingJobs(); - - $columns = ['created_at', 'filename', 'cost', 'state']; - $printJobs = user()->printJobs()->orderby('created_at', 'desc'); - - return $this->printJobsPaginator($printJobs, $columns); - } - - public function listAllFreePages() - { - $this->authorize('viewAny', FreePages::class); - - $columns = ['amount', 'deadline', 'modifier', 'comment', 'user.name', 'created_at']; - - $freePages = FreePages::join('users as user', 'user.id', '=', 'user_id'); - - return $this->freePagesPaginator($freePages, $columns); - } - - public function listFreePages() - { - $this->authorize('viewSelf', FreePages::class); - - $columns = ['amount', 'deadline', 'modifier', 'comment']; - $freePages = user()->freePages(); - - return $this->freePagesPaginator($freePages, $columns); - } - - public function listPrintAccountHistory() - { - $this->authorize('viewAny', PrintJob::class); - - $columns = ['user.name', 'balance_change', 'free_page_change', 'deadline_change', 'modifier.name', 'modified_at']; - $paginator = TabulatorPaginator::from( - PrintAccountHistory::join('users as user', 'user.id', '=', 'user_id') - ->join('users as modifier', 'modifier.id', '=', 'modified_by') - ->select('print_account_history.*') - ->with('user') - ->with('modifier') - )->sortable($columns) - ->filterable($columns) - ->paginate(); - return $paginator; - } - - public function cancelPrintJob($id) - { - $printJob = PrintJob::findOrFail($id); - - $this->authorize('update', $printJob); - - if ($printJob->state === PrintJob::QUEUED) { - $result = Commands::cancelPrintJob($printJob->job_id); - - if ($result['exit_code'] == 0) { - // Command was successful, job cancelled. - $printJob->state = PrintJob::CANCELLED; - // Reverting balance change - // TODO: test what happens when cancelled right before the end - $printAccount = $printJob->user->printAccount; - $printAccount->update(['last_modified_by' => user()->id]); - $printAccount->increment('balance', $printJob->cost); - } else { - if (strpos($result['output'], "already canceled") !== false) { - return redirect()->back()->with('error', __('print.already_cancelled')); - } elseif (strpos($result['output'], "already completed") !== false) { - $printJob->state = PrintJob::SUCCESS; - return redirect()->back()->with('message', __('general.successful_modification')); - } else { - Log::warning("cannot cancel print job " . $printJob->job_id ." for unknown reasons: " . var_dump($result)); - return redirect()->back()->with('error', __('general.unknown_error')); - } - } - $printJob->save(); - } - } - - /** Private helper functions */ - - private function printJobsPaginator($printJobs, $columns) - { - $paginator = TabulatorPaginator::from($printJobs)->sortable($columns)->filterable($columns)->paginate(); - - $paginator->getCollection()->transform(PrintJob::translateStates()); - $paginator->getCollection()->transform(PrintJob::addCurrencyTag()); - - return $paginator; - } - - private function freePagesPaginator($freePages, $columns) - { - $paginator = TabulatorPaginator::from( - $freePages->join('users as creator', 'creator.id', '=', 'last_modified_by') - ->select('creator.name as modifier', 'printing_free_pages.*') - ->with('user') - )->sortable($columns)->filterable($columns)->paginate(); - return $paginator; - } - - private function updateCompletedPrintingJobs() - { - try { - $result = Commands::getCompletedPrintingJobs(); - PrintJob::whereIn('job_id', $result)->update(['state' => PrintJob::SUCCESS]); - } catch (\Exception $e) { - Log::error("Printing error at line: " . __FILE__ . ":" . __LINE__ . " (in function " . __FUNCTION__ . "). " . $e->getMessage()); - } - } - - private function storeFile($file) - { - $path = $file->storePubliclyAs( - '', - md5(rand(0, 100000) . date('c')) . '.pdf', - 'printing' - ); - $path = Storage::disk('printing')->path($path); - - return $path; - } - - private function handleNoBalance() - { - return back()->withInput()->with('error', __('print.no_balance')); - } -} diff --git a/app/Http/Controllers/Dormitory/Printing/FreePagesController.php b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php new file mode 100644 index 000000000..02c1a4541 --- /dev/null +++ b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php @@ -0,0 +1,89 @@ +authorize('viewSelf', FreePages::class); + + return $this->freePagesPaginator( + freePages: user()->freePages(), + columns: [ + 'amount', + 'deadline', + 'modifier', + 'comment', + ] + ); + } + + /** + * Returns a paginated list of all `FreePages`. + * @return LengthAwarePaginator + */ + public function adminIndex() + { + $this->authorize('viewAny', FreePages::class); + + return $this->freePagesPaginator( + freePages: FreePages::with('user'), + columns: [ + 'amount', + 'deadline', + 'modifier', + 'comment', + 'user.name', + 'created_at', + ] + ); + } + + + /** + * Private helper function to create a paginator for `FreePages`. + */ + private function freePagesPaginator(Builder $freePages, array $columns) + { + $paginator = TabulatorPaginator::from( + $freePages->with('modifier') + )->sortable($columns)->filterable($columns)->paginate(); + return $paginator; + } + + /** + * Adds new free pages to a user's account. + * @param Request $request + * @return RedirectResponse + */ + public function store(Request $request) + { + $data = $request->validate([ + "user_id" => "required|exists:users,id", + "amount" => "required|integer|min:1", + "deadline" => "required|date|after:date:now", + "comment" => "string", + ]); + + $this->authorize('create', FreePages::class); + + FreePages::create($data + [ + "last_modified_by" => user()->id, + ]); + + return redirect()->back()->with('message', __('general.successfully_added')); + } +} diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php new file mode 100644 index 000000000..846456a88 --- /dev/null +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php @@ -0,0 +1,151 @@ +validate([ + 'amount' => 'required|integer', + 'user' => 'required|exists:users,id', // Normally this would be a path parameter for the PrintAccount, but we can't do that because of the limitations of blade templates + 'other_user' => 'nullable|exists:users,id', + ]); + + $printAccount = User::find($request->get('user'))->printAccount; + + // If user can not even transfer balance, we can stop here + $this->authorize('transferBalance', $printAccount); + + $otherAccount = $request->other_user ? User::find($request->get('other_user'))->printAccount : null; + + // This is a transfer between accounts + if ($otherAccount !== null) { + return $this->transferBalance($printAccount, $otherAccount, $request->get('amount')); + } + // This is a modification of the current account + else { + return $this->modifyBalance($printAccount, $request->get('amount')); + } + } + + /** + * Private helper function to transfer balance between two `PrintAccount`s. + * @param PrintAccount $printAccount The account from which the money is transfered. + * @param PrintAccount $otherAccount The account to which the money is transfered. + * @param int $amount The amount of money to be transfered. + * @return RedirectResponse + */ + private function transferBalance(PrintAccount $printAccount, PrintAccount $otherAccount, int $amount) + { + DB::beginTransaction(); + // Cannot transfer to yourself + if ($otherAccount->user_id === $printAccount->user_id) { + abort(400); + } + + // Cannot transfer from other user's account (even if you are admin) + if ($printAccount->user_id !== user()->id) { + abort(403); + } + + // This would be effectively stealing printing money from the other account + if ($amount < 0) { + abort(400); + } + + // Cannot transfer if there is not enough balance to be transfered + if ($printAccount->balance < $amount) { + return $this->returnNoBalance(); + } + + $printAccount->update([ + 'balance' => $printAccount->balance - $amount, + 'last_modified_by' => user()->id, + ]); + + $otherAccount->update([ + 'balance' => $otherAccount->balance + $amount, + 'last_modified_by' => user()->id, + ]); + + DB::commit(); + + Mail::to($printAccount->user)->queue(new ChangedPrintBalance($printAccount->user, $amount, user()->name)); + + return redirect()->back()->with('message', __('general.successful_transaction')); + } + + /** + * Private helper function to modify the balance of a `PrintAccount`. + * @param PrintAccount $printAccount The account to be modified. + * @param int $amount The amount of money to be added or subtracted. + * @return RedirectResponse + */ + private function modifyBalance(PrintAccount $printAccount, int $amount) + { + DB::beginTransaction(); + // Only admins can modify accounts + $this->authorize('modify', $printAccount); + + if ($amount < 0 && $printAccount->balance < $amount) { + $this->returnNoBalance(); + } + + $printAccount->update([ + 'balance' => $printAccount->balance + $amount, + 'last_modified_by' => user()->id, + ]); + + Mail::to($printAccount->user)->queue(new ChangedPrintBalance($printAccount->user, $amount, user()->name)); + + $adminCheckout = Checkout::admin(); + Transaction::create([ + 'checkout_id' => $adminCheckout->id, + 'receiver_id' => user()->id, + 'payer_id' => $printAccount->user->id, + 'semester_id' => Semester::current()->id, + 'amount' => $amount, + 'payment_type_id' => PaymentType::print()->id, + 'comment' => null, + 'moved_to_checkout' => null, + ]); + + DB::commit(); + + return redirect()->back()->with('message', __('general.successful_modification')); + } + + /** + * Private helper function to return a redirect with an error message if there is not enough balance. + * @return RedirectResponse + * @throws BindingResolutionException + * @throws NotFoundExceptionInterface + * @throws ContainerExceptionInterface + */ + private function returnNoBalance() + { + return back()->withInput()->with('error', __('print.no_balance')); + } +} diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php new file mode 100644 index 000000000..30a6cb34e --- /dev/null +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php @@ -0,0 +1,34 @@ +authorize('viewAny', PrintJob::class); + + $columns = ['user.name', 'balance_change', 'free_page_change', 'deadline_change', 'modifier.name', 'modified_at']; + return TabulatorPaginator::from( + PrintAccountHistory::with(['user', 'modifier'])->select('print_account_history.*') + )->sortable($columns) + ->filterable($columns) + ->paginate(); + } +} diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php new file mode 100644 index 000000000..b229962c5 --- /dev/null +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -0,0 +1,234 @@ +authorize('viewAny', PrintJob::class); + + PrinterHelper::updateCompletedPrintJobs(); + + return $this->paginatorFrom( + printJobs: PrintJob::query() + ->with('user') + ->orderBy('print_jobs.created_at', 'desc'), + columns: [ + 'created_at', + 'filename', + 'cost', + 'state', + 'user.name', + ] + ); + } + + $this->authorize('viewSelf', PrintJob::class); + + PrinterHelper::updateCompletedPrintJobs(); + return $this->paginatorFrom( + printJobs: user() + ->printJobs() + ->orderBy('created_at', 'desc'), + columns: [ + 'created_at', + 'filename', + 'cost', + 'state', + ] + ); + } + + /** + * Prints a document, then stores the corresponding `PrintJob`. + * @param Request $request + * @return RedirectResponse + */ + public function store(Request $request) + { + DB::beginTransaction(); + + $request->validate([ + 'file' => 'required|file', + 'copies' => 'required|integer|min:1', + 'two_sided' => 'in:on,off', + 'printer_id' => 'exists:printers,id', + 'use_free_pages' => 'in:on,off', + ]); + + $useFreePages = $request->boolean('use_free_pages'); + $copyNumber = $request->input('copies'); + $twoSided = $request->boolean('two_sided'); + $file = $request->file('file'); + + /** @var Printer */ + $printer = $request->has('printer_id') ? Printer::find($request->input("printer_id")) : Printer::firstWhere('name', config('print.printer_name')); + + $path = $file->store('print-documents'); + $pageNumber = PrinterHelper::getDocumentPageNumber($path); + + /** @var PrintAccount */ + $printAccount = user()->printAccount; + + if (!(($useFreePages && $printAccount->hasEnoughFreePages($pageNumber, $copyNumber, $twoSided)) || + (!$useFreePages && $printAccount->hasEnoughBalance($pageNumber, $copyNumber, $twoSided))) + ) { + return back()->with('error', __('print.no_balance')); + } + + $jobId = null; + try { + $jobId = $printer->print($twoSided, $copyNumber, $path, user()); + } catch (\Exception $e) { + return back()->with('error', __('print.error_printing')); + } finally { + Storage::delete($path); + } + + $cost = $useFreePages ? + PrinterHelper::getFreePagesNeeeded($pageNumber, $copyNumber, $twoSided) : + PrinterHelper::getBalanceNeeded($pageNumber, $copyNumber, $twoSided); + + Log::info("Printjob cost: $cost"); + + user()->printJobs()->create([ + 'state' => PrintJobStatus::QUEUED, + 'job_id' => $jobId, + 'cost' => $cost, + 'used_free_pages' => $useFreePages, + 'filename' => $file->getClientOriginalName(), + ]); + + // Update the print account history + $printAccount->last_modified_by = user()->id; + + if ($useFreePages) { + $freePagesToSubtract = $cost; + $freePages = $printAccount->available_free_pages->where('amount', '>', 0); + + /** @var FreePages */ + foreach ($freePages as $pages) { + $subtractablePages = min($freePagesToSubtract, $pages->amount); + $pages->update([ + 'last_modified_by' => user()->id, + 'amount' => $pages->amount - $subtractablePages, + ]); + + $freePagesToSubtract -= $subtractablePages; + + if ($freePagesToSubtract <= 0) { // < should not be necessary, but better safe than sorry + break; + } + } + // Set value in the session so that free page checkbox stays checked + session()->put('use_free_pages', true); + } else { + $printAccount->balance -= $cost; + + // Remove value regarding the free page checkbox from the session + session()->remove('use_free_pages'); + } + + $printAccount->save(); + + DB::commit(); + + return back()->with('message', __('print.success')); + } + + /** + * Cancels a `PrintJob` + * @param PrintJob $job + * @return RedirectResponse + */ + public function update(PrintJob $job) + { + $this->authorize('update', $job); + + if ($job->state === PrintJobStatus::QUEUED) { + $result = $job->cancel(); + switch ($result) { + case PrinterCancelResult::Success: + $job->update([ + 'state' => PrintJobStatus::CANCELLED, + ]); + $printAccount = $job->printAccount; + $printAccount->last_modified_by = user()->id; + + if ($job->used_free_pages) { + $pages = $printAccount->available_free_pages->first(); + $pages->update([ + 'last_modified_by' => user()->id, + 'amount' => $pages->amount + $job->cost, + ]); + } else { + $printAccount->balance += $job->cost; + } + + $job->save(); + return back()->with('message', __('general.successful_modification')); + case PrinterCancelResult::AlreadyCompleted: + $job->update([ + 'state' => PrintJobStatus::SUCCESS, + ]); + break; + case PrinterCancelResult::AlreadyCancelled: + $job->update([ + 'state' => PrintJobStatus::CANCELLED, + ]); + break; + } + + return back()->with('error', __("print.$result->value")); + } + + return back(); + } + + /** + * Returns a paginated list of `PrintJob`s. + * @param Builder $printJobs + * @param array $columns + * @return LengthAwarePaginator + * @throws BindingResolutionException + * @throws InvalidArgumentException + */ + private function paginatorFrom(Builder $printJobs, array $columns) + { + $paginator = TabulatorPaginator::from($printJobs)->sortable($columns)->filterable($columns)->paginate(); + + // Process the data before showing it in a table. + $paginator->getCollection()->append([ + 'translated_cost', + 'translated_state', + ]); + + return $paginator; + } +} diff --git a/app/Http/Controllers/Dormitory/Printing/PrinterController.php b/app/Http/Controllers/Dormitory/Printing/PrinterController.php new file mode 100644 index 000000000..0b9035417 --- /dev/null +++ b/app/Http/Controllers/Dormitory/Printing/PrinterController.php @@ -0,0 +1,61 @@ +authorize('handleAny', PrintAccount::class); + + return view('dormitory.print.manage.app', ["users" => User::all()]); + } + + return view('dormitory.print.app', [ + "users" => User::all(), + "user" => user(), + "printer" => Printer::firstWhere('name', config('print.printer_name')), + ]); + } + + /** + * Sets the given printer's out of paper sign. + */ + public function update(Request $request, Printer $printer) + { + $request->validate([ + "no_paper" => "boolean", + ]); + + if ($request->boolean("no_paper")) { + if ($printer->paper_out_at === null || now()->diffInMinutes($printer->paper_out_at) > 5) { + Mail::to(User::withRole(Role::SYS_ADMIN)->get())->queue(new NoPaper(user()->name)); + } + $printer->paper_out_at = now(); + $printer->save(); + return redirect()->back()->with('message', __('mail.email_sent')); + } else { + $this->authorize('handleAny', PrintAccount::class); + $printer->update([ + "paper_out_at" => null, + ]); + return redirect()->back()->with('message', __('general.successful_modification')); + } + } +} diff --git a/app/Mail/NoPaper.php b/app/Mail/NoPaper.php index 8a1431b18..ba6fbde45 100644 --- a/app/Mail/NoPaper.php +++ b/app/Mail/NoPaper.php @@ -11,7 +11,6 @@ class NoPaper extends Mailable use Queueable; use SerializesModels; - public string $recipient; public string $reporter; /** @@ -19,9 +18,8 @@ class NoPaper extends Mailable * * @param string $userName */ - public function __construct(string $recipient, string $reporter) + public function __construct(string $reporter) { - $this->recipient = $recipient; $this->reporter = $reporter; } diff --git a/app/Models/FreePages.php b/app/Models/FreePages.php index 936e0fdc5..7d261219a 100644 --- a/app/Models/FreePages.php +++ b/app/Models/FreePages.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * Model to keep track of the users' free pages. @@ -51,23 +52,43 @@ class FreePages extends Model 'comment', ]; - public function user() + protected $casts = [ + 'deadline' => 'date', + ]; + + /** + * The user this free pages entry belongs to. + * @return BelongsTo + */ + public function user(): BelongsTo { - return $this->belongsTo('App\Models\User'); + return $this->belongsTo(User::class); } + /** + * The print account this free pages entry belongs to. + * @return BelongsTo + */ public function printAccount() { - return $this->belongsTo('App\Models\PrintAccount', 'user_id', 'user_id'); + return $this->belongsTo(PrintAccount::class, 'user_id', 'user_id'); } - public function available() + /** + * Wether the free pages are still available. + * @return bool + */ + protected function getAvailableAttribute() { - return $this->deadline > date('Y-m-d'); + return now()->isBefore($this->deadline); } - public function lastModifiedBy() + /** + * The user who last modified this free pages entry. + * @return BelongsTo + */ + public function modifier(): BelongsTo { - return User::find($this->last_modified_by); + return $this->belongsTo(User::class, 'last_modified_by'); } } diff --git a/app/Models/PrintAccount.php b/app/Models/PrintAccount.php index 8089f590d..c63d59f29 100644 --- a/app/Models/PrintAccount.php +++ b/app/Models/PrintAccount.php @@ -2,8 +2,12 @@ namespace App\Models; +use Illuminate\Contracts\Container\BindingResolutionException; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Psr\Container\NotFoundExceptionInterface; +use Psr\Container\ContainerExceptionInterface; /** * Model to keep track of the users' print balance. @@ -31,7 +35,6 @@ class PrintAccount extends Model { use HasFactory; - protected $table = 'print_accounts'; protected $primaryKey = 'user_id'; public $incrementing = false; public $timestamps = false; @@ -54,31 +57,48 @@ class PrintAccount extends Model public function user() { - return $this->belongsTo('App\Models\User'); + return $this->belongsTo(User::class); } public function freePages() { - return $this->hasMany('App\Models\FreePages', 'user_id', 'user_id'); + return $this->hasMany(FreePages::class, 'user_id', 'user_id'); } - public function hasEnoughMoney($balance) + /** + * The free pages which are currently available. Sorts the free pages by their deadline. + * @return Collection + */ + public function getAvailableFreePagesAttribute() { - return $this->balance >= abs($balance); + return $this->freePages()->where('deadline', '>', now())->orderBy('deadline')->get(); } - public static function getCost($pages, $is_two_sided, $number_of_copies) + /** + * Returns wether the user has enough free pages to print a document. + * A free page is enough to print either a one sided or a two sided page. + * @param int $pages + * @param int $copies + * @param bool $twoSided + * @return bool + */ + public function hasEnoughFreePages(int $pages, int $copies, bool $twoSided) { - if (!$is_two_sided) { - return $pages * self::$COST['one_sided'] * $number_of_copies; - } - - $orphan_ending = $pages % 2; - $one_copy_cost = floor($pages / 2) * self::$COST['two_sided'] - + $orphan_ending * self::$COST['one_sided']; + return $this->getAvailableFreePagesAttribute()->sum('amount') > + PrinterHelper::getFreePagesNeeeded($pages, $copies, $twoSided); + } - return $one_copy_cost * $number_of_copies; + /** + * Returns wether the user has enough balance to print a document. + * @param int $pages + * @param int $copies + * @param bool $twoSided + * @return bool + */ + public function hasEnoughBalance(int $pages, int $copies, bool $twoSided) + { + return $this->balance >= PrinterHelper::getBalanceNeeded($pages, $twoSided, $copies); } -} -PrintAccount::$COST = config('print.cost'); + +} diff --git a/app/Models/PrintAccountHistory.php b/app/Models/PrintAccountHistory.php index 75c0d79bb..ad03e5e63 100644 --- a/app/Models/PrintAccountHistory.php +++ b/app/Models/PrintAccountHistory.php @@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Model; // Note: the elements of this class should no be changed manually. -// Triggers are set up in the database (see migration). +// Obeservers are set up. /** * App\Models\PrintAccountHistory * @@ -47,11 +47,11 @@ class PrintAccountHistory extends Model public function user() { - return $this->belongsTo('App\Models\User', 'user_id'); + return $this->belongsTo(User::class); } public function modifier() { - return $this->belongsTo('App\Models\User', 'modified_by'); + return $this->belongsTo(User::class, 'modified_by'); } } diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index 25f73b0e5..a9e7baaaf 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -2,8 +2,13 @@ namespace App\Models; +use App\Enums\PrintJobStatus; +use App\Utils\Process; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasOneThrough; +use Log; /** * App\Models\PrintJob @@ -37,46 +42,92 @@ class PrintJob extends Model { use HasFactory; - protected $table = 'print_jobs'; - protected $primaryKey = 'id'; - public $incrementing = true; public $timestamps = true; - public const QUEUED = 'QUEUED'; - public const ERROR = 'ERROR'; - public const CANCELLED = 'CANCELLED'; - public const SUCCESS = 'SUCCESS'; - public const STATES = [ - self::QUEUED, - self::ERROR, - self::CANCELLED, - self::SUCCESS, + protected $fillable = [ + 'user_id', + 'state', + 'job_id', + 'cost', + 'printer_id', + 'used_free_pages', + 'filename', ]; - protected $fillable = [ - 'filename', 'filepath', 'user_id', 'state', 'job_id', 'cost', + protected $casts = [ + 'state' => PrintJobStatus::class, + 'used_free_pages' => 'boolean', ]; public function user() { - return $this->belongsTo('App\Models\User'); + return $this->belongsTo(User::class); + } + + /** + * `Printer` which this `PrintJob` was sent to. + * @return BelongsTo + */ + public function printer() + { + return $this->belongsTo(Printer::class); } - public static function translateStates(): \Closure + /** + * `PrintAccount` which is related to this `PrintJob` through the `User`. + * The `PrintJob` and the `PrintAccount` both belong to the `User`, in this sense this relationship is articifial. + * Trying to fix the decision made for the database a few years ago. + * @return HasOneThrough + */ + public function printAccount() { - return function ($data) { - $data->state = __('print.'.strtoupper($data->state)); + return $this->hasOneThrough( + PrintAccount::class, + User::class, + 'id', // Foreign key on users + 'user_id', // Foreign key on print_accounts + 'user_id', // Local key on print_jobs + 'id', // Local key on users + ); + } - return $data; - }; + /** + * Attribute for the translated cost. + */ + public function getTranslatedCostAttribute() + { + return $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF"; + } + + /** + * Attribute for the translated state. + */ + public function getTranslatedStateAttribute() + { + return __("print." . strtoupper($this->state->value)); } - public static function addCurrencyTag(): \Closure + /** + * Attemts to cancel the given `PrintJob`. Returns wether it was successful. + * @param PrintJob $this + * @return PrinterCancelResult + */ + public function cancel() { - return function ($data) { - $data->cost = "{$data->cost} HUF"; + $printer = $this->printer ?? Printer::firstWhere('name', config('print.printer_name')); + $process = new Process(['cancel', $this->job_id, '-h', "$printer->ip:$printer->port"]); + $process->run(); + $result = ['output' => $process->getOutput(), 'exit_code' => $process->getExitCode()]; - return $data; - }; + if ($result['exit_code'] == 0) { + return PrinterCancelResult::Success; + } + if (strpos($result['output'], "already canceled") !== false) { + return PrinterCancelResult::AlreadyCancelled; + } + if (strpos($result['output'], "already completed") !== false) { + return PrinterCancelResult::AlreadyCompleted; + } + return PrinterCancelResult::CannotCancel; } } diff --git a/app/Models/Printer.php b/app/Models/Printer.php new file mode 100644 index 000000000..4de688760 --- /dev/null +++ b/app/Models/Printer.php @@ -0,0 +1,117 @@ + 'datetime', + ]; + + /** + * Returns the `PrintJob`s that were executed by this printer. + * @return HasMany + */ + public function printJobs() { + return $this->hasMany(PrintJob::class); + } + + /** + * Asks the printer to print a document with the given configuration. + * @param bool $twoSided + * @param int $copies + * @param string $path + * @return int The `jobId` belonging to the printjob + * @throws PrinterException If the printing fails + */ + public function print(bool $twoSided, int $copies, string $path) { + if (config('app.debug')) { + return -1; + } + $jobId = null; + try { + $process = new Process([ + 'lp', + '-d', $this->name, + '-h', "$this->ip:$this->port", + ($twoSided ? '-o sides=two-sided-long-edge' : ''), + '-n', $copies, + $path + ]); + $process->run(); + if (!$process->isSuccessful()) { + Log::error("Printing error at line: " . __FILE__ . ":" . __LINE__ . " (in function " . __FUNCTION__ . "). " . $process->getErrorOutput()); + throw new PrinterException($process->getErrorOutput()); + } + $result = $process->getOutput(); + if (!preg_match("/^request id is ([^\s]*) \\([0-9]* file\\(s\\)\\)$/", $result, $matches)) { + Log::error("Printing error at line: " . __FILE__ . ":" . __LINE__ . " (in function " . __FUNCTION__ . "). result:" + . print_r($result, true)); + throw new PrinterException($result); + } + $jobId = intval($matches[1]); + } catch (\Exception $e) { + Log::error("Printing error at line: " . __FILE__ . ":" . __LINE__ . " (in function " . __FUNCTION__ . "). " . $e->getMessage()); + throw new PrinterException($e->getMessage(), $e->getCode(), $e->getPrevious()); + } + + return $jobId; + } + + /** + * Returns the completed printjobs for this printer. + * @return array + * @throws NotFoundExceptionInterface + * @throws ContainerExceptionInterface + */ + public function getCompletedPrintJobs() { + try { + $process = new Process(['lpstat', '-W', 'completed', '-o', $this->name, '-h', "$this->ip:$this->port", '|', 'awk', "'{print $1}'"]); + $process->run(); + $result = explode("\n", $process->getOutput()); + return $result; + } catch (\Exception $e) { + Log::error("Printing error at line: " . __FILE__ . ":" . __LINE__ . " (in function " . __FUNCTION__ . "). " . $e->getMessage()); + } + } + + /** + * Updates the state of the completed printjobs to `PrintJobStatus::SUCCESS`. + */ + public function updateCompletedPrintJobs() { + PrintJob::whereIn( + 'job_id', + $this->getCompletedPrintJobs() + )->update(['state' => PrintJobStatus::SUCCESS]); + } +} + +enum PrinterCancelResult: string { + case AlreadyCancelled = "already-cancelled"; + case AlreadyCompleted = "already-completed"; + case CannotCancel = "cannot-cancel"; + case Success = "successfully-cancelled"; +} + +class PrinterException extends \Exception { + // +} diff --git a/app/Models/Role.php b/app/Models/Role.php index d6b3195e7..d00115b27 100644 --- a/app/Models/Role.php +++ b/app/Models/Role.php @@ -99,9 +99,6 @@ class Role extends Model self::ETHICS_COMMISSIONER ]; - // Module-related roles - public const PRINTER = 'printer'; - //collegist related roles public const RESIDENT = 'resident'; public const EXTERN = 'extern'; @@ -118,7 +115,6 @@ class Role extends Model self::SECRETARY, self::DIRECTOR, self::STAFF, - self::PRINTER, self::LOCALE_ADMIN, self::STUDENT_COUNCIL, self::STUDENT_COUNCIL_SECRETARY, @@ -301,7 +297,6 @@ public function color(): string self::SECRETARY => 'indigo', self::DIRECTOR => 'blue', self::STAFF => 'cyan', - self::PRINTER => 'teal', self::LOCALE_ADMIN => 'amber', self::STUDENT_COUNCIL => 'green darken-4', self::APPLICATION_COMMITTEE_MEMBER => 'light-blue darken-4', diff --git a/app/Models/User.php b/app/Models/User.php index 9025ce1d8..6724b4f20 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -1008,15 +1008,6 @@ public static function staff(): ?User { return self::withRole(Role::STAFF)->first(); } - - /** - * @return array|Collection|User[] the users with printer role - */ - public static function printers(): Collection|array - { - return self::withRole(Role::PRINTER)->get(); - } - /** * @return array|Collection|User[] the users with printer role */ diff --git a/app/Policies/FreePagesPolicy.php b/app/Policies/FreePagesPolicy.php index d1800a264..bf6f0d388 100644 --- a/app/Policies/FreePagesPolicy.php +++ b/app/Policies/FreePagesPolicy.php @@ -16,10 +16,6 @@ public function before(User $user) if ($user->isAdmin()) { return true; } - - if (!$user->hasRole(Role::PRINTER)) { - return false; - } } public function create(User $user) diff --git a/app/Policies/PrintAccountPolicy.php b/app/Policies/PrintAccountPolicy.php index 4269655dd..f3105fed4 100644 --- a/app/Policies/PrintAccountPolicy.php +++ b/app/Policies/PrintAccountPolicy.php @@ -16,9 +16,6 @@ public function before(User $user, $ability) if ($user->isAdmin()) { return true; } - if (!$user->hasRole(Role::PRINTER)) { - return false; - } } /** @@ -43,4 +40,14 @@ public function modify(User $user): bool { return false; } + /** + * Determine whether the user can transfer balance from the print account. + * @param User $user + * @param PrintAccount $printAccount + * @return bool + */ + public function transferBalance(User $user, PrintAccount $printAccount): bool + { + return $user->id == $printAccount->user_id; + } } diff --git a/app/Policies/PrintJobPolicy.php b/app/Policies/PrintJobPolicy.php index 25cc23ef9..ba45aad68 100644 --- a/app/Policies/PrintJobPolicy.php +++ b/app/Policies/PrintJobPolicy.php @@ -16,9 +16,6 @@ public function before(User $user) if ($user->isAdmin()) { return true; } - if (!$user->hasRole(Role::PRINTER)) { - return false; - } } /** diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index bf54e521f..11808968e 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -54,13 +54,9 @@ public function boot() }); } - public function registerPrintingPermissionHandlingPolicies() - { - Gate::define('print.print', function ($user) { - return $user->hasRole(Role::PRINTER); - }); - } - + /** + * Register policies for documents. + */ public function registerDocumentPolicies() { Gate::define('document.status-certificate.viewAny', function ($user) { @@ -88,6 +84,9 @@ public function registerDocumentPolicies() }); } + /** + * Register policies for verification. + */ public function registerVerificationPolicies() { Gate::define('registration.handle', function ($user) { diff --git a/app/Utils/Printer.php b/app/Utils/Printer.php deleted file mode 100644 index 575f40c75..000000000 --- a/app/Utils/Printer.php +++ /dev/null @@ -1,160 +0,0 @@ -filename = $filename; - $this->path = $path; - $this->is_two_sided = $is_two_sided; - $this->number_of_copies = $number_of_copies; - $this->use_free_pages = $use_free_pages; - $this->print_account = user()->printAccount; - } - - public function print() - { - // Getting the number of pages from the document - $errors = $this->setPages(); - if ($errors != null) { - return $errors; - } - - // If using free pages, check the amount that can be used - if ($this->use_free_pages) { - $this->calculateFreePagePool(); - } - - // Calculate cost - $this->cost = PrintAccount::getCost($this->pages, $this->is_two_sided, $this->number_of_copies); - - // Check balance - if (!$this->print_account->hasEnoughMoney($this->cost)) { - return back()->withInput()->with('error', __('print.no_balance')); - } - - // Print document - return $this->printDocument(); - } - - /** - * Only calculating the values here to see how many pages can be covered free of charge. - */ - private function calculateFreePagePool() - { - $this->free_page_pool = []; - $available_pages = 0; - $all_pages = user()->freePages - ->where('deadline', '>', Carbon::now()) - ->sortBy('deadline'); - - foreach ($all_pages as $key => $free_page) { - if ($available_pages + $free_page->amount >= $this->pages) { - $this->free_page_pool[] = [ - 'page' => $free_page, - 'new_amount' => $free_page->amount - ($this->pages - $available_pages) - ]; - $available_pages = $this->pages; - break; - } - $this->free_page_pool[] = [ - 'page' => $free_page, - 'new_amount' => 0 - ]; - $available_pages += $free_page->amount; - } - - $this->pages -= $available_pages; - } - - private function printDocument() - { - // Print file and return on error - if (!$this->printFile()) { - return back()->with('error', __('print.error_printing')); - } - - // Update print account history - $this->print_account->update(['last_modified_by' => user()->id]); - foreach ($this->free_page_pool as $fp) { - $fp['page']->update([ - 'amount' => $fp['new_amount'], - 'last_modified_by' => user()->id - ]); - } - - // Update print account - $this->print_account->decrement('balance', $this->cost); - - return back()->with('message', __('print.success')); - } - - private function printFile() - { - $printer_name = config('print.printer_name'); - $state = PrintJob::QUEUED; - try { - $command = "lp -d " . $printer_name - . ($this->is_two_sided ? " -o sides=two-sided-long-edge " : " ") - . "-n " . $this->number_of_copies . " " - . $this->path . " 2>&1"; - $result = Commands::print($command); - if (!preg_match("/^request id is ([^\s]*) \\([0-9]* file\\(s\\)\\)$/", $result, $job)) { - Log::error("Printing error at line: " . __FILE__ . ":" . __LINE__ . " (in function " . __FUNCTION__ . "). result:" - . print_r($result, true)); - $state = PrintJob::ERROR; - } - $job_id = $job[1]; - } catch (\Exception $e) { - Log::error("Printing error at line: " . __FILE__ . ":" . __LINE__ . " (in function " . __FUNCTION__ . "). " . $e->getMessage()); - $state = PrintJob::ERROR; - $job_id = ""; - $this->path = ""; - } - - PrintJob::create([ - 'filename' => $this->filename, - 'filepath' => $this->path, - 'user_id' => user()->id, - 'state' => $state, - 'job_id' => $job_id, - 'cost' => $this->cost, - ]); - return $state == PrintJob::QUEUED; - } - - private function setPages() - { - try { - $this->pages = Commands::getPages($this->path); - } catch (\Exception $e) { - Log::error("File retrieval exception at line: " . __FILE__ . ":" . __LINE__ . " (in function " . __FUNCTION__ . "). " . $e->getMessage()); - $this->pages = ""; - } - - if ($this->pages == "" || !is_numeric($this->pages) || $this->pages <= 0) { - Log::error("Cannot get number of pages for uploaded file!" . print_r($this->pages, true)); - return back()->withInput()->with('error', __('print.invalid_pdf')); - } - return null; - } -} diff --git a/app/Utils/PrinterHelper.php b/app/Utils/PrinterHelper.php new file mode 100644 index 000000000..27d761a2d --- /dev/null +++ b/app/Utils/PrinterHelper.php @@ -0,0 +1,87 @@ +run(); + $result = intval($process->getOutput(strval(rand(1, 10)))); + return $result; + } + + /** + * Returns an array with the number of one-sided and two-sided pages needed to print the given number of pages. + * @param int $pages + * @param bool $twoSided + * @return array + */ + public static function getPageTypesNeeded(int $pages, bool $twoSided) + { + $oneSidedPages = 0; + $twoSidedPages = 0; + if (!$twoSided) { + $oneSidedPages = $pages; + } else { + $oneSidedPages = $pages % 2; + $twoSidedPages = floor($pages / 2); + } + + return [ + 'one_sided' => $oneSidedPages, + 'two_sided' => $twoSidedPages, + ]; + } + + /** + * Returns the number of free pages needed to print with given configuration. + * @param int $pages + * @param mixed $copies + * @param mixed $twoSided + * @return int|float + */ + public static function getFreePagesNeeeded(int $pages, $copies, $twoSided) + { + $pageTypesNeeded = self::getPageTypesNeeded($pages, $twoSided); + + return ($pageTypesNeeded['one_sided'] + $pageTypesNeeded['two_sided']) * $copies; + } + + /** + * Returns the amount of money needed to print with given configuration. + * @param int $pages + * @param int $copies + * @param bool $twoSided + * @return mixed + * @throws BindingResolutionException + * @throws NotFoundExceptionInterface + * @throws ContainerExceptionInterface + */ + public static function getBalanceNeeded(int $pages, int $copies, bool $twoSided) + { + $pageTypesNeeded = self::getPageTypesNeeded($pages, $twoSided); + + return $pageTypesNeeded['one_sided'] * config('print.one_sided_cost') * $copies + + $pageTypesNeeded['two_sided'] * config('print.two_sided_cost') * $copies; + } + + /** + * Gets the printjob-status with every printer, updates the status of the completed printjobs. + */ + public static function updateCompletedPrintJobs() + { + foreach(PrintJob::where('state', PrintJobStatus::QUEUED)->whereNotNull('printer_id')->pluck('printer_id')->unique() as $printer_id) { + Printer::find($printer_id)->updateCompletedPrintJobs(); + } + } +} diff --git a/app/Utils/Process.php b/app/Utils/Process.php new file mode 100644 index 000000000..db8e75b4c --- /dev/null +++ b/app/Utils/Process.php @@ -0,0 +1,32 @@ +=7.0" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "bin": [ "bin/php-parse" @@ -3221,7 +3220,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -3245,9 +3244,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" }, - "time": "2023-12-10T21:03:43+00:00" + "time": "2024-03-05T20:51:40+00:00" }, { "name": "nunomaduro/termwind", @@ -3634,16 +3633,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.34", + "version": "3.0.37", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "56c79f16a6ae17e42089c06a2144467acc35348a" + "reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56c79f16a6ae17e42089c06a2144467acc35348a", - "reference": "56c79f16a6ae17e42089c06a2144467acc35348a", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cfa2013d0f68c062055180dd4328cc8b9d1f30b8", + "reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8", "shasum": "" }, "require": { @@ -3724,7 +3723,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.34" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.37" }, "funding": [ { @@ -3740,7 +3739,7 @@ "type": "tidelift" } ], - "time": "2023-11-27T11:13:31+00:00" + "time": "2024-03-03T02:14:58+00:00" }, { "name": "psr/cache", @@ -4205,25 +4204,25 @@ }, { "name": "psy/psysh", - "version": "v0.11.22", + "version": "v0.12.2", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "128fa1b608be651999ed9789c95e6e2a31b5802b" + "reference": "9185c66c2165bbf4d71de78a69dccf4974f9538d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/128fa1b608be651999ed9789c95e6e2a31b5802b", - "reference": "128fa1b608be651999ed9789c95e6e2a31b5802b", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/9185c66c2165bbf4d71de78a69dccf4974f9538d", + "reference": "9185c66c2165bbf4d71de78a69dccf4974f9538d", "shasum": "" }, "require": { "ext-json": "*", "ext-tokenizer": "*", - "nikic/php-parser": "^4.0 || ^3.1", - "php": "^8.0 || ^7.0.8", - "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4", - "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4" + "nikic/php-parser": "^5.0 || ^4.0", + "php": "^8.0 || ^7.4", + "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" }, "conflict": { "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" @@ -4234,8 +4233,7 @@ "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." + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." }, "bin": [ "bin/psysh" @@ -4243,7 +4241,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-0.11": "0.11.x-dev" + "dev-main": "0.12.x-dev" }, "bamarni-bin": { "bin-links": false, @@ -4279,9 +4277,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.11.22" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.2" }, - "time": "2023-10-14T21:56:36+00:00" + "time": "2024-03-17T01:53:00+00:00" }, { "name": "ralouphie/getallheaders", @@ -4672,20 +4670,20 @@ }, { "name": "spatie/laravel-package-tools", - "version": "1.16.1", + "version": "1.16.3", "source": { "type": "git", "url": "https://github.com/spatie/laravel-package-tools.git", - "reference": "cc7c991555a37f9fa6b814aa03af73f88026a83d" + "reference": "59db18c2e20d49a0b6d447bb1c654f6c123beb9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/cc7c991555a37f9fa6b814aa03af73f88026a83d", - "reference": "cc7c991555a37f9fa6b814aa03af73f88026a83d", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/59db18c2e20d49a0b6d447bb1c654f6c123beb9e", + "reference": "59db18c2e20d49a0b6d447bb1c654f6c123beb9e", "shasum": "" }, "require": { - "illuminate/contracts": "^9.28|^10.0", + "illuminate/contracts": "^9.28|^10.0|^11.0", "php": "^8.0" }, "require-dev": { @@ -4720,7 +4718,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-package-tools/issues", - "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.1" + "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.3" }, "funding": [ { @@ -4728,7 +4726,7 @@ "type": "github" } ], - "time": "2023-08-23T09:04:39+00:00" + "time": "2024-03-07T07:35:57+00:00" }, { "name": "spatie/laravel-signal-aware-command", @@ -4867,16 +4865,16 @@ }, { "name": "symfony/console", - "version": "v6.4.1", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd" + "reference": "0d9e4eb5ad413075624378f474c4167ea202de78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a550a7c99daeedef3f9d23fb82e3531525ff11fd", - "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd", + "url": "https://api.github.com/repos/symfony/console/zipball/0d9e4eb5ad413075624378f474c4167ea202de78", + "reference": "0d9e4eb5ad413075624378f474c4167ea202de78", "shasum": "" }, "require": { @@ -4941,7 +4939,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.1" + "source": "https://github.com/symfony/console/tree/v6.4.4" }, "funding": [ { @@ -4957,24 +4955,24 @@ "type": "tidelift" } ], - "time": "2023-11-30T10:54:28+00:00" + "time": "2024-02-22T20:27:10+00:00" }, { "name": "symfony/css-selector", - "version": "v7.0.0", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "bb51d46e53ef8d50d523f0c5faedba056a27943e" + "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/bb51d46e53ef8d50d523f0c5faedba056a27943e", - "reference": "bb51d46e53ef8d50d523f0c5faedba056a27943e", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/ee0f7ed5cf298cc019431bb3b3977ebc52b86229", + "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -5006,7 +5004,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.0.0" + "source": "https://github.com/symfony/css-selector/tree/v6.4.3" }, "funding": [ { @@ -5022,7 +5020,7 @@ "type": "tidelift" } ], - "time": "2023-10-31T17:59:56+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "symfony/deprecation-contracts", @@ -5093,16 +5091,16 @@ }, { "name": "symfony/error-handler", - "version": "v6.4.0", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788" + "reference": "c725219bdf2afc59423c32793d5019d2a904e13a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/c873490a1c97b3a0a4838afc36ff36c112d02788", - "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/c725219bdf2afc59423c32793d5019d2a904e13a", + "reference": "c725219bdf2afc59423c32793d5019d2a904e13a", "shasum": "" }, "require": { @@ -5148,7 +5146,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.0" + "source": "https://github.com/symfony/error-handler/tree/v6.4.4" }, "funding": [ { @@ -5164,28 +5162,28 @@ "type": "tidelift" } ], - "time": "2023-10-18T09:43:34+00:00" + "time": "2024-02-22T20:27:10+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.0.0", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e" + "reference": "ae9d3a6f3003a6caf56acd7466d8d52378d44fef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c459b40ffe67c49af6fd392aac374c9edf8a027e", - "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ae9d3a6f3003a6caf56acd7466d8d52378d44fef", + "reference": "ae9d3a6f3003a6caf56acd7466d8d52378d44fef", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.1", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<6.4", + "symfony/dependency-injection": "<5.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -5194,13 +5192,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -5228,7 +5226,7 @@ "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/v7.0.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.3" }, "funding": [ { @@ -5244,7 +5242,7 @@ "type": "tidelift" } ], - "time": "2023-07-27T16:29:09+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -5388,16 +5386,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.0", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771" + "reference": "ebc713bc6e6f4b53f46539fc158be85dfcd77304" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/44a6d39a9cc11e154547d882d5aac1e014440771", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ebc713bc6e6f4b53f46539fc158be85dfcd77304", + "reference": "ebc713bc6e6f4b53f46539fc158be85dfcd77304", "shasum": "" }, "require": { @@ -5445,7 +5443,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.0" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.4" }, "funding": [ { @@ -5461,20 +5459,20 @@ "type": "tidelift" } ], - "time": "2023-11-20T16:41:16+00:00" + "time": "2024-02-08T15:01:18+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.1", + "version": "v6.4.5", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "2953274c16a229b3933ef73a6898e18388e12e1b" + "reference": "f6947cb939d8efee137797382cb4db1af653ef75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2953274c16a229b3933ef73a6898e18388e12e1b", - "reference": "2953274c16a229b3933ef73a6898e18388e12e1b", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f6947cb939d8efee137797382cb4db1af653ef75", + "reference": "f6947cb939d8efee137797382cb4db1af653ef75", "shasum": "" }, "require": { @@ -5523,7 +5521,7 @@ "symfony/process": "^5.4|^6.0|^7.0", "symfony/property-access": "^5.4.5|^6.0.5|^7.0", "symfony/routing": "^5.4|^6.0|^7.0", - "symfony/serializer": "^6.3|^7.0", + "symfony/serializer": "^6.4.4|^7.0.4", "symfony/stopwatch": "^5.4|^6.0|^7.0", "symfony/translation": "^5.4|^6.0|^7.0", "symfony/translation-contracts": "^2.5|^3", @@ -5558,7 +5556,7 @@ "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/v6.4.1" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.5" }, "funding": [ { @@ -5574,20 +5572,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T17:02:02+00:00" + "time": "2024-03-04T21:00:47+00:00" }, { "name": "symfony/mailer", - "version": "v6.4.0", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba" + "reference": "791c5d31a8204cf3db0c66faab70282307f4376b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", - "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", + "url": "https://api.github.com/repos/symfony/mailer/zipball/791c5d31a8204cf3db0c66faab70282307f4376b", + "reference": "791c5d31a8204cf3db0c66faab70282307f4376b", "shasum": "" }, "require": { @@ -5638,7 +5636,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.4.0" + "source": "https://github.com/symfony/mailer/tree/v6.4.4" }, "funding": [ { @@ -5654,20 +5652,20 @@ "type": "tidelift" } ], - "time": "2023-11-12T18:02:22+00:00" + "time": "2024-02-03T21:33:47+00:00" }, { "name": "symfony/mime", - "version": "v6.4.0", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "ca4f58b2ef4baa8f6cecbeca2573f88cd577d205" + "reference": "5017e0a9398c77090b7694be46f20eb796262a34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/ca4f58b2ef4baa8f6cecbeca2573f88cd577d205", - "reference": "ca4f58b2ef4baa8f6cecbeca2573f88cd577d205", + "url": "https://api.github.com/repos/symfony/mime/zipball/5017e0a9398c77090b7694be46f20eb796262a34", + "reference": "5017e0a9398c77090b7694be46f20eb796262a34", "shasum": "" }, "require": { @@ -5722,7 +5720,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.4.0" + "source": "https://github.com/symfony/mime/tree/v6.4.3" }, "funding": [ { @@ -5738,20 +5736,20 @@ "type": "tidelift" } ], - "time": "2023-10-17T11:49:05+00:00" + "time": "2024-01-30T08:32:12+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", "shasum": "" }, "require": { @@ -5765,9 +5763,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -5804,7 +5799,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" }, "funding": [ { @@ -5820,20 +5815,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", "shasum": "" }, "require": { @@ -5844,9 +5839,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -5885,7 +5877,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" }, "funding": [ { @@ -5901,20 +5893,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d" + "reference": "a287ed7475f85bf6f61890146edbc932c0fff919" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919", + "reference": "a287ed7475f85bf6f61890146edbc932c0fff919", "shasum": "" }, "require": { @@ -5927,9 +5919,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -5972,7 +5961,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.29.0" }, "funding": [ { @@ -5988,20 +5977,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:30:37+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", "shasum": "" }, "require": { @@ -6012,9 +6001,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6056,7 +6042,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" }, "funding": [ { @@ -6072,20 +6058,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "shasum": "" }, "require": { @@ -6099,9 +6085,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6139,7 +6122,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" }, "funding": [ { @@ -6155,20 +6138,20 @@ "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" + "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25", + "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25", "shasum": "" }, "require": { @@ -6176,9 +6159,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6215,7 +6195,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.29.0" }, "funding": [ { @@ -6231,20 +6211,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", "shasum": "" }, "require": { @@ -6252,9 +6232,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6298,7 +6275,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" }, "funding": [ { @@ -6314,20 +6291,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11" + "reference": "86fcae159633351e5fd145d1c47de6c528f8caff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/86fcae159633351e5fd145d1c47de6c528f8caff", + "reference": "86fcae159633351e5fd145d1c47de6c528f8caff", "shasum": "" }, "require": { @@ -6336,9 +6313,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6378,7 +6352,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.29.0" }, "funding": [ { @@ -6394,20 +6368,20 @@ "type": "tidelift" } ], - "time": "2023-08-16T06:22:46+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e" + "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/9c44518a5aff8da565c8a55dbe85d2769e6f630e", - "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/3abdd21b0ceaa3000ee950097bc3cf9efc137853", + "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853", "shasum": "" }, "require": { @@ -6421,9 +6395,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6460,7 +6431,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.29.0" }, "funding": [ { @@ -6476,20 +6447,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/process", - "version": "v6.4.0", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa" + "reference": "710e27879e9be3395de2b98da3f52a946039f297" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/191703b1566d97a5425dc969e4350d32b8ef17aa", - "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa", + "url": "https://api.github.com/repos/symfony/process/zipball/710e27879e9be3395de2b98da3f52a946039f297", + "reference": "710e27879e9be3395de2b98da3f52a946039f297", "shasum": "" }, "require": { @@ -6521,7 +6492,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.0" + "source": "https://github.com/symfony/process/tree/v6.4.4" }, "funding": [ { @@ -6537,20 +6508,20 @@ "type": "tidelift" } ], - "time": "2023-11-17T21:06:49+00:00" + "time": "2024-02-20T12:31:00+00:00" }, { "name": "symfony/routing", - "version": "v6.4.1", + "version": "v6.4.5", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40" + "reference": "7fe30068e207d9c31c0138501ab40358eb2d49a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0c95c164fdba18b12523b75e64199ca3503e6d40", - "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40", + "url": "https://api.github.com/repos/symfony/routing/zipball/7fe30068e207d9c31c0138501ab40358eb2d49a4", + "reference": "7fe30068e207d9c31c0138501ab40358eb2d49a4", "shasum": "" }, "require": { @@ -6604,7 +6575,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.1" + "source": "https://github.com/symfony/routing/tree/v6.4.5" }, "funding": [ { @@ -6620,25 +6591,25 @@ "type": "tidelift" } ], - "time": "2023-12-01T14:54:37+00:00" + "time": "2024-02-27T12:33:30+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.4.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -6686,7 +6657,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -6702,24 +6673,24 @@ "type": "tidelift" } ], - "time": "2023-07-30T20:28:31+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/string", - "version": "v7.0.0", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620" + "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/92bd2bfbba476d4a1838e5e12168bef2fd1e6620", - "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620", + "url": "https://api.github.com/repos/symfony/string/zipball/4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", + "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", @@ -6729,11 +6700,11 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -6772,7 +6743,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.0.0" + "source": "https://github.com/symfony/string/tree/v6.4.4" }, "funding": [ { @@ -6788,20 +6759,20 @@ "type": "tidelift" } ], - "time": "2023-11-29T08:40:23+00:00" + "time": "2024-02-01T13:16:41+00:00" }, { "name": "symfony/translation", - "version": "v6.4.0", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37" + "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", - "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", + "url": "https://api.github.com/repos/symfony/translation/zipball/bce6a5a78e94566641b2594d17e48b0da3184a8e", + "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e", "shasum": "" }, "require": { @@ -6824,7 +6795,7 @@ "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { - "nikic/php-parser": "^4.13", + "nikic/php-parser": "^4.18|^5.0", "psr/log": "^1|^2|^3", "symfony/config": "^5.4|^6.0|^7.0", "symfony/console": "^5.4|^6.0|^7.0", @@ -6867,7 +6838,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.0" + "source": "https://github.com/symfony/translation/tree/v6.4.4" }, "funding": [ { @@ -6883,20 +6854,20 @@ "type": "tidelift" } ], - "time": "2023-11-29T08:14:36+00:00" + "time": "2024-02-20T13:16:58+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.4.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" + "reference": "06450585bf65e978026bda220cdebca3f867fde7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", + "reference": "06450585bf65e978026bda220cdebca3f867fde7", "shasum": "" }, "require": { @@ -6945,7 +6916,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" }, "funding": [ { @@ -6961,20 +6932,20 @@ "type": "tidelift" } ], - "time": "2023-07-25T15:08:44+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/uid", - "version": "v6.4.0", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "8092dd1b1a41372110d06374f99ee62f7f0b9a92" + "reference": "1d31267211cc3a2fff32bcfc7c1818dac41b6fc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/8092dd1b1a41372110d06374f99ee62f7f0b9a92", - "reference": "8092dd1b1a41372110d06374f99ee62f7f0b9a92", + "url": "https://api.github.com/repos/symfony/uid/zipball/1d31267211cc3a2fff32bcfc7c1818dac41b6fc0", + "reference": "1d31267211cc3a2fff32bcfc7c1818dac41b6fc0", "shasum": "" }, "require": { @@ -7019,7 +6990,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.4.0" + "source": "https://github.com/symfony/uid/tree/v6.4.3" }, "funding": [ { @@ -7035,20 +7006,20 @@ "type": "tidelift" } ], - "time": "2023-10-31T08:18:17+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.0", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6" + "reference": "b439823f04c98b84d4366c79507e9da6230944b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/b439823f04c98b84d4366c79507e9da6230944b1", + "reference": "b439823f04c98b84d4366c79507e9da6230944b1", "shasum": "" }, "require": { @@ -7104,7 +7075,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.0" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.4" }, "funding": [ { @@ -7120,7 +7091,7 @@ "type": "tidelift" } ], - "time": "2023-11-09T08:28:32+00:00" + "time": "2024-02-15T11:23:52+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -7395,36 +7366,36 @@ "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.9.2", + "version": "v3.12.2", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "bfd0131c146973cab164e50f5cdd8a67cc60cab1" + "reference": "43555503052443964ce2c1c1f3b0378e58219eb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/bfd0131c146973cab164e50f5cdd8a67cc60cab1", - "reference": "bfd0131c146973cab164e50f5cdd8a67cc60cab1", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/43555503052443964ce2c1c1f3b0378e58219eb8", + "reference": "43555503052443964ce2c1c1f3b0378e58219eb8", "shasum": "" }, "require": { - "illuminate/routing": "^9|^10", - "illuminate/session": "^9|^10", - "illuminate/support": "^9|^10", - "maximebf/debugbar": "^1.18.2", + "illuminate/routing": "^9|^10|^11", + "illuminate/session": "^9|^10|^11", + "illuminate/support": "^9|^10|^11", + "maximebf/debugbar": "~1.21.0", "php": "^8.0", - "symfony/finder": "^6" + "symfony/finder": "^6|^7" }, "require-dev": { "mockery/mockery": "^1.3.3", - "orchestra/testbench-dusk": "^5|^6|^7|^8", - "phpunit/phpunit": "^8.5.30|^9.0", + "orchestra/testbench-dusk": "^5|^6|^7|^8|^9", + "phpunit/phpunit": "^9.6|^10.5", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.8-dev" + "dev-master": "3.10-dev" }, "laravel": { "providers": [ @@ -7463,7 +7434,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.9.2" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.12.2" }, "funding": [ { @@ -7475,44 +7446,44 @@ "type": "github" } ], - "time": "2023-08-25T18:43:57+00:00" + "time": "2024-03-13T09:50:34+00:00" }, { "name": "barryvdh/laravel-ide-helper", - "version": "v2.13.0", + "version": "v2.15.1", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "81d5b223ff067a1f38e14c100997e153b837fe4a" + "reference": "77831852bb7bc54f287246d32eb91274eaf87f8b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/81d5b223ff067a1f38e14c100997e153b837fe4a", - "reference": "81d5b223ff067a1f38e14c100997e153b837fe4a", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/77831852bb7bc54f287246d32eb91274eaf87f8b", + "reference": "77831852bb7bc54f287246d32eb91274eaf87f8b", "shasum": "" }, "require": { "barryvdh/reflection-docblock": "^2.0.6", "composer/class-map-generator": "^1.0", - "doctrine/dbal": "^2.6 || ^3", + "doctrine/dbal": "^2.6 || ^3.1.4", "ext-json": "*", - "illuminate/console": "^8 || ^9 || ^10", - "illuminate/filesystem": "^8 || ^9 || ^10", - "illuminate/support": "^8 || ^9 || ^10", - "nikic/php-parser": "^4.7", - "php": "^7.3 || ^8.0", + "illuminate/console": "^9 || ^10", + "illuminate/filesystem": "^9 || ^10", + "illuminate/support": "^9 || ^10", + "nikic/php-parser": "^4.18 || ^5", + "php": "^8.0", "phpdocumentor/type-resolver": "^1.1.0" }, "require-dev": { "ext-pdo_sqlite": "*", - "friendsofphp/php-cs-fixer": "^2", - "illuminate/config": "^8 || ^9 || ^10", - "illuminate/view": "^8 || ^9 || ^10", + "friendsofphp/php-cs-fixer": "^3", + "illuminate/config": "^9 || ^10", + "illuminate/view": "^9 || ^10", "mockery/mockery": "^1.4", - "orchestra/testbench": "^6 || ^7 || ^8", - "phpunit/phpunit": "^8.5 || ^9", - "spatie/phpunit-snapshot-assertions": "^3 || ^4", - "vimeo/psalm": "^3.12" + "orchestra/testbench": "^7 || ^8", + "phpunit/phpunit": "^9", + "spatie/phpunit-snapshot-assertions": "^4", + "vimeo/psalm": "^5.4" }, "suggest": { "illuminate/events": "Required for automatic helper generation (^6|^7|^8|^9|^10)." @@ -7520,7 +7491,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.12-dev" + "dev-master": "2.15-dev" }, "laravel": { "providers": [ @@ -7557,7 +7528,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", - "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.13.0" + "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.15.1" }, "funding": [ { @@ -7569,7 +7540,7 @@ "type": "github" } ], - "time": "2023-02-04T13:56:40+00:00" + "time": "2024-02-15T14:23:20+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -7625,16 +7596,16 @@ }, { "name": "composer/class-map-generator", - "version": "1.1.0", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/composer/class-map-generator.git", - "reference": "953cc4ea32e0c31f2185549c7d216d7921f03da9" + "reference": "8286a62d243312ed99b3eee20d5005c961adb311" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/class-map-generator/zipball/953cc4ea32e0c31f2185549c7d216d7921f03da9", - "reference": "953cc4ea32e0c31f2185549c7d216d7921f03da9", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/8286a62d243312ed99b3eee20d5005c961adb311", + "reference": "8286a62d243312ed99b3eee20d5005c961adb311", "shasum": "" }, "require": { @@ -7678,7 +7649,7 @@ ], "support": { "issues": "https://github.com/composer/class-map-generator/issues", - "source": "https://github.com/composer/class-map-generator/tree/1.1.0" + "source": "https://github.com/composer/class-map-generator/tree/1.1.1" }, "funding": [ { @@ -7694,20 +7665,20 @@ "type": "tidelift" } ], - "time": "2023-06-30T13:58:57+00:00" + "time": "2024-03-15T12:53:41+00:00" }, { "name": "composer/pcre", - "version": "3.1.1", + "version": "3.1.2", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9" + "reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9", - "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9", + "url": "https://api.github.com/repos/composer/pcre/zipball/4775f35b2d70865807c89d32c8e7385b86eb0ace", + "reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace", "shasum": "" }, "require": { @@ -7749,7 +7720,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.1" + "source": "https://github.com/composer/pcre/tree/3.1.2" }, "funding": [ { @@ -7765,7 +7736,7 @@ "type": "tidelift" } ], - "time": "2023-10-11T07:11:09+00:00" + "time": "2024-03-07T15:38:35+00:00" }, { "name": "doctrine/cache", @@ -7862,16 +7833,16 @@ }, { "name": "doctrine/dbal", - "version": "3.7.2", + "version": "3.8.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "0ac3c270590e54910715e9a1a044cc368df282b2" + "reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/0ac3c270590e54910715e9a1a044cc368df282b2", - "reference": "0ac3c270590e54910715e9a1a044cc368df282b2", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/db922ba9436b7b18a23d1653a0b41ff2369ca41c", + "reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c", "shasum": "" }, "require": { @@ -7887,14 +7858,14 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.42", + "phpstan/phpstan": "1.10.58", "phpstan/phpstan-strict-rules": "^1.5", - "phpunit/phpunit": "9.6.13", + "phpunit/phpunit": "9.6.16", "psalm/plugin-phpunit": "0.18.4", "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.7.2", - "symfony/cache": "^5.4|^6.0", - "symfony/console": "^4.4|^5.4|^6.0", + "squizlabs/php_codesniffer": "3.9.0", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/console": "^4.4|^5.4|^6.0|^7.0", "vimeo/psalm": "4.30.0" }, "suggest": { @@ -7955,7 +7926,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.7.2" + "source": "https://github.com/doctrine/dbal/tree/3.8.3" }, "funding": [ { @@ -7971,20 +7942,20 @@ "type": "tidelift" } ], - "time": "2023-11-19T08:06:58+00:00" + "time": "2024-03-03T15:55:06+00:00" }, { "name": "doctrine/deprecations", - "version": "1.1.2", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931" + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931", - "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", "shasum": "" }, "require": { @@ -8016,9 +7987,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.2" + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" }, - "time": "2023-09-27T20:04:15+00:00" + "time": "2024-01-30T19:34:25+00:00" }, { "name": "doctrine/event-manager", @@ -8183,16 +8154,16 @@ }, { "name": "fakerphp/faker", - "version": "v1.23.0", + "version": "v1.23.1", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01" + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", - "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/bfb4fe148adbf78eff521199619b93a52ae3554b", + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b", "shasum": "" }, "require": { @@ -8218,11 +8189,6 @@ "ext-mbstring": "Required for multibyte Unicode string functionality." }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "v1.21-dev" - } - }, "autoload": { "psr-4": { "Faker\\": "src/Faker/" @@ -8245,9 +8211,9 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.23.0" + "source": "https://github.com/FakerPHP/Faker/tree/v1.23.1" }, - "time": "2023-06-12T08:44:38+00:00" + "time": "2024-01-02T13:46:09+00:00" }, { "name": "filp/whoops", @@ -8427,22 +8393,22 @@ }, { "name": "laravel/sail", - "version": "v1.26.3", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "fa1ad5fbb03686dfc752bfd1861d86091cc1c32d" + "reference": "e40cc7ffb5186c45698dbd47e9477e0e429396d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/fa1ad5fbb03686dfc752bfd1861d86091cc1c32d", - "reference": "fa1ad5fbb03686dfc752bfd1861d86091cc1c32d", + "url": "https://api.github.com/repos/laravel/sail/zipball/e40cc7ffb5186c45698dbd47e9477e0e429396d0", + "reference": "e40cc7ffb5186c45698dbd47e9477e0e429396d0", "shasum": "" }, "require": { - "illuminate/console": "^9.0|^10.0|^11.0", - "illuminate/contracts": "^9.0|^10.0|^11.0", - "illuminate/support": "^9.0|^10.0|^11.0", + "illuminate/console": "^9.52.16|^10.0|^11.0", + "illuminate/contracts": "^9.52.16|^10.0|^11.0", + "illuminate/support": "^9.52.16|^10.0|^11.0", "php": "^8.0", "symfony/yaml": "^6.0|^7.0" }, @@ -8455,9 +8421,6 @@ ], "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, "laravel": { "providers": [ "Laravel\\Sail\\SailServiceProvider" @@ -8488,26 +8451,26 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2023-12-02T18:26:39+00:00" + "time": "2024-03-08T16:32:33+00:00" }, { "name": "maximebf/debugbar", - "version": "v1.19.1", + "version": "v1.21.3", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "03dd40a1826f4d585ef93ef83afa2a9874a00523" + "reference": "0b407703b08ea0cf6ebc61e267cc96ff7000911b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/03dd40a1826f4d585ef93ef83afa2a9874a00523", - "reference": "03dd40a1826f4d585ef93ef83afa2a9874a00523", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/0b407703b08ea0cf6ebc61e267cc96ff7000911b", + "reference": "0b407703b08ea0cf6ebc61e267cc96ff7000911b", "shasum": "" }, "require": { "php": "^7.1|^8", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^4|^5|^6" + "symfony/var-dumper": "^4|^5|^6|^7" }, "require-dev": { "phpunit/phpunit": ">=7.5.20 <10.0", @@ -8521,7 +8484,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-master": "1.21-dev" } }, "autoload": { @@ -8552,13 +8515,13 @@ ], "support": { "issues": "https://github.com/maximebf/php-debugbar/issues", - "source": "https://github.com/maximebf/php-debugbar/tree/v1.19.1" + "source": "https://github.com/maximebf/php-debugbar/tree/v1.21.3" }, - "time": "2023-10-12T08:10:52+00:00" + "time": "2024-03-12T14:23:07+00:00" }, { "name": "mockery/mockery", - "version": "1.6.7", + "version": "1.6.9", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", @@ -8788,20 +8751,21 @@ }, { "name": "phar-io/manifest", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", @@ -8842,9 +8806,15 @@ "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/2.0.3" + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "time": "2021-07-20T11:28:43+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", @@ -8952,21 +8922,21 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.7.3", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419" + "reference": "153ae662783729388a584b4361f2545e4d841e3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", - "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", "shasum": "" }, "require": { "doctrine/deprecations": "^1.0", - "php": "^7.4 || ^8.0", + "php": "^7.3 || ^8.0", "phpdocumentor/reflection-common": "^2.0", "phpstan/phpdoc-parser": "^1.13" }, @@ -9004,22 +8974,22 @@ "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.7.3" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" }, - "time": "2023-08-12T11:01:26+00:00" + "time": "2024-02-23T11:10:43+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "1.24.5", + "version": "1.26.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc" + "reference": "231e3186624c03d7e7c890ec662b81e6b0405227" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fedf211ff14ec8381c9bf5714e33a7a552dd1acc", - "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/231e3186624c03d7e7c890ec662b81e6b0405227", + "reference": "231e3186624c03d7e7c890ec662b81e6b0405227", "shasum": "" }, "require": { @@ -9051,22 +9021,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.5" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.26.0" }, - "time": "2023-12-16T09:33:33+00:00" + "time": "2024-02-23T16:05:55+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.30", + "version": "9.2.31", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", "shasum": "" }, "require": { @@ -9123,7 +9093,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" }, "funding": [ { @@ -9131,7 +9101,7 @@ "type": "github" } ], - "time": "2023-12-22T06:47:57+00:00" + "time": "2024-03-02T06:37:42+00:00" }, { "name": "phpunit/php-file-iterator", @@ -9376,16 +9346,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.15", + "version": "9.6.17", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" + "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd", + "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd", "shasum": "" }, "require": { @@ -9459,7 +9429,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.15" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.17" }, "funding": [ { @@ -9475,20 +9445,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T16:55:19+00:00" + "time": "2024-02-23T13:14:51+00:00" }, { "name": "sebastian/cli-parser", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", "shasum": "" }, "require": { @@ -9523,7 +9493,7 @@ "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" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" }, "funding": [ { @@ -9531,7 +9501,7 @@ "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2024-03-02T06:27:43+00:00" }, { "name": "sebastian/code-unit", @@ -9777,16 +9747,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", "shasum": "" }, "require": { @@ -9831,7 +9801,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" }, "funding": [ { @@ -9839,7 +9809,7 @@ "type": "github" } ], - "time": "2023-05-07T05:35:17+00:00" + "time": "2024-03-02T06:30:58+00:00" }, { "name": "sebastian/environment", @@ -9906,16 +9876,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", "shasum": "" }, "require": { @@ -9971,7 +9941,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" }, "funding": [ { @@ -9979,20 +9949,20 @@ "type": "github" } ], - "time": "2022-09-14T06:03:37+00:00" + "time": "2024-03-02T06:33:00+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.6", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bde739e7565280bda77be70044ac1047bc007e34" + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", - "reference": "bde739e7565280bda77be70044ac1047bc007e34", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", "shasum": "" }, "require": { @@ -10035,7 +10005,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" }, "funding": [ { @@ -10043,7 +10013,7 @@ "type": "github" } ], - "time": "2023-08-02T09:26:13+00:00" + "time": "2024-03-02T06:35:11+00:00" }, { "name": "sebastian/lines-of-code", @@ -10279,16 +10249,16 @@ }, { "name": "sebastian/resource-operations", - "version": "3.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", "shasum": "" }, "require": { @@ -10300,7 +10270,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -10321,8 +10291,7 @@ "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" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" }, "funding": [ { @@ -10330,7 +10299,7 @@ "type": "github" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2024-03-14T16:00:52+00:00" }, { "name": "sebastian/type", @@ -10505,21 +10474,20 @@ }, { "name": "spatie/flare-client-php", - "version": "1.4.3", + "version": "1.4.4", "source": { "type": "git", "url": "https://github.com/spatie/flare-client-php.git", - "reference": "5db2fdd743c3ede33f2a5367d89ec1a7c9c1d1ec" + "reference": "17082e780752d346c2db12ef5d6bee8e835e399c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/5db2fdd743c3ede33f2a5367d89ec1a7c9c1d1ec", - "reference": "5db2fdd743c3ede33f2a5367d89ec1a7c9c1d1ec", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/17082e780752d346c2db12ef5d6bee8e835e399c", + "reference": "17082e780752d346c2db12ef5d6bee8e835e399c", "shasum": "" }, "require": { "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0", - "nesbot/carbon": "^2.62.1", "php": "^8.0", "spatie/backtrace": "^1.5.2", "symfony/http-foundation": "^5.2|^6.0|^7.0", @@ -10563,7 +10531,7 @@ ], "support": { "issues": "https://github.com/spatie/flare-client-php/issues", - "source": "https://github.com/spatie/flare-client-php/tree/1.4.3" + "source": "https://github.com/spatie/flare-client-php/tree/1.4.4" }, "funding": [ { @@ -10571,20 +10539,20 @@ "type": "github" } ], - "time": "2023-10-17T15:54:07+00:00" + "time": "2024-01-31T14:18:45+00:00" }, { "name": "spatie/ignition", - "version": "1.11.3", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "3d886de644ff7a5b42e4d27c1e1f67c8b5f00044" + "reference": "5b6f801c605a593106b623e45ca41496a6e7d56d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/3d886de644ff7a5b42e4d27c1e1f67c8b5f00044", - "reference": "3d886de644ff7a5b42e4d27c1e1f67c8b5f00044", + "url": "https://api.github.com/repos/spatie/ignition/zipball/5b6f801c605a593106b623e45ca41496a6e7d56d", + "reference": "5b6f801c605a593106b623e45ca41496a6e7d56d", "shasum": "" }, "require": { @@ -10654,7 +10622,7 @@ "type": "github" } ], - "time": "2023-10-18T14:09:40+00:00" + "time": "2024-01-03T15:49:39+00:00" }, { "name": "spatie/laravel-ignition", @@ -10748,16 +10716,16 @@ }, { "name": "symfony/yaml", - "version": "v6.4.0", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587" + "reference": "d75715985f0f94f978e3a8fa42533e10db921b90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/4f9237a1bb42455d609e6687d2613dde5b41a587", - "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587", + "url": "https://api.github.com/repos/symfony/yaml/zipball/d75715985f0f94f978e3a8fa42533e10db921b90", + "reference": "d75715985f0f94f978e3a8fa42533e10db921b90", "shasum": "" }, "require": { @@ -10800,7 +10768,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.0" + "source": "https://github.com/symfony/yaml/tree/v6.4.3" }, "funding": [ { @@ -10816,20 +10784,20 @@ "type": "tidelift" } ], - "time": "2023-11-06T11:00:25+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { @@ -10858,7 +10826,7 @@ "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/1.2.2" + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { @@ -10866,7 +10834,7 @@ "type": "github" } ], - "time": "2023-11-20T00:12:19+00:00" + "time": "2024-03-03T12:36:25+00:00" } ], "aliases": [], @@ -10878,5 +10846,5 @@ "php": "^8.0" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/config/print.php b/config/print.php index 3e5c9f1c6..8fa5667d6 100644 --- a/config/print.php +++ b/config/print.php @@ -2,10 +2,8 @@ return [ - 'cost' => [ - 'one_sided' => env('PRINT_COST_ONESIDED'), - 'two_sided' => env('PRINT_COST_TWOSIDED'), - ], + 'one_sided_cost' => env('PRINT_COST_ONESIDED'), + 'two_sided_cost' => env('PRINT_COST_TWOSIDED'), // Maximum accepted PDF size in byte. 'pdf_size_limit' => env('PRINT_MAX_FILE_SIZE', 5000000), diff --git a/database/factories/PrintJobFactory.php b/database/factories/PrintJobFactory.php index 801b7ee4c..5eae04289 100644 --- a/database/factories/PrintJobFactory.php +++ b/database/factories/PrintJobFactory.php @@ -2,6 +2,7 @@ namespace Database\Factories; +use App\Enums\PrintJobStatus; use App\Models\PrintJob; use Illuminate\Database\Eloquent\Factories\Factory; @@ -13,8 +14,7 @@ public function definition() { return [ 'filename' => $this->faker->text, - 'filepath' => $this->faker->text, - 'state' => $this->faker->randomElement(PrintJob::STATES), + 'state' => $this->faker->randomElement(PrintJobStatus::cases()), 'job_id' => $this->faker->randomNumber, 'cost' => $this->faker->numberBetween(8, 1000), ]; diff --git a/database/migrations/2019_10_06_224327_create_print_jobs_table.php b/database/migrations/2019_10_06_224327_create_print_jobs_table.php index 0f3817600..f20bacf52 100644 --- a/database/migrations/2019_10_06_224327_create_print_jobs_table.php +++ b/database/migrations/2019_10_06_224327_create_print_jobs_table.php @@ -1,5 +1,6 @@ text('filename'); $table->text('filepath'); $table->unsignedBigInteger('user_id')->nullable(); - $table->set('state', \App\Models\PrintJob::STATES); + $table->set('state', array_map(fn ($state) => $state->value, PrintJobStatus::cases())); $table->unsignedBigInteger('job_id'); $table->unsignedInteger('cost'); $table->timestamps(); diff --git a/database/migrations/2023_12_25_182310_create_printers_table.php b/database/migrations/2023_12_25_182310_create_printers_table.php new file mode 100644 index 000000000..3de21d905 --- /dev/null +++ b/database/migrations/2023_12_25_182310_create_printers_table.php @@ -0,0 +1,42 @@ +id(); + $table->string('name')->unique(); + $table->string('ip')->nullable(); + $table->string('port')->nullable(); + $table->timestamp('paper_out_at')->nullable(); + }); + + + // Create the default printer + DB::table('printers')->insert([ + 'name' => env('PRINTER_NAME'), + 'ip' => env('PRINTER_IP'), + 'port' => env('PRINTER_PORT'), + ]); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('printers'); + } +}; diff --git a/database/migrations/2023_12_25_184733_update_print_jobs_table.php b/database/migrations/2023_12_25_184733_update_print_jobs_table.php new file mode 100644 index 000000000..f40375192 --- /dev/null +++ b/database/migrations/2023_12_25_184733_update_print_jobs_table.php @@ -0,0 +1,37 @@ +foreignIdFor(Printer::class)->nullable()->after('user_id')->constrained()->nullOnDelete(); + $table->boolean('used_free_pages')->default(false)->after('cost'); + $table->dropColumn('filepath'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('print_jobs', function (Blueprint $table) { + $table->dropForeign(['printer_id']); + $table->dropColumn('printer_id'); + $table->dropColumn('used_free_pages'); + $table->string('filepath')->after('user_id'); + }); + } +}; diff --git a/database/seeders/UsersTableSeeder.php b/database/seeders/UsersTableSeeder.php index 102299d61..817426efb 100644 --- a/database/seeders/UsersTableSeeder.php +++ b/database/seeders/UsersTableSeeder.php @@ -105,7 +105,6 @@ private function createCollegist($user) ); $user->educationalInformation()->save(EducationalInformation::factory()->make(['user_id' => $user->id])); StudyLine::factory()->count(rand(1, 2))->create(['educational_information_id' => $user->educationalInformation->id]); - $user->roles()->attach(Role::get(Role::PRINTER)->id); $wifi_username = $user->internetAccess->setWifiCredentials(); WifiConnection::factory($user->id % 5)->create(['wifi_username' => $wifi_username]); for ($x = 0; $x < rand(1, 3); $x++) { diff --git a/resources/views/dormitory/print/app.blade.php b/resources/views/dormitory/print/app.blade.php index f3c818d0b..e4c843f57 100644 --- a/resources/views/dormitory/print/app.blade.php +++ b/resources/views/dormitory/print/app.blade.php @@ -9,10 +9,10 @@ @include("dormitory.print.print")
- @include("dormitory.print.history", ['route' => route('print.print_jobs.list')]) + @include("dormitory.print.history", ['route' => route('print-job.index'), 'admin' => false])
- @include("dormitory.print.free", ['route' => route('print.free_pages.list')]) + @include("dormitory.print.free", ['route' => route('free-pages.index'), 'admin' => false])
@include("dormitory.print.send") diff --git a/resources/views/dormitory/print/free.blade.php b/resources/views/dormitory/print/free.blade.php index 15aced843..e8800dc8f 100644 --- a/resources/views/dormitory/print/free.blade.php +++ b/resources/views/dormitory/print/free.blade.php @@ -27,6 +27,7 @@ ajaxURL: "{{ $route }}", //set url for ajax request placeholder: "@lang('print.no_free_pages')", columns: [ + @if($admin) @can('viewAny', App\Models\FreePages::class) { title: "@lang('internet.created_at')", @@ -41,6 +42,7 @@ sorter: "string", headerFilter: 'input' }, + @endif @endcan { title: "@lang('print.free')", @@ -52,11 +54,12 @@ title: "@lang('print.deadline')", field: "deadline", sorter: "datetime", + formatter:dateFormatter, @can('viewAny', App\Models\FreePages::class) headerFilter: 'input' @endif }, { title: "@lang('print.last_modified_by')", - field: "modifier", + field: "modifier.name", sorter: "string", @can('viewAny', App\Models\FreePages::class) headerFilter: 'input' @endif }, diff --git a/resources/views/dormitory/print/history.blade.php b/resources/views/dormitory/print/history.blade.php index 8645ad6a5..1ae3a31c2 100644 --- a/resources/views/dormitory/print/history.blade.php +++ b/resources/views/dormitory/print/history.blade.php @@ -7,13 +7,13 @@ $(document).ready(function() { var deleteButton = function(cell, formatterParams, onRendered) { var data = cell.getRow().getData(); - if(data.state == '@lang('print.'.App\Models\PrintJob::QUEUED)'){ + if(data.state == "QUEUED"){ return $( "" ).click(function() { $.ajax({ - type: "POST", - url: "{{ route('print.print_jobs.cancel', [':id']) }}".replace(':id', data.id), + type: "PUT", + url: "{{ route('print-job.update', [':job']) }}".replace(':job', data.id), success: function() { cell.getTable().setPage(cell.getTable().getPage()); }, @@ -49,22 +49,24 @@ placeholder: "@lang('internet.nothing_to_show')", headerSort: false, columnMinWidth:200, - columns: [{ + columns: [ + { title: "@lang('internet.created_at')", field: "created_at", sorter: "datetime", formatter:dateFormatter, @can('viewAny', App\Models\PrintJob::class) headerFilter: 'input' @endcan }, + @if ($admin) @can('viewAny', App\Models\PrintJob::class) { - //TODO empty when not in admin view title: "@lang('print.user')", field: "user.name", sorter: "string", headerFilter: 'input' }, @endcan + @endif { title: "@lang('print.document')", field: "filename", @@ -73,18 +75,18 @@ }, { title: "@lang('print.cost')", - field: "cost", + field: "translated_cost", sorter: "string", @can('viewAny', App\Models\PrintJob::class) headerFilter: 'input' @endcan }, { title: "@lang('print.state')", - field: "state", + field: "translated_state", sorter: "string", @can('viewAny', App\Models\PrintJob::class) headerFilterParams: { - @foreach(\App\Models\PrintJob::STATES as $key => $state) - "{{ $state }}": "@lang('print.' . $state)", + @foreach(\App\Enums\PrintJobStatus::cases() as $state) + "{{ $state }}": "@lang('print.' . $state->value)", @endforeach } @endcan diff --git a/resources/views/dormitory/print/manage/account_history.blade.php b/resources/views/dormitory/print/manage/account_history.blade.php index 7290b931b..aa60f2406 100644 --- a/resources/views/dormitory/print/manage/account_history.blade.php +++ b/resources/views/dormitory/print/manage/account_history.blade.php @@ -6,7 +6,7 @@ paginationSize: 20, layout: "fitColumns", pagination: "remote", //enable remote pagination - ajaxURL: "{{ route('print.account_history') }}", //set url for ajax request + ajaxURL: "{{ route('print-account-history.index') }}", //set url for ajax request ajaxSorting: true, ajaxFiltering: true, placeholder: "@lang('general.nothing_to_show')", diff --git a/resources/views/dormitory/print/manage/app.blade.php b/resources/views/dormitory/print/manage/app.blade.php index 5ec642741..346d6c3b5 100644 --- a/resources/views/dormitory/print/manage/app.blade.php +++ b/resources/views/dormitory/print/manage/app.blade.php @@ -30,10 +30,10 @@
- @include("dormitory.print.free", ['route' => route('print.free_pages.list.all')]) + @include("dormitory.print.free", ['route' => route('free-pages.index.admin'), 'admin' => true])
- @include("dormitory.print.history", ['route' => route('print.print_jobs.list.all') ]) + @include("dormitory.print.history", ['route' => route('print-job.index', ['filter' => 'all']), 'admin' => true])
diff --git a/resources/views/dormitory/print/manage/free.blade.php b/resources/views/dormitory/print/manage/free.blade.php index 29892e9f1..7ceb953e8 100644 --- a/resources/views/dormitory/print/manage/free.blade.php +++ b/resources/views/dormitory/print/manage/free.blade.php @@ -1,10 +1,10 @@ @can('create', \App\Models\FreePages::class) Ingyenes oldalak hozzáadása
-
+ @csrf - - + + diff --git a/resources/views/dormitory/print/manage/modify.blade.php b/resources/views/dormitory/print/manage/modify.blade.php index 5fc650321..1305a983a 100644 --- a/resources/views/dormitory/print/manage/modify.blade.php +++ b/resources/views/dormitory/print/manage/modify.blade.php @@ -2,10 +2,11 @@ Egyenleg módosítása
A tranzakció az admin kasszába fog kerülni.
- + @csrf - - + @method('PUT') + +
diff --git a/resources/views/dormitory/print/print.blade.php b/resources/views/dormitory/print/print.blade.php index f50c5802d..6d8c467b6 100644 --- a/resources/views/dormitory/print/print.blade.php +++ b/resources/views/dormitory/print/print.blade.php @@ -1,3 +1,12 @@ +@php + /** + * Variables: + * $user -> the current user + * $users -> all users, used to transfer money between print accounts + * $printer -> the model corresponding to the printer, which is used to print (currently only one is available at all times) + */ + $printAccount = $user->printAccount; +@endphp
@lang('print.print_document') @@ -5,22 +14,23 @@

@lang('print.pdf_description') @lang("print.pdf_maxsize", ['maxsize' => config('print.pdf_size_limit')/1000/1000]) - @lang('print.costs',['one_sided'=>App\Models\PrintAccount::$COST['one_sided'], "two_sided" => env('PRINT_COST_TWOSIDED')]) + @lang('print.costs',['one_sided'=>config('print.one_sided_cost'), "two_sided" => config('print.two_sided_cost')])

- @lang('print.available_money'): {{ user()->printAccount->balance }} HUF. + @lang('print.available_money'): {{ $printAccount->balance }} HUF. @lang('print.upload_money')

-
@csrf - @method('PUT')
- - + + - @if($free_pages>0) {{-- only show when user have active free pages --}} - + @if($printAccount->available_free_pages->sum('amount') > 0) {{-- only show when user have active free pages --}} + @else @@ -30,22 +40,27 @@
- @if(Cache::has('print.no-paper')) - @lang('print.no-paper-reported', ['date' => Cache::get('print.no-paper')]) + @if($printer->paper_out_at != null) + @lang('print.no-paper-reported', ['date' => $printer->paper_out_at]) @else @lang('print.no-paper-description') @endif
- @if(Cache::has('print.no-paper') && user()->can('handleAny', \App\Models\PrintAccount::class)) - + @if($printer->paper_out_at != null && $user->can('handleAny', \App\Models\PrintAccount::class)) + + @method('PUT') @csrf + {{-- value set to "1" instead of true so that laravel has no problem with validation --}} + @else -
+ + @method('PUT') @csrf + @endif
diff --git a/resources/views/dormitory/print/send.blade.php b/resources/views/dormitory/print/send.blade.php index 8a39eb240..8c6ede6e0 100644 --- a/resources/views/dormitory/print/send.blade.php +++ b/resources/views/dormitory/print/send.blade.php @@ -4,11 +4,13 @@
@lang('print.how_transfer_works')
-
+ @csrf + @method('PUT')
- - + + +
diff --git a/resources/views/emails/no_paper.blade.php b/resources/views/emails/no_paper.blade.php index 9b363c516..70b87fa0a 100644 --- a/resources/views/emails/no_paper.blade.php +++ b/resources/views/emails/no_paper.blade.php @@ -1,5 +1,5 @@ @component('mail::message') -

@lang('mail.dear') {{ $recipient }}!

+

@lang('mail.dear') Rendszergazdák!

{{ $reporter }} az imént jelezte, hogy kifogyott a papír a nyomtatóból.

diff --git a/resources/views/layouts/navbar.blade.php b/resources/views/layouts/navbar.blade.php index 953b2e75a..dab58b649 100644 --- a/resources/views/layouts/navbar.blade.php +++ b/resources/views/layouts/navbar.blade.php @@ -37,8 +37,7 @@ class="material-icons">menu @if(Auth::user()?->verified) @can('use', \App\Models\PrintAccount::class) -
  • local_printshop@lang('print.print')
  • +
  • local_printshop@lang('print.print')
  • @endif
  • person_searchFelvételi
  • @endcan @if(Auth::user()->isAdmin() || Auth::user()->isCollegist()) - {{-- Sysadmin module --}} -
  • - - admin_panel_settings - Rendszergazda - arrow_drop_down - -
    -
      - - @can('handleAny', \App\Models\PrintAccount::class) -
    • - - local_printshopNyomtatás - -
    • - @endcan + {{-- Sysadmin module --}} +
    • + + admin_panel_settings + Rendszergazda + arrow_drop_down + +
      +
        + + @can('handleAny', \App\Models\PrintAccount::class) +
      • + + local_printshopNyomtatás + +
      • + @endcan @can('handleAny', \App\Models\Internet\InternetAccess::class) diff --git a/resources/views/secretariat/document/import.blade.php b/resources/views/secretariat/document/import.blade.php index 948dfa170..b588a6014 100644 --- a/resources/views/secretariat/document/import.blade.php +++ b/resources/views/secretariat/document/import.blade.php @@ -62,10 +62,8 @@
        letöltés - @can('print.print') Nyomtatás - @endcan
    diff --git a/resources/views/secretariat/document/index.blade.php b/resources/views/secretariat/document/index.blade.php index 96e20299e..fa11e813b 100644 --- a/resources/views/secretariat/document/index.blade.php +++ b/resources/views/secretariat/document/index.blade.php @@ -24,9 +24,7 @@ - @can('print.print') - @endcan @endcan @@ -40,9 +38,7 @@ - @can('print.print') - @endcan @endcan diff --git a/resources/views/user/printing.blade.php b/resources/views/user/printing.blade.php index 989eb8972..9c12b173e 100644 --- a/resources/views/user/printing.blade.php +++ b/resources/views/user/printing.blade.php @@ -11,14 +11,14 @@ @foreach($user->freePages->sortBy('deadline') as $page)
  • {{ $page->amount }} - {{ $page->lastModifiedBy()?->name }}: {{ $page->comment }} + {{ $page->modifier?->name }}: {{ $page->comment }}
  • @endforeach diff --git a/routes/web.php b/routes/web.php index c77401386..b3c675438 100644 --- a/routes/web.php +++ b/routes/web.php @@ -14,13 +14,16 @@ use App\Http\Controllers\Auth\ApplicationController; use App\Http\Controllers\Auth\RegisterController; use App\Http\Controllers\Dormitory\FaultController; -use App\Http\Controllers\Dormitory\PrintController; +use App\Http\Controllers\Dormitory\Printing\FreePagesController; +use App\Http\Controllers\Dormitory\Printing\PrinterController; +use App\Http\Controllers\Dormitory\Printing\PrintJobController; +use App\Http\Controllers\Dormitory\Printing\PrintAccountController; +use App\Http\Controllers\Dormitory\Printing\PrintAccountHistoryController; use App\Http\Controllers\Dormitory\RoomController; use App\Http\Controllers\HomeController; use App\Http\Controllers\LocaleController; use App\Http\Controllers\Network\AdminCheckoutController; use App\Http\Controllers\Network\AdminInternetController; -use App\Http\Controllers\Network\AdminMacAddressController; use App\Http\Controllers\Network\InternetController; use App\Http\Controllers\Network\MacAddressController; use App\Http\Controllers\Network\RouterController; @@ -111,22 +114,20 @@ }); /** Printing */ - Route::get('/print', [PrintController::class, 'index'])->name('print'); - Route::post('/print/no-paper', [PrintController::class, 'noPaper'])->name('print.no_paper'); - Route::post('/print/added-paper', [PrintController::class, 'addedPaper'])->name('print.added_paper'); - Route::get('/print/free_pages/list', [PrintController::class, 'listFreePages'])->name('print.free_pages.list'); - Route::get('/print/print_jobs/list', [PrintController::class, 'listPrintJobs'])->name('print.print_jobs.list'); - Route::get('/print/free_pages/list/all', [PrintController::class, 'listAllFreePages'])->name('print.free_pages.list.all'); - Route::get('/print/print_jobs/list/all', [PrintController::class, 'listAllPrintJobs'])->name('print.print_jobs.list.all'); - Route::post('/print/transfer_balance', [PrintController::class, 'transferBalance'])->name('print.transfer-balance'); - Route::post('/print/print_jobs/{id}/cancel', [PrintController::class, 'cancelPrintJob'])->name('print.print_jobs.cancel'); - Route::put('/print/print', [PrintController::class, 'print'])->name('print.print'); - Route::middleware(['can:modify,App\Models\PrintAccount'])->group(function () { - Route::get('/print/account_history', [PrintController::class, 'listPrintAccountHistory'])->name('print.account_history'); - Route::get('/print/manage', [PrintController::class, 'admin'])->name('print.manage'); - Route::post('/print/modify_balance', [PrintController::class, 'modifyBalance'])->name('print.modify'); - }); - Route::post('/print/add_free_pages', [PrintController::class, 'addFreePages'])->name('print.free_pages')->middleware('can:create,App\Models\FreePages'); + Route::get('/printer/{page?}', [PrinterController::class, 'index'])->name('printer.index'); // also print.manage, print + Route::put('/printer/{printer}', [PrinterController::class, 'update'])->name('printer.update'); // print.added_paper, print.no_paper + + Route::get('/print-job/{filter?}', [PrintJobController::class, 'indexPrintJobs'])->name('print-job.index'); // print.print_jobs.list, print.print_jobs.list.all + Route::post('print-job', [PrintJobController::class, 'store'])->name('print-job.store'); // print.print + Route::put('/print-job/{job}', [PrintJobController::class, 'update'])->name('print-job.update'); // print.print_jobs.cancel + + Route::get('/free-pages', [FreePagesController::class, 'index'])->name('free-pages.index'); // print.free_pages.list, print.free_pages.list.all + Route::post('/free-pages', [FreePagesController::class, 'store'])->name('free-pages.store'); // print.free_pages + Route::get('/free-pages/admin', [FreePagesController::class, 'adminIndex'])->name('free-pages.index.admin'); // print.free_pages.manage + + Route::put('/print-account', [PrintAccountController::class, 'update'])->name('print-account.update'); // print.transfer-balance, print.modify + + Route::get('/print-account-history', [PrintAccountHistoryController::class, 'indexPrintAccountHistory'])->name('print-account-history.index'); //print.account_history Route::prefix('internet')->name('internet.')->group(function () { Route::get('/', [InternetController::class, 'index'])->name('index'); diff --git a/tests/Feature/PrintControllerTest.php b/tests/Feature/PrintControllerTest.php index e4670907e..cf416fcf9 100644 --- a/tests/Feature/PrintControllerTest.php +++ b/tests/Feature/PrintControllerTest.php @@ -56,7 +56,6 @@ public function testUserWithPrinterPermissions() { $user = User::factory()->create(); $user->setVerified(); - $user->roles()->attach(Role::get(Role::PRINTER)->id); $this->actingAs($user); $response = $this->get('/print'); @@ -96,7 +95,6 @@ public function testUserWithPrintAdminPermissions() { $user = User::factory()->create(); $user->setVerified(); - $user->roles()->attach(Role::get(Role::PRINTER)->id); $user->roles()->attach(Role::get(Role::SYS_ADMIN)->id); $this->actingAs($user); @@ -136,12 +134,10 @@ public function testBalanceTransfer() $sender = User::factory()->create(); $sender->setVerified(); - $sender->roles()->attach(Role::get(Role::PRINTER)->id); $this->actingAs($sender); $reciever = User::factory()->create(); $reciever->setVerified(); - $reciever->roles()->attach(Role::get(Role::PRINTER)->id); // Setting initial valeus $this->assertEquals($sender->printAccount->balance, 0); @@ -187,7 +183,6 @@ public function testModifyBalance() $reciever = User::factory()->create(); $reciever->setVerified(); - $reciever->roles()->attach(Role::firstWhere('name', Role::PRINTER)->id); // Asserting initial valeus $this->assertEquals($sender->printAccount->balance, 0); diff --git a/tests/Feature/RegistrationTest.php b/tests/Feature/RegistrationTest.php index d19756977..12540da39 100644 --- a/tests/Feature/RegistrationTest.php +++ b/tests/Feature/RegistrationTest.php @@ -57,7 +57,6 @@ public function test_register_collegist() 'status' => ApplicationForm::STATUS_IN_PROGRESS ]); - $this->assertTrue($user->hasRole(Role::PRINTER)); $this->assertTrue($user->hasRole(Role::COLLEGIST)); } @@ -102,8 +101,6 @@ public function test_tenant_collegist() 'user_id' => $user->id, 'balance' => 0 ]); - - $this->assertTrue($user->hasRole(Role::PRINTER)); $this->assertTrue($user->hasRole(Role::TENANT)); } } diff --git a/tests/Unit/PrintTest.php b/tests/Unit/PrintTest.php index 70c354b2f..0923b530f 100644 --- a/tests/Unit/PrintTest.php +++ b/tests/Unit/PrintTest.php @@ -18,7 +18,6 @@ class PrintTest extends TestCase public function testPrintAccount() { $user = User::factory()->create(); - //$user->roles()->attach(Role::getId(Role::PRINTER)); $this->assertNotNull($user->printAccount); $this->assertEquals($user->printAccount, PrintAccount::find($user->id));