Issues (1776)

src/AdvancedSubscriptionPlugin.php (5 issues)

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Session;
6
use Chamilo\CoreBundle\Framework\Container;
7
use Chamilo\CoreBundle\Hook\HookAdminBlock;
8
use Chamilo\CoreBundle\Hook\HookNotificationContent;
9
use Chamilo\CoreBundle\Hook\HookNotificationTitle;
10
use Chamilo\CoreBundle\Hook\HookWSRegistration;
11
use Chamilo\CoreBundle\Hook\Interfaces\HookPluginInterface;
12
13
/**
14
 * Class AdvancedSubscriptionPlugin
15
 * This class is used to add an advanced subscription allowing the admin to
16
 * create user queues requesting a subscribe to a session.
17
 */
18
class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface
19
{
20
    protected $strings;
21
    private $errorMessages;
22
23
    /**
24
     * Constructor.
25
     */
26
    public function __construct()
27
    {
28
        $parameters = [
29
            'yearly_cost_limit' => 'text',
30
            'yearly_hours_limit' => 'text',
31
            'yearly_cost_unit_converter' => 'text',
32
            'courses_count_limit' => 'text',
33
            'course_session_credit_year_start_date' => 'text',
34
            'ws_url' => 'text',
35
            'min_profile_percentage' => 'text',
36
            'check_induction' => 'boolean',
37
            'secret_key' => 'text',
38
            'terms_and_conditions' => 'wysiwyg',
39
        ];
40
41
        parent::__construct('1.0', 'Imanol Losada, Daniel Barreto', $parameters);
42
        $this->errorMessages = [];
43
    }
44
45
    /**
46
     * Instance the plugin.
47
     *
48
     * @staticvar null $result
49
     *
50
     * @return AdvancedSubscriptionPlugin
51
     */
52
    public static function create()
53
    {
54
        static $result = null;
55
56
        return $result ?: $result = new self();
57
    }
58
59
    /**
60
     * Install the plugin.
61
     */
62
    public function install()
63
    {
64
        $this->installDatabase();
65
        $this->addAreaField();
66
        $this->installHook();
67
    }
68
69
    /**
70
     * Uninstall the plugin.
71
     */
72
    public function uninstall()
73
    {
74
        //$setting = api_get_setting('advanced_subscription');
75
        $setting = false;
76
        if (!empty($setting)) {
77
            $this->uninstallHook();
78
            // Note: Keeping area field data is intended so it will not be removed
79
            $this->uninstallDatabase();
80
        }
81
    }
82
83
    /**
84
     * Get the error messages list.
85
     *
86
     * @return array The message list
87
     */
88
    public function getErrorMessages()
89
    {
90
        return $this->errorMessages;
91
    }
92
93
    /**
94
     * Check if is allowed subscribe to open session.
95
     *
96
     * @param array $params WS params
97
     *
98
     * @return bool
99
     */
100
    public function isAllowedSubscribeToOpenSession($params)
101
    {
102
        $self = self::create();
103
        $wsUrl = $self->get('ws_url');
104
        $profileCompleted = 0;
105
        if (!empty($wsUrl)) {
106
            $client = new SoapClient(
107
                null,
108
                ['location' => $wsUrl, 'uri' => $wsUrl]
109
            );
110
            $userInfo = api_get_user_info(
111
                $params['user_id'],
112
                false,
113
                false,
114
                true
115
            );
116
117
            try {
118
                $profileCompleted = $client->__soapCall(
119
                    'getProfileCompletionPercentage',
120
                    $userInfo['extra']['drupal_user_id']
121
                );
122
            } catch (\Exception $e) {
123
                $profileCompleted = 0;
124
            }
125
        } elseif (isset($params['profile_completed'])) {
126
            $profileCompleted = (float) $params['profile_completed'];
127
        }
128
        $profileCompletedMin = (float) $self->get('min_profile_percentage');
129
130
        if ($profileCompleted < $profileCompletedMin) {
131
            $this->errorMessages[] = sprintf(
132
                $this->get_lang('AdvancedSubscriptionProfileIncomplete'),
133
                $profileCompletedMin,
134
                $profileCompleted
135
            );
136
        }
137
138
        $vacancy = $self->getVacancy($params['session_id']);
139
        $sessionInfo = api_get_session_info($params['session_id']);
140
141
        if ($sessionInfo['nbr_users'] >= $vacancy) {
142
            $this->errorMessages[] = sprintf(
143
                $this->get_lang('SessionXWithoutVacancies'),
144
                $sessionInfo['name']
145
            );
146
        }
147
148
        return empty($this->errorMessages);
149
    }
150
151
    /**
152
     * Return true if user is allowed to be added to queue for session subscription.
153
     *
154
     * @param int   $userId
155
     * @param array $params        MUST have keys:
156
     *                             "is_connected" Indicate if the user is online on external web
157
     *                             "profile_completed" Percentage of completed profile, given by WS
158
     * @param bool  $collectErrors Optional. Default is false. Whether collect all errors or throw exeptions
159
     *
160
     * @throws Exception
161
     *
162
     * @return bool
163
     */
164
    public function isAllowedToDoRequest($userId, $params = [], $collectErrors = false)
165
    {
166
        $plugin = self::create();
167
        $wsUrl = $plugin->get('ws_url');
168
        // Student always is connected
169
        $isConnected = true;
170
171
        if (!$isConnected) {
172
            $this->errorMessages[] = $this->get_lang('AdvancedSubscriptionNotConnected');
173
174
            if (!$collectErrors) {
175
                throw new \Exception($this->get_lang('AdvancedSubscriptionNotConnected'));
176
            }
177
        }
178
179
        $profileCompletedMin = (float) $plugin->get('min_profile_percentage');
180
        $profileCompleted = 0;
181
182
        if (is_string($wsUrl) && !empty($wsUrl)) {
183
            $options = [
184
                'location' => $wsUrl,
185
                'uri' => $wsUrl,
186
            ];
187
            $client = new SoapClient(null, $options);
188
            $userInfo = api_get_user_info($userId);
189
190
            try {
191
                $profileCompleted = $client->__soapCall('getProfileCompletionPercentage', $userInfo['extra']['drupal_user_id']);
192
            } catch (\Exception $e) {
193
                $profileCompleted = 0;
194
            }
195
        } elseif (isset($params['profile_completed'])) {
196
            $profileCompleted = (float) $params['profile_completed'];
197
        }
198
199
        if ($profileCompleted < $profileCompletedMin) {
200
            $errorMessage = sprintf(
201
                $this->get_lang('AdvancedSubscriptionProfileIncomplete'),
202
                $profileCompletedMin,
203
                $profileCompleted
204
            );
205
206
            $this->errorMessages[] = $errorMessage;
207
208
            if (!$collectErrors) {
209
                throw new \Exception($errorMessage);
210
            }
211
        }
212
213
        $yearlyCostLimit = $plugin->get('yearly_cost_limit');
214
        $maxCost = $plugin->get('yearly_cost_unit_converter');
215
        $maxCost *= $yearlyCostLimit;
216
        $userCost = 0;
217
        $now = new DateTime(api_get_utc_datetime());
218
        $newYearDate = $plugin->get('course_session_credit_year_start_date');
219
        $newYearDate = !empty($newYearDate) ?
220
            new \DateTime($newYearDate.$now->format('/Y')) : $now;
221
        $extra = new ExtraFieldValue('session');
222
        $joinSessionTable = Database::get_main_table(TABLE_MAIN_SESSION_USER).' su INNER JOIN '.
223
            Database::get_main_table(TABLE_MAIN_SESSION).' s ON s.id = su.session_id';
224
        $whereSessionParams = 'su.relation_type = ? AND s.access_start_date >= ? AND su.user_id = ?';
225
        $whereSessionParamsValues = [
226
            Session::STUDENT,
227
            $newYearDate->format('Y-m-d'),
228
            $userId,
229
        ];
230
        $whereSession = [
231
            'where' => [
232
                $whereSessionParams => $whereSessionParamsValues,
233
            ],
234
        ];
235
        $selectSession = 's.id AS id';
236
        $sessions = Database::select(
237
            $selectSession,
238
            $joinSessionTable,
239
            $whereSession
240
        );
241
242
        $expendedTimeMax = $plugin->get('yearly_hours_limit');
243
        $expendedTime = 0;
244
245
        if (is_array($sessions) && count($sessions) > 0) {
246
            foreach ($sessions as $session) {
247
                $costField = $extra->get_values_by_handler_and_field_variable($session['id'], 'cost');
248
                $userCost += $costField['value'];
249
                $teachingHoursField = $extra->get_values_by_handler_and_field_variable($session['id'], 'teaching_hours');
250
                $expendedTime += $teachingHoursField['value'];
251
            }
252
        }
253
254
        if (isset($params['sessionId'])) {
255
            $costField = $extra->get_values_by_handler_and_field_variable($params['sessionId'], 'cost');
256
            $userCost += $costField['value'];
257
258
            $teachingHoursField = $extra->get_values_by_handler_and_field_variable($params['sessionId'], 'teaching_hours');
259
            $expendedTime += $teachingHoursField['value'];
260
        }
261
262
        if ($maxCost <= $userCost) {
263
            $errorMessage = sprintf(
264
                $this->get_lang('AdvancedSubscriptionCostXLimitReached'),
265
                $yearlyCostLimit
266
            );
267
268
            $this->errorMessages[] = $errorMessage;
269
270
            if (!$collectErrors) {
271
                throw new \Exception($errorMessage);
272
            }
273
        }
274
275
        if ($expendedTimeMax <= $expendedTime) {
276
            $errorMessage = sprintf(
277
                $this->get_lang('AdvancedSubscriptionTimeXLimitReached'),
278
                $expendedTimeMax
279
            );
280
281
            $this->errorMessages[] = $errorMessage;
282
283
            if (!$collectErrors) {
284
                throw new \Exception($errorMessage);
285
            }
286
        }
287
288
        $expendedNumMax = $plugin->get('courses_count_limit');
289
        $expendedNum = count($sessions);
290
291
        if ($expendedNumMax <= $expendedNum) {
292
            $errorMessage = sprintf(
293
                $this->get_lang('AdvancedSubscriptionCourseXLimitReached'),
294
                $expendedNumMax
295
            );
296
297
            $this->errorMessages[] = $errorMessage;
298
299
            if (!$collectErrors) {
300
                throw new \Exception($errorMessage);
301
            }
302
        }
303
304
        $checkInduction = $plugin->get('check_induction');
305
        $numberOfApprovedInductionSessions = $this->getApprovedInductionSessions($userId);
306
        $completedInduction = $numberOfApprovedInductionSessions > 0;
307
308
        if ('true' == $checkInduction && !$completedInduction) {
309
            $this->errorMessages[] = $this->get_lang('AdvancedSubscriptionIncompleteInduction');
310
311
            if (!$collectErrors) {
312
                throw new \Exception($this->get_lang('AdvancedSubscriptionIncompleteInduction'));
313
            }
314
        }
315
316
        return empty($this->errorMessages);
317
    }
318
319
    /**
320
     * Register a user into a queue for a session.
321
     *
322
     * @param $userId
323
     * @param $sessionId
324
     *
325
     * @return bool|int
326
     */
327
    public function addToQueue($userId, $sessionId)
328
    {
329
        // Filter input variables
330
        $userId = (int) $userId;
331
        $sessionId = (int) $sessionId;
332
        $now = api_get_utc_datetime();
333
        $advancedSubscriptionQueueTable = Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE);
334
        $attributes = [
335
            'session_id' => $sessionId,
336
            'user_id' => $userId,
337
            'status' => 0,
338
            'created_at' => $now,
339
            'updated_at' => null,
340
        ];
341
342
        return Database::insert($advancedSubscriptionQueueTable, $attributes);
343
    }
