Passed
Pull Request — master (#6922)
by
unknown
08:45
created

Certificate::generate()   F

Complexity

Conditions 16
Paths 996

Size

Total Lines 88
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 62
nc 996
nop 2
dl 0
loc 88
rs 1.4055
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\GradebookCategory;
6
use Chamilo\CoreBundle\Entity\PersonalFile;
7
use Chamilo\CoreBundle\Entity\ResourceFile;
8
use Chamilo\CoreBundle\Entity\ResourceNode;
9
use Chamilo\CoreBundle\Framework\Container;
10
use Endroid\QrCode\ErrorCorrectionLevel;
11
use Endroid\QrCode\QrCode;
12
use JetBrains\PhpStorm\NoReturn;
13
use Symfony\Component\HttpFoundation\File\UploadedFile;
14
15
/**
16
 * Certificate Class
17
 * Generate certificates based in the gradebook tool.
18
 */
19
class Certificate extends Model
20
{
21
    public $table;
22
    public $columns = [
23
        'id',
24
        'cat_id',
25
        'score_certificate',
26
        'created_at',
27
        'path_certificate',
28
    ];
29
    /**
30
     * Certification data.
31
     */
32
    public $certificate_data = [];
33
34
    /**
35
     * Student's certification path.
36
     */
37
    public $certification_user_path = null;
38
    public $certification_web_user_path = null;
39
    public $html_file = null;
40
    public $qr_file = null;
41
    public $user_id;
42
43
    /** If true every time we enter to the certificate URL
44
     * we would generate a new certificate (good thing because we can edit the
45
     * certificate and all users will have the latest certificate bad because we.
46
     * load the certificate every time */
47
    public $force_certificate_generation = true;
48
49
    /**
50
     * Constructor.
51
     *
52
     * @param int  $certificate_id        ID of the certificate
53
     * @param int  $userId
54
     * @param bool $sendNotification      send message to student
55
     * @param bool $updateCertificateData
56
     * @param string $pathToCertificate
57
     *
58
     * If no ID given, take user_id and try to generate one
59
     */
60
    public function __construct(
61
        $certificate_id = 0,
62
        $userId = 0,
63
        $sendNotification = false,
64
        $updateCertificateData = true,
65
        $pathToCertificate = ''
66
    ) {
67
        $this->table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
68
        $this->user_id = !empty($userId) ? $userId : api_get_user_id();
69
70
        if (!empty($certificate_id)) {
71
            $certificate = $this->get($certificate_id);
72
            if (!empty($certificate) && is_array($certificate)) {
73
                $this->certificate_data = $certificate;
74
                $this->user_id = $this->certificate_data['user_id'];
75
            }
76
        }
77
78
        if ($this->user_id) {
79
            // To force certification generation
80
            if ($this->force_certificate_generation) {
81
                $this->generate(['certificate_path' => ''], $sendNotification);
82
            }
83
            if (
84
                isset($this->certificate_data)
85
                && $this->certificate_data
86
                && empty($this->certificate_data['path_certificate'])
87
            ) {
88
                $this->generate(['certificate_path' => $pathToCertificate], $sendNotification);
89
            }
90
        }
91
92
        // Setting the qr and html variables
93
        if (isset($certificate_id) &&
94
            !empty($this->certification_user_path) &&
95
            isset($this->certificate_data['path_certificate'])
96
        ) {
97
            //$pathinfo = pathinfo($this->certificate_data['path_certificate']);
98
            $this->html_file = $this->certificate_data['path_certificate'];
99
            //$this->qr_file = $this->certification_user_path.$pathinfo['filename'].'_qr.png';
100
        } else {
101
            //$this->checkCertificatePath();
102
            if ('true' === api_get_setting('certificate.allow_general_certificate')) {
103
                // General certificate
104
                // store as a Resource (resource_type = user_certificate) instead of PersonalFile
105
                $repo     = Container::getGradeBookCertificateRepository();
106
                $content  = $this->generateCustomCertificate();
107
                $categoryId = isset($this->certificate_data['cat_id']) ? (int) $this->certificate_data['cat_id'] : 0;
108
                $hash     = hash('sha256', $this->user_id.$categoryId);
109
                $fileName = $hash.'.html';
110
111
                try {
112
                    // upsertCertificateResource(catId, userId, score, htmlContent, pdfBinary?, legacyFileName?)
113
                    $cert = $repo->upsertCertificateResource(0, $this->user_id, 100.0, $content, null, $fileName);
114
115
                    // Keep legacy compatibility fields
116
                    if ($updateCertificateData) {
117
                        $repo->registerUserInfoAboutCertificate(0, $this->user_id, 100.0, $fileName);
118
                    }
119
120
                    $this->certificate_data['path_certificate'] = $fileName;
121
                    // Optionally keep the in-memory HTML content
122
                    $this->certificate_data['file_content'] = $repo->getResourceFileContent($cert);
123
                } catch (\Throwable $e) {
124
                    error_log('[CERT] general certificate upsert error: '.$e->getMessage());
125
                }
126
127
128
                if (null !== $cert) {
129
                    // Updating the path
130
                    self::updateUserCertificateInfo(
131
                        0,
132
                        $this->user_id,
133
                        $fileName,
134
                        $updateCertificateData
135
                    );
136
                    $this->certificate_data['path_certificate'] = $fileName;
137
                }
138
            }
139
        }
140
    }
141
142
    /**
143
     * Deletes the current certificate object. This is generally triggered by
144
     * the teacher from the gradebook tool to re-generate the certificate because
145
     * the original version wa flawed.
146
     *
147
     * @param bool $force_delete
148
     *
149
     * @return bool
150
     */
151
    public function deleteCertificate(): bool
152
    {
153
        if (empty($this->certificate_data)) {
154
            return false;
155
        }
156
157
        $categoryId = isset($this->certificate_data['cat_id']) ? (int) $this->certificate_data['cat_id'] : 0;
158
        $certRepo   = Container::getGradeBookCertificateRepository();
159
160
        try {
161
            $certRepo->deleteCertificateResource($this->certificate_data['user_id'], $categoryId);
162
163
            return true;
164
        } catch (\Throwable $e) {
165
            error_log('[CERTIFICATE::deleteCertificate] delete error: '.$e->getMessage());
166
            return false;
167
        }
168
    }
169
170
    /**
171
     *  Generates an HTML Certificate and fills the path_certificate field in the DB.
172
     *
173
     * @param array $params
174
     * @param bool  $sendNotification
175
     *
176
     * @return bool|int
177
     */
178
    public function generate($params = [], $sendNotification = false)
179
    {
180
        $result = false;
181
        $params['hide_print_button'] = isset($params['hide_print_button']) ? true : false;
182
        $categoryId = 0;
183
        $isCertificateAvailableInCategory = false;
184
        $category = null;
185
        if (isset($this->certificate_data['cat_id'])) {
186
            $categoryId = (int) $this->certificate_data['cat_id'];
187
            $myCategory = Category::load($categoryId);
188
            $repo = Container::getGradeBookCategoryRepository();
189
            /** @var GradebookCategory $category */
190
            $category = $repo->find($categoryId);
191
            $isCertificateAvailableInCategory = !empty($categoryId) && $myCategory[0]->is_certificate_available($this->user_id);
192
        }
193
194
        $certRepo = Container::getGradeBookCertificateRepository();
195
196
        if ($isCertificateAvailableInCategory && null !== $category) {
197
            $courseInfo = api_get_course_info($category->getCourse()->getCode());
198
            $courseId   = $courseInfo['real_id'];
199
            $sessionId  = $category->getSession() ? $category->getSession()->getId() : 0;
200
201
            $skill = new SkillModel();
202
            $skill->addSkillToUser(
203
                $this->user_id,
204
                $category,
205
                $courseId,
206
                $sessionId
207
            );
208
209
            if (!empty($this->certificate_data)) {
210
                $gb = GradebookUtils::get_user_certificate_content(
211
                    $this->user_id,
212
                    $category->getCourse()->getId(),
213
                    $category->getSession() ? $category->getSession()->getId() : 0,
214
                    false,
215
                    $params['hide_print_button']
216
                );
217
218
                $html  = is_array($gb) && isset($gb['content']) ? $gb['content'] : '';
219
                $score = isset($gb['score']) ? (float) $gb['score'] : 100.0;
220
221
                try {
222
                    // Upsert como Resource (resource_type = user_certificate)
223
                    $certEntity = $certRepo->upsertCertificateResource($categoryId, $this->user_id, $score, $html);
224
                    $certRepo->registerUserInfoAboutCertificate($categoryId, $this->user_id, $score);
225
226
                    $this->certification_user_path = 'resource://user_certificate';
227
                    $this->certificate_data['path_certificate'] = '';
228
229
                    if ($this->isHtmlFileGenerated() && $sendNotification) {
230
                        $subject = get_lang('Certificate notification');
231
                        $message = nl2br(get_lang('((user_first_name)),'));
232
                        $htmlUrl = $certRepo->getResourceFileUrl($certEntity);
233
234
                        self::sendNotification(
235
                            $subject,
236
                            $message,
237
                            api_get_user_info($this->user_id),
238
                            $courseInfo,
239
                            [
240
                                'score_certificate' => $score,
241
                                'html_url'          => $htmlUrl,
242
                            ]
243
                        );
244
                    }
245
246
                    return true;
247
                } catch (\Throwable $e) {
248
                    error_log('[CERTIFICATE::generate] upsert error: '.$e->getMessage());
249
                    return false;
250
                }
251
            }
252
        } else {
253
            $gbHtml = $this->generateCustomCertificate();
254
            try {
255
                $certEntity = $certRepo->upsertCertificateResource(0, $this->user_id, 100.0, $gbHtml);
256
                $this->certificate_data['file_content'] = $certRepo->getResourceFileContent($certEntity);
257
                $this->certificate_data['path_certificate'] = '';
258
                return true;
259
            } catch (\Throwable $e) {
260
                error_log('[CERTIFICATE::generate] general certificate upsert error: '.$e->getMessage());
261
                return false;
262
            }
263
        }
264
265
        return false;
266
    }
267
268
    /**
269
     * @return array
270
     */
271
    public static function notificationTags()
272
    {
273
        $tags = [
274
            '((course_title))',
275
            '((user_first_name))',
276
            '((user_last_name))',
277
            '((author_first_name))',
278
            '((author_last_name))',
279
            '((score))',
280
            '((portal_name))',
281
            '((certificate_link))',
282
        ];
283
284
        return $tags;
285
    }
286
287
    /**
288
     * @param string $subject
289
     * @param string $message
290
     * @param array  $userInfo
291
     * @param array  $courseInfo
292
     * @param array  $certificateInfo
293
     *
294
     * @return bool
295
     */
296
    public static function sendNotification(
297
        $subject,
298
        $message,
299
        $userInfo,
300
        $courseInfo,
301
        $certificateInfo
302
    ) {
303
        if (empty($userInfo) || empty($courseInfo)) {
304
            return false;
305
        }
306
307
        $currentUserInfo = api_get_user_info();
308
        $url = '';
309
310
        // Prefer resource URL if present
311
        if (!empty($certificateInfo['html_url'])) {
312
            $url = $certificateInfo['html_url'];
313
        } elseif (!empty($certificateInfo['path_certificate'])) {
314
            $hash = pathinfo($certificateInfo['path_certificate'], PATHINFO_FILENAME);
315
            $url = api_get_path(WEB_PATH) . 'certificates/' . $hash . '.html';
316
        }
317
        $link = Display::url($url, $url);
318
319
        $replace = [
320
            $courseInfo['title'],
321
            $userInfo['firstname'],
322
            $userInfo['lastname'],
323
            $currentUserInfo['firstname'],
324
            $currentUserInfo['lastname'],
325
            $certificateInfo['score_certificate'],
326
            api_get_setting('Institution'),
327
            $link,
328
        ];
329
330
        $message = str_replace(self::notificationTags(), $replace, $message);
331
        MessageManager::send_message(
332
            $userInfo['id'],
333
            $subject,
334
            $message,
335
            [],
336
            [],
337
            0,
338
            0,
339
            0,
340
            0,
341
            $currentUserInfo['id']
342
        );
343
    }
344
345
    /**
346
     * Update user info about certificate.
347
     *
348
     * @param int    $categoryId            category id
349
     * @param int    $user_id               user id
350
     * @param string $path_certificate      the path name of the certificate
351
     * @param bool   $updateCertificateData
352
     */
353
    public function updateUserCertificateInfo(
354
        $categoryId,
355
        $user_id,
356
        $path_certificate,
357
        $updateCertificateData = true
358
    ) {
359
        if (!$updateCertificateData) {
360
            return;
361
        }
362
        $certRepo = Container::getGradeBookCertificateRepository();
363
364
        $certRepo->registerUserInfoAboutCertificate(
365
            (int)$categoryId,
366
            (int)$user_id,
367
            (float)($this->certificate_data['score_certificate'] ?? 100.0),
368
            (string)$path_certificate
369
        );
370
    }
371
372
    /**
373
     * Check if the file was generated.
374
     *
375
     * @return bool
376
     */
377
    public function isHtmlFileGenerated()
378
    {
379
        if (empty($this->certification_user_path)) {
380
            return false;
381
        }
382
        if (!empty($this->certificate_data) &&
383
            isset($this->certificate_data['path_certificate']) &&
384
            !empty($this->certificate_data['path_certificate'])
385
        ) {
386
            return true;
387
        }
388
389
        return false;
390
    }
391
392
    /**
393
     * Generates a QR code for the certificate. The QR code embeds the text given.
394
     *
395
     * @param string $text Text to be added in the QR code
396
     * @param string $path file path of the image
397
     *
398
     * @return bool
399
     */
400
    public function generateQRImage($text, $path): bool
401
    {
402
        throw new \Exception('generateQRImage');
403
        if (!empty($text) && !empty($path)) {
0 ignored issues
show
Unused Code introduced by
IfNode is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
404
            $qrCode = new QrCode($text);
405
            //$qrCode->setEncoding('UTF-8');
406
            $qrCode->setSize(120);
407
            $qrCode->setMargin(5);
408
            /*$qrCode->setWriterByName('png');
409
            $qrCode->setErrorCorrectionLevel(ErrorCorrectionLevel::MEDIUM());
410
            $qrCode->setForegroundColor(['r' => 0, 'g' => 0, 'b' => 0, 'a' => 0]);
411
            $qrCode->setBackgroundColor(['r' => 255, 'g' => 255, 'b' => 255, 'a' => 0]);
412
            $qrCode->setValidateResult(false);
413
            $qrCode->writeFile($path);*/
414
415
            return true;
416
        }
417
418
        return false;
419
    }
420
421
    /**
422
     * Transforms certificate tags into text values. This function is very static
423
     * (it doesn't allow for much flexibility in terms of what tags are printed).
424
     *
425
     * @param array $array Contains two array entries: first are the headers,
426
     *                     second is an array of contents
427
     *
428
     * @return string The translated string
429
     */
430
    public function parseCertificateVariables($array)
431
    {
432
        $headers = $array[0];
433
        $content = $array[1];
434
        $final_content = [];
435
436
        if (!empty($content)) {
437
            foreach ($content as $key => $value) {
438
                $my_header = str_replace(['((', '))'], '', $headers[$key]);
439
                $final_content[$my_header] = $value;
440
            }
441
        }
442
443
        /* Certificate tags
444
         *
445
          0 => string '((user_firstname))' (length=18)
446
          1 => string '((user_lastname))' (length=17)
447
          2 => string '((gradebook_institution))' (length=25)
448
          3 => string '((gradebook_sitename))' (length=22)
449
          4 => string '((teacher_firstname))' (length=21)
450
          5 => string '((teacher_lastname))' (length=20)
451
          6 => string '((official_code))' (length=17)
452
          7 => string '((date_certificate))' (length=20)
453
          8 => string '((course_code))' (length=15)
454
          9 => string '((course_title))' (length=16)
455
          10 => string '((gradebook_grade))' (length=19)
456
          11 => string '((certificate_link))' (length=20)
457
          12 => string '((certificate_link_html))' (length=25)
458
          13 => string '((certificate_barcode))' (length=23)
459
         */
460
461
        $break_space = " \n\r ";
462
        $text =
463
            $final_content['gradebook_institution'].' - '.
464
            $final_content['gradebook_sitename'].' - '.
465
            get_lang('Certification').$break_space.
466
            get_lang('Learner').': '.$final_content['user_firstname'].' '.$final_content['user_lastname'].$break_space.
467
            get_lang('Trainer').': '.$final_content['teacher_firstname'].' '.$final_content['teacher_lastname'].$break_space.
468
            get_lang('Date').': '.$final_content['date_certificate'].$break_space.
469
            get_lang('Score').': '.$final_content['gradebook_grade'].$break_space.
470
            'URL'.': '.$final_content['certificate_link'];
471
472
        return $text;
473
    }
474
475
    /**
476
     * Check if the certificate is visible for the current user
477
     * If the global setting allow_public_certificates is set to 'false', no certificate can be printed.
478
     * If the global allow_public_certificates is set to 'true' and the course setting allow_public_certificates
479
     * is set to 0, no certificate *in this course* can be printed (for anonymous users).
480
     * Connected users can always print them.
481
     *
482
     * @return bool
483
     */
484
    public function isVisible()
485
    {
486
        if (!api_is_anonymous()) {
487
            return true;
488
        }
489
490
        if ('true' != api_get_setting('certificate.allow_public_certificates')) {
491
            // The "non-public" setting is set, so do not print
492
            return false;
493
        }
494
495
        if (!isset($this->certificate_data, $this->certificate_data['cat_id'])) {
496
            return false;
497
        }
498
499
        $gradeBook = new Gradebook();
500
        $gradeBookInfo = $gradeBook->get($this->certificate_data['cat_id']);
501
502
        if (empty($gradeBookInfo['course_code'])) {
503
            return false;
504
        }
505
506
        $setting = api_get_course_setting(
507
            'allow_public_certificates',
508
            api_get_course_info($gradeBookInfo['course_code'])
509
        );
510
511
        if (0 == $setting) {
512
            // Printing not allowed
513
            return false;
514
        }
515
516
        return true;
517
    }
518
519
    /**
520
     * Check if the certificate is available.
521
     *
522
     * @return bool
523
     */
524
    public function isAvailable()
525
    {
526
        $certRepo = Container::getGradeBookCertificateRepository();
527
528
        $categoryId = isset($this->certificate_data['cat_id']) ? (int) $this->certificate_data['cat_id'] : 0;
529
530
        try {
531
            $entity = $certRepo->getCertificateByUserId(0 === $categoryId ? null : $categoryId, $this->user_id);
532
            if (!$entity || !$entity->hasResourceNode()) {
533
                return false;
534
            }
535
536
            $node = $entity->getResourceNode();
537
            return $node->hasResourceFile() && $node->getResourceFiles()->count() > 0;
538
        } catch (\Throwable $e) {
539
            error_log('[CERTIFICATE::isAvailable] check error: '.$e->getMessage());
540
            return false;
541
        }
542
    }
543
544
    /**
545
     * Shows the student's certificate (HTML file).
546
     */
547
    public function show()
548
    {
549
        $certRepo = Container::getGradeBookCertificateRepository();
550
        $categoryId = isset($this->certificate_data['cat_id']) ? (int) $this->certificate_data['cat_id'] : 0;
551
552
        try {
553
            $entity = $certRepo->getCertificateByUserId(0 === $categoryId ? null : $categoryId, $this->user_id);
554
            if (!$entity || !$entity->hasResourceNode()) {
555
                api_not_allowed(true);
556
            }
557
558
            // Read HTML content from the Resource layer
559
            $certificateContent = '<!DOCTYPE html>';
560
            $certificateContent .= $certRepo->getResourceFileContent($entity);
561
            $certificateContent = str_replace(' media="screen"', '', $certificateContent);
562
563
            // Track “downloaded_at” (legacy extra fields)
564
            if ($this->user_id == api_get_user_id() &&
565
                !empty($this->certificate_data) &&
566
                isset($this->certificate_data['id'])
567
            ) {
568
                $certificateId = $this->certificate_data['id'];
569
                $extraFieldValue = new ExtraFieldValue('user_certificate');
570
                $value = $extraFieldValue->get_values_by_handler_and_field_variable(
571
                    $certificateId,
572
                    'downloaded_at'
573
                );
574
                if (empty($value)) {
575
                    $params = [
576
                        'item_id' => $this->certificate_data['id'],
577
                        'extra_downloaded_at' => api_get_utc_datetime(),
578
                    ];
579
                    $extraFieldValue->saveFieldValues($params);
580
                }
581
            }
582
583
            header('Content-Type: text/html; charset='.api_get_system_encoding());
584
            echo $certificateContent;
585
            return;
586
        } catch (\Throwable $e) {
587
            error_log('[CERTIFICATE::show] read error: '.$e->getMessage());
588
            api_not_allowed(true);
589
        }
590
    }
591
592
    /**
593
     * @return string
594
     */
595
    public function generateCustomCertificate(string $fileName = ''): string
596
    {
597
        $certificateRepo = Container::getGradeBookCertificateRepository();
598
        $certificateRepo->registerUserInfoAboutCertificate(0, $this->user_id, 100, $fileName);
599
600
        $userInfo = api_get_user_info($this->user_id);
601
        $extraFieldValue = new ExtraFieldValue('user');
602
        $value = $extraFieldValue->get_values_by_handler_and_field_variable($this->user_id, 'legal_accept');
603
        $termsValidationDate = '';
604
        if (isset($value) && !empty($value['value'])) {
605
            [$id, $id2, $termsValidationDate] = explode(':', $value['value']);
606
        }
607
608
        $sessions = SessionManager::get_sessions_by_user($this->user_id, false, true);
609
        $totalTimeInLearningPaths = 0;
610
        $sessionsApproved = [];
611
        $coursesApproved = [];
612
        $courseList = [];
613
614
        $gradeBookRepo = Container::getGradeBookCategoryRepository();
615
        if ($sessions) {
616
            foreach ($sessions as $session) {
617
                $allCoursesApproved = [];
618
                foreach ($session['courses'] as $course) {
619
                    $course = api_get_course_entity($course['real_id']);
620
                    $courseId = $course->getId();
621
                    /* @var GradebookCategory $category */
622
                    $category = $gradeBookRepo->findOneBy(['course' => $course, 'session' => $session['session_id']]);
623
624
                    if (null !== $category) {
625
                        $result = Category::userFinishedCourse(
626
                            $this->user_id,
627
                            $category,
628
                            true,
629
                            $courseId,
630
                            $session['session_id']
631
                        );
632
633
                        $lpList = new LearnpathList(
634
                            $this->user_id,
635
                            api_get_course_info_by_id($courseId),
636
                            $session['session_id']
637
                        );
638
                        $lpFlatList = $lpList->get_flat_list();
639
640
                        // Find time spent in LP
641
                        $timeSpent = Tracking::get_time_spent_in_lp(
642
                            $this->user_id,
643
                            $course,
644
                            !empty($lpFlatList) ? array_keys($lpFlatList) : [],
645
                            $session['session_id']
646
                        );
647
648
                        if (!isset($courseList[$courseId])) {
649
                            $courseList[$courseId]['approved'] = false;
650
                            $courseList[$courseId]['time_spent'] = 0;
651
                        }
652
653
                        if ($result) {
654
                            $courseList[$courseId]['approved'] = true;
655
                            $coursesApproved[$courseId] = $course->getTitle();
656
                            $allCoursesApproved[] = true;
657
                        }
658
                        $courseList[$courseId]['time_spent'] += $timeSpent;
659
                    }
660
                }
661
662
                if (count($allCoursesApproved) == count($session['courses'])) {
663
                    $sessionsApproved[] = $session;
664
                }
665
            }
666
        }
667
668
        $totalTimeInLearningPaths = 0;
669
        foreach ($courseList as $courseId => $courseData) {
670
            if (true === $courseData['approved']) {
671
                $totalTimeInLearningPaths += $courseData['time_spent'];
672
            }
673
        }
674
675
        $skill = new SkillModel();
676
        $skills = $skill->getStudentSkills($this->user_id, 2);
677
        $allowAll = ('true' === api_get_setting('skill.allow_teacher_access_student_skills'));
678
        $courseIdForSkills  = $allowAll ? 0 : 0;
679
        $sessionIdForSkills = $allowAll ? 0 : 0;
680
        $skillsTable = $skill->getUserSkillsTable(
681
            $this->user_id,
682
            $courseIdForSkills,
683
            $sessionIdForSkills,
684
            false
685
        );
686
687
        $timeInSeconds = Tracking::get_time_spent_on_the_platform(
688
            $this->user_id,
689
            'ever'
690
        );
691
        $time = api_time_to_hms($timeInSeconds);
692
693
        $tplContent = new Template(null, false, false, false, false, false);
694
695
        // variables for the default template
696
        $tplContent->assign('complete_name', $userInfo['complete_name']);
697
        $tplContent->assign('time_in_platform', $time);
698
        $tplContent->assign('certificate_generated_date', isset($myCertificate['created_at']) ? api_get_local_time($myCertificate['created_at']) : '');
699
        if (!empty($termsValidationDate)) {
700
            $termsValidationDate = api_get_local_time($termsValidationDate);
701
        }
702
        $tplContent->assign('terms_validation_date', $termsValidationDate);
703
704
        if (empty($totalTimeInLearningPaths)) {
705
            $totalTimeInLearningPaths = $timeInSeconds;
706
        }
707
708
        // Ofaj
709
        $tplContent->assign('time_in_platform_in_hours', round($timeInSeconds/3600, 1));
710
        $tplContent->assign(
711
            'certificate_generated_date_no_time',
712
            api_get_local_time(
713
                $myCertificate['created_at'] ?? null,
714
                null,
715
                null,
716
                false,
717
                false,
718
                false,
719
                'd-m-Y'
720
            )
721
        );
722
        $tplContent->assign(
723
            'terms_validation_date_no_time',
724
            api_get_local_time(
725
                $termsValidationDate,
726
                null,
727
                null,
728
                false,
729
                false,
730
                false,
731
                'd-m-Y'
732
            )
733
        );
734
        $tplContent->assign('skills', $skills);
735
        $tplContent->assign('skills_table_html', $skillsTable['table']);
736
        $tplContent->assign('skills_rows', $skillsTable['skills']);
737
        $tplContent->assign('sessions', $sessionsApproved);
738
        $tplContent->assign('courses', $coursesApproved);
739
        $tplContent->assign('time_spent_in_lps', api_time_to_hms($totalTimeInLearningPaths));
740
        $tplContent->assign('time_spent_in_lps_in_hours', round($totalTimeInLearningPaths/3600, 1));
741
742
        $layoutContent = $tplContent->get_template('gradebook/custom_certificate.html.twig');
743
        $content = $tplContent->fetch($layoutContent);
744
745
        return $content;
746
    }
747
748
    /**
749
     * Ofaj.
750
     */
751
    public function generatePdfFromCustomCertificate(): void
752
    {
753
        $orientation = api_get_setting('certificate.certificate_pdf_orientation');
754
755
        $params['orientation'] = 'landscape';
756
        if (!empty($orientation)) {
757
            $params['orientation'] = $orientation;
758
        }
759
760
        $params['left'] = 0;
761
        $params['right'] = 0;
762
        $params['top'] = 0;
763
        $params['bottom'] = 0;
764
        $page_format = 'landscape' == $params['orientation'] ? 'A4-L' : 'A4';
765
        $pdf = new PDF($page_format, $params['orientation'], $params);
766
767
        $pdf->content_to_pdf(
768
            $this->certificate_data['file_content'],
769
            null,
770
            get_lang('Certificates'),
771
            api_get_course_id(),
772
            'D',
773
            false,
774
            null,
775
            false,
776
            true,
777
            true,
778
            true,
779
            true
780
        );
781
    }
782
783
    /**
784
     * @param int $userId
785
     *
786
     * @return array
787
     */
788
    public static function getCertificateByUser($userId)
789
    {
790
        $userId = (int) $userId;
791
        if (empty($userId)) {
792
            return [];
793
        }
794
795
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
796
        $sql = "SELECT * FROM $table
797
                WHERE user_id= $userId";
798
        $rs = Database::query($sql);
799
800
        return Database::store_result($rs, 'ASSOC');
801
    }
802
803
    /**
804
     * @param int $userId
805
     */
806
    public static function generateUserSkills($userId)
807
    {
808
        $controller = new IndexManager(get_lang('My courses'));
809
        $courseAndSessions = $controller->returnCoursesAndSessions($userId, true, null, true, false);
810
        $repo = Container::getGradeBookCategoryRepository();
811
        if (isset($courseAndSessions['courses']) && !empty($courseAndSessions['courses'])) {
812
            foreach ($courseAndSessions['courses'] as $course) {
813
                $category = $repo->findOneBy(['course' => $course['real_id']]);
814
                /*$cats = Category::load(
815
                    null,
816
                    null,
817
                    $course['code'],
818
                    null,
819
                    null,
820
                    null,
821
                    false
822
                );*/
823
                if (null !== $category) {
824
                    Category::generateUserCertificate($category, $userId);
825
                }
826
            }
827
        }
828
829
        if (isset($courseAndSessions['sessions']) && !empty($courseAndSessions['sessions'])) {
830
            foreach ($courseAndSessions['sessions'] as $sessionCategory) {
831
                if (isset($sessionCategory['sessions'])) {
832
                    foreach ($sessionCategory['sessions'] as $sessionData) {
833
                        if (!empty($sessionData['courses'])) {
834
                            $sessionId = $sessionData['session_id'];
835
                            foreach ($sessionData['courses'] as $courseData) {
836
                                /*$cats = Category:: load(
837
                                    null,
838
                                    null,
839
                                    $courseData['course_code'],
840
                                    null,
841
                                    null,
842
                                    $sessionId,
843
                                    false
844
                                );*/
845
846
                                $category = $repo->findOneBy(
847
                                    ['course' => $courseData['real_id'], 'session' => $sessionId]
848
                                );
849
                                if (null !== $category) {
850
                                    Category::generateUserCertificate($category, $userId);
851
                                }
852
                            }
853
                        }
854
                    }
855
                }
856
            }
857
        }
858
    }
859
}
860