Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 76
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
AccountSignupStep1Logic
0.00% covered (danger)
0.00%
0 / 76
0.00% covered (danger)
0.00%
0 / 5
182
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 startup
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 validateImpl
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
20
 executeImpl
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 1
20
 cleanup
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3declare(strict_types=1);
4
5namespace PeServer\App\Models\Domain\Page\Account;
6
7use PeServer\App\Models\AppConfiguration;
8use PeServer\App\Models\AppCryptography;
9use PeServer\App\Models\AppMailer;
10use PeServer\App\Models\AppTemplate;
11use PeServer\App\Models\Dao\Entities\SignUpWaitEmailsEntityDao;
12use PeServer\App\Models\AppEmailInformation;
13use PeServer\App\Models\AppUrl;
14use PeServer\App\Models\Data\EmailInformation;
15use PeServer\App\Models\Data\SessionAnonymous;
16use PeServer\App\Models\Domain\AccountValidator;
17use PeServer\App\Models\Domain\Page\PageLogicBase;
18use PeServer\App\Models\Domain\Page\SessionAnonymousTrait;
19use PeServer\App\Models\Domain\UserUtility;
20use PeServer\App\Models\SessionKey;
21use PeServer\Core\Code;
22use PeServer\Core\Collection\Arr;
23use PeServer\Core\Cryptography;
24use PeServer\Core\Database\IDatabaseContext;
25use PeServer\Core\Http\HttpStatus;
26use PeServer\Core\I18n;
27use PeServer\Core\Mail\EmailAddress;
28use PeServer\Core\Mail\EmailMessage;
29use PeServer\Core\Mail\Mailer;
30use PeServer\Core\Mvc\LogicCallMode;
31use PeServer\Core\Mvc\LogicParameter;
32use PeServer\Core\Text;
33use PeServer\Core\Web\UrlPath;
34
35class AccountSignupStep1Logic extends PageLogicBase
36{
37    use SessionAnonymousTrait;
38
39    private const TEMP_TOKEN = 'sign_up_token';
40
41    public function __construct(LogicParameter $parameter, private AppConfiguration $config, private AppCryptography $cryptography, private Mailer $mailer, private AppTemplate $appTemplate, private AppEmailInformation $appEmailInformation, private AppUrl $appUrl)
42    {
43        parent::__construct($parameter);
44    }
45
46    #region PageLogicBase
47
48    protected function startup(LogicCallMode $callMode): void
49    {
50        $this->setValue('email', $this->appEmailInformation);
51
52        $this->registerParameterKeys([
53            'value',
54            'account_signup_token',
55            'account_signup_value',
56            'account_signup_email',
57        ], true);
58    }
59
60    protected function validateImpl(LogicCallMode $callMode): void
61    {
62        if ($callMode === LogicCallMode::Initialize) {
63            return;
64        }
65
66        $this->throwHttpStatusIfNotSignup1(HttpStatus::NotFound);
67
68        $this->validation('account_signup_email', function (string $key, string $value) {
69            $accountValidator = new AccountValidator($this, $this->validator);
70            $accountValidator->isEmail($key, $value);
71        });
72
73        $temp = $this->popTemporary(self::TEMP_TOKEN);
74        $tempValue = $temp['value'] ?? Text::EMPTY;
75        $tempToken = $temp['token'] ?? Text::EMPTY;
76
77        $inputValue = $this->getRequest('account_signup_value');
78        $inputToken = $this->getRequest('account_signup_token');
79
80        if (!($tempValue === $inputValue && $tempToken == $inputToken)) {
81            $this->addError('account_signup_value', I18n::message('error/sign_up_token'));
82        }
83    }
84
85    protected function executeImpl(LogicCallMode $callMode): void
86    {
87        if ($callMode === LogicCallMode::Initialize) {
88            $this->setSession(SessionKey::ANONYMOUS, new SessionAnonymous(signup1: true));
89            return;
90        }
91
92        $email = $this->getRequest('account_signup_email');
93        $token = UserUtility::generateSignupToken();
94
95        $params = [
96            'token' => $token,
97            'raw_email' => $email,
98            'email' => $this->cryptography->encrypt($email),
99            'mark_email' => $this->cryptography->toMark($email),
100        ];
101
102        $this->logger->info('ユーザー登録処理開始: {0}', $params['token']);
103
104        $database = $this->openDatabase();
105        $database->transaction(function (IDatabaseContext $context) use ($params) {
106            $signUpWaitEmailsEntityDao = new SignUpWaitEmailsEntityDao($context);
107
108            $likeItems = $signUpWaitEmailsEntityDao->selectLikeEmails($params['mark_email']);
109            foreach ($likeItems->rows as $likeItem) {
110                $rawLikeEmail = $this->cryptography->decrypt($likeItem['email']);
111                if ($rawLikeEmail === $params['raw_email']) {
112                    $this->logger->info('重複メールアドレスを破棄: {0}', $likeItem['token']);
113                    $signUpWaitEmailsEntityDao->deleteToken($likeItem['token']);
114                }
115            }
116
117            $signUpWaitEmailsEntityDao->insertEmail(
118                $params['token'],
119                $params['email'],
120                $params['mark_email'],
121                $this->stores->special->getServer('REMOTE_ADDR'),
122                $this->stores->special->getServer('HTTP_USER_AGENT')
123            );
124
125            return true;
126        });
127
128
129        $url = $this->appUrl->addPublicUrl(new UrlPath("account/signup/$token"));
130
131        $subject = I18n::message('subject/sign_up_step1');
132        $values = [
133            'url' => $url->toString(),
134        ];
135        $html = $this->appTemplate->createMailTemplate('mail_signup_step1', $subject, $values);
136
137        $this->mailer->toAddresses = [
138            new EmailAddress($email),
139        ];
140        $this->mailer->subject = $subject;
141        $this->mailer->setMessage(new EmailMessage(null, $html));
142
143        $this->mailer->send();
144    }
145
146    protected function cleanup(LogicCallMode $callMode): void
147    {
148        if ($callMode === LogicCallMode::Submit && Arr::containsKey($this->result, 'token')) {
149            $this->removeTemporary(self::TEMP_TOKEN);
150            return;
151        }
152
153        $tempToken = Cryptography::generateRandomBinary(10)->toHex();
154        $tempValue = sprintf('%04d', Cryptography::generateRandomInteger(0, 9999));
155        $this->pushTemporary(self::TEMP_TOKEN, [
156            'token' => $tempToken,
157            'value' => $tempValue,
158        ]);
159        $this->setValue('account_signup_token', $tempToken);
160        $this->setValue('account_signup_value', Text::EMPTY);
161        $this->setValue('value', $tempValue);
162    }
163
164    #endregion
165}