344
345
    /**
346
     * Register message with type and status.
347
     *
348
     * @param $mailId
349
     * @param $userId
350
     * @param $sessionId
351
     *
352
     * @return bool|int
353
     */
354
    public function saveLastMessage($mailId, $userId, $sessionId)
355
    {
356
        // Filter variables
357
        $mailId = (int) $mailId;
358
        $userId = (int) $userId;
359
        $sessionId = (int) $sessionId;
360
        $queueTable = Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE);
361
        $attributes = [
362
            'last_message_id' => $mailId,
363
            'updated_at' => api_get_utc_datetime(),
364
        ];
365
366
        return Database::update(
367
            $queueTable,
368
            $attributes,
369
            ['user_id = ? AND session_id = ?' => [$userId, $sessionId]]
370
        );
371
    }
372
373
    /**
374
     * Check for requirements and register user into queue.
375
     *
376
     * @param $userId
377
     * @param $sessionId
378
     * @param $params
379
     *
380
     * @return bool|string
381
     */
382
    public function startSubscription($userId, $sessionId, $params)
383
    {
384
        $result = 'Params not found';
385
        if (!empty($sessionId) && !empty($userId)) {
386
            $plugin = self::create();
387
388
            try {
389
                if ($plugin->isAllowedToDoRequest($userId, $params)) {
390
                    $result = (bool) $plugin->addToQueue($userId, $sessionId);
391
                } else {
392
                    throw new \Exception($this->get_lang('AdvancedSubscriptionNotMoreAble'));
393
                }
394
            } catch (Exception $e) {
395
                $result = $e->getMessage();
396
            }
397
        }
398
399
        return $result;
400
    }
401
402
    /**
403
     * Send message for the student subscription approval to a specific session.
404
     *
405
     * @param int|array $studentId
406
     * @param int       $receiverId
407
     * @param string    $subject
408
     * @param string    $content
409
     * @param int       $sessionId
410
     * @param bool      $save
411
     * @param array     $fileAttachments
412
     *
413
     * @return bool|int
414
     */
