Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
93.75% covered (success)
93.75%
15 / 16
90.91% covered (success)
90.91%
10 / 11
66.67% covered (warning)
66.67%
6 / 9
80.00% covered (warning)
80.00%
4 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiKeyService
93.75% covered (success)
93.75%
15 / 16
90.91% covered (success)
90.91%
10 / 11
66.67% covered (warning)
66.67%
6 / 9
80.00% covered (warning)
80.00%
4 / 5
10.37
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 findKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hashKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createKey
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 findValidKey
83.33% covered (warning)
83.33%
5 / 6
85.71% covered (warning)
85.71%
6 / 7
40.00% covered (danger)
40.00%
2 / 5
0.00% covered (danger)
0.00%
0 / 1
7.46
1<?php
2
3namespace App\Service\Data;
4
5use App\Dto\Result\GeneratedApiKey;
6use App\Entity\ApiKey;
7use App\Repository\ApiKeyRepositoryInterface;
8use Doctrine\ORM\EntityManagerInterface;
9use Psr\Clock\ClockInterface;
10
11/**
12 * @author Wilhelm Zwertvaegher
13 */
14readonly class ApiKeyService implements ApiKeyServiceInterface
15{
16    public function __construct(
17        private ApiKeyRepositoryInterface $repository,
18        private ApiKeyGeneratorInterface $generator,
19        private EntityManagerInterface $entityManager,
20        private ClockInterface $clock,
21    ) {
22    }
23
24    public function findKey(int $id): ?ApiKey
25    {
26        return $this->repository->findById($id);
27    }
28
29    private function hashKey(string $key): string
30    {
31        return hash('sha256', $key);
32    }
33
34    public function createKey(): GeneratedApiKey
35    {
36        $rawKey = $this->generator->generate();
37
38        $apiKey = new ApiKey(
39            $this->hashKey($rawKey),
40            $this->clock->now()
41        );
42
43        $this->entityManager->persist($apiKey);
44
45        return new GeneratedApiKey($apiKey, $rawKey);
46    }
47
48    public function findValidKey(string $receivedKey): ?ApiKey
49    {
50        $apiKey = $this->repository->findByHash($this->hashKey($receivedKey));
51        if (!$apiKey) {
52            return null;
53        }
54
55        if ($apiKey->getExpiresAt() && $apiKey->getExpiresAt() < $this->clock->now()) {
56            return null;
57        }
58
59        return $apiKey;
60    }
61}

Branches

Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once. Please also be aware that some branches may be implicit rather than explicit, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

ApiKeyService->__construct
16    public function __construct(
17        private ApiKeyRepositoryInterface $repository,
18        private ApiKeyGeneratorInterface $generator,
19        private EntityManagerInterface $entityManager,
20        private ClockInterface $clock,
21    ) {
22    }
ApiKeyService->createKey
36        $rawKey = $this->generator->generate();
37
38        $apiKey = new ApiKey(
39            $this->hashKey($rawKey),
40            $this->clock->now()
41        );
42
43        $this->entityManager->persist($apiKey);
44
45        return new GeneratedApiKey($apiKey, $rawKey);
46    }
ApiKeyService->findKey
24    public function findKey(int $id): ?ApiKey
25    {
26        return $this->repository->findById($id);
27    }
ApiKeyService->findValidKey
48    public function findValidKey(string $receivedKey): ?ApiKey
49    {
50        $apiKey = $this->repository->findByHash($this->hashKey($receivedKey));
51        if (!$apiKey) {
52            return null;
55        if ($apiKey->getExpiresAt() && $apiKey->getExpiresAt() < $this->clock->now()) {
55        if ($apiKey->getExpiresAt() && $apiKey->getExpiresAt() < $this->clock->now()) {
55        if ($apiKey->getExpiresAt() && $apiKey->getExpiresAt() < $this->clock->now()) {
56            return null;
59        return $apiKey;
60    }
ApiKeyService->hashKey
29    private function hashKey(string $key): string
30    {
31        return hash('sha256', $key);
32    }
{main}
3namespace App\Service\Data;
4
5use App\Dto\Result\GeneratedApiKey;
6use App\Entity\ApiKey;
7use App\Repository\ApiKeyRepositoryInterface;
8use Doctrine\ORM\EntityManagerInterface;
9use Psr\Clock\ClockInterface;
10
11/**
12 * @author Wilhelm Zwertvaegher
13 */
14readonly class ApiKeyService implements ApiKeyServiceInterface
15{
16    public function __construct(
17        private ApiKeyRepositoryInterface $repository,
18        private ApiKeyGeneratorInterface $generator,
19        private EntityManagerInterface $entityManager,
20        private ClockInterface $clock,
21    ) {
22    }
23
24    public function findKey(int $id): ?ApiKey
25    {
26        return $this->repository->findById($id);
27    }
28
29    private function hashKey(string $key): string
30    {
31        return hash('sha256', $key);
32    }
33
34    public function createKey(): GeneratedApiKey
35    {
36        $rawKey = $this->generator->generate();
37
38        $apiKey = new ApiKey(
39            $this->hashKey($rawKey),
40            $this->clock->now()
41        );
42
43        $this->entityManager->persist($apiKey);
44
45        return new GeneratedApiKey($apiKey, $rawKey);
46    }
47
48    public function findValidKey(string $receivedKey): ?ApiKey
49    {
50        $apiKey = $this->repository->findByHash($this->hashKey($receivedKey));
51        if (!$apiKey) {
52            return null;
53        }
54
55        if ($apiKey->getExpiresAt() && $apiKey->getExpiresAt() < $this->clock->now()) {
56            return null;
57        }
58
59        return $apiKey;
60    }