Lines
82.60%
19 / 23
Methods
66.66%
2 / 3
Classes
0.00%
0 / 1
| Name | Lines | Methods | CRAP | ||||
|---|---|---|---|---|---|---|---|
| __construct | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| create | 63.63% | 7 / 11 | 0.00% | 0 / 1 | 4.77 | ||
| checkAgentName | 100.00% | 11 / 11 | 100.00% | 1 / 1 | 6 | ||
| 17 | class AgentStatService | |
| 18 | { | |
| 19 | public function __construct( | |
| 20 | private readonly EntityManagerInterface $entityManager, | |
| 21 | private readonly AgentStatRepository $agentStatRepository, | |
| 22 | private readonly UserRepository $userRepository, | |
| 23 | ) { | |
| 24 | } | |
| 25 | ||
| 26 | /** See AgentStat's #[UniqueConstraint]. */ | |
| 27 | private const string OWNER_DATETIME_CONSTRAINT = 'agent_stat_owner_datetime'; | |
| 28 | ||
| 29 | /** | |
| 30 | * @throws AgentNameException if the stats are for another agent, or the nickname is no agent name or taken | |
| 31 | * @throws StatsAlreadyAddedException if the owner already imported stats with this datetime | |
| 32 | */ | |
| 33 | public function create(User $owner, AgentStatInput $input): AgentStat | |
| 34 | { | |
| 35 | $this->checkAgentName($owner, \trim($input->nickname)); | |
| 36 | ||
| 37 | $agentStat = new AgentStat($owner, $input); | |
| 38 | ||
| 39 | if ($this->agentStatRepository->has($owner, $agentStat->datetime)) { | |
| 40 | throw new StatsAlreadyAddedException('Stat entry already added!'); | |
| 41 | } | |
| 42 | ||
| 43 | $this->entityManager->persist($agentStat); | |
| 44 | ||
| 45 | try { | |
| 46 | $this->entityManager->flush(); | |
| 47 | } catch (UniqueConstraintViolationException $uniqueConstraintViolationException) { | |
| 48 | // Another user took the agent name at the same moment | |
| 49 | if (!\str_contains($uniqueConstraintViolationException->getMessage(), self::OWNER_DATETIME_CONSTRAINT)) { | |
| 50 | throw new AgentNameException(User::AGENT_NAME_TAKEN, $uniqueConstraintViolationException->getCode(), previous: $uniqueConstraintViolationException); | |
| 51 | } | |
| 52 | ||
| 53 | // Same stats sent twice at the same moment | |
| 54 | throw new StatsAlreadyAddedException('Stat entry already added!', $uniqueConstraintViolationException->getCode(), previous: $uniqueConstraintViolationException); | |
| 55 | } | |
| 56 | ||
| 57 | return $agentStat; | |
| 58 | } | |
| 59 | ||
| 60 | /** | |
| 61 | * Without an agent name, the stats' nickname becomes the owner's agent name, unless another | |
| 62 | * user has it (ignoring case). | |
| 63 | * | |
| 64 | * @throws AgentNameException if the stats are for another agent, or the nickname is no agent name or taken | |
| 65 | */ | |
| 66 | private function checkAgentName(User $owner, string $nickname): void | |
| 67 | { | |
| 68 | $agentName = $owner->getAgentName(); | |
| 69 | if (null !== $agentName) { | |
| 70 | if (!$owner->isAgentName($nickname)) { | |
| 71 | throw new AgentNameException(\sprintf('These stats are for agent %s, your agent name is %s.', $nickname, $agentName)); | |
| 72 | } | |
| 73 | ||
| 74 | return; | |
| 75 | } | |
| 76 | ||
| 77 | if (1 !== \preg_match(User::AGENT_NAME_PATTERN, $nickname)) { | |
| 78 | throw new AgentNameException(User::AGENT_NAME_INVALID); | |
| 79 | } | |
| 80 | ||
| 81 | $other = $this->userRepository->findOneByAgentName($nickname); | |
| 82 | if ($other instanceof User && $other !== $owner) { | |
| 83 | throw new AgentNameException(User::AGENT_NAME_TAKEN); | |
| 84 | } | |
| 85 | ||
| 86 | $owner->setAgentName($nickname); | |
| 87 | } | |
| 88 | } |