From 676ac18e89a79c68721341e10dc4c29515df331c Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Wed, 3 Jan 2024 18:24:42 +0100 Subject: [PATCH 01/55] refactor --- .env.example | 2 + app/Console/Commands.php | 51 --- app/Console/Commands/CreateDefaultPrinter.php | 39 +++ app/Enums/PrintJobStatus.php | 10 + .../Controllers/Dormitory/PrintController.php | 323 ------------------ .../Printing/FreePagesController.php | 66 ++++ .../Printing/PrintAccountController.php | 115 +++++++ .../PrintAccountHistoryController.php | 26 ++ .../Dormitory/Printing/PrintJobController.php | 208 +++++++++++ .../Dormitory/Printing/PrinterController.php | 60 ++++ app/Mail/NoPaper.php | 4 +- app/Models/FreePages.php | 19 +- app/Models/PrintAccount.php | 91 +++-- app/Models/PrintAccountHistory.php | 6 +- app/Models/PrintJob.php | 76 +++-- app/Models/Printer.php | 129 +++++++ app/Policies/PrintAccountPolicy.php | 10 +- app/Utils/Printer.php | 160 --------- config/print.php | 6 +- database/factories/PrintJobFactory.php | 4 +- ...9_10_06_224327_create_print_jobs_table.php | 3 +- ...023_12_25_182310_create_printers_table.php | 34 ++ ...3_12_25_184733_update_print_jobs_table.php | 38 +++ resources/views/dormitory/print/app.blade.php | 4 +- .../views/dormitory/print/free.blade.php | 4 +- .../views/dormitory/print/history.blade.php | 18 +- .../print/manage/account_history.blade.php | 2 +- .../dormitory/print/manage/app.blade.php | 4 +- .../dormitory/print/manage/free.blade.php | 6 +- .../dormitory/print/manage/modify.blade.php | 7 +- .../views/dormitory/print/print.blade.php | 35 +- .../views/dormitory/print/send.blade.php | 8 +- resources/views/emails/no_paper.blade.php | 2 +- resources/views/layouts/navbar.blade.php | 4 +- resources/views/user/printing.blade.php | 4 +- routes/web.php | 35 +- 36 files changed, 944 insertions(+), 669 deletions(-) create mode 100644 app/Console/Commands/CreateDefaultPrinter.php create mode 100644 app/Enums/PrintJobStatus.php delete mode 100644 app/Http/Controllers/Dormitory/PrintController.php create mode 100644 app/Http/Controllers/Dormitory/Printing/FreePagesController.php create mode 100644 app/Http/Controllers/Dormitory/Printing/PrintAccountController.php create mode 100644 app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php create mode 100644 app/Http/Controllers/Dormitory/Printing/PrintJobController.php create mode 100644 app/Http/Controllers/Dormitory/Printing/PrinterController.php create mode 100644 app/Models/Printer.php delete mode 100644 app/Utils/Printer.php create mode 100644 database/migrations/2023_12_25_182310_create_printers_table.php create mode 100644 database/migrations/2023_12_25_184733_update_print_jobs_table.php 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/app/Console/Commands.php b/app/Console/Commands.php index 6af3de083..a8ef4700a 100644 --- a/app/Console/Commands.php +++ b/app/Console/Commands.php @@ -15,57 +15,6 @@ 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()) { diff --git a/app/Console/Commands/CreateDefaultPrinter.php b/app/Console/Commands/CreateDefaultPrinter.php new file mode 100644 index 000000000..c36d20775 --- /dev/null +++ b/app/Console/Commands/CreateDefaultPrinter.php @@ -0,0 +1,39 @@ + env('PRINTER_NAME'), + 'ip' => env('PRINTER_IP'), + 'port' => env('PRINTER_PORT'), + ]); + + return Command::SUCCESS; + } +} 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 @@ +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..173982bee --- /dev/null +++ b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php @@ -0,0 +1,66 @@ +authorize('viewAny', FreePages::class); + + return $this->freePagesPaginator( + freePages: FreePages::with('user'), + columns: [ + 'amount', + 'deadline', + 'modifier', + 'comment', + 'user.name', + 'created_at', + ] + ); + } + + $this->authorize('viewSelf', FreePages::class); + + return $this->freePagesPaginator( + freePages: user()->freePages(), + columns: [ + 'amount', + 'deadline', + 'modifier', + 'comment', + ] + ); + } + + private function freePagesPaginator(Builder $freePages, array $columns) { + $paginator = TabulatorPaginator::from( + $freePages->with('modifier') + )->sortable($columns)->filterable($columns)->paginate(); + return $paginator; + } + + 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..93769c7b1 --- /dev/null +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php @@ -0,0 +1,115 @@ +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 + if (user()->cannot('transferBalance', $printAccount)) { + abort(403); + } + + $otherAccount = $request->other_user ? User::find($request->get('other_user'))->printAccount : null; + + // This is a transfer between accounts + if ($otherAccount !== null) { + // 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); + } + + $amount = $request->get('amount'); + + // 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, + ]); + + Mail::to($printAccount->user)->queue(new ChangedPrintBalance($printAccount->user, $request->get('amount'), user()->name)); + + return redirect()->back()->with('message', __('general.successful_transaction')); + } + // This is a modification of the current account + else { + // Only admins can modify accounts + if (user()->cannot('modify', $printAccount)) { + abort(403); + } + + $amount = $request->get('amount'); + + 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, $request->get('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, + ]); + + return redirect()->back()->with('message', __('general.successful_modification')); + } + } + + 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..0c17bb03c --- /dev/null +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php @@ -0,0 +1,26 @@ +authorize('viewAny', PrintJob::class); + + $columns = ['user.name', 'balance_change', 'free_page_change', 'deadline_change', 'modifier.name', 'modified_at']; + return 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') // TODO: check this + ->with('modifier') + )->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..edb9e2daa --- /dev/null +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -0,0 +1,208 @@ +authorize('viewAny', PrintJob::class); + + PrintJob::checkAndUpdateStatuses(); + + return $this->paginatorFrom( + printJobs: PrintJob::query() + ->with('user') + ->orderBy('print_jobs.created_at', 'desc'), // TODO: test if it works without join + columns: [ + 'created_at', + 'filename', + 'cost', + 'state', + 'user.name', + ] + ); + } + + $this->authorize('viewSelf', PrintJob::class); + + PrintJob::checkAndUpdateStatuses(); + 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) { + $request->validate([ + 'file' => 'required|file', + 'copies' => 'required|integer|min:1', + 'two_sided' => 'boolean', + 'printer_id' => 'nullable|exists:printers,id', + 'use_free_pages' => 'nullable|boolean', + ]); + + $useFreePages = $request->boolean('use_free_pages'); + $copyNumber = $request->get('copies'); + $twoSided = $request->get('two_sided'); + $file = $request->file('file'); + + /** @var Printer */ + $printer = $request->printer_id ? Printer::find($request->get("printer_id")) : Printer::firstWhere('name', config('print.printer_name')); + + $path = $file->store('print-documents'); + $pageNumber = Printer::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); + } catch (\Exception $e) { + return back()->with('error', __('print.error_printing')); + } finally { + Storage::delete($path); + } + + $cost = $useFreePages ? + PrintAccount::getFreePagesNeeeded($pageNumber, $copyNumber, $twoSided) : + PrintAccount::getBalanceNeeded($pageNumber, $copyNumber, $twoSided); + + 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; + } + } + } else { + $printAccount->balance -= $cost; + } + + $printAccount->save(); + + return back()->with('message', __('print.success')); + } + + /** + * Cancels a `PrintJob` + * @param PrintJob $job + * @return RedirectResponse + */ + public function update(PrintJob $job) { + Log::info('asd'); + $this->authorize('update', $job); + Log::info($job->state->value); + + if ($job->state === PrintJobStatus::QUEUED ) { + $result = ($job->printer ?? Printer::firstWhere('name', config('print.printer_name')))->cancelPrintJob($job); + 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")); + } + } + + + + 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()->transform(function (PrintJob $printJob) { + $printJob->translatedState = __("print." . strtoupper($printJob->state->value)); + $printJob->cost = "$printJob->cost HUF"; + return $printJob; + }); + + 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..4d2f88de9 --- /dev/null +++ b/app/Http/Controllers/Dormitory/Printing/PrinterController.php @@ -0,0 +1,60 @@ +authorize('handleAny', PrintAccount::class); + + return view('dormitory.print.manage.app', ["users" => User::all()]); + } + + return view('dormitory.print.app', [ + "users" => User::printers(), + "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->update([ + "paper_out_at" => now(), + ]); + 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 807a435eb..a9c8df0ad 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. @@ -27,23 +28,27 @@ class FreePages extends Model 'comment', ]; - public function user() + protected $casts = [ + 'deadline' => 'date', + ]; + + public function user(): BelongsTo { - return $this->belongsTo('App\Models\User'); + return $this->belongsTo(User::class); } 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() + protected function getAvailableAttribute() { - return $this->deadline > date('Y-m-d'); + return now()->isBefore($this->deadline); } - public function lastModifiedBy() + 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 2333872b0..2730b17dc 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. @@ -11,11 +15,9 @@ * * @property mixed $user_id */ -class PrintAccount extends Model -{ +class PrintAccount extends Model { use HasFactory; - protected $table = 'print_accounts'; protected $primaryKey = 'user_id'; public $incrementing = false; public $timestamps = false; @@ -36,33 +38,78 @@ class PrintAccount extends Model 'balance' => 0, ]; - public function user() - { - return $this->belongsTo('App\Models\User'); + public function user() { + return $this->belongsTo(User::class); } - public function freePages() - { - return $this->hasMany('App\Models\FreePages', 'user_id', 'user_id'); + public function freePages() { + return $this->hasMany(FreePages::class, 'user_id', 'user_id'); } - public function hasEnoughMoney($balance) - { - return $this->balance >= abs($balance); + /** + * The free pages which are currently available. Sorts the free pages by their deadline. + * @return Collection + */ + public function getAvailableFreePagesAttribute() { + return $this->freePages()->where('deadline', '>', now())->orderBy('deadline')->get(); + } + + /** + * 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) { + return $this->getAvailableFreePagesAttribute()->sum('amount') > + $this::getFreePagesNeeeded($pages, $copies, $twoSided); + } + + /** + * 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 >= $this::getBalanceNeeded($pages, $twoSided, $copies); } - public static function getCost($pages, $is_two_sided, $number_of_copies) - { - if (!$is_two_sided) { - return $pages * self::$COST['one_sided'] * $number_of_copies; + /** + * 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); } - $orphan_ending = $pages % 2; - $one_copy_cost = floor($pages / 2) * self::$COST['two_sided'] - + $orphan_ending * self::$COST['one_sided']; + return [ + 'one_sided' => $oneSidedPages, + 'two_sided' => $twoSidedPages, + ]; + } + + public static function getFreePagesNeeeded(int $pages, $copies, $twoSided) { + $pageTypesNeeded = self::getPageTypesNeeded($pages, $twoSided); - return $one_copy_cost * $number_of_copies; + return ($pageTypesNeeded['one_sided'] + $pageTypesNeeded['two_sided']) * $copies; } -} -PrintAccount::$COST = config('print.cost'); + 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; + } +} diff --git a/app/Models/PrintAccountHistory.php b/app/Models/PrintAccountHistory.php index b8744108d..4634060ef 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. class PrintAccountHistory extends Model { protected $table = 'print_account_history'; @@ -23,11 +23,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 d9c4f108e..ce8e0540b 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -2,56 +2,66 @@ namespace App\Models; +use App\Enums\PrintJobStatus; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasOneThrough; +use Log; /** * @property mixed $user_id */ -class PrintJob extends Model -{ +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' ]; - 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'); + public function user() { + return $this->belongsTo(User::class); } - public static function translateStates(): \Closure - { - return function ($data) { - $data->state = __('print.'.strtoupper($data->state)); - - return $data; - }; + public function printer() { + return $this->belongsTo(Printer::class); + } + + /** + * `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 $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 + ); } - public static function addCurrencyTag(): \Closure - { - return function ($data) { - $data->cost = "{$data->cost} HUF"; - - return $data; - }; + /** + * Gets the printjob-status with every printer, updates the status of the completed printjobs. + */ + public static function checkAndUpdateStatuses() { + foreach(PrintJob::query()->where('state', PrintJobStatus::QUEUED)->whereNotNull('printer_id')->pluck('printer_id')->unique() as $printer_id) { + $printJobs = Printer::find($printer_id)->getCompletedPrintJobs(); + PrintJob::whereIn('job_id', $printJobs)->update(['state' => PrintJobStatus::SUCCESS]); + } } } diff --git a/app/Models/Printer.php b/app/Models/Printer.php new file mode 100644 index 000000000..6461b43f7 --- /dev/null +++ b/app/Models/Printer.php @@ -0,0 +1,129 @@ + 'datetime', + ]; + + public function printJobs() { + return $this->hasMany(PrintJob::class); + } + + /** + * Attemts to cancel the given `PrintJob`. Returns wether it was successful. + * @param PrintJob $printJob + * @return PrinterCancelResult + */ + public function cancelPrintJob(PrintJob $printJob) { + $command = "cancel $printJob->job_id -h $this->ip:$this->port"; + if (config('app.debug')) { + // 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]); + 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; + } + + /** + * 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) { // TODO: debug mode + $jobId = null; + try { + $result = exec( + "lp -d $this->name" + . "-h $this->ip:$this->port " + . ($twoSided ? "-o sides=two-sided-long-edge " : " ") + . "-n $copies $path 2>&1" + ); + 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 number of pages in the PDF document at the given path. + * @param string $path + * @return int + */ + public static function getDocumentPageNumber(string $path): int { + + $command = "pdfinfo " . $path . " | grep '^Pages' | awk '{print $2}' 2>&1"; + if (config('app.debug')) { + $result = rand(1, 10); + } else { + $result = exec($command); + } + Log::info([$command, $result]); + return $result; + } + + public function getCompletedPrintJobs() { + try { + $command = "lpstat -W completed -o $this->name -h $this->ip:$this->port" . " | awk '{print $1}'"; + if (config('app.debug')) { + $result = []; + } else { + $result = []; + exec($command, $result); + } + Log::info([$command, $result]); + } catch (\Exception $e) { + Log::error("Printing error at line: " . __FILE__ . ":" . __LINE__ . " (in function " . __FUNCTION__ . "). " . $e->getMessage()); + } + } +} + +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/Policies/PrintAccountPolicy.php b/app/Policies/PrintAccountPolicy.php index 4269655dd..db5f369cf 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; - } } /** @@ -37,10 +34,15 @@ public function handleAny(User $user) public function view(User $user, PrintAccount $printAccount): bool { return $user->id === $printAccount->user_id; - } + } public function modify(User $user): bool { return false; } + + public function transferBalance(User $user, PrintAccount $printAccount): bool + { + return $user->id == $printAccount->user_id; + } } 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/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..10c513057 --- /dev/null +++ b/database/migrations/2023_12_25_182310_create_printers_table.php @@ -0,0 +1,34 @@ +id(); + $table->string('name')->unique(); + $table->string('ip')->nullable(); + $table->string('port')->nullable(); + $table->timestamp('paper_out_at')->nullable(); + }); + } + + /** + * 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..dc882b62c --- /dev/null +++ b/database/migrations/2023_12_25_184733_update_print_jobs_table.php @@ -0,0 +1,38 @@ +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/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..ecfc6492e 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')", @@ -56,7 +58,7 @@ }, { 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..661b16a61 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", @@ -79,12 +81,12 @@ }, { title: "@lang('print.state')", - field: "state", + field: "translatedState", 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..30b931f4f 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', ['filter' => 'all']), '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..9f3ff6121 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,21 +14,21 @@

