PluginProbe ʕ •ᴥ•ʔ
FAPI Member / 2.2.30
FAPI Member v2.2.30
2.2.33 2.2.32 trunk 1.9.47 2.1.18 2.2.24 2.2.25 2.2.26 2.2.28 2.2.29 2.2.30 2.2.31
fapi-member / src / Api / V2 / Endpoints / MembershipsController.php
fapi-member / src / Api / V2 / Endpoints Last commit date
ApiConnectionsController.php 3 months ago EmailsController.php 3 months ago MembershipsController.php 3 months ago PagesController.php 3 months ago SectionsController.php 3 months ago StatisticsController.php 3 months ago UsersController.php 3 months ago
MembershipsController.php
388 lines
1 <?php
2
3 namespace FapiMember\Api\V2\Endpoints;
4
5 use FapiMember\Api\V2\ApiController;
6 use FapiMember\Container\Container;
7 use FapiMember\FapiMemberPlugin;
8 use FapiMember\Library\SmartEmailing\Types\BoolType;
9 use FapiMember\Library\SmartEmailing\Types\IntType;
10 use FapiMember\Library\SmartEmailing\Types\StringType;
11 use FapiMember\Model\Enums\Alert;
12 use FapiMember\Model\Enums\Format;
13 use FapiMember\Model\Enums\Keys\OptionKey;
14 use FapiMember\Model\Enums\Types\RequestMethodType;
15 use FapiMember\Model\Membership;
16 use FapiMember\Repository\LevelRepository;
17 use FapiMember\Repository\MembershipRepository;
18 use FapiMember\Repository\PageRepository;
19 use FapiMember\Service\ApiService;
20 use FapiMember\Service\EmailService;
21 use FapiMember\Service\LevelService;
22 use FapiMember\Service\MembershipService;
23 use FapiMember\Service\RedirectService;
24 use FapiMember\Service\UserService;
25 use FapiMember\Utils\DateTimeHelper;
26 use Throwable;
27 use WP_REST_Request;
28
29 class MembershipsController
30 {
31 private MembershipRepository $membershipRepository;
32 private LevelRepository $levelRepository;
33 private PageRepository $pageRepository;
34 private MembershipService $membershipService;
35 private RedirectService $redirectService;
36 private EmailService $emailService;
37 private UserService $userService;
38 private LevelService $levelService;
39 private ApiService $apiService;
40 private ApiController $apiController;
41
42 public function __construct()
43 {
44 $this->membershipRepository = Container::get(MembershipRepository::class);
45 $this->levelRepository = Container::get(LevelRepository::class);
46 $this->pageRepository = Container::get(PageRepository::class);
47 $this->membershipService = Container::get(MembershipService::class);
48 $this->redirectService = Container::get(RedirectService::class);
49 $this->emailService = Container::get(EmailService::class);
50 $this->userService = Container::get(UserService::class);
51 $this->levelService = Container::get(LevelService::class);
52 $this->apiController = Container::get(ApiController::class);
53 $this->apiService = Container::get(ApiService::class);
54 }
55
56 public function list(): array
57 {
58 $membershipsByUsers = $this->membershipRepository->getAll();
59 $membershipData = [];
60
61 foreach ($membershipsByUsers as $membershipsByUser) {
62 foreach ($membershipsByUser as $membership) {
63 $membershipData[] = $membership->toArray();
64 }
65 }
66
67 return $membershipData;
68 }
69
70 public function getAllForUser(WP_REST_Request $request): array
71 {
72 $this->apiController->checkRequestMethod($request, RequestMethodType::POST);
73 $body = json_decode($request->get_body(), true);
74
75 $userId = $this->apiController->extractParam($body, 'user_id', IntType::class);
76
77 $memberships = $this->membershipRepository->getActiveByUserId($userId);
78
79 $membershipData = [];
80
81 foreach ($memberships as $membership) {
82 $membershipData[] = $membership->toArray();
83 }
84
85 return $membershipData;
86 }
87
88 public function updateAllForUser(WP_REST_Request $request): void
89 {
90 $this->apiController->checkRequestMethod($request, RequestMethodType::POST);
91 $body = json_decode($request->get_body(), true);
92
93 $userId = $this->apiController->extractParam($body, 'user_id', IntType::class);
94
95 if (isset($body['memberships']) && is_array($body['memberships'])) {
96 $membershipsData = $body['memberships'];
97 } else {
98 $this->apiController->invalidParameterError('memberships');
99 }
100
101 $memberships = [];
102
103 foreach ($membershipsData as $membershipData) {
104 $membershipData['user_id'] = $userId;
105 $memberships[] = new Membership($membershipData);
106 }
107
108 try {
109 $this->membershipService->saveAll($userId, $memberships);
110 } catch (Throwable) {
111 $this->apiController->callbackError([
112 'class'=> self::class,
113 'description' => "Failed to save memberships.",
114 ]);
115 }
116
117 $savedMemberships = $this->membershipService->getActiveByUserIdAndUpdate($userId);
118
119 foreach ($savedMemberships as $savedMembership) {
120 foreach ($memberships as $membership) {
121 if (
122 $membership->getLevelId() === $savedMembership->getLevelId()
123 ) {
124 if ($membership->getRegistered()->format(Format::DATE_TIME) !== $savedMembership->getRegistered()->format(Format::DATE_TIME)) {
125 $this->apiController->callbackResponse([], Alert::MEMBERSHIP_REGISTERED_EXTENDED);
126 }
127
128 if ($membership->getUntil()?->format(Format::DATE_TIME) !== $savedMembership->getUntil()?->format(Format::DATE_TIME)) {
129 $this->apiController->callbackResponse([], Alert::MEMBERSHIP_UNTIL_EXTENDED);
130 }
131 }
132 }
133 }
134
135 $this->apiController->callbackResponse([], Alert::SETTINGS_SAVED);
136 }
137
138 public function createMultiple(WP_REST_Request $request): void
139 {
140 $this->apiController->checkRequestMethod($request, RequestMethodType::POST);
141 $rows = json_decode($request->get_body(), true);
142
143 foreach ($rows as $row) {
144 if (isset($row['email']) && $row['email'] !== null && $row['email'] !== '') {
145 $this->create($row, true);
146 }
147 }
148 }
149
150 public function create(array $body, bool $creatingMultiple = false): void
151 {
152 if (!isset($body['level'])) {
153 $this->apiController->callbackError([
154 'class'=> self::class,
155 'description' => 'Level parameter missing in get params.',
156 ], Alert::IMPORT_FAILED);
157 }
158
159 if (is_array($body['level'])) {
160 $levelIds = [];
161
162 foreach ($body['level'] as $level) {
163 $levelIds[] = (int) $level;
164 }
165 } else {
166 $levelIds = [(int) $body['level']];
167 }
168
169 $token = $this->apiController->extractParamOrNull($body, 'token', StringType::class);
170 $voucher = $this->apiController->extractParamOrNull($body, 'voucher', IntType::class);
171 $id = $this->apiController->extractParamOrNull($body, 'id', IntType::class);
172
173 $debug = $this->apiController->extractParamOrNull($body, 'debug', BoolType::class);
174 $sendEmail = $this->apiController->extractParamOrNull($body, 'send_email', BoolType::class);
175 $days = $this->apiController->extractParamOrNull($body, 'days', IntType::class);
176
177 $registeredValue = $this->apiController->extractParamOrNull($body, 'registered', StringType::class);
178 $registered = DateTimeHelper::createOrNull($registeredValue, Format::DATE_TIME_BASIC)
179 ?? DateTimeHelper::createOrNull($registeredValue, Format::DATE);
180
181 $until = DateTimeHelper::createOrNull(
182 $this->apiController->extractParamOrNull($body, 'until', StringType::class),
183 Format::DATE,
184 );
185
186 try {
187 foreach ($levelIds as $levelId) {
188 $level = $this->levelRepository->getLevelById($levelId);
189
190 if ($level === null) {
191 $this->apiController->callbackError([
192 'class' => self::class,
193 'description' => sprintf(
194 'Section or level with ID %s, does not exist.',
195 $levelId,
196 ),
197 ], Alert::IMPORT_LEVEL_ID_DOESNT_EXIST);
198 }
199 }
200
201 if ($voucher !== null) {
202 $userData = $this->emailService->getEmailFromValidVoucher($body);
203 } elseif ($id !== null) {
204 $userData = $this->emailService->getEmailFromPaidInvoice($body);
205 } elseif ($token !== null) {
206 $userData = $this->emailService->getEmailFromBodyWithValidToken($body);
207 } else {
208 $this->apiController->callbackError([
209 'class' => self::class,
210 'description' => 'Invalid notification received. Missing voucher, id or token.',
211 ], Alert::MISSING_EMAIL);
212 }
213
214 if (!is_email($userData['email'])) {
215 $this->apiController->callbackError([
216 'class' => self::class,
217 'description' => 'Invalid email provided. Email given: ' . $userData['email'],
218 ], Alert::INVALID_EMAIL);
219 }
220
221 if ($id !== null && $days !== null) {
222 $invoice = $this->apiService->getInvoice($id);
223 $repaymentNumber = $invoice['repayment_number'] ?? 1;
224 $repaymentInvoices = $this->apiService->getAllInvoicesInRepayment($id);
225 $highestRepayment = 1;
226
227 if ($repaymentNumber !== 0 && $repaymentNumber !== null) {
228 foreach ($repaymentInvoices as $repaymentInvoice) {
229 if (
230 isset($repaymentInvoice['repayment_number']) &&
231 $repaymentInvoice['repayment_number'] > $highestRepayment
232 ) {
233 $highestRepayment = $repaymentInvoice['repayment_number'];
234 }
235 }
236
237 $repaymentDays = intdiv($days, $highestRepayment);
238
239 if ($repaymentNumber === 1) {
240 $repaymentDays += $days % $highestRepayment;
241 }
242
243 $days = $repaymentDays;
244 }
245 }
246
247 $props = [];
248 $user = $this->userService->getOrCreateUser($userData, $props);
249
250 if ($user === null) {
251 $this->apiController->callbackError([
252 'class' => self::class,
253 'description' => 'Failed to create user.',
254 ], Alert::IMPORT_FAILED);
255 }
256
257 foreach ($levelIds as $levelId) {
258 if ($registered === null) {
259 $props = $this->membershipService->createOrProlongMembershipByDays(
260 $user->getId(),
261 $levelId,
262 $days,
263 ) + $props;
264 } else {
265 $props = $this->membershipService->createOrUpdateMembership(
266 $user->getId(),
267 $levelId,
268 $registered,
269 $until,
270 ) + $props;
271 }
272 }
273
274 $wasUserCreatedNow = isset($props['new_user']) && $props['new_user'] === true;
275 $newToMembership = $props['oldMembership'] === null;
276 $levels = $this->levelRepository->getLevelsByIds($levelIds);
277
278 if ($sendEmail === true || $sendEmail === null) {
279 $emailsToSend = $this->emailService->findEmailsToSend($levels, $wasUserCreatedNow, $newToMembership);
280
281 foreach ($emailsToSend as $emailToSend) {
282 [$type, $level] = $emailToSend;
283
284 $this->emailService->sendEmail($user->getEmail(), $type, $level->getId(), $props);
285 }
286 }
287
288 } catch (Throwable $exception) {
289 $actualToken = get_option(OptionKey::TOKEN, null);
290
291 if (
292 $actualToken === $token &&
293 $debug === true
294 ) {
295 wp_send_json_error($exception->getMessage());
296 } else {
297 $this->apiController->callbackError([
298 'class' => self::class,
299 'description' => 'An internal error occurred.',
300 ]);
301 }
302 }
303
304 if (!$creatingMultiple) {
305 wp_send_json_success([FapiMemberPlugin::FAPI_MEMBER_PLUGIN_VERSION_KEY => FAPI_MEMBER_PLUGIN_VERSION]);
306 die;
307 }
308 }
309
310 public function unlockLevelForLoggedInUser(WP_REST_Request $request): void
311 {
312 $this->apiController->checkRequestMethod($request, RequestMethodType::GET);
313 $params = $request->get_params();
314
315 $levelId = $this->apiController->extractParamOrNull($params, 'level_id', IntType::class);
316 $pageId = $this->apiController->extractParamOrNull($params, 'page_id', IntType::class);
317
318 if ($levelId === null) {
319 $this->redirectService->redirectToNoAccessPage($levelId);
320 }
321
322 $userId = get_current_user_id();
323
324 if ($userId <= 0) {
325 $this->redirectService->redirectToNoAccessPage($levelId);
326 }
327
328 $level = $this->levelRepository->getLevelById($levelId);
329
330 if ($level === null || !$this->levelRepository->isButtonUnlock($levelId)) {
331 $this->redirectService->redirectToNoAccessPage($levelId);
332 }
333
334 $memberships = $this->membershipRepository->getActiveByUserId($userId);
335 $ownsParent = false;
336
337 foreach ($memberships as $membership) {
338 if ($membership->getLevelId() === $level->getParentId()){
339 $ownsParent = true;
340 break;
341 }
342 }
343
344 if ($ownsParent === false) {
345 $this->redirectService->redirectToNoAccessPage($levelId);
346 }
347
348 $this->membershipService->saveOne(new Membership([
349 'level_id' => $levelId,
350 'user_id' => $userId,
351 'registered' => DateTimeHelper::getNow()->format(Format::DATE_TIME),
352 'is_unlimited' => true,
353 ]));
354
355 if ($pageId === null) {
356 $pageId = $level->getAfterLoginPageId()
357 ?? $this->pageRepository->getCommonDashboardPageId();
358
359 if ($pageId === null) {
360 wp_redirect(home_url());
361 }
362 }
363
364 wp_redirect(home_url() . '/?page_id=' . $pageId);
365 }
366
367 public function getUnlockDate(WP_REST_Request $request): string|null
368 {
369 $this->apiController->checkRequestMethod($request, RequestMethodType::POST);
370 $body = json_decode($request->get_body(), true);
371 $userId = get_current_user_id();
372 $levelId = $this->apiController->extractParam($body, 'level_id', IntType::class);
373 $registrationDate = $this->apiController->extractParamOrNull($body, 'registration_date', StringType::class);
374 $registrationDate = DateTimeHelper::createOrNull($registrationDate, Format::DATE);
375
376 try {
377 return $this->membershipService
378 ->getUnlockDate($levelId, $userId, $registrationDate)?->format(Format::DATE_TIME);
379 } catch (Throwable) {
380 $this->apiController->callbackError([
381 'class'=> self::class,
382 'description' => "Failed to get unlock date",
383 ]);
384 }
385 }
386
387 }
388