415
    public function sendMailMessage(
416
        $studentId,
417
        $receiverId,
418
        $subject,
419
        $content,
420
        $sessionId,
421
        $save = false,
422
        $fileAttachments = []
423
    ) {
424
        if (!empty($fileAttachments) &&
425
            is_array($fileAttachments) &&
426
            isset($fileAttachments['files']) &&
427
            isset($fileAttachments['comments'])
428
        ) {
429
            $mailId = MessageManager::send_message(
430
                $receiverId,
431
                $subject,
432
                $content,
433
                $fileAttachments['files'],
434
                $fileAttachments['comments']
435
            );
436
        } else {
437
            $mailId = MessageManager::send_message(
438
                $receiverId,
439
                $subject,
440
                $content
441
            );
442
        }
443
444
        if ($save && !empty($mailId)) {
445
            // Save as sent message
446
            if (is_array($studentId) && !empty($studentId)) {
447
                foreach ($studentId as $student) {
448
                    $this->saveLastMessage($mailId, $student['user_id'], $sessionId);
449
                }
450
            } else {
451
                $studentId = (int) $studentId;
452
                $this->saveLastMessage($mailId, $studentId, $sessionId);
453
            }
454
        } elseif (!empty($mailId)) {
455
            // Update queue row, updated_at
456
            Database::update(
457
                Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE),
458
                [
459
                    'updated_at' => api_get_utc_datetime(),
460
                ],
461
                [
462
                    'user_id = ? AND session_id = ?' => [$studentId, $sessionId],
463
                ]
464
            );
465
        }
466
467
        return $mailId;
468
    }
469
470
    /**
471
     * Check if session is open for subscription.
472
     *
473
     * @param $sessionId
474
     * @param string $fieldVariable
475
     *
476
     * @return bool
477
     */
478
    public function isSessionOpen($sessionId, $fieldVariable = 'is_open_session')
479
    {
480
        $extraFieldValue = new ExtraFieldValue('session');
481
        $result = $extraFieldValue->get_values_by_handler_and_field_variable(
482
            $sessionId,
483
            $fieldVariable
484
        );
485
486
        $isOpen = false;
487
        if (!empty($result)) {
488
            $isOpen = (bool) $result['value'];
489
        }
490
491
        return $isOpen;
492
    }
493
494
    /**
495
     * Check if user is in the session's target group based on its area.
496
     *
497
     * @param $userId
498
     * @param $sessionId
499
     * @param string $userFieldVariable
500
     * @param string $sessionFieldVariable
501
     *
502
     * @return bool
503
     */
504
    public function isUserInTargetGroup(
505
        $userId,
506
        $sessionId,
507
        $userFieldVariable = 'area',
508
        $sessionFieldVariable = 'target'
509
    ) {
510
        $extraSessionFieldValue = new ExtraFieldValue('session');
511
        $sessionTarget = $extraSessionFieldValue->get_values_by_handler_and_field_variable(
512
            $sessionId,
513
            $sessionFieldVariable
514
        );
515
        $extraUserFieldValue = new ExtraFieldValue('user');
516
        $userArea = $extraUserFieldValue->get_values_by_handler_and_field_variable(
517
            $userId,
518
            $userFieldVariable
519
        );
520
        $isInTargetGroup = false;
521
        if (isset($sessionTarget) && (!empty($sessionTarget)) && 'minedu' == $sessionTarget['value']) {
522
            if ('MINEDU' == substr($userArea['value'], 0, 6)) {
523
                $isInTargetGroup = true;
524
            }
525
        }
526
        if (isset($sessionTarget) && (!empty($sessionTarget)) && 'regiones' == $sessionTarget['value']) {
527
            if (('UGEL' == substr($userArea['value'], 0, 4)) || ('DRE' == substr($userArea['value'], 0, 3))) {
528
                $isInTargetGroup = true;
529
            }
530
        }
531
532
        return $isInTargetGroup;
533
    }
534
535
    /**
536
     * Update the queue status for subscription approval rejected or accepted.
537
     *
538
     * @param $params
539
     * @param $newStatus
540
     *
541
     * @return bool
542
     */
543
    public function updateQueueStatus($params, $newStatus)
544
    {
545
        $newStatus = (int) $newStatus;
546
        $res = false;
547
548
        if (isset($params['queue']['id'])) {
549
            $where = [
550
                'id = ?' => (int) ($params['queue']['id']),
551
            ];
552
        } elseif (isset($params['studentUserId']) && isset($params['sessionId'])) {
553
            $where = [
554
                'user_id = ? AND session_id = ? AND status <> ? AND status <> ?' => [
555
                    (int) ($params['studentUserId']),
556
                    (int) ($params['sessionId']),
557
                    $newStatus,
558
                    ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED,
559
                ],
560
            ];
561
        }
562
        if (isset($where)) {
563
            $res = (bool) Database::update(
564
                Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE),
565
                [
566
                    'status' => $newStatus,
567
                    'updated_at' => api_get_utc_datetime(),
568
                ],
569
                $where
570
            );
571
        }
572
573
        return $res;
574
    }
575
576
    /**
577
     * Render and send mail by defined advanced subscription action.
578
     *
579
     * @param $data
580
     * @param $actionType
581
     *
582
     * @return array
583
     */
584
    public function sendMail($data, $actionType)
