Skip to content

Commit bd06d57

Browse files
committed
Issue #14 Add mustache template to cms type.
1 parent cb63d3c commit bd06d57

13 files changed

+411
-21
lines changed

classes/form/cms_types_form.php

+47
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
namespace mod_cms\form;
2626

2727
use core\form\persistent as persistent_form;
28+
use mod_cms\local\model\cms_types;
29+
use mod_cms\local\renderer;
2830

2931
/**
3032
* Form for manipulating the content types
@@ -52,6 +54,51 @@ protected function definition() {
5254
$mform->addElement('editor', 'description', get_string('description'));
5355
$mform->setType('description', PARAM_RAW);
5456

57+
$mform->addElement(
58+
'textarea',
59+
'mustache',
60+
get_string('mustache', 'cms'),
61+
['rows' => 10, 'style' => 'font-family: monospace; font-size: 12px;']
62+
);
63+
$mform->setType('mustache', PARAM_RAW);
64+
65+
// Generate the help text for mustache template.
66+
$cmstype = $this->get_persistent();
67+
$cms = $cmstype->get_sample_cms();
68+
$renderer = new renderer($cms);
69+
$data = $renderer->get_data();
70+
$syntaxlink = \html_writer::link(
71+
new \moodle_url('https://moodledev.io/docs/guides/templates'),
72+
get_string('mustache_template', 'cms')
73+
);
74+
$helptext = get_string('mustache_help', 'cms', $syntaxlink);
75+
$helptext .= \html_writer::table($renderer->get_data_as_table());
76+
$mform->addElement('static', 'mustache_help', '', $helptext);
77+
78+
$html = $renderer->get_html();
79+
$mform->addElement('static', 'preview', get_string('preview', 'cms', get_string('savechangesanddisplay')), $html);
80+
5581
$this->add_action_buttons();
5682
}
83+
84+
/**
85+
* Adds submit buttons to the form.
86+
*
87+
* @param bool $cancel
88+
* @param null $submitlabel Not used
89+
*/
90+
public function add_action_buttons($cancel = true, $submitlabel=null) {
91+
$mform = $this->_form;
92+
93+
$classarray = ['class' => 'form-submit'];
94+
$buttonarray = [
95+
$mform->createElement('submit', 'saveandreturn', get_string('savechangesandreturn'), $classarray),
96+
$mform->createElement('submit', 'saveanddisplay', get_string('savechangesanddisplay'), $classarray),
97+
];
98+
if ($cancel) {
99+
$buttonarray[] = &$mform->createElement('cancel');
100+
}
101+
$mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
102+
$mform->closeHeaderBefore('buttonar');
103+
}
57104
}

classes/local/lib.php

+18
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,22 @@ public static function update_instance(stdClass $instancedata, $mform): bool {
108108
$cms->save();
109109
return true;
110110
}
111+
112+
/**
113+
* Obtains info on course module.
114+
*
115+
* @param stdClass $coursemodule
116+
* @return \cached_cm_info
117+
*/
118+
public static function get_coursemodule_info(stdClass $coursemodule): \cached_cm_info {
119+
// Put the template contents into the block.
120+
$cms = new cms($coursemodule->instance);
121+
122+
$info = new \cached_cm_info();
123+
$info->name = $cms->get('name');
124+
125+
$renderer = new renderer($cms);
126+
$info->content = $renderer->get_html();
127+
return $info;
128+
}
111129
}

classes/local/model/cms.php

+9
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,13 @@ protected static function define_properties(): array {
7373
],
7474
];
7575
}
76+
77+
/**
78+
* Gets the type object for this cms.
79+
*
80+
* @return cms_types
81+
*/
82+
public function get_type(): cms_types {
83+
return new cms_types($this->get('typeid'));
84+
}
7685
}

classes/local/model/cms_types.php

+16
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ protected static function define_properties(): array {
6464
'type' => PARAM_INT,
6565
'default' => 1
6666
],
67+
'mustache' => [
68+
'type' => PARAM_RAW,
69+
'default' => ''
70+
],
6771
];
6872
}
6973

@@ -125,4 +129,16 @@ protected function after_delete($result): void {
125129
public function can_delete(): bool {
126130
return true;
127131
}
132+
133+
/**
134+
* Get a sample cms of this type, filled with arbitrary data.
135+
*
136+
* @return cms
137+
*/
138+
public function get_sample_cms(): cms {
139+
$cms = new cms();
140+
$cms->set('typeid', $this->get('id'));
141+
142+
return $cms;
143+
}
128144
}

