CourseController   F
last analyzed

Complexity

Total Complexity 66

Size/Duplication

Total Lines 735
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 442
dl 0
loc 735
rs 3.12
c 0
b 0
f 0
wmc 66

10 Methods

Rating   Name   Duplication   Size   Complexity  
B returnItem() 0 65 8
A show() 0 23 4
B edit() 0 72 6
A __construct() 0 5 1
D launch() 0 153 14
A createLtiLink() 0 37 5
A variableSubstitution() 0 35 6
B getReplaceableVariables() 0 112 7
B grade() 0 104 8
B courseConfigure() 0 97 7

How to fix   Complexity   

Complex Class

Complex classes like CourseController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CourseController, and based on these observations, apply Extract Interface, too.

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\Entity\Course;
11
use Chamilo\CoreBundle\Entity\GradebookEvaluation;
12
use Chamilo\CoreBundle\Entity\Session;
13
use Chamilo\CoreBundle\Entity\User;
14
use Chamilo\CoreBundle\Enums\ToolIcon;
15
use Chamilo\CoreBundle\Helpers\UserHelper;
16
use Chamilo\CourseBundle\Controller\ToolBaseController;
17
use Chamilo\CourseBundle\Entity\CTool;
18
use Chamilo\CourseBundle\Repository\CShortcutRepository;
19
use Chamilo\LtiBundle\Entity\ExternalTool;
20
use Chamilo\LtiBundle\Form\ExternalToolType;
21
use Chamilo\LtiBundle\Util\Utils;
22
use Display;
23
use Doctrine\Persistence\ManagerRegistry;
24
use EvalForm;
25
use Evaluation;
26
use HTML_QuickForm_select;
27
use OAuthConsumer;
28
use OAuthRequest;
29
use OAuthSignatureMethod_HMAC_SHA1;
30
use Symfony\Component\HttpFoundation\Request;
31
use Symfony\Component\HttpFoundation\Response;
32
use Symfony\Component\Routing\Attribute\Route;
33
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
34
use Symfony\Component\Security\Http\Attribute\IsGranted;
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()) {
0 ignored issues
show
Bug introduced by
The method getCourse() does not exist on Chamilo\LtiBundle\Entity\ExternalTool. ( Ignorable by Annotation )

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

140
        if (empty($tool->/** @scrutinizer ignore-call */ getCourse()) || $tool->getCourse()->getId() !== $course->getId()) {

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...
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->isHRM()) {
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
    #[IsGranted('ROLE_TEACHER')]
376
    #[Route(path: '/', name: 'chamilo_lti_configure')]
377
    #[Route(path: '/add/{id}', name: 'chamilo_lti_configure_global', requirements: ['id' => '\d+'])]
378
    public function courseConfigure(?int $id, Request $request): Response
379
    {
380
        $em = $this->managerRegistry->getManager();
381
        $repo = $em->getRepository(ExternalTool::class);
382
383
        $externalTool = new ExternalTool();
384
385
        if (null !== $id) {
386
            $parentTool = $repo->findOneBy([
387
                'id' => $id,
388
                'course' => null,
389
            ]);
390
391
            if (empty($parentTool)) {
392
                throw $this->createNotFoundException('External tool not found');
393
            }
394
395
            $externalTool = clone $parentTool;
396
            $externalTool->setToolParent($parentTool);
397
        }
398
399
        $course = $this->getCourse();
400
401
        $form = $this->createForm(ExternalToolType::class, $externalTool);
402
        $form->get('shareName')->setData($externalTool->isSharingName());
403
        $form->get('shareEmail')->setData($externalTool->isSharingEmail());
404
        $form->get('sharePicture')->setData($externalTool->isSharingPicture());
405
        $form->handleRequest($request);
406
407
        if (!$form->isSubmitted() || !$form->isValid()) {
408
            $categories = Category::load(null, null, $course->getId());
409
            $actions = '';
410
411
            if (!empty($categories)) {
412
                $actions .= Display::url(
413
                    Display::getMdiIcon(ToolIcon::GRADEBOOK, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Add to gradebook')),
414
                    $this->generateUrl(
415
                        'chamilo_lti_grade',
416
                        [
417
                            'catId' => $categories[0]->get_id(),
418
                            'course_code' => $course->getCode(),
419
                        ]
420
                    )
421
                );
422
            }
423
424
            return $this->render(
425
                '@ChamiloCore/Lti/course_configure.twig',
426
                [
427
                    'title' => $this->trans('Add external tool'),
428
                    'added_tools' => $repo->findBy([
429
                        'course' => $course,
430
                    ]),
431
                    'global_tools' => $repo->findBy([
432
                        'parent' => null,
433
                        'course' => null,
434
                    ]),
435
                    'form' => $form,
436
                    'course' => $course,
437
                    'actions' => $actions,
438
                ]
439
            );
440
        }
441
442
        /** @var ExternalTool $externalTool */
443
        $externalTool = $form->getData();
444
        $externalTool
445
            ->setCourse($course)
0 ignored issues
show
Bug introduced by
The method setCourse() does not exist on Chamilo\LtiBundle\Entity\ExternalTool. ( Ignorable by Annotation )

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

445
            ->/** @scrutinizer ignore-call */ 
446
              setCourse($course)

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...
446
            ->setParent($course)
447
            ->addCourseLink($course)
448
        ;
449
450
        $em->persist($externalTool);
451
        $em->flush();
452
453
        $this->addFlash('success', $this->trans('External tool added'));
454
455
        $user = $this->userHelper->getCurrent();
456
457
        if (!$externalTool->isActiveDeepLinking()) {
458
            $this->shortcutRepository->addShortCut($externalTool, $user, $course);
459
460
            return $this->redirectToRoute(
461
                'chamilo_core_course_home',
462
                [
463
                    'cid' => $course->getId(),
464
                ]
465
            );
466
        }
467
468
        return $this->redirectToRoute(
469
            'chamilo_lti_configure',
470
            [
471
                'course' => $course->getCode(),
472
            ]
473
        );
474
    }
475
476
    #[Route(path: '/grade/{catId}', name: 'chamilo_lti_grade', requirements: ['catId' => '\d+'])]
477
    #[IsGranted('ROLE_TEACHER')]
478
    public function grade(int $catId): Response
479
    {
480
        $em = $this->managerRegistry->getManager();
481
        $toolRepo = $em->getRepository(ExternalTool::class);
482
        $course = $this->getCourse();
483
484
        $user = $this->userHelper->getCurrent();
485
486
        $categories = Category::load(null, null, $course->getId());
487
488
        if (empty($categories)) {
489
            throw $this->createNotFoundException();
490
        }
491
492
        $evaladd = new Evaluation();
493
        $evaladd->set_user_id($user->getId());
494
495
        if (!empty($catId)) {
496
            $evaladd->set_category_id($catId);
497
            $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

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