Passed
Push — dev ( fd7324...4b1ed0 )
by Nico
29:02
created

PlayerCreator   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Test Coverage

Coverage 52.31%

Importance

Changes 0
Metric Value
eloc 60
dl 0
loc 133
ccs 34
cts 65
cp 0.5231
rs 10
c 0
b 0
f 0
wmc 23

7 Methods

Rating   Name   Duplication   Size   Complexity  
A createWithMobileNumber() 0 25 1
A __construct() 0 9 1
B checkForException() 0 19 11
A isMobileNumberCountryAllowed() 0 3 3
A saveReferer() 0 12 3
A isMobileFormatCorrect() 0 3 1
A createPlayer() 0 47 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Component\Player\Register;
6
7
use Doctrine\ORM\EntityManagerInterface;
8
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Stu\Component\Player\Register\Exception\EmailAddressInvalidException;
10
use Stu\Component\Player\Register\Exception\LoginNameInvalidException;
11
use Stu\Component\Player\Register\Exception\MobileNumberInvalidException;
12
use Stu\Component\Player\Register\Exception\PlayerDuplicateException;
13
use Stu\Module\Control\StuHashInterface;
14
use Stu\Module\PlayerSetting\Lib\UserEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\PlayerSetting\Lib\UserEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use Stu\Orm\Entity\FactionInterface;
16
use Stu\Orm\Entity\UserInterface;
17
use Stu\Orm\Repository\UserRepositoryInterface;
18
use Stu\Orm\Repository\UserRefererRepositoryInterface;
19
20
/**
21
 * Creates players with registration and optional sms validation
22
 */
23
class PlayerCreator implements PlayerCreatorInterface
24
{
25 7
    public function __construct(
26
        protected UserRepositoryInterface $userRepository,
27
        protected PlayerDefaultsCreatorInterface $playerDefaultsCreator,
28
        private RegistrationEmailSenderInterface $registrationEmailSender,
29
        private SmsVerificationCodeSenderInterface $smsVerificationCodeSender,
30
        private StuHashInterface $stuHash,
31
        private EntityManagerInterface $entityManager,
32
        private UserRefererRepositoryInterface $userRefererRepository
33 7
    ) {}
34
35 4
    #[Override]
36
    public function createWithMobileNumber(
37
        string $loginName,
38
        string $emailAddress,
39
        FactionInterface $faction,
40
        string $mobile,
41
        string $password,
42
        ?string $referer = null
43
    ): void {
44 4
        $mobileWithDoubleZero = str_replace('+', '00', $mobile);
45 4
        $this->checkForException($loginName, $emailAddress, $mobileWithDoubleZero);
46
47
        $randomHash = substr(md5(uniqid((string) random_int(0, mt_getrandmax()), true)), 16, 6);
48
49
        $player = $this->createPlayer(
50
            $loginName,
51
            $emailAddress,
52
            $faction,
53
            $password,
54
            $mobileWithDoubleZero,
55
            $randomHash,
56
            $referer
57
        );
58
59
        $this->smsVerificationCodeSender->send($player, $randomHash);
60
    }
61
62
63 4
    private function checkForException(string $loginName, string $emailAddress, ?string $mobile = null): void
64
    {
65
        if (
66 4
            !preg_match('/^[a-zA-Z0-9]+$/i', $loginName) ||
67 4
            mb_strlen($loginName) < 6
68
        ) {
69 1
            throw new LoginNameInvalidException();
70
        }
71 3
        if (!filter_var($emailAddress, FILTER_VALIDATE_EMAIL)) {
72 1
            throw new EmailAddressInvalidException();
73
        }
74 2
        if ($this->userRepository->getByLogin($loginName) || $this->userRepository->getByEmail($emailAddress)) {
75 2
            throw new PlayerDuplicateException();
76
        }
77
        if ($mobile !== null && $this->userRepository->getByMobile($mobile, $this->stuHash->hash($mobile))) {
78
            throw new PlayerDuplicateException();
79
        }
80
        if ($mobile !== null && (!$this->isMobileNumberCountryAllowed($mobile) || !$this->isMobileFormatCorrect($mobile))) {
81
            throw new MobileNumberInvalidException();
82
        }
83
    }
84
85
    private function isMobileNumberCountryAllowed(string $mobile): bool
86
    {
87
        return strpos($mobile, '0049') === 0 || strpos($mobile, '0041') === 0 || strpos($mobile, '0043') === 0;
88
    }
89
90
    private function isMobileFormatCorrect(string $mobile): bool
91
    {
92
        return (bool) preg_match('/00..[1-9]\d/', $mobile);
93
    }
94
95 1
    #[Override]
96
    public function createPlayer(
97
        string $loginName,
98
        string $emailAddress,
99
        FactionInterface $faction,
100
        string $password,
101
        ?string $mobile = null,
102
        ?string $smsCode = null,
103
        ?string $referer = null
104
    ): UserInterface {
105 1
        $player = $this->userRepository->prototype();
106 1
        $player->setLogin($loginName);
107 1
        $player->setEmail($emailAddress);
108 1
        $player->setFaction($faction);
109
110 1
        $this->userRepository->save($player);
111 1
        $this->entityManager->flush();
112
113 1
        $player->setUsername('Siedler ' . $player->getId());
114 1
        $player->setTick(1);
115 1
        $player->setCreationDate(time());
116 1
        $player->setPassword(password_hash($password, PASSWORD_DEFAULT));
117
118
        // Generate email activation code
119 1
        $activationData = $player->getId() . substr($loginName, 0, 3) . substr($emailAddress, 0, 3);
120 1
        $hash = hash('sha256', $activationData);
121 1
        $activationCode = strrev(substr($hash, -6));
122
123 1
        $player->setState(UserEnum::USER_STATE_ACCOUNT_VERIFICATION);
124
125
        // set player state to awaiting sms code if mobile provided
126 1
        if ($mobile !== null) {
127
            $player->setMobile($mobile);
128
            $player->setSmsCode($smsCode);
129
            $player->setState(UserEnum::USER_STATE_ACCOUNT_VERIFICATION);
130
        }
131
132 1
        if ($referer !== null) {
133
            $this->saveReferer($player, $referer);
134
        }
135
136 1
        $this->userRepository->save($player);
137
138 1
        $this->playerDefaultsCreator->createDefault($player);
139 1
        $this->registrationEmailSender->send($player, $activationCode);
140
141 1
        return $player;
142
    }
143
144
    private function saveReferer(UserInterface $user, ?string $referer): void
145
    {
146
        if ($referer !== null) {
147
148
            $sanitizedReferer = preg_replace('/[^\p{L}\p{N}\s]/u', '', $referer);
149
            $sanitizedReferer = $sanitizedReferer !== null ? substr($sanitizedReferer, 0, 2000) : '';
150
151
            $userReferer = $this->userRefererRepository->prototype();
152
            $userReferer->setUser($user);
153
            $userReferer->setReferer($sanitizedReferer);
154
155
            $this->userRefererRepository->save($userReferer);
156
        }
157
    }
158
}
159