FrankProjects/UltimateWarfare

View on GitHub
src/Service/Action/FederationApplicationActionService.php

Summary

Maintainability
A
2 hrs
Test Coverage
<?php

declare(strict_types=1);

namespace FrankProjects\UltimateWarfare\Service\Action;

use FrankProjects\UltimateWarfare\Entity\Federation;
use FrankProjects\UltimateWarfare\Entity\FederationApplication;
use FrankProjects\UltimateWarfare\Entity\FederationNews;
use FrankProjects\UltimateWarfare\Entity\Player;
use FrankProjects\UltimateWarfare\Entity\Report;
use FrankProjects\UltimateWarfare\Repository\FederationApplicationRepository;
use FrankProjects\UltimateWarfare\Repository\FederationNewsRepository;
use FrankProjects\UltimateWarfare\Repository\FederationRepository;
use FrankProjects\UltimateWarfare\Repository\PlayerRepository;
use FrankProjects\UltimateWarfare\Repository\ReportRepository;
use RuntimeException;

final class FederationApplicationActionService
{
    private FederationRepository $federationRepository;
    private FederationNewsRepository $federationNewsRepository;
    private FederationApplicationRepository $federationApplicationRepository;
    private PlayerRepository $playerRepository;
    private ReportRepository $reportRepository;

    public function __construct(
        FederationRepository $federationRepository,
        FederationApplicationRepository $federationApplicationRepository,
        FederationNewsRepository $federationNewsRepository,
        PlayerRepository $playerRepository,
        ReportRepository $reportRepository
    ) {
        $this->federationRepository = $federationRepository;
        $this->federationApplicationRepository = $federationApplicationRepository;
        $this->federationNewsRepository = $federationNewsRepository;
        $this->playerRepository = $playerRepository;
        $this->reportRepository = $reportRepository;
    }

    public function acceptFederationApplication(Player $player, int $applicationId): void
    {
        $this->ensureFederationEnabled($player);
        $federation = $player->getFederation();
        if ($federation === null) {
            throw new RuntimeException("Player is not in Federation!");
        }

        $federationApplication = $this->getFederationApplication($player, $applicationId);
        if ($federationApplication->getPlayer()->getFederation() !== null) {
            throw new RuntimeException("Player is already in another Federation!");
        }

        if ($federationApplication->getFederation()->getId() !== $federation->getId()) {
            throw new RuntimeException("FederationApplication does not belong to your Federation!");
        }

        if (count($federation->getPlayers()) >= $player->getWorld()->getFederationLimit()) {
            throw new RuntimeException("Federation members world limit reached!");
        }

        $news = "{$federationApplication->getPlayer()->getName()} has has been accepted into the Federation by {$player->getName()}";
        $federationNews = FederationNews::createForFederation($federation, $news);
        $this->federationNewsRepository->save($federationNews);

        $reportString = "You have been accepted in the Federation {$federation->getName()}";
        $report = Report::createForPlayer(
            $federationApplication->getPlayer(),
            time(),
            Report::TYPE_GENERAL,
            $reportString
        );
        $this->reportRepository->save($report);

        $applicationPlayer = $federationApplication->getPlayer();
        $applicationPlayer->setFederation($federation);
        $applicationPlayer->setFederationHierarchy(Player::FEDERATION_HIERARCHY_RECRUIT);
        $applicationPlayerNotifications = $applicationPlayer->getNotifications();
        $applicationPlayerNotifications->setGeneral(true);
        $applicationPlayer->setNotifications($applicationPlayerNotifications);
        $this->playerRepository->save($applicationPlayer);

        $federation->setNetworth($federation->getNetworth() + $federationApplication->getPlayer()->getNetworth());
        $federation->setRegions(
            $federation->getRegions() + count($federationApplication->getPlayer()->getWorldRegions())
        );
        $this->federationRepository->save($federation);

        $this->federationApplicationRepository->remove($federationApplication);
    }

    public function rejectFederationApplication(Player $player, int $applicationId): void
    {
        $this->ensureFederationEnabled($player);
        $federation = $player->getFederation();
        if ($federation === null) {
            throw new RuntimeException("Player is not in Federation!");
        }

        $federationApplication = $this->getFederationApplication($player, $applicationId);
        if ($federationApplication->getFederation()->getId() !== $federation->getId()) {
            throw new RuntimeException("FederationApplication does not belong to your Federation!");
        }

        $news = "{$federationApplication->getPlayer()->getName()} has has been rejected to join the Federation by {$player->getName()}";
        $federationNews = FederationNews::createForFederation($federation, $news);
        $this->federationNewsRepository->save($federationNews);

        $reportString = "You have been rejected by the Federation {$federation->getName()}";
        $report = Report::createForPlayer(
            $federationApplication->getPlayer(),
            time(),
            Report::TYPE_GENERAL,
            $reportString
        );
        $this->reportRepository->save($report);

        $this->federationApplicationRepository->remove($federationApplication);
    }

    public function sendFederationApplication(Player $player, Federation $federation, string $application): void
    {
        $this->ensureFederationEnabled($player);

        if ($player->getFederation() !== null) {
            throw new RuntimeException("You are already in a Federation");
        }

        if ($federation->getWorld()->getId() !== $player->getWorld()->getId()) {
            throw new RuntimeException("Federation is not in your world!");
        }

        $federationApplication = FederationApplication::createForFederation($federation, $player, $application);
        $this->federationApplicationRepository->save($federationApplication);
    }

    private function ensureFederationEnabled(Player $player): void
    {
        $world = $player->getWorld();
        if (!$world->getFederation()) {
            throw new RuntimeException("Federations not enabled!");
        }
    }

    private function getFederationApplication(Player $player, int $federationApplicationId): FederationApplication
    {
        $federationApplication = $this->federationApplicationRepository->findByIdAndWorld(
            $federationApplicationId,
            $player->getWorld()
        );

        if ($federationApplication === null) {
            throw new RuntimeException('FederationApplication does not exist!');
        }

        if ($player->getFederation() === null) {
            throw new RuntimeException('You are not in a Federation!');
        }

        if ($player->getFederation()->getId() !== $federationApplication->getFederation()->getId()) {
            throw new RuntimeException('FederationApplication does not belong to your Federation!');
        }

        return $federationApplication;
    }
}