Skip to content

Commit f1b3466

Browse files
Frederic Massartdanpoltawski
authored andcommitted
MDL-55495 output: Make url_select a templatable
Part of MDL-55071
1 parent 8a47abc commit f1b3466

File tree

3 files changed

+209
-1
lines changed

3 files changed

+209
-1
lines changed

lib/outputcomponents.php

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,7 @@ public function export_for_template(renderer_base $output) {
951951
* @package core
952952
* @category output
953953
*/
954-
class url_select implements renderable {
954+
class url_select implements renderable, templatable {
955955
/**
956956
* @var array $urls associative array value=>label ex.: array(1=>'One, 2=>Two)
957957
* it is also possible to specify optgroup as complex label array ex.:
@@ -1061,6 +1061,155 @@ public function set_label($label, $attributes = array()) {
10611061
$this->label = $label;
10621062
$this->labelattributes = $attributes;
10631063
}
1064+
1065+
/**
1066+
* Clean a URL.
1067+
*
1068+
* @param string $value The URL.
1069+
* @return The cleaned URL.
1070+
*/
1071+
protected function clean_url($value) {
1072+
global $CFG;
1073+
1074+
if (empty($value)) {
1075+
// Nothing.
1076+
1077+
} else if (strpos($value, $CFG->wwwroot . '/') === 0) {
1078+
$value = str_replace($CFG->wwwroot, '', $value);
1079+
1080+
} else if (strpos($value, '/') !== 0) {
1081+
debugging("Invalid url_select urls parameter: url '$value' is not local relative url!", DEBUG_DEVELOPER);
1082+
}
1083+
1084+
return $value;
1085+
}
1086+
1087+
/**
1088+
* Flatten the options for Mustache.
1089+
*
1090+
* This also cleans the URLs.
1091+
*
1092+
* @param array $options The options.
1093+
* @param array $nothing The nothing option.
1094+
* @return array
1095+
*/
1096+
protected function flatten_options($options, $nothing) {
1097+
$flattened = [];
1098+
1099+
foreach ($options as $value => $option) {
1100+
if (is_array($option)) {
1101+
foreach ($option as $groupname => $optoptions) {
1102+
if (!isset($flattened[$groupname])) {
1103+
$flattened[$groupname] = [
1104+
'name' => $groupname,
1105+
'isgroup' => true,
1106+
'options' => []
1107+
];
1108+
}
1109+
foreach ($optoptions as $optvalue => $optoption) {
1110+
$cleanedvalue = $this->clean_url($optvalue);
1111+
$flattened[$groupname]['options'][$cleanedvalue] = [
1112+
'name' => $optoption,
1113+
'value' => $cleanedvalue,
1114+
'selected' => $this->selected == $optvalue,
1115+
];
1116+
}
1117+
}
1118+
1119+
} else {
1120+
$cleanedvalue = $this->clean_url($value);
1121+
$flattened[$cleanedvalue] = [
1122+
'name' => $option,
1123+
'value' => $cleanedvalue,
1124+
'selected' => $this->selected == $value,
1125+
];
1126+
}
1127+
}
1128+
1129+
if (!empty($nothing)) {
1130+
$value = key($nothing);
1131+
$name = reset($nothing);
1132+
$flattened = [
1133+
$value => ['name' => $name, 'value' => $value, 'selected' => $this->selected == $value]
1134+
] + $flattened;
1135+
}
1136+
1137+
// Make non-associative array.
1138+
foreach ($flattened as $key => $value) {
1139+
if (!empty($value['options'])) {
1140+
$flattened[$key]['options'] = array_values($value['options']);
1141+
}
1142+
}
1143+
$flattened = array_values($flattened);
1144+
1145+
return $flattened;
1146+
}
1147+
1148+
/**
1149+
* Export for template.
1150+
*
1151+
* @param renderer_base $output Renderer.
1152+
* @return stdClass
1153+
*/
1154+
public function export_for_template(renderer_base $output) {
1155+
$attributes = $this->attributes;
1156+
1157+
$data = new stdClass();
1158+
$data->formid = !empty($this->formid) ? $this->formid : html_writer::random_id('url_select_f');
1159+
$data->classes = $this->class;
1160+
$data->label = $this->label;
1161+
$data->disabled = $this->disabled;
1162+
$data->title = $this->tooltip;
1163+
$data->id = !empty($attributes['id']) ? $attributes['id'] : html_writer::random_id('url_select');
1164+
$data->sesskey = sesskey();
1165+
$data->action = (new moodle_url('/course/jumpto.php'))->out(false);
1166+
1167+
// Remove attributes passed as property directly.
1168+
unset($attributes['class']);
1169+
unset($attributes['id']);
1170+
unset($attributes['name']);
1171+
unset($attributes['title']);
1172+
1173+
$data->showbutton = $this->showbutton;
1174+
if (empty($this->showbutton)) {
1175+
$data->classes .= ' autosubmit';
1176+
}
1177+
1178+
// Select options.
1179+
$nothing = false;
1180+
if (is_string($this->nothing) && $this->nothing !== '') {
1181+
$nothing = ['' => $this->nothing];
1182+
$hasnothing = true;
1183+
} else if (is_array($this->nothing)) {
1184+
$key = key($this->nothing);
1185+
if ($key === 'choose' || $key === 'choosedots') {
1186+
$nothing = [$key => get_string('choosedots')];
1187+
} else {
1188+
$nothing = [$key => reset($this->nothing)];
1189+
}
1190+
$hasnothing = true;
1191+
}
1192+
$data->hasnothing = !empty($nothing);
1193+
$data->nothingkey = $data->hasnothing ? key($nothing) : false;
1194+
$data->options = $this->flatten_options($this->urls, $nothing);
1195+
1196+
// Label attributes.
1197+
$data->labelattributes = [];
1198+
foreach ($this->labelattributes as $key => $value) {
1199+
$data->labelattributes[] = ['name' => $key, 'value' => $value];
1200+
}
1201+
1202+
// Help icon.
1203+
$data->helpicon = !empty($this->helpicon) ? $this->helpicon->export_for_template($output) : false;
1204+
1205+
// Finally all the remaining attributes.
1206+
$data->attributes = [];
1207+
foreach ($this->attributes as $key => $value) {
1208+
$data->attributes = ['name' => $key, 'value' => $value];
1209+
}
1210+
1211+
return $data;
1212+
}
10641213
}
10651214

10661215
/**

theme/noname/classes/output/core_renderer.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use help_icon;
3131
use single_select;
3232
use paging_bar;
33+
use url_select;
3334

3435
defined('MOODLE_INTERNAL') || die;
3536

@@ -297,4 +298,13 @@ protected function render_paging_bar(paging_bar $pagingbar) {
297298
return $this->render_from_template('core/paging_bar', $pagingbar->export_for_template($this));
298299
}
299300

301+
/**
302+
* Renders a url select.
303+
*
304+
* @param url_select $select The object.
305+
* @return string HTML
306+
*/
307+
protected function render_url_select(url_select $select) {
308+
return $this->render_from_template('core/url_select', $select->export_for_template($this));
309+
}
300310
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<div class="{{classes}}">
2+
<form method="post" action="{{action}}" class="form-inline" id="{{formid}}">
3+
<input type="hidden" name="sesskey" value="{{sesskey}}">
4+
<div class="form-group">
5+
{{#label}}
6+
<label for="{{id}}" {{#labelattributes}}{{name}}="{{value}}" {{/labelattributes}}>
7+
{{label}}
8+
</label>
9+
{{/label}}
10+
{{#helpicon}}
11+
{{>core/help_icon}}
12+
{{/helpicon}}
13+
<select {{#attributes}}{{name}}="{{value}}" {{/attributes}} id="{{id}}" class="form-control {{classes}}" name="jump">
14+
{{#options}}
15+
{{#isgroup}}
16+
<optgroup label="{{name}}">
17+
{{#options}}
18+
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
19+
{{/options}}
20+
</optgroup>
21+
{{/isgroup}}
22+
{{^isgroup}}
23+
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
24+
{{/isgroup}}
25+
{{/options}}
26+
</select>
27+
</div>
28+
{{#showbutton}}
29+
<button type="submit" class="btn btn-secondary">{{showbutton}}</button>
30+
{{/showbutton}}
31+
{{^showbutton}}
32+
<noscript>
33+
<button type="submit" class="btn btn-secondary">{{#str}}go, core{{/str}}</button>
34+
</noscript>
35+
{{/showbutton}}
36+
</form>
37+
</div>
38+
{{^showbutton}}
39+
{{#js}}
40+
require(['core/yui'], function(Y) {
41+
Y.use('moodle-core-formautosubmit', function() {
42+
M.core.init_formautosubmit({
43+
selectid: '{{id}}',
44+
nothing: {{#hasnothing}}'{{nothingkey}}'{{/hasnothing}}{{^hasnothing}}false{{/hasnothing}}
45+
});
46+
});
47+
});
48+
{{/js}}
49+
{{/showbutton}}

0 commit comments

Comments
 (0)