Passed
Pull Request — master (#5329)
by Angel Fernando Quiroz
12:42 queued 05:42
created

CourseController::show()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 3
nop 1
dl 0
loc 23
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\LtiBundle\Controller;
8
9
use Category;
10
use Chamilo\CoreBundle\Component\Utils\ToolIcon;
11
use Chamilo\CoreBundle\Entity\Course;
12
use Chamilo\CoreBundle\Entity\Session;
13
use Chamilo\CoreBundle\Entity\User;
14
use Chamilo\CoreBundle\ServiceHelper\UserHelper;
15
use Chamilo\CourseBundle\Controller\ToolBaseController;
16
use Chamilo\CourseBundle\Entity\CTool;
17
use Chamilo\CourseBundle\Repository\CShortcutRepository;
18
use Chamilo\LtiBundle\Entity\ExternalTool;
19
use Chamilo\LtiBundle\Form\ExternalToolType;
20
use Chamilo\LtiBundle\Util\Utils;
21
use Display;
22
use Doctrine\Persistence\ManagerRegistry;
23
use EvalForm;
24
use Evaluation;
25
use Exception;
26
use HTML_QuickForm_select;
27
use OAuthConsumer;
28
use OAuthRequest;
29
use OAuthSignatureMethod_HMAC_SHA1;
30
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
31
use Symfony\Component\HttpFoundation\Request;
32
use Symfony\Component\HttpFoundation\Response;
33
use Symfony\Component\Routing\Attribute\Route;
34
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
35
use UserManager;
36
37
#[Route(path: '/courses/{cid}/lti')] // ;
38
class CourseController extends ToolBaseController
39
{
40
    public function __construct(
41
        private readonly CShortcutRepository $shortcutRepository,
42
        private readonly ManagerRegistry $managerRegistry,
43
        private readonly UserHelper $userHelper,
44
    ) {}
45
46
    #[Route(path: '/edit/{id}', name: 'chamilo_lti_edit', requirements: ['id' => '\d+'])]
47
    public function edit(int $id, Request $request): Response
48
    {
49
        $em = $this->managerRegistry->getManager();
50
51
        /** @var ExternalTool $tool */
52
        $tool = $em->find(ExternalTool::class, $id);
53
54
        if (empty($tool)) {
55
            throw $this->createNotFoundException('External tool not found');
56
        }
57
58
        $course = $this->getCourse();
59
60
        $form = $this->createForm(ExternalToolType::class, $tool);
61
        $form->get('shareName')->setData($tool->isSharingName());
62
        $form->get('shareEmail')->setData($tool->isSharingEmail());
63
        $form->get('sharePicture')->setData($tool->isSharingPicture());
64
        $form->handleRequest($request);
65
66
        if (!$form->isSubmitted() || !$form->isValid()) {
67
            return $this->render(
68
                '@ChamiloCore/Lti/course_configure.twig',
69
                [
70
                    'title' => $this->trans('Edit external tool'),
71
                    'added_tools' => [],
72
                    'global_tools' => [],
73
                    'form' => $form,
74
                    'course' => $course,
75
                ]
76
            );
77
        }
78
79
        /** @var ExternalTool $tool */
80
        $tool = $form->getData();
81
82
        $em->persist($tool);
83
84
        if (!$tool->isActiveDeepLinking()) {
85
            $courseTool = $em->getRepository(CTool::class)
86
                ->findOneBy(
87
                    [
88
                        'course' => $course,
89
                        'link' => $this->generateUrl(
90
                            'chamilo_lti_show',
91
                            [
92
                                'code' => $course->getCode(),
93
                                'id' => $tool->getId(),
94
                            ]
95
                        ),
96
                    ]
97
                )
98
            ;
99
100
            if (empty($courseTool)) {
101
                throw $this->createNotFoundException('Course tool not found.');
102
            }
103
104
            $courseTool->setTitle($tool->getTitle());
105
106
            $em->persist($courseTool);
107
        }
108
109
        $em->flush();
110
111
        $this->addFlash('success', $this->trans('External tool edited'));
112
113
        return $this->redirectToRoute(
114
            'chamilo_lti_edit',
115
            [
116
                'id' => $tool->getId(),
117
                'cid' => $course->getId(),
118
            ]
119
        );
120
    }
121
122
    #[Route(path: '/launch/{id}', name: 'chamilo_lti_launch', requirements: ['id' => '\d+'])]
123
    public function launch(int $id, Utils $ltiUtil): Response
124
    {
125
        $em = $this->managerRegistry->getManager();
126
127
        /** @var null|ExternalTool $tool */
128
        $tool = $em->find(ExternalTool::class, $id);
129
130
        if (empty($tool)) {
131
            throw $this->createNotFoundException();
132
        }
133
134
        $settingsManager = $this->get('chamilo.settings.manager');
135
136
        $user = $this->userHelper->getCurrent();
137
        $course = $this->getCourse();
138
        $session = $this->getCourseSession();
139
140
        if (empty($tool->getCourse()) || $tool->getCourse()->getId() !== $course->getId()) {
141
            throw $this->createAccessDeniedException('');
142
        }
143
144
        $institutionDomain = $ltiUtil->getInstitutionDomain();
145
        $toolUserId = $ltiUtil->generateToolUserId($user->getId());
146
147
        $params = [];
148
        $params['lti_version'] = 'LTI-1p0';
149
150
        if ($tool->isActiveDeepLinking()) {
151
            $params['lti_message_type'] = 'ContentItemSelectionRequest';
152
            $params['content_item_return_url'] = $this->generateUrl(
153
                'chamilo_lti_return_item',
154
                [
155
                    'code' => $course->getCode(),
156
                ],
157
                UrlGeneratorInterface::ABSOLUTE_URL
158
            );
159
            $params['accept_media_types'] = '*/*';
160
            $params['accept_presentation_document_targets'] = 'iframe';
161
            $params['title'] = $tool->getTitle();
162
            $params['text'] = $tool->getDescription();
163
            $params['data'] = 'tool:'.$tool->getId();
164
        } else {
165
            $params['lti_message_type'] = 'basic-lti-launch-request';
166
            $params['resource_link_id'] = $tool->getId();
167
            $params['resource_link_title'] = $tool->getTitle();
168
            $params['resource_link_description'] = $tool->getDescription();
169
170
            $toolEval = $tool->getGradebookEval();
171
172
            if (!empty($toolEval)) {
173
                $params['lis_result_sourcedid'] = json_encode(
174
                    [
175
                        'e' => $toolEval->getId(),
176
                        'u' => $user->getId(),
177
                        'l' => uniqid(),
178
                        'lt' => time(),
179
                    ]
180
                );
181
                $params['lis_outcome_service_url'] = api_get_path(WEB_PATH).'lti/os';
182
                /* $params['lis_outcome_service_url'] = $this->generateUrl(
183
                    'chamilo_lti_os',
184
                    [],
185
                    UrlGeneratorInterface::ABSOLUTE_URL
186
                ); */
187
                $params['lis_person_sourcedid'] = "{$institutionDomain}:{$toolUserId}";
188
                $params['lis_course_section_sourcedid'] = "{$institutionDomain}:".$course->getId();
189
190
                if ($session) {
191
                    $params['lis_course_section_sourcedid'] .= ':'.$session->getId();
192
                }
193
            }
194
        }
195
196
        $params['user_id'] = $toolUserId;
197
198
        if ($tool->isSharingPicture()) {
199
            $params['user_image'] = UserManager::getUserPicture($user->getId());
200
        }
201
202
        $params['roles'] = Utils::generateUserRoles($user);
203
204
        if ($tool->isSharingName()) {
205
            $params['lis_person_name_given'] = $user->getFirstname();
206
            $params['lis_person_name_family'] = $user->getLastname();
207
            $params['lis_person_name_full'] = $user->getFirstname().' '.$user->getLastname();
208
        }
209
210
        if ($tool->isSharingEmail()) {
211
            $params['lis_person_contact_email_primary'] = $user->getEmail();
212
        }
213
214
        if ($user->hasRole('ROLE_RRHH')) {
215
            $scopeMentor = $ltiUtil->generateRoleScopeMentor($user);
216
217
            if (!empty($scopeMentor)) {
218
                $params['role_scope_mentor'] = $scopeMentor;
219
            }
220
        }
221
222
        $params['context_id'] = $course->getId();
223
        $params['context_type'] = 'CourseSection';
224
        $params['context_label'] = $course->getCode();
225
        $params['context_title'] = $course->getTitle();
226
        $params['launch_presentation_locale'] = 'en';
227
        $params['launch_presentation_document_target'] = 'iframe';
228
        $params['tool_consumer_info_product_family_code'] = 'Chamilo LMS';
229
        $params['tool_consumer_info_version'] = '2.0';
230
        $params['tool_consumer_instance_guid'] = $institutionDomain;
231
        $params['tool_consumer_instance_name'] = $settingsManager->getSetting('platform.site_name');
232
        $params['tool_consumer_instance_url'] = $this->generateUrl(
233
            'home',
234
            [],
235
            UrlGeneratorInterface::ABSOLUTE_URL
236
        );
237
        $params['tool_consumer_instance_contact_email'] = $settingsManager->getSetting('admin.administrator_email');
238
239
        $params['oauth_callback'] = 'about:blank';
240
241
        $customParams = $tool->parseCustomParams();
242
        Utils::trimParams($customParams);
243
        $this->variableSubstitution($params, $customParams, $user, $course, $session);
244
245
        $params += $customParams;
246
        Utils::trimParams($params);
247
248
        if (!empty($tool->getConsumerKey()) && !empty($tool->getSharedSecret())) {
249
            $consumer = new OAuthConsumer(
250
                $tool->getConsumerKey(),
251
                $tool->getSharedSecret(),
252
                null
253
            );
254
            $hmacMethod = new OAuthSignatureMethod_HMAC_SHA1();
255
256
            $request = OAuthRequest::from_consumer_and_token(
257
                $consumer,
258
                '',
259
                'POST',
260
                $tool->getLaunchUrl(),
261
                $params
262
            );
263
            $request->sign_request($hmacMethod, $consumer, '');
264
265
            $params = $request->get_parameters();
266
        }
267
268
        Utils::removeQueryParamsFromLaunchUrl($tool, $params);
269
270
        return $this->render(
271
            '@ChamiloCore/Lti/launch.html.twig',
272
            [
273
                'params' => $params,
274
                'launch_url' => $tool->getLaunchUrl(),
275
            ]
276
        );
277
    }
278
279
    #[Route(path: '/item_return', name: 'chamilo_lti_return_item')]
280
    public function returnItem(Request $request): Response
281
    {
282
        $contentItems = $request->get('content_items');
283
        $data = $request->get('data');
284
285
        if (empty($contentItems) || empty($data)) {
286
            throw $this->createAccessDeniedException();
287
        }
288
289
        $em = $this->managerRegistry->getManager();
290
291
        /** @var ExternalTool $tool */
292
        $tool = $em->find(ExternalTool::class, str_replace('tool:', '', $data));
293
294
        if (empty($tool)) {
295
            throw $this->createNotFoundException('External tool not found');
296
        }
297
298
        $course = $this->getCourse();
299
        $url = $this->generateUrl(
300
            'chamilo_lti_return_item',
301
            [
302
                'code' => $course->getCode(),
303
            ],
304
            UrlGeneratorInterface::ABSOLUTE_URL
305
        );
306
307
        $signatureIsValid = Utils::checkRequestSignature(
308
            $url,
309
            $request->get('oauth_consumer_key'),
310
            $request->get('oauth_signature'),
311
            $tool
312
        );
313
314
        if (!$signatureIsValid) {
315
            throw $this->createAccessDeniedException();
316
        }
317
318
        $contentItems = json_decode($contentItems, true)['@graph'];
319
320
        $supportedItemTypes = ['LtiLinkItem'];
321
322
        foreach ($contentItems as $contentItem) {
323
            if (!\in_array($contentItem['@type'], $supportedItemTypes, true)) {
324
                continue;
325
            }
326
327
            if ('LtiLinkItem' === $contentItem['@type']) {
328
                $newTool = $this->createLtiLink($contentItem, $tool);
329
330
                $this->addFlash(
331
                    'success',
332
                    sprintf(
333
                        $this->trans('External tool added: %s'),
334
                        $newTool->getTitle()
335
                    )
336
                );
337
            }
338
        }
339
340
        return $this->render(
341
            '@ChamiloCore/Lti/item_return.html.twig',
342
            [
343
                'course' => $course,
344
            ]
345
        );
346
    }
347
348
    #[Route(path: '/{id}', name: 'chamilo_lti_show', requirements: ['id' => '\d+'])]
349
    public function show(int $id): Response
350
    {
351
        $course = $this->getCourse();
352
353
        $em = $this->managerRegistry->getManager();
354
355
        /** @var null|ExternalTool $externalTool */
356
        $externalTool = $em->find(ExternalTool::class, $id);
357
358
        if (empty($externalTool)) {
359
            throw $this->createNotFoundException();
360
        }
361
362
        if (empty($externalTool->getCourse()) || $externalTool->getCourse()->getId() !== $course->getId()) {
363
            throw $this->createAccessDeniedException('');
364
        }
365
366
        return $this->render(
367
            '@ChamiloCore/Lti/iframe.html.twig',
368
            [
369
                'tool' => $externalTool,
370
                'course' => $course,
371
            ]
372
        );
373
    }
374
375
    /**
376
     * @Security("is_granted('ROLE_TEACHER')")
377
     */
378
    #[Route(path: '/', name: 'chamilo_lti_configure')]
379
    #[Route(path: '/add/{id}', name: 'chamilo_lti_configure_global', requirements: ['id' => '\d+'])]
380
    public function courseConfigure(?int $id, Request $request): Response
381
    {
382
        $em = $this->managerRegistry->getManager();
383
        $repo = $em->getRepository(ExternalTool::class);
384
385
        $externalTool = new ExternalTool();
386
387
        if (null !== $id) {
388
            $parentTool = $repo->findOneBy([
389
                'id' => $id,
390
                'course' => null,
391
            ]);
392
393
            if (empty($parentTool)) {
394
                throw $this->createNotFoundException('External tool not found');
395
            }
396
397
            $externalTool = clone $parentTool;
398
            $externalTool->setToolParent($parentTool);
399
        }
400
401
        $course = $this->getCourse();
402
403
        $form = $this->createForm(ExternalToolType::class, $externalTool);
404
        $form->get('shareName')->setData($externalTool->isSharingName());
405
        $form->get('shareEmail')->setData($externalTool->isSharingEmail());
406
        $form->get('sharePicture')->setData($externalTool->isSharingPicture());
407
        $form->handleRequest($request);
408
409
        if (!$form->isSubmitted() || !$form->isValid()) {
410
            $categories = Category::load(null, null, $course->getId());
411
            $actions = '';
412
413
            if (!empty($categories)) {
414
                $actions .= Display::url(
415
                    Display::getMdiIcon(ToolIcon::GRADEBOOK, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Add to gradebook')),
416
                    $this->generateUrl(
417
                        'chamilo_lti_grade',
418
                        [
419
                            'catId' => $categories[0]->get_id(),
420
                            'course_code' => $course->getCode(),
421
                        ]
422
                    )
423
                );
424
            }
425
426
            return $this->render(
427
                '@ChamiloCore/Lti/course_configure.twig',
428
                [
429
                    'title' => $this->trans('Add external tool'),
430
                    'added_tools' => $repo->findBy([
431
                        'course' => $course,
432
                    ]),
433
                    'global_tools' => $repo->findBy([
434
                        'parent' => null,
435
                        'course' => null,
436
                    ]),
437
                    'form' => $form,
438
                    'course' => $course,
439
                    'actions' => $actions,
440
                ]
441
            );
442
        }
443
444
        /** @var ExternalTool $externalTool */
445
        $externalTool = $form->getData();
446
        $externalTool
447
            ->setCourse($course)
448
            ->setParent($course)
449
            ->addCourseLink($course)
450
        ;
451
452
        $em->persist($externalTool);
453
        $em->flush();
454
455
        $this->addFlash('success', $this->trans('External tool added'));
456
457
        $user = $this->userHelper->getCurrent();
458
459
        if (!$externalTool->isActiveDeepLinking()) {
460
            $this->shortcutRepository->addShortCut($externalTool, $user, $course);
461
462
            return $this->redirectToRoute(
463
                'chamilo_core_course_home',
464
                [
465
                    'cid' => $course->getId(),
466
                ]
467
            );
468
        }
469
470
        return $this->redirectToRoute(
471
            'chamilo_lti_configure',
472
            [
473
                'course' => $course->getCode(),
474
            ]
475
        );
476
    }
477
478
    /**
479
     * @Security("is_granted('ROLE_TEACHER')")
480
     *
481
     * @param string $catId
482
     *
483
     * @throws Exception
484
     */
485
    #[Route(path: '/grade/{catId}', name: 'chamilo_lti_grade', requirements: ['catId' => '\d+'])]
486
    public function grade(int $catId): Response
487
    {
488
        $em = $this->managerRegistry->getManager();
489
        $toolRepo = $em->getRepository(ExternalTool::class);
490
        $course = $this->getCourse();
491
492
        $user = $this->userHelper->getCurrent();
493
494
        $categories = Category::load(null, null, $course->getId());
495
496
        if (empty($categories)) {
497
            throw $this->createNotFoundException();
498
        }
499
500
        $evaladd = new Evaluation();
501
        $evaladd->set_user_id($user->getId());
502
503
        if (!empty($catId)) {
504
            $evaladd->set_category_id($catId);
505
            $evaladd->set_course_code($course->getCode());
0 ignored issues
show
Bug introduced by
The method set_course_code() does not exist on Evaluation. ( Ignorable by Annotation )

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

505
            $evaladd->/** @scrutinizer ignore-call */ 
506
                      set_course_code($course->getCode());

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...
506
        } else {
507
            $evaladd->set_category_id(0);
508
        }
509
510
        $form = new EvalForm(
511
            EvalForm::TYPE_ADD,
512
            $evaladd,
513
            null,
514
            'add_eval_form',
515
            null,
516
            $this->generateUrl(
517
                'chamilo_lti_grade',
518
                [
519
                    'catId' => $catId,
520
                    'code' => $course->getCode(),
521
                ]
522
            ).'?'.api_get_cidreq()
523
        );
524
        $form->removeElement('name');
525
        $form->removeElement('addresult');
526
527
        /** @var HTML_QuickForm_select $slcLtiTools */
528
        $slcLtiTools = $form->createElement('select', 'name', $this->trans('External tool'));
529
        $form->insertElementBefore($slcLtiTools, 'hid_category_id');
530
        $form->addRule('name', get_lang('Required field'), 'required');
531
532
        $tools = $toolRepo->findBy([
533
            'course' => $course,
534
            'gradebookEval' => null,
535
        ]);
536
537
        /** @var ExternalTool $tool */
538
        foreach ($tools as $tool) {
539
            $slcLtiTools->addOption($tool->getTitle(), $tool->getId());
540
        }
541
542
        if (!$form->validate()) {
543
            return $this->render(
544
                '@ChamiloCore/Lti/gradebook.html.twig',
545
                [
546
                    'form' => $form->returnForm(),
547
                ]
548
            );
549
        }
550
551
        $values = $form->exportValues();
552
553
        $tool = $toolRepo->find($values['name']);
554
555
        if (empty($tool)) {
556
            throw $this->createNotFoundException();
557
        }
558
559
        $eval = new Evaluation();
560
        $eval->set_name($tool->getTitle());
561
        $eval->set_description($values['description']);
562
        $eval->set_user_id($values['hid_user_id']);
563
564
        if (!empty($values['hid_course_code'])) {
565
            $eval->set_course_code($values['hid_course_code']);
566
        }
567
568
        $eval->set_course_code($course->getCode());
569
        $eval->set_category_id($values['hid_category_id']);
570
571
        $values['weight'] = $values['weight_mask'];
572
573
        $eval->set_weight($values['weight']);
574
        $eval->set_max($values['max']);
575
        $eval->set_visible(empty($values['visible']) ? 0 : 1);
576
        $eval->add();
577
578
        $gradebookEval = $em->find('ChamiloCoreBundle:GradebookEvaluation', $eval->get_id());
579
580
        $tool->setGradebookEval($gradebookEval);
581
582
        $em->persist($tool);
583
        $em->flush();
584
585
        $this->addFlash('success', $this->trans('Evaluation for external tool added'));
586
587
        return $this->redirect(api_get_course_url());
588
    }
589
590
    private function variableSubstitution(
591
        array $params,
592
        array &$customParams,
593
        User $user,
594
        Course $course,
595
        ?Session $session = null
596
    ): void {
597
        $replaceable = self::getReplaceableVariables($user, $course, $session);
598
        $variables = array_keys($replaceable);
599
600
        foreach ($customParams as $customKey => $customValue) {
601
            if (!\in_array($customValue, $variables, true)) {
602
                continue;
603
            }
604
605
            $val = $replaceable[$customValue];
606
607
            if (\is_array($val)) {
608
                $val = current($val);
609
610
                if (\array_key_exists($val, $params)) {
611
                    $customParams[$customKey] = $params[$val];
612
613
                    continue;
614
                }
615
                $val = false;
616
            }
617
618
            if (false === $val) {
619
                $customParams[$customKey] = $customValue;
620
621
                continue;
622
            }
623
624
            $customParams[$customKey] = $replaceable[$customValue];
625
        }
626
    }
627
628
    private static function getReplaceableVariables(User $user, Course $course, ?Session $session = null): array
629
    {
630
        return [
631
            '$User.id' => $user->getId(),
632
            '$User.image' => ['user_image'],
633
            '$User.username' => $user->getUsername(),
634
635
            '$Person.sourcedId' => false,
636
            '$Person.name.full' => $user->getFullname(),
637
            '$Person.name.family' => $user->getLastname(),
638
            '$Person.name.given' => $user->getFirstname(),
639
            '$Person.name.middle' => false,
640
            '$Person.name.prefix' => false,
641
            '$Person.name.suffix' => false,
642
            '$Person.address.street1' => $user->getAddress(),
643
            '$Person.address.street2' => false,
644
            '$Person.address.street3' => false,
645
            '$Person.address.street4' => false,
646
            '$Person.address.locality' => false,
647
            '$Person.address.statepr' => false,
648
            '$Person.address.country' => false,
649
            '$Person.address.postcode' => false,
650
            '$Person.address.timezone' => false,
651
            // $user->getTimezone(),
652
            '$Person.phone.mobile' => false,
653
            '$Person.phone.primary' => $user->getPhone(),
654
            '$Person.phone.home' => false,
655
            '$Person.phone.work' => false,
656
            '$Person.email.primary' => $user->getEmail(),
657
            '$Person.email.personal' => false,
658
            '$Person.webaddress' => false,
659
            // $user->getWebsite(),
660
            '$Person.sms' => false,
661
662
            '$CourseTemplate.sourcedId' => false,
663
            '$CourseTemplate.label' => false,
664
            '$CourseTemplate.title' => false,
665
            '$CourseTemplate.shortDescription' => false,
666
            '$CourseTemplate.longDescription' => false,
667
            '$CourseTemplate.courseNumber' => false,
668
            '$CourseTemplate.credits' => false,
669
670
            '$CourseOffering.sourcedId' => false,
671
            '$CourseOffering.label' => false,
672
            '$CourseOffering.title' => false,
673
            '$CourseOffering.shortDescription' => false,
674
            '$CourseOffering.longDescription' => false,
675
            '$CourseOffering.courseNumber' => false,
676
            '$CourseOffering.credits' => false,
677
            '$CourseOffering.academicSession' => false,
678
679
            '$CourseSection.sourcedId' => ['lis_course_section_sourcedid'],
680
            '$CourseSection.label' => $course->getCode(),
681
            '$CourseSection.title' => $course->getTitle(),
682
            '$CourseSection.shortDescription' => false,
683
            '$CourseSection.longDescription' => $session && $session->getShowDescription()
684
                ? $session->getDescription()
685
                : false,
686
            '$CourseSection.courseNumber' => false,
687
            '$CourseSection.credits' => false,
688
            '$CourseSection.maxNumberofStudents' => false,
689
            '$CourseSection.numberofStudents' => false,
690
            '$CourseSection.dept' => false,
691
            '$CourseSection.timeFrame.begin' => $session && $session->getDisplayStartDate()
692
                ? $session->getDisplayStartDate()->format('Y-m-d\TH:i:sP')
693
                : false,
694
            '$CourseSection.timeFrame.end' => $session && $session->getDisplayEndDate()
695
                ? $session->getDisplayEndDate()->format('Y-m-d\TH:i:sP')
696
                : false,
697
            '$CourseSection.enrollControl.accept' => false,
698
            '$CourseSection.enrollControl.allowed' => false,
699
            '$CourseSection.dataSource' => false,
700
            '$CourseSection.sourceSectionId' => false,
701
702
            '$Group.sourcedId' => false,
703
            '$Group.grouptype.scheme' => false,
704
            '$Group.grouptype.typevalue' => false,
705
            '$Group.grouptype.level' => false,
706
            '$Group.email' => false,
707
            '$Group.url' => false,
708
            '$Group.timeFrame.begin' => false,
709
            '$Group.timeFrame.end' => false,
710
            '$Group.enrollControl.accept' => false,
711
            '$Group.enrollControl.allowed' => false,
712
            '$Group.shortDescription' => false,
713
            '$Group.longDescription' => false,
714
            '$Group.parentId' => false,
715
716
            '$Membership.sourcedId' => false,
717
            '$Membership.collectionSourcedId' => false,
718
            '$Membership.personSourcedId' => false,
719
            '$Membership.status' => false,
720
            '$Membership.role' => ['roles'],
721
            '$Membership.createdTimestamp' => false,
722
            '$Membership.dataSource' => false,
723
724
            '$LineItem.sourcedId' => false,
725
            '$LineItem.type' => false,
726
            '$LineItem.type.displayName' => false,
727
            '$LineItem.resultValue.max' => false,
728
            '$LineItem.resultValue.list' => false,
729
            '$LineItem.dataSource' => false,
730
731
            '$Result.sourcedGUID' => ['lis_result_sourcedid'],
732
            '$Result.sourcedId' => ['lis_result_sourcedid'],
733
            '$Result.createdTimestamp' => false,
734
            '$Result.status' => false,
735
            '$Result.resultScore' => false,
736
            '$Result.dataSource' => false,
737
738
            '$ResourceLink.title' => ['resource_link_title'],
739
            '$ResourceLink.description' => ['resource_link_description'],
740
        ];
741
    }
742
743
    private function createLtiLink(array &$contentItem, ExternalTool $baseTool): ExternalTool
744
    {
745
        $newTool = clone $baseTool;
746
        $newTool->setToolParent($baseTool);
747
        $newTool->setActiveDeepLinking(false);
748
749
        if (!empty($contentItem['title'])) {
750
            $newTool->setTitle($contentItem['title']);
751
        }
752
753
        if (!empty($contentItem['text'])) {
754
            $newTool->setDescription($contentItem['text']);
755
        }
756
757
        if (!empty($contentItem['url'])) {
758
            $newTool->setLaunchUrl($contentItem['url']);
759
        }
760
761
        if (!empty($contentItem['custom'])) {
762
            $newTool->setCustomParams(
763
                $newTool->encodeCustomParams($contentItem['custom'])
764
            );
765
        }
766
767
        $em = $this->managerRegistry->getManager();
768
769
        $course = $newTool->getCourse();
770
771
        $newTool->addCourseLink($course);
772
773
        $em->persist($newTool);
774
        $em->flush();
775
776
        $user = $this->userHelper->getCurrent();
777
        $this->shortcutRepository->addShortCut($newTool, $user, $course);
778
779
        return $newTool;
780
    }
781
}
782