585
    {
586
        $template = new Template($this->get_lang('plugin_title'));
587
        $template->assign('data', $data);
588
        $templateParams = [
589
            'user',
590
            'student',
591
            'students',
592
            'superior',
593
            'admins',
594
            'session',
595
            'signature',
596
            'admin_view_url',
597
            'acceptUrl',
598
            'rejectUrl',
599
        ];
600
        foreach ($templateParams as $templateParam) {
601
            $template->assign($templateParam, $data[$templateParam]);
602
        }
603
        $mailIds = [];
604
        switch ($actionType) {
605
            case ADVANCED_SUBSCRIPTION_ACTION_STUDENT_REQUEST:
606
                // Mail to student
607
                $mailIds['render'] = $this->sendMailMessage(
608
                    $data['studentUserId'],
609
                    $data['student']['user_id'],
610
                    $this->get_lang('MailStudentRequest'),
611
                    $template->fetch('/advanced_subscription/views/student_notice_student.tpl'),
612
                    $data['sessionId'],
613
                    true
614
                );
615
                // Mail to superior
616
                $mailIds[] = $this->sendMailMessage(
617
                    $data['studentUserId'],
618
                    $data['superior']['user_id'],
619
                    $this->get_lang('MailStudentRequest'),
620
                    $template->fetch('/advanced_subscription/views/student_notice_superior.tpl'),
621
                    $data['sessionId']
622
                );
623
624
                break;
625
            case ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_APPROVE:
626
                // Mail to student
627
                $mailIds[] = $this->sendMailMessage(
628
                    $data['studentUserId'],
629
                    $data['student']['user_id'],
630
                    $this->get_lang('MailBossAccept'),
631
                    $template->fetch('/advanced_subscription/views/superior_accepted_notice_student.tpl'),
632
                    $data['sessionId'],
633
                    true
634
                );
635
                // Mail to superior
636
                $mailIds['render'] = $this->sendMailMessage(
637
                    $data['studentUserId'],
638
                    $data['superior']['user_id'],
639
                    $this->get_lang('MailBossAccept'),
640
                    $template->fetch('/advanced_subscription/views/superior_accepted_notice_superior.tpl'),
641
                    $data['sessionId']
642
                );
643
                // Mail to admin
644
                foreach ($data['admins'] as $adminId => $admin) {
645
                    $template->assign('admin', $admin);
646
                    $mailIds[] = $this->sendMailMessage(
647
                        $data['studentUserId'],
648
                        $adminId,
649
                        $this->get_lang('MailBossAccept'),
650
                        $template->fetch('/advanced_subscription/views/superior_accepted_notice_admin.tpl'),
651
                        $data['sessionId']
652
                    );
653
                }
654
655
                break;
656
            case ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_DISAPPROVE:
657
                // Mail to student
658
                $mailIds[] = $this->sendMailMessage(
659
                    $data['studentUserId'],
660
                    $data['student']['user_id'],
661
                    $this->get_lang('MailBossReject'),
662
                    $template->fetch('/advanced_subscription/views/superior_rejected_notice_student.tpl'),
663
                    $data['sessionId'],
664
                    true
665
                );
666
                // Mail to superior
667
                $mailIds['render'] = $this->sendMailMessage(
668
                    $data['studentUserId'],
669
                    $data['superior']['user_id'],
670
                    $this->get_lang('MailBossReject'),
671
                    $template->fetch('/advanced_subscription/views/superior_rejected_notice_superior.tpl'),
672
                    $data['sessionId']
673
                );
674
675
                break;
676
            case ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_SELECT:
677
                // Mail to student
678
                $mailIds[] = $this->sendMailMessage(
679
                    $data['studentUserId'],
680
                    $data['student']['user_id'],
681
                    $this->get_lang('MailStudentRequestSelect'),
682
                    $template->fetch('/advanced_subscription/views/student_notice_student.tpl'),
683
                    $data['sessionId'],
684
                    true
685
                );
686
                // Mail to superior
687
                $mailIds['render'] = $this->sendMailMessage(
688
                    $data['studentUserId'],
689
                    $data['superior']['user_id'],
690
                    $this->get_lang('MailStudentRequestSelect'),
691
                    $template->fetch('/advanced_subscription/views/student_notice_superior.tpl'),
692
                    $data['sessionId']
693
                );
694
695
                break;
696
            case ADVANCED_SUBSCRIPTION_ACTION_ADMIN_APPROVE:
697
                $fileAttachments = [];
698
                if (api_get_plugin_setting('courselegal', 'tool_enable')) {
699
                    $courseLegal = CourseLegalPlugin::create();
700
                    $courses = SessionManager::get_course_list_by_session_id($data['sessionId']);
701
                    $course = current($courses);
702
                    $data['courseId'] = $course['id'];
703
                    $data['course'] = api_get_course_info_by_id($data['courseId']);
704
                    $termsAndConditions = $courseLegal->getData($data['courseId'], $data['sessionId']);
705
                    $termsAndConditions = $termsAndConditions['content'];
706
                    $termsAndConditions = $this->renderTemplateString($termsAndConditions, $data);
707
                    $tpl = new Template(get_lang('Terms and Conditions'));
708
                    $tpl->assign('session', $data['session']);
709
                    $tpl->assign('student', $data['student']);
710
                    $tpl->assign('sessionId', $data['sessionId']);
711
                    $tpl->assign('termsContent', $termsAndConditions);
712
                    $termsAndConditions = $tpl->fetch('/advanced_subscription/views/terms_and_conditions_to_pdf.tpl');
713
                    $pdf = new PDF();
714
                    $filename = 'terms'.sha1(rand(0, 99999));
715
                    $pdf->content_to_pdf($termsAndConditions, null, $filename, null, 'F');
716
                    $fileAttachments['file'][] = [
717
                        'name' => $filename.'.pdf',
718
                        'application/pdf' => $filename.'.pdf',
719
                        'tmp_name' => api_get_path(SYS_ARCHIVE_PATH).$filename.'.pdf',
720
                        'error' => UPLOAD_ERR_OK,
721
                        'size' => filesize(api_get_path(SYS_ARCHIVE_PATH).$filename.'.pdf'),
722
                    ];
723
                    $fileAttachments['comments'][] = get_lang('Terms and Conditions');
724
                }
725
                // Mail to student
726
                $mailIds[] = $this->sendMailMessage(
727
                    $data['studentUserId'],
728
                    $data['student']['user_id'],
729
                    $this->get_lang('MailAdminAccept'),
730
                    $template->fetch('/advanced_subscription/views/admin_accepted_notice_student.tpl'),
731
                    $data['sessionId'],
732
                    true,
733
                    $fileAttachments
734
                );
735
                // Mail to superior
736
                $mailIds[] = $this->sendMailMessage(
737
                    $data['studentUserId'],
738
                    $data['superior']['user_id'],
739
                    $this->get_lang('MailAdminAccept'),
740
                    $template->fetch('/advanced_subscription/views/admin_accepted_notice_superior.tpl'),
741
                    $data['sessionId']
742
                );
743
                // Mail to admin
744
                $adminId = $data['currentUserId'];
745
                $template->assign('admin', $data['admins'][$adminId]);
746
                $mailIds['render'] = $this->sendMailMessage(
747
                    $data['studentUserId'],
748
                    $adminId,
749
                    $this->get_lang('MailAdminAccept'),
750
                    $template->fetch('/advanced_subscription/views/admin_accepted_notice_admin.tpl'),
751
                    $data['sessionId']
752
                );
753
754
                break;
755
            case ADVANCED_SUBSCRIPTION_ACTION_ADMIN_DISAPPROVE:
756
                // Mail to student
757
                $mailIds[] = $this->sendMailMessage(
758
                    $data['studentUserId'],
759
                    $data['student']['user_id'],
760
                    $this->get_lang('MailAdminReject'),
761
                    $template->fetch('/advanced_subscription/views/admin_rejected_notice_student.tpl'),
762
                    $data['sessionId'],
763
                    true
764
                );
765
                // Mail to superior
766
                $mailIds[] = $this->sendMailMessage(
767
                    $data['studentUserId'],
768
                    $data['superior']['user_id'],
769
                    $this->get_lang('MailAdminReject'),
770
                    $template->fetch('/advanced_subscription/views/admin_rejected_notice_superior.tpl'),
771
                    $data['sessionId']
772
                );
773
                // Mail to admin
774
                $adminId = $data['currentUserId'];
775
                $template->assign('admin', $data['admins'][$adminId]);
776
                $mailIds['render'] = $this->sendMailMessage(
777
                    $data['studentUserId'],
778
                    $adminId,
779
                    $this->get_lang('MailAdminReject'),
780
                    $template->fetch('/advanced_subscription/views/admin_rejected_notice_admin.tpl'),
781
                    $data['sessionId']
782
                );
783
784
                break;
785
            case ADVANCED_SUBSCRIPTION_ACTION_STUDENT_REQUEST_NO_BOSS:
786
                // Mail to student
787
                $mailIds['render'] = $this->sendMailMessage(
788
                    $data['studentUserId'],
789
                    $data['student']['user_id'],
790
                    $this->get_lang('MailStudentRequestNoBoss'),
791
                    $template->fetch('/advanced_subscription/views/student_no_superior_notice_student.tpl'),
792
                    $data['sessionId'],
793
                    true
794
                );
795
                // Mail to admin
796
                foreach ($data['admins'] as $adminId => $admin) {
797
                    $template->assign('admin', $admin);
798
                    $mailIds[] = $this->sendMailMessage(
799
                        $data['studentUserId'],
800
                        $adminId,
801
                        $this->get_lang('MailStudentRequestNoBoss'),
802
                        $template->fetch('/advanced_subscription/views/student_no_superior_notice_admin.tpl'),
803
                        $data['sessionId']
804
                    );
805
                }
806
807
                break;
808
            case ADVANCED_SUBSCRIPTION_ACTION_REMINDER_STUDENT:
809
                $mailIds['render'] = $this->sendMailMessage(
810
                    $data['student']['user_id'],
811
                    $data['student']['user_id'],
812
                    $this->get_lang('MailRemindStudent'),
813
                    $template->fetch('/advanced_subscription/views/reminder_notice_student.tpl'),
814
                    $data['sessionId'],
815
                    true
816
                );
817
818
                break;
819
            case ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR:
820
                $mailIds['render'] = $this->sendMailMessage(
821
                    $data['students'],
822
                    $data['superior']['user_id'],
823
                    $this->get_lang('MailRemindSuperior'),
824
                    $template->fetch('/advanced_subscription/views/reminder_notice_superior.tpl'),
825
                    $data['sessionId']
826
                );
827
828
                break;
829
            case ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR_MAX:
830
                $mailIds['render'] = $this->sendMailMessage(
831
                    $data['students'],
832
                    $data['superior']['user_id'],
833
                    $this->get_lang('MailRemindSuperior'),
834
                    $template->fetch('/advanced_subscription/views/reminder_notice_superior_max.tpl'),
835
                    $data['sessionId']
836
                );
837
838
                break;
839
            case ADVANCED_SUBSCRIPTION_ACTION_REMINDER_ADMIN:
840
                // Mail to admin
841
                foreach ($data['admins'] as $adminId => $admin) {
842
                    $template->assign('admin', $admin);
843
                    $mailIds[] = $this->sendMailMessage(
844
                        $data['students'],
845
                        $adminId,
846
                        $this->get_lang('MailRemindAdmin'),
847
                        $template->fetch('/advanced_subscription/views/reminder_notice_admin.tpl'),
848
                        $data['sessionId']
849
                    );
850
                }
851
852
                break;
853
            default:
854
                break;
855
        }
856
857
        return $mailIds;
858
    }
