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

ImsLti::getCourseSectionSourcedId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 3
dl 0
loc 9
rs 10
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Entity\Course;
5
use Chamilo\CoreBundle\Entity\Session;
6
use Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool;
7
use Chamilo\UserBundle\Entity\User;
8
9
/**
10
 * Class ImsLti.
11
 */
12
class ImsLti
13
{
14
    const V_1P1 = 'lti1p1';
15
    const V_1P3 = 'lti1p3';
16
    const LTI_RSA_KEY = 'rsa_key';
17
    const LTI_JWK_KEYSET = 'jwk_keyset';
18
19
    /**
20
     * @param Session|null $session    Optional.
21
     * @param string       $domain     Optional. Institution domain.
22
     * @param string       $ltiVersion Optional. Default is lti1p1.
23
     *
24
     * @return array
25
     */
26
    public static function getSubstitutableVariables(
27
        User $user,
28
        Course $course,
29
        Session $session = null,
30
        $domain = '',
31
        $ltiVersion = self::V_1P1,
32
        ImsLtiTool $tool
33
    ) {
34
        $isLti1p3 = $ltiVersion === self::V_1P3;
35
36
        return [
37
            '$User.id' => $user->getId(),
38
            '$User.image' => $isLti1p3 ? ['claim' => 'sub'] : ['user_image'],
39
            '$User.username' => $user->getUsername(),
40
            '$User.org' => false,
41
            '$User.scope.mentor' => $isLti1p3 ? ['claim' => '/claim/role_scope_mentor'] : ['role_scope_mentor'],
42
43
            '$Person.sourcedId' => $isLti1p3
44
                ? self::getPersonSourcedId($domain, $user)
45
                : "$domain:".ImsLtiPlugin::getLaunchUserIdClaim($tool, $user),
46
            '$Person.name.full' => $user->getFullname(),
47
            '$Person.name.family' => $user->getLastname(),
48
            '$Person.name.given' => $user->getFirstname(),
49
            '$Person.address.street1' => $user->getAddress(),
50
            '$Person.phone.primary' => $user->getPhone(),
51
            '$Person.email.primary' => $user->getEmail(),
52
53
            '$CourseSection.sourcedId' => $isLti1p3
54
                ? ['claim' => '/claim/lis', 'property' => 'course_section_sourcedid']
55
                : ['lis_course_section_sourcedid'],
56
            '$CourseSection.label' => $course->getCode(),
57
            '$CourseSection.title' => $course->getTitle(),
58
            '$CourseSection.longDescription' => $session && $session->getShowDescription()
59
                ? $session->getDescription()
60
                : false,
61
            '$CourseSection.timeFrame.begin' => $session && $session->getDisplayStartDate()
62
                ? $session->getDisplayStartDate()->format(DateTime::ATOM)
63
                : '$CourseSection.timeFrame.begin',
64
            '$CourseSection.timeFrame.end' => $session && $session->getDisplayEndDate()
65
                ? $session->getDisplayEndDate()->format(DateTime::ATOM)
66
                : '$CourseSection.timeFrame.end',
67
68
            '$Membership.role' => $isLti1p3 ? ['claim' => '/claim/roles'] : ['roles'],
69
70
            '$Result.sourcedGUID' => $isLti1p3 ? ['claim' => 'sub'] : ['lis_result_sourcedid'],
71
            '$Result.sourcedId' => $isLti1p3 ? ['claim' => 'sub'] : ['lis_result_sourcedid'],
72
73
            '$ResourceLink.id' => $isLti1p3
74
                ? ['claim' => '/claim/resource_link', 'property' => 'id']
75
                : ['resource_link_id'],
76
            '$ResourceLink.title' => $isLti1p3
77
                ? ['claim' => '/claim/resource_link', 'property' => 'title']
78
                : ['resource_link_title'],
79
            '$ResourceLink.description' => $isLti1p3
80
                ? ['claim' => '/claim/resource_link', 'property' => 'description']
81
                : ['resource_link_description'],
82
        ];
83
    }
84
85
    /**
86
     * @param array        $launchParams All params for launch.
87
     * @param array        $customParams Custom params where search variables to substitute.
88
     * @param Session|null $session      Optional.
89
     * @param string       $domain       Optional. Institution domain.
90
     * @param string       $ltiVersion   Optional. Default is lti1p1.
91
     *
92
     * @return array
93
     */
94
    public static function substituteVariablesInCustomParams(
95
        array $launchParams,
96
        array $customParams,
97
        User $user,
98
        Course $course,
99
        Session $session = null,
100
        $domain = '',
101
        $ltiVersion = self::V_1P1,
102
        ImsLtiTool $tool
103
    ) {
104
        $substitutables = self::getSubstitutableVariables($user, $course, $session, $domain, $ltiVersion, $tool);
105
        $variables = array_keys($substitutables);
106
107
        foreach ($customParams as $customKey => $customValue) {
108
            if (!in_array($customValue, $variables)) {
109
                continue;
110
            }
111
112
            $substitute = $substitutables[$customValue];
113
114
            if (is_array($substitute)) {
115
                if ($ltiVersion === self::V_1P1) {
116
                    $substitute = current($substitute);
117
118
                    $substitute = $launchParams[$substitute];
119
                } elseif ($ltiVersion === self::V_1P3) {
120
                    $claim = array_key_exists($substitute['claim'], $launchParams)
121
                        ? $substitute['claim']
122
                        : "https://purl.imsglobal.org/spec/lti{$substitute['claim']}";
123
124
                    $substitute = empty($substitute['property'])
125
                        ? $launchParams[$claim]
126
                        : $launchParams[$claim][$substitute['property']];
127
                } else {
128
                    continue;
129
                }
130
            }
131
132
            $customParams[$customKey] = $substitute;
133
        }
134
135
        array_walk_recursive(
136
            $customParams,
137
            function (&$value) {
138
                if (gettype($value) !== 'array') {
139
                    $value = (string) $value;
140
                }
141
            }
142
        );
143
144
        return $customParams;
145
    }
146
147
    /**
148
     * Generate a user sourced ID for LIS.
149
     *
150
     * @param string $domain
151
     *
152
     * @return string
153
     */
154
    public static function getPersonSourcedId($domain, User $user)
155
    {
156
        $sourceId = [$domain, $user->getId()];
157
158
        return implode(':', $sourceId);
159
    }
160
161
    /**
162
     * Generate a course sourced ID for LIS.
163
     *
164
     * @param string  $domain
165
     * @param Session $session Optional.
166
     *
167
     * @return string
168
     */
169
    public static function getCourseSectionSourcedId($domain, Course $course, Session $session = null)
170
    {
171
        $sourceId = [$domain, $course->getId()];
172
173
        if ($session) {
174
            $sourceId[] = $session->getId();
175
        }
176
177
        return implode(':', $sourceId);
178
    }
179
180
    /**
181
     * Get instances for LTI Advantage services.
182
     *
183
     * @return array
184
     */
185
    public static function getAdvantageServices(ImsLtiTool $tool)
186
    {
187
        return [
188
            new LtiAssignmentGradesService($tool),
189
            new LtiNamesRoleProvisioningService($tool),
190
        ];
191
    }
192
193
    /**
194
     * @param int $length
195
     *
196
     * @return string
197
     */
198
    public static function generateClientId($length = 20)
199
    {
200
        $hash = md5(mt_rand().time());
201
202
        $clientId = '';
203
204
        for ($p = 0; $p < $length; $p++) {
205
            $op = mt_rand(1, 3);
206
207
            if ($op === 1) {
208
                $char = chr(mt_rand(97, 97 + 25));
209
            } elseif ($op === 2) {
210
                $char = chr(mt_rand(65, 65 + 25));
211
            } else {
212
                $char = substr($hash, mt_rand(0, strlen($hash) - 1), 1);
213
            }
214
215
            $clientId .= $char;
216
        }
217
218
        return $clientId;
219
    }
220
221
    /**
222
     * Validate the format ISO 8601 for date strings coming from JSON or JavaScript.
223
     *
224
     * @see https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/ Pattern source.
225
     *
226
     * @param string $strDate
227
     *
228
     * @return bool
229
     */
230
    public static function validateFormatDateIso8601($strDate)
231
    {
232
        $pattern = '/^([\+-]?\d{4}(?!\d{2}\b))((-?)('
233
            .'(0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W'
234
            .'([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))('
235
            .'[T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?'
236
            .'([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/';
237
238
        return preg_match($pattern, $strDate) !== false;
239
    }
240
}
241