@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 +39,26 @@
- @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 + @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 b2a85e442..63cf7d3eb 100644 --- a/resources/views/layouts/navbar.blade.php +++ b/resources/views/layouts/navbar.blade.php @@ -37,7 +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 @can('possess', \App\Models\Internet\InternetAccess::class) @@ -124,7 +124,7 @@ class="material-icons">menu @can('handleAny', \App\Models\PrintAccount::class)
  • - + local_printshopNyomtatás
  • 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 be5d216b4..4877f5e18 100644 --- a/routes/web.php +++ b/routes/web.php @@ -14,7 +14,11 @@ 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\HomeController; use App\Http\Controllers\LocaleController; use App\Http\Controllers\Network\AdminCheckoutController; @@ -91,22 +95,19 @@ }); /** 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/{id}', [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/{filter?}', [FreePagesController::class, 'indexFreePages'])->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::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 /** Internet */ Route::get('/internet', [InternetController::class, 'index'])->name('internet'); From d330b8b6e6d047d71dd2d5e4cc6aabc7ffb409f3 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Wed, 3 Jan 2024 18:29:20 +0100 Subject: [PATCH 02/55] remove printer role --- app/Http/Controllers/Auth/RegisterController.php | 2 -- .../Controllers/Dormitory/Printing/PrinterController.php | 2 +- app/Models/User.php | 9 --------- app/Policies/FreePagesPolicy.php | 4 ---- app/Policies/PrintJobPolicy.php | 3 --- app/Providers/AuthServiceProvider.php | 9 +-------- database/seeders/UsersTableSeeder.php | 1 - resources/views/secretariat/document/import.blade.php | 2 -- resources/views/secretariat/document/index.blade.php | 4 ---- tests/Feature/PrintControllerTest.php | 5 ----- tests/Feature/RegistrationTest.php | 2 -- tests/Unit/PrintTest.php | 1 - 12 files changed, 2 insertions(+), 42 deletions(-) diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index 5dc2108f7..9a3169e95 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -104,8 +104,6 @@ public function create(array $data) 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); - - $user->roles()->attach(Role::firstWhere('name', Role::PRINTER)->id); $user->roles()->attach(Role::firstWhere('name', Role::INTERNET_USER)->id); $user->roles()->attach(Role::firstWhere('name', $data['user_type'])->id); diff --git a/app/Http/Controllers/Dormitory/Printing/PrinterController.php b/app/Http/Controllers/Dormitory/Printing/PrinterController.php index 4d2f88de9..0fbd4aba9 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrinterController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrinterController.php @@ -27,7 +27,7 @@ public function index(?string $page = null) { } return view('dormitory.print.app', [ - "users" => User::printers(), + "users" => User::all(), "user" => user(), "printer" => Printer::firstWhere('name', config('print.printer_name')), ]); diff --git a/app/Models/User.php b/app/Models/User.php index 9ee8c131b..9fd7f4da1 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -986,15 +986,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/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..7c1da14e0 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -53,14 +53,7 @@ public function boot() return $user->isAdmin(); }); } - - public function registerPrintingPermissionHandlingPolicies() - { - Gate::define('print.print', function ($user) { - return $user->hasRole(Role::PRINTER); - }); - } - + public function registerDocumentPolicies() { Gate::define('document.status-certificate.viewAny', function ($user) { diff --git a/database/seeders/UsersTableSeeder.php b/database/seeders/UsersTableSeeder.php index 2fa5d8731..c2ad9ad69 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); $user->roles()->attach(Role::get(Role::INTERNET_USER)->id); $wifi_username = $user->internetAccess->setWifiCredentials(); WifiConnection::factory($user->id % 5)->create(['wifi_username' => $wifi_username]); 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/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 09bfbaa8d..a9514a61f 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::INTERNET_USER)); $this->assertTrue($user->hasRole(Role::COLLEGIST)); } @@ -104,7 +103,6 @@ public function test_tenant_collegist() 'balance' => 0 ]); - $this->assertTrue($user->hasRole(Role::PRINTER)); $this->assertTrue($user->hasRole(Role::INTERNET_USER)); $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)); From 056fb9ed710f08703848cc450b84c0e9f4107494 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 17:30:11 +0000 Subject: [PATCH 03/55] style: format code with PHP CS Fixer This commit fixes the style issues introduced in d330b8b according to the output from PHP CS Fixer. Details: https://github.com/EotvosCollegium/mars/pull/394 --- .../Printing/FreePagesController.php | 13 +++-- .../Printing/PrintAccountController.php | 10 ++-- .../PrintAccountHistoryController.php | 7 +-- .../Dormitory/Printing/PrintJobController.php | 30 +++++++----- .../Dormitory/Printing/PrinterController.php | 6 ++- app/Models/PrintAccount.php | 47 +++++++++++-------- app/Models/PrintJob.php | 31 +++++++----- app/Policies/PrintAccountPolicy.php | 2 +- app/Providers/AuthServiceProvider.php | 2 +- ...023_12_25_182310_create_printers_table.php | 3 +- ...3_12_25_184733_update_print_jobs_table.php | 3 +- 11 files changed, 89 insertions(+), 65 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/FreePagesController.php b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php index 173982bee..93bad1efa 100644 --- a/app/Http/Controllers/Dormitory/Printing/FreePagesController.php +++ b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php @@ -8,9 +8,10 @@ use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Http\Request; -class FreePagesController extends Controller { - - public function indexFreePages(?string $filter = null) { +class FreePagesController extends Controller +{ + public function indexFreePages(?string $filter = null) + { if ($filter === "all") { $this->authorize('viewAny', FreePages::class); @@ -40,14 +41,16 @@ public function indexFreePages(?string $filter = null) { ); } - private function freePagesPaginator(Builder $freePages, array $columns) { + private function freePagesPaginator(Builder $freePages, array $columns) + { $paginator = TabulatorPaginator::from( $freePages->with('modifier') )->sortable($columns)->filterable($columns)->paginate(); return $paginator; } - public function store(Request $request) { + public function store(Request $request) + { $data = $request->validate([ "user_id" => "required|exists:users,id", "amount" => "required|integer|min:1", diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php index 93769c7b1..a3e1b467d 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php @@ -12,13 +12,15 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Mail; -class PrintAccountController extends Controller { +class PrintAccountController extends Controller +{ /** - * Updates balance of a `PrintAccount`. + * Updates balance of a `PrintAccount`. * This can be done in two ways: either by topping up the account by giving money to an admin * or by transfering money from one account to the other. */ - public function update(Request $request) { + public function update(Request $request) + { $request->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 @@ -80,7 +82,7 @@ public function update(Request $request) { } $amount = $request->get('amount'); - + if ($amount < 0 && $printAccount->balance < $amount) { $this->returnNoBalance(); } diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php index 0c17bb03c..bce25afcb 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php @@ -7,9 +7,10 @@ use App\Models\PrintJob; use App\Utils\TabulatorPaginator; -class PrintAccountHistoryController extends Controller { - - public function indexPrintAccountHistory() { +class PrintAccountHistoryController extends Controller +{ + public function indexPrintAccountHistory() + { $this->authorize('viewAny', PrintJob::class); $columns = ['user.name', 'balance_change', 'free_page_change', 'deadline_change', 'modifier.name', 'modified_at']; diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index edb9e2daa..915954fb3 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -17,14 +17,15 @@ use Log; use Storage; -class PrintJobController extends Controller { - +class PrintJobController extends Controller +{ /** * Returns a paginated list of `PrintJob`s. * @param null|string $filter Decides wether all `PrintJob`s or just the user's `PrintJob`s should be listed. * @return LengthAwarePaginator */ - public function indexPrintJobs(?string $filter = null) { + public function indexPrintJobs(?string $filter = null) + { if ($filter === "all") { $this->authorize('viewAny', PrintJob::class); @@ -60,10 +61,11 @@ public function indexPrintJobs(?string $filter = null) { /** * Prints a document, then stores the corresponding `PrintJob`. - * @param Request $request - * @return RedirectResponse + * @param Request $request + * @return RedirectResponse */ - public function store(Request $request) { + public function store(Request $request) + { $request->validate([ 'file' => 'required|file', 'copies' => 'required|integer|min:1', @@ -101,7 +103,7 @@ public function store(Request $request) { Storage::delete($path); } - $cost = $useFreePages ? + $cost = $useFreePages ? PrintAccount::getFreePagesNeeeded($pageNumber, $copyNumber, $twoSided) : PrintAccount::getBalanceNeeded($pageNumber, $copyNumber, $twoSided); @@ -145,15 +147,16 @@ public function store(Request $request) { /** * Cancels a `PrintJob` - * @param PrintJob $job - * @return RedirectResponse + * @param PrintJob $job + * @return RedirectResponse */ - public function update(PrintJob $job) { + public function update(PrintJob $job) + { Log::info('asd'); $this->authorize('update', $job); Log::info($job->state->value); - if ($job->state === PrintJobStatus::QUEUED ) { + if ($job->state === PrintJobStatus::QUEUED) { $result = ($job->printer ?? Printer::firstWhere('name', config('print.printer_name')))->cancelPrintJob($job); switch ($result) { case PrinterCancelResult::Success: @@ -186,14 +189,15 @@ public function update(PrintJob $job) { ]); break; } - + return back()->with('error', __("print.$result->value")); } } - private function paginatorFrom(Builder $printJobs, array $columns) { + 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. diff --git a/app/Http/Controllers/Dormitory/Printing/PrinterController.php b/app/Http/Controllers/Dormitory/Printing/PrinterController.php index 0fbd4aba9..f9cbeb915 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrinterController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrinterController.php @@ -19,7 +19,8 @@ class PrinterController extends Controller * @param null|string $page Determines wether we are on the admin or the normal printing page. * @return View */ - public function index(?string $page = null) { + public function index(?string $page = null) + { if ($page === "admin") { $this->authorize('handleAny', PrintAccount::class); @@ -36,7 +37,8 @@ public function index(?string $page = null) { /** * Sets the given printer's out of paper sign. */ - public function update(Request $request, Printer $printer) { + public function update(Request $request, Printer $printer) + { $request->validate([ "no_paper" => "boolean", ]); diff --git a/app/Models/PrintAccount.php b/app/Models/PrintAccount.php index 2730b17dc..a2346cd09 100644 --- a/app/Models/PrintAccount.php +++ b/app/Models/PrintAccount.php @@ -15,7 +15,8 @@ * * @property mixed $user_id */ -class PrintAccount extends Model { +class PrintAccount extends Model +{ use HasFactory; protected $primaryKey = 'user_id'; @@ -38,53 +39,59 @@ class PrintAccount extends Model { 'balance' => 0, ]; - public function user() { + public function user() + { return $this->belongsTo(User::class); } - public function freePages() { + public function freePages() + { return $this->hasMany(FreePages::class, 'user_id', 'user_id'); } /** * The free pages which are currently available. Sorts the free pages by their deadline. - * @return Collection + * @return Collection */ - public function getAvailableFreePagesAttribute() { + public function getAvailableFreePagesAttribute() + { return $this->freePages()->where('deadline', '>', now())->orderBy('deadline')->get(); } /** * 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 $pages * @param int $copies - * @param bool $twoSided + * @param bool $twoSided * @return bool */ - public function hasEnoughFreePages(int $pages, int $copies, bool $twoSided) { + public function hasEnoughFreePages(int $pages, int $copies, bool $twoSided) + { return $this->getAvailableFreePagesAttribute()->sum('amount') > $this::getFreePagesNeeeded($pages, $copies, $twoSided); } /** * Returns wether the user has enough balance to print a document. - * @param int $pages - * @param int $copies - * @param bool $twoSided - * @return bool + * @param int $pages + * @param int $copies + * @param bool $twoSided + * @return bool */ - public function hasEnoughBalance(int $pages, int $copies, bool $twoSided) { + public function hasEnoughBalance(int $pages, int $copies, bool $twoSided) + { return $this->balance >= $this::getBalanceNeeded($pages, $twoSided, $copies); } /** * 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 + * @param int $pages + * @param bool $twoSided + * @return array */ - public static function getPageTypesNeeded(int $pages, bool $twoSided) { + public static function getPageTypesNeeded(int $pages, bool $twoSided) + { $oneSidedPages = 0; $twoSidedPages = 0; if (!$twoSided) { @@ -100,13 +107,15 @@ public static function getPageTypesNeeded(int $pages, bool $twoSided) { ]; } - public static function getFreePagesNeeeded(int $pages, $copies, $twoSided) { + public static function getFreePagesNeeeded(int $pages, $copies, $twoSided) + { $pageTypesNeeded = self::getPageTypesNeeded($pages, $twoSided); return ($pageTypesNeeded['one_sided'] + $pageTypesNeeded['two_sided']) * $copies; } - public static function getBalanceNeeded(int $pages, int $copies, bool $twoSided) { + 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 + diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index ce8e0540b..80e0b9dec 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -11,15 +11,16 @@ /** * @property mixed $user_id */ -class PrintJob extends Model { +class PrintJob extends Model +{ use HasFactory; public $timestamps = true; protected $fillable = [ - 'user_id', - 'state', - 'job_id', + 'user_id', + 'state', + 'job_id', 'cost', 'printer_id', 'used_free_pages' @@ -30,24 +31,27 @@ class PrintJob extends Model { 'used_free_pages' => 'boolean', ]; - public function user() { + public function user() + { return $this->belongsTo(User::class); } - public function printer() { + public function printer() + { return $this->belongsTo(Printer::class); } - + /** * `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 + * Trying to fix the decision made for the database a few years ago. + * @return HasOneThrough */ - public function printAccount() { + public function printAccount() + { return $this->hasOneThrough( - PrintAccount::class, - User::class, + PrintAccount::class, + User::class, 'id', // Foreign key on users 'user_id', // Foreign key on print_accounts 'user_id', // Local key on print_jobs @@ -58,7 +62,8 @@ public function printAccount() { /** * Gets the printjob-status with every printer, updates the status of the completed printjobs. */ - public static function checkAndUpdateStatuses() { + public static function checkAndUpdateStatuses() + { foreach(PrintJob::query()->where('state', PrintJobStatus::QUEUED)->whereNotNull('printer_id')->pluck('printer_id')->unique() as $printer_id) { $printJobs = Printer::find($printer_id)->getCompletedPrintJobs(); PrintJob::whereIn('job_id', $printJobs)->update(['state' => PrintJobStatus::SUCCESS]); diff --git a/app/Policies/PrintAccountPolicy.php b/app/Policies/PrintAccountPolicy.php index db5f369cf..55cc043de 100644 --- a/app/Policies/PrintAccountPolicy.php +++ b/app/Policies/PrintAccountPolicy.php @@ -34,7 +34,7 @@ public function handleAny(User $user) public function view(User $user, PrintAccount $printAccount): bool { return $user->id === $printAccount->user_id; - } + } public function modify(User $user): bool { diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 7c1da14e0..aa09b1db4 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -53,7 +53,7 @@ public function boot() return $user->isAdmin(); }); } - + public function registerDocumentPolicies() { Gate::define('document.status-certificate.viewAny', function ($user) { diff --git a/database/migrations/2023_12_25_182310_create_printers_table.php b/database/migrations/2023_12_25_182310_create_printers_table.php index 10c513057..6ee0ba34c 100644 --- a/database/migrations/2023_12_25_182310_create_printers_table.php +++ b/database/migrations/2023_12_25_182310_create_printers_table.php @@ -4,8 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * 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 index dc882b62c..f40375192 100644 --- a/database/migrations/2023_12_25_184733_update_print_jobs_table.php +++ b/database/migrations/2023_12_25_184733_update_print_jobs_table.php @@ -5,8 +5,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. * From 3689f71c0ec935d22ceca9fb5343ad495da58528 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Wed, 3 Jan 2024 18:35:55 +0100 Subject: [PATCH 04/55] remove printer role --- app/Models/Role.php | 5 ----- 1 file changed, 5 deletions(-) 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', From 9d745154de25da0c0953e84fee9f25c5768d72d6 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 17:36:28 +0000 Subject: [PATCH 05/55] style: format code with PHP CS Fixer This commit fixes the style issues introduced in 74b27a2 according to the output from PHP CS Fixer. Details: https://github.com/EotvosCollegium/mars/pull/394 --- tests/Feature/RegistrationTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/RegistrationTest.php b/tests/Feature/RegistrationTest.php index ebeb95204..12540da39 100644 --- a/tests/Feature/RegistrationTest.php +++ b/tests/Feature/RegistrationTest.php @@ -56,7 +56,7 @@ public function test_register_collegist() 'user_id' => $user->id, 'status' => ApplicationForm::STATUS_IN_PROGRESS ]); - + $this->assertTrue($user->hasRole(Role::COLLEGIST)); } From 1f3dbfb51fe89d25d1f13742d189850a049a0ff9 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Wed, 3 Jan 2024 18:49:55 +0100 Subject: [PATCH 06/55] solving todos --- .../Dormitory/Printing/PrintAccountHistoryController.php | 6 +----- .../Controllers/Dormitory/Printing/PrintJobController.php | 2 +- app/Models/Printer.php | 7 +++++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php index bce25afcb..2d5402f3c 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php @@ -15,11 +15,7 @@ public function indexPrintAccountHistory() $columns = ['user.name', 'balance_change', 'free_page_change', 'deadline_change', 'modifier.name', 'modified_at']; return 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') // TODO: check this - ->with('modifier') + 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 index 915954fb3..e684b2bb7 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -34,7 +34,7 @@ public function indexPrintJobs(?string $filter = null) return $this->paginatorFrom( printJobs: PrintJob::query() ->with('user') - ->orderBy('print_jobs.created_at', 'desc'), // TODO: test if it works without join + ->orderBy('print_jobs.created_at', 'desc'), columns: [ 'created_at', 'filename', diff --git a/app/Models/Printer.php b/app/Models/Printer.php index 6461b43f7..92bd40b50 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -61,7 +61,10 @@ public function cancelPrintJob(PrintJob $printJob) { * @return int The `jobId` belonging to the printjob * @throws PrinterException If the printing fails */ - public function print(bool $twoSided, int $copies, string $path) { // TODO: debug mode + public function print(bool $twoSided, int $copies, string $path) { + if (config('app.debug')) { + return -1; + } $jobId = null; try { $result = exec( @@ -103,7 +106,7 @@ public static function getDocumentPageNumber(string $path): int { public function getCompletedPrintJobs() { try { - $command = "lpstat -W completed -o $this->name -h $this->ip:$this->port" . " | awk '{print $1}'"; + $command = "lpstat -W completed -o $this->name -h $this->ip:$this->port | awk '{print $1}'"; if (config('app.debug')) { $result = []; } else { From c8f89bdee96ee207072f92b817f775c02df07e2e Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Wed, 3 Jan 2024 19:08:27 +0100 Subject: [PATCH 07/55] replace exec with process->run --- app/Console/Commands.php | 11 +++-- .../Dormitory/Printing/PrintJobController.php | 2 + app/Models/Printer.php | 44 ++++++++++++------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/app/Console/Commands.php b/app/Console/Commands.php index a8ef4700a..d09cde2c1 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. @@ -21,8 +22,9 @@ public static function pingRouter($router) $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; } @@ -33,8 +35,9 @@ public static function latexToPdf($path, $outputDir) $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/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index e684b2bb7..d7392a02b 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -192,6 +192,8 @@ public function update(PrintJob $job) return back()->with('error', __("print.$result->value")); } + + return back(); } diff --git a/app/Models/Printer.php b/app/Models/Printer.php index 92bd40b50..6fda6acdb 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Log; +use Symfony\Component\Process\Process; class Printer extends Model { use HasFactory; @@ -32,15 +33,16 @@ public function printJobs() { * @return PrinterCancelResult */ public function cancelPrintJob(PrintJob $printJob) { + $process = new Process(['cancel', $printJob->job_id, '-h', "$this->ip:$this->port"]); $command = "cancel $printJob->job_id -h $this->ip:$this->port"; if (config('app.debug')) { // 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]; + $process->run(); + $result = ['output' => $process->getOutput(), 'exit_code' => $process->getExitCode()]; } - Log::info([$command, $result]); + Log::info([$process->getCommandLine(), $result]); if ($result['exit_code'] == 0) { return PrinterCancelResult::Success; } @@ -67,12 +69,20 @@ public function print(bool $twoSided, int $copies, string $path) { } $jobId = null; try { - $result = exec( - "lp -d $this->name" - . "-h $this->ip:$this->port " - . ($twoSided ? "-o sides=two-sided-long-edge " : " ") - . "-n $copies $path 2>&1" - ); + $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)); @@ -93,27 +103,27 @@ public function print(bool $twoSided, int $copies, string $path) { * @return int */ public static function getDocumentPageNumber(string $path): int { - - $command = "pdfinfo " . $path . " | grep '^Pages' | awk '{print $2}' 2>&1"; + $process = new Process(['pdfinfo', $path, '|', 'grep', "'^Pages'", '|', 'awk', "'{print $2}'"]); if (config('app.debug')) { $result = rand(1, 10); } else { - $result = exec($command); + $process->run(); + $result = intval($process->getOutput()); } - Log::info([$command, $result]); + Log::info([$process->getCommandLine(), $result]); return $result; } public function getCompletedPrintJobs() { try { - $command = "lpstat -W completed -o $this->name -h $this->ip:$this->port | awk '{print $1}'"; + $process = new Process(['lpstat', '-W', 'completed', '-o', $this->name, '-h', "$this->ip:$this->port", '|', 'awk', "'{print $1}'"]); if (config('app.debug')) { $result = []; } else { - $result = []; - exec($command, $result); + $process->run(); + $result = $process->getOutput(); } - Log::info([$command, $result]); + Log::info([$process->getCommandLine(), $result]); } catch (\Exception $e) { Log::error("Printing error at line: " . __FILE__ . ":" . __LINE__ . " (in function " . __FUNCTION__ . "). " . $e->getMessage()); } From 781ac184dd01b8cf39e508225b1e0446b02e6571 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 18:08:56 +0000 Subject: [PATCH 08/55] style: format code with PHP CS Fixer This commit fixes the style issues introduced in c8f89bd according to the output from PHP CS Fixer. Details: https://github.com/EotvosCollegium/mars/pull/394 --- app/Http/Controllers/Dormitory/Printing/PrintJobController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index d7392a02b..54af51c61 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -192,7 +192,7 @@ public function update(PrintJob $job) return back()->with('error', __("print.$result->value")); } - + return back(); } From 913a4a66f6825c7bc0d24e787c7406850420c964 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Wed, 3 Jan 2024 19:26:12 +0100 Subject: [PATCH 09/55] added missing doc strings --- app/Console/Commands.php | 1 - .../Dormitory/Printing/FreePagesController.php | 18 ++++++++++++++++-- .../Printing/PrintAccountController.php | 11 +++++++++++ .../Printing/PrintAccountHistoryController.php | 11 +++++++++++ .../Dormitory/Printing/PrintJobController.php | 12 ++++++++++-- app/Models/FreePages.php | 16 ++++++++++++++++ app/Models/PrintAccount.php | 17 +++++++++++++++++ app/Models/Printer.php | 13 +++++++++++++ 8 files changed, 94 insertions(+), 5 deletions(-) diff --git a/app/Console/Commands.php b/app/Console/Commands.php index d09cde2c1..fe993f36c 100644 --- a/app/Console/Commands.php +++ b/app/Console/Commands.php @@ -34,7 +34,6 @@ public static function latexToPdf($path, $outputDir) if (self::isDebugMode()) { $result = "ok"; } else { - $command = "pdflatex " . "-interaction=nonstopmode -output-dir " . $outputDir . " " . $path . " 2>&1"; $process = new Process(['pdflatex', '-interaction=nonstopmode', '-output-dir', $outputDir, $path]); $process->run(); $result = $process->getOutput(); diff --git a/app/Http/Controllers/Dormitory/Printing/FreePagesController.php b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php index 93bad1efa..d78fcc886 100644 --- a/app/Http/Controllers/Dormitory/Printing/FreePagesController.php +++ b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php @@ -6,10 +6,17 @@ use App\Models\FreePages; use App\Utils\TabulatorPaginator; use Illuminate\Contracts\Database\Eloquent\Builder; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; +use Illuminate\Pagination\LengthAwarePaginator; class FreePagesController extends Controller -{ +{ + /** + * Returns a paginated list of `FreePages`. + * @param null|string $filter Decides wether all `FreePages` or just the user's `FreePages` should be listed. + * @return LengthAwarePaginator + */ public function indexFreePages(?string $filter = null) { if ($filter === "all") { @@ -40,7 +47,9 @@ public function indexFreePages(?string $filter = null) ] ); } - + /** + * Private helper function to create a paginator for `FreePages`. + */ private function freePagesPaginator(Builder $freePages, array $columns) { $paginator = TabulatorPaginator::from( @@ -49,6 +58,11 @@ private function freePagesPaginator(Builder $freePages, array $columns) return $paginator; } + /** + * Adds new free pages to a user's account. + * @param Request $request + * @return RedirectResponse + */ public function store(Request $request) { $data = $request->validate([ diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php index a3e1b467d..6f173a03f 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php @@ -9,8 +9,12 @@ use App\Models\Semester; use App\Models\Transaction; use App\Models\User; +use Illuminate\Http\RedirectResponse; +use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Http\Request; use Illuminate\Support\Facades\Mail; +use Psr\Container\NotFoundExceptionInterface; +use Psr\Container\ContainerExceptionInterface; class PrintAccountController extends Controller { @@ -110,6 +114,13 @@ public function update(Request $request) } } + /** + * 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 index 2d5402f3c..114c3754c 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php @@ -6,9 +6,20 @@ use App\Models\PrintAccountHistory; use App\Models\PrintJob; use App\Utils\TabulatorPaginator; +use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Auth\Access\AuthorizationException; +use Illuminate\Contracts\Container\BindingResolutionException; +use InvalidArgumentException; class PrintAccountHistoryController extends Controller { + /** + * Returns a paginated list of `PrintAccountHistory` entries. + * @return LengthAwarePaginator + * @throws AuthorizationException + * @throws BindingResolutionException + * @throws InvalidArgumentException + */ public function indexPrintAccountHistory() { $this->authorize('viewAny', PrintJob::class); diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index d7392a02b..3f14631fd 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -10,10 +10,12 @@ use App\Models\PrinterCancelResult; use App\Models\PrintJob; use App\Utils\TabulatorPaginator; +use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; +use InvalidArgumentException; use Log; use Storage; @@ -196,8 +198,14 @@ public function update(PrintJob $job) 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(); diff --git a/app/Models/FreePages.php b/app/Models/FreePages.php index 3d1a50af8..a2b3dab56 100644 --- a/app/Models/FreePages.php +++ b/app/Models/FreePages.php @@ -56,21 +56,37 @@ class FreePages extends Model 'deadline' => 'date', ]; + /** + * The user this free pages entry belongs to. + * @return BelongsTo + */ public function user(): BelongsTo { return $this->belongsTo(User::class); } + /** + * The print account this free pages entry belongs to. + * @return BelongsTo + */ public function printAccount() { return $this->belongsTo(PrintAccount::class, 'user_id', 'user_id'); } + /** + * Wether the free pages are still available. + * @return bool + */ protected function getAvailableAttribute() { return now()->isBefore($this->deadline); } + /** + * The user who last modified this free pages entry. + * @return BelongsTo + */ public function modifier(): BelongsTo { return $this->belongsTo(User::class, 'last_modified_by'); diff --git a/app/Models/PrintAccount.php b/app/Models/PrintAccount.php index 4855eb62c..08b7ce8d9 100644 --- a/app/Models/PrintAccount.php +++ b/app/Models/PrintAccount.php @@ -123,6 +123,13 @@ public static function getPageTypesNeeded(int $pages, bool $twoSided) ]; } + /** + * 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); @@ -130,6 +137,16 @@ public static function getFreePagesNeeeded(int $pages, $copies, $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); diff --git a/app/Models/Printer.php b/app/Models/Printer.php index 6fda6acdb..ebbcb793f 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -4,7 +4,10 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Facades\Log; +use Psr\Container\NotFoundExceptionInterface; +use Psr\Container\ContainerExceptionInterface; use Symfony\Component\Process\Process; class Printer extends Model { @@ -23,6 +26,10 @@ class Printer extends Model { 'paper_out_at' => 'datetime', ]; + /** + * Returns the `PrintJob`s that were executed by this printer. + * @return HasMany + */ public function printJobs() { return $this->hasMany(PrintJob::class); } @@ -114,6 +121,12 @@ public static function getDocumentPageNumber(string $path): int { return $result; } + /** + * Returns the completed printjobs for this printer. + * @return void + * @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}'"]); From 7ea9be047604d71999910e18c1f75ecf0a4304e2 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 18:26:46 +0000 Subject: [PATCH 10/55] style: format code with PHP CS Fixer This commit fixes the style issues introduced in 6612ad8 according to the output from PHP CS Fixer. Details: https://github.com/EotvosCollegium/mars/pull/394 --- .../Printing/FreePagesController.php | 4 ++-- .../Printing/PrintAccountController.php | 8 +++---- .../PrintAccountHistoryController.php | 8 +++---- .../Dormitory/Printing/PrintJobController.php | 10 ++++----- app/Models/FreePages.php | 6 ++--- app/Models/PrintAccount.php | 22 +++++++++---------- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/FreePagesController.php b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php index d78fcc886..eb7a040e2 100644 --- a/app/Http/Controllers/Dormitory/Printing/FreePagesController.php +++ b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php @@ -11,7 +11,7 @@ use Illuminate\Pagination\LengthAwarePaginator; class FreePagesController extends Controller -{ +{ /** * Returns a paginated list of `FreePages`. * @param null|string $filter Decides wether all `FreePages` or just the user's `FreePages` should be listed. @@ -60,7 +60,7 @@ private function freePagesPaginator(Builder $freePages, array $columns) /** * Adds new free pages to a user's account. - * @param Request $request + * @param Request $request * @return RedirectResponse */ public function store(Request $request) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php index 6f173a03f..f14faca75 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php @@ -116,10 +116,10 @@ public function update(Request $request) /** * 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 + * @return RedirectResponse + * @throws BindingResolutionException + * @throws NotFoundExceptionInterface + * @throws ContainerExceptionInterface */ private function returnNoBalance() { diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php index 114c3754c..30a6cb34e 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php @@ -15,10 +15,10 @@ class PrintAccountHistoryController extends Controller { /** * Returns a paginated list of `PrintAccountHistory` entries. - * @return LengthAwarePaginator - * @throws AuthorizationException - * @throws BindingResolutionException - * @throws InvalidArgumentException + * @return LengthAwarePaginator + * @throws AuthorizationException + * @throws BindingResolutionException + * @throws InvalidArgumentException */ public function indexPrintAccountHistory() { diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index fb2021958..dbc43ebd8 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -200,11 +200,11 @@ public function update(PrintJob $job) /** * Returns a paginated list of `PrintJob`s. - * @param Builder $printJobs - * @param array $columns - * @return LengthAwarePaginator - * @throws BindingResolutionException - * @throws InvalidArgumentException + * @param Builder $printJobs + * @param array $columns + * @return LengthAwarePaginator + * @throws BindingResolutionException + * @throws InvalidArgumentException */ private function paginatorFrom(Builder $printJobs, array $columns) { diff --git a/app/Models/FreePages.php b/app/Models/FreePages.php index a2b3dab56..7d261219a 100644 --- a/app/Models/FreePages.php +++ b/app/Models/FreePages.php @@ -58,7 +58,7 @@ class FreePages extends Model /** * The user this free pages entry belongs to. - * @return BelongsTo + * @return BelongsTo */ public function user(): BelongsTo { @@ -67,7 +67,7 @@ public function user(): BelongsTo /** * The print account this free pages entry belongs to. - * @return BelongsTo + * @return BelongsTo */ public function printAccount() { @@ -85,7 +85,7 @@ protected function getAvailableAttribute() /** * The user who last modified this free pages entry. - * @return BelongsTo + * @return BelongsTo */ public function modifier(): BelongsTo { diff --git a/app/Models/PrintAccount.php b/app/Models/PrintAccount.php index 08b7ce8d9..c48b9e94f 100644 --- a/app/Models/PrintAccount.php +++ b/app/Models/PrintAccount.php @@ -125,10 +125,10 @@ public static function getPageTypesNeeded(int $pages, bool $twoSided) /** * Returns the number of free pages needed to print with given configuration. - * @param int $pages - * @param mixed $copies - * @param mixed $twoSided - * @return int|float + * @param int $pages + * @param mixed $copies + * @param mixed $twoSided + * @return int|float */ public static function getFreePagesNeeeded(int $pages, $copies, $twoSided) { @@ -139,13 +139,13 @@ public static function getFreePagesNeeeded(int $pages, $copies, $twoSided) /** * 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 + * @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) { From 19307676a474220a41abf2916ef19aa79e846413 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Wed, 3 Jan 2024 19:31:10 +0100 Subject: [PATCH 11/55] add missing doc comments --- app/Models/PrintJob.php | 5 +++++ app/Policies/PrintAccountPolicy.php | 7 ++++++- app/Providers/AuthServiceProvider.php | 6 ++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index b1c62f113..78b68a53d 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -5,6 +5,7 @@ use App\Enums\PrintJobStatus; 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; @@ -61,6 +62,10 @@ public function user() return $this->belongsTo(User::class); } + /** + * `Printer` which this `PrintJob` was sent to. + * @return BelongsTo + */ public function printer() { return $this->belongsTo(Printer::class); diff --git a/app/Policies/PrintAccountPolicy.php b/app/Policies/PrintAccountPolicy.php index 55cc043de..92dcee33a 100644 --- a/app/Policies/PrintAccountPolicy.php +++ b/app/Policies/PrintAccountPolicy.php @@ -40,7 +40,12 @@ 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/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index aa09b1db4..11808968e 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -54,6 +54,9 @@ public function boot() }); } + /** + * Register policies for documents. + */ public function registerDocumentPolicies() { Gate::define('document.status-certificate.viewAny', function ($user) { @@ -81,6 +84,9 @@ public function registerDocumentPolicies() }); } + /** + * Register policies for verification. + */ public function registerVerificationPolicies() { Gate::define('registration.handle', function ($user) { From ead482cbf56d79135598c5762054f76a825e4da3 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 18:31:45 +0000 Subject: [PATCH 12/55] style: format code with PHP CS Fixer This commit fixes the style issues introduced in 26c746f according to the output from PHP CS Fixer. Details: https://github.com/EotvosCollegium/mars/pull/394 --- app/Models/PrintJob.php | 2 +- app/Policies/PrintAccountPolicy.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index 78b68a53d..e9adc2830 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -64,7 +64,7 @@ public function user() /** * `Printer` which this `PrintJob` was sent to. - * @return BelongsTo + * @return BelongsTo */ public function printer() { diff --git a/app/Policies/PrintAccountPolicy.php b/app/Policies/PrintAccountPolicy.php index 92dcee33a..f3105fed4 100644 --- a/app/Policies/PrintAccountPolicy.php +++ b/app/Policies/PrintAccountPolicy.php @@ -42,9 +42,9 @@ public function modify(User $user): bool } /** * Determine whether the user can transfer balance from the print account. - * @param User $user - * @param PrintAccount $printAccount - * @return bool + * @param User $user + * @param PrintAccount $printAccount + * @return bool */ public function transferBalance(User $user, PrintAccount $printAccount): bool { From 31527fe42295fcc76ae67ff9b73df54d783adf69 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Wed, 3 Jan 2024 19:37:58 +0100 Subject: [PATCH 13/55] fix --- .../Dormitory/Printing/PrintJobController.php | 15 +++++++-------- app/Models/PrintJob.php | 10 ++++++++++ resources/views/dormitory/print/history.blade.php | 4 ++-- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index dbc43ebd8..509f022fc 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -51,7 +51,9 @@ public function indexPrintJobs(?string $filter = null) PrintJob::checkAndUpdateStatuses(); return $this->paginatorFrom( - printJobs: user()->printJobs()->orderBy('created_at', 'desc'), + printJobs: user() + ->printJobs() + ->orderBy('created_at', 'desc'), columns: [ 'created_at', 'filename', @@ -154,9 +156,7 @@ public function store(Request $request) */ public function update(PrintJob $job) { - Log::info('asd'); $this->authorize('update', $job); - Log::info($job->state->value); if ($job->state === PrintJobStatus::QUEUED) { $result = ($job->printer ?? Printer::firstWhere('name', config('print.printer_name')))->cancelPrintJob($job); @@ -211,11 +211,10 @@ 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()->transform(function (PrintJob $printJob) { - $printJob->translatedState = __("print." . strtoupper($printJob->state->value)); - $printJob->cost = "$printJob->cost HUF"; - return $printJob; - }); + $paginator->getCollection()->append([ + 'translated_cost', + 'translated_state', + ]); return $paginator; } diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index 78b68a53d..280ed8f2d 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -89,6 +89,16 @@ public function printAccount() ); } + public function getTranslatedCostAttribute() + { + return "$this->cost HUF"; + } + + public function getTranslatedStateAttribute() + { + return __("print." . strtoupper($this->state->value)); + } + /** * Gets the printjob-status with every printer, updates the status of the completed printjobs. */ diff --git a/resources/views/dormitory/print/history.blade.php b/resources/views/dormitory/print/history.blade.php index 661b16a61..1ae3a31c2 100644 --- a/resources/views/dormitory/print/history.blade.php +++ b/resources/views/dormitory/print/history.blade.php @@ -75,13 +75,13 @@ }, { 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: "translatedState", + field: "translated_state", sorter: "string", @can('viewAny', App\Models\PrintJob::class) headerFilterParams: { From 62252a9d22fbac51c1c903de56e49bc0bb4154ee Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Wed, 3 Jan 2024 19:41:07 +0100 Subject: [PATCH 14/55] add missing doc comment --- app/Models/PrintJob.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index f0f85ab0f..f8a86a7eb 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -88,12 +88,18 @@ public function printAccount() 'id', // Local key on users ); } - + + /** + * Attribute for the translated cost. + */ public function getTranslatedCostAttribute() { return "$this->cost HUF"; } + /** + * Attribute for the translated state. + */ public function getTranslatedStateAttribute() { return __("print." . strtoupper($this->state->value)); From d8fe59852cd291d4f2aff28596af6d5c1a6fbf1e Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 18:41:39 +0000 Subject: [PATCH 15/55] style: format code with PHP CS Fixer This commit fixes the style issues introduced in 62252a9 according to the output from PHP CS Fixer. Details: https://github.com/EotvosCollegium/mars/pull/394 --- app/Models/PrintJob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index f8a86a7eb..a8eef4734 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -88,7 +88,7 @@ public function printAccount() 'id', // Local key on users ); } - + /** * Attribute for the translated cost. */ From 80db86f179d91541abb3d7c96ec568c3822a085b Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Wed, 3 Jan 2024 20:53:21 +0100 Subject: [PATCH 16/55] fixes and #344 --- .vscode/launch.json | 48 +++++++++++++++++++ .vscode/settings.json | 3 ++ .../Dormitory/Printing/PrintJobController.php | 26 ++++++---- .../Dormitory/Printing/PrinterController.php | 5 +- app/Models/PrintJob.php | 5 +- app/Models/Printer.php | 1 - .../views/dormitory/print/free.blade.php | 1 + .../views/dormitory/print/print.blade.php | 14 +++--- routes/web.php | 2 +- 9 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json 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/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index 509f022fc..28af6c8f7 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -70,21 +70,24 @@ public function indexPrintJobs(?string $filter = null) */ public function store(Request $request) { + xdebug_break(); + Log::info($request->all()); $request->validate([ 'file' => 'required|file', 'copies' => 'required|integer|min:1', - 'two_sided' => 'boolean', - 'printer_id' => 'nullable|exists:printers,id', - 'use_free_pages' => 'nullable|boolean', + 'two_sided' => 'in:on,off', + 'printer_id' => 'exists:printers,id', + 'use_free_pages' => 'in:on,off', ]); + Log::info("Printjob cost 2"); $useFreePages = $request->boolean('use_free_pages'); - $copyNumber = $request->get('copies'); - $twoSided = $request->get('two_sided'); + $copyNumber = $request->input('copies'); + $twoSided = $request->boolean('two_sided'); $file = $request->file('file'); /** @var Printer */ - $printer = $request->printer_id ? Printer::find($request->get("printer_id")) : Printer::firstWhere('name', config('print.printer_name')); + $printer = $request->has('printer_id') ? Printer::find($request->input("printer_id")) : Printer::firstWhere('name', config('print.printer_name')); $path = $file->store('print-documents'); $pageNumber = Printer::getDocumentPageNumber($path); @@ -92,8 +95,8 @@ public function store(Request $request) /** @var PrintAccount */ $printAccount = user()->printAccount; - if (($useFreePages && $printAccount->hasEnoughFreePages($pageNumber, $copyNumber, $twoSided)) || - (!$useFreePages && $printAccount->hasEnoughBalance($pageNumber, $copyNumber, $twoSided)) + if (!(($useFreePages && $printAccount->hasEnoughFreePages($pageNumber, $copyNumber, $twoSided)) || + (!$useFreePages && $printAccount->hasEnoughBalance($pageNumber, $copyNumber, $twoSided))) ) { return back()->with('error', __('print.no_balance')); } @@ -111,6 +114,8 @@ public function store(Request $request) PrintAccount::getFreePagesNeeeded($pageNumber, $copyNumber, $twoSided) : PrintAccount::getBalanceNeeded($pageNumber, $copyNumber, $twoSided); + Log::info("Printjob cost: $cost"); + user()->printJobs()->create([ 'state' => PrintJobStatus::QUEUED, 'job_id' => $jobId, @@ -140,8 +145,13 @@ public function store(Request $request) 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(); diff --git a/app/Http/Controllers/Dormitory/Printing/PrinterController.php b/app/Http/Controllers/Dormitory/Printing/PrinterController.php index f9cbeb915..0b9035417 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrinterController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrinterController.php @@ -47,9 +47,8 @@ public function update(Request $request, Printer $printer) 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->update([ - "paper_out_at" => now(), - ]); + $printer->paper_out_at = now(); + $printer->save(); return redirect()->back()->with('message', __('mail.email_sent')); } else { $this->authorize('handleAny', PrintAccount::class); diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index f8a86a7eb..3643a77c5 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -49,7 +49,8 @@ class PrintJob extends Model 'job_id', 'cost', 'printer_id', - 'used_free_pages' + 'used_free_pages', + 'filename', ]; protected $casts = [ @@ -94,7 +95,7 @@ public function printAccount() */ public function getTranslatedCostAttribute() { - return "$this->cost HUF"; + return $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF"; } /** diff --git a/app/Models/Printer.php b/app/Models/Printer.php index ebbcb793f..2f5697952 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -41,7 +41,6 @@ public function printJobs() { */ public function cancelPrintJob(PrintJob $printJob) { $process = new Process(['cancel', $printJob->job_id, '-h', "$this->ip:$this->port"]); - $command = "cancel $printJob->job_id -h $this->ip:$this->port"; if (config('app.debug')) { // cancel(1) exits with status code 0 if it succeeds $result = ['output' => '', 'exit_code' => 0]; diff --git a/resources/views/dormitory/print/free.blade.php b/resources/views/dormitory/print/free.blade.php index ecfc6492e..e8800dc8f 100644 --- a/resources/views/dormitory/print/free.blade.php +++ b/resources/views/dormitory/print/free.blade.php @@ -54,6 +54,7 @@ title: "@lang('print.deadline')", field: "deadline", sorter: "datetime", + formatter:dateFormatter, @can('viewAny', App\Models\FreePages::class) headerFilter: 'input' @endif }, { diff --git a/resources/views/dormitory/print/print.blade.php b/resources/views/dormitory/print/print.blade.php index 9f3ff6121..6d8c467b6 100644 --- a/resources/views/dormitory/print/print.blade.php +++ b/resources/views/dormitory/print/print.blade.php @@ -23,13 +23,14 @@
    @csrf - @method('PUT')
    @if($printAccount->available_free_pages->sum('amount') > 0) {{-- only show when user have active free pages --}} - + @else @@ -47,18 +48,19 @@
    @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/routes/web.php b/routes/web.php index b090424e5..a151dd20d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -115,7 +115,7 @@ /** Printing */ Route::get('/printer/{page?}', [PrinterController::class, 'index'])->name('printer.index'); // also print.manage, print - Route::put('/printer/{id}', [PrinterController::class, 'update'])->name('printer.update'); // print.added_paper, print.no_paper + 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 From d6fbe58edc0660885a3e438d73c1a5e85fe94bd1 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Thu, 9 May 2024 22:31:46 +0200 Subject: [PATCH 17/55] Created Process class, created PrinterHelper class, code improvements, fixes. --- app/Console/Commands/CreateDefaultPrinter.php | 39 - .../Printing/FreePagesController.php | 43 +- .../Printing/PrintAccountController.php | 149 ++- .../Dormitory/Printing/PrintJobController.php | 27 +- app/Models/PrintAccount.php | 59 +- app/Models/PrintJob.php | 25 +- app/Models/Printer.php | 69 +- app/Utils/PrinterHelper.php | 85 ++ app/Utils/Process.php | 30 + composer.lock | 1032 ++++++++--------- ...023_12_25_182310_create_printers_table.php | 9 + .../dormitory/print/manage/app.blade.php | 2 +- routes/web.php | 3 +- 13 files changed, 789 insertions(+), 783 deletions(-) delete mode 100644 app/Console/Commands/CreateDefaultPrinter.php create mode 100644 app/Utils/PrinterHelper.php create mode 100644 app/Utils/Process.php diff --git a/app/Console/Commands/CreateDefaultPrinter.php b/app/Console/Commands/CreateDefaultPrinter.php deleted file mode 100644 index c36d20775..000000000 --- a/app/Console/Commands/CreateDefaultPrinter.php +++ /dev/null @@ -1,39 +0,0 @@ - env('PRINTER_NAME'), - 'ip' => env('PRINTER_IP'), - 'port' => env('PRINTER_PORT'), - ]); - - return Command::SUCCESS; - } -} diff --git a/app/Http/Controllers/Dormitory/Printing/FreePagesController.php b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php index eb7a040e2..e15c1030a 100644 --- a/app/Http/Controllers/Dormitory/Printing/FreePagesController.php +++ b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php @@ -13,28 +13,11 @@ class FreePagesController extends Controller { /** - * Returns a paginated list of `FreePages`. - * @param null|string $filter Decides wether all `FreePages` or just the user's `FreePages` should be listed. + * Returns a paginated list of the current user's `FreePages`. * @return LengthAwarePaginator */ - public function indexFreePages(?string $filter = null) + public function index() { - if ($filter === "all") { - $this->authorize('viewAny', FreePages::class); - - return $this->freePagesPaginator( - freePages: FreePages::with('user'), - columns: [ - 'amount', - 'deadline', - 'modifier', - 'comment', - 'user.name', - 'created_at', - ] - ); - } - $this->authorize('viewSelf', FreePages::class); return $this->freePagesPaginator( @@ -47,6 +30,28 @@ public function indexFreePages(?string $filter = null) ] ); } + + /** + * 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`. */ diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php index f14faca75..7f777041e 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php @@ -6,12 +6,14 @@ use App\Mail\ChangedPrintBalance; use App\Models\Checkout; use App\Models\PaymentType; +use App\Models\PrintAccount; use App\Models\Semester; use App\Models\Transaction; use App\Models\User; use Illuminate\Http\RedirectResponse; use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Mail; use Psr\Container\NotFoundExceptionInterface; use Psr\Container\ContainerExceptionInterface; @@ -34,84 +36,103 @@ public function update(Request $request) $printAccount = User::find($request->get('user'))->printAccount; // If user can not even transfer balance, we can stop here - if (user()->cannot('transferBalance', $printAccount)) { - abort(403); - } + $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) { - // Cannot transfer to yourself - if ($otherAccount->user_id === $printAccount->user_id) { - abort(400); - } + return $this->transferBalance($printAccount, $otherAccount, $request->get('amount')); + } + // This is a modification of the current account + else { + return $this->modifyBalance($printAccount, $request->get('amount')); + } + } - // Cannot transfer from other user's account (even if you are admin) - if ($printAccount->user_id !== user()->id) { - abort(403); - } + /** + * 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); + } - $amount = $request->get('amount'); + // 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); - } + // 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(); - } + // 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, - ]); + $printAccount->update([ + 'balance' => $printAccount->balance - $amount, + 'last_modified_by' => user()->id, + ]); - $otherAccount->update([ - 'balance' => $otherAccount->balance + $amount, - 'last_modified_by' => user()->id, - ]); + $otherAccount->update([ + 'balance' => $otherAccount->balance + $amount, + 'last_modified_by' => user()->id, + ]); - Mail::to($printAccount->user)->queue(new ChangedPrintBalance($printAccount->user, $request->get('amount'), user()->name)); + DB::commit(); - return redirect()->back()->with('message', __('general.successful_transaction')); - } - // This is a modification of the current account - else { - // Only admins can modify accounts - if (user()->cannot('modify', $printAccount)) { - abort(403); - } - - $amount = $request->get('amount'); - - 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, $request->get('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, - ]); - - return redirect()->back()->with('message', __('general.successful_modification')); + 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')); } /** diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index 28af6c8f7..b229962c5 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -8,6 +8,7 @@ use App\Models\PrintAccount; use App\Models\Printer; use App\Models\PrinterCancelResult; +use App\Models\PrinterHelper; use App\Models\PrintJob; use App\Utils\TabulatorPaginator; use Illuminate\Contracts\Container\BindingResolutionException; @@ -15,9 +16,10 @@ use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Storage; use InvalidArgumentException; -use Log; -use Storage; class PrintJobController extends Controller { @@ -31,7 +33,7 @@ public function indexPrintJobs(?string $filter = null) if ($filter === "all") { $this->authorize('viewAny', PrintJob::class); - PrintJob::checkAndUpdateStatuses(); + PrinterHelper::updateCompletedPrintJobs(); return $this->paginatorFrom( printJobs: PrintJob::query() @@ -49,7 +51,7 @@ public function indexPrintJobs(?string $filter = null) $this->authorize('viewSelf', PrintJob::class); - PrintJob::checkAndUpdateStatuses(); + PrinterHelper::updateCompletedPrintJobs(); return $this->paginatorFrom( printJobs: user() ->printJobs() @@ -70,8 +72,8 @@ public function indexPrintJobs(?string $filter = null) */ public function store(Request $request) { - xdebug_break(); - Log::info($request->all()); + DB::beginTransaction(); + $request->validate([ 'file' => 'required|file', 'copies' => 'required|integer|min:1', @@ -79,7 +81,6 @@ public function store(Request $request) 'printer_id' => 'exists:printers,id', 'use_free_pages' => 'in:on,off', ]); - Log::info("Printjob cost 2"); $useFreePages = $request->boolean('use_free_pages'); $copyNumber = $request->input('copies'); @@ -90,7 +91,7 @@ public function store(Request $request) $printer = $request->has('printer_id') ? Printer::find($request->input("printer_id")) : Printer::firstWhere('name', config('print.printer_name')); $path = $file->store('print-documents'); - $pageNumber = Printer::getDocumentPageNumber($path); + $pageNumber = PrinterHelper::getDocumentPageNumber($path); /** @var PrintAccount */ $printAccount = user()->printAccount; @@ -103,7 +104,7 @@ public function store(Request $request) $jobId = null; try { - $jobId = $printer->print($twoSided, $copyNumber, $path); + $jobId = $printer->print($twoSided, $copyNumber, $path, user()); } catch (\Exception $e) { return back()->with('error', __('print.error_printing')); } finally { @@ -111,8 +112,8 @@ public function store(Request $request) } $cost = $useFreePages ? - PrintAccount::getFreePagesNeeeded($pageNumber, $copyNumber, $twoSided) : - PrintAccount::getBalanceNeeded($pageNumber, $copyNumber, $twoSided); + PrinterHelper::getFreePagesNeeeded($pageNumber, $copyNumber, $twoSided) : + PrinterHelper::getBalanceNeeded($pageNumber, $copyNumber, $twoSided); Log::info("Printjob cost: $cost"); @@ -156,6 +157,8 @@ public function store(Request $request) $printAccount->save(); + DB::commit(); + return back()->with('message', __('print.success')); } @@ -169,7 +172,7 @@ public function update(PrintJob $job) $this->authorize('update', $job); if ($job->state === PrintJobStatus::QUEUED) { - $result = ($job->printer ?? Printer::firstWhere('name', config('print.printer_name')))->cancelPrintJob($job); + $result = $job->cancel(); switch ($result) { case PrinterCancelResult::Success: $job->update([ diff --git a/app/Models/PrintAccount.php b/app/Models/PrintAccount.php index c48b9e94f..a96cac2a1 100644 --- a/app/Models/PrintAccount.php +++ b/app/Models/PrintAccount.php @@ -85,7 +85,7 @@ public function getAvailableFreePagesAttribute() public function hasEnoughFreePages(int $pages, int $copies, bool $twoSided) { return $this->getAvailableFreePagesAttribute()->sum('amount') > - $this::getFreePagesNeeeded($pages, $copies, $twoSided); + PrinterHelper::getFreePagesNeeeded($pages, $copies, $twoSided); } /** @@ -97,61 +97,8 @@ public function hasEnoughFreePages(int $pages, int $copies, bool $twoSided) */ public function hasEnoughBalance(int $pages, int $copies, bool $twoSided) { - return $this->balance >= $this::getBalanceNeeded($pages, $twoSided, $copies); + return $this->balance >= PrinterHelper::getBalanceNeeded($pages, $twoSided, $copies); } - /** - * 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; - } + } diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index 758274fdb..8b111064c 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -3,6 +3,7 @@ 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; @@ -107,13 +108,25 @@ public function getTranslatedStateAttribute() } /** - * Gets the printjob-status with every printer, updates the status of the completed printjobs. + * Attemts to cancel the given `PrintJob`. Returns wether it was successful. + * @param PrintJob $this + * @return PrinterCancelResult */ - public static function checkAndUpdateStatuses() - { - foreach(PrintJob::query()->where('state', PrintJobStatus::QUEUED)->whereNotNull('printer_id')->pluck('printer_id')->unique() as $printer_id) { - $printJobs = Printer::find($printer_id)->getCompletedPrintJobs(); - PrintJob::whereIn('job_id', $printJobs)->update(['state' => PrintJobStatus::SUCCESS]); + public function cancel() { + $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()]; + + 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 index 2f5697952..4de688760 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -2,13 +2,14 @@ namespace App\Models; +use App\Enums\PrintJobStatus; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Facades\Log; use Psr\Container\NotFoundExceptionInterface; use Psr\Container\ContainerExceptionInterface; -use Symfony\Component\Process\Process; +use App\Utils\Process; class Printer extends Model { use HasFactory; @@ -34,33 +35,6 @@ public function printJobs() { return $this->hasMany(PrintJob::class); } - /** - * Attemts to cancel the given `PrintJob`. Returns wether it was successful. - * @param PrintJob $printJob - * @return PrinterCancelResult - */ - public function cancelPrintJob(PrintJob $printJob) { - $process = new Process(['cancel', $printJob->job_id, '-h', "$this->ip:$this->port"]); - if (config('app.debug')) { - // cancel(1) exits with status code 0 if it succeeds - $result = ['output' => '', 'exit_code' => 0]; - } else { - $process->run(); - $result = ['output' => $process->getOutput(), 'exit_code' => $process->getExitCode()]; - } - Log::info([$process->getCommandLine(), $result]); - 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; - } - /** * Asks the printer to print a document with the given configuration. * @param bool $twoSided @@ -103,43 +77,32 @@ public function print(bool $twoSided, int $copies, string $path) { return $jobId; } - /** - * Returns the number of pages in the PDF document at the given path. - * @param string $path - * @return int - */ - public static function getDocumentPageNumber(string $path): int { - $process = new Process(['pdfinfo', $path, '|', 'grep', "'^Pages'", '|', 'awk', "'{print $2}'"]); - if (config('app.debug')) { - $result = rand(1, 10); - } else { - $process->run(); - $result = intval($process->getOutput()); - } - Log::info([$process->getCommandLine(), $result]); - return $result; - } - /** * Returns the completed printjobs for this printer. - * @return void + * @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}'"]); - if (config('app.debug')) { - $result = []; - } else { - $process->run(); - $result = $process->getOutput(); - } - Log::info([$process->getCommandLine(), $result]); + $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 { diff --git a/app/Utils/PrinterHelper.php b/app/Utils/PrinterHelper.php new file mode 100644 index 000000000..96e627dd7 --- /dev/null +++ b/app/Utils/PrinterHelper.php @@ -0,0 +1,85 @@ +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(); + } + } +} \ No newline at end of file diff --git a/app/Utils/Process.php b/app/Utils/Process.php new file mode 100644 index 000000000..547f4be28 --- /dev/null +++ b/app/Utils/Process.php @@ -0,0 +1,30 @@ +=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/database/migrations/2023_12_25_182310_create_printers_table.php b/database/migrations/2023_12_25_182310_create_printers_table.php index 6ee0ba34c..3de21d905 100644 --- a/database/migrations/2023_12_25_182310_create_printers_table.php +++ b/database/migrations/2023_12_25_182310_create_printers_table.php @@ -3,6 +3,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; +use Illuminate\Support\Facades\DB; return new class () extends Migration { /** @@ -19,6 +20,14 @@ public function up() $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'), + ]); } /** diff --git a/resources/views/dormitory/print/manage/app.blade.php b/resources/views/dormitory/print/manage/app.blade.php index 30b931f4f..346d6c3b5 100644 --- a/resources/views/dormitory/print/manage/app.blade.php +++ b/resources/views/dormitory/print/manage/app.blade.php @@ -30,7 +30,7 @@
    - @include("dormitory.print.free", ['route' => route('free-pages.index', ['filter' => 'all']), 'admin' => true]) + @include("dormitory.print.free", ['route' => route('free-pages.index.admin'), 'admin' => true])
    @include("dormitory.print.history", ['route' => route('print-job.index', ['filter' => 'all']), 'admin' => true]) diff --git a/routes/web.php b/routes/web.php index a151dd20d..b3c675438 100644 --- a/routes/web.php +++ b/routes/web.php @@ -121,8 +121,9 @@ 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/{filter?}', [FreePagesController::class, 'indexFreePages'])->name('free-pages.index'); // print.free_pages.list, print.free_pages.list.all + 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 From 1b1685cd9137cced28df1475b32217ccf7d4e5fc Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 20:33:00 +0000 Subject: [PATCH 18/55] style: format code with PHP CS Fixer This commit fixes the style issues introduced in d6fbe58 according to the output from PHP CS Fixer. Details: https://github.com/EotvosCollegium/mars/pull/394 --- .../Dormitory/Printing/FreePagesController.php | 3 ++- .../Dormitory/Printing/PrintAccountController.php | 6 ++++-- app/Models/PrintAccount.php | 2 +- app/Models/PrintJob.php | 5 +++-- app/Utils/PrinterHelper.php | 12 +++++++----- app/Utils/Process.php | 12 +++++++----- 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/FreePagesController.php b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php index e15c1030a..02c1a4541 100644 --- a/app/Http/Controllers/Dormitory/Printing/FreePagesController.php +++ b/app/Http/Controllers/Dormitory/Printing/FreePagesController.php @@ -35,7 +35,8 @@ public function index() * Returns a paginated list of all `FreePages`. * @return LengthAwarePaginator */ - public function adminIndex() { + public function adminIndex() + { $this->authorize('viewAny', FreePages::class); return $this->freePagesPaginator( diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php index 7f777041e..846456a88 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php @@ -57,7 +57,8 @@ public function update(Request $request) * @param int $amount The amount of money to be transfered. * @return RedirectResponse */ - private function transferBalance(PrintAccount $printAccount, PrintAccount $otherAccount, int $amount) { + private function transferBalance(PrintAccount $printAccount, PrintAccount $otherAccount, int $amount) + { DB::beginTransaction(); // Cannot transfer to yourself if ($otherAccount->user_id === $printAccount->user_id) { @@ -102,7 +103,8 @@ private function transferBalance(PrintAccount $printAccount, PrintAccount $other * @param int $amount The amount of money to be added or subtracted. * @return RedirectResponse */ - private function modifyBalance(PrintAccount $printAccount, int $amount) { + private function modifyBalance(PrintAccount $printAccount, int $amount) + { DB::beginTransaction(); // Only admins can modify accounts $this->authorize('modify', $printAccount); diff --git a/app/Models/PrintAccount.php b/app/Models/PrintAccount.php index a96cac2a1..c63d59f29 100644 --- a/app/Models/PrintAccount.php +++ b/app/Models/PrintAccount.php @@ -100,5 +100,5 @@ public function hasEnoughBalance(int $pages, int $copies, bool $twoSided) return $this->balance >= PrinterHelper::getBalanceNeeded($pages, $twoSided, $copies); } - + } diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index 8b111064c..a9e7baaaf 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -109,10 +109,11 @@ public function getTranslatedStateAttribute() /** * Attemts to cancel the given `PrintJob`. Returns wether it was successful. - * @param PrintJob $this + * @param PrintJob $this * @return PrinterCancelResult */ - public function cancel() { + public function cancel() + { $printer = $this->printer ?? Printer::firstWhere('name', config('print.printer_name')); $process = new Process(['cancel', $this->job_id, '-h', "$printer->ip:$printer->port"]); $process->run(); diff --git a/app/Utils/PrinterHelper.php b/app/Utils/PrinterHelper.php index 96e627dd7..27d761a2d 100644 --- a/app/Utils/PrinterHelper.php +++ b/app/Utils/PrinterHelper.php @@ -5,13 +5,15 @@ use App\Enums\PrintJobStatus; use App\Utils\Process; -class PrinterHelper { +class PrinterHelper +{ /** * Returns the number of pages in the PDF document at the given path. - * @param string $path - * @return int + * @param string $path + * @return int */ - public static function getDocumentPageNumber(string $path): int { + public static function getDocumentPageNumber(string $path): int + { $process = new Process(['pdfinfo', $path, '|', 'grep', "'^Pages'", '|', 'awk', "'{print $2}'"]); $process->run(); $result = intval($process->getOutput(strval(rand(1, 10)))); @@ -82,4 +84,4 @@ public static function updateCompletedPrintJobs() Printer::find($printer_id)->updateCompletedPrintJobs(); } } -} \ No newline at end of file +} diff --git a/app/Utils/Process.php b/app/Utils/Process.php index 547f4be28..db8e75b4c 100644 --- a/app/Utils/Process.php +++ b/app/Utils/Process.php @@ -4,16 +4,18 @@ use Symfony\Component\Process\Process as SymfonyProcess; -class Process extends SymfonyProcess { - - public function run(?callable $callback = null, array $env = []): int { +class Process extends SymfonyProcess +{ + public function run(?callable $callback = null, array $env = []): int + { if (config('app.debug') === false) { return parent::run($callback, $env); } return 0; } - public function getOutput(string $debugOutput = ''): string { + public function getOutput(string $debugOutput = ''): string + { if (config('app.debug') === false) { return parent::getOutput(); } @@ -27,4 +29,4 @@ public function getExitCode(): ?int } return 0; } -} \ No newline at end of file +} From 9499653d778878249c0632ae4b37e1a41c77ebfb Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Mon, 23 Dec 2024 23:41:18 +0100 Subject: [PATCH 19/55] Resolving comments --- .gitignore | 1 + .vscode/launch.json | 48 ----- .vscode/settings.json | 3 - app/Enums/PrintJobStatus.php | 1 + .../PrintAccountHistoryController.php | 2 +- .../Dormitory/Printing/PrintJobController.php | 178 +++++++----------- .../Dormitory/Printing/PrinterController.php | 25 +-- app/Models/FreePages.php | 35 +++- app/Models/PrintAccount.php | 55 +++++- app/Models/PrintAccountHistory.php | 2 +- app/Models/PrintJob.php | 38 +++- app/Models/Printer.php | 29 +++ app/Utils/PrinterHelper.php | 2 +- ...3_12_25_184733_update_print_jobs_table.php | 7 + resources/lang/hu/print.php | 4 +- .../views/dormitory/print/history.blade.php | 2 +- .../dormitory/print/manage/app.blade.php | 2 +- .../views/dormitory/print/print.blade.php | 3 +- resources/views/layouts/navbar.blade.php | 2 +- routes/web.php | 22 ++- 20 files changed, 257 insertions(+), 204 deletions(-) delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index af039d7a1..9b7c676c3 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ _ide_helper.php _ide_helper_models.php .phpstorm.meta.php *.DS_Store +.vscode \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 9dc6b4df6..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - // 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 deleted file mode 100644 index 942c363bc..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "julia.environmentPath": "c:\\Users\\sszajbely\\mars" -} \ No newline at end of file diff --git a/app/Enums/PrintJobStatus.php b/app/Enums/PrintJobStatus.php index e64d38d0b..c485b55fa 100644 --- a/app/Enums/PrintJobStatus.php +++ b/app/Enums/PrintJobStatus.php @@ -7,4 +7,5 @@ enum PrintJobStatus: string { case ERROR = 'ERROR'; case CANCELLED = 'CANCELLED'; case SUCCESS = 'SUCCESS'; + // case REIMBURSED = 'REIMBURSED'; } \ No newline at end of file diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php index 30a6cb34e..66a9ba602 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountHistoryController.php @@ -20,7 +20,7 @@ class PrintAccountHistoryController extends Controller * @throws BindingResolutionException * @throws InvalidArgumentException */ - public function indexPrintAccountHistory() + public function index() { $this->authorize('viewAny', PrintJob::class); diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index b229962c5..2387061b7 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -16,42 +16,28 @@ use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Support\Arr; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Storage; +use Illuminate\Validation\Rule; use InvalidArgumentException; class PrintJobController extends Controller { /** - * Returns a paginated list of `PrintJob`s. - * @param null|string $filter Decides wether all `PrintJob`s or just the user's `PrintJob`s should be listed. + * Returns a paginated list of the current user's `PrintJob`s. * @return LengthAwarePaginator */ - public function indexPrintJobs(?string $filter = null) + public function index() { - if ($filter === "all") { - $this->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(); + PrinterHelper::updateCompletedPrintJobs(); + + PrinterHelper::updateCompletedPrintJobs(); + return $this->paginatorFrom( printJobs: user() ->printJobs() @@ -65,6 +51,29 @@ public function indexPrintJobs(?string $filter = null) ); } + /** + * Returns a paginated list of all `PrintJob`s. + * @return LengthAwarePaginator + */ + public function adminIndex() + { + $this->authorize('viewAny', PrintJob::class); + + PrinterHelper::updateCompletedPrintJobs(); + + return $this->paginatorFrom( + printJobs: PrintJob::with('user') + ->orderBy('print_jobs.created_at', 'desc'), + columns: [ + 'created_at', + 'filename', + 'cost', + 'state', + 'user.name', + ] + ); + } + /** * Prints a document, then stores the corresponding `PrintJob`. * @param Request $request @@ -78,7 +87,6 @@ public function store(Request $request) 'file' => 'required|file', 'copies' => 'required|integer|min:1', 'two_sided' => 'in:on,off', - 'printer_id' => 'exists:printers,id', 'use_free_pages' => 'in:on,off', ]); @@ -88,75 +96,37 @@ public function store(Request $request) $file = $request->file('file'); /** @var Printer */ - $printer = $request->has('printer_id') ? Printer::find($request->input("printer_id")) : Printer::firstWhere('name', config('print.printer_name')); + $printer = Printer::firstWhere('name', config('print.printer_name')); $path = $file->store('print-documents'); + $originalName = $file->getClientOriginalName(); $pageNumber = PrinterHelper::getDocumentPageNumber($path); /** @var PrintAccount */ $printAccount = user()->printAccount; - if (!(($useFreePages && $printAccount->hasEnoughFreePages($pageNumber, $copyNumber, $twoSided)) || - (!$useFreePages && $printAccount->hasEnoughBalance($pageNumber, $copyNumber, $twoSided))) - ) { + if (!$printAccount->hasEnoughBalanceOrFreePages($useFreePages, $pageNumber, $copyNumber, $twoSided)) { + DB::rollBack(); return back()->with('error', __('print.no_balance')); } - $jobId = null; + $cost = $useFreePages ? + PrinterHelper::getFreePagesNeeded($pageNumber, $copyNumber, $twoSided) : + PrinterHelper::getBalanceNeeded($pageNumber, $copyNumber, $twoSided); + + $printAccount->updateHistory($useFreePages, $cost); + try { - $jobId = $printer->print($twoSided, $copyNumber, $path, user()); + $printJob = $printer->createPrintJob($useFreePages, $cost, $path, $originalName, $twoSided, $copyNumber); + Log::info("User $printAccount->user_id started print job a document for $cost. Job ID: $printJob->job_id. Used free pages: $useFreePages. File: $originalName"); } catch (\Exception $e) { + DB::rollBack(); + Log::error("Error while creating print job: " . $e->getMessage()); 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')); @@ -167,48 +137,32 @@ public function store(Request $request) * @param PrintJob $job * @return RedirectResponse */ - public function update(PrintJob $job) + public function update(PrintJob $job, Request $request) { $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; - } + $data = $request->validate([ + 'state' => ['required', Rule::enum(PrintJobStatus::class)->only(PrintJobStatus::CANCELLED)], + ]); - $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")); + /** @var PrintJobStatus */ + $newState = $data['state']; + + switch ($newState->value) { + case PrintJobStatus::CANCELLED: + if ($job->state === PrintJobStatus::QUEUED) { + /** @var PrinterCancelResult */ + $result = $job->cancel(); + + if ($result === PrinterCancelResult::Success) { + return back()->with('message', __('general.successful_modification')); + } + return back()->with('error', __("print.$result->value")); + } + return back()->with('error', __('print.cannot_cancel')); + default: + abort(422); } - - return back(); } /** diff --git a/app/Http/Controllers/Dormitory/Printing/PrinterController.php b/app/Http/Controllers/Dormitory/Printing/PrinterController.php index 0b9035417..ea39e9764 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrinterController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrinterController.php @@ -15,18 +15,11 @@ class PrinterController extends Controller { /** - * Returns the print page for either the admin or the normal page. - * @param null|string $page Determines wether we are on the admin or the normal printing page. + * Returns the print page. * @return View */ - public function index(?string $page = null) + public function index() { - if ($page === "admin") { - $this->authorize('handleAny', PrintAccount::class); - - return view('dormitory.print.manage.app', ["users" => User::all()]); - } - return view('dormitory.print.app', [ "users" => User::all(), "user" => user(), @@ -34,6 +27,17 @@ public function index(?string $page = null) ]); } + /** + * Returns the admin print page. + * @return View + */ + public function adminIndex() + { + $this->authorize('handleAny', PrintAccount::class); + + return view('dormitory.print.manage.app', ["users" => User::all()]); + } + /** * Sets the given printer's out of paper sign. */ @@ -47,8 +51,7 @@ public function update(Request $request, Printer $printer) 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(); + $printer->update(['paper_out_at' => now()]); return redirect()->back()->with('message', __('mail.email_sent')); } else { $this->authorize('handleAny', PrintAccount::class); diff --git a/app/Models/FreePages.php b/app/Models/FreePages.php index 7d261219a..6e77d8069 100644 --- a/app/Models/FreePages.php +++ b/app/Models/FreePages.php @@ -2,6 +2,7 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -78,9 +79,11 @@ public function printAccount() * Wether the free pages are still available. * @return bool */ - protected function getAvailableAttribute() + protected function available() { - return now()->isBefore($this->deadline); + return Attribute::make( + get: fn() => now()->isBefore($this->deadline) + ); } /** @@ -91,4 +94,32 @@ public function modifier(): BelongsTo { return $this->belongsTo(User::class, 'last_modified_by'); } + + + /** + * Returns the amount of pages that can be subtracted from the free pages. + * If the amount is greater than the available pages, only the available pages are subtracted. + * @param int $amount + * @return int + */ + public function calculateSubtractablePages(int $amount) + { + return min($amount, $this->amount); + } + + /** + * Subtracts the given amount of pages from the free pages. + * If the amount is greater than the available pages, only the available pages are subtracted. + * @param int $amount + */ + public function subtractPages(int $amount) + { + if ($amount <= 0 || $amount > $this->amount) { + throw new \InvalidArgumentException("Amount must be greater than 0 and less than or equal to the available pages."); + } + $this->update([ + 'last_modified_by' => user()->id, + 'amount' => $this->amount - $amount, + ]); + } } diff --git a/app/Models/PrintAccount.php b/app/Models/PrintAccount.php index c63d59f29..347311ee6 100644 --- a/app/Models/PrintAccount.php +++ b/app/Models/PrintAccount.php @@ -3,6 +3,7 @@ namespace App\Models; use Illuminate\Contracts\Container\BindingResolutionException; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -69,9 +70,11 @@ public function freePages() * The free pages which are currently available. Sorts the free pages by their deadline. * @return Collection */ - public function getAvailableFreePagesAttribute() + public function availableFreePages() { - return $this->freePages()->where('deadline', '>', now())->orderBy('deadline')->get(); + return Attribute::make( + get: fn () => $this->freePages()->where('deadline', '>', now())->orderBy('deadline')->get() + ); } /** @@ -84,8 +87,8 @@ public function getAvailableFreePagesAttribute() */ public function hasEnoughFreePages(int $pages, int $copies, bool $twoSided) { - return $this->getAvailableFreePagesAttribute()->sum('amount') > - PrinterHelper::getFreePagesNeeeded($pages, $copies, $twoSided); + return $this->available_free_pages->sum('amount') > + PrinterHelper::getFreePagesNeeded($pages, $copies, $twoSided); } /** @@ -100,5 +103,49 @@ public function hasEnoughBalance(int $pages, int $copies, bool $twoSided) return $this->balance >= PrinterHelper::getBalanceNeeded($pages, $twoSided, $copies); } + /** + * Returns wether the user has enough balance or free pages to print a document. + * @param bool $useFreePages + * @param int $pages + * @param int $copies + * @param bool $twoSided + * @return bool + */ + public function hasEnoughBalanceOrFreePages(bool $useFreePages, int $pages, int $copies, bool $twoSided) + { + return $useFreePages ? $this->hasEnoughFreePages($pages, $copies, $twoSided) : $this->hasEnoughBalance($pages, $copies, $twoSided); + } + + public function updateHistory(bool $useFreePages, int $cost) { + // Update the print account history + $this->last_modified_by = user()->id; + + if ($useFreePages) { + $freePagesToSubtract = $cost; + $availableFreePages = $this->available_free_pages->where('amount', '>', 0); + + // Subtract the pages from the free pages pool, as many free pages as necessary + /** @var FreePages */ + foreach ($availableFreePages as $freePages) { + $subtractablePages = $freePages->calculateSubtractablePages($freePagesToSubtract); + $freePages->subtractPages($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 { + $this->balance -= $cost; + + // Remove value regarding the free page checkbox from the session + session()->remove('use_free_pages'); + } + + $this->save(); + } + } diff --git a/app/Models/PrintAccountHistory.php b/app/Models/PrintAccountHistory.php index ad03e5e63..3471eb89c 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. -// Obeservers are set up. +// Observers for updating entries are set up. /** * App\Models\PrintAccountHistory * diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index a9e7baaaf..7def5c06f 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -4,6 +4,7 @@ use App\Enums\PrintJobStatus; use App\Utils\Process; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -94,17 +95,21 @@ public function printAccount() /** * Attribute for the translated cost. */ - public function getTranslatedCostAttribute() + public function translatedCost() { - return $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF"; + return Attribute::make( + get: fn() => $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF" + ); } /** * Attribute for the translated state. */ - public function getTranslatedStateAttribute() + public function translatedState() { - return __("print." . strtoupper($this->state->value)); + return Attribute::make( + get: fn() => __("print." . strtoupper($this->state->value)) + ); } /** @@ -114,18 +119,41 @@ public function getTranslatedStateAttribute() */ public function cancel() { - $printer = $this->printer ?? Printer::firstWhere('name', config('print.printer_name')); + $printer = $this->printer; $process = new Process(['cancel', $this->job_id, '-h', "$printer->ip:$printer->port"]); $process->run(); $result = ['output' => $process->getOutput(), 'exit_code' => $process->getExitCode()]; if ($result['exit_code'] == 0) { + $this->update([ + 'state' => PrintJobStatus::CANCELLED, + ]); + $printAccount = $this->printAccount; + $printAccount->last_modified_by = user()->id; + + if ($this->used_free_pages) { + $pages = $printAccount->available_free_pages->first(); + $pages->update([ + 'last_modified_by' => user()->id, + 'amount' => $pages->amount + $this->cost, + ]); + } else { + $printAccount->balance += $this->cost; + } + + $this->save(); return PrinterCancelResult::Success; } if (strpos($result['output'], "already canceled") !== false) { + $this->update([ + 'state' => PrintJobStatus::CANCELLED, + ]); return PrinterCancelResult::AlreadyCancelled; } if (strpos($result['output'], "already completed") !== false) { + $this->update([ + 'state' => PrintJobStatus::SUCCESS, + ]); return PrinterCancelResult::AlreadyCompleted; } return PrinterCancelResult::CannotCancel; diff --git a/app/Models/Printer.php b/app/Models/Printer.php index 4de688760..309f2aac9 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -10,6 +10,8 @@ use Psr\Container\NotFoundExceptionInterface; use Psr\Container\ContainerExceptionInterface; use App\Utils\Process; +use Illuminate\Auth\AuthenticationException; +use Illuminate\Database\Eloquent\MassAssignmentException; class Printer extends Model { use HasFactory; @@ -35,6 +37,33 @@ public function printJobs() { return $this->hasMany(PrintJob::class); } + + /** + * Starts a new print job for the current user and saves it. + * @param bool $useFreePages + * @param int $cost + * @param string $filePath + * @param string $originalName + * @param bool $twoSided + * @param int $copyNumber + * @return Model + * @throws AuthenticationException + * @throws PrinterException + * @throws MassAssignmentException + */ + public function createPrintJob(bool $useFreePages, int $cost, string $filePath, string $originalName, bool $twoSided, int $copyNumber) { + $jobId = $this->print($twoSided, $copyNumber, $filePath, user()); + + return user()->printJobs()->create([ + 'printer_id' => $this->id, + 'state' => PrintJobStatus::QUEUED, + 'job_id' => $jobId, + 'cost' => $cost, + 'used_free_pages' => $useFreePages, + 'filename' => $originalName, + ]); + } + /** * Asks the printer to print a document with the given configuration. * @param bool $twoSided diff --git a/app/Utils/PrinterHelper.php b/app/Utils/PrinterHelper.php index 27d761a2d..d79d9b64c 100644 --- a/app/Utils/PrinterHelper.php +++ b/app/Utils/PrinterHelper.php @@ -50,7 +50,7 @@ public static function getPageTypesNeeded(int $pages, bool $twoSided) * @param mixed $twoSided * @return int|float */ - public static function getFreePagesNeeeded(int $pages, $copies, $twoSided) + public static function getFreePagesNeeded(int $pages, $copies, $twoSided) { $pageTypesNeeded = self::getPageTypesNeeded($pages, $twoSided); 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 index f40375192..9c5d410af 100644 --- a/database/migrations/2023_12_25_184733_update_print_jobs_table.php +++ b/database/migrations/2023_12_25_184733_update_print_jobs_table.php @@ -3,6 +3,7 @@ use App\Models\Printer; use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; return new class () extends Migration { @@ -18,6 +19,12 @@ public function up() $table->boolean('used_free_pages')->default(false)->after('cost'); $table->dropColumn('filepath'); }); + DB::table('print_jobs')->update([ + 'printer_id' => DB::table('printers')->first()->id + ]); + Schema::table('print_jobs', function (Blueprint $table) { + $table->foreignIdFor(Printer::class)->nullable(false)->change(); + }); } /** diff --git a/resources/lang/hu/print.php b/resources/lang/hu/print.php index 1fafbc5e3..572289b4e 100644 --- a/resources/lang/hu/print.php +++ b/resources/lang/hu/print.php @@ -6,7 +6,8 @@ 'QUEUED' => 'Sorban áll', 'SUCCESS' => 'Kész', 'add' => 'Hozzáadás', - 'already_cancelled' => 'A nyomtatás már vissza lett vonva.', + 'already_cancelled' => 'A nyomtatás már visszavonásra került.', + 'already_completed' => 'A nyomtatás már befejeződött.', 'amount' => 'Összeg', 'available_free_pages' => 'Ezen felül ingyenesen nyomtatható :number_of_free_pages oldal', 'available_money' => 'Rendelkezésre álló összeg', @@ -14,6 +15,7 @@ 'balance_change' => 'Egyenlegváltozás', 'cancel' => 'Mégse', 'cancel_job' => 'Megszakítás', + 'cannot_cancel' => 'Nem lehetett megszakítani a nyomtatást', 'changed_balance' => 'Megváltozott nyomtatási egyenleg', 'changed_balance_descr' => ':modifier módosította a nyomtatási egyenleged ennyivel: :amount. Az új egyenleged :balance Ft.', 'confirm_cancel' => 'Biztos, hogy meg szeretnéd szakítani a dokumentum nyomtatását?', diff --git a/resources/views/dormitory/print/history.blade.php b/resources/views/dormitory/print/history.blade.php index 1ae3a31c2..862258659 100644 --- a/resources/views/dormitory/print/history.blade.php +++ b/resources/views/dormitory/print/history.blade.php @@ -13,7 +13,7 @@ ).click(function() { $.ajax({ type: "PUT", - url: "{{ route('print-job.update', [':job']) }}".replace(':job', data.id), + url: "{{ route('print-job.update', [':job', 'state' => 'CANCELLED']) }}".replace(':job', data.id), success: function() { cell.getTable().setPage(cell.getTable().getPage()); }, diff --git a/resources/views/dormitory/print/manage/app.blade.php b/resources/views/dormitory/print/manage/app.blade.php index 346d6c3b5..e6b668e70 100644 --- a/resources/views/dormitory/print/manage/app.blade.php +++ b/resources/views/dormitory/print/manage/app.blade.php @@ -33,7 +33,7 @@ @include("dormitory.print.free", ['route' => route('free-pages.index.admin'), 'admin' => true])
    - @include("dormitory.print.history", ['route' => route('print-job.index', ['filter' => 'all']), 'admin' => true]) + @include("dormitory.print.history", ['route' => route('print-job.index.admin'), 'admin' => true])
    diff --git a/resources/views/dormitory/print/print.blade.php b/resources/views/dormitory/print/print.blade.php index 6d8c467b6..846fe1fdb 100644 --- a/resources/views/dormitory/print/print.blade.php +++ b/resources/views/dormitory/print/print.blade.php @@ -20,8 +20,7 @@ @lang('print.upload_money')

    -
    + @csrf
    diff --git a/resources/views/layouts/navbar.blade.php b/resources/views/layouts/navbar.blade.php index dab58b649..4295845b3 100644 --- a/resources/views/layouts/navbar.blade.php +++ b/resources/views/layouts/navbar.blade.php @@ -127,7 +127,7 @@ class="material-icons left">person_searchFelvételi @can('handleAny', \App\Models\PrintAccount::class)
  • - + local_printshopNyomtatás
  • diff --git a/routes/web.php b/routes/web.php index b3c675438..e2befe110 100644 --- a/routes/web.php +++ b/routes/web.php @@ -114,20 +114,22 @@ }); /** Printing */ - 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('/printer', [PrinterController::class, 'index'])->name('printer.index'); + Route::get('/printer/admin', [PrinterController::class, 'adminIndex'])->name('printer.index.admin'); + Route::put('/printer/{printer}', [PrinterController::class, 'update'])->name('printer.update'); - 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('/print-job', [PrintJobController::class, 'index'])->name('print-job.index'); + Route::get('/print-job/admin', [PrintJobController::class, 'adminIndex'])->name('print-job.index.admin'); + Route::post('print-job', [PrintJobController::class, 'store'])->name('print-job.store'); + Route::put('/print-job/{job}', [PrintJobController::class, 'update'])->name('print-job.update'); - 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::get('/free-pages', [FreePagesController::class, 'index'])->name('free-pages.index'); + Route::post('/free-pages', [FreePagesController::class, 'store'])->name('free-pages.store'); + Route::get('/free-pages/admin', [FreePagesController::class, 'adminIndex'])->name('free-pages.index.admin'); - Route::put('/print-account', [PrintAccountController::class, 'update'])->name('print-account.update'); // print.transfer-balance, print.modify + Route::put('/print-account', [PrintAccountController::class, 'update'])->name('print-account.update'); - Route::get('/print-account-history', [PrintAccountHistoryController::class, 'indexPrintAccountHistory'])->name('print-account-history.index'); //print.account_history + Route::get('/print-account-history', [PrintAccountHistoryController::class, 'index'])->name('print-account-history.index'); Route::prefix('internet')->name('internet.')->group(function () { Route::get('/', [InternetController::class, 'index'])->name('index'); From d5da58bd2cba9fe81bacb25e14b987786764a729 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:49:55 +0000 Subject: [PATCH 20/55] style: format code with PHP CS Fixer This commit fixes the style issues introduced in 9499653 according to the output from PHP CS Fixer. Details: https://github.com/EotvosCollegium/mars/pull/394 --- .../Controllers/Dormitory/Printing/PrintJobController.php | 2 +- app/Models/FreePages.php | 2 +- app/Models/PrintAccount.php | 3 ++- app/Models/PrintJob.php | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index 2387061b7..49220cc59 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -153,7 +153,7 @@ public function update(PrintJob $job, Request $request) if ($job->state === PrintJobStatus::QUEUED) { /** @var PrinterCancelResult */ $result = $job->cancel(); - + if ($result === PrinterCancelResult::Success) { return back()->with('message', __('general.successful_modification')); } diff --git a/app/Models/FreePages.php b/app/Models/FreePages.php index 6e77d8069..208b0e65d 100644 --- a/app/Models/FreePages.php +++ b/app/Models/FreePages.php @@ -82,7 +82,7 @@ public function printAccount() protected function available() { return Attribute::make( - get: fn() => now()->isBefore($this->deadline) + get: fn () => now()->isBefore($this->deadline) ); } diff --git a/app/Models/PrintAccount.php b/app/Models/PrintAccount.php index 347311ee6..50c00a9cc 100644 --- a/app/Models/PrintAccount.php +++ b/app/Models/PrintAccount.php @@ -116,7 +116,8 @@ public function hasEnoughBalanceOrFreePages(bool $useFreePages, int $pages, int return $useFreePages ? $this->hasEnoughFreePages($pages, $copies, $twoSided) : $this->hasEnoughBalance($pages, $copies, $twoSided); } - public function updateHistory(bool $useFreePages, int $cost) { + public function updateHistory(bool $useFreePages, int $cost) + { // Update the print account history $this->last_modified_by = user()->id; diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index 7def5c06f..ad3eb436b 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -98,7 +98,7 @@ public function printAccount() public function translatedCost() { return Attribute::make( - get: fn() => $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF" + get: fn () => $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF" ); } @@ -108,7 +108,7 @@ public function translatedCost() public function translatedState() { return Attribute::make( - get: fn() => __("print." . strtoupper($this->state->value)) + get: fn () => __("print." . strtoupper($this->state->value)) ); } From 67e6413e3dde55cf80a6fa47b9cf0fa97e9bf6c7 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Tue, 24 Dec 2024 00:19:04 +0100 Subject: [PATCH 21/55] Minor fixes --- app/Http/Controllers/Dormitory/Printing/PrintJobController.php | 3 --- app/Models/PrintAccount.php | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index 49220cc59..7236354ff 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -33,9 +33,6 @@ public function index() { $this->authorize('viewSelf', PrintJob::class); - PrinterHelper::updateCompletedPrintJobs(); - PrinterHelper::updateCompletedPrintJobs(); - PrinterHelper::updateCompletedPrintJobs(); return $this->paginatorFrom( diff --git a/app/Models/PrintAccount.php b/app/Models/PrintAccount.php index 50c00a9cc..31662dfb2 100644 --- a/app/Models/PrintAccount.php +++ b/app/Models/PrintAccount.php @@ -87,7 +87,7 @@ public function availableFreePages() */ public function hasEnoughFreePages(int $pages, int $copies, bool $twoSided) { - return $this->available_free_pages->sum('amount') > + return $this->available_free_pages->sum('amount') >= PrinterHelper::getFreePagesNeeded($pages, $copies, $twoSided); } From 1455bb9bf4f744df208ae4355431db8d7c7d873c Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Tue, 24 Dec 2024 00:28:33 +0100 Subject: [PATCH 22/55] Added doc comments --- app/Models/PrintAccount.php | 7 ++++++- app/Utils/Process.php | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/app/Models/PrintAccount.php b/app/Models/PrintAccount.php index 31662dfb2..fc7df092f 100644 --- a/app/Models/PrintAccount.php +++ b/app/Models/PrintAccount.php @@ -100,7 +100,7 @@ public function hasEnoughFreePages(int $pages, int $copies, bool $twoSided) */ public function hasEnoughBalance(int $pages, int $copies, bool $twoSided) { - return $this->balance >= PrinterHelper::getBalanceNeeded($pages, $twoSided, $copies); + return $this->balance >= PrinterHelper::getBalanceNeeded($pages, $copies, $twoSided); } /** @@ -116,6 +116,11 @@ public function hasEnoughBalanceOrFreePages(bool $useFreePages, int $pages, int return $useFreePages ? $this->hasEnoughFreePages($pages, $copies, $twoSided) : $this->hasEnoughBalance($pages, $copies, $twoSided); } + /** + * Updates the print account history and the print account balance. + * @param bool $useFreePages + * @param int $cost + */ public function updateHistory(bool $useFreePages, int $cost) { // Update the print account history diff --git a/app/Utils/Process.php b/app/Utils/Process.php index db8e75b4c..9504e4801 100644 --- a/app/Utils/Process.php +++ b/app/Utils/Process.php @@ -6,6 +6,13 @@ class Process extends SymfonyProcess { + /** + * Run the process. + * + * @param callable|null $callback + * @param array $env + * @return int + */ public function run(?callable $callback = null, array $env = []): int { if (config('app.debug') === false) { @@ -14,6 +21,12 @@ public function run(?callable $callback = null, array $env = []): int return 0; } + /** + * Get the output of the process. + * + * @param string $debugOutput + * @return string + */ public function getOutput(string $debugOutput = ''): string { if (config('app.debug') === false) { @@ -22,6 +35,12 @@ public function getOutput(string $debugOutput = ''): string return $debugOutput; } + /** + * Get the exit code of the process. + * + * @param string $debugOutput + * @return string + */ public function getExitCode(): ?int { if (config('app.debug') === false) { From 0fd4a0c2ea4822f0049d3950c46fde3e88223ef5 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Tue, 24 Dec 2024 00:46:01 +0100 Subject: [PATCH 23/55] Fixed piping in commands. --- app/Console/Commands.php | 29 ++++++++--------------------- app/Models/Printer.php | 2 +- app/Utils/Process.php | 2 +- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/app/Console/Commands.php b/app/Console/Commands.php index fe993f36c..4e7b157be 100644 --- a/app/Console/Commands.php +++ b/app/Console/Commands.php @@ -2,8 +2,8 @@ namespace App\Console; +use App\Utils\Process; use Illuminate\Support\Facades\Log; -use Symfony\Component\Process\Process; /** * Collection of exec commands. @@ -11,33 +11,20 @@ */ class Commands { - private static function isDebugMode() - { - return config('app.debug'); - } - public static function pingRouter($router) { - if (self::isDebugMode()) { - $result = rand(1, 10) > 9 ? "error" : ''; - } else { - // This happens too often to log. - $process = new Process(['ping', $router->ip, '-c', '1', '|', 'grep', "'error\|unreachable'"]); - $process->run(); - $result = $process->getOutput(); - } + // This happens too often to log. + $process = Process::fromShellCommandline("ping $router->ip -c 1 | grep 'error\|unreachable'"); + $process->run(); + $result = $process->getOutput(debugOutput: rand(1, 10) > 9 ? "error" : ''); return $result; } public static function latexToPdf($path, $outputDir) { - if (self::isDebugMode()) { - $result = "ok"; - } else { - $process = new Process(['pdflatex', '-interaction=nonstopmode', '-output-dir', $outputDir, $path]); - $process->run(); - $result = $process->getOutput(); - } + $process = new Process(['pdflatex', '-interaction=nonstopmode', '-output-dir', $outputDir, $path]); + $process->run(); + $result = $process->getOutput(debugOutput: 'ok'); return $result; } } diff --git a/app/Models/Printer.php b/app/Models/Printer.php index 309f2aac9..ce5b46b86 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -114,7 +114,7 @@ public function print(bool $twoSided, int $copies, string $path) { */ public function getCompletedPrintJobs() { try { - $process = new Process(['lpstat', '-W', 'completed', '-o', $this->name, '-h', "$this->ip:$this->port", '|', 'awk', "'{print $1}'"]); + $process = Process::fromShellCommandline("lpstat -W completed -o $this->name -h $this->ip:$this->port | awk '{print $1}'"); $process->run(); $result = explode("\n", $process->getOutput()); return $result; diff --git a/app/Utils/Process.php b/app/Utils/Process.php index 9504e4801..3ab98d2cb 100644 --- a/app/Utils/Process.php +++ b/app/Utils/Process.php @@ -7,7 +7,7 @@ class Process extends SymfonyProcess { /** - * Run the process. + * Run the process. If the app is in debug mode, the process will not be executed. * * @param callable|null $callback * @param array $env From 4acf0a89663e204ca58cf90e41f3e121a80883c2 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Tue, 24 Dec 2024 00:50:36 +0100 Subject: [PATCH 24/55] Use commands config file --- app/Console/Commands.php | 4 ++-- app/Models/PrintJob.php | 2 +- app/Models/Printer.php | 2 +- app/Utils/PrinterHelper.php | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/Console/Commands.php b/app/Console/Commands.php index 4e7b157be..ec751daad 100644 --- a/app/Console/Commands.php +++ b/app/Console/Commands.php @@ -14,7 +14,7 @@ class Commands public static function pingRouter($router) { // This happens too often to log. - $process = Process::fromShellCommandline("ping $router->ip -c 1 | grep 'error\|unreachable'"); + $process = Process::fromShellCommandline(config('commands.ping') . " $router->ip -c 1 | grep 'error\|unreachable'"); $process->run(); $result = $process->getOutput(debugOutput: rand(1, 10) > 9 ? "error" : ''); return $result; @@ -22,7 +22,7 @@ public static function pingRouter($router) public static function latexToPdf($path, $outputDir) { - $process = new Process(['pdflatex', '-interaction=nonstopmode', '-output-dir', $outputDir, $path]); + $process = new Process([config('commands.pdflatex'), '-interaction=nonstopmode', '-output-dir', $outputDir, $path]); $process->run(); $result = $process->getOutput(debugOutput: 'ok'); return $result; diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index ad3eb436b..e3c98083d 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -120,7 +120,7 @@ public function translatedState() public function cancel() { $printer = $this->printer; - $process = new Process(['cancel', $this->job_id, '-h', "$printer->ip:$printer->port"]); + $process = new Process([config('commands.cancel'), $this->job_id, '-h', "$printer->ip:$printer->port"]); $process->run(); $result = ['output' => $process->getOutput(), 'exit_code' => $process->getExitCode()]; diff --git a/app/Models/Printer.php b/app/Models/Printer.php index ce5b46b86..4b6953afa 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -114,7 +114,7 @@ public function print(bool $twoSided, int $copies, string $path) { */ public function getCompletedPrintJobs() { try { - $process = Process::fromShellCommandline("lpstat -W completed -o $this->name -h $this->ip:$this->port | awk '{print $1}'"); + $process = Process::fromShellCommandline(config('commands.lpstat') . " -W completed -o $this->name -h $this->ip:$this->port | awk '{print $1}'"); $process->run(); $result = explode("\n", $process->getOutput()); return $result; diff --git a/app/Utils/PrinterHelper.php b/app/Utils/PrinterHelper.php index d79d9b64c..3ae89b4ef 100644 --- a/app/Utils/PrinterHelper.php +++ b/app/Utils/PrinterHelper.php @@ -14,7 +14,7 @@ class PrinterHelper */ public static function getDocumentPageNumber(string $path): int { - $process = new Process(['pdfinfo', $path, '|', 'grep', "'^Pages'", '|', 'awk', "'{print $2}'"]); + $process = Process::fromShellCommandline(config('commands.pdfinfo') . " $path | grep '^Pages' | awk '{print $2}'"); $process->run(); $result = intval($process->getOutput(strval(rand(1, 10)))); return $result; From f85af3d5a61d265d7d33a67facfd733ff7aeaf0f Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Tue, 24 Dec 2024 09:23:06 +0100 Subject: [PATCH 25/55] Minor fixes. --- .env.example | 1 + app/Console/Commands.php | 5 ++++- app/Enums/PrinterCancelResult.php | 10 ++++++++++ .../Dormitory/Printing/PrintJobController.php | 2 +- app/Models/PrintAccount.php | 9 ++++----- app/Models/PrintJob.php | 1 + app/Models/Printer.php | 10 ++-------- app/Utils/Process.php | 8 ++++---- config/commands.php | 1 + resources/views/dormitory/print/print.blade.php | 2 +- 10 files changed, 29 insertions(+), 20 deletions(-) create mode 100644 app/Enums/PrinterCancelResult.php diff --git a/.env.example b/.env.example index 5c4e968b9..11d7cbd99 100644 --- a/.env.example +++ b/.env.example @@ -88,6 +88,7 @@ CANCEL_COMMAND=cancel PDFINFO_COMMAND=pdfinfo PING_COMMAND=ping PDFLATEX_COMMAND=/usr/bin/pdflatex +RUN_COMMANDS_IN_DEBUG_MODE=false WORKSHOP_BALANCE_EXTERN=0.45 WORKSHOP_BALANCE_RESIDENT=0.6 diff --git a/app/Console/Commands.php b/app/Console/Commands.php index ec751daad..6ca582487 100644 --- a/app/Console/Commands.php +++ b/app/Console/Commands.php @@ -13,7 +13,10 @@ class Commands { public static function pingRouter($router) { - // This happens too often to log. + if (preg_match('/[a-zA-Z]/', $router->ip)) { + throw new \InvalidArgumentException("Invalid IP address: " . $router->ip); + } + $process = Process::fromShellCommandline(config('commands.ping') . " $router->ip -c 1 | grep 'error\|unreachable'"); $process->run(); $result = $process->getOutput(debugOutput: rand(1, 10) > 9 ? "error" : ''); diff --git a/app/Enums/PrinterCancelResult.php b/app/Enums/PrinterCancelResult.php new file mode 100644 index 000000000..4ba0ebff6 --- /dev/null +++ b/app/Enums/PrinterCancelResult.php @@ -0,0 +1,10 @@ + $this->freePages()->where('deadline', '>', now())->orderBy('deadline')->get() - ); + return $this->freePages()->where('deadline', '>', now())->orderBy('deadline')->get(); } /** @@ -87,7 +85,7 @@ public function availableFreePages() */ public function hasEnoughFreePages(int $pages, int $copies, bool $twoSided) { - return $this->available_free_pages->sum('amount') >= + return $this->availableFreePages()->sum('amount') >= PrinterHelper::getFreePagesNeeded($pages, $copies, $twoSided); } @@ -118,6 +116,7 @@ public function hasEnoughBalanceOrFreePages(bool $useFreePages, int $pages, int /** * Updates the print account history and the print account balance. + * Important note: This function should only be called within a transaction. Otherwise, the history may not be consistent. * @param bool $useFreePages * @param int $cost */ @@ -128,7 +127,7 @@ public function updateHistory(bool $useFreePages, int $cost) if ($useFreePages) { $freePagesToSubtract = $cost; - $availableFreePages = $this->available_free_pages->where('amount', '>', 0); + $availableFreePages = $this->availableFreePages()->where('amount', '>', 0); // Subtract the pages from the free pages pool, as many free pages as necessary /** @var FreePages */ diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index e3c98083d..a3cc14c29 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Enums\PrinterCancelResult; use App\Enums\PrintJobStatus; use App\Utils\Process; use Illuminate\Database\Eloquent\Casts\Attribute; diff --git a/app/Models/Printer.php b/app/Models/Printer.php index 4b6953afa..32e208e12 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -52,7 +52,7 @@ public function printJobs() { * @throws MassAssignmentException */ public function createPrintJob(bool $useFreePages, int $cost, string $filePath, string $originalName, bool $twoSided, int $copyNumber) { - $jobId = $this->print($twoSided, $copyNumber, $filePath, user()); + $jobId = $this->print($twoSided, $copyNumber, $filePath); return user()->printJobs()->create([ 'printer_id' => $this->id, @@ -120,6 +120,7 @@ public function getCompletedPrintJobs() { return $result; } 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()); } } @@ -134,13 +135,6 @@ public function updateCompletedPrintJobs() { } } -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/Utils/Process.php b/app/Utils/Process.php index 3ab98d2cb..f5b372087 100644 --- a/app/Utils/Process.php +++ b/app/Utils/Process.php @@ -15,7 +15,7 @@ class Process extends SymfonyProcess */ public function run(?callable $callback = null, array $env = []): int { - if (config('app.debug') === false) { + if (config('app.debug') === false || config('commands.run_in_debug') === true) { return parent::run($callback, $env); } return 0; @@ -29,7 +29,7 @@ public function run(?callable $callback = null, array $env = []): int */ public function getOutput(string $debugOutput = ''): string { - if (config('app.debug') === false) { + if (config('app.debug') === false || config('commands.run_in_debug') === true) { return parent::getOutput(); } return $debugOutput; @@ -39,11 +39,11 @@ public function getOutput(string $debugOutput = ''): string * Get the exit code of the process. * * @param string $debugOutput - * @return string + * @return int|null */ public function getExitCode(): ?int { - if (config('app.debug') === false) { + if (config('app.debug') === false || config('commands.run_in_debug') === true) { return parent::getExitCode(); } return 0; diff --git a/config/commands.php b/config/commands.php index c3ea4f12c..528076759 100644 --- a/config/commands.php +++ b/config/commands.php @@ -6,4 +6,5 @@ 'pdfinfo' => env('PDFINFO_COMMAND', 'pdfinfo'), 'ping' => env('PING_COMMAND', 'ping'), 'pdflatex' => env('PDFLATEX_COMMAND', '/usr/bin/pdflatex'), + 'run_in_debug' => env('RUN_COMMANDS_IN_DEBUG_MODE', false), ]; diff --git a/resources/views/dormitory/print/print.blade.php b/resources/views/dormitory/print/print.blade.php index d5f6e9684..8ede8b9ce 100644 --- a/resources/views/dormitory/print/print.blade.php +++ b/resources/views/dormitory/print/print.blade.php @@ -29,7 +29,7 @@ - @if($printAccount->available_free_pages->sum('amount') > 0) {{-- only show when user have active free pages --}} + @if($printAccount->availableFreePages()->sum('amount') > 0) {{-- only show if the user has active free pages --}} From a42a2828b3357bc00570677baec8d98f17ddb312 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Tue, 24 Dec 2024 08:23:39 +0000 Subject: [PATCH 26/55] style: format code with PHP CS Fixer This commit fixes the style issues introduced in f85af3d according to the output from PHP CS Fixer. Details: https://github.com/EotvosCollegium/mars/pull/394 --- app/Models/Printer.php | 65 +++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/app/Models/Printer.php b/app/Models/Printer.php index 32e208e12..0b4679897 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -13,7 +13,8 @@ use Illuminate\Auth\AuthenticationException; use Illuminate\Database\Eloquent\MassAssignmentException; -class Printer extends Model { +class Printer extends Model +{ use HasFactory; public $timestamps = false; @@ -31,27 +32,29 @@ class Printer extends Model { /** * Returns the `PrintJob`s that were executed by this printer. - * @return HasMany + * @return HasMany */ - public function printJobs() { + public function printJobs() + { return $this->hasMany(PrintJob::class); } /** * Starts a new print job for the current user and saves it. - * @param bool $useFreePages - * @param int $cost - * @param string $filePath - * @param string $originalName - * @param bool $twoSided - * @param int $copyNumber - * @return Model - * @throws AuthenticationException - * @throws PrinterException - * @throws MassAssignmentException + * @param bool $useFreePages + * @param int $cost + * @param string $filePath + * @param string $originalName + * @param bool $twoSided + * @param int $copyNumber + * @return Model + * @throws AuthenticationException + * @throws PrinterException + * @throws MassAssignmentException */ - public function createPrintJob(bool $useFreePages, int $cost, string $filePath, string $originalName, bool $twoSided, int $copyNumber) { + public function createPrintJob(bool $useFreePages, int $cost, string $filePath, string $originalName, bool $twoSided, int $copyNumber) + { $jobId = $this->print($twoSided, $copyNumber, $filePath); return user()->printJobs()->create([ @@ -66,24 +69,25 @@ public function createPrintJob(bool $useFreePages, int $cost, string $filePath, /** * Asks the printer to print a document with the given configuration. - * @param bool $twoSided - * @param int $copies - * @param string $path + * @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) { + 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", + 'lp', + '-d', $this->name, + '-h', "$this->ip:$this->port", ($twoSided ? '-o sides=two-sided-long-edge' : ''), - '-n', $copies, + '-n', $copies, $path ]); $process->run(); @@ -108,11 +112,12 @@ public function print(bool $twoSided, int $copies, string $path) { /** * Returns the completed printjobs for this printer. - * @return array - * @throws NotFoundExceptionInterface - * @throws ContainerExceptionInterface + * @return array + * @throws NotFoundExceptionInterface + * @throws ContainerExceptionInterface */ - public function getCompletedPrintJobs() { + public function getCompletedPrintJobs() + { try { $process = Process::fromShellCommandline(config('commands.lpstat') . " -W completed -o $this->name -h $this->ip:$this->port | awk '{print $1}'"); $process->run(); @@ -127,14 +132,16 @@ public function getCompletedPrintJobs() { /** * Updates the state of the completed printjobs to `PrintJobStatus::SUCCESS`. */ - public function updateCompletedPrintJobs() { + public function updateCompletedPrintJobs() + { PrintJob::whereIn( - 'job_id', + 'job_id', $this->getCompletedPrintJobs() )->update(['state' => PrintJobStatus::SUCCESS]); } } -class PrinterException extends \Exception { +class PrinterException extends \Exception +{ // } From 548981f6940e85b4814b420cc295d194b4d79353 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Tue, 24 Dec 2024 09:30:49 +0100 Subject: [PATCH 27/55] Fix for migration. --- .../migrations/2023_12_25_184733_update_print_jobs_table.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 9c5d410af..b77c95f5d 100644 --- a/database/migrations/2023_12_25_184733_update_print_jobs_table.php +++ b/database/migrations/2023_12_25_184733_update_print_jobs_table.php @@ -15,7 +15,7 @@ public function up() { Schema::table('print_jobs', function (Blueprint $table) { - $table->foreignIdFor(Printer::class)->nullable()->after('user_id')->constrained()->nullOnDelete(); + $table->foreignIdFor(Printer::class)->nullable()->after('user_id')->constrained(); $table->boolean('used_free_pages')->default(false)->after('cost'); $table->dropColumn('filepath'); }); From d6569445d56f1a06dd74ecdf2329beba5a53f29d Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Tue, 24 Dec 2024 09:42:08 +0100 Subject: [PATCH 28/55] Minor fixes --- app/Models/PrintJob.php | 75 +++++++++++++++++++++-------------------- app/Models/Printer.php | 11 +++--- app/Utils/Process.php | 4 +++ 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index a3cc14c29..a98530e20 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -10,6 +10,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasOneThrough; +use Illuminate\Support\Facades\DB; use Log; /** @@ -99,7 +100,7 @@ public function printAccount() public function translatedCost() { return Attribute::make( - get: fn () => $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF" + get: fn() => $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF" ); } @@ -109,7 +110,7 @@ public function translatedCost() public function translatedState() { return Attribute::make( - get: fn () => __("print." . strtoupper($this->state->value)) + get: fn() => __("print." . strtoupper($this->state->value)) ); } @@ -120,43 +121,45 @@ public function translatedState() */ public function cancel() { - $printer = $this->printer; - $process = new Process([config('commands.cancel'), $this->job_id, '-h', "$printer->ip:$printer->port"]); - $process->run(); - $result = ['output' => $process->getOutput(), 'exit_code' => $process->getExitCode()]; + return DB::transaction(function () { + $printer = $this->printer; + $process = new Process([config('commands.cancel'), $this->job_id, '-h', "$printer->ip:$printer->port"]); + $process->run(); + $result = ['output' => $process->getOutput(), 'exit_code' => $process->getExitCode()]; - if ($result['exit_code'] == 0) { - $this->update([ - 'state' => PrintJobStatus::CANCELLED, - ]); - $printAccount = $this->printAccount; - $printAccount->last_modified_by = user()->id; + if ($result['exit_code'] == 0) { + $this->update([ + 'state' => PrintJobStatus::CANCELLED, + ]); + $printAccount = $this->printAccount; + $printAccount->last_modified_by = user()->id; + + if ($this->used_free_pages) { + $pages = $printAccount->availableFreePages()->first(); + $pages->update([ + 'last_modified_by' => user()->id, + 'amount' => $pages->amount + $this->cost, + ]); + } else { + $printAccount->balance += $this->cost; + } - if ($this->used_free_pages) { - $pages = $printAccount->available_free_pages->first(); - $pages->update([ - 'last_modified_by' => user()->id, - 'amount' => $pages->amount + $this->cost, + $this->save(); + return PrinterCancelResult::Success; + } + if (strpos($result['output'], "already canceled") !== false) { + $this->update([ + 'state' => PrintJobStatus::CANCELLED, ]); - } else { - $printAccount->balance += $this->cost; + return PrinterCancelResult::AlreadyCancelled; } - - $this->save(); - return PrinterCancelResult::Success; - } - if (strpos($result['output'], "already canceled") !== false) { - $this->update([ - 'state' => PrintJobStatus::CANCELLED, - ]); - return PrinterCancelResult::AlreadyCancelled; - } - if (strpos($result['output'], "already completed") !== false) { - $this->update([ - 'state' => PrintJobStatus::SUCCESS, - ]); - return PrinterCancelResult::AlreadyCompleted; - } - return PrinterCancelResult::CannotCancel; + if (strpos($result['output'], "already completed") !== false) { + $this->update([ + 'state' => PrintJobStatus::SUCCESS, + ]); + return PrinterCancelResult::AlreadyCompleted; + } + return PrinterCancelResult::CannotCancel; + }); } } diff --git a/app/Models/Printer.php b/app/Models/Printer.php index 0b4679897..3bda2f435 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -12,6 +12,7 @@ use App\Utils\Process; use Illuminate\Auth\AuthenticationException; use Illuminate\Database\Eloquent\MassAssignmentException; +use Illuminate\Support\Facades\DB; class Printer extends Model { @@ -134,10 +135,12 @@ public function getCompletedPrintJobs() */ public function updateCompletedPrintJobs() { - PrintJob::whereIn( - 'job_id', - $this->getCompletedPrintJobs() - )->update(['state' => PrintJobStatus::SUCCESS]); + return DB::transaction(function () { + PrintJob::whereIn( + 'job_id', + $this->getCompletedPrintJobs() + )->update(['state' => PrintJobStatus::SUCCESS]); + }); } } diff --git a/app/Utils/Process.php b/app/Utils/Process.php index f5b372087..46b988176 100644 --- a/app/Utils/Process.php +++ b/app/Utils/Process.php @@ -2,6 +2,7 @@ namespace App\Utils; +use Illuminate\Support\Facades\Log; use Symfony\Component\Process\Process as SymfonyProcess; class Process extends SymfonyProcess @@ -18,6 +19,7 @@ public function run(?callable $callback = null, array $env = []): int if (config('app.debug') === false || config('commands.run_in_debug') === true) { return parent::run($callback, $env); } + Log::info("Process not executed in debug mode."); return 0; } @@ -32,6 +34,7 @@ public function getOutput(string $debugOutput = ''): string if (config('app.debug') === false || config('commands.run_in_debug') === true) { return parent::getOutput(); } + Log::info("Process output not available in debug mode."); return $debugOutput; } @@ -46,6 +49,7 @@ public function getExitCode(): ?int if (config('app.debug') === false || config('commands.run_in_debug') === true) { return parent::getExitCode(); } + Log::info("Process exit code not available in debug mode."); return 0; } } From 840f339b34817989720de283286f39aa9bd75049 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Tue, 24 Dec 2024 08:42:37 +0000 Subject: [PATCH 29/55] style: format code with PHP CS Fixer This commit fixes the style issues introduced in d656944 according to the output from PHP CS Fixer. Details: https://github.com/EotvosCollegium/mars/pull/394 --- app/Models/PrintJob.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index a98530e20..776addbf5 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -100,7 +100,7 @@ public function printAccount() public function translatedCost() { return Attribute::make( - get: fn() => $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF" + get: fn () => $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF" ); } @@ -110,7 +110,7 @@ public function translatedCost() public function translatedState() { return Attribute::make( - get: fn() => __("print." . strtoupper($this->state->value)) + get: fn () => __("print." . strtoupper($this->state->value)) ); } From 83c86fac83aa66c40c076523b0eef7ef301fd902 Mon Sep 17 00:00:00 2001 From: Samuel Szajbely Date: Tue, 24 Dec 2024 23:14:32 +0100 Subject: [PATCH 30/55] Fixed PrinterHelper namespace --- .../Controllers/Dormitory/Printing/PrintJobController.php | 2 +- app/Utils/PrinterHelper.php | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index 52420b2a6..306f77431 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -8,7 +8,7 @@ use App\Models\PrintAccount; use App\Models\Printer; use App\Enums\PrinterCancelResult; -use App\Models\PrinterHelper; +use App\Utils\PrinterHelper; use App\Models\PrintJob; use App\Utils\TabulatorPaginator; use Illuminate\Contracts\Container\BindingResolutionException; diff --git a/app/Utils/PrinterHelper.php b/app/Utils/PrinterHelper.php index 3ae89b4ef..3fd6f750d 100644 --- a/app/Utils/PrinterHelper.php +++ b/app/Utils/PrinterHelper.php @@ -1,8 +1,10 @@ Date: Wed, 25 Dec 2024 13:15:42 +0100 Subject: [PATCH 31/55] Remove references for Models in migrations Referencing Models in migrations should be avoided as changing the Model might change older migrations. Migrations are usually the "way of propagating changes you make to your Models (adding a field, deleting a model, etc.) into your database schema" (https://docs.djangoproject.com/en/5.1/topics/migrations/). Therefore migrations should never ever reference the Models as their main purpose is to have a migration between two different versions of models. Once a migration is written, they should usually never be edited in the future (unless the language / framework changes the syntax). But functionally a migration should remain the same in its whole life regardless of how the application is developed. --- database/migrations/2019_10_13_130718_create_roles_table.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/database/migrations/2019_10_13_130718_create_roles_table.php b/database/migrations/2019_10_13_130718_create_roles_table.php index db80fd83f..e62fd1f04 100644 --- a/database/migrations/2019_10_13_130718_create_roles_table.php +++ b/database/migrations/2019_10_13_130718_create_roles_table.php @@ -1,6 +1,5 @@ $role) { - DB::table('roles')->insert(['name' => $role]); + foreach (['sys-admin', 'collegist', 'tenant', 'workshop-administrator', 'workshop-leader', 'application-committee', 'aggregated-application-committee', 'secretary', 'director', 'staff', 'printer', 'locale-admin', 'student-council', 'student-council-secretary', 'board-of-trustees-member', 'ethics-commissioner', 'alumni', 'receptionist'] as $role_name) { + DB::table('roles')->insert(['name' => $role_name]); } } From c261baa0464559556bd897fd0352b6ed7e233ac0 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Wed, 25 Dec 2024 15:30:30 +0100 Subject: [PATCH 32/55] Fix seeders Seeders could not work with an entirely empty database. It's a problem that was introduced by the recent changes in migrations --- database/seeders/UsersTableSeeder.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/database/seeders/UsersTableSeeder.php b/database/seeders/UsersTableSeeder.php index bf896f641..62acc766c 100644 --- a/database/seeders/UsersTableSeeder.php +++ b/database/seeders/UsersTableSeeder.php @@ -2,6 +2,7 @@ namespace Database\Seeders; +use App\Models\Semester; use App\Models\Checkout; use App\Models\Faculty; use App\Models\FreePages; @@ -27,6 +28,8 @@ class UsersTableSeeder extends Seeder */ public function run() { + Semester::current(); // generate current semester if still not exists + $this->createSuperUser(); $this->createStaff(); From 344a4d68bc3b5e7e795f513604eca64f081b301c Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Wed, 25 Dec 2024 13:36:20 +0100 Subject: [PATCH 33/55] Remove printer role using migration --- .../2024_12_25_112824_remove_printer_role.php | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 database/migrations/2024_12_25_112824_remove_printer_role.php diff --git a/database/migrations/2024_12_25_112824_remove_printer_role.php b/database/migrations/2024_12_25_112824_remove_printer_role.php new file mode 100644 index 000000000..78244fab6 --- /dev/null +++ b/database/migrations/2024_12_25_112824_remove_printer_role.php @@ -0,0 +1,37 @@ +where('name', 'printer')->first()->id; + + DB::table('role_users')->where('role_id', $printer_role_id)->delete(); + + DB::table('roles')->where('name', 'printer')->delete(); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + $printer_role_id = DB::table('roles')->insertGetId([ + 'name' => 'printer' + ]); + + foreach(DB::table('users')->where('verified', 1)->get() as $user){ + DB::table('role_users')->insert([ + 'role_id' => $printer_role_id, + 'user_id' => $user->id + ]); + } + } +}; From b5fa0142352993bb0478f9b6e4b2ab4b4287d3f0 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Wed, 25 Dec 2024 12:35:28 +0000 Subject: [PATCH 34/55] Fixes --- app/Models/FreePages.php | 2 +- app/Models/PrintJob.php | 4 ++-- database/factories/PrintJobFactory.php | 1 + .../views/dormitory/print/manage/account_history.blade.php | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/Models/FreePages.php b/app/Models/FreePages.php index 208b0e65d..f5dbc11a7 100644 --- a/app/Models/FreePages.php +++ b/app/Models/FreePages.php @@ -79,7 +79,7 @@ public function printAccount() * Wether the free pages are still available. * @return bool */ - protected function available() + protected function available() : Attribute { return Attribute::make( get: fn () => now()->isBefore($this->deadline) diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index 776addbf5..fd1fd7811 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -97,7 +97,7 @@ public function printAccount() /** * Attribute for the translated cost. */ - public function translatedCost() + public function translatedCost() : Attribute { return Attribute::make( get: fn () => $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF" @@ -107,7 +107,7 @@ public function translatedCost() /** * Attribute for the translated state. */ - public function translatedState() + public function translatedState() : Attribute { return Attribute::make( get: fn () => __("print." . strtoupper($this->state->value)) diff --git a/database/factories/PrintJobFactory.php b/database/factories/PrintJobFactory.php index 5eae04289..d29dbbc96 100644 --- a/database/factories/PrintJobFactory.php +++ b/database/factories/PrintJobFactory.php @@ -13,6 +13,7 @@ class PrintJobFactory extends Factory public function definition() { return [ + 'printer_id' => 1, 'filename' => $this->faker->text, 'state' => $this->faker->randomElement(PrintJobStatus::cases()), 'job_id' => $this->faker->randomNumber, diff --git a/resources/views/dormitory/print/manage/account_history.blade.php b/resources/views/dormitory/print/manage/account_history.blade.php index a1b5adf47..aa60f2406 100644 --- a/resources/views/dormitory/print/manage/account_history.blade.php +++ b/resources/views/dormitory/print/manage/account_history.blade.php @@ -14,7 +14,7 @@ columns: [ { title: "Felhasználó", - field: "user_name", + field: "user.name", sorter: "string", headerFilter: 'input', minWidth:200 @@ -39,7 +39,7 @@ }, { title: "Módosító", - field: "modifier_name", + field: "modifier.name", sorter: "string", headerFilter: 'input', minWidth:180 From d79cd34875f5a0f7387f5d6f21fbbb5c5f62f0ba Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Wed, 25 Dec 2024 16:22:53 +0100 Subject: [PATCH 35/55] Added better check for pinging command --- app/Console/Commands.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Console/Commands.php b/app/Console/Commands.php index 6ca582487..d6b6d6236 100644 --- a/app/Console/Commands.php +++ b/app/Console/Commands.php @@ -13,7 +13,7 @@ class Commands { public static function pingRouter($router) { - if (preg_match('/[a-zA-Z]/', $router->ip)) { + if (!preg_match('^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$', $router->ip)) { throw new \InvalidArgumentException("Invalid IP address: " . $router->ip); } From b5dbb572becb4f02c5ebcf3ff37cc1efde5e96c2 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Wed, 25 Dec 2024 16:58:52 +0100 Subject: [PATCH 36/55] Added logging for the results of commands It has been extremely useful several times that we had commands of successful and failed commands. --- app/Console/Commands.php | 2 +- .../Controllers/Secretariat/DocumentController.php | 2 +- app/Utils/Process.php | 13 +++++++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/Console/Commands.php b/app/Console/Commands.php index d6b6d6236..6abbf5c40 100644 --- a/app/Console/Commands.php +++ b/app/Console/Commands.php @@ -18,7 +18,7 @@ public static function pingRouter($router) } $process = Process::fromShellCommandline(config('commands.ping') . " $router->ip -c 1 | grep 'error\|unreachable'"); - $process->run(); + $process->run($log = false); $result = $process->getOutput(debugOutput: rand(1, 10) > 9 ? "error" : ''); return $result; } diff --git a/app/Http/Controllers/Secretariat/DocumentController.php b/app/Http/Controllers/Secretariat/DocumentController.php index 1932d4e27..d19730080 100644 --- a/app/Http/Controllers/Secretariat/DocumentController.php +++ b/app/Http/Controllers/Secretariat/DocumentController.php @@ -158,7 +158,7 @@ private function generatePDF($path, $data) // TODO: figure out result Commands::latexToPdf($pathTex, $outputDir); - if (config('app.debug')) { + if (config('app.debug') && !config('commands.run_in_debug')) { return $pathTex; } else { return $pathPdf; diff --git a/app/Utils/Process.php b/app/Utils/Process.php index 46b988176..7ad6914aa 100644 --- a/app/Utils/Process.php +++ b/app/Utils/Process.php @@ -7,6 +7,7 @@ class Process extends SymfonyProcess { + /** * Run the process. If the app is in debug mode, the process will not be executed. * @@ -14,10 +15,18 @@ class Process extends SymfonyProcess * @param array $env * @return int */ - public function run(?callable $callback = null, array $env = []): int + public function run(?callable $callback = null, array $env = [], bool $log = true): int { if (config('app.debug') === false || config('commands.run_in_debug') === true) { - return parent::run($callback, $env); + $return_value = parent::run($callback, $env); + if($log) { + if($return_value === 0) { + Log::info("Command: " . $this->getCommandLine() . " executed successfully."); + } else { + Log::error("Command: " . $this->getCommandLine() . " failed with error code: " . $return_value . "\nWith output: " . $this->getOutput() . " and error output: " . $this->getErrorOutput()); + } + } + return $return_value; } Log::info("Process not executed in debug mode."); return 0; From afd2f1f4ec8c371baa1c488a6120fb6c09ebe5fe Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Wed, 25 Dec 2024 17:11:30 +0100 Subject: [PATCH 37/55] Added prefix for printing --- resources/views/dormitory/print/app.blade.php | 4 +-- .../views/dormitory/print/history.blade.php | 2 +- .../print/manage/account_history.blade.php | 2 +- .../dormitory/print/manage/app.blade.php | 4 +-- .../dormitory/print/manage/free.blade.php | 2 +- .../dormitory/print/manage/modify.blade.php | 2 +- .../views/dormitory/print/print.blade.php | 6 ++--- .../views/dormitory/print/send.blade.php | 2 +- resources/views/layouts/navbar.blade.php | 4 +-- routes/web.php | 26 ++++++++++--------- 10 files changed, 28 insertions(+), 26 deletions(-) diff --git a/resources/views/dormitory/print/app.blade.php b/resources/views/dormitory/print/app.blade.php index e4c843f57..ad0f5f05d 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-job.index'), 'admin' => false]) + @include("dormitory.print.history", ['route' => route('print.print-job.index'), 'admin' => false])
    - @include("dormitory.print.free", ['route' => route('free-pages.index'), 'admin' => false]) + @include("dormitory.print.free", ['route' => route('print.free-pages.index'), 'admin' => false])
    @include("dormitory.print.send") diff --git a/resources/views/dormitory/print/history.blade.php b/resources/views/dormitory/print/history.blade.php index 862258659..435f31530 100644 --- a/resources/views/dormitory/print/history.blade.php +++ b/resources/views/dormitory/print/history.blade.php @@ -13,7 +13,7 @@ ).click(function() { $.ajax({ type: "PUT", - url: "{{ route('print-job.update', [':job', 'state' => 'CANCELLED']) }}".replace(':job', data.id), + url: "{{ route('print.print-job.update', [':job', 'state' => 'CANCELLED']) }}".replace(':job', data.id), success: function() { cell.getTable().setPage(cell.getTable().getPage()); }, diff --git a/resources/views/dormitory/print/manage/account_history.blade.php b/resources/views/dormitory/print/manage/account_history.blade.php index aa60f2406..3a6b9c69e 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.index') }}", //set url for ajax request + ajaxURL: "{{ route('print.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 e6b668e70..c3a917e50 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('free-pages.index.admin'), 'admin' => true]) + @include("dormitory.print.free", ['route' => route('print.free-pages.index.admin'), 'admin' => true])
    - @include("dormitory.print.history", ['route' => route('print-job.index.admin'), 'admin' => true]) + @include("dormitory.print.history", ['route' => route('print.print-job.index.admin'), 'admin' => true])
    diff --git a/resources/views/dormitory/print/manage/free.blade.php b/resources/views/dormitory/print/manage/free.blade.php index 7ceb953e8..85f80be03 100644 --- a/resources/views/dormitory/print/manage/free.blade.php +++ b/resources/views/dormitory/print/manage/free.blade.php @@ -1,7 +1,7 @@ @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 1305a983a..216ca224c 100644 --- a/resources/views/dormitory/print/manage/modify.blade.php +++ b/resources/views/dormitory/print/manage/modify.blade.php @@ -2,7 +2,7 @@ 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 8ede8b9ce..71f1b9e2f 100644 --- a/resources/views/dormitory/print/print.blade.php +++ b/resources/views/dormitory/print/print.blade.php @@ -23,7 +23,7 @@ @lang('print.payment_methods_cannot_be_mixed')

    - + @csrf
    @@ -50,7 +50,7 @@
    @if($printer->paper_out_at != null && $user->can('handleAny', \App\Models\PrintAccount::class)) - + @method('PUT') @csrf @@ -58,7 +58,7 @@ @else -
    + @method('PUT') @csrf diff --git a/resources/views/dormitory/print/send.blade.php b/resources/views/dormitory/print/send.blade.php index 8c6ede6e0..d559d4e20 100644 --- a/resources/views/dormitory/print/send.blade.php +++ b/resources/views/dormitory/print/send.blade.php @@ -4,7 +4,7 @@
    @lang('print.how_transfer_works')
    - + @csrf @method('PUT')
    diff --git a/resources/views/layouts/navbar.blade.php b/resources/views/layouts/navbar.blade.php index f1c9bf7a7..134cc47c3 100644 --- a/resources/views/layouts/navbar.blade.php +++ b/resources/views/layouts/navbar.blade.php @@ -37,7 +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
  • build@lang('faults.faults') @can('handleAny', \App\Models\PrintAccount::class)
  • - + local_printshopNyomtatás
  • diff --git a/routes/web.php b/routes/web.php index 8fa6a83fb..a7fcbbef1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -127,22 +127,24 @@ }); /** Printing */ - Route::get('/printer', [PrinterController::class, 'index'])->name('printer.index'); - Route::get('/printer/admin', [PrinterController::class, 'adminIndex'])->name('printer.index.admin'); - Route::put('/printer/{printer}', [PrinterController::class, 'update'])->name('printer.update'); + Route::prefix('print')->name('print.')->group(function(){ + Route::get('/', [PrinterController::class, 'index'])->name('index'); + Route::get('/admin', [PrinterController::class, 'adminIndex'])->name('index.admin'); + Route::put('/{printer}', [PrinterController::class, 'update'])->name('update'); - Route::get('/print-job', [PrintJobController::class, 'index'])->name('print-job.index'); - Route::get('/print-job/admin', [PrintJobController::class, 'adminIndex'])->name('print-job.index.admin'); - Route::post('print-job', [PrintJobController::class, 'store'])->name('print-job.store'); - Route::put('/print-job/{job}', [PrintJobController::class, 'update'])->name('print-job.update'); + Route::get('/print-job', [PrintJobController::class, 'index'])->name('print-job.index'); + Route::get('/print-job/admin', [PrintJobController::class, 'adminIndex'])->name('print-job.index.admin'); + Route::post('print-job', [PrintJobController::class, 'store'])->name('print-job.store'); + Route::put('/print-job/{job}', [PrintJobController::class, 'update'])->name('print-job.update'); - Route::get('/free-pages', [FreePagesController::class, 'index'])->name('free-pages.index'); - Route::post('/free-pages', [FreePagesController::class, 'store'])->name('free-pages.store'); - Route::get('/free-pages/admin', [FreePagesController::class, 'adminIndex'])->name('free-pages.index.admin'); + Route::get('/free-pages', [FreePagesController::class, 'index'])->name('free-pages.index'); + Route::post('/free-pages', [FreePagesController::class, 'store'])->name('free-pages.store'); + Route::get('/free-pages/admin', [FreePagesController::class, 'adminIndex'])->name('free-pages.index.admin'); - Route::put('/print-account', [PrintAccountController::class, 'update'])->name('print-account.update'); + Route::put('/print-account', [PrintAccountController::class, 'update'])->name('print-account.update'); - Route::get('/print-account-history', [PrintAccountHistoryController::class, 'index'])->name('print-account-history.index'); + Route::get('/print-account-history', [PrintAccountHistoryController::class, 'index'])->name('print-account-history.index'); + }); Route::prefix('internet')->name('internet.')->group(function () { Route::get('/', [InternetController::class, 'index'])->name('index'); From 7961a112f308cfa8b01242e8c80802a964fc4bbc Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Sun, 29 Dec 2024 15:30:50 +0000 Subject: [PATCH 38/55] style: format code with PHP CS Fixer This commit fixes the style issues introduced in afd2f1f according to the output from PHP CS Fixer. Details: https://github.com/EotvosCollegium/mars/pull/394 --- app/Models/FreePages.php | 2 +- app/Models/PrintJob.php | 4 ++-- app/Utils/Process.php | 1 - .../migrations/2024_12_25_112824_remove_printer_role.php | 7 +++---- routes/web.php | 4 ++-- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/app/Models/FreePages.php b/app/Models/FreePages.php index f5dbc11a7..e06de7551 100644 --- a/app/Models/FreePages.php +++ b/app/Models/FreePages.php @@ -79,7 +79,7 @@ public function printAccount() * Wether the free pages are still available. * @return bool */ - protected function available() : Attribute + protected function available(): Attribute { return Attribute::make( get: fn () => now()->isBefore($this->deadline) diff --git a/app/Models/PrintJob.php b/app/Models/PrintJob.php index fd1fd7811..195e82ba2 100644 --- a/app/Models/PrintJob.php +++ b/app/Models/PrintJob.php @@ -97,7 +97,7 @@ public function printAccount() /** * Attribute for the translated cost. */ - public function translatedCost() : Attribute + public function translatedCost(): Attribute { return Attribute::make( get: fn () => $this->used_free_pages ? "$this->cost ingyenes oldal" : "$this->cost HUF" @@ -107,7 +107,7 @@ public function translatedCost() : Attribute /** * Attribute for the translated state. */ - public function translatedState() : Attribute + public function translatedState(): Attribute { return Attribute::make( get: fn () => __("print." . strtoupper($this->state->value)) diff --git a/app/Utils/Process.php b/app/Utils/Process.php index 7ad6914aa..a312a6d2d 100644 --- a/app/Utils/Process.php +++ b/app/Utils/Process.php @@ -7,7 +7,6 @@ class Process extends SymfonyProcess { - /** * Run the process. If the app is in debug mode, the process will not be executed. * diff --git a/database/migrations/2024_12_25_112824_remove_printer_role.php b/database/migrations/2024_12_25_112824_remove_printer_role.php index 78244fab6..df08c3287 100644 --- a/database/migrations/2024_12_25_112824_remove_printer_role.php +++ b/database/migrations/2024_12_25_112824_remove_printer_role.php @@ -4,8 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class () extends Migration { /** * Run the migrations. */ @@ -26,8 +25,8 @@ public function down(): void $printer_role_id = DB::table('roles')->insertGetId([ 'name' => 'printer' ]); - - foreach(DB::table('users')->where('verified', 1)->get() as $user){ + + foreach(DB::table('users')->where('verified', 1)->get() as $user) { DB::table('role_users')->insert([ 'role_id' => $printer_role_id, 'user_id' => $user->id diff --git a/routes/web.php b/routes/web.php index a7fcbbef1..d3107fe59 100644 --- a/routes/web.php +++ b/routes/web.php @@ -127,7 +127,7 @@ }); /** Printing */ - Route::prefix('print')->name('print.')->group(function(){ + Route::prefix('print')->name('print.')->group(function () { Route::get('/', [PrinterController::class, 'index'])->name('index'); Route::get('/admin', [PrinterController::class, 'adminIndex'])->name('index.admin'); Route::put('/{printer}', [PrinterController::class, 'update'])->name('update'); @@ -144,7 +144,7 @@ Route::put('/print-account', [PrintAccountController::class, 'update'])->name('print-account.update'); Route::get('/print-account-history', [PrintAccountHistoryController::class, 'index'])->name('print-account-history.index'); - }); + }); Route::prefix('internet')->name('internet.')->group(function () { Route::get('/', [InternetController::class, 'index'])->name('index'); From 02daade8418dde4f8dad7add12c956df5f80d145 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 16:58:03 +0000 Subject: [PATCH 39/55] Make .env.example more understandable --- .env.example | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.env.example b/.env.example index 11d7cbd99..7ae98f43a 100644 --- a/.env.example +++ b/.env.example @@ -71,6 +71,8 @@ PREVENT_ACCESSING_MISSING_ATTRIBUTES=false PRINT_COST_ONESIDED=8 PRINT_COST_TWOSIDED=12 + +#Data used during migration in 2023_12_25_182310_create_printers_table.php PRINTER_NAME=NemUjBela PRINTER_IP= PRINTER_PORT= From c51937864e3890cffe6d0fdb2b4794c19910f817 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 18:01:24 +0100 Subject: [PATCH 40/55] Using proper filtering instead of regex for ip Use filter_var instead of regex. Coderabbit suggested the change. I do not agree with the reasoning coderabbit gave, it was functional, this is simply more readable. --- app/Console/Commands.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Console/Commands.php b/app/Console/Commands.php index 6abbf5c40..a91249ba8 100644 --- a/app/Console/Commands.php +++ b/app/Console/Commands.php @@ -13,7 +13,7 @@ class Commands { public static function pingRouter($router) { - if (!preg_match('^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$', $router->ip)) { + if (!filter_var($router->ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { throw new \InvalidArgumentException("Invalid IP address: " . $router->ip); } From 7238e6402bc3f2ccd6c411323256c814ef73c0f1 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 18:10:43 +0100 Subject: [PATCH 41/55] Added more strict rate limiting --- app/Http/Controllers/Dormitory/Printing/PrinterController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrinterController.php b/app/Http/Controllers/Dormitory/Printing/PrinterController.php index ea39e9764..b67328581 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrinterController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrinterController.php @@ -48,7 +48,7 @@ public function update(Request $request, Printer $printer) ]); if ($request->boolean("no_paper")) { - if ($printer->paper_out_at === null || now()->diffInMinutes($printer->paper_out_at) > 5) { + if ($printer->paper_out_at === null || now()->diffInMinutes($printer->paper_out_at) > 30) { Mail::to(User::withRole(Role::SYS_ADMIN)->get())->queue(new NoPaper(user()->name)); } $printer->update(['paper_out_at' => now()]); From 9fac10713b174bccd658b01a08c1e6f59d9db009 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 18:29:50 +0100 Subject: [PATCH 42/55] Fixing up routes --- resources/views/dormitory/print/manage/modify.blade.php | 2 +- resources/views/dormitory/print/send.blade.php | 2 +- routes/web.php | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/resources/views/dormitory/print/manage/modify.blade.php b/resources/views/dormitory/print/manage/modify.blade.php index 216ca224c..1305a983a 100644 --- a/resources/views/dormitory/print/manage/modify.blade.php +++ b/resources/views/dormitory/print/manage/modify.blade.php @@ -2,7 +2,7 @@ Egyenleg módosítása
    A tranzakció az admin kasszába fog kerülni.
    - + @csrf @method('PUT') diff --git a/resources/views/dormitory/print/send.blade.php b/resources/views/dormitory/print/send.blade.php index d559d4e20..8c6ede6e0 100644 --- a/resources/views/dormitory/print/send.blade.php +++ b/resources/views/dormitory/print/send.blade.php @@ -4,7 +4,7 @@
    @lang('print.how_transfer_works')
    - + @csrf @method('PUT')
    diff --git a/routes/web.php b/routes/web.php index d3107fe59..5c629e0dd 100644 --- a/routes/web.php +++ b/routes/web.php @@ -141,11 +141,12 @@ Route::post('/free-pages', [FreePagesController::class, 'store'])->name('free-pages.store'); Route::get('/free-pages/admin', [FreePagesController::class, 'adminIndex'])->name('free-pages.index.admin'); - Route::put('/print-account', [PrintAccountController::class, 'update'])->name('print-account.update'); Route::get('/print-account-history', [PrintAccountHistoryController::class, 'index'])->name('print-account-history.index'); }); + Route::put('/print-account-update', [PrintAccountController::class, 'update'])->name('print-account.update'); + Route::prefix('internet')->name('internet.')->group(function () { Route::get('/', [InternetController::class, 'index'])->name('index'); Route::post('/reset', [InternetController::class, 'resetWifiPassword'])->name('password.reset'); From a4f888c8d61a0f97a3ca04406cb1cc7e063b07a9 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 18:34:22 +0100 Subject: [PATCH 43/55] Better emailing for e-mail balances Added a missing Ft to Hungarian email and also emailing the recipient. --- .../Controllers/Dormitory/Printing/PrintAccountController.php | 3 ++- resources/lang/hu/print.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php index 846456a88..5e25f510a 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php @@ -92,7 +92,8 @@ private function transferBalance(PrintAccount $printAccount, PrintAccount $other DB::commit(); - Mail::to($printAccount->user)->queue(new ChangedPrintBalance($printAccount->user, $amount, user()->name)); + Mail::to($printAccount->user)->queue(new ChangedPrintBalance($printAccount->user, -$amount, user()->name)); + Mail::to($otherAccount->user)->queue(new ChangedPrintBalance($otherAccount->user, $amount, user()->name)); return redirect()->back()->with('message', __('general.successful_transaction')); } diff --git a/resources/lang/hu/print.php b/resources/lang/hu/print.php index a91cdd46a..6f510ca27 100644 --- a/resources/lang/hu/print.php +++ b/resources/lang/hu/print.php @@ -17,7 +17,7 @@ 'cancel_job' => 'Megszakítás', 'cannot_cancel' => 'Nem lehetett megszakítani a nyomtatást', 'changed_balance' => 'Megváltozott nyomtatási egyenleg', - 'changed_balance_descr' => ':modifier módosította a nyomtatási egyenleged ennyivel: :amount. Az új egyenleged :balance Ft.', + 'changed_balance_descr' => ':modifier módosította a nyomtatási egyenleged ennyivel: :amount Ft. Az új egyenleged :balance Ft.', 'confirm_cancel' => 'Biztos, hogy meg szeretnéd szakítani a dokumentum nyomtatását?', 'cost' => 'Költség', 'costs' => 'Az egyoldalas nyomtatás díja :one_sided, a kétoldalasé :two_sided Ft.', From bd6c4cb9b687c80bbec6fb706b2245e7f2918c3f Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 19:03:43 +0100 Subject: [PATCH 44/55] Emailing all involved Send emails to each individual of all of the balance changes. (For better transparency.) --- .../Dormitory/Printing/PrintAccountController.php | 15 +++++++++++---- app/Mail/ChangedPrintBalance.php | 4 +++- resources/lang/en/print.php | 3 ++- resources/lang/hu/print.php | 3 ++- .../views/emails/changed_print_balance.blade.php | 6 +++++- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php index 5e25f510a..6851724b6 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php @@ -92,8 +92,10 @@ private function transferBalance(PrintAccount $printAccount, PrintAccount $other DB::commit(); - Mail::to($printAccount->user)->queue(new ChangedPrintBalance($printAccount->user, -$amount, user()->name)); - Mail::to($otherAccount->user)->queue(new ChangedPrintBalance($otherAccount->user, $amount, user()->name)); + Mail::to($printAccount->user)->queue(new ChangedPrintBalance($printAccount->user, $printAccount->user, -$amount, user()->name)); + Mail::to($otherAccount->user)->queue(new ChangedPrintBalance($otherAccount->user, $printAccount->user, -$amount, user()->name)); + Mail::to($printAccount->user)->queue(new ChangedPrintBalance($printAccount->user, $otherAccount->user, $amount, user()->name)); + Mail::to($otherAccount->user)->queue(new ChangedPrintBalance($otherAccount->user, $otherAccount->user, $amount, user()->name)); return redirect()->back()->with('message', __('general.successful_transaction')); } @@ -119,8 +121,6 @@ private function modifyBalance(PrintAccount $printAccount, int $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, @@ -135,6 +135,13 @@ private function modifyBalance(PrintAccount $printAccount, int $amount) DB::commit(); + Mail::to(user())->queue(new ChangedPrintBalance(user(), $printAccount->user, $amount, user()->name)); + + //Do not send duplicate emails + if($printAccount->user->id !== user()->id) { + Mail::to($printAccount->user)->queue(new ChangedPrintBalance($printAccount->user, $printAccount->user, $amount, user()->name)); + } + return redirect()->back()->with('message', __('general.successful_modification')); } diff --git a/app/Mail/ChangedPrintBalance.php b/app/Mail/ChangedPrintBalance.php index 492ad5cf0..2a4f5b89b 100644 --- a/app/Mail/ChangedPrintBalance.php +++ b/app/Mail/ChangedPrintBalance.php @@ -12,6 +12,7 @@ class ChangedPrintBalance extends Mailable use SerializesModels; public $recipient; //User model + public $print_account_holder; //User model public $amount; //how much the balance has changed public $modifier; //modifier's name @@ -20,9 +21,10 @@ class ChangedPrintBalance extends Mailable * * @return void */ - public function __construct($recipient, $amount, $modifier) + public function __construct($recipient, $print_account_holder, $amount, $modifier) { $this->recipient = $recipient; + $this->print_account_holder = $print_account_holder; $this->amount = $amount; $this->modifier = $modifier; } diff --git a/resources/lang/en/print.php b/resources/lang/en/print.php index fdc65f6e7..663dcaba4 100644 --- a/resources/lang/en/print.php +++ b/resources/lang/en/print.php @@ -15,7 +15,6 @@ 'cancel' => 'Cancel', 'cancel_job' => 'Abort', 'changed_balance' => 'Modified print balance', - 'changed_balance_descr' => ':modifier have been added :amount HUF to your print balance. Your new balance is :balance HUF.', 'confirm_cancel' => 'Are you sure you wish to abort printing this document?', 'cost' => 'Cost', 'costs' => 'One-sided printing costs :one_sided, and two-sided printing costs :two_sided HUF.', @@ -43,6 +42,7 @@ 'number_of_copies' => 'Number of copies', 'number_of_printed_documents' => 'Number of printed documents', 'options' => 'Printing options', + 'others_balance_changed_descr' => ':modifier has changed the print balance of :holder-name by HUF :amount.', 'payment_methods_cannot_be_mixed' => 'A print job can be either free or paid as they cannot be mixed.', 'pdf_description' => 'Only .pdf files can be printed.', 'pdf_maxsize' => 'The maximum file size is :maxsize MB.', @@ -61,4 +61,5 @@ 'upload_money' => 'You can upload money to your account at the system admins.', 'use_free_pages' => 'Use free pages', 'user' => 'User', + 'your_balance_changed_descr' => ':modifier has changed your print balance by HUF :amount. The new balance is HUF :balance.', ]; diff --git a/resources/lang/hu/print.php b/resources/lang/hu/print.php index 6f510ca27..fa44e4668 100644 --- a/resources/lang/hu/print.php +++ b/resources/lang/hu/print.php @@ -17,7 +17,6 @@ 'cancel_job' => 'Megszakítás', 'cannot_cancel' => 'Nem lehetett megszakítani a nyomtatást', 'changed_balance' => 'Megváltozott nyomtatási egyenleg', - 'changed_balance_descr' => ':modifier módosította a nyomtatási egyenleged ennyivel: :amount Ft. Az új egyenleged :balance Ft.', 'confirm_cancel' => 'Biztos, hogy meg szeretnéd szakítani a dokumentum nyomtatását?', 'cost' => 'Költség', 'costs' => 'Az egyoldalas nyomtatás díja :one_sided, a kétoldalasé :two_sided Ft.', @@ -45,6 +44,7 @@ 'number_of_copies' => 'Példányszám', 'number_of_printed_documents' => 'Nyomtatott dokumentumok száma', 'options' => 'Beállítások', + 'others_balance_changed_descr' => ':modifier módosította :holder-name egyenlegét :amount Ft-tal.', 'payment_methods_cannot_be_mixed' => 'Egy nyomtatás vagy ingyenes vagy fizetős lehet, nem keverhető.', 'pdf_description' => 'Csak .pdf fájl nyomtatható.', 'pdf_maxsize' => 'A fájl mérete legfeljebb :maxsize MB lehet.', @@ -63,4 +63,5 @@ 'upload_money' => 'Pénzt feltölteni a rendszergazdáknál tudsz.', 'use_free_pages' => 'Ingyenes oldalak használata', 'user' => 'Felhasználó', + 'your_balance_changed_descr' => ':modifier módosította a nyomtatási egyenleged :amount Ft-tal. Az új egyenleged :balance Ft.', ]; diff --git a/resources/views/emails/changed_print_balance.blade.php b/resources/views/emails/changed_print_balance.blade.php index 381f4d357..b09f62e10 100644 --- a/resources/views/emails/changed_print_balance.blade.php +++ b/resources/views/emails/changed_print_balance.blade.php @@ -1,6 +1,10 @@ @component('mail::message')

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

    -@lang('print.changed_balance_descr', ['amount' => $amount, 'balance' => $recipient->printAccount->balance, 'modifier' => $modifier]) +@if ($print_account_holder->id === $recipient->id) + @lang('print.your_balance_changed_descr', ['amount' => $amount, 'balance' => $print_account_holder->printAccount->balance, 'modifier' => $modifier]) +@else + @lang('print.others_balance_changed_descr', ['amount' => $amount, 'holder-name' => $print_account_holder->name, 'modifier' => $modifier]) +@endif

    @endcomponent From 517157bbd86e83b4974c7cce0647420fee4584ed Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 19:11:28 +0100 Subject: [PATCH 45/55] Better commenting --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 7ae98f43a..cdc4e4060 100644 --- a/.env.example +++ b/.env.example @@ -72,7 +72,7 @@ PREVENT_ACCESSING_MISSING_ATTRIBUTES=false PRINT_COST_ONESIDED=8 PRINT_COST_TWOSIDED=12 -#Data used during migration in 2023_12_25_182310_create_printers_table.php +#Data used during migration in 2023_12_25_182310_create_printers_table.php to create a new printer PRINTER_NAME=NemUjBela PRINTER_IP= PRINTER_PORT= From ee9b1754641fdf0613363bb978f867cb0dd76efc Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 19:16:09 +0100 Subject: [PATCH 46/55] Restore composer.lock --- composer.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index 67c27f926..c5147dd72 100644 --- a/composer.lock +++ b/composer.lock @@ -4875,7 +4875,7 @@ "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "autoload": { @@ -5082,11 +5082,11 @@ "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -5095,13 +5095,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "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/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/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0|^7.0" + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6519,7 +6519,7 @@ "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", @@ -6534,7 +6534,7 @@ "symfony/http-client": "^6.4|^7.0", "symfony/intl": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -10657,5 +10657,5 @@ "php": "^8.2" }, "platform-dev": [], - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } From 78f252caaaabe584153a730719b25e1cb0b7a6c3 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 19:41:18 +0100 Subject: [PATCH 47/55] Bugfixes and better suit our needs Using the printing filesystem for printing. In case of free pages we are charging for each side we need to put toner on. We try to minimize our paper usage by automatically selecting double-sided printing. --- .../Controllers/Dormitory/Printing/PrintJobController.php | 4 ++-- app/Models/PrintAccount.php | 1 + app/Utils/PrinterHelper.php | 6 ++---- app/Utils/Process.php | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index 306f77431..1e325b3d2 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -95,9 +95,9 @@ public function store(Request $request) /** @var Printer */ $printer = Printer::firstWhere('name', config('print.printer_name')); - $path = $file->store('print-documents'); + $path = $file->store('', 'printing'); $originalName = $file->getClientOriginalName(); - $pageNumber = PrinterHelper::getDocumentPageNumber($path); + $pageNumber = PrinterHelper::getDocumentPageNumber(Storage::disk('printing')->path($path)); /** @var PrintAccount */ $printAccount = user()->printAccount; diff --git a/app/Models/PrintAccount.php b/app/Models/PrintAccount.php index ed7129633..2ccb29cf3 100644 --- a/app/Models/PrintAccount.php +++ b/app/Models/PrintAccount.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Utils\PrinterHelper; use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Collection; diff --git a/app/Utils/PrinterHelper.php b/app/Utils/PrinterHelper.php index 3fd6f750d..dc7741454 100644 --- a/app/Utils/PrinterHelper.php +++ b/app/Utils/PrinterHelper.php @@ -52,11 +52,9 @@ public static function getPageTypesNeeded(int $pages, bool $twoSided) * @param mixed $twoSided * @return int|float */ - public static function getFreePagesNeeded(int $pages, $copies, $twoSided) + public static function getFreePagesNeeded(int $pages, int $copies, bool $twoSided) { - $pageTypesNeeded = self::getPageTypesNeeded($pages, $twoSided); - - return ($pageTypesNeeded['one_sided'] + $pageTypesNeeded['two_sided']) * $copies; + return $pages * $copies; //We are charging for each of the printed sides of paper } /** diff --git a/app/Utils/Process.php b/app/Utils/Process.php index a312a6d2d..7552134b8 100644 --- a/app/Utils/Process.php +++ b/app/Utils/Process.php @@ -20,7 +20,7 @@ public function run(?callable $callback = null, array $env = [], bool $log = tru $return_value = parent::run($callback, $env); if($log) { if($return_value === 0) { - Log::info("Command: " . $this->getCommandLine() . " executed successfully."); + Log::info("Command: " . $this->getCommandLine() . " executed successfully. With output: " . $this->getOutput() . " and error output: " . $this->getErrorOutput()); } else { Log::error("Command: " . $this->getCommandLine() . " failed with error code: " . $return_value . "\nWith output: " . $this->getOutput() . " and error output: " . $this->getErrorOutput()); } From fe6e80bf7f6a8e2822017cbfc8b09a5cf98839f4 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 21:14:21 +0100 Subject: [PATCH 48/55] Command fix --- app/Http/Controllers/Dormitory/Printing/PrintJobController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index 1e325b3d2..5c74d340d 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -96,8 +96,9 @@ public function store(Request $request) $printer = Printer::firstWhere('name', config('print.printer_name')); $path = $file->store('', 'printing'); + $path = Storage::disk('printing')->path($path); $originalName = $file->getClientOriginalName(); - $pageNumber = PrinterHelper::getDocumentPageNumber(Storage::disk('printing')->path($path)); + $pageNumber = PrinterHelper::getDocumentPageNumber($path); /** @var PrintAccount */ $printAccount = user()->printAccount; From ea2f243c07789ec2633ecb4e888abeabba5a0de4 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 21:28:19 +0100 Subject: [PATCH 49/55] Command fix --- .../Controllers/Dormitory/Printing/PrintJobController.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php index 5c74d340d..464482561 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintJobController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintJobController.php @@ -96,9 +96,8 @@ public function store(Request $request) $printer = Printer::firstWhere('name', config('print.printer_name')); $path = $file->store('', 'printing'); - $path = Storage::disk('printing')->path($path); $originalName = $file->getClientOriginalName(); - $pageNumber = PrinterHelper::getDocumentPageNumber($path); + $pageNumber = PrinterHelper::getDocumentPageNumber(Storage::disk('printing')->path($path)); /** @var PrintAccount */ $printAccount = user()->printAccount; @@ -115,14 +114,14 @@ public function store(Request $request) $printAccount->updateHistory($useFreePages, $cost); try { - $printJob = $printer->createPrintJob($useFreePages, $cost, $path, $originalName, $twoSided, $copyNumber); + $printJob = $printer->createPrintJob($useFreePages, $cost, Storage::disk('printing')->path($path), $originalName, $twoSided, $copyNumber); Log::info("User $printAccount->user_id started print job a document for $cost. Job ID: $printJob->job_id. Used free pages: $useFreePages. File: $originalName"); } catch (\Exception $e) { DB::rollBack(); Log::error("Error while creating print job: " . $e->getMessage()); return back()->with('error', __('print.error_printing')); } finally { - Storage::delete($path); + Storage::disk('printing')->delete($path); } DB::commit(); From d1fb9825ced6e222cc0a1b2d71224c2f0247c61c Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 21:40:03 +0100 Subject: [PATCH 50/55] Fix statuses --- app/Enums/PrintJobStatus.php | 2 +- app/Models/Printer.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Enums/PrintJobStatus.php b/app/Enums/PrintJobStatus.php index c485b55fa..d6a2664f8 100644 --- a/app/Enums/PrintJobStatus.php +++ b/app/Enums/PrintJobStatus.php @@ -4,7 +4,7 @@ enum PrintJobStatus: string { case QUEUED = 'QUEUED'; - case ERROR = 'ERROR'; + //case ERROR = 'ERROR'; //There are some older print jobs that have this status, but it is not used anymore case CANCELLED = 'CANCELLED'; case SUCCESS = 'SUCCESS'; // case REIMBURSED = 'REIMBURSED'; diff --git a/app/Models/Printer.php b/app/Models/Printer.php index 3bda2f435..f10e4a072 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -136,7 +136,7 @@ public function getCompletedPrintJobs() public function updateCompletedPrintJobs() { return DB::transaction(function () { - PrintJob::whereIn( + PrintJob::where('state', PrintJobStatus::QUEUED)->whereIn( 'job_id', $this->getCompletedPrintJobs() )->update(['state' => PrintJobStatus::SUCCESS]); From 6d45febdce50e551f4276cdabdcb5755d332b3fb Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 21:44:25 +0100 Subject: [PATCH 51/55] Adding missing translation --- resources/lang/en/print.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/lang/en/print.php b/resources/lang/en/print.php index 663dcaba4..6a1b95ad7 100644 --- a/resources/lang/en/print.php +++ b/resources/lang/en/print.php @@ -7,6 +7,7 @@ 'SUCCESS' => 'Completed', 'add' => 'Add', 'already_cancelled' => 'The print job was already cancelled.', + 'already_completed' => 'The print job was already completed.', 'amount' => 'Amount', 'available_free_pages' => 'Number of free pages left: :number_of_free_pages', 'available_money' => 'Available money', @@ -14,6 +15,7 @@ 'balance_change' => 'Balance change', 'cancel' => 'Cancel', 'cancel_job' => 'Abort', + 'cannot_cancel' => 'Unable to cancel the print job', 'changed_balance' => 'Modified print balance', 'confirm_cancel' => 'Are you sure you wish to abort printing this document?', 'cost' => 'Cost', From 40ee670ed718c1c79334237661377b1dd1187c1b Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 21:49:44 +0100 Subject: [PATCH 52/55] Fix tests --- tests/Feature/PrintControllerTest.php | 80 +++++++++++---------------- 1 file changed, 32 insertions(+), 48 deletions(-) diff --git a/tests/Feature/PrintControllerTest.php b/tests/Feature/PrintControllerTest.php index cf416fcf9..b13abccc9 100644 --- a/tests/Feature/PrintControllerTest.php +++ b/tests/Feature/PrintControllerTest.php @@ -18,35 +18,29 @@ public function testUserWithoutPermissions() $user->setVerified(); $this->actingAs($user); - // The user is not allowed to see the page without the correct permissions. - // TODO: test this with freshly registered user. $response = $this->get('/print'); + $response->assertStatus(200); + $response = $this->get('/print/free_pages'); + $response->assertStatus(200); + $response = $this->get('/print/print_job'); + $response->assertStatus(200); + $response = $this->get('/print/free_pages/admin'); $response->assertStatus(403); - $response = $this->get('/print/free_pages/list'); - $response->assertStatus(403); - $response = $this->get('/print/print_jobs/list'); - $response->assertStatus(403); - $response = $this->get('/print/free_pages/list/all'); - $response->assertStatus(403); - $response = $this->get('/print/print_jobs/list/all'); - $response->assertStatus(403); - $response = $this->get('/print/manage'); + $response = $this->get('/print/print_job/admin'); $response->assertStatus(403); - $response = $this->get('/print/account_history'); + $response = $this->get('/print/admin'); $response->assertStatus(403); + $response = $this->get('/print-account_history'); + $response->assertStatus(200); - $response = $this->post('/print/modify_balance', []); - $response->assertStatus(403); - $response = $this->post('/print/add_free_pages', []); - $response->assertStatus(403); - $response = $this->post('/print/transfer_balance', []); - $response->assertStatus(403); + $response = $this->post('/print-account-update', []); + $response->assertStatus(302); // TODO: #514 // $response = $this->post('/print/print_jobs/0/cancel', []); // $response->assertStatus(403); $response = $this->put('/print/print', []); - $response->assertStatus(403); + $response->assertStatus(302); } /** @@ -60,29 +54,24 @@ public function testUserWithPrinterPermissions() $response = $this->get('/print'); $response->assertStatus(200); - $response = $this->get('/print/free_pages/list'); + $response = $this->get('/print/free_pages'); $response->assertStatus(200); - $response = $this->get('/print/print_jobs/list'); + $response = $this->get('/print/print_job'); $response->assertStatus(200); - $response = $this->get('/print/free_pages/list/all'); - $response->assertStatus(403); - $response = $this->get('/print/print_jobs/list/all'); + $response = $this->get('/print/free_pages/admin'); $response->assertStatus(403); - $response = $this->get('/print/manage'); + $response = $this->get('/print/print_job/admin'); $response->assertStatus(403); - $response = $this->get('/print/account_history'); + $response = $this->get('/print/admin'); $response->assertStatus(403); + $response = $this->get('/print-account_history'); + $response->assertStatus(200); - $response = $this->post('/print/modify_balance', []); - $response->assertStatus(403); - $response = $this->post('/print/add_free_pages', []); - $response->assertStatus(403); - $response = $this->post('/print/transfer_balance', []); + $response = $this->post('/print-account-update', []); $response->assertStatus(302); // TODO: #514 - // $printJob = \App\Models\PrintJob::factory()->create(['user_id' => $user->id]); - // $response = $this->post('/print/print_jobs/' . $printJob->id . '/cancel', []); - // $response->assertStatus(200); + // $response = $this->post('/print/print_jobs/0/cancel', []); + // $response->assertStatus(403); $response = $this->put('/print/print', []); $response->assertStatus(302); @@ -100,29 +89,24 @@ public function testUserWithPrintAdminPermissions() $response = $this->get('/print'); $response->assertStatus(200); - $response = $this->get('/print/free_pages/list'); + $response = $this->get('/print/free_pages'); $response->assertStatus(200); - $response = $this->get('/print/print_jobs/list'); + $response = $this->get('/print/print_job'); $response->assertStatus(200); - $response = $this->get('/print/free_pages/list/all'); + $response = $this->get('/print/free_pages/admin'); $response->assertStatus(200); - $response = $this->get('/print/print_jobs/list/all'); + $response = $this->get('/print/print_job/admin'); $response->assertStatus(200); - $response = $this->get('/print/manage'); + $response = $this->get('/print/admin'); $response->assertStatus(200); - $response = $this->get('/print/account_history'); + $response = $this->get('/print-account_history'); $response->assertStatus(200); - $response = $this->post('/print/modify_balance', []); - $response->assertStatus(302); - $response = $this->post('/print/add_free_pages', []); - $response->assertStatus(302); - $response = $this->post('/print/transfer_balance', []); + $response = $this->post('/print-account-update', []); $response->assertStatus(302); // TODO: #514 - // $printJob = \App\Models\PrintJob::factory()->create(['user_id' => $user->id]); - // $response = $this->post('/print/print_jobs/' . $printJob->id . '/cancel', []); - // $response->assertStatus(200); + // $response = $this->post('/print/print_jobs/0/cancel', []); + // $response->assertStatus(403); $response = $this->put('/print/print', []); $response->assertStatus(302); From 12f5a2837761f12ad54d9e4d0fbb45b8e30bf310 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 21:53:11 +0100 Subject: [PATCH 53/55] Fix tests --- tests/Feature/PrintControllerTest.php | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/Feature/PrintControllerTest.php b/tests/Feature/PrintControllerTest.php index b13abccc9..f6077b450 100644 --- a/tests/Feature/PrintControllerTest.php +++ b/tests/Feature/PrintControllerTest.php @@ -20,17 +20,17 @@ public function testUserWithoutPermissions() $response = $this->get('/print'); $response->assertStatus(200); - $response = $this->get('/print/free_pages'); + $response = $this->get('/print/free-pages'); $response->assertStatus(200); - $response = $this->get('/print/print_job'); + $response = $this->get('/print/print-job'); $response->assertStatus(200); - $response = $this->get('/print/free_pages/admin'); + $response = $this->get('/print/free-pages/admin'); $response->assertStatus(403); - $response = $this->get('/print/print_job/admin'); + $response = $this->get('/print/print-job/admin'); $response->assertStatus(403); $response = $this->get('/print/admin'); $response->assertStatus(403); - $response = $this->get('/print-account_history'); + $response = $this->get('/print-account-history'); $response->assertStatus(200); $response = $this->post('/print-account-update', []); @@ -54,17 +54,17 @@ public function testUserWithPrinterPermissions() $response = $this->get('/print'); $response->assertStatus(200); - $response = $this->get('/print/free_pages'); + $response = $this->get('/print/free-pages'); $response->assertStatus(200); - $response = $this->get('/print/print_job'); + $response = $this->get('/print/print-job'); $response->assertStatus(200); - $response = $this->get('/print/free_pages/admin'); + $response = $this->get('/print/free-pages/admin'); $response->assertStatus(403); - $response = $this->get('/print/print_job/admin'); + $response = $this->get('/print/print-job/admin'); $response->assertStatus(403); $response = $this->get('/print/admin'); $response->assertStatus(403); - $response = $this->get('/print-account_history'); + $response = $this->get('/print-account-history'); $response->assertStatus(200); $response = $this->post('/print-account-update', []); @@ -89,17 +89,17 @@ public function testUserWithPrintAdminPermissions() $response = $this->get('/print'); $response->assertStatus(200); - $response = $this->get('/print/free_pages'); + $response = $this->get('/print/free-pages'); $response->assertStatus(200); - $response = $this->get('/print/print_job'); + $response = $this->get('/print/print-job'); $response->assertStatus(200); - $response = $this->get('/print/free_pages/admin'); + $response = $this->get('/print/free-pages/admin'); $response->assertStatus(200); - $response = $this->get('/print/print_job/admin'); + $response = $this->get('/print/print-job/admin'); $response->assertStatus(200); $response = $this->get('/print/admin'); $response->assertStatus(200); - $response = $this->get('/print-account_history'); + $response = $this->get('/print-account-history'); $response->assertStatus(200); $response = $this->post('/print-account-update', []); From eecb8cbbc092889a0d3ef2d2d3477b0a3a1ae842 Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 22:37:08 +0100 Subject: [PATCH 54/55] Fix tests --- .../Printing/PrintAccountController.php | 4 +- routes/web.php | 2 +- tests/Feature/PrintControllerTest.php | 133 +++++++++--------- tests/Unit/PrintTest.php | 16 +-- 4 files changed, 79 insertions(+), 76 deletions(-) diff --git a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php index 6851724b6..81ec92de9 100644 --- a/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php +++ b/app/Http/Controllers/Dormitory/Printing/PrintAccountController.php @@ -112,8 +112,8 @@ private function modifyBalance(PrintAccount $printAccount, int $amount) // Only admins can modify accounts $this->authorize('modify', $printAccount); - if ($amount < 0 && $printAccount->balance < $amount) { - $this->returnNoBalance(); + if ($amount < 0 && $printAccount->balance < abs($amount)) { + return $this->returnNoBalance(); } $printAccount->update([ diff --git a/routes/web.php b/routes/web.php index 5c629e0dd..77a2e9366 100644 --- a/routes/web.php +++ b/routes/web.php @@ -134,7 +134,7 @@ Route::get('/print-job', [PrintJobController::class, 'index'])->name('print-job.index'); Route::get('/print-job/admin', [PrintJobController::class, 'adminIndex'])->name('print-job.index.admin'); - Route::post('print-job', [PrintJobController::class, 'store'])->name('print-job.store'); + Route::post('/print-job', [PrintJobController::class, 'store'])->name('print-job.store'); Route::put('/print-job/{job}', [PrintJobController::class, 'update'])->name('print-job.update'); Route::get('/free-pages', [FreePagesController::class, 'index'])->name('free-pages.index'); diff --git a/tests/Feature/PrintControllerTest.php b/tests/Feature/PrintControllerTest.php index f6077b450..6b9b8fe44 100644 --- a/tests/Feature/PrintControllerTest.php +++ b/tests/Feature/PrintControllerTest.php @@ -30,16 +30,16 @@ public function testUserWithoutPermissions() $response->assertStatus(403); $response = $this->get('/print/admin'); $response->assertStatus(403); - $response = $this->get('/print-account-history'); - $response->assertStatus(200); + $response = $this->get('/print/print-account-history'); + $response->assertStatus(403); - $response = $this->post('/print-account-update', []); + $response = $this->put('/print-account-update', []); $response->assertStatus(302); // TODO: #514 // $response = $this->post('/print/print_jobs/0/cancel', []); // $response->assertStatus(403); - $response = $this->put('/print/print', []); + $response = $this->post('/print/print-job', []); $response->assertStatus(302); } @@ -64,16 +64,16 @@ public function testUserWithPrinterPermissions() $response->assertStatus(403); $response = $this->get('/print/admin'); $response->assertStatus(403); - $response = $this->get('/print-account-history'); - $response->assertStatus(200); + $response = $this->get('/print/print-account-history'); + $response->assertStatus(403); - $response = $this->post('/print-account-update', []); + $response = $this->put('/print-account-update', []); $response->assertStatus(302); // TODO: #514 // $response = $this->post('/print/print_jobs/0/cancel', []); // $response->assertStatus(403); - $response = $this->put('/print/print', []); + $response = $this->post('/print/print-job', []); $response->assertStatus(302); } @@ -99,16 +99,16 @@ public function testUserWithPrintAdminPermissions() $response->assertStatus(200); $response = $this->get('/print/admin'); $response->assertStatus(200); - $response = $this->get('/print-account-history'); + $response = $this->get('/print/print-account-history'); $response->assertStatus(200); - $response = $this->post('/print-account-update', []); + $response = $this->put('/print-account-update', []); $response->assertStatus(302); // TODO: #514 // $response = $this->post('/print/print_jobs/0/cancel', []); // $response->assertStatus(403); - $response = $this->put('/print/print', []); + $response = $this->post('/print/print-job', []); $response->assertStatus(302); } @@ -120,40 +120,40 @@ public function testBalanceTransfer() $sender->setVerified(); $this->actingAs($sender); - $reciever = User::factory()->create(); - $reciever->setVerified(); + $receiver = User::factory()->create(); + $receiver->setVerified(); // Setting initial valeus $this->assertEquals($sender->printAccount->balance, 0); $sender->printAccount->update(['last_modified_by' => $sender->id]); $sender->printAccount->increment('balance', 43); $this->assertEquals($sender->printAccount->balance, 43); - $this->assertEquals($reciever->printAccount->balance, 0); + $this->assertEquals($receiver->printAccount->balance, 0); // Simple transfer test - $response = $this->transfer($reciever, 10); - $this->assertCorrectTransfer($response, $sender, $reciever, 33, 10); + $response = $this->transfer($receiver, 10); + $this->assertCorrectTransfer($response, $sender, $receiver, 33, 10); // Transferring values over balance - $response = $this->transfer($reciever, 123); - $response = $this->transfer($reciever, 34); - $this->assertCorrectTransfer($response, $sender, $reciever, 33, 10); + $response = $this->transfer($receiver, 123); + $response = $this->transfer($receiver, 34); + $this->assertCorrectTransfer($response, $sender, $receiver, 33, 10); // Transferring nothing - $response = $this->transfer($reciever, 0); - $this->assertCorrectTransfer($response, $sender, $reciever, 33, 10); + $response = $this->transfer($receiver, 0); + $this->assertCorrectTransfer($response, $sender, $receiver, 33, 10); // Transferring negative values - $response = $this->transfer($reciever, -5); - $this->assertCorrectTransfer($response, $sender, $reciever, 33, 10); + $response = $this->transfer($receiver, -5); + $response->assertStatus(400); // Transferring all balance - $response = $this->transfer($reciever, 33); - $this->assertCorrectTransfer($response, $sender, $reciever, 0, 43); + $response = $this->transfer($receiver, 33); + $this->assertCorrectTransfer($response, $sender, $receiver, 0, 43); // Transferring with empty balance - $response = $this->transfer($reciever, 1); - $this->assertCorrectTransfer($response, $sender, $reciever, 0, 43); + $response = $this->transfer($receiver, 1); + $this->assertCorrectTransfer($response, $sender, $receiver, 0, 43); } public function testModifyBalance() @@ -165,76 +165,79 @@ public function testModifyBalance() $sender->roles()->attach(Role::firstWhere('name', Role::SYS_ADMIN)->id); $this->actingAs($sender); - $reciever = User::factory()->create(); - $reciever->setVerified(); + $receiver = User::factory()->create(); + $receiver->setVerified(); // Asserting initial valeus $this->assertEquals($sender->printAccount->balance, 0); - $this->assertEquals($reciever->printAccount->balance, 0); + $this->assertEquals($receiver->printAccount->balance, 0); - $response = $this->modify($reciever, 10); - $this->assertCorrectModification($response, $reciever, 10); + $response = $this->modify($receiver, 10); + $this->assertCorrectModification($response, $receiver, 10); - $response = $this->modify($reciever, 123); - $this->assertCorrectModification($response, $reciever, 133); + $response = $this->modify($receiver, 123); + $this->assertCorrectModification($response, $receiver, 133); - $response = $this->modify($reciever, -23); - $this->assertCorrectModification($response, $reciever, 110); + $response = $this->modify($receiver, -23); + $this->assertCorrectModification($response, $receiver, 110); - $response = $this->modify($reciever, 1); - $this->assertCorrectModification($response, $reciever, 111); + $response = $this->modify($receiver, 1); + $this->assertCorrectModification($response, $receiver, 111); - $response = $this->modify($reciever, 0); - $this->assertCorrectModification($response, $reciever, 111); + $response = $this->modify($receiver, 0); + $this->assertCorrectModification($response, $receiver, 111); - $response = $this->modify($reciever, -112); - $this->assertCorrectModification($response, $reciever, 111); + $response = $this->modify($receiver, -112); + $this->assertCorrectModification($response, $receiver, 111); - $response = $this->modify($reciever, -111); - $this->assertCorrectModification($response, $reciever, 0); + $response = $this->modify($receiver, -111); + $this->assertCorrectModification($response, $receiver, 0); - $response = $this->modify($reciever, -1); - $this->assertCorrectModification($response, $reciever, 0); + $response = $this->modify($receiver, -1); + $this->assertCorrectModification($response, $receiver, 0); - $response = $this->modify($reciever, 0); - $this->assertCorrectModification($response, $reciever, 0); + $response = $this->modify($receiver, 0); + $this->assertCorrectModification($response, $receiver, 0); - $response = $this->modify($reciever, 12); - $this->assertCorrectModification($response, $reciever, 12); + $response = $this->modify($receiver, 12); + $this->assertCorrectModification($response, $receiver, 12); //Sender is not affected $this->assertEquals($sender->printAccount->balance, 0); } // Helpers - private function transfer($reciever, $balance) + private function transfer($receiver, $balance) { - $response = $this->post('/print/transfer_balance', [ - 'user_to_send' => $reciever->id, - 'balance' => $balance, + $response = $this->put('/print-account-update', [ + 'user' => user()->id, + 'other_user' => $receiver->id, + 'amount' => $balance, ]); + return $response; } - private function assertCorrectTransfer($response, $sender, $reciever, $senderBalance, $receiverBalance) + private function assertCorrectTransfer($response, $sender, $receiver, $senderBalance, $receiverBalance) { $response->assertStatus(302); - $reciever = User::find($reciever->id); // We have to reload the reciever here. - $this->assertEquals($sender->printAccount->balance, $senderBalance); - $this->assertEquals($reciever->printAccount->balance, $receiverBalance); + $sender = User::find($sender->id); // We have to reload the sender here. + $receiver = User::find($receiver->id); // We have to reload the receiver here. + $this->assertEquals($senderBalance, $sender->printAccount->balance); + $this->assertEquals($receiverBalance, $receiver->printAccount->balance); } - private function modify($reciever, $balance) + private function modify($receiver, $balance) { - $response = $this->post('/print/modify_balance', [ - 'user_id_modify' => $reciever->id, - 'balance' => $balance, + $response = $this->put('/print-account-update', [ + 'user' => $receiver->id, + 'amount' => $balance, ]); return $response; } - private function assertCorrectModification($response, $reciever, $receiverBalance) + private function assertCorrectModification($response, $receiver, $receiverBalance) { $response->assertStatus(302); - $reciever = User::find($reciever->id); // We have to reload the reciever here. - $this->assertEquals($reciever->printAccount->balance, $receiverBalance); + $receiver = User::find($receiver->id); // We have to reload the receiver here. + $this->assertEquals($receiverBalance, $receiver->printAccount->balance); } } diff --git a/tests/Unit/PrintTest.php b/tests/Unit/PrintTest.php index 0923b530f..d99cd25c8 100644 --- a/tests/Unit/PrintTest.php +++ b/tests/Unit/PrintTest.php @@ -23,16 +23,16 @@ public function testPrintAccount() $this->assertEquals($user->printAccount, PrintAccount::find($user->id)); $this->assertEquals($user->printAccount->balance, 0); - $this->assertFalse($user->printAccount->hasEnoughMoney(1)); - $this->assertTrue($user->printAccount->hasEnoughMoney(0)); + //$this->assertFalse($user->printAccount->hasEnoughMoney(1)); + //$this->assertTrue($user->printAccount->hasEnoughMoney(0)); $user->printAccount->update(['last_modified_by' => $user->id]); $user->printAccount->increment('balance', 43); - $this->assertTrue($user->printAccount->hasEnoughMoney(43)); - $this->assertTrue($user->printAccount->hasEnoughMoney(15)); - $this->assertFalse($user->printAccount->hasEnoughMoney(44)); - $this->assertFalse($user->printAccount->hasEnoughMoney(112)); - $this->assertTrue($user->printAccount->hasEnoughMoney(-43)); - $this->assertFalse($user->printAccount->hasEnoughMoney(-44)); + //$this->assertTrue($user->printAccount->hasEnoughMoney(43)); + //$this->assertTrue($user->printAccount->hasEnoughMoney(15)); + //$this->assertFalse($user->printAccount->hasEnoughMoney(44)); + //$this->assertFalse($user->printAccount->hasEnoughMoney(112)); + //$this->assertTrue($user->printAccount->hasEnoughMoney(-43)); + //$this->assertFalse($user->printAccount->hasEnoughMoney(-44)); } } From e83748bc3ec4d5c6d3cf4ac85d060da903f4650e Mon Sep 17 00:00:00 2001 From: Balint Horcsin Date: Sun, 29 Dec 2024 23:17:55 +0100 Subject: [PATCH 55/55] Fix commands as the order of parameters matter --- app/Models/Printer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/Printer.php b/app/Models/Printer.php index f10e4a072..34a403394 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -85,8 +85,8 @@ public function print(bool $twoSided, int $copies, string $path) try { $process = new Process([ 'lp', - '-d', $this->name, '-h', "$this->ip:$this->port", + '-d', $this->name, ($twoSided ? '-o sides=two-sided-long-edge' : ''), '-n', $copies, $path @@ -120,7 +120,7 @@ public function print(bool $twoSided, int $copies, string $path) public function getCompletedPrintJobs() { try { - $process = Process::fromShellCommandline(config('commands.lpstat') . " -W completed -o $this->name -h $this->ip:$this->port | awk '{print $1}'"); + $process = Process::fromShellCommandline(config('commands.lpstat') . " -h $this->ip:$this->port -W completed -o $this->name | awk '{print $1}'"); $process->run(); $result = explode("\n", $process->getOutput()); return $result;