859
860
    /**
861
     * Count the users in queue filtered by params (sessions, status).
862
     *
863
     * @param array $params Input array containing the set of
864
     *                      session and status to count from queue
865
     *                      e.g:
866
     *                      array('sessions' => array(215, 218, 345, 502),
867
     *                      'status' => array(0, 1, 2))
868
     *
869
     * @return int
870
     */
871
    public function countQueueByParams($params)
872
    {
873
        $count = 0;
874
        if (!empty($params) && is_array($params)) {
875
            $advancedSubscriptionQueueTable = Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE);
876
            $where['1 = ? '] = 1;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$where was never initialized. Although not strictly required by PHP, it is generally a good practice to add $where = array(); before regardless.
Loading history...
877
            if (isset($params['sessions']) && is_array($params['sessions'])) {
878
                foreach ($params['sessions'] as &$sessionId) {
879
                    $sessionId = (int) $sessionId;
880
                }
881
                $where['AND session_id IN ( ? ) '] = implode($params['sessions']);
882
            }
883
            if (isset($params['status']) && is_array($params['status'])) {
884
                foreach ($params['status'] as &$status) {
885
                    $status = (int) $status;
886
                }
887
                $where['AND status IN ( ? ) '] = implode($params['status']);
888
            }
889
            $where['where'] = $where;
890
            $count = Database::select('COUNT(*)', $advancedSubscriptionQueueTable, $where);
891
            $count = $count[0]['COUNT(*)'];
892
        }
893
894
        return $count;
895
    }
896
897
    /**
898
     * This method will call the Hook management insertHook to add Hook observer from this plugin.
899
     */
900
    public function installHook()
901
    {
902
        $hookObserver = HookAdvancedSubscription::create();
903
904
        $hookFactory = Container::$container->get('chamilo_core.hook_factory');
0 ignored issues
show
The method get() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

904
        /** @scrutinizer ignore-call */ 
905
        $hookFactory = Container::$container->get('chamilo_core.hook_factory');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
905
        $hookFactory->build(HookAdminBlock::class)->attach($hookObserver);
906
        $hookFactory->build(HookWSRegistration::class)->attach($hookObserver);
907
        $hookFactory->build(HookNotificationContent::class)->attach($hookObserver);
908
        $hookFactory->build(HookNotificationTitle::class)->attach($hookObserver);
909
    }
910
911
    /**
912
     * This method will call the Hook management deleteHook to disable Hook observer from this plugin.
913
     */
914
    public function uninstallHook()
915
    {
916
        $hookObserver = HookAdvancedSubscription::create();
917
918
        $hookFactory = Container::$container->get('chamilo_core.hook_factory');
919
        $hookFactory->build(HookAdminBlock::class)->detach($hookObserver);
920
        $hookFactory->build(HookWSRegistration::class)->detach($hookObserver);
921
        $hookFactory->build(HookNotificationContent::class)->detach($hookObserver);
922
        $hookFactory->build(HookNotificationTitle::class)->detach($hookObserver);
923
    }
924
925
    /**
926
     * Return the status from user in queue to session subscription.
927
     *
928
     * @param int $userId
929
     * @param int $sessionId
930
     *
931
     * @return bool|int
932
     */
933
    public function getQueueStatus($userId, $sessionId)
934
    {
935
        $userId = (int) $userId;
936
        $sessionId = (int) $sessionId;
937
        if (!empty($userId) && !empty($sessionId)) {
938
            $queueTable = Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE);
939
            $row = Database::select(
940
                'status',
941
                $queueTable,
942
                [
943
                    'where' => [
944
                        'user_id = ? AND session_id = ?' => [$userId, $sessionId],
945
                    ],
946
                ]
947
            );
948
949
            if (1 == count($row)) {
950
                return $row[0]['status'];
951
            } else {
952
                return ADVANCED_SUBSCRIPTION_QUEUE_STATUS_NO_QUEUE;
953
            }
954
        }
955
956
        return false;
957
    }
958
959
    /**
960
     * Return the remaining vacancy.
961
     *
962
     * @param $sessionId
963
     *
964
     * @return bool|int
965
     */
966
    public function getVacancy($sessionId)
967
    {
968
        if (!empty($sessionId)) {
969
            $extra = new ExtraFieldValue('session');
970
            $var = $extra->get_values_by_handler_and_field_variable(
971
                $sessionId,
972
                'vacancies'
973
            );
974
            $vacancy = (int) ($var['value']);
975
            if (!empty($vacancy)) {
976
                $vacancy -= $this->countQueueByParams(
977
                    [
978
                        'sessions' => [$sessionId],
979
                        'status' => [ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED],
980
                    ]
981
                );
982
                if ($vacancy >= 0) {
983
                    return $vacancy;
984
                } else {
985
                    return 0;
986
                }
987
            }
988
        }
989
990
        return false;
991
    }
