19declare(strict_types=1);
25use Psr\Http\Message\ServerRequestInterface;
38 0 =>
"il_uuid_user_id",
40 1 =>
"il_uuid_ext_account",
41 5 =>
"il_uuid_SHA256",
42 6 =>
"il_uuid_sha256url",
43 4 =>
"il_uuid_random",
46 private const array
PRIVACY_NAMES = [0 =>
"none", 1 =>
"firstname", 2 =>
"lastname", 3 =>
"fullname"];
47 private const string DEPRECATION_URL =
"https://www.1edtech.org/lti-security-announcement-and-deprecation-schedule";
53 private readonly
Factory $ui_factory,
56 private readonly
int $tool_id,
58 private readonly
bool $in_administration =
false
67 public function getForm(
string $action,
string $submit_label =
''): Form
69 $field = $this->ui_factory->input()->field();
71 $text = fn(
string $column) => (string) ($row[$column] ??
"");
72 $flag = fn(
string $column) => (bool) ($row[$column] ??
false);
75 "title" => $field->text($this->
lng->txt(
"lti_con_prov_title"))->withRequired(
true)->withValue(
$text(
"title")),
76 "description" => $field->text($this->lng->txt(
"lti_con_prov_description"))->
withValue(
$text(
"description")),
79 if ($this->in_administration) {
80 $availability = $field->radio($this->
lng->txt(
"lti_con_prov_availability"));
82 $availability = $availability->withOption((
string) $value, $label);
84 $general_inputs[
"availability"] = $availability
90 $this->
lng->txt($this->tool_id > 0 ?
"lti_form_provider_edit" :
"lti_form_provider_create")
94 $privacy_ident = $field->radio(
95 $this->
lng->txt(
"conf_privacy_ident"),
98 foreach (self::PRIVACY_IDENTS as $value => $name) {
99 $privacy_ident = $privacy_ident->withOption(
101 $this->
lng->txt(
"conf_privacy_ident_" . $name),
102 $this->
lng->txt(
"conf_privacy_ident_" . $name .
"_info")
105 $privacy_name = $field->radio($this->
lng->txt(
"conf_privacy_name"), $this->
lng->txt(
"conf_privacy_name_info"));
106 foreach (self::PRIVACY_NAMES as $value => $name) {
107 $privacy_name = $privacy_name->withOption(
109 $this->
lng->txt(
"conf_privacy_name_" . $name),
110 $this->
lng->txt(
"conf_privacy_name_" . $name .
"_info")
113 $privacy = $field->section([
114 "privacy_ident" => $privacy_ident->withValue((
string) ($row[
"privacy_ident"] ?? 0)),
115 "instructor_email" => $field->checkbox(
116 $this->
lng->txt(
"lti_con_prov_instructor_email"),
117 $this->lng->txt(
"lti_con_prov_instructor_email_info")
118 )->withValue($flag(
"instructor_send_email")),
119 "privacy_name" => $privacy_name->withValue((
string) ($row[
"privacy_name"] ?? 0)),
120 "instructor_name" => $field->checkbox(
121 $this->
lng->txt(
"lti_con_prov_instructor_name"),
122 $this->lng->txt(
"lti_con_prov_instructor_name_info")
123 )->withValue($flag(
"instructor_send_name")),
124 "inc_usr_pic" => $field->checkbox(
125 $this->
lng->txt(
"lti_con_prov_inc_usr_pic"),
126 $this->lng->txt(
"lti_con_prov_inc_usr_pic_info")
127 )->withValue($flag(
"inc_usr_pic")),
128 "external_provider" => $field->checkbox(
129 $this->
lng->txt(
"lti_con_prov_external_provider"),
130 $this->lng->txt(
"lti_con_prov_external_provider_info")
131 )->withValue($flag(
"external_provider")),
132 ], $this->
lng->txt(
"lti_con_prov_privacy_settings"));
134 $outcome = $field->optionalGroup([
135 "mastery_score" => $field->numeric(
136 $this->lng->txt(
"lti_con_prov_mastery_score_default"),
137 $this->lng->txt(
"lti_con_prov_mastery_score_default_info")
138 )->withStepSize(0.01)
140 ->withAdditionalTransformation($this->
refinery->int()->isGreaterThanOrEqual(0))
141 ->withAdditionalTransformation($this->
refinery->int()->isLessThanOrEqual(100))
142 ->withValue(round(100 * (
float) ($row[
"mastery_score"] ?? 0.8), 2)),
143 ], $this->
lng->txt(
"lti_con_prov_has_outcome_service"), $this->
lng->txt(
"lti_con_prov_has_outcome_service_info"));
145 "has_outcome" => $flag(
"has_outcome") ? $outcome : $outcome->withValue(
null),
146 ], $this->
lng->txt(
"lti_con_prov_learning_progress_options"));
148 $xapi = $field->optionalGroup([
149 "xapi_launch_url" => $field->text(
150 $this->lng->txt(
"lti_con_prov_xapi_launch_url"),
151 $this->lng->txt(
"lti_con_prov_xapi_launch_url_info")
152 )->withRequired(
true)->withValue(
$text(
"xapi_launch_url")),
153 "xapi_launch_key" => $field->text($this->
lng->txt(
"lti_con_prov_xapi_launch_key"))
154 ->withRequired(
true)->withValue(
$text(
"xapi_launch_key")),
155 "xapi_launch_secret" => $field->text($this->
lng->txt(
"lti_con_prov_xapi_launch_secret"))
156 ->withRequired(
true)->withValue(
$text(
"xapi_launch_secret")),
157 "xapi_activity_id" => $field->text(
158 $this->
lng->txt(
"lti_con_prov_xapi_activity_id"),
159 $this->lng->txt(
"lti_con_prov_xapi_activity_id_info")
160 )->withValue(
$text(
"xapi_activity_id")),
161 ], $this->
lng->txt(
"lti_con_prov_use_xapi"), $this->
lng->txt(
"lti_con_prov_use_xapi_info"));
162 $launch = $field->section([
163 "use_provider_id" => $field->checkbox(
164 $this->lng->txt(
"lti_con_prov_use_provider_id"),
165 $this->lng->txt(
"lti_con_prov_use_provider_id_info")
166 )->withValue($flag(
"use_provider_id")),
167 "always_learner" => $field->checkbox(
168 $this->
lng->txt(
"lti_con_prov_always_learner"),
169 $this->lng->txt(
"lti_con_prov_always_learner_info")
170 )->withValue($flag(
"always_learner")),
171 "use_xapi" => $flag(
"use_xapi") ? $xapi : $xapi->withValue(
null),
172 "custom_params" => $field->textarea(
173 $this->
lng->txt(
"lti_con_prov_custom_params"),
174 $this->lng->txt(
"lti_con_prov_custom_params_info")
175 )->withValue(
$text(
"custom_params")),
176 ], $this->
lng->txt(
"lti_con_prov_launch_options"));
178 $category = $field->radio($this->
lng->txt(
"lti_con_prov_category"), $this->
lng->txt(
"lti_con_prov_category_info"));
180 foreach ($categories as $name => $label) {
181 $category = $category->withOption($name, $label);
183 $group = $field->section([
184 "keywords" => $field->text($this->lng->txt(
"lti_con_prov_keywords"), $this->lng->txt(
"lti_con_prov_keywords_info"))
185 ->withValue(
$text(
"keywords")),
186 "category" => $category->withRequired(
true)->withValue(isset($categories[
$text(
"category")]) ?
$text(
"category") :
"content"),
187 ], $this->
lng->txt(
"lti_con_prov_group_options"));
189 $hints = $field->section([
190 "remarks" => $field->textarea($this->lng->txt(
"lti_con_prov_remarks"))->withValue(
$text(
"remarks")),
191 ], $this->
lng->txt(
"lti_con_prov_hints"));
193 $form = $this->ui_factory->input()->container()->form()->standard($action, [
196 "privacy" => $privacy,
203 return $submit_label ===
'' ? $form : $form->withSubmitLabel($submit_label);
210 public function save(
string $action, ServerRequestInterface
$request,
bool $own_tool =
false): ?Form
212 $form = $this->
getForm($action, $own_tool ? $this->
lng->txt(
"lti_add_own_provider") :
"")->withRequest($request);
213 $data = $form->getData();
214 if (
$data ===
null) {
219 "title" => [
"text",
$data[
"general"][
"title"]],
220 "description" => [
"text",
$data[
"general"][
"description"]],
221 "privacy_ident" => [
"integer", (
int)
$data[
"privacy"][
"privacy_ident"]],
222 "instructor_send_email" => [
"integer", (
int)
$data[
"privacy"][
"instructor_email"]],
223 "privacy_name" => [
"integer", (
int)
$data[
"privacy"][
"privacy_name"]],
224 "instructor_send_name" => [
"integer", (
int)
$data[
"privacy"][
"instructor_name"]],
225 "inc_usr_pic" => [
"integer", (
int)
$data[
"privacy"][
"inc_usr_pic"]],
226 "external_provider" => [
"integer", (
int)
$data[
"privacy"][
"external_provider"]],
227 "has_outcome" => [
"integer", (
int) (
$data[
"learning_progress"][
"has_outcome"] !==
null)],
228 "mastery_score" => [
"float", (
$data[
"learning_progress"][
"has_outcome"][
"mastery_score"] ?? 80) / 100],
229 "use_provider_id" => [
"integer", (
int)
$data[
"launch"][
"use_provider_id"]],
230 "always_learner" => [
"integer", (
int)
$data[
"launch"][
"always_learner"]],
231 "use_xapi" => [
"integer", (
int) (
$data[
"launch"][
"use_xapi"] !==
null)],
232 "xapi_launch_url" => [
"text",
$data[
"launch"][
"use_xapi"][
"xapi_launch_url"] ??
""],
233 "xapi_launch_key" => [
"text",
$data[
"launch"][
"use_xapi"][
"xapi_launch_key"] ??
""],
234 "xapi_launch_secret" => [
"text",
$data[
"launch"][
"use_xapi"][
"xapi_launch_secret"] ??
""],
235 "xapi_activity_id" => [
"text",
$data[
"launch"][
"use_xapi"][
"xapi_activity_id"] ??
""],
236 "custom_params" => [
"text",
$data[
"launch"][
"custom_params"]],
237 "keywords" => [
"text",
$data[
"group"][
"keywords"]],
238 "category" => [
"text",
$data[
"group"][
"category"]],
239 "remarks" => [
"text",
$data[
"hints"][
"remarks"]],
240 "lti_version" => [
"text", $this->version],
245 if ($this->in_administration) {
246 $fields[
"availability"] = [
"integer", (
int)
$data[
"general"][
"availability"]];
247 } elseif ($this->tool_id === 0) {
251 if ($this->tool_id > 0) {
253 $this->saved_id = $this->tool_id;
258 $fields + [
"client_id" => [
"text", Util::getRandomString(15)]],
259 $this->
user->getId(),
279 return $this->ui_factory->input()->field()->section(
281 $this->
lng->txt(
"lti_con_prov_authentication"),
282 $this->isAdvantage() ? $this->getAdvantageByline() :
""
298 $link = $ui_factory->link()->standard(
$lng->txt(
"lti_1p1_deprecated_link"), self::DEPRECATION_URL)
299 ->withOpenInNewViewport(
true);
301 return $ui_factory->messageBox()->confirmation(
$lng->txt(
"lti_1p1_deprecated_info"))->withLinks([$link]);
306 return $this->
lng->txt($this->tool_id === 0 ?
"lti_con_version_1.3_before_id" :
"lti13_hints");
315 $field = $this->ui_factory->input()->field();
316 $key_global = $field->optionalGroup([
317 "provider_key" => $field->text($this->lng->txt(
"lti_con_prov_key"))
318 ->withRequired(
true)->withValue((
string) ($row[
"provider_key"] ??
"")),
319 "provider_secret" => $field->text($this->lng->txt(
"lti_con_prov_secret"))
320 ->withRequired(
true)->withValue((
string) ($row[
"provider_secret"] ??
"")),
321 ], $this->lng->txt(
"lti_con_prov_provider_key_global"), $this->lng->txt(
"lti_con_prov_provider_key_global_info"));
324 "provider_url" => $field->text($this->
lng->txt(
"lti_con_prov_url"))
325 ->withRequired(
true)->withValue((
string) ($row[
"provider_url"] ??
"")),
326 "key_global" => ($row[
"provider_key_customizable"] ?? 1) ? $key_global->withValue(
null) : $key_global,
337 "provider_url" => [
"text",
$data[
"provider_url"]],
338 "provider_key_customizable" => [
"integer", (
int) (
$data[
"key_global"] ===
null)],
339 "provider_key" => [
"text",
$data[
"key_global"][
"provider_key"] ??
""],
340 "provider_secret" => [
"text",
$data[
"key_global"][
"provider_secret"] ??
""],
350 $field = $this->ui_factory->input()->field();
351 $content_item = $field->optionalGroup([
352 "content_item_url" => $field->text($this->lng->txt(
"lti_con_content_item_url"))
353 ->withValue((
string) ($row[
"content_item_url"] ??
"")),
354 ], $this->lng->txt(
"lti_con_content_item"));
355 $key_type = $field->switchableGroup([
357 "public_key" => $field->textarea(
358 $this->lng->txt(
"lti_con_key_type_rsa_public_key"),
359 $this->lng->txt(
"lti_con_key_type_rsa_public_key_info")
360 )->withRequired(
true)->withValue((
string) ($row[
"public_key"] ??
"")),
361 ], $this->lng->txt(
"lti_con_key_type_rsa")),
363 "public_keyset" => $field->text($this->lng->txt(
"lti_con_key_type_jwk_url"))
364 ->withRequired(
true)->withValue((
string) ($row[
"public_keyset"] ??
"")),
365 ], $this->lng->txt(
"lti_con_key_type_jwk")),
366 ], $this->lng->txt(
"lti_con_key_type"))->withRequired(
true);
368 $key_type = $key_type->withValue($row[
"key_type"]);
372 "provider_url" => $field->text($this->
lng->txt(
"lti_con_tool_url"))
373 ->withRequired(
true)->withValue((
string) ($row[
"provider_url"] ??
"")),
374 "initiate_login" => $field->text($this->
lng->txt(
"lti_con_initiate_login_url"))
375 ->withRequired(
true)->withValue((
string) ($row[
"initiate_login"] ??
"")),
376 "redirection_uris" => $field->textarea($this->
lng->txt(
"lti_con_redirection_uris"))
377 ->withRequired(
true)->withValue(str_replace(
",",
"\n", (
string) ($row[
"redirection_uris"] ??
""))),
378 "key_type" => $key_type,
379 "content_item" => ($row[
"content_item"] ??
false) ? $content_item : $content_item->withValue(
null),
380 "grade_synchronization" => $field->checkbox(
381 $this->
lng->txt(
"lti_con_grade_synchronization"),
382 $this->
lng->txt(
"lti_con_grade_synchronization_info")
383 )->
withValue((
bool) ($row[
"grade_synchronization"] ??
false)),
384 "names_roles" => $field->checkbox(
385 $this->
lng->txt(
"lti_con_names_roles"),
386 $this->
lng->txt(
"lti_con_names_roles_info")
387 )->
withValue((
bool) ($row[
"names_roles"] ??
false)),
390 if ($this->tool_id === 0) {
397 "lti_13_client_id" => (string) ($row[
"client_id"] ??
""),
398 "lti_13_deployment_id" => (string) $this->tool_id,
403 foreach ($platform_data as $txt => $value) {
404 $inputs[$txt] = $field->text($this->
lng->txt($txt))->withValue($value)->withDisabled(
true);
416 [$key_type, $key_data] =
$data[
"key_type"];
417 preg_match_all(
'/\S+/', (
string)
$data[
"redirection_uris"], $redirection_uris);
420 "provider_url" => [
"text",
$data[
"provider_url"]],
421 "initiate_login" => [
"text",
$data[
"initiate_login"]],
422 "redirection_uris" => [
"text", implode(
",", $redirection_uris[0])],
423 "key_type" => [
"text", $key_type],
424 "public_key" => [
"text", $key_data[
"public_key"] ??
""],
425 "public_keyset" => [
"text", $key_data[
"public_keyset"] ??
""],
426 "content_item" => [
"integer", (
int) (
$data[
"content_item"] !==
null)],
427 "content_item_url" => [
"text",
$data[
"content_item"][
"content_item_url"] ??
""],
428 "grade_synchronization" => [
"integer", (
int)
$data[
"grade_synchronization"]],
429 "names_roles" => [
"integer", (
int)
$data[
"names_roles"]],
Builds a Color from either hex- or rgb values.
const string AUTHENTICATION
static getUrl(string $script, string $suffix='')
The URL of an entry point, with the query or path that follows it.
static getBaseUrl()
The base URL of the installation as the request reached it.
This is how the factory for UI elements looks.
$request
@ilCtrl_Calls ilObjLearningSequenceContentGUI: ilObjLearningSequenceConditionsGUI
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
if(!file_exists('../ilias.ini.php'))