Skip to content

Commit c1fed1e

Browse files
committed
Convert to use custom fields.
# Conflicts: # classes/local/datasource/userlist.php
1 parent f4cec38 commit c1fed1e

11 files changed

+414
-140
lines changed

classes/local/datasource/userlist.php

+157-56
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616

1717
namespace mod_cms\local\datasource;
1818

19-
use core_customfield\field;
19+
use core_customfield\{data_controller, field, field_controller};
2020
use core_customfield\output\management;
2121
use mod_cms\customfield\cmsuserlist_handler;
22-
use mod_cms\helper;
2322
use mod_cms\local\lib;
24-
use mod_cms\local\model\{cms, cms_userlist, cms_userlist_columns};
23+
use mod_cms\local\model\{cms, cms_userlist};
2524

2625
/**
2726
* User designed lists
@@ -36,12 +35,6 @@
3635
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3736
*/
3837
class userlist extends base {
39-
40-
/** URL for the config page. */
41-
const CONFIG_URL = '/mod/cms/userlist.php';
42-
/** Icon to use for the link in the table list. */
43-
const ACTION_ICON = 't/grades';
44-
4538
/** Default number of rows to include in the list edit form. */
4639
const DEFAULT_NUM_ROWS = 2;
4740
/** Prefix to use for list elements. */
@@ -101,10 +94,24 @@ public function get_data(): \stdClass {
10194
if ($this->cms->issample) {
10295
$data->data = $this->get_sample($columndefs);
10396
} else {
104-
$list = cms_userlist::get_from_cmsid($this->cms->get('id'));
105-
if (isset($list)) {
106-
$data->data = $list->get('data');
97+
$instanceids = $this->get_instance_ids();
98+
ksort($instanceids);
99+
$rows = [];
100+
foreach ($instanceids as $id) {
101+
$rowobj = new \stdClass();
102+
$row = $this->cfhandler->get_instance_data($id, true);
103+
foreach ($row as $datacontroller) {
104+
$name = $datacontroller->get_field()->get('shortname');
105+
$rowobj->$name = $datacontroller->export_value();
106+
}
107+
$rows[] = $rowobj;
107108
}
109+
$data->data = $rows;
110+
}
111+
if (isset($data->data)) {
112+
$data->numrows = count($data->data);
113+
} else {
114+
$data->numrows = 0;
108115
}
109116

110117
return $data;
@@ -158,34 +165,34 @@ public function config_form_definition(\MoodleQuickForm $mform) {
158165
* @param \MoodleQuickForm $mform
159166
*/
160167
public function instance_form_definition(\moodleform_mod $form, \MoodleQuickForm $mform) {
168+
$cmsid = $this->cms->get('id');
161169
$fakeform = new \MoodleQuickForm('a', 'b', 'c');
162-
$this->cfhandler->instance_form_definition($fakeform, $this->cms->get('id'));
163-
$list = cms_userlist::get_from_cmsid($this->cms->get('id'));
170+
$this->cfhandler->instance_form_definition($fakeform, $cmsid);
164171

172+
$instanceids = $this->get_instance_ids();
165173
$repeatable = [];
166174
$repeatoptions = [];
167-
$repeatno = $list ? $list->get('numrows') : self::DEFAULT_NUM_ROWS;
175+
$repeatno = count($instanceids) ?: self::DEFAULT_NUM_ROWS;
168176

169177
$fields = $this->cfhandler->get_fields();
170178
foreach ($fields as $field) {
171-
$actualname = self::FORM_PREFIX . $field->get('shortname');
172-
$fakename = self::CUSTOMFIELD_PREFIX . $field->get('shortname');
173-
$element = $fakeform->getElement($fakename);
174-
$element->setName($actualname);
179+
$names = $this->get_element_names($field);
180+
$element = $fakeform->getElement($names->cfelementname);
181+
$element->setName($names->ulelementname);
175182
$repeatable[] = $element;
176183

177184
// Sometimes, the default has to be an integer.
178185
$default = $field->get_configdata_property('defaultvalue');
179186
if ($default == (int) $default) {
180187
$default = (int) $default;
181188
}
182-
$repeatoptions[$actualname] = [
189+
$repeatoptions[$names->ulelementname] = [
183190
'default' => $default,
184-
'type' => $fakeform->getCleanType($fakename, 0),
191+
'type' => $fakeform->getCleanType($names->cfelementname, 0),
185192
];
186193
// Set the rule. Only one rule is allowed.
187194
if ($field->get_configdata_property('required')) {
188-
$repeatoptions[$actualname]['rule'] = 'required';
195+
$repeatoptions[$names->ulelementname]['rule'] = 'required';
189196
}
190197
}
191198
$repeatable[] = $mform->createElement('submit', 'delete', 'Remove', [], false);
@@ -209,17 +216,20 @@ public function instance_form_definition(\moodleform_mod $form, \MoodleQuickForm
209216

210217
/**
211218
* Get extra data needed to add to the form.
219+
*
212220
* @param mixed $data
213221
*/
214222
public function instance_form_default_data(&$data) {
215-
$list = cms_userlist::get_from_cmsid($this->cms->get('id'));
216-
217-
// Extract the values of the column defs and convert into the format that the form requires.
218-
$listdata = $list->get('data');
219-
foreach ($listdata as $count => $row) {
220-
foreach ($row as $idx => $val) {
221-
$key = self::FORM_PREFIX . "{$idx}[{$count}]";
222-
$data->$key = $val;
223+
$instanceids = $this->get_instance_ids();
224+
foreach ($instanceids as $rownum => $id) {
225+
$cfdata = new \stdClass();
226+
$cfdata->id = $id;
227+
$this->cfhandler->instance_form_before_set_data($cfdata);
228+
unset($cfdata->id);
229+
$cfdata = $this->swap_prefix($cfdata, self::CUSTOMFIELD_PREFIX, self::FORM_PREFIX);
230+
foreach ($cfdata as $name => $value) {
231+
$key = "{$name}[{$rownum}]";
232+
$data->$key = $value;
223233
}
224234
}
225235
}
@@ -233,11 +243,12 @@ public function instance_form_default_data(&$data) {
233243
*/
234244
public function instance_form_validation(array $data, array $files): array {
235245
$objdata = (object) $data;
236-
$this->convert($objdata, self::CUSTOMFIELD_PREFIX);
246+
$this->from_repeatable($objdata);
237247

238248
$errors = [];
239249
foreach ($objdata->data as $count => $group) {
240-
$fielderrors = $this->cfhandler->instance_form_validation((array)$group, $files);
250+
$datatovalidate = $this->swap_prefix($group, self::FORM_PREFIX, self::CUSTOMFIELD_PREFIX);
251+
$fielderrors = $this->cfhandler->instance_form_validation((array)$datatovalidate, $files);
241252
foreach ($fielderrors as $idx => $error) {
242253
$idx = str_replace(self::CUSTOMFIELD_PREFIX, self::FORM_PREFIX, $idx);
243254
$errors["{$idx}[{$count}"] = $error;
@@ -253,17 +264,27 @@ public function instance_form_validation(array $data, array $files): array {
253264
* @param bool $isnewinstance
254265
*/
255266
public function update_instance(\stdClass $instancedata, bool $isnewinstance) {
256-
$list = cms_userlist::get_from_cmsid($instancedata->id);
257-
if ($list === null) {
258-
$list = new cms_userlist();
259-
$list->set('cmsid', $instancedata->id);
260-
$list->set('typeid', $this->cms->get('typeid'));
267+
$this->from_repeatable($instancedata);
268+
269+
$instanceids = $this->get_instance_ids();
270+
271+
$numexisting = count($instanceids);
272+
273+
foreach ($instancedata->data as $count => $group) {
274+
$datatosave = $this->swap_prefix($group, self::FORM_PREFIX, self::CUSTOMFIELD_PREFIX);
275+
$datatosave->id = $this->get_instance_id($count);
276+
$this->cfhandler->instance_form_save($datatosave, $count >= $numexisting);
261277
}
262278

263-
$this->convert($instancedata);
264-
$list->set('data', $instancedata->data);
265-
$list->set('numrows', $instancedata->numrows);
266-
$list->save();
279+
// Remove excess.
280+
$count = count($instancedata->data);
281+
if ($count < $numexisting) {
282+
for ($i = $count; $i < $numexisting; ++$i) {
283+
$this->cfhandler->delete_instance($instanceids[$i]);
284+
}
285+
$instanceids = array_slice($instanceids, 0, $count, true);
286+
$this->cms->set_custom_data('userlistinstanceids', $instanceids);
287+
}
267288

268289
// Update hash.
269290
$hash = hash(lib::HASH_ALGO, serialize($this->get_data()));
@@ -273,22 +294,23 @@ public function update_instance(\stdClass $instancedata, bool $isnewinstance) {
273294
}
274295

275296
/**
276-
* Convert the form data to something settable to the persistent.
297+
* Convert the form data from the raw format returned by the form into a more usable format where each element group is
298+
* actually grouped.
299+
*
277300
* Data comes in as
278301
* {
279302
* userlist_name : ['John', 'Andy'],
280303
* userlist_age : [12, 14]
281304
* }
282305
* Converts to
283306
* [
284-
* { name : 'John', age : 12 },
285-
* { name : 'Andy', age : 14 }
307+
* { userlist_name : 'John', userlist_age : 12 },
308+
* { userlist_name : 'Andy', userlist_age : 14 }
286309
* ]
287310
*
288311
* @param \stdClass $data Form data as returned by moodleform::get_data().
289-
* @param string $prefix A prefix to put at the front of names when adding to data.
290312
*/
291-
protected function convert(\stdClass $data, $prefix = '') {
313+
protected function from_repeatable(\stdClass $data) {
292314
$deletehidden = 'delete-hidden';
293315
$deletehidden = isset($data->$deletehidden) ? $data->$deletehidden : [];
294316

@@ -305,24 +327,52 @@ protected function convert(\stdClass $data, $prefix = '') {
305327
}
306328

307329
foreach ($columndefs as $columndef) {
308-
$name = $columndef->get('shortname');
309-
$formname = self::FORM_PREFIX . $name;
330+
$names = $this->get_element_names($columndef);
331+
$formname = $names->ulelementname;
310332
foreach ($data->$formname as $i => $val) {
311333
if (isset($deletehidden[$i])) {
312334
continue;
313335
}
314-
$savename = $prefix . $name;
315-
$defs[$i]->$savename = $val;
336+
$defs[$i]->$formname = $val;
316337
}
317338
}
318339

319-
// Re-sequence array indexes.
320-
$defs = array_values($defs);
321-
340+
$defs = array_values($defs); // Re-sequence array indexes.
322341
$data->data = $defs;
323342
$data->numrows = count($defs);
324343
}
325344

345+
/**
346+
* Swaps the prefixes of the data.
347+
*
348+
* @param \stdClass $data
349+
* @param string $fromprefix
350+
* @param string $toprefix
351+
* @return \stdClass
352+
*/
353+
protected function swap_prefix(\stdClass $data, string $fromprefix, string $toprefix): \stdClass {
354+
$newdata = new \stdClass();
355+
foreach ($data as $name => $value) {
356+
$newname = str_replace($fromprefix, $toprefix, $name);
357+
$newdata->$newname = $value;
358+
}
359+
return $newdata;
360+
}
361+
362+
/**
363+
* Called after updating cms type to perform any extra saving required by datasource.
364+
*
365+
* @param mixed $data
366+
*/
367+
public function config_on_update($data) {
368+
$categories = $this->cfhandler->get_categories_with_fields();
369+
// Add a category if creating.
370+
if (count($categories) === 0) {
371+
$this->cfhandler->create_category('');
372+
}
373+
$this->update_config_hash();
374+
}
375+
326376
/**
327377
* Get configuration data for exporting.
328378
*
@@ -387,9 +437,60 @@ public function config_on_delete() {
387437
* Called when deleting a CMS instance.
388438
*/
389439
public function instance_on_delete() {
390-
$list = cms_userlist::get_from_cmsid($this->cms->get('id'));
391-
if (isset($list)) {
392-
$list->delete();
440+
$ids = $this->get_instance_ids();
441+
foreach ($ids as $id) {
442+
$this->cfhandler->delete_instance($id);
443+
}
444+
}
445+
446+
/**
447+
* Get the various names for the element.
448+
*
449+
* @param field_controller $columndef Custom field containing the definition of the list column elements.
450+
* @param int $rownum
451+
*
452+
* @return \stdClass An object with the various names for the column.
453+
* - shortname: The actual name of the column. Use in the mustache template. e.g. 'mytextarea'.
454+
* - cfelementname: The form name provided by the custom field. e.g. 'customfield_mytextarea_editor'.
455+
* - ulelementname: The form name to be used in the userlist mod instance form. e.g 'userlist_mytextarea_editor'.
456+
*/
457+
public function get_element_names(field_controller $columndef, int $rownum = 0): \stdClass {
458+
$names = new \stdClass();
459+
$datacontroller = data_controller::create(0, (object)['instanceid' => 0], $columndef);
460+
$names->shortname = $columndef->get('shortname');
461+
$names->cfelementname = $datacontroller->get_form_element_name();
462+
$names->ulelementname = str_replace(self::CUSTOMFIELD_PREFIX, self::FORM_PREFIX, $names->cfelementname);
463+
return $names;
464+
}
465+
466+
/**
467+
* Obtain a unqiue instance ID to use to store the row in the custom field table.
468+
*
469+
* @param int $rownum
470+
* @return int
471+
*/
472+
protected function get_instance_id(int $rownum): int {
473+
$ids = $this->get_instance_ids();
474+
if (!isset($ids[$rownum])) {
475+
$nextid = $this->cms->get_custom_data('userlistmaxinstanceid') + 1;
476+
$this->cms->set_custom_data('userlistmaxinstanceid', $nextid);
477+
$ids[$rownum] = $nextid;
478+
$this->cms->set_custom_data('userlistinstanceids', $ids);
479+
$this->cms->save();
480+
}
481+
return $ids[$rownum];
482+
}
483+
484+
/**
485+
* Gets the custom fields instance IDs for this CMS instance. Indexed by row number.
486+
*
487+
* @return array
488+
*/
489+
protected function get_instance_ids(): array {
490+
$ids = $this->cms->get_custom_data('userlistinstanceids');
491+
if (is_null($ids)) {
492+
$ids = [];
393493
}
494+
return (array) $ids;
394495
}
395496
}

classes/local/lib.php

+2
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ public static function cm_info_view(\cm_info $cminfo) {
157157
$renderer = new renderer($cms);
158158
$content = $renderer->get_html();
159159
$cminfo->set_content($content);
160+
// This removes all the 'activity' chrome which makes it easier to style.
161+
$cminfo->set_custom_cmlist_item(true);
160162
}
161163

162164
/**

0 commit comments

Comments
 (0)