992
993
    /**
994
     * Return the session details data from a session ID (including the extra
995
     * fields used for the advanced subscription mechanism).
996
     *
997
     * @param $sessionId
998
     *
999
     * @return bool|mixed
1000
     */
1001
    public function getSessionDetails($sessionId)
1002
    {
1003
        if (!empty($sessionId)) {
1004
            // Assign variables
1005
            $fieldsArray = [
1006
                'code',
1007
                'cost',
1008
                'place',
1009
                'allow_visitors',
1010
                'teaching_hours',
1011
                'brochure',
1012
                'banner',
1013
            ];
1014
            $extraField = new ExtraField('session');
1015
            // Get session fields
1016
            $fieldList = $extraField->get_all([
1017
                'variable IN ( ?, ?, ?, ?, ?, ?, ? )' => $fieldsArray,
1018
            ]);
1019
            // Index session fields
1020
            $fields = [];
1021
            foreach ($fieldList as $field) {
1022
                $fields[$field['id']] = $field['variable'];
1023
            }
1024
1025
            $mergedArray = array_merge([$sessionId], array_keys($fields));
1026
1027
            $sql = 'SELECT * FROM '.Database::get_main_table(TABLE_EXTRA_FIELD_VALUES).'
1028
                    WHERE item_id = %d AND field_id IN (%d, %d, %d, %d, %d, %d, %d)';
1029
            $sql = vsprintf($sql, $mergedArray);
1030
            $sessionFieldValueList = Database::query($sql);
1031
            while ($sessionFieldValue = Database::fetch_assoc($sessionFieldValueList)) {
1032
                // Check if session field value is set in session field list
1033
                if (isset($fields[$sessionFieldValue['field_id']])) {
1034
                    $var = $fields[$sessionFieldValue['field_id']];
1035
                    $val = $sessionFieldValue['value'];
1036
                    // Assign session field value to session
1037
                    $sessionArray[$var] = $val;
1038
                }
1039
            }
1040
            $sessionArray['description'] = SessionManager::getDescriptionFromSessionId($sessionId);
1041
1042
            if (isset($sessionArray['brochure'])) {
1043
                $sessionArray['brochure'] = api_get_path(WEB_UPLOAD_PATH).$sessionArray['brochure'];
0 ignored issues
show
The constant WEB_UPLOAD_PATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1044
            }
1045
            if (isset($sessionArray['banner'])) {
1046
                $sessionArray['banner'] = api_get_path(WEB_UPLOAD_PATH).$sessionArray['banner'];
1047
            }
1048
1049
            return $sessionArray;
1050
        }
1051
1052
        return false;
1053
    }
1054
1055
    /**
1056
     * Get status message.
1057
     *
1058
     * @param int  $status
1059
     * @param bool $isAble
1060
     *
1061
     * @return string
1062
     */
1063
    public function getStatusMessage($status, $isAble = true)
1064
    {
1065
        switch ($status) {
1066
            case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_NO_QUEUE:
1067
                $message = $this->get_lang('AdvancedSubscriptionNoQueue');
1068
                if ($isAble) {
1069
                    $message = $this->get_lang('AdvancedSubscriptionNoQueueIsAble');
1070
                }
1071
1072
                break;
1073
            case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START:
1074
                $message = $this->get_lang('AdvancedSubscriptionQueueStart');
1075
1076
                break;
1077
            case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_DISAPPROVED:
1078
                $message = $this->get_lang('AdvancedSubscriptionQueueBossDisapproved');
1079
1080
                break;
1081
            case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED:
1082
                $message = $this->get_lang('AdvancedSubscriptionQueueBossApproved');
1083
1084
                break;
1085
            case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_DISAPPROVED:
1086
                $message = $this->get_lang('AdvancedSubscriptionQueueAdminDisapproved');
1087
1088
                break;
1089
            case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED:
1090
                $message = $this->get_lang('AdvancedSubscriptionQueueAdminApproved');
1091
1092
                break;
1093
            default:
1094
                $message = sprintf($this->get_lang('AdvancedSubscriptionQueueDefault'), $status);
1095
        }
1096
1097
        return $message;
1098
    }
1099
1100
    /**
1101
     * Return the url to go to session.
1102
     *
1103
     * @param $sessionId
1104
     *
1105
     * @return string
1106
     */
1107
    public function getSessionUrl($sessionId)
1108
    {
1109
        return api_get_path(WEB_CODE_PATH).'session/?session_id='.(int) $sessionId;
1110
    }
1111
1112
    /**
1113
     * Get a url for subscribe a user in session.
1114
     *
1115
     * @param int   $userId The user ID
1116
     * @param array $params Params from WS
1117
     *
1118
     * @return string
1119
     */
1120
    public function getOpenSessionUrl($userId, $params)
1121
    {
1122
        $userIsSubscribed = SessionManager::isUserSubscribedAsStudent(
1123
            $params['session_id'],
1124
            $userId
1125
        );
1126
1127
        if ($userIsSubscribed) {
1128
            return api_get_path(WEB_CODE_PATH)
1129
                .'session/index.php?session_id='
1130
                .(int) ($params['session_id']);
1131
        }
1132
1133
        $params['secret_key'] = null;
1134
        $params['user_id'] = null;
1135
        $params['user_field'] = null;
1136
        $params['is_connected'] = null;
1137
1138
        $urlParams = array_merge($params, ['user_id' => $userId]);
1139
1140
        $url = api_get_path(WEB_PLUGIN_PATH);
1141
        $url .= 'advanced_subscription/src/open_session.php?';
1142
        $url .= http_build_query($urlParams);
1143
1144
        return 'javascript:void(window.open(\''
1145
            .$url
1146
            .'\',\'AdvancedSubscriptionTerms\', \'toolbar=no,location=no,'
1147
            .'status=no,menubar=no,scrollbars=yes,resizable=yes,width=700px,'
1148
            .'height=600px\', \'100\' ))';
1149
    }
1150
1151
    /**
1152
     * Return the url to enter to subscription queue to session.
1153
     *
1154
     * @param $params
1155
     *
1156
     * @return string
1157
     */
1158
    public function getQueueUrl($params)
1159
    {
1160
        return api_get_path(WEB_PLUGIN_PATH).'advanced_subscription/ajax/advanced_subscription.ajax.php?'.
1161
            'a='.Security::remove_XSS($params['action']).'&'.
0 ignored issues
show
Are you sure Security::remove_XSS($params['action']) of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1161
            'a='./** @scrutinizer ignore-type */ Security::remove_XSS($params['action']).'&'.
Loading history...
1162
            's='.(int) ($params['sessionId']).'&'.
1163
            'current_user_id='.(int) ($params['currentUserId']).'&'.
1164
            'e='.(int) ($params['newStatus']).'&'.
1165
            'u='.(int) ($params['studentUserId']).'&'.
1166
            'q='.(int) ($params['queueId']).'&'.
1167
            'is_connected=1&'.
1168
            'profile_completed='.(int) ($params['profile_completed']).'&'.
1169
            'v='.$this->generateHash($params);
1170
    }
