Merge branch 'main' into #126-vacation-request-reminders
# Conflicts: # app/Domain/Actions/VacationRequest/CreateAction.php # app/Domain/Validation/Rules/DoesNotExceedLimitRule.php
This commit is contained in:
		@@ -0,0 +1,79 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Console\Commands;
 | 
			
		||||
 | 
			
		||||
use Carbon\CarbonInterface;
 | 
			
		||||
use Illuminate\Console\Command;
 | 
			
		||||
use Illuminate\Support\Carbon;
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
use Illuminate\Support\Facades\Http;
 | 
			
		||||
use Toby\Domain\DailySummaryRetriever;
 | 
			
		||||
use Toby\Eloquent\Models\Holiday;
 | 
			
		||||
use Toby\Infrastructure\Slack\Elements\AbsencesAttachment;
 | 
			
		||||
use Toby\Infrastructure\Slack\Elements\BirthdaysAttachment;
 | 
			
		||||
use Toby\Infrastructure\Slack\Elements\RemotesAttachment;
 | 
			
		||||
 | 
			
		||||
class SendDailySummaryToSlack extends Command
 | 
			
		||||
{
 | 
			
		||||
    protected $signature = "toby:slack:daily-summary {--f|force}";
 | 
			
		||||
    protected $description = "Sent daily summary to slack";
 | 
			
		||||
 | 
			
		||||
    public function handle(DailySummaryRetriever $dailySummaryRetriever): void
 | 
			
		||||
    {
 | 
			
		||||
        $now = Carbon::today();
 | 
			
		||||
 | 
			
		||||
        if (!$this->option("force") && !$this->shouldHandle($now)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $attachments = new Collection([
 | 
			
		||||
            new AbsencesAttachment($dailySummaryRetriever->getAbsences($now)),
 | 
			
		||||
            new RemotesAttachment($dailySummaryRetriever->getRemoteDays($now)),
 | 
			
		||||
            new BirthdaysAttachment($dailySummaryRetriever->getBirthdays($now)),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        Http::withToken($this->getSlackClientToken())
 | 
			
		||||
            ->post($this->getUrl(), [
 | 
			
		||||
                "channel" => $this->getSlackChannel(),
 | 
			
		||||
                "text" => "Podsumowanie dla dnia {$now->toDisplayString()}",
 | 
			
		||||
                "attachments" => $attachments,
 | 
			
		||||
            ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function shouldHandle(CarbonInterface $day): bool
 | 
			
		||||
    {
 | 
			
		||||
        $holidays = Holiday::query()->whereDate("date", $day)->pluck("date");
 | 
			
		||||
 | 
			
		||||
        if ($day->isWeekend()) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($holidays->contains($day)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getUrl(): string
 | 
			
		||||
    {
 | 
			
		||||
        return "{$this->getSlackBaseUrl()}/chat.postMessage";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getSlackBaseUrl(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return config("services.slack.url");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getSlackClientToken(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return config("services.slack.client_token");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getSlackChannel(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return config("services.slack.default_channel");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -16,6 +16,6 @@ class CalculateVacationDaysController extends Controller
 | 
			
		||||
    {
 | 
			
		||||
        $days = $calculator->calculateDays($request->from(), $request->to());
 | 
			
		||||
 | 
			
		||||
        return new JsonResponse($days->map(fn(Carbon $day) => $day->toDateString())->all());
 | 
			
		||||
        return new JsonResponse($days->map(fn(Carbon $day): string => $day->toDateString())->all());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,8 @@ class GetAvailableVacationTypesController extends Controller
 | 
			
		||||
        $user = User::query()->find($request->get("user"));
 | 
			
		||||
 | 
			
		||||
        $types = VacationType::all()
 | 
			
		||||
            ->filter(fn(VacationType $type) => $configRetriever->isAvailableFor($type, $user->profile->employment_form))
 | 
			
		||||
            ->map(fn(VacationType $type) => [
 | 
			
		||||
            ->filter(fn(VacationType $type): bool => $configRetriever->isAvailableFor($type, $user->profile->employment_form))
 | 
			
		||||
            ->map(fn(VacationType $type): array => [
 | 
			
		||||
                "label" => $type->label(),
 | 
			
		||||
                "value" => $type->value,
 | 
			
		||||
            ])
 | 
			
		||||
 
 | 
			
		||||
@@ -7,12 +7,11 @@ namespace Toby\Infrastructure\Http\Controllers;
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
use Illuminate\Support\Carbon;
 | 
			
		||||
use Inertia\Response;
 | 
			
		||||
use Toby\Domain\Enums\VacationType;
 | 
			
		||||
use Toby\Domain\DailySummaryRetriever;
 | 
			
		||||
use Toby\Domain\UserVacationStatsRetriever;
 | 
			
		||||
use Toby\Domain\VacationRequestStatesRetriever;
 | 
			
		||||
use Toby\Domain\VacationTypeConfigRetriever;
 | 
			
		||||
use Toby\Eloquent\Helpers\YearPeriodRetriever;
 | 
			
		||||
use Toby\Eloquent\Models\Vacation;
 | 
			
		||||
use Toby\Eloquent\Models\VacationRequest;
 | 
			
		||||
use Toby\Infrastructure\Http\Resources\HolidayResource;
 | 
			
		||||
use Toby\Infrastructure\Http\Resources\VacationRequestResource;
 | 
			
		||||
@@ -25,24 +24,14 @@ class DashboardController extends Controller
 | 
			
		||||
        YearPeriodRetriever $yearPeriodRetriever,
 | 
			
		||||
        UserVacationStatsRetriever $vacationStatsRetriever,
 | 
			
		||||
        VacationTypeConfigRetriever $configRetriever,
 | 
			
		||||
        DailySummaryRetriever $dailySummaryRetriever,
 | 
			
		||||
    ): Response {
 | 
			
		||||
        $user = $request->user();
 | 
			
		||||
        $now = Carbon::now();
 | 
			
		||||
        $yearPeriod = $yearPeriodRetriever->selected();
 | 
			
		||||
 | 
			
		||||
        $absences = Vacation::query()
 | 
			
		||||
            ->with(["user", "vacationRequest"])
 | 
			
		||||
            ->whereDate("date", $now)
 | 
			
		||||
            ->approved()
 | 
			
		||||
            ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => $configRetriever->isVacation($type)))
 | 
			
		||||
            ->get();
 | 
			
		||||
 | 
			
		||||
        $remoteDays = Vacation::query()
 | 
			
		||||
            ->with(["user", "vacationRequest"])
 | 
			
		||||
            ->whereDate("date", $now)
 | 
			
		||||
            ->approved()
 | 
			
		||||
            ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => !$configRetriever->isVacation($type)))
 | 
			
		||||
            ->get();
 | 
			
		||||
        $absences = $dailySummaryRetriever->getAbsences($now);
 | 
			
		||||
        $remoteDays = $dailySummaryRetriever->getRemoteDays($now);
 | 
			
		||||
 | 
			
		||||
        if ($user->can("listAll", VacationRequest::class)) {
 | 
			
		||||
            $vacationRequests = $yearPeriod->vacationRequests()
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,8 @@ use Illuminate\Auth\Access\AuthorizationException;
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
use Inertia\Response;
 | 
			
		||||
use Symfony\Component\HttpFoundation\RedirectResponse;
 | 
			
		||||
use Toby\Domain\Notifications\KeyHasBeenGivenNotification;
 | 
			
		||||
use Toby\Domain\Notifications\KeyHasBeenTakenNotification;
 | 
			
		||||
use Toby\Eloquent\Models\Key;
 | 
			
		||||
use Toby\Eloquent\Models\User;
 | 
			
		||||
use Toby\Infrastructure\Http\Requests\GiveKeyRequest;
 | 
			
		||||
@@ -60,6 +62,8 @@ class KeysController extends Controller
 | 
			
		||||
 | 
			
		||||
        $key->save();
 | 
			
		||||
 | 
			
		||||
        $key->notify(new KeyHasBeenTakenNotification($request->user(), $previousUser));
 | 
			
		||||
 | 
			
		||||
        return redirect()
 | 
			
		||||
            ->back()
 | 
			
		||||
            ->with("success", __("Key no :number has been taken from :user.", [
 | 
			
		||||
@@ -81,6 +85,8 @@ class KeysController extends Controller
 | 
			
		||||
 | 
			
		||||
        $key->save();
 | 
			
		||||
 | 
			
		||||
        $key->notify(new KeyHasBeenGivenNotification($request->user(), $recipient));
 | 
			
		||||
 | 
			
		||||
        return redirect()
 | 
			
		||||
            ->back()
 | 
			
		||||
            ->with("success", __("Key no :number has been given to :user.", [
 | 
			
		||||
 
 | 
			
		||||
@@ -35,8 +35,10 @@ class TimesheetController extends Controller
 | 
			
		||||
 | 
			
		||||
        $types = VacationType::all()
 | 
			
		||||
            ->filter(
 | 
			
		||||
                fn(VacationType $type) => $configRetriever->isAvailableFor($type, EmploymentForm::EmploymentContract)
 | 
			
		||||
                    && $configRetriever->isVacation($type),
 | 
			
		||||
                fn(VacationType $type): bool => $configRetriever->isAvailableFor(
 | 
			
		||||
                    $type,
 | 
			
		||||
                    EmploymentForm::EmploymentContract,
 | 
			
		||||
                ) && $configRetriever->isVacation($type),
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        $filename = "{$carbonMonth->translatedFormat("F Y")}.xlsx";
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ class VacationLimitController extends Controller
 | 
			
		||||
            ->sortBy(fn(VacationLimit $limit): string => "{$limit->user->profile->last_name} {$limit->user->profile->first_name}")
 | 
			
		||||
            ->values();
 | 
			
		||||
 | 
			
		||||
        $limitsResource = $limits->map(fn(VacationLimit $limit) => [
 | 
			
		||||
        $limitsResource = $limits->map(fn(VacationLimit $limit): array => [
 | 
			
		||||
            "id" => $limit->id,
 | 
			
		||||
            "user" => new UserResource($limit->user),
 | 
			
		||||
            "hasVacation" => $limit->hasVacation(),
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ class HandleInertiaRequests extends Middleware
 | 
			
		||||
    {
 | 
			
		||||
        $user = $request->user();
 | 
			
		||||
 | 
			
		||||
        return fn() => [
 | 
			
		||||
        return fn(): array => [
 | 
			
		||||
            "user" => $user ? new UserResource($user) : null,
 | 
			
		||||
            "can" => [
 | 
			
		||||
                "manageVacationLimits" => $user ? $user->can("manageVacationLimits") : false,
 | 
			
		||||
@@ -45,7 +45,7 @@ class HandleInertiaRequests extends Middleware
 | 
			
		||||
 | 
			
		||||
    protected function getFlashData(Request $request): Closure
 | 
			
		||||
    {
 | 
			
		||||
        return fn() => [
 | 
			
		||||
        return fn(): array => [
 | 
			
		||||
            "success" => $request->session()->get("success"),
 | 
			
		||||
            "error" => $request->session()->get("error"),
 | 
			
		||||
            "info" => $request->session()->get("info"),
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,8 @@ class UserRequest extends FormRequest
 | 
			
		||||
            "position" => ["required"],
 | 
			
		||||
            "employmentForm" => ["required", new Enum(EmploymentForm::class)],
 | 
			
		||||
            "employmentDate" => ["required", "date_format:Y-m-d"],
 | 
			
		||||
            "birthday" => ["nullable", "date_format:Y-m-d"],
 | 
			
		||||
            "slackId" => [],
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -41,6 +43,8 @@ class UserRequest extends FormRequest
 | 
			
		||||
            "position" => $this->get("position"),
 | 
			
		||||
            "employment_form" => $this->get("employmentForm"),
 | 
			
		||||
            "employment_date" => $this->get("employmentDate"),
 | 
			
		||||
            "birthday" => $this->get("birthday"),
 | 
			
		||||
            "slack_id" => $this->get("slackId"),
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,8 @@ class UserFormDataResource extends JsonResource
 | 
			
		||||
            "position" => $this->profile->position,
 | 
			
		||||
            "employmentForm" => $this->profile->employment_form,
 | 
			
		||||
            "employmentDate" => $this->profile->employment_date->toDateString(),
 | 
			
		||||
            "birthday" => $this->profile->birthday?->toDateString(),
 | 
			
		||||
            "slackId" => $this->profile->slack_id,
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								app/Infrastructure/Slack/Channels/SlackApiChannel.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Infrastructure/Slack/Channels/SlackApiChannel.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Channels;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Http\Client\Response;
 | 
			
		||||
use Illuminate\Notifications\Notification;
 | 
			
		||||
use Illuminate\Support\Facades\Http;
 | 
			
		||||
use Toby\Domain\Notifications\Notifiable;
 | 
			
		||||
 | 
			
		||||
class SlackApiChannel
 | 
			
		||||
{
 | 
			
		||||
    public function send(Notifiable $notifiable, Notification $notification): Response
 | 
			
		||||
    {
 | 
			
		||||
        $baseUrl = $this->getBaseUrl();
 | 
			
		||||
        $url = "{$baseUrl}/chat.postMessage";
 | 
			
		||||
        $channel = $notifiable->routeNotificationFor("slack", $notification);
 | 
			
		||||
 | 
			
		||||
        return Http::withToken($this->getClientToken())
 | 
			
		||||
            ->post($url, [
 | 
			
		||||
                "channel" => $channel,
 | 
			
		||||
                "text" => $notification->toSlack($notifiable),
 | 
			
		||||
            ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getClientToken(): string
 | 
			
		||||
    {
 | 
			
		||||
        return config("services.slack.client_token");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getBaseUrl(): string
 | 
			
		||||
    {
 | 
			
		||||
        return config("services.slack.url");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								app/Infrastructure/Slack/Controller.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								app/Infrastructure/Slack/Controller.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\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\InvalidRequest;
 | 
			
		||||
use Spatie\SlashCommand\Exceptions\RequestCouldNotBeHandled;
 | 
			
		||||
use Spatie\SlashCommand\Exceptions\SlackSlashCommandException;
 | 
			
		||||
use Spatie\SlashCommand\Response;
 | 
			
		||||
 | 
			
		||||
class Controller extends SlackController
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @throws InvalidRequest|RequestCouldNotBeHandled
 | 
			
		||||
     */
 | 
			
		||||
    public function getResponse(IlluminateRequest $request): IlluminateResponse
 | 
			
		||||
    {
 | 
			
		||||
        $this->verifyWithSigning($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 => Attachment::create()
 | 
			
		||||
                    ->setColor("danger")
 | 
			
		||||
                    ->setText($message[0]),
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        return Response::create($this->request)
 | 
			
		||||
            ->withText(":x: Polecenie `/{$this->request->command} {$this->request->text}` jest niepoprawne:")
 | 
			
		||||
            ->withAttachments($errors->all());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								app/Infrastructure/Slack/Elements/AbsencesAttachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Infrastructure/Slack/Elements/AbsencesAttachment.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Elements;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
use Toby\Eloquent\Models\Vacation;
 | 
			
		||||
 | 
			
		||||
class AbsencesAttachment extends ListAttachment
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(Collection $absences)
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
 | 
			
		||||
        $this
 | 
			
		||||
            ->setTitle("Nieobecności :palm_tree:")
 | 
			
		||||
            ->setColor("#eab308")
 | 
			
		||||
            ->setItems($absences->map(fn(Vacation $vacation): string => $vacation->user->profile->full_name))
 | 
			
		||||
            ->setEmptyText("Wszyscy dzisiaj pracują :muscle:");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								app/Infrastructure/Slack/Elements/Attachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/Infrastructure/Slack/Elements/Attachment.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Elements;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Contracts\Support\Arrayable;
 | 
			
		||||
use Spatie\SlashCommand\Attachment as BaseAttachment;
 | 
			
		||||
 | 
			
		||||
class Attachment extends BaseAttachment implements Arrayable
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								app/Infrastructure/Slack/Elements/BirthdaysAttachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Infrastructure/Slack/Elements/BirthdaysAttachment.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Elements;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
use Toby\Eloquent\Models\User;
 | 
			
		||||
 | 
			
		||||
class BirthdaysAttachment extends ListAttachment
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(Collection $birthdays)
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
 | 
			
		||||
        $this
 | 
			
		||||
            ->setTitle("Urodziny :birthday:")
 | 
			
		||||
            ->setColor("#3c5f97")
 | 
			
		||||
            ->setItems($birthdays->map(fn(User $user): string => $user->profile->full_name))
 | 
			
		||||
            ->setEmptyText("Dzisiaj nikt nie ma urodzin :cry:");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								app/Infrastructure/Slack/Elements/KeysAttachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								app/Infrastructure/Slack/Elements/KeysAttachment.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Elements;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
use Toby\Eloquent\Models\Key;
 | 
			
		||||
 | 
			
		||||
class KeysAttachment extends ListAttachment
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(Collection $keys)
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
 | 
			
		||||
        $this
 | 
			
		||||
            ->setColor("#3c5f97")
 | 
			
		||||
            ->setItems($keys->map(fn(Key $key): string => "Klucz nr {$key->id} - <@{$key->user->profile->slack_id}>"))
 | 
			
		||||
            ->setEmptyText("Nie ma żadnych kluczy w tobym");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								app/Infrastructure/Slack/Elements/ListAttachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Infrastructure/Slack/Elements/ListAttachment.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Elements;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
 | 
			
		||||
class ListAttachment extends Attachment
 | 
			
		||||
{
 | 
			
		||||
    protected Collection $items;
 | 
			
		||||
    protected string $emptyText = "";
 | 
			
		||||
 | 
			
		||||
    public function setItems(Collection $items): static
 | 
			
		||||
    {
 | 
			
		||||
        $this->items = $items;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setEmptyText(string $emptyText): static
 | 
			
		||||
    {
 | 
			
		||||
        $this->emptyText = $emptyText;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function toArray(): array
 | 
			
		||||
    {
 | 
			
		||||
        $fields = parent::toArray();
 | 
			
		||||
 | 
			
		||||
        return array_merge($fields, [
 | 
			
		||||
            "text" => $this->items->isNotEmpty() ? $this->items->implode("\n") : $this->emptyText,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								app/Infrastructure/Slack/Elements/RemotesAttachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Infrastructure/Slack/Elements/RemotesAttachment.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Elements;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
use Toby\Eloquent\Models\Vacation;
 | 
			
		||||
 | 
			
		||||
class RemotesAttachment extends ListAttachment
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(Collection $remoteDays)
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
 | 
			
		||||
        $this
 | 
			
		||||
            ->setTitle("Praca zdalna :house_with_garden:")
 | 
			
		||||
            ->setColor("#527aba")
 | 
			
		||||
            ->setItems($remoteDays->map(fn(Vacation $vacation): string => $vacation->user->profile->full_name))
 | 
			
		||||
            ->setEmptyText("Wszyscy dzisiaj są w biurze :boom:");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Exceptions;
 | 
			
		||||
 | 
			
		||||
use Spatie\SlashCommand\Exceptions\SlackSlashCommandException;
 | 
			
		||||
 | 
			
		||||
class UserNotFoundException extends SlackSlashCommandException
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								app/Infrastructure/Slack/Handlers/CatchAll.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/Infrastructure/Slack/Handlers/CatchAll.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Handlers;
 | 
			
		||||
 | 
			
		||||
use Spatie\SlashCommand\Handlers\BaseHandler;
 | 
			
		||||
use Spatie\SlashCommand\Request;
 | 
			
		||||
use Spatie\SlashCommand\Response;
 | 
			
		||||
use Toby\Infrastructure\Slack\Elements\Attachment;
 | 
			
		||||
use Toby\Infrastructure\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ę polecenia. Lista wszystkich poleceń:")
 | 
			
		||||
            ->withAttachment(
 | 
			
		||||
                Attachment::create()
 | 
			
		||||
                    ->setColor("danger")
 | 
			
		||||
                    ->useMarkdown()
 | 
			
		||||
                    ->setFields($attachmentFields),
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								app/Infrastructure/Slack/Handlers/DailySummary.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Infrastructure/Slack/Handlers/DailySummary.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Handlers;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Support\Carbon;
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
use Spatie\SlashCommand\Request;
 | 
			
		||||
use Spatie\SlashCommand\Response;
 | 
			
		||||
use Toby\Domain\DailySummaryRetriever;
 | 
			
		||||
use Toby\Infrastructure\Slack\Elements\AbsencesAttachment;
 | 
			
		||||
use Toby\Infrastructure\Slack\Elements\BirthdaysAttachment;
 | 
			
		||||
use Toby\Infrastructure\Slack\Elements\RemotesAttachment;
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
 | 
			
		||||
        $attachments = new Collection([
 | 
			
		||||
            new AbsencesAttachment($dailySummaryRetriever->getAbsences($now)),
 | 
			
		||||
            new RemotesAttachment($dailySummaryRetriever->getRemoteDays($now)),
 | 
			
		||||
            new BirthdaysAttachment($dailySummaryRetriever->getBirthdays($now)),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        return $this->respondToSlack("Podsumowanie dla dnia {$now->toDisplayString()}")
 | 
			
		||||
            ->withAttachments($attachments->all());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								app/Infrastructure/Slack/Handlers/GiveKeysTo.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								app/Infrastructure/Slack/Handlers/GiveKeysTo.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Handlers;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Validation\ValidationException;
 | 
			
		||||
use Spatie\SlashCommand\Request;
 | 
			
		||||
use Spatie\SlashCommand\Response;
 | 
			
		||||
use Toby\Domain\Notifications\KeyHasBeenGivenNotification;
 | 
			
		||||
use Toby\Eloquent\Models\Key;
 | 
			
		||||
use Toby\Infrastructure\Slack\Exceptions\UserNotFoundException;
 | 
			
		||||
use Toby\Infrastructure\Slack\Rules\SlackUserExistsRule;
 | 
			
		||||
use Toby\Infrastructure\Slack\Traits\FindsUserBySlackId;
 | 
			
		||||
 | 
			
		||||
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",
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								app/Infrastructure/Slack/Handlers/Help.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								app/Infrastructure/Slack/Handlers/Help.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Handlers;
 | 
			
		||||
 | 
			
		||||
use Spatie\SlashCommand\Request;
 | 
			
		||||
use Spatie\SlashCommand\Response;
 | 
			
		||||
use Toby\Infrastructure\Slack\Elements\Attachment;
 | 
			
		||||
use Toby\Infrastructure\Slack\Traits\ListsHandlers;
 | 
			
		||||
 | 
			
		||||
class Help extends SignatureHandler
 | 
			
		||||
{
 | 
			
		||||
    use ListsHandlers;
 | 
			
		||||
 | 
			
		||||
    protected $signature = "toby pomoc";
 | 
			
		||||
    protected $description = "Wyświetl wszystkie dostępne polecenia";
 | 
			
		||||
 | 
			
		||||
    public function handle(Request $request): Response
 | 
			
		||||
    {
 | 
			
		||||
        $handlers = $this->findAvailableHandlers();
 | 
			
		||||
 | 
			
		||||
        $attachmentFields = $this->mapHandlersToAttachments($handlers);
 | 
			
		||||
 | 
			
		||||
        return $this->respondToSlack("Dostępne polecenia:")
 | 
			
		||||
            ->withAttachment(
 | 
			
		||||
                Attachment::create()
 | 
			
		||||
                    ->setColor("good")
 | 
			
		||||
                    ->useMarkdown()
 | 
			
		||||
                    ->setFields($attachmentFields),
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								app/Infrastructure/Slack/Handlers/HomeOffice.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/Infrastructure/Slack/Handlers/HomeOffice.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\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\Eloquent\Models\User;
 | 
			
		||||
use Toby\Eloquent\Models\YearPeriod;
 | 
			
		||||
use Toby\Infrastructure\Slack\Traits\FindsUserBySlackId;
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								app/Infrastructure/Slack/Handlers/KeyList.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/Infrastructure/Slack/Handlers/KeyList.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Handlers;
 | 
			
		||||
 | 
			
		||||
use Spatie\SlashCommand\Request;
 | 
			
		||||
use Spatie\SlashCommand\Response;
 | 
			
		||||
use Toby\Eloquent\Models\Key;
 | 
			
		||||
use Toby\Infrastructure\Slack\Elements\KeysAttachment;
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
 | 
			
		||||
        return $this->respondToSlack("Lista kluczy :key:")
 | 
			
		||||
            ->withAttachment(new KeysAttachment($keys));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								app/Infrastructure/Slack/Handlers/SignatureHandler.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/Infrastructure/Slack/Handlers/SignatureHandler.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\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 [];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								app/Infrastructure/Slack/Handlers/TakeKeysFrom.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								app/Infrastructure/Slack/Handlers/TakeKeysFrom.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Handlers;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Validation\ValidationException;
 | 
			
		||||
use Spatie\SlashCommand\Request;
 | 
			
		||||
use Spatie\SlashCommand\Response;
 | 
			
		||||
use Toby\Domain\Notifications\KeyHasBeenTakenNotification;
 | 
			
		||||
use Toby\Eloquent\Models\Key;
 | 
			
		||||
use Toby\Infrastructure\Slack\Exceptions\UserNotFoundException;
 | 
			
		||||
use Toby\Infrastructure\Slack\Rules\SlackUserExistsRule;
 | 
			
		||||
use Toby\Infrastructure\Slack\Traits\FindsUserBySlackId;
 | 
			
		||||
 | 
			
		||||
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",
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								app/Infrastructure/Slack/Rules/SlackUserExistsRule.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								app/Infrastructure/Slack/Rules/SlackUserExistsRule.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\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";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								app/Infrastructure/Slack/Traits/FindsUserBySlackId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								app/Infrastructure/Slack/Traits/FindsUserBySlackId.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Traits;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Support\Str;
 | 
			
		||||
use Toby\Eloquent\Models\User;
 | 
			
		||||
use Toby\Infrastructure\Slack\Exceptions\UserNotFoundException;
 | 
			
		||||
 | 
			
		||||
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, "<@", "|");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								app/Infrastructure/Slack/Traits/ListsHandlers.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								app/Infrastructure/Slack/Traits/ListsHandlers.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Toby\Infrastructure\Slack\Traits;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
use Illuminate\Support\Str;
 | 
			
		||||
use Spatie\SlashCommand\AttachmentField;
 | 
			
		||||
use Spatie\SlashCommand\Handlers\BaseHandler;
 | 
			
		||||
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): BaseHandler => new $handlerClassName($this->request))
 | 
			
		||||
            ->filter(fn(HandlesSlashCommand $handler): bool => $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): int => strcmp(
 | 
			
		||||
                    $handlerA->getFullCommand(),
 | 
			
		||||
                    $handlerB->getFullCommand(),
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
            ->map(
 | 
			
		||||
                fn(SignatureHandler $handler): AttachmentField => AttachmentField::create(
 | 
			
		||||
                    $handler->getDescription(),
 | 
			
		||||
                    "`/{$handler->getSignature()}`",
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
            ->all();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user