Passed
Push — master ( 1c618d...c1c6b0 )
by Yannick
10:36 queued 02:52
created

SocialController::getUserProfile()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 48
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 27
nc 7
nop 8
dl 0
loc 48
rs 9.1768
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Controller;
8
9
use Chamilo\CoreBundle\Entity\ExtraField;
10
use Chamilo\CoreBundle\Entity\Legal;
11
use Chamilo\CoreBundle\Entity\Message;
12
use Chamilo\CoreBundle\Entity\MessageAttachment;
13
use Chamilo\CoreBundle\Entity\User;
14
use Chamilo\CoreBundle\Entity\Usergroup;
15
use Chamilo\CoreBundle\Entity\UserRelUser;
16
use Chamilo\CoreBundle\Repository\ExtraFieldOptionsRepository;
17
use Chamilo\CoreBundle\Repository\ExtraFieldRepository;
18
use Chamilo\CoreBundle\Repository\LanguageRepository;
19
use Chamilo\CoreBundle\Repository\LegalRepository;
20
use Chamilo\CoreBundle\Repository\MessageRepository;
21
use Chamilo\CoreBundle\Repository\Node\IllustrationRepository;
22
use Chamilo\CoreBundle\Repository\Node\MessageAttachmentRepository;
23
use Chamilo\CoreBundle\Repository\Node\UsergroupRepository;
24
use Chamilo\CoreBundle\Repository\Node\UserRepository;
25
use Chamilo\CoreBundle\Repository\TrackEOnlineRepository;
26
use Chamilo\CoreBundle\Serializer\UserToJsonNormalizer;
27
use Chamilo\CoreBundle\ServiceHelper\UserHelper;
28
use Chamilo\CoreBundle\Settings\SettingsManager;
29
use Chamilo\CourseBundle\Repository\CForumThreadRepository;
30
use DateTime;
31
use DateTimeInterface;
32
use Doctrine\ORM\EntityManagerInterface;
33
use Exception;
34
use ExtraFieldValue;
35
use MessageManager;
36
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
37
use Symfony\Component\HttpFoundation\File\UploadedFile;
38
use Symfony\Component\HttpFoundation\JsonResponse;
39
use Symfony\Component\HttpFoundation\Request;
40
use Symfony\Component\HttpFoundation\RequestStack;
41
use Symfony\Component\HttpFoundation\Response;
42
use Symfony\Component\Mailer\MailerInterface;
43
use Symfony\Component\Mime\Email;
44
use Symfony\Component\Routing\Attribute\Route;
45
use Symfony\Contracts\Translation\TranslatorInterface;
46
use UserManager;
47
48
#[Route('/social-network')]
49
class SocialController extends AbstractController
50
{
51
    public function __construct(
52
        private readonly UserHelper $userHelper,
53
    ) {}
54
55
    #[Route('/personal-data/{userId}', name: 'chamilo_core_social_personal_data')]
56
    public function getPersonalData(
57
        int $userId,
58
        SettingsManager $settingsManager,
59
        UserToJsonNormalizer $userToJsonNormalizer
60
    ): JsonResponse {
61
        $propertiesToJson = $userToJsonNormalizer->serializeUserData($userId);
62
        $properties = $propertiesToJson ? json_decode($propertiesToJson, true) : [];
63
64
        $officerData = [
65
            ['name' => $settingsManager->getSetting('profile.data_protection_officer_name')],
66
            ['role' => $settingsManager->getSetting('profile.data_protection_officer_role')],
67
            ['email' => $settingsManager->getSetting('profile.data_protection_officer_email')],
68
        ];
69
        $properties['officer_data'] = $officerData;
70
71
        $dataForVue = [
72
            'personalData' => $properties,
73
        ];
74
75
        return $this->json($dataForVue);
76
    }
77
78
    #[Route('/terms-and-conditions/{userId}', name: 'chamilo_core_social_terms')]
79
    public function getLegalTerms(
80
        int $userId,
81
        SettingsManager $settingsManager,
82
        TranslatorInterface $translator,
83
        LegalRepository $legalTermsRepo,
84
        UserRepository $userRepo,
85
        LanguageRepository $languageRepo
86
    ): JsonResponse {
87
        $user = $userRepo->find($userId);
88
        if (!$user) {
89
            return $this->json(['error' => 'User not found']);
90
        }
91
92
        $isoCode = $user->getLocale();
93
        $extraFieldValue = new ExtraFieldValue('user');
94
        $value = $extraFieldValue->get_values_by_handler_and_field_variable($userId, 'legal_accept');
95
        if ($value && !empty($value['value'])) {
96
            [$legalId, $legalLanguageId, $legalTime] = explode(':', $value['value']);
97
            $term = $legalTermsRepo->find($legalId);
98
        } else {
99
            $term = $this->getLastConditionByLanguage($languageRepo, $isoCode, $legalTermsRepo, $settingsManager);
100
        }
101
102
        if (!$term) {
103
            return $this->json(['error' => 'Terms not found']);
104
        }
105
106
        $termExtraFields = new ExtraFieldValue('terms_and_condition');
107
        $values = $termExtraFields->getAllValuesByItem($term->getId());
108
109
        $termsContent = [];
110
        foreach ($values as $value) {
111
            if (!empty($value['value'])) {
112
                $termsContent[] = [
113
                    'title' => $translator->trans($value['display_text'], [], 'messages', $isoCode),
114
                    'content' => $value['value'],
115
                ];
116
            }
117
        }
118
119
        if (empty($termsContent)) {
120
            $termsContent[] = [
121
                'title' => $translator->trans('Terms and Conditions', [], 'messages', $isoCode),
122
                'content' => $term->getContent(),
123
            ];
124
        }
125
126
        $formattedDate = new DateTime('@'.$term->getDate());
127
128
        $dataForVue = [
129
            'terms' => $termsContent,
130
            'date_text' => $translator->trans('PublicationDate', [], 'messages', $isoCode).': '.$formattedDate->format('Y-m-d H:i:s'),
131
        ];
132
133
        return $this->json($dataForVue);
134
    }
135
136
    #[Route('/legal-status/{userId}', name: 'chamilo_core_social_legal_status')]
137
    public function getLegalStatus(
138
        int $userId,
139
        SettingsManager $settingsManager,
140
        TranslatorInterface $translator,
141
        UserRepository $userRepo,
142
    ): JsonResponse {
143
        $allowTermsConditions = 'true' === $settingsManager->getSetting('registration.allow_terms_conditions');
144
145
        if (!$allowTermsConditions) {
146
            return $this->json([
147
                'message' => $translator->trans('No terms and conditions available', [], 'messages'),
148
            ]);
149
        }
150
151
        $user = $userRepo->find($userId);
152
        if (!$user) {
153
            return $this->json(['error' => 'User not found']);
154
        }
155
156
        $extraFieldValue = new ExtraFieldValue('user');
157
        $value = $extraFieldValue->get_values_by_handler_and_field_variable($userId, 'legal_accept');
158
159
        if (empty($value['value'])) {
160
            return $this->json([
161
                'isAccepted' => false,
162
                'message' => $translator->trans('Send legal agreement', [], 'messages'),
163
            ]);
164
        }
165
166
        [$legalId, $legalLanguageId, $legalTime] = explode(':', $value['value']);
167
        $dateTime = new DateTime("@$legalTime");
168
        $response = [
169
            'isAccepted' => true,
170
            'acceptDate' => $dateTime->format('Y-m-d H:i:s'),
171
            'message' => '',
172
        ];
173
174
        return $this->json($response);
175
    }
176
177
    #[Route('/send-legal-term', name: 'chamilo_core_social_send_legal_term')]
178
    public function sendLegalTerm(
179
        Request $request,
180
        SettingsManager $settingsManager,
181
        TranslatorInterface $translator,
182
        LegalRepository $legalTermsRepo,
183
        UserRepository $userRepo,
184
        LanguageRepository $languageRepo
185
    ): JsonResponse {
186
        $data = json_decode($request->getContent(), true);
187
        $userId = $data['userId'] ?? null;
188
189
        /** @var User $user */
190
        $user = $userRepo->find($userId);
191
        if (!$user) {
0 ignored issues
show
introduced by
$user is of type Chamilo\CoreBundle\Entity\User, thus it always evaluated to true.
Loading history...
192
            return $this->json(['error' => 'User not found']);
193
        }
194
195
        $isoCode = $user->getLocale();
196
197
        /** @var Legal $term */
198
        $term = $this->getLastConditionByLanguage($languageRepo, $isoCode, $legalTermsRepo, $settingsManager);
199
200
        if (!$term) {
0 ignored issues
show
introduced by
$term is of type Chamilo\CoreBundle\Entity\Legal, thus it always evaluated to true.
Loading history...
201
            return $this->json(['error' => 'Terms not found']);
202
        }
203
204
        $legalAcceptType = $term->getVersion().':'.$term->getLanguageId().':'.time();
205
        UserManager::update_extra_field_value(
206
            $userId,
207
            'legal_accept',
208
            $legalAcceptType
209
        );
210
211
        $bossList = UserManager::getStudentBossList($userId);
212
        if (!empty($bossList)) {
213
            $bossList = array_column($bossList, 'boss_id');
214
            foreach ($bossList as $bossId) {
215
                $subjectEmail = sprintf(
216
                    $translator->trans('User %s signed the agreement'),
217
                    $user->getFullname()
218
                );
219
                $contentEmail = sprintf(
220
                    $translator->trans('User %s signed the agreement.TheDateY'),
221
                    $user->getFullname(),
222
                    api_get_local_time()
223
                );
224
225
                MessageManager::send_message_simple(
226
                    $bossId,
227
                    $subjectEmail,
228
                    $contentEmail,
229
                    $userId
230
                );
231
            }
232
        }
233
234
        return $this->json([
235
            'success' => true,
236
            'message' => $translator->trans('Terms accepted successfully.'),
237
        ]);
238
    }
239
240
    #[Route('/delete-legal', name: 'chamilo_core_social_delete_legal')]
241
    public function deleteLegal(Request $request, TranslatorInterface $translator): JsonResponse
242
    {
243
        $data = json_decode($request->getContent(), true);
244
        $userId = $data['userId'] ?? null;
245
246
        if (!$userId) {
247
            return $this->json(['error' => $translator->trans('User ID not provided')], Response::HTTP_BAD_REQUEST);
248
        }
249
250
        $extraFieldValue = new ExtraFieldValue('user');
251
        $value = $extraFieldValue->get_values_by_handler_and_field_variable($userId, 'legal_accept');
252
        if ($value && isset($value['id'])) {
253
            $extraFieldValue->delete($value['id']);
254
        }
255
256
        $value = $extraFieldValue->get_values_by_handler_and_field_variable($userId, 'termactivated');
257
        if ($value && isset($value['id'])) {
258
            $extraFieldValue->delete($value['id']);
259
        }
260
261
        return $this->json(['success' => true, 'message' => $translator->trans('Legal acceptance revoked successfully.')]);
262
    }
263
264
    #[Route('/handle-privacy-request', name: 'chamilo_core_social_handle_privacy_request')]
265
    public function handlePrivacyRequest(
266
        Request $request,
267
        SettingsManager $settingsManager,
268
        UserRepository $userRepo,
269
        TranslatorInterface $translator,
270
        MailerInterface $mailer,
271
        RequestStack $requestStack
272
    ): JsonResponse {
273
        $data = json_decode($request->getContent(), true);
274
        $userId = $data['userId'] ? (int) $data['userId'] : null;
275
        $explanation = $data['explanation'] ?? '';
276
        $requestType = $data['requestType'] ?? '';
277
278
        /** @var User $user */
279
        $user = $userRepo->find($userId);
280
281
        if (!$user) {
0 ignored issues
show
introduced by
$user is of type Chamilo\CoreBundle\Entity\User, thus it always evaluated to true.
Loading history...
282
            return $this->json(['success' => false, 'message' => 'User not found']);
283
        }
284
285
        if ('delete_account' === $requestType) {
286
            $fieldToUpdate = 'request_for_delete_account';
287
            $justificationFieldToUpdate = 'request_for_delete_account_justification';
288
            $emailSubject = $translator->trans('Request for account deletion');
289
            $emailContent = sprintf($translator->trans('User %s asked for the deletion of his/her account, explaining that : ').$explanation, $user->getFullName());
290
        } elseif ('delete_legal' === $requestType) {
291
            $fieldToUpdate = 'request_for_legal_agreement_consent_removal';
292
            $justificationFieldToUpdate = 'request_for_legal_agreement_consent_removal_justification';
293
            $emailSubject = $translator->trans('Request for consent withdrawal on legal terms');
294
            $emailContent = sprintf($translator->trans('User %s asked for the removal of his/her consent to our legal terms, explaining that: ').$explanation, $user->getFullName());
295
        } else {
296
            return $this->json(['success' => false, 'message' => 'Invalid action type']);
297
        }
298
299
        UserManager::createDataPrivacyExtraFields();
300
        UserManager::update_extra_field_value($userId, $fieldToUpdate, 1);
301
        UserManager::update_extra_field_value($userId, $justificationFieldToUpdate, $explanation);
302
303
        $request = $requestStack->getCurrentRequest();
304
        $baseUrl = $request->getSchemeAndHttpHost().$request->getBasePath();
305
        $specificPath = '/main/admin/user_list_consent.php';
306
        $link = $baseUrl.$specificPath;
307
        $emailContent .= $translator->trans('Go here : ').'<a href="'.$link.'">'.$link.'</a>';
308
309
        $emailOfficer = $settingsManager->getSetting('profile.data_protection_officer_email');
310
        if (!empty($emailOfficer)) {
311
            $email = new Email();
312
            $email
313
                ->from($user->getEmail())
314
                ->to($emailOfficer)
315
                ->subject($emailSubject)
316
                ->html($emailContent)
317
            ;
318
            $mailer->send($email);
319
        } else {
320
            MessageManager::sendMessageToAllAdminUsers($user->getId(), $emailSubject, $emailContent);
321
        }
322
323
        return $this->json([
324
            'success' => true,
325
            'message' => $translator->trans('Your request has been received.'),
326
        ]);
327
    }
328
329
    #[Route('/groups/{userId}', name: 'chamilo_core_social_groups')]
330
    public function getGroups(
331
        int $userId,
332
        UsergroupRepository $usergroupRepository,
333
        CForumThreadRepository $forumThreadRepository,
334
        SettingsManager $settingsManager,
335
        RequestStack $requestStack
336
    ): JsonResponse {
337
        $baseUrl = $requestStack->getCurrentRequest()->getBaseUrl();
338
        $cid = (int) $settingsManager->getSetting('forum.global_forums_course_id');
339
        $items = [];
340
        $goToUrl = '';
341
342
        if (!empty($cid)) {
343
            $threads = $forumThreadRepository->getThreadsBySubscriptions($userId, $cid);
344
            foreach ($threads as $thread) {
345
                $threadId = $thread->getIid();
346
                $forumId = (int) $thread->getForum()->getIid();
347
                $items[] = [
348
                    'id' => $threadId,
349
                    'name' => $thread->getTitle(),
350
                    'description' => '',
351
                    'url' => $baseUrl.'/main/forum/viewthread.php?cid='.$cid.'&sid=0&gid=0&forum='.$forumId.'&thread='.$threadId,
352
                ];
353
            }
354
            $goToUrl = $baseUrl.'/main/forum/index.php?cid='.$cid.'&sid=0&gid=0';
355
        } else {
356
            $groups = $usergroupRepository->getGroupsByUser($userId);
357
            foreach ($groups as $group) {
358
                $items[] = [
359
                    'id' => $group->getId(),
360
                    'name' => $group->getTitle(),
361
                    'description' => $group->getDescription(),
362
                    'url' => $baseUrl.'/resources/usergroups/show/'.$group->getId(),
363
                ];
364
            }
365
        }
366
367
        return $this->json([
368
            'items' => $items,
369
            'go_to' => $goToUrl,
370
        ]);
371
    }
372
373
    #[Route('/group/{groupId}/discussion/{discussionId}/messages', name: 'chamilo_core_social_group_discussion_messages')]
374
    public function getDiscussionMessages(
375
        $groupId,
376
        $discussionId,
377
        MessageRepository $messageRepository,
378
        UserRepository $userRepository,
379
        MessageAttachmentRepository $attachmentRepository
380
    ): JsonResponse {
381
        $messages = $messageRepository->getMessagesByGroupAndMessage((int) $groupId, (int) $discussionId);
382
383
        $formattedMessages = $this->formatMessagesHierarchy($messages, $userRepository, $attachmentRepository);
384
385
        return $this->json($formattedMessages);
386
    }
387
388
    #[Route('/get-forum-link', name: 'get_forum_link')]
389
    public function getForumLink(
390
        SettingsManager $settingsManager,
391
        RequestStack $requestStack
392
    ): JsonResponse {
393
        $baseUrl = $requestStack->getCurrentRequest()->getBaseUrl();
394
        $cid = (int) $settingsManager->getSetting('forum.global_forums_course_id');
395
396
        $goToLink = '';
397
        if (!empty($cid)) {
398
            $goToLink = $baseUrl.'/main/forum/index.php?cid='.$cid.'&sid=0&gid=0';
399
        }
400
401
        return $this->json(['go_to' => $goToLink]);
402
    }
403
404
    #[Route('/invite-friends/{userId}/{groupId}', name: 'chamilo_core_social_invite_friends')]
405
    public function inviteFriends(
406
        int $userId,
407
        int $groupId,
408
        UserRepository $userRepository,
409
        UsergroupRepository $usergroupRepository,
410
        IllustrationRepository $illustrationRepository
411
    ): JsonResponse {
412
        $user = $userRepository->find($userId);
413
        if (!$user) {
414
            return $this->json(['error' => 'User not found'], Response::HTTP_NOT_FOUND);
415
        }
416
417
        $group = $usergroupRepository->find($groupId);
418
        if (!$group) {
419
            return $this->json(['error' => 'Group not found'], Response::HTTP_NOT_FOUND);
420
        }
421
422
        $friends = $userRepository->getFriendsNotInGroup($userId, $groupId);
423
424
        $friendsList = array_map(function ($friend) use ($illustrationRepository) {
425
            return [
426
                'id' => $friend->getId(),
427
                'name' => $friend->getFirstName().' '.$friend->getLastName(),
428
                'avatar' => $illustrationRepository->getIllustrationUrl($friend),
429
            ];
430
        }, $friends);
431
432
        return $this->json(['friends' => $friendsList]);
433
    }
434
435
    #[Route('/add-users-to-group/{groupId}', name: 'chamilo_core_social_add_users_to_group')]
436
    public function addUsersToGroup(Request $request, int $groupId, UsergroupRepository $usergroupRepository): JsonResponse
437
    {
438
        $data = json_decode($request->getContent(), true);
439
        $userIds = $data['userIds'] ?? [];
440
441
        try {
442
            $usergroupRepository->addUserToGroup($userIds, $groupId);
443
444
            return $this->json(['success' => true, 'message' => 'Users added to group successfully.']);
445
        } catch (Exception $e) {
446
            return $this->json(['success' => false, 'message' => 'An error occurred: '.$e->getMessage()], Response::HTTP_BAD_REQUEST);
447
        }
448
    }
449
450
    #[Route('/group/{groupId}/invited-users', name: 'chamilo_core_social_group_invited_users')]
451
    public function groupInvitedUsers(int $groupId, UsergroupRepository $usergroupRepository, IllustrationRepository $illustrationRepository): JsonResponse
452
    {
453
        $invitedUsers = $usergroupRepository->getInvitedUsersByGroup($groupId);
454
455
        $invitedUsersList = array_map(function ($user) {
456
            return [
457
                'id' => $user['id'],
458
                'name' => $user['username'],
459
                // 'avatar' => $illustrationRepository->getIllustrationUrl($user),
460
            ];
461
        }, $invitedUsers);
462
463
        return $this->json(['invitedUsers' => $invitedUsersList]);
464
    }
465
466
    #[Route('/user-profile/{userId}', name: 'chamilo_core_social_user_profile')]
467
    public function getUserProfile(
468
        int $userId,
469
        SettingsManager $settingsManager,
470
        LanguageRepository $languageRepository,
471
        UserRepository $userRepository,
472
        RequestStack $requestStack,
473
        TrackEOnlineRepository $trackOnlineRepository,
474
        ExtraFieldRepository $extraFieldRepository,
475
        ExtraFieldOptionsRepository $extraFieldOptionsRepository
476
    ): JsonResponse {
477
        $user = $userRepository->find($userId);
478
        if (!$user) {
479
            return $this->json(['error' => 'User not found'], Response::HTTP_NOT_FOUND);
480
        }
481
482
        $baseUrl = $requestStack->getCurrentRequest()->getBaseUrl();
483
        $profileFieldsVisibilityJson = $settingsManager->getSetting('profile.profile_fields_visibility');
484
        $profileFieldsVisibility = json_decode($profileFieldsVisibilityJson, true)['options'] ?? [];
485
486
        $vCardUserLink = $profileFieldsVisibility['vcard'] ?? true ? $baseUrl.'/main/social/vcard_export.php?userId='.(int) $userId : '';
487
488
        $languageInfo = null;
489
        if ($profileFieldsVisibility['language'] ?? true) {
490
            $language = $languageRepository->findByIsoCode($user->getLocale());
491
            if ($language) {
492
                $languageInfo = [
493
                    'label' => $language->getOriginalName(),
494
                    'value' => $language->getEnglishName(),
495
                    'code' => $language->getIsocode(),
496
                ];
497
            }
498
        }
499
500
        $isUserOnline = $trackOnlineRepository->isUserOnline($userId);
501
        $userOnlyInChat = $this->checkUserStatus($userId, $userRepository);
502
        $extraFields = $this->getExtraFieldBlock($userId, $userRepository, $settingsManager, $extraFieldRepository, $extraFieldOptionsRepository);
503
504
        $response = [
505
            'vCardUserLink' => $vCardUserLink,
506
            'language' => $languageInfo,
507
            'visibility' => $profileFieldsVisibility,
508
            'isUserOnline' => $isUserOnline,
509
            'userOnlyInChat' => $userOnlyInChat,
510
            'extraFields' => $extraFields,
511
        ];
512
513
        return $this->json($response);
514
    }
515
516
    private function getExtraFieldBlock(
517
        int $userId,
518
        UserRepository $userRepository,
519
        SettingsManager $settingsManager,
520
        ExtraFieldRepository $extraFieldRepository,
521
        ExtraFieldOptionsRepository $extraFieldOptionsRepository
522
    ): array {
523
        $user = $userRepository->find($userId);
524
        if (!$user) {
525
            return [];
526
        }
527
528
        $fieldVisibilityConfig = $settingsManager->getSetting('profile.profile_fields_visibility');
529
        $fieldVisibility = $fieldVisibilityConfig ? json_decode($fieldVisibilityConfig, true)['options'] : [];
530
531
        $extraUserData = $userRepository->getExtraUserData($userId);
532
        $extraFieldsFormatted = [];
533
        foreach ($extraUserData as $key => $value) {
534
            $fieldVariable = str_replace('extra_', '', $key);
535
536
            $extraField = $extraFieldRepository->getHandlerFieldInfoByFieldVariable($fieldVariable, ExtraField::USER_FIELD_TYPE);
537
            if (!$extraField || !isset($fieldVisibility[$fieldVariable]) || !$fieldVisibility[$fieldVariable]) {
538
                continue;
539
            }
540
541
            $fieldValue = \is_array($value) ? implode(', ', $value) : $value;
542
543
            switch ($extraField['type']) {
544
                case ExtraField::FIELD_TYPE_RADIO:
545
                case ExtraField::FIELD_TYPE_SELECT:
546
                    $extraFieldOptions = $extraFieldOptionsRepository->getFieldOptionByFieldAndOption($extraField['id'], $fieldValue, ExtraField::USER_FIELD_TYPE);
547
                    if (!empty($extraFieldOptions)) {
548
                        $optionTexts = array_map(function ($option) {
549
                            return $option['display_text'];
550
                        }, $extraFieldOptions);
551
                        $fieldValue = implode(', ', $optionTexts);
552
                    }
553
554
                    break;
555
556
                case ExtraField::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
557
                case ExtraField::FIELD_TYPE_GEOLOCALIZATION:
558
                    $geoData = explode('::', $fieldValue);
559
                    $locationName = $geoData[0];
560
                    $coordinates = $geoData[1] ?? '';
561
                    $fieldValue = $locationName;
562
563
                    break;
564
            }
565
566
            $extraFieldsFormatted[] = [
567
                'variable' => $fieldVariable,
568
                'label' => $extraField['display_text'],
569
                'value' => $fieldValue,
570
            ];
571
        }
572
573
        return $extraFieldsFormatted;
574
    }
575
576
    #[Route('/invitations/{userId}', name: 'chamilo_core_social_invitations')]
577
    public function getInvitations(
578
        int $userId,
579
        MessageRepository $messageRepository,
580
        UsergroupRepository $usergroupRepository,
581
        UserRepository $userRepository,
582
        TranslatorInterface $translator
583
    ): JsonResponse {
584
        $user = $this->userHelper->getCurrent();
585
        if ($userId !== $user->getId()) {
586
            return $this->json(['error' => 'Unauthorized'], Response::HTTP_UNAUTHORIZED);
587
        }
588
589
        $receivedMessages = $messageRepository->findReceivedInvitationsByUser($user);
590
        $receivedInvitations = [];
591
        foreach ($receivedMessages as $message) {
592
            $sender = $message->getSender();
593
            $receivedInvitations[] = [
594
                'id' => $message->getId(),
595
                'itemId' => $sender->getId(),
596
                'itemName' => $sender->getFirstName().' '.$sender->getLastName(),
597
                'itemPicture' => $userRepository->getUserPicture($sender->getId()),
598
                'content' => $message->getContent(),
599
                'date' => $message->getSendDate()->format('Y-m-d H:i:s'),
600
                'canAccept' => true,
601
                'canDeny' => true,
602
            ];
603
        }
604
605
        $sentMessages = $messageRepository->findSentInvitationsByUser($user);
606
        $sentInvitations = [];
607
        foreach ($sentMessages as $message) {
608
            foreach ($message->getReceivers() as $receiver) {
609
                $receiverUser = $receiver->getReceiver();
610
                $sentInvitations[] = [
611
                    'id' => $message->getId(),
612
                    'itemId' => $receiverUser->getId(),
613
                    'itemName' => $receiverUser->getFirstName().' '.$receiverUser->getLastName(),
614
                    'itemPicture' => $userRepository->getUserPicture($receiverUser->getId()),
615
                    'content' => $message->getContent(),
616
                    'date' => $message->getSendDate()->format('Y-m-d H:i:s'),
617
                    'canAccept' => false,
618
                    'canDeny' => false,
619
                ];
620
            }
621
        }
622
623
        $pendingGroupInvitations = [];
624
        $pendingGroups = $usergroupRepository->getGroupsByUser($userId, Usergroup::GROUP_USER_PERMISSION_PENDING_INVITATION);
625
626
        /** @var Usergroup $group */
627
        foreach ($pendingGroups as $group) {
628
            $isGroupVisible = 1 === (int) $group->getVisibility();
629
            $infoVisibility = !$isGroupVisible ? ' - '.$translator->trans('This group is closed.') : '';
630
            $pendingGroupInvitations[] = [
631
                'id' => $group->getId(),
632
                'itemId' => $group->getId(),
633
                'itemName' => $group->getTitle().$infoVisibility,
634
                'itemPicture' => $usergroupRepository->getUsergroupPicture($group->getId()),
635
                'content' => $group->getDescription(),
636
                'date' => $group->getCreatedAt()->format('Y-m-d H:i:s'),
637
                'canAccept' => $isGroupVisible,
638
                'canDeny' => true,
639
            ];
640
        }
641
642
        return $this->json([
643
            'receivedInvitations' => $receivedInvitations,
644
            'sentInvitations' => $sentInvitations,
645
            'pendingGroupInvitations' => $pendingGroupInvitations,
646
        ]);
647
    }
648
649
    #[Route('/invitations/count/{userId}', name: 'chamilo_core_social_invitations_count')]
650
    public function getInvitationsCount(
651
        int $userId,
652
        MessageRepository $messageRepository,
653
        UsergroupRepository $usergroupRepository
654
    ): JsonResponse {
655
        $user = $this->userHelper->getCurrent();
656
        if ($userId !== $user->getId()) {
657
            return $this->json(['error' => 'Unauthorized']);
658
        }
659
660
        $receivedMessagesCount = \count($messageRepository->findReceivedInvitationsByUser($user));
661
        $pendingGroupInvitationsCount = \count($usergroupRepository->getGroupsByUser($userId, Usergroup::GROUP_USER_PERMISSION_PENDING_INVITATION));
662
        $totalInvitationsCount = $receivedMessagesCount + $pendingGroupInvitationsCount;
663
664
        return $this->json(['totalInvitationsCount' => $totalInvitationsCount]);
665
    }
666
667
    #[Route('/search', name: 'chamilo_core_social_search')]
668
    public function search(
669
        Request $request,
670
        UserRepository $userRepository,
671
        UsergroupRepository $usergroupRepository,
672
        TrackEOnlineRepository $trackOnlineRepository,
673
        MessageRepository $messageRepository
674
    ): JsonResponse {
675
        $query = $request->query->get('query', '');
676
        $type = $request->query->get('type', 'user');
677
        $from = $request->query->getInt('from', 0);
678
        $numberOfItems = $request->query->getInt('number_of_items', 1000);
679
680
        $formattedResults = [];
681
        if ('user' === $type) {
682
            $user = $this->userHelper->getCurrent();
683
            $results = $userRepository->searchUsersByTags($query, $user->getId(), 0, $from, $numberOfItems);
684
            foreach ($results as $item) {
685
                $isUserOnline = $trackOnlineRepository->isUserOnline($item['id']);
686
                $relation = $userRepository->getUserRelationWithType($user->getId(), $item['id']);
687
                $userReceiver = $userRepository->find($item['id']);
688
                $existingInvitations = $messageRepository->existingInvitations($user, $userReceiver);
689
                $formattedResults[] = [
690
                    'id' => $item['id'],
691
                    'name' => $item['firstname'].' '.$item['lastname'],
692
                    'avatar' => $userRepository->getUserPicture($item['id']),
693
                    'role' => 5 === $item['status'] ? 'student' : 'teacher',
694
                    'status' => $isUserOnline ? 'online' : 'offline',
695
                    'url' => '/social?id='.$item['id'],
696
                    'relationType' => $relation['relationType'] ?? null,
697
                    'existingInvitations' => $existingInvitations,
698
                ];
699
            }
700
        } elseif ('group' === $type) {
701
            // Perform group search
702
            $results = $usergroupRepository->searchGroupsByTags($query, $from, $numberOfItems);
703
            foreach ($results as $item) {
704
                $formattedResults[] = [
705
                    'id' => $item['id'],
706
                    'name' => $item['title'],
707
                    'description' => $item['description'] ?? '',
708
                    'image' => $usergroupRepository->getUsergroupPicture($item['id']),
709
                    'url' => '/resources/usergroups/show/'.$item['id'],
710
                ];
711
            }
712
        }
713
714
        return $this->json(['results' => $formattedResults]);
715
    }
716
717
    #[Route('/group-details/{groupId}', name: 'chamilo_core_social_group_details')]
718
    public function groupDetails(
719
        int $groupId,
720
        UsergroupRepository $usergroupRepository,
721
        TrackEOnlineRepository $trackOnlineRepository
722
    ): JsonResponse {
723
        $user = $this->userHelper->getCurrent();
724
        if (!$user) {
725
            return $this->json(['error' => 'User not authenticated'], Response::HTTP_UNAUTHORIZED);
726
        }
727
728
        /** @var Usergroup $group */
729
        $group = $usergroupRepository->find($groupId);
730
        if (!$group) {
0 ignored issues
show
introduced by
$group is of type Chamilo\CoreBundle\Entity\Usergroup, thus it always evaluated to true.
Loading history...
731
            return $this->json(['error' => 'Group not found'], Response::HTTP_NOT_FOUND);
732
        }
733
734
        $isMember = $usergroupRepository->isGroupMember($groupId, $user);
735
        $role = $usergroupRepository->getUserGroupRole($groupId, $user->getId());
736
        $isUserOnline = $trackOnlineRepository->isUserOnline($user->getId());
737
        $isModerator = $usergroupRepository->isGroupModerator($groupId, $user->getId());
738
739
        $groupDetails = [
740
            'id' => $group->getId(),
741
            'title' => $group->getTitle(),
742
            'description' => $group->getDescription(),
743
            'url' => $group->getUrl(),
744
            'image' => $usergroupRepository->getUsergroupPicture($group->getId()),
745
            'visibility' => (int) $group->getVisibility(),
746
            'allowMembersToLeaveGroup' => $group->getAllowMembersToLeaveGroup(),
747
            'isMember' => $isMember,
748
            'isModerator' => $isModerator,
749
            'role' => $role,
750
            'isUserOnline' => $isUserOnline,
751
            'isAllowedToLeave' => 1 === $group->getAllowMembersToLeaveGroup(),
752
        ];
753
754
        return $this->json($groupDetails);
755
    }
756
757
    #[Route('/group-action', name: 'chamilo_core_social_group_action')]
758
    public function group(
759
        Request $request,
760
        UsergroupRepository $usergroupRepository,
761
        EntityManagerInterface $em,
762
        MessageRepository $messageRepository
763
    ): JsonResponse {
764
        if (str_starts_with($request->headers->get('Content-Type'), 'multipart/form-data')) {
765
            $userId = $request->request->get('userId');
766
            $groupId = $request->request->get('groupId');
767
            $action = $request->request->get('action');
768
            $title = $request->request->get('title', '');
769
            $content = $request->request->get('content', '');
770
            $parentId = $request->request->get('parentId', 0);
771
            $editMessageId = $request->request->get('messageId', 0);
772
773
            $structuredFiles = [];
774
            if ($request->files->has('files')) {
775
                $files = $request->files->get('files');
776
                foreach ($files as $file) {
777
                    $structuredFiles[] = [
778
                        'name' => $file->getClientOriginalName(),
779
                        'full_path' => $file->getRealPath(),
780
                        'type' => $file->getMimeType(),
781
                        'tmp_name' => $file->getPathname(),
782
                        'error' => $file->getError(),
783
                        'size' => $file->getSize(),
784
                    ];
785
                }
786
            }
787
        } else {
788
            $data = json_decode($request->getContent(), true);
789
            $userId = $data['userId'] ?? null;
790
            $groupId = $data['groupId'] ?? null;
791
            $action = $data['action'] ?? null;
792
        }
793
794
        if (!$userId || !$groupId || !$action) {
795
            return $this->json(['error' => 'Missing parameters'], Response::HTTP_BAD_REQUEST);
796
        }
797
798
        try {
799
            switch ($action) {
800
                case 'accept':
801
                    $userRole = $usergroupRepository->getUserGroupRole($groupId, $userId);
802
                    if (\in_array(
803
                        $userRole,
804
                        [
805
                            Usergroup::GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER,
806
                            Usergroup::GROUP_USER_PERMISSION_PENDING_INVITATION,
807
                        ]
808
                    )) {
809
                        $usergroupRepository->updateUserRole($userId, $groupId, Usergroup::GROUP_USER_PERMISSION_READER);
810
                    }
811
812
                    break;
813
814
                case 'join':
815
                    $usergroupRepository->addUserToGroup($userId, $groupId);
816
817
                    break;
818
819
                case 'deny':
820
                    $usergroupRepository->removeUserFromGroup($userId, $groupId, false);
821
822
                    break;
823
824
                case 'leave':
825
                    $usergroupRepository->removeUserFromGroup($userId, $groupId);
826
827
                    break;
828
829
                case 'reply_message_group':
830
                    $title = $title ?: substr(strip_tags($content), 0, 50);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $title does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $content does not seem to be defined for all execution paths leading up to this point.
Loading history...
831
832
                    // no break
833
                case 'edit_message_group':
834
                case 'add_message_group':
835
                    $res = MessageManager::send_message(
836
                        $userId,
837
                        $title,
838
                        $content,
839
                        $structuredFiles,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $structuredFiles does not seem to be defined for all execution paths leading up to this point.
Loading history...
840
                        [],
841
                        $groupId,
842
                        $parentId,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $parentId does not seem to be defined for all execution paths leading up to this point.
Loading history...
843
                        $editMessageId,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $editMessageId does not seem to be defined for all execution paths leading up to this point.
Loading history...
844
                        0,
845
                        $userId,
846
                        false,
847
                        0,
848
                        false,
849
                        false,
850
                        Message::MESSAGE_TYPE_GROUP
851
                    );
852
853
                    break;
854
855
                case 'delete_message_group':
856
                    $messageId = $data['messageId'] ?? null;
857
858
                    if (!$messageId) {
859
                        return $this->json(['error' => 'Missing messageId parameter'], Response::HTTP_BAD_REQUEST);
860
                    }
861
862
                    $messageRepository->deleteTopicAndChildren($groupId, $messageId);
863
864
                    break;
865
866
                default:
867
                    return $this->json(['error' => 'Invalid action'], Response::HTTP_BAD_REQUEST);
868
            }
869
870
            $em->flush();
871
872
            return $this->json(['success' => 'Action completed successfully']);
873
        } catch (Exception $e) {
874
            return $this->json(['error' => $e->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
875
        }
876
    }
877
878
    #[Route('/user-action', name: 'chamilo_core_social_user_action')]
879
    public function user(
880
        Request $request,
881
        UserRepository $userRepository,
882
        MessageRepository $messageRepository,
883
        EntityManagerInterface $em
884
    ): JsonResponse {
885
        $data = json_decode($request->getContent(), true);
886
887
        $userId = $data['userId'] ?? null;
888
        $targetUserId = $data['targetUserId'] ?? null;
889
        $action = $data['action'] ?? null;
890
        $isMyFriend = $data['is_my_friend'] ?? false;
891
        $subject = $data['subject'] ?? '';
892
        $content = $data['content'] ?? '';
893
894
        if (!$userId || !$targetUserId || !$action) {
895
            return $this->json(['error' => 'Missing parameters']);
896
        }
897
898
        $currentUser = $userRepository->find($userId);
899
        $friendUser = $userRepository->find($targetUserId);
900
901
        if (null === $currentUser || null === $friendUser) {
902
            return $this->json(['error' => 'User not found']);
903
        }
904
905
        try {
906
            switch ($action) {
907
                case 'send_invitation':
908
                    $result = $messageRepository->sendInvitationToFriend($currentUser, $friendUser, $subject, $content);
909
                    if (!$result) {
910
                        return $this->json(['error' => 'Invitation already exists or could not be sent']);
911
                    }
912
913
                    break;
914
915
                case 'send_message':
916
                    $result = MessageManager::send_message($friendUser->getId(), $subject, $content);
917
918
                    break;
919
920
                case 'add_friend':
921
                    $relationType = $isMyFriend ? UserRelUser::USER_RELATION_TYPE_FRIEND : UserRelUser::USER_UNKNOWN;
922
923
                    $userRepository->relateUsers($currentUser, $friendUser, $relationType);
924
                    $userRepository->relateUsers($friendUser, $currentUser, $relationType);
925
926
                    $messageRepository->invitationAccepted($friendUser, $currentUser);
927
928
                    break;
929
930
                case 'deny_friend':
931
                    $messageRepository->invitationDenied($friendUser, $currentUser);
932
933
                    break;
934
935
                default:
936
                    return $this->json(['error' => 'Invalid action']);
937
            }
938
939
            $em->flush();
940
941
            return $this->json(['success' => 'Action completed successfully']);
942
        } catch (Exception $e) {
943
            return $this->json(['error' => $e->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
944
        }
945
    }
946
947
    #[Route('/user-relation/{currentUserId}/{profileUserId}', name: 'chamilo_core_social_get_user_relation')]
948
    public function getUserRelation(int $currentUserId, int $profileUserId, EntityManagerInterface $em): JsonResponse
949
    {
950
        $isAllowed = $this->checkUserRelationship($currentUserId, $profileUserId, $em);
951
952
        return $this->json([
953
            'isAllowed' => $isAllowed,
954
        ]);
955
    }
956
957
    #[Route('/online-status', name: 'chamilo_core_social_get_online_status', methods: ['POST'])]
958
    public function getOnlineStatus(Request $request, TrackEOnlineRepository $trackOnlineRepository): JsonResponse
959
    {
960
        $data = json_decode($request->getContent(), true);
961
        $userIds = $data['userIds'] ?? [];
962
963
        $onlineStatuses = [];
964
        foreach ($userIds as $userId) {
965
            $onlineStatuses[$userId] = $trackOnlineRepository->isUserOnline($userId);
966
        }
967
968
        return $this->json($onlineStatuses);
969
    }
970
971
    #[Route('/upload-group-picture/{groupId}', name: 'chamilo_core_social_upload_group_picture')]
972
    public function uploadGroupPicture(
973
        Request $request,
974
        int $groupId,
975
        UsergroupRepository $usergroupRepository,
976
        IllustrationRepository $illustrationRepository
977
    ): JsonResponse {
978
        $file = $request->files->get('picture');
979
        if ($file instanceof UploadedFile) {
980
            $userGroup = $usergroupRepository->find($groupId);
981
            $illustrationRepository->addIllustration($userGroup, $this->userHelper->getCurrent(), $file);
982
        }
983
984
        return new JsonResponse(['success' => 'Group and image saved successfully'], Response::HTTP_OK);
985
    }
986
987
    #[Route('/terms-restrictions/{userId}', name: 'chamilo_core_social_terms_restrictions')]
988
    public function checkTermsRestrictions(
989
        int $userId,
990
        UserRepository $userRepo,
991
        ExtraFieldRepository $extraFieldRepository,
992
        TranslatorInterface $translator,
993
        SettingsManager $settingsManager
994
    ): JsonResponse {
995
        /** @var User $user */
996
        $user = $userRepo->find($userId);
997
998
        if (!$user) {
0 ignored issues
show
introduced by
$user is of type Chamilo\CoreBundle\Entity\User, thus it always evaluated to true.
Loading history...
999
            return $this->json(['error' => 'User not found'], Response::HTTP_NOT_FOUND);
1000
        }
1001
1002
        $isAdmin = $user->hasRole('ROLE_ADMIN') || $user->hasRole('ROLE_SUPER_ADMIN');
1003
1004
        $termActivated = false;
1005
        $blockButton = false;
1006
        $infoMessage = '';
1007
1008
        if (!$isAdmin) {
1009
            if ('true' === $settingsManager->getSetting('ticket.show_terms_if_profile_completed')) {
1010
                $extraFieldValue = new ExtraFieldValue('user');
1011
                $value = $extraFieldValue->get_values_by_handler_and_field_variable($userId, 'termactivated');
1012
                if (isset($value['value'])) {
1013
                    $termActivated = !empty($value['value']) && 1 === (int) $value['value'];
1014
                }
1015
1016
                if (false === $termActivated) {
1017
                    $blockButton = true;
1018
                    $infoMessage .= $translator->trans('The terms and conditions have not yet been validated by your tutor.').'&nbsp;';
1019
                }
1020
1021
                if (!$user->isProfileCompleted()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $user->isProfileCompleted() of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
1022
                    $blockButton = true;
1023
                    $infoMessage .= $translator->trans('You must first fill your profile to enable the terms and conditions validation.');
1024
                }
1025
            }
1026
        }
1027
1028
        return $this->json([
1029
            'blockButton' => $blockButton,
1030
            'infoMessage' => $infoMessage,
1031
        ]);
1032
    }
1033
1034
    /**
1035
     * Formats a hierarchical structure of messages for display.
1036
     *
1037
     * This function takes an array of Message entities and recursively formats them into a hierarchical structure.
1038
     * Each message is formatted with details such as user information, creation date, content, and attachments.
1039
     * The function also assigns a level to each message based on its depth in the hierarchy for display purposes.
1040
     */
1041
    private function formatMessagesHierarchy(array $messages, UserRepository $userRepository, MessageAttachmentRepository $attachmentRepository, ?int $parentId = null, int $level = 0): array
1042
    {
1043
        $formattedMessages = [];
1044
1045
        /** @var Message $message */
1046
        foreach ($messages as $message) {
1047
            if (($message->getParent() ? $message->getParent()->getId() : null) === $parentId) {
1048
                $attachments = $message->getAttachments();
1049
                $attachmentsUrls = [];
1050
                $attachmentSize = 0;
1051
                if ($attachments) {
1052
                    /** @var MessageAttachment $attachment */
1053
                    foreach ($attachments as $attachment) {
1054
                        $attachmentsUrls[] = [
1055
                            'link' => $attachmentRepository->getResourceFileDownloadUrl($attachment),
1056
                            'filename' => $attachment->getFilename(),
1057
                            'size' => $attachment->getSize(),
1058
                        ];
1059
                        $attachmentSize += $attachment->getSize();
1060
                    }
1061
                }
1062
                $formattedMessage = [
1063
                    'id' => $message->getId(),
1064
                    'user' => $message->getSender()->getFullName(),
1065
                    'created' => $message->getSendDate()->format(DateTimeInterface::ATOM),
1066
                    'title' => $message->getTitle(),
1067
                    'content' => $message->getContent(),
1068
                    'parentId' => $message->getParent() ? $message->getParent()->getId() : null,
1069
                    'avatar' => $userRepository->getUserPicture($message->getSender()->getId()),
1070
                    'senderId' => $message->getSender()->getId(),
1071
                    'attachment' => $attachmentsUrls ?? null,
1072
                    'attachmentSize' => $attachmentSize > 0 ? $attachmentSize : null,
1073
                    'level' => $level,
1074
                ];
1075
1076
                $children = $this->formatMessagesHierarchy($messages, $userRepository, $attachmentRepository, $message->getId(), $level + 1);
1077
                if (!empty($children)) {
1078
                    $formattedMessage['children'] = $children;
1079
                }
1080
1081
                $formattedMessages[] = $formattedMessage;
1082
            }
1083
        }
1084
1085
        return $formattedMessages;
1086
    }
1087
1088
    /**
1089
     * Checks the relationship between the current user and another user.
1090
     *
1091
     * This method first checks for a direct relationship between the two users. If no direct relationship is found,
1092
     * it then checks for indirect relationships through common friends (friends of friends).
1093
     */
1094
    private function checkUserRelationship(int $currentUserId, int $otherUserId, EntityManagerInterface $em): bool
1095
    {
1096
        if ($currentUserId === $otherUserId) {
1097
            return true;
1098
        }
1099
1100
        $relation = $em->getRepository(UserRelUser::class)
1101
            ->findOneBy([
1102
                'relationType' => [
1103
                    UserRelUser::USER_RELATION_TYPE_FRIEND,
1104
                    UserRelUser::USER_RELATION_TYPE_GOODFRIEND,
1105
                ],
1106
                'friend' => $otherUserId,
1107
                'user' => $currentUserId,
1108
            ])
1109
        ;
1110
1111
        if (null !== $relation) {
1112
            return true;
1113
        }
1114
1115
        $friendsOfCurrentUser = $em->getRepository(UserRelUser::class)
1116
            ->findBy([
1117
                'relationType' => [
1118
                    UserRelUser::USER_RELATION_TYPE_FRIEND,
1119
                    UserRelUser::USER_RELATION_TYPE_GOODFRIEND,
1120
                ],
1121
                'user' => $currentUserId,
1122
            ])
1123
        ;
1124
1125
        foreach ($friendsOfCurrentUser as $friendRelation) {
1126
            $friendId = $friendRelation->getFriend()->getId();
1127
            $relationThroughFriend = $em->getRepository(UserRelUser::class)
1128
                ->findOneBy([
1129
                    'relationType' => [
1130
                        UserRelUser::USER_RELATION_TYPE_FRIEND,
1131
                        UserRelUser::USER_RELATION_TYPE_GOODFRIEND,
1132
                    ],
1133
                    'friend' => $otherUserId,
1134
                    'user' => $friendId,
1135
                ])
1136
            ;
1137
1138
            if (null !== $relationThroughFriend) {
1139
                return true;
1140
            }
1141
        }
1142
1143
        return false;
1144
    }
1145
1146
    /**
1147
     * Checks the chat status of a user based on their user ID. It verifies if the user's chat status
1148
     * is active (indicated by a status of 1).
1149
     */
1150
    private function checkUserStatus(int $userId, UserRepository $userRepository): bool
1151
    {
1152
        $userStatus = $userRepository->getExtraUserDataByField($userId, 'user_chat_status');
1153
1154
        return !empty($userStatus) && isset($userStatus['user_chat_status']) && 1 === (int) $userStatus['user_chat_status'];
1155
    }
1156
1157
    /**
1158
     * Retrieves the most recent legal terms for a specified language. If no terms are found for the given language,
1159
     * the function attempts to retrieve terms for the platform's default language. If terms are still not found,
1160
     * it defaults to English ('en_US').
1161
     */
1162
    private function getLastConditionByLanguage(LanguageRepository $languageRepo, string $isoCode, LegalRepository $legalTermsRepo, SettingsManager $settingsManager): ?Legal
1163
    {
1164
        $language = $languageRepo->findByIsoCode($isoCode);
1165
        $languageId = (int) $language->getId();
1166
        $term = $legalTermsRepo->getLastConditionByLanguage($languageId);
1167
        if (!$term) {
1168
            $defaultLanguage = $settingsManager->getSetting('language.platform_language');
1169
            $language = $languageRepo->findByIsoCode($defaultLanguage);
1170
            $languageId = (int) $language->getId();
1171
            $term = $legalTermsRepo->getLastConditionByLanguage((int) $languageId);
1172
            if (!$term) {
1173
                $language = $languageRepo->findByIsoCode('en_US');
1174
                $languageId = (int) $language->getId();
1175
                $term = $legalTermsRepo->getLastConditionByLanguage((int) $languageId);
1176
            }
1177
        }
1178
1179
        return $term;
1180
    }
1181
}
1182