Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
47.62% covered (danger)
47.62%
30 / 63
16.67% covered (danger)
16.67%
1 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
UserDomainDao
47.62% covered (danger)
47.62%
30 / 63
16.67% covered (danger)
16.67%
1 / 6
17.20
0.00% covered (danger)
0.00%
0 / 1
 selectLoginUser
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
2.00
 selectEmailAndWaitTokenTimestamp
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 selectCacheItems
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
1
 selectUserIdFromApiKey
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 selectUserItems
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 updateEmailFromWaitEmail
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace PeServer\App\Models\Dao\Domain;
6
7use DateTime;
8use PeServer\App\Models\Cache\UserCache;
9use PeServer\App\Models\Cache\UserCacheItem;
10use PeServer\App\Models\Data\Dto\LoginUserDto;
11use PeServer\App\Models\Data\Dto\UserListItemDto;
12use PeServer\App\Models\Domain\UserLevel;
13use PeServer\App\Models\Domain\UserState;
14use PeServer\Core\Database\DaoBase;
15use PeServer\Core\Database\DaoTrait;
16use PeServer\Core\Database\DatabaseRowResult;
17use PeServer\Core\Database\IDatabaseContext;
18use PeServer\Core\TypeUtility;
19use PeServer\Core\Utc;
20
21class UserDomainDao extends DaoBase
22{
23    use DaoTrait;
24
25    #region function
26
27    /**
28     * @param string $loginId
29     * @phpstan-return LoginUserDto|null
30     */
31    public function selectLoginUser(string $loginId): ?LoginUserDto
32    {
33        $result = $this->context->querySingleOrNull(
34            <<<SQL
35
36            select
37                users.user_id,
38                users.login_id,
39                users.name,
40                users.level,
41                users.state,
42                user_authentications.current_password
43            from
44                users
45                inner join
46                    user_authentications
47                    on
48                    (
49                        user_authentications.user_id = users.user_id
50                    )
51            where
52                users.login_id = :login_id
53                and
54                (
55                    users.state = 'enabled'
56                )
57
58            SQL,
59            [
60                'login_id' => $loginId,
61            ]
62        );
63
64        if ($result === null) {
65            return null;
66        }
67
68        return $result->mapping(LoginUserDto::class);
69    }
70
71    /**
72     * @template TFieldArray of array{email:string,wait_email:string,token_timestamp_utc:string}
73     *
74     * @param string $userId
75     * @phpstan-return DatabaseRowResult<TFieldArray>
76     */
77    public function selectEmailAndWaitTokenTimestamp(string $userId, int $limitMinutes): DatabaseRowResult
78    {
79        /** @phpstan-var DatabaseRowResult<TFieldArray> */
80        return $this->context->querySingle(
81            <<<SQL
82
83            select
84                users.email,
85                IFNULL(user_change_wait_emails.email, '') as wait_email,
86                IFNULL(STRFTIME('%Y-%m-%dT%H:%M:%SZ', user_change_wait_emails.timestamp), '') as token_timestamp_utc
87            from
88                users
89                left join
90                    user_change_wait_emails
91                    on
92                    (
93                        user_change_wait_emails.user_id = users.user_id
94                        and
95                        (STRFTIME('%s', CURRENT_TIMESTAMP) - STRFTIME('%s', user_change_wait_emails.timestamp)) < :limit_minutes * 60
96                    )
97            where
98                users.user_id = :user_id
99
100            SQL,
101            [
102                'user_id' => $userId,
103                'limit_minutes' => $limitMinutes,
104            ]
105        );
106    }
107
108    /**
109     * Undocumented function
110     *
111     * @return UserCacheItem[]
112     */
113    public function selectCacheItems(): array
114    {
115        $result = $this->context->query(
116            <<<SQL
117
118            select
119                users.user_id,
120                users.name,
121                users.level,
122                users.state,
123                users.website,
124                users.description,
125                IFNULL(api_keys.api_key, '') as api_key,
126                IFNULL(api_keys.secret_key, '') as secret_key,
127                api_keys.created_timestamp as api_created_timestamp
128            from
129                users
130                left join
131                    api_keys
132                    on
133                    (
134                        api_keys.user_id = users.user_id
135                    )
136            order by
137                users.user_id
138
139            SQL
140        );
141
142        return array_map(function ($i) {
143            $rawApiTimestamp = $i['api_created_timestamp'];
144            /** @var DateTime|null */
145            $apiTimestamp = null;
146            Utc::tryParseDateTime($rawApiTimestamp, $apiTimestamp);
147
148            $cache = new UserCacheItem(
149                $i['user_id'],
150                $i['name'],
151                $i['level'],
152                $i['state'],
153                $i['website'],
154                $i['description'],
155                $i['api_key'],
156                $i['secret_key'],
157                $apiTimestamp
158            );
159
160            return $cache;
161        }, $result->rows);
162    }
163
164    public function selectUserIdFromApiKey(string $apiKey, string $secretKey): ?string
165    {
166        // 特に何かとくっつける必要はないが将来的になんか項目が増えたら面倒なのでこのクラスに実装
167
168        /** @phpstan-var DatabaseRowResult<non-empty-array<string,string>>|null */
169        $result = $this->context->querySingleOrNull(
170            <<<SQL
171
172            select
173                api_keys.user_id
174            from
175                api_keys
176            where
177                api_keys.api_key = :api_key
178                and
179                api_keys.secret_key = :secret_key
180
181            SQL,
182            [
183                'api_key' => $apiKey,
184                'secret_key' => $secretKey,
185            ]
186        );
187
188        if ($result === null) {
189            return null;
190        }
191
192        return $result->fields['user_id'];
193    }
194
195    /**
196     * 管理用ユーザー一覧取得。
197     *
198     * @phpstan-return UserListItemDto[]
199     */
200    public function selectUserItems(): array
201    {
202        $result = $this->context->selectOrdered(
203            <<<SQL
204
205            select
206                Users.user_id,
207                Users.login_id,
208                Users.name,
209                Users.state,
210                Users.level
211            from
212                Users
213            order by
214                case Users.state
215                    when 'enabled' then 0
216                    when 'locked' then 1
217                    when 'disabled' then 2
218                    else 100
219                end,
220                Users.name,
221                Users.login_id
222
223            SQL,
224        );
225
226        return $result->mapping(UserListItemDto::class);
227    }
228
229
230    public function updateEmailFromWaitEmail(string $userId, string $token): bool
231    {
232        return $this->context->updateByKeyOrNothing(
233            <<<SQL
234
235            update
236                users
237            set
238                email = (
239                    select
240                        user_change_wait_emails.email
241                    from
242                        user_change_wait_emails
243                    where
244                        user_change_wait_emails.user_id = users.user_id
245                        and
246                        user_change_wait_emails.token = :token
247                ),
248                mark_email = (
249                    select
250                        user_change_wait_emails.mark_email
251                    from
252                        user_change_wait_emails
253                    where
254                        user_change_wait_emails.user_id = users.user_id
255                        and
256                        user_change_wait_emails.token = :token
257                )
258            where
259                users.user_id = :user_id
260
261            SQL,
262            [
263                'user_id' => $userId,
264                'token' => $token,
265            ]
266        );
267    }
268
269    #endregion
270}