classes/local/renderer.php

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
// This file is part of Moodle - https://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16+
17+
namespace mod_cms\local;
18+
19+
use Mustache_Engine;
20+
use mod_cms\local\model\cms;
21+
22+
/**
23+
* Renders the contents of a mustache template.
24+
*
25+
* @package mod_cms
26+
* @author Jason den Dulk <[email protected]>
27+
* @copyright 2023, Catalyst IT
28+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
29+
*/
30+
class renderer {
31+
/** @var cms */
32+
protected $cms;
33+
34+
/**
35+
* Constructs a renderer for the given cms.
36+
*
37+
* @param cms $cms
38+
*/
39+
public function __construct(cms $cms) {
40+
$this->cms = $cms;
41+
}
42+
43+
/**
44+
* Get the data array for the cms.
45+
*
46+
* @return array
47+
*/
48+
public function get_data(): array {
49+
global $CFG, $SITE;
50+
51+
$data = [];
52+
53+
$data['site'] = [
54+
'fullname' => $SITE->fullname,
55+
'shortname' => $SITE->shortname,
56+
'wwwroot' => $CFG->wwwroot,
57+
];
58+
59+
return $data;
60+
}
61+
62+
/**
63+
* Flattens an array with nested arrays into a single array.
64+
*
65+
* @param array $output The output array to be written to.
66+
* @param array $source The source array to be read from.
67+
* @param string $prefix String to put at the front of the key name.
68+
*/
69+
public static function flatten(array &$output, array $source, string $prefix = '') {
70+
foreach ($source as $key => $value) {
71+
if (is_array($value)) {
72+
self::flatten($output, $value, $prefix .= '.' . $key);
73+
} else {
74+
$output[ltrim($prefix . '.' . $key, '.')] = $value;
75+
}
76+
}
77+
}
78+
79+
/**
80+
* Retrieves the data for the cms as a flat array, with the keys concatenated using dots.
81+
*
82+
* @return \html_table
83+
*/
84+
public function get_data_as_table(): \html_table {
85+
$flatarray = [];
86+
self::flatten($flatarray, $this->get_data());
87+
88+
$table = new \html_table();
89+
$table->attributes['class'] = 'noclass';
90+
$table->head = [ 'Name', 'Sample value' ];
91+
foreach ($flatarray as $name => $value) {
92+
$left = new \html_table_cell('{{' . $name . '}}');
93+
$right = new \html_table_cell($value);
94+
$row = new \html_table_row([$left, $right]);
95+
$table->data[] = $row;
96+
}
97+
return $table;
98+
}
99+
100+
/**
101+
* Renders the template with the data and returns the content.
102+
*
103+
* @return string
104+
*/
105+
public function get_html(): string {
106+
$data = $this->get_data();
107+
108+
$mustache = self::get_mustache();
109+
$template = $this->cms->get_type()->get('mustache');
110+
$html = $mustache->render($template, $data);
111+
112+
return $html;
113+
}
114+
115+
/**
116+
* Get a Mustache engine suitable for use with this renderer.
117+
*
118+
* @return Mustache_Engine
119+
*/
120+
public static function get_mustache(): Mustache_Engine {
121+
$mustache = new Mustache_Engine([
122+
'escape' => 's',
123+
'pragmas' => [Mustache_Engine::PRAGMA_BLOCKS],
124+
]);
125+
return $mustache;
126+
}
127+
}

classes/manage_content_types.php