1171
1172
    /**
1173
     * Return the list of student, in queue used by admin view.
1174
     *
1175
     * @param int $sessionId
1176
     *
1177
     * @return array
1178
     */
1179
    public function listAllStudentsInQueueBySession($sessionId)
1180
    {
1181
        // Filter input variable
1182
        $sessionId = (int) $sessionId;
1183
        // Assign variables
1184
        $fieldsArray = [
1185
            'target',
1186
            'publication_end_date',
1187
            'mode',
1188
            'recommended_number_of_participants',
1189
            'vacancies',
1190
        ];
1191
        $sessionArray = api_get_session_info($sessionId);
1192
        $extraSession = new ExtraFieldValue('session');
1193
        $extraField = new ExtraField('session');
1194
        // Get session fields
1195
        $fieldList = $extraField->get_all([
1196
            'variable IN ( ?, ?, ?, ?, ?)' => $fieldsArray,
1197
        ]);
1198
        // Index session fields
1199
        $fields = [];
1200
        foreach ($fieldList as $field) {
1201
            $fields[$field['id']] = $field['variable'];
1202
        }
1203
1204
        $mergedArray = array_merge([$sessionId], array_keys($fields));
1205
        $sessionFieldValueList = $extraSession->get_all(
1206
            [
1207
                'item_id = ? field_id IN ( ?, ?, ?, ?, ?, ?, ? )' => $mergedArray,
1208
            ]
1209
        );
1210
        foreach ($sessionFieldValueList as $sessionFieldValue) {
1211
            // Check if session field value is set in session field list
1212
            if (isset($fields[$sessionFieldValue['field_id']])) {
1213
                $var = $fields[$sessionFieldValue['field_id']];
1214
                $val = $sessionFieldValue['value'];
1215
                // Assign session field value to session
1216
                $sessionArray[$var] = $val;
1217
            }
1218
        }
1219
        $queueTable = Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE);
1220
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
1221
        $userJoinTable = $queueTable.' q INNER JOIN '.$userTable.' u ON q.user_id = u.id';
1222
        $where = [
1223
            'where' => [
1224
                'q.session_id = ?' => [
1225
                    $sessionId,
1226
                ],
1227
            ],
1228
            'order' => 'q.status DESC, u.lastname ASC',
1229
        ];
1230
        $select = 'u.user_id, u.firstname, u.lastname, q.created_at, q.updated_at, q.status, q.id as queue_id';
1231
        $students = Database::select($select, $userJoinTable, $where);
1232
        foreach ($students as &$student) {
1233
            $status = (int) ($student['status']);
1234
            switch ($status) {
1235
                case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_NO_QUEUE:
1236
                case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START:
1237
                    $student['validation'] = '';
1238
1239
                    break;
1240
                case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_DISAPPROVED:
1241
                case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_DISAPPROVED:
1242
                    $student['validation'] = 'No';
1243
1244
                    break;
1245
                case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED:
1246
                case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED:
1247
                    $student['validation'] = 'Yes';
1248
1249
                    break;
1250
                default:
1251
                    error_log(__FILE__.' '.__FUNCTION__.' Student status no detected');
1252
            }
1253
        }
1254
        $return = [
1255
            'session' => $sessionArray,
1256
            'students' => $students,
1257
        ];
1258
1259
        return $return;
1260
    }
1261
1262
    /**
1263
     * List all session (id, title) for select input.
1264
     *
1265
     * @param int $limit
1266
     *
1267
     * @return array
1268
     */
1269
    public function listAllSessions($limit = 100)
1270
    {
1271
        $limit = (int) $limit;
1272
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
1273
        $columns = 'id, title';
1274
        $conditions = [];
1275
        if ($limit > 0) {
1276
            $conditions = [
1277
                'order' => 'title',
1278
                'limit' => $limit,
1279
            ];
1280
        }
1281
1282
        return Database::select($columns, $sessionTable, $conditions);
1283
    }
1284
1285
    /**
1286
     * Generate security hash to check data send by url params.
1287
     *
1288
     * @param string $data
1289
     *
1290
     * @return string
1291
     */
1292
    public function generateHash($data)
1293
    {
1294
        $key = sha1($this->get('secret_key'));
1295
        // Prepare array to have specific type variables
1296
        $dataPrepared['action'] = (string) ($data['action']);
0 ignored issues
show
Comprehensibility Best Practice introduced by
$dataPrepared was never initialized. Although not strictly required by PHP, it is generally a good practice to add $dataPrepared = array(); before regardless.
Loading history...
1297
        $dataPrepared['sessionId'] = (int) ($data['sessionId']);
1298
        $dataPrepared['currentUserId'] = (int) ($data['currentUserId']);
1299
        $dataPrepared['studentUserId'] = (int) ($data['studentUserId']);
1300
        $dataPrepared['queueId'] = (int) ($data['queueId']);
1301
        $dataPrepared['newStatus'] = (int) ($data['newStatus']);
1302
        $dataPrepared = serialize($dataPrepared);
1303
1304
        return sha1($dataPrepared.$key);
1305
    }
1306
1307
    /**
1308
     * Verify hash from data.
1309
     *
1310
     * @param string $data
1311
     * @param string $hash
1312
     *
1313
     * @return bool
1314
     */
1315
    public function checkHash($data, $hash)
1316
    {
1317
        return $this->generateHash($data) == $hash;
1318
    }
1319
1320
    /**
1321
     * Copied and fixed from plugin.class.php
1322
     * Returns the "system" name of the plugin in lowercase letters.
1323
     *
1324
     * @return string
1325
     */
1326
    public function get_name()
1327
    {
1328
        return 'advanced_subscription';
1329
    }
1330
1331
    /**
1332
     * Return the url to show subscription terms.
1333
     *
1334
     * @param array $params
1335
     * @param int   $mode
1336
     *
1337
     * @return string
1338
     */
1339
    public function getTermsUrl($params, $mode = ADVANCED_SUBSCRIPTION_TERMS_MODE_POPUP)
1340
    {
1341
        $urlParams = [
1342
            'a' => Security::remove_XSS($params['action']),
1343
            's' => (int) ($params['sessionId']),
1344
            'current_user_id' => (int) ($params['currentUserId']),
1345
            'e' => (int) ($params['newStatus']),
1346
            'u' => (int) ($params['studentUserId']),
1347
            'q' => (int) ($params['queueId']),
1348
            'is_connected' => 1,
1349
            'profile_completed' => (int) ($params['profile_completed']),
1350
            'v' => $this->generateHash($params),
1351
        ];
1352
1353
        switch ($mode) {
1354
            case ADVANCED_SUBSCRIPTION_TERMS_MODE_POPUP:
1355
            case ADVANCED_SUBSCRIPTION_TERMS_MODE_FINAL:
1356
                $urlParams['r'] = 0;
1357
1358
                break;
1359
            case ADVANCED_SUBSCRIPTION_TERMS_MODE_REJECT:
1360
                $urlParams['r'] = 1;
1361
1362
                break;
1363
        }
1364
1365
        $url = api_get_path(WEB_PLUGIN_PATH).'advanced_subscription/src/terms_and_conditions.php?';
1366
        $url .= http_build_query($urlParams);
1367
1368
        // Launch popup
1369
        if (ADVANCED_SUBSCRIPTION_TERMS_MODE_POPUP == $mode) {
1370
            $url = 'javascript:void(window.open(\''.$url.'\',\'AdvancedSubscriptionTerms\', \'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=700px,height=600px\', \'100\' ))';
1371
        }
1372
1373
        return $url;
1374
    }
