#116 - cr fix
This commit is contained in:
		| @@ -57,6 +57,6 @@ class CalendarGenerator | ||||
|             ->approved() | ||||
|             ->with("vacationRequest") | ||||
|             ->get() | ||||
|             ->groupBy(fn(Vacation $vacation) => $vacation->date->toDateString()); | ||||
|             ->groupBy(fn(Vacation $vacation): string => $vacation->date->toDateString()); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -22,7 +22,9 @@ class DailySummaryRetriever | ||||
|             ->with(["user", "vacationRequest"]) | ||||
|             ->whereDate("date", $date) | ||||
|             ->approved() | ||||
|             ->whereTypes(VacationType::all()->filter(fn(VacationType $type): bool => $this->configRetriever->isVacation($type))) | ||||
|             ->whereTypes( | ||||
|                 VacationType::all()->filter(fn(VacationType $type): bool => $this->configRetriever->isVacation($type)), | ||||
|             ) | ||||
|             ->get(); | ||||
|     } | ||||
|  | ||||
| @@ -32,7 +34,9 @@ class DailySummaryRetriever | ||||
|             ->with(["user", "vacationRequest"]) | ||||
|             ->whereDate("date", $date) | ||||
|             ->approved() | ||||
|             ->whereTypes(VacationType::all()->filter(fn(VacationType $type): bool => !$this->configRetriever->isVacation($type))) | ||||
|             ->whereTypes( | ||||
|                 VacationType::all()->filter(fn(VacationType $type): bool => !$this->configRetriever->isVacation($type)), | ||||
|             ) | ||||
|             ->get(); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,7 @@ enum EmploymentForm: string | ||||
|         $cases = collect(EmploymentForm::cases()); | ||||
|  | ||||
|         return $cases->map( | ||||
|             fn(EmploymentForm $enum) => [ | ||||
|             fn(EmploymentForm $enum): array => [ | ||||
|                 "label" => $enum->label(), | ||||
|                 "value" => $enum->value, | ||||
|             ], | ||||
|   | ||||
| @@ -21,7 +21,7 @@ enum Role: string | ||||
|         $cases = collect(Role::cases()); | ||||
|  | ||||
|         return $cases->map( | ||||
|             fn(Role $enum) => [ | ||||
|             fn(Role $enum): array => [ | ||||
|                 "label" => $enum->label(), | ||||
|                 "value" => $enum->value, | ||||
|             ], | ||||
|   | ||||
| @@ -30,7 +30,7 @@ enum VacationType: string | ||||
|         $cases = VacationType::all(); | ||||
|  | ||||
|         return $cases->map( | ||||
|             fn(VacationType $enum) => [ | ||||
|             fn(VacationType $enum): array => [ | ||||
|                 "label" => $enum->label(), | ||||
|                 "value" => $enum->value, | ||||
|             ], | ||||
|   | ||||
							
								
								
									
										11
									
								
								app/Domain/Notifications/Channels.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/Domain/Notifications/Channels.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Notifications; | ||||
|  | ||||
| class Channels | ||||
| { | ||||
|     public const MAIL = "mail"; | ||||
|     public const SLACK = "slack"; | ||||
| } | ||||
| @@ -19,10 +19,10 @@ class KeyHasBeenGivenNotification extends Notification | ||||
|  | ||||
|     public function via(): array | ||||
|     { | ||||
|         return ["slack"]; | ||||
|         return [Channels::SLACK]; | ||||
|     } | ||||
|  | ||||
|     public function toSlack($notifiable): string | ||||
|     public function toSlack(Notifiable $notifiable): string | ||||
|     { | ||||
|         return __(":sender gives key no :key to :recipient", [ | ||||
|             "sender" => $this->getName($this->sender), | ||||
|   | ||||
| @@ -19,10 +19,10 @@ class KeyHasBeenTakenNotification extends Notification | ||||
|  | ||||
|     public function via(): array | ||||
|     { | ||||
|         return ["slack"]; | ||||
|         return [Channels::SLACK]; | ||||
|     } | ||||
|  | ||||
|     public function toSlack($notifiable): string | ||||
|     public function toSlack(Notifiable $notifiable): string | ||||
|     { | ||||
|         return __(":recipient takes key no :key from :sender", [ | ||||
|             "recipient" => $this->getName($this->recipient), | ||||
|   | ||||
							
								
								
									
										10
									
								
								app/Domain/Notifications/Notifiable.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								app/Domain/Notifications/Notifiable.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Notifications; | ||||
|  | ||||
| interface Notifiable | ||||
| { | ||||
|     public function notify($instance); | ||||
| } | ||||
| @@ -20,7 +20,7 @@ class VacationRequestCreatedNotification extends Notification | ||||
|  | ||||
|     public function via(): array | ||||
|     { | ||||
|         return ["mail", "slack"]; | ||||
|         return [Channels::MAIL, Channels::SLACK]; | ||||
|     } | ||||
|  | ||||
|     public function toSlack(): string | ||||
|   | ||||
| @@ -22,7 +22,7 @@ class VacationRequestStatusChangedNotification extends Notification | ||||
|  | ||||
|     public function via(): array | ||||
|     { | ||||
|         return ["mail", "slack"]; | ||||
|         return [Channels::MAIL, Channels::SLACK]; | ||||
|     } | ||||
|  | ||||
|     public function toSlack(): string | ||||
|   | ||||
| @@ -23,7 +23,7 @@ class VacationRequestWaitsForApprovalNotification extends Notification | ||||
|  | ||||
|     public function via(): array | ||||
|     { | ||||
|         return ["mail", "slack"]; | ||||
|         return [Channels::MAIL, Channels::SLACK]; | ||||
|     } | ||||
|  | ||||
|     public function toSlack(): string | ||||
|   | ||||
| @@ -26,7 +26,7 @@ class PolishHolidaysRetriever | ||||
|  | ||||
|     protected function prepareHolidays(array $holidays): Collection | ||||
|     { | ||||
|         return collect($holidays)->map(fn(Holiday $holiday) => [ | ||||
|         return collect($holidays)->map(fn(Holiday $holiday): array => [ | ||||
|             "name" => $holiday->getName([static::LANG_KEY]), | ||||
|             "date" => Carbon::createFromTimestamp($holiday->getTimestamp()), | ||||
|         ])->values(); | ||||
|   | ||||
| @@ -1,25 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Channels; | ||||
|  | ||||
| use Illuminate\Http\Client\Response; | ||||
| use Illuminate\Notifications\Notification; | ||||
| use Illuminate\Support\Facades\Http; | ||||
|  | ||||
| class SlackApiChannel | ||||
| { | ||||
|     public function send($notifiable, Notification $notification): Response | ||||
|     { | ||||
|         $baseUrl = config("services.slack.url"); | ||||
|         $url = "{$baseUrl}/chat.postMessage"; | ||||
|         $channel = $notifiable->routeNotificationFor("slack", $notification); | ||||
|  | ||||
|         return Http::withToken(config("services.slack.client_token")) | ||||
|             ->post($url, [ | ||||
|                 "channel" => $channel, | ||||
|                 "text" => $notification->toSlack($notifiable), | ||||
|             ]); | ||||
|     } | ||||
| } | ||||
| @@ -1,55 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack; | ||||
|  | ||||
| use Exception; | ||||
| use Illuminate\Http\Request as IlluminateRequest; | ||||
| use Illuminate\Http\Response as IlluminateResponse; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Validation\ValidationException; | ||||
| use Spatie\SlashCommand\Attachment; | ||||
| use Spatie\SlashCommand\Controller as SlackController; | ||||
| use Spatie\SlashCommand\Exceptions\RequestCouldNotBeHandled; | ||||
| use Spatie\SlashCommand\Exceptions\SlackSlashCommandException; | ||||
| use Spatie\SlashCommand\Response; | ||||
|  | ||||
| class Controller extends SlackController | ||||
| { | ||||
|     /** | ||||
|      * @throws RequestCouldNotBeHandled | ||||
|      */ | ||||
|     public function getResponse(IlluminateRequest $request): IlluminateResponse | ||||
|     { | ||||
|         $this->guardAgainstInvalidRequest($request); | ||||
|  | ||||
|         $handler = $this->determineHandler(); | ||||
|  | ||||
|         try { | ||||
|             $response = $handler->handle($this->request); | ||||
|         } catch (SlackSlashCommandException $exception) { | ||||
|             $response = $exception->getResponse($this->request); | ||||
|         } catch (ValidationException $exception) { | ||||
|             $response = $this->prepareValidationResponse($exception); | ||||
|         } catch (Exception $exception) { | ||||
|             $response = $this->convertToResponse($exception); | ||||
|         } | ||||
|  | ||||
|         return $response->getIlluminateResponse(); | ||||
|     } | ||||
|  | ||||
|     protected function prepareValidationResponse(ValidationException $exception): Response | ||||
|     { | ||||
|         $errors = (new Collection($exception->errors())) | ||||
|             ->map( | ||||
|                 fn(array $message) => Attachment::create() | ||||
|                     ->setColor("danger") | ||||
|                     ->setText($message[0]), | ||||
|             ); | ||||
|  | ||||
|         return Response::create($this->request) | ||||
|             ->withText(":x: Komenda `/{$this->request->command} {$this->request->text}` jest niepoprawna:") | ||||
|             ->withAttachments($errors->all()); | ||||
|     } | ||||
| } | ||||
| @@ -1,11 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Exceptions; | ||||
|  | ||||
| use Spatie\SlashCommand\Exceptions\SlackSlashCommandException; | ||||
|  | ||||
| class UserNotFoundException extends SlackSlashCommandException | ||||
| { | ||||
| } | ||||
| @@ -1,35 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Spatie\SlashCommand\Attachment; | ||||
| use Spatie\SlashCommand\Handlers\BaseHandler; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Toby\Domain\Slack\Traits\ListsHandlers; | ||||
|  | ||||
| class CatchAll extends BaseHandler | ||||
| { | ||||
|     use ListsHandlers; | ||||
|  | ||||
|     public function canHandle(Request $request): bool | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $handlers = $this->findAvailableHandlers(); | ||||
|         $attachmentFields = $this->mapHandlersToAttachments($handlers); | ||||
|  | ||||
|         return $this->respondToSlack(":x: Nie rozpoznaję tej komendy. Lista wszystkich komend:") | ||||
|             ->withAttachment( | ||||
|                 Attachment::create() | ||||
|                     ->setColor("danger") | ||||
|                     ->useMarkdown() | ||||
|                     ->setFields($attachmentFields), | ||||
|             ); | ||||
|     } | ||||
| } | ||||
| @@ -1,55 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Illuminate\Support\Carbon; | ||||
| use Spatie\SlashCommand\Attachment; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Toby\Domain\DailySummaryRetriever; | ||||
| use Toby\Eloquent\Models\User; | ||||
| use Toby\Eloquent\Models\Vacation; | ||||
|  | ||||
| class DailySummary extends SignatureHandler | ||||
| { | ||||
|     protected $signature = "toby dzisiaj"; | ||||
|     protected $description = "Codzienne podsumowanie"; | ||||
|  | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $dailySummaryRetriever = app()->make(DailySummaryRetriever::class); | ||||
|  | ||||
|         $now = Carbon::today(); | ||||
|  | ||||
|         $absences = $dailySummaryRetriever->getAbsences($now) | ||||
|             ->map(fn(Vacation $vacation): string => $vacation->user->profile->full_name); | ||||
|  | ||||
|         $remoteDays = $dailySummaryRetriever->getRemoteDays($now) | ||||
|             ->map(fn(Vacation $vacation): string => $vacation->user->profile->full_name); | ||||
|  | ||||
|         $birthdays = $dailySummaryRetriever->getBirthdays($now) | ||||
|             ->map(fn(User $user): string => $user->profile->full_name); | ||||
|  | ||||
|         $absencesAttachment = Attachment::create() | ||||
|             ->setTitle("Nieobecności :sunny:") | ||||
|             ->setColor("#eab308") | ||||
|             ->setText($absences->isNotEmpty() ? $absences->implode("\n") : "Wszyscy dzisiaj pracują :muscle:"); | ||||
|  | ||||
|         $remoteAttachment = Attachment::create() | ||||
|             ->setTitle("Praca zdalna :house_with_garden:") | ||||
|             ->setColor("#527aba") | ||||
|             ->setText($remoteDays->isNotEmpty() ? $remoteDays->implode("\n") : "Wszyscy dzisiaj są w biurze :boom:"); | ||||
|  | ||||
|         $birthdayAttachment = Attachment::create() | ||||
|             ->setTitle("Urodziny :birthday:") | ||||
|             ->setColor("#3c5f97") | ||||
|             ->setText($birthdays->isNotEmpty() ? $birthdays->implode("\n") : "Dzisiaj nikt nie ma urodzin :cry:"); | ||||
|  | ||||
|         return $this->respondToSlack("Podsumowanie dla dnia {$now->toDisplayString()}") | ||||
|             ->withAttachment($absencesAttachment) | ||||
|             ->withAttachment($remoteAttachment) | ||||
|             ->withAttachment($birthdayAttachment); | ||||
|     } | ||||
| } | ||||
| @@ -1,71 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Illuminate\Validation\ValidationException; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Toby\Domain\Notifications\KeyHasBeenGivenNotification; | ||||
| use Toby\Domain\Slack\Exceptions\UserNotFoundException; | ||||
| use Toby\Domain\Slack\Rules\SlackUserExistsRule; | ||||
| use Toby\Domain\Slack\Traits\FindsUserBySlackId; | ||||
| use Toby\Eloquent\Models\Key; | ||||
|  | ||||
| class GiveKeysTo extends SignatureHandler | ||||
| { | ||||
|     use FindsUserBySlackId; | ||||
|  | ||||
|     protected $signature = "toby klucze:dla {user}"; | ||||
|     protected $description = "Przekaż klucze wskazanemu użytkownikowi"; | ||||
|  | ||||
|     /** | ||||
|      * @throws UserNotFoundException | ||||
|      * @throws ValidationException | ||||
|      */ | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         ["user" => $from] = $this->validate(); | ||||
|  | ||||
|         $authUser = $this->findUserBySlackIdOrFail($request->userId); | ||||
|         $user = $this->findUserBySlackId($from); | ||||
|  | ||||
|         /** @var Key $key */ | ||||
|         $key = $authUser->keys()->first(); | ||||
|  | ||||
|         if (!$key) { | ||||
|             throw ValidationException::withMessages(["key" => "Nie masz żadnego klucza do przekazania"]); | ||||
|         } | ||||
|  | ||||
|         if ($user->is($authUser)) { | ||||
|             throw ValidationException::withMessages([ | ||||
|                 "key" => "Nie możesz przekazać sobie kluczy :dzban:", | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $key->user()->associate($user); | ||||
|  | ||||
|         $key->save(); | ||||
|  | ||||
|         $key->notify(new KeyHasBeenGivenNotification($authUser, $user)); | ||||
|  | ||||
|         return $this->respondToSlack( | ||||
|             ":white_check_mark: Klucz nr {$key->id} został przekazany użytkownikowi <@{$user->profile->slack_id}>", | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     protected function getRules(): array | ||||
|     { | ||||
|         return [ | ||||
|             "user" => ["required", new SlackUserExistsRule()], | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     protected function getMessages(): array | ||||
|     { | ||||
|         return [ | ||||
|             "user.required" => "Musisz podać użytkownika, któremu chcesz przekazać klucze", | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,33 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Spatie\SlashCommand\Attachment; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Toby\Domain\Slack\Traits\ListsHandlers; | ||||
|  | ||||
| class Help extends SignatureHandler | ||||
| { | ||||
|     use ListsHandlers; | ||||
|  | ||||
|     protected $signature = "toby pomoc"; | ||||
|     protected $description = "Wyświetl wszystkie dostępne komendy"; | ||||
|  | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $handlers = $this->findAvailableHandlers(); | ||||
|  | ||||
|         $attachmentFields = $this->mapHandlersToAttachments($handlers); | ||||
|  | ||||
|         return $this->respondToSlack("Dostępne komendy:") | ||||
|             ->withAttachment( | ||||
|                 Attachment::create() | ||||
|                     ->setColor("good") | ||||
|                     ->useMarkdown() | ||||
|                     ->setFields($attachmentFields), | ||||
|             ); | ||||
|     } | ||||
| } | ||||
| @@ -1,45 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Illuminate\Support\Carbon; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Toby\Domain\Actions\VacationRequest\CreateAction; | ||||
| use Toby\Domain\Enums\VacationType; | ||||
| use Toby\Domain\Slack\Traits\FindsUserBySlackId; | ||||
| use Toby\Eloquent\Models\User; | ||||
| use Toby\Eloquent\Models\YearPeriod; | ||||
|  | ||||
| class HomeOffice extends SignatureHandler | ||||
| { | ||||
|     use FindsUserBySlackId; | ||||
|  | ||||
|     protected $signature = "toby zdalnie"; | ||||
|     protected $description = "Pracuj dzisiaj zdalnie"; | ||||
|  | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $user = $this->findUserBySlackId($request->userId); | ||||
|  | ||||
|         $this->createRemoteday($user, Carbon::today()); | ||||
|  | ||||
|         return $this->respondToSlack(":white_check_mark: Pracujesz dzisiaj zdalnie"); | ||||
|     } | ||||
|  | ||||
|     protected function createRemoteday(User $user, Carbon $date): void | ||||
|     { | ||||
|         $yearPeriod = YearPeriod::findByYear($date->year); | ||||
|  | ||||
|         app(CreateAction::class)->execute([ | ||||
|             "user_id" => $user->id, | ||||
|             "type" => VacationType::HomeOffice, | ||||
|             "from" => $date, | ||||
|             "to" => $date, | ||||
|             "year_period_id" => $yearPeriod->id, | ||||
|             "flow_skipped" => false, | ||||
|         ], $user); | ||||
|     } | ||||
| } | ||||
| @@ -1,31 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Spatie\SlashCommand\Attachment; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Toby\Eloquent\Models\Key; | ||||
|  | ||||
| class KeyList extends SignatureHandler | ||||
| { | ||||
|     protected $signature = "toby klucze"; | ||||
|     protected $description = "Lista wszystkich kluczy"; | ||||
|  | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $keys = Key::query() | ||||
|             ->orderBy("id") | ||||
|             ->get() | ||||
|             ->map(fn(Key $key) => "Klucz nr {$key->id} - <@{$key->user->profile->slack_id}>"); | ||||
|  | ||||
|         return $this->respondToSlack("Lista kluczy :key:") | ||||
|             ->withAttachment( | ||||
|                 Attachment::create() | ||||
|                     ->setColor("#3c5f97") | ||||
|                     ->setText($keys->isNotEmpty() ? $keys->implode("\n") : "Nie ma żadnych kluczy w tobym"), | ||||
|             ); | ||||
|     } | ||||
| } | ||||
| @@ -1,26 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Illuminate\Support\Facades\Validator; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler as BaseSignatureHandler; | ||||
|  | ||||
| abstract class SignatureHandler extends BaseSignatureHandler | ||||
| { | ||||
|     public function validate() | ||||
|     { | ||||
|         return Validator::validate($this->getArguments(), $this->getRules(), $this->getMessages()); | ||||
|     } | ||||
|  | ||||
|     protected function getRules(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     protected function getMessages(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
| } | ||||
| @@ -1,70 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Illuminate\Validation\ValidationException; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Toby\Domain\Notifications\KeyHasBeenTakenNotification; | ||||
| use Toby\Domain\Slack\Exceptions\UserNotFoundException; | ||||
| use Toby\Domain\Slack\Rules\SlackUserExistsRule; | ||||
| use Toby\Domain\Slack\Traits\FindsUserBySlackId; | ||||
| use Toby\Eloquent\Models\Key; | ||||
|  | ||||
| class TakeKeysFrom extends SignatureHandler | ||||
| { | ||||
|     use FindsUserBySlackId; | ||||
|  | ||||
|     protected $signature = "toby klucze:od {user}"; | ||||
|     protected $description = "Zabierz klucze wskazanemu użytkownikowi"; | ||||
|  | ||||
|     /** | ||||
|      * @throws UserNotFoundException|ValidationException | ||||
|      */ | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         ["user" => $from] = $this->validate(); | ||||
|  | ||||
|         $authUser = $this->findUserBySlackIdOrFail($request->userId); | ||||
|         $user = $this->findUserBySlackId($from); | ||||
|  | ||||
|         /** @var Key $key */ | ||||
|         $key = $user->keys()->first(); | ||||
|  | ||||
|         if (!$key) { | ||||
|             throw ValidationException::withMessages([ | ||||
|                 "key" => "Użytkownik <@{$user->profile->slack_id}> nie ma żadnych kluczy", | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         if ($key->user()->is($authUser)) { | ||||
|             throw ValidationException::withMessages([ | ||||
|                 "key" => "Nie możesz zabrać sobie kluczy :dzban:", | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $key->user()->associate($authUser); | ||||
|  | ||||
|         $key->save(); | ||||
|  | ||||
|         $key->notify(new KeyHasBeenTakenNotification($authUser, $user)); | ||||
|  | ||||
|         return $this->respondToSlack(":white_check_mark: Klucz nr {$key->id} został zabrany użytkownikowi <@{$user->profile->slack_id}>"); | ||||
|     } | ||||
|  | ||||
|     protected function getRules(): array | ||||
|     { | ||||
|         return [ | ||||
|             "user" => ["required", new SlackUserExistsRule()], | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     protected function getMessages(): array | ||||
|     { | ||||
|         return [ | ||||
|             "user.required" => "Musisz podać użytkownika, któremu chcesz zabrać klucze", | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,24 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Rules; | ||||
|  | ||||
| use Illuminate\Contracts\Validation\Rule; | ||||
| use Illuminate\Support\Str; | ||||
| use Toby\Eloquent\Models\Profile; | ||||
|  | ||||
| class SlackUserExistsRule implements Rule | ||||
| { | ||||
|     public function passes($attribute, $value): bool | ||||
|     { | ||||
|         $slackId = Str::between($value, "<@", "|"); | ||||
|  | ||||
|         return Profile::query()->where("slack_id", $slackId)->exists(); | ||||
|     } | ||||
|  | ||||
|     public function message(): string | ||||
|     { | ||||
|         return "Użytkownik :input nie istnieje w tobym"; | ||||
|     } | ||||
| } | ||||
| @@ -1,43 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Traits; | ||||
|  | ||||
| use Illuminate\Support\Str; | ||||
| use Toby\Domain\Slack\Exceptions\UserNotFoundException; | ||||
| use Toby\Eloquent\Models\User; | ||||
|  | ||||
| trait FindsUserBySlackId | ||||
| { | ||||
|     protected function findUserBySlackId(string $slackId): ?User | ||||
|     { | ||||
|         $id = $this->prepareSlackIdFromString($slackId); | ||||
|  | ||||
|         /** @var User $user */ | ||||
|         $user = User::query() | ||||
|             ->whereRelation("profile", "slack_id", $id) | ||||
|             ->first(); | ||||
|  | ||||
|         return $user; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @throws UserNotFoundException | ||||
|      */ | ||||
|     protected function findUserBySlackIdOrFail(string $slackId): ?User | ||||
|     { | ||||
|         $user = $this->findUserBySlackId($slackId); | ||||
|  | ||||
|         if (!$user) { | ||||
|             throw new UserNotFoundException("Użytkownik {$slackId} nie istnieje w tobym"); | ||||
|         } | ||||
|  | ||||
|         return $user; | ||||
|     } | ||||
|  | ||||
|     protected function prepareSlackIdFromString(string $slackId): string | ||||
|     { | ||||
|         return Str::between($slackId, "<@", "|"); | ||||
|     } | ||||
| } | ||||
| @@ -1,45 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Traits; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\Str; | ||||
| use Spatie\SlashCommand\AttachmentField; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler; | ||||
| use Spatie\SlashCommand\Handlers\SignatureParts; | ||||
| use Spatie\SlashCommand\HandlesSlashCommand; | ||||
|  | ||||
| trait ListsHandlers | ||||
| { | ||||
|     protected function findAvailableHandlers(): Collection | ||||
|     { | ||||
|         return collect(config("laravel-slack-slash-command.handlers")) | ||||
|             ->map(fn(string $handlerClassName) => new $handlerClassName($this->request)) | ||||
|             ->filter(fn(HandlesSlashCommand $handler) => $handler instanceof SignatureHandler) | ||||
|             ->filter(function (SignatureHandler $handler) { | ||||
|                 $signatureParts = new SignatureParts($handler->getSignature()); | ||||
|  | ||||
|                 return Str::is($signatureParts->getSlashCommandName(), $this->request->command); | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     protected function mapHandlersToAttachments(Collection $handlers): array | ||||
|     { | ||||
|         return $handlers | ||||
|             ->sort( | ||||
|                 fn(SignatureHandler $handlerA, SignatureHandler $handlerB) => strcmp( | ||||
|                     $handlerA->getFullCommand(), | ||||
|                     $handlerB->getFullCommand(), | ||||
|                 ), | ||||
|             ) | ||||
|             ->map( | ||||
|                 fn(SignatureHandler $handler) => AttachmentField::create( | ||||
|                     $handler->getDescription(), | ||||
|                     "`/{$handler->getSignature()}`", | ||||
|                 ), | ||||
|             ) | ||||
|             ->all(); | ||||
|     } | ||||
| } | ||||
| @@ -18,7 +18,7 @@ class TimesheetExport implements WithMultipleSheets | ||||
|     public function sheets(): array | ||||
|     { | ||||
|         return $this->users | ||||
|             ->map(fn(User $user) => new TimesheetPerUserSheet($user, $this->month, $this->types)) | ||||
|             ->map(fn(User $user): TimesheetPerUserSheet => new TimesheetPerUserSheet($user, $this->month, $this->types)) | ||||
|             ->toArray(); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -193,8 +193,8 @@ class TimesheetPerUserSheet implements WithTitle, WithHeadings, WithEvents, With | ||||
|             ->get() | ||||
|             ->groupBy( | ||||
|                 [ | ||||
|                     fn(Vacation $vacation) => $vacation->date->toDateString(), | ||||
|                     fn(Vacation $vacation) => $vacation->vacationRequest->type->value, | ||||
|                     fn(Vacation $vacation): string => $vacation->date->toDateString(), | ||||
|                     fn(Vacation $vacation): string => $vacation->vacationRequest->type->value, | ||||
|                 ], | ||||
|             ); | ||||
|     } | ||||
|   | ||||
| @@ -42,8 +42,8 @@ class UserVacationStatsRetriever | ||||
|                     ->states(VacationRequestStatesRetriever::successStates()), | ||||
|             ) | ||||
|             ->get() | ||||
|             ->groupBy(fn(Vacation $vacation) => strtolower($vacation->date->englishMonth)) | ||||
|             ->map(fn(Collection $items) => $items->count()); | ||||
|             ->groupBy(fn(Vacation $vacation): string => strtolower($vacation->date->englishMonth)) | ||||
|             ->map(fn(Collection $items): int => $items->count()); | ||||
|     } | ||||
|  | ||||
|     public function getPendingVacationDays(User $user, YearPeriod $yearPeriod): int | ||||
| @@ -107,13 +107,13 @@ class UserVacationStatsRetriever | ||||
|     { | ||||
|         $types = VacationType::all(); | ||||
|  | ||||
|         return $types->filter(fn(VacationType $type) => $this->configRetriever->hasLimit($type)); | ||||
|         return $types->filter(fn(VacationType $type): bool => $this->configRetriever->hasLimit($type)); | ||||
|     } | ||||
|  | ||||
|     protected function getNotLimitableVacationTypes(): Collection | ||||
|     { | ||||
|         $types = VacationType::all(); | ||||
|  | ||||
|         return $types->filter(fn(VacationType $type) => !$this->configRetriever->hasLimit($type)); | ||||
|         return $types->filter(fn(VacationType $type): bool => !$this->configRetriever->hasLimit($type)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -64,6 +64,6 @@ class DoesNotExceedLimitRule implements VacationRequestRule | ||||
|     { | ||||
|         $types = VacationType::all(); | ||||
|  | ||||
|         return $types->filter(fn(VacationType $type) => $this->configRetriever->hasLimit($type)); | ||||
|         return $types->filter(fn(VacationType $type): bool => $this->configRetriever->hasLimit($type)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -19,7 +19,7 @@ class VacationTypeCanBeSelected implements VacationRequestRule | ||||
|         $employmentForm = $vacationRequest->user->profile->employment_form; | ||||
|  | ||||
|         $availableTypes = VacationType::all() | ||||
|             ->filter(fn(VacationType $type) => $this->configRetriever->isAvailableFor($type, $employmentForm)); | ||||
|             ->filter(fn(VacationType $type): bool => $this->configRetriever->isAvailableFor($type, $employmentForm)); | ||||
|  | ||||
|         return $availableTypes->contains($vacationRequest->type); | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user