+11-4
Original file line numberDiff line numberDiff line change
@@ -193,21 +193,28 @@ protected function edit(string $action, ?int $id = null): void {
193193
if ($form->is_cancelled()) {
194194
redirect(new moodle_url(self::get_base_url()));
195195
} else if ($data = $form->get_data()) {
196-
unset($data->submitbutton);
196+
$stayonpage = isset($data->saveanddisplay);
197+
unset($data->saveandreturn);
198+
unset($data->saveanddisplay);
197199
try {
198200
// Create new.
199201
if (empty($data->id)) {
200202
$contenttype = $this->get_instance(0, $data);
201-
$contenttype->create();
203+
$instance = $contenttype->create();
202204
} else { // Update existing.
203205
$instance->from_record($data);
204206
$instance->update();
205207
}
206208
notification::success(get_string('changessaved'));
207-
} catch (Exception $e) {
209+
} catch (\Exception $e) {
208210
notification::error($e->getMessage());
209211
}
210-
redirect(new moodle_url(self::get_base_url()));
212+
$redirecturl = new moodle_url(self::get_base_url());
213+
if ($stayonpage) {
214+
$redirecturl->param('action', 'edit');
215+
$redirecturl->param('id', $instance->get('id'));
216+
}
217+
redirect($redirecturl);
211218
} else {
212219
if (empty($instance)) {
213220
$this->header($this->get_new_heading());

db/install.xml

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="Name of the custom content type."/>
2828
<FIELD NAME="description" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Description of the custom content type."/>
2929
<FIELD NAME="descriptionformat" TYPE="int" LENGTH="4" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the description field of the custom content type."/>
30+
<FIELD NAME="mustache" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Mustache template for the content."/>
3031
<FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
3132
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
3233
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>

db/upgrade.php

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
// This file is part of Moodle - https://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16+
17+
/**
18+
* Datbase upgrade script
19+
*
20+
* @package mod_cms
21+
* @author Jason den Dulk <[email protected]>
22+
* @copyright 2023, Catalyst IT
23+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24+
*/
25+
26+
/**
27+
* Function to upgrade mod_cms database
28+
*
29+
* @param int $oldversion the version we are upgrading from
30+
* @return bool result
31+
*/
32+
function xmldb_cms_upgrade($oldversion) {
33+
global $DB;
34+
35+
$dbman = $DB->get_manager();
36+
37+
if ($oldversion < 2023060601) {
38+
39+
// Define field pathinfo to be added to tool_excimer_profiles.
40+
$table = new xmldb_table('cms_types');
41+
$field = new xmldb_field('mustache', XMLDB_TYPE_TEXT, null, null, false, null, null, 'descriptionformat');
42+
43+
// Conditionally launch add field mustache.
44+
if (!$dbman->field_exists($table, $field)) {
45+
$dbman->add_field($table, $field);
46+
}
47+
48+
upgrade_mod_savepoint(true, 2023060601, 'cms');
49+
}
50+
51+
return true;
52+
}

lang/en/cms.php

+4
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,7 @@
4848
$string['table:name'] = 'Custom content type';
4949
$string['cms:addinstance'] = 'Add a new custom content instance';
5050
$string['pluginadministration'] = 'Plugin administration';
51+
$string['mustache'] = 'Mustache template';
52+
$string['mustache_help'] = 'The above content will need to be a valid {$a}. Sample variables that are available for use in this template are given below.';
53+
$string['mustache_template'] = 'mustache template';
54+
$string['preview'] = 'Preview (click "{$a}" to update)';

lib.php

+2-12
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
use core_course\local\entity\content_item;
2727
use mod_cms\local\lib;
28-
use mod_cms\local\model\cms;
2928

3029
/**
3130
* Returns whether a feature is supported or not.
@@ -44,10 +43,10 @@
4443
function cms_supports($feature) {
4544
switch($feature) {
4645
case FEATURE_IDNUMBER:
47-
case FEATURE_MOD_INTRO:
4846
case FEATURE_BACKUP_MOODLE2:
4947
case FEATURE_NO_VIEW_LINK:
5048
return true;
49+
case FEATURE_MOD_INTRO:
5150
case FEATURE_GROUPS:
5251
case FEATURE_GROUPINGS:
5352
case FEATURE_COMPLETION_TRACKS_VIEWS:
@@ -114,16 +113,7 @@ function cms_delete_instance(int $id): bool {
114113
*
115114
* @param stdClass $coursemodule
116115
* @return cached_cm_info
117-
* @throws coding_exception
118-
* @throws moodle_exception
119116
*/
120117
function cms_get_coursemodule_info($coursemodule) {
121-
// TODO This is a stub to provide minimum functionality.
122-
$cms = new cms($coursemodule->instance);
123-
124-
$info = new cached_cm_info();
125-
$info->name = $cms->get('name');
126-
$link = new moodle_url('/mod/cms/view.php', ['id' => $coursemodule->id, 'forcedview' => 1]);
127-
$info->content = html_writer::link($link, $info->name);
128-
return $info;
118+
return lib::get_coursemodule_info($coursemodule);
129119
}

0 commit comments

Comments
 (0)