1375
1376
    /**
1377
     * Return the url to get mail rendered.
1378
     *
1379
     * @param array $params
1380
     *
1381
     * @return string
1382
     */
1383
    public function getRenderMailUrl($params)
1384
    {
1385
        return api_get_path(WEB_PLUGIN_PATH).'advanced_subscription/src/render_mail.php?'.
1386
            'q='.$params['queueId'].'&'.
1387
            'v='.$this->generateHash($params);
1388
    }
1389
1390
    /**
1391
     * Return the last message id from queue row.
1392
     *
1393
     * @param int $studentUserId
1394
     * @param int $sessionId
1395
     *
1396
     * @return int|bool
1397
     */
1398
    public function getLastMessageId($studentUserId, $sessionId)
1399
    {
1400
        $studentUserId = (int) $studentUserId;
1401
        $sessionId = (int) $sessionId;
1402
        if (!empty($sessionId) && !empty($studentUserId)) {
1403
            $row = Database::select(
1404
                'last_message_id',
1405
                Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE),
1406
                [
1407
                    'where' => [
1408
                        'user_id = ? AND session_id = ?' => [$studentUserId, $sessionId],
1409
                    ],
1410
                ]
1411
            );
1412
1413
            if (count($row) > 0) {
1414
                return $row[0]['last_message_id'];
1415
            }
1416
        }
1417
1418
        return false;
1419
    }
1420
1421
    /**
1422
     * Return string replacing tags "{{}}"with variables assigned in $data.
1423
     *
1424
     * @param string $templateContent
1425
     * @param array  $data
1426
     *
1427
     * @return string
1428
     */
1429
    public function renderTemplateString($templateContent, $data = [])
1430
    {
1431
        $twigString = new \Twig_Environment(new \Twig_Loader_String());
1432
1433
        return $twigString->render(
1434
            $templateContent,
1435
            $data
1436
        );
1437
    }
1438
1439
    /**
1440
     * addAreaField() (adds an area field if it is not already created).
1441
     */
1442
    private function addAreaField()
1443
    {
1444
        $extraField = new ExtraField('user');
1445
        $extraFieldHandler = $extraField->get_handler_field_info_by_field_variable('area');
1446
        $areaExists = false !== $extraFieldHandler;
1447
1448
        if (!$areaExists) {
1449
            $extraField = new ExtraField('user');
1450
            $extraField->save([
1451
                'value_type' => 1,
1452
                'variable' => 'area',
1453
                'display_text' => get_plugin_lang('Area', 'AdvancedSubscriptionPlugin'),
1454
                'default_value' => null,
1455
                'field_order' => null,
1456
                'visible_to_self' => 1,
1457
                'changeable' => 1,
1458
                'filter' => null,
1459
            ]);
1460
        }
1461
    }
1462
1463
    /**
1464
     * Create the database tables for the plugin.
1465
     */
1466
    private function installDatabase()
1467
    {
1468
        $advancedSubscriptionQueueTable = Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE);
1469
1470
        $sql = "CREATE TABLE IF NOT EXISTS $advancedSubscriptionQueueTable (".
1471
            'id int UNSIGNED NOT NULL AUTO_INCREMENT, '.
1472
            'session_id int UNSIGNED NOT NULL, '.
1473
            'user_id int UNSIGNED NOT NULL, '.
1474
            'status int UNSIGNED NOT NULL, '.
1475
            'last_message_id int UNSIGNED NOT NULL, '.
1476
            'created_at datetime NOT NULL, '.
1477
            'updated_at datetime NULL, '.
1478
            'PRIMARY KEY PK_advanced_subscription_queue (id), '.
1479
            'UNIQUE KEY UK_advanced_subscription_queue (user_id, session_id)); ';
1480
        Database::query($sql);
1481
    }
1482
1483
    /**
1484
     * Drop the database tables for the plugin.
1485
     */
1486
    private function uninstallDatabase()
1487
    {
1488
        /* Drop plugin tables */
1489
        $advancedSubscriptionQueueTable = Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE);
1490
        $sql = "DROP TABLE IF EXISTS $advancedSubscriptionQueueTable; ";
1491
        Database::query($sql);
1492
1493
        /* Delete settings */
1494
        $settingsTable = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1495
        Database::query("DELETE FROM $settingsTable WHERE subkey = 'advanced_subscription'");
1496
    }
1497
1498
    /**
1499
     * Get the count of approved induction sessions by a user.
1500
     *
1501
     * @param int $userId The user id
1502
     *
1503
     * @return int The count of approved sessions
1504
     */
1505
    private function getApprovedInductionSessions($userId)
1506
    {
1507
        $tSession = Database::get_main_table(TABLE_MAIN_SESSION);
1508
        $tSessionField = Database::get_main_table(TABLE_EXTRA_FIELD);
1509
        $tSessionFieldValues = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1510
        $tSessionUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
1511
        $extraFieldType = \Chamilo\CoreBundle\Entity\ExtraField::SESSION_FIELD_TYPE;
1512
        $sql = "SELECT s.id FROM $tSession AS s
1513
            INNER JOIN $tSessionFieldValues AS sfv ON s.id = sfv.item_id
1514
            INNER JOIN $tSessionField AS sf ON sfv.field_id = sf.id
1515
            INNER JOIN $tSessionUser AS su ON s.id = su.session_id
1516
            WHERE
1517
                sf.item_type = $extraFieldType AND
1518
                sf.variable = 'is_induction_session' AND
1519
                su.relation_type = ".Session::STUDENT." AND
1520
                su.user_id = ".(int) $userId;
1521
1522
        $result = Database::query($sql);
1523
1524
        if (false === $result) {
1525
            return 0;
1526
        }
1527
1528
        $numberOfApproved = 0;
1529
1530
        while ($session = Database::fetch_assoc($result)) {
1531
            $numberOfApprovedCourses = 0;
1532
            $courses = SessionManager::get_course_list_by_session_id($session['id']);
1533
1534
            foreach ($courses as $course) {
1535
                $courseCategories = Category::load(
1536
                    null,
1537
                    null,
1538
                    $course['real_id'],
1539
                    null,
1540
                    null,
1541
                    $session['id'],
1542
                    null
1543
                );
1544
1545
                if (count($courseCategories) > 0 &&
1546
                    Category::userFinishedCourse($userId, $courseCategories[0])
1547
                ) {
1548
                    $numberOfApprovedCourses++;
1549
                }
1550
            }
1551
1552
            if ($numberOfApprovedCourses === count($courses)) {
1553
                $numberOfApproved++;
1554
            }
1555
        }
1556
1557
        return $numberOfApproved;
1558
    }
1559
}
1560