• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ewallah / moodle-format_masonry / 17801099810

17 Sep 2025 02:32PM UTC coverage: 97.436% (-1.3%) from 98.75%
17801099810

push

github

rdebleu
dev

228 of 234 relevant lines covered (97.44%)

7.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.39
/lib.php
1
<?php
2
// This file is part of Moodle - http://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
 * Lib for masonry course format.
19
 *
20
 * @package    format_masonry
21
 * @copyright  eWallah.net
22
 * @author     Renaat Debleu <info@eWallah.net>
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25

26
defined('MOODLE_INTERNAL') || die();
27
require_once($CFG->dirroot . '/course/format/lib.php');
2✔
28

29
use core\output\inplace_editable;
30

31
/**
32
 * Main class for the masonry course format
33
 *
34
 * @package    format_masonry
35
 * @copyright  eWallah.net
36
 * @author     Renaat Debleu <info@eWallah.net>
37
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38
 */
39
class format_masonry extends core_courseformat\base {
40
    /**
41
     * Returns instance of page renderer used by this plugin
42
     *
43
     * @param moodle_page $page
44
     * @return renderer_base
45
     */
46
    public function get_renderer(moodle_page $page) {
47
        return $page->get_renderer('format_masonry');
8✔
48
    }
49

50
    /**
51
     * Returns the default section name for the masonry course format.
52
     *
53
     * @param stdClass $section Section object from database or just field course_sections section
54
     * @return string The default value for the section name.
55
     */
56
    public function get_default_section_name($section) {
57
        if ($section->section == 0) {
10✔
58
            // Return the general section.
59
            return get_string('section0name', 'format_masonry');
8✔
60
        } else {
61
            // Use course_format::get_default_section_name implementation which
62
            // will display the section name in "Topic n" format.
63
            return parent::get_default_section_name($section);
10✔
64
        }
65
    }
66

67
    /**
68
     * Returns the display name of the given section that the course prefers.
69
     *
70
     * @param int|stdClass $section Section object from database or just field section.section
71
     * @return string Display name that the course format prefers, e.g. "Topic 2"
72
     */
73
    public function get_section_name($section) {
74
        $section = $this->get_section($section);
12✔
75
        if ((string)$section->name !== '') {
12✔
76
            // Return the name the user set.
77
            return format_string($section->name, true, ['context' => context_course::instance($this->courseid)]);
2✔
78
        } else {
79
            return $this->get_default_section_name($section);
10✔
80
        }
81
    }
82

83
    /**
84
     * This course format supports components.
85
     *
86
     * @return boolean
87
     */
88
    public function supports_components() {
89
        return true;
8✔
90
    }
91

92
    /**
93
     * The URL to use for the specified course (without section)
94
     *
95
     * @param int|stdClass $section Section object from database or just field course_sections.section
96
     * @param array $options options for view URL. ignored
97
     * @return null|moodle_url
98
     */
99
    public function get_view_url($section, $options = []) {
100
        $course = $this->get_course();
4✔
101
        return new \moodle_url('/course/view.php', ['id' => $course->id]);
4✔
102
    }
103

104
    /**
105
     * Definitions of the additional options that this course format uses for section
106
     *
107
     * @param bool $foreditform
108
     * @return array
109
     */
110
    public function section_format_options($foreditform = false) {
111
        $color = get_config('format_masonry', 'defaultbordercolor');
14✔
112
        return [
14✔
113
            'backcolor' => [
14✔
114
                'type' => PARAM_RAW,
14✔
115
                'name' => 'bordercolor',
14✔
116
                'label' => new \lang_string('backgroundcolor', 'format_masonry'),
14✔
117
                'element_type' => 'text',
14✔
118
                'default' => $color,
14✔
119
                'cache' => true,
14✔
120
                'cachedefault' => $color,
14✔
121
                'help' => 'colordisplay',
14✔
122
                'help_component' => 'format_masonry',
14✔
123
            ],
14✔
124
        ];
14✔
125
    }
126

127
    /**
128
     * Definitions of the additional options that this course format uses for course
129
     *
130
     * @param bool $foreditform
131
     * @return array of options
132
     */
133
    public function course_format_options($foreditform = false) {
134
        static $courseformatoptions = false;
14✔
135
        if ($courseformatoptions === false) {
14✔
136
            $courseconfig = get_config('moodlecourse');
2✔
137
            $courseformatoptions = [
2✔
138
                'hiddensections' => ['type' => PARAM_INT, 'default' => 1],
2✔
139
                'coursedisplay' => ['type' => PARAM_INT, 'default' => 1],
2✔
140
                'borderwidth' => ['type' => PARAM_INT, 'default' => 1],
2✔
141
                'bordercolor' => ['type' => PARAM_TEXT, 'default' => '#F0F0F0'],
2✔
142
                'backcolor' => ['type' => PARAM_TEXT, 'default' => '#F0F0F0'], ];
2✔
143
        }
144
        if ($foreditform && !isset($courseformatoptions['coursedisplay']['label'])) {
14✔
145
            $courseconfig = get_config('moodlecourse');
2✔
146
            $max = (int)$courseconfig->maxsections;
2✔
147
            $sectionmenu = [];
2✔
148
            for ($i = 0; $i <= $max; $i++) {
2✔
149
                $sectionmenu[$i] = "$i";
2✔
150
            }
151
            $courseoptionsedit = [
2✔
152
                'hiddensections' => [
2✔
153
                    'label' => 'hidden1',
2✔
154
                    'element_type' => 'hidden',
2✔
155
                    'element_attributes' => [[1 => new \lang_string('hiddensectionsinvisible')]],
2✔
156
                ],
2✔
157
                'coursedisplay' => [
2✔
158
                    'label' => 'hidden2',
2✔
159
                    'element_type' => 'hidden',
2✔
160
                    'element_attributes' => [[COURSE_DISPLAY_SINGLEPAGE => new \lang_string('coursedisplay_single')]],
2✔
161
                ],
2✔
162
                'borderwidth' => [
2✔
163
                    'label' => new \lang_string('borderwidth', 'format_masonry'),
2✔
164
                    'element_type' => 'select',
2✔
165
                    'element_attributes' => [[0 => '0', 1 => '1', 2 => '2']],
2✔
166
                ],
2✔
167
                'bordercolor' => [
2✔
168
                    'label' => new \lang_string('bordercolor', 'format_masonry'),
2✔
169
                    'element_type' => 'text',
2✔
170
                    'element_attributes' => [['value' => $courseformatoptions['bordercolor']['default']]],
2✔
171
                ],
2✔
172
                'backcolor' => [
2✔
173
                    'label' => new \lang_string('colordisplay', 'format_masonry'),
2✔
174
                    'element_type' => 'text',
2✔
175
                    'help' => 'colordisplay',
2✔
176
                    'help_component' => 'format_masonry',
2✔
177
                    'element_attributes' => [['value' => $courseformatoptions['backcolor']['default']]],
2✔
178
                ],
2✔
179
            ];
2✔
180
            $courseformatoptions = array_merge_recursive($courseformatoptions, $courseoptionsedit);
2✔
181
        }
182
        return $courseformatoptions;
14✔
183
    }
184

185
    /**
186
     * Updates format options for a course
187
     *
188
     * @param stdClass|array $data
189
     * @param stdClass $oldcourse
190
     * @return bool whether there were any changes to the options values
191
     */
192
    public function update_course_format_options($data, $oldcourse = null) {
193
        if ($oldcourse !== null) {
14✔
194
            $data->backcolor = get_config('format_masonry', 'defaultbackgroundcolor');
2✔
195
            $data->bordercolor = get_config('format_masonry', 'defaultbordercolor');
2✔
196
            return parent::update_course_format_options($data, $oldcourse);
2✔
197
        }
198
        return $this->update_format_options($data);
14✔
199
    }
200

201
    /**
202
     * Prepares the templateable object to display section name.
203
     *
204
     * @param \section_info|\stdClass $section
205
     * @param bool $linkifneeded
206
     * @param bool $editable
207
     * @param null|lang_string|string $edithint
208
     * @param null|lang_string|string $editlabel
209
     * @return inplace_editable
210
     */
211
    public function inplace_editable_render_section_name(
212
        $section,
213
        $linkifneeded = false,
214
        $editable = null,
215
        $edithint = null,
216
        $editlabel = null
217
    ) {
218
        if (empty($edithint)) {
8✔
219
            $edithint = ($section->section == 0) ? 'section0name' : 'sectionname';
8✔
220
            $edithint = new lang_string($edithint, 'format_masonry');
8✔
221
        }
222
        if (empty($editlabel)) {
8✔
223
            $title = get_section_name($section->course, $section);
8✔
224
            $editlabel = new lang_string('newsectionname', 'format_masonry', $title);
8✔
225
        }
226
        return parent::inplace_editable_render_section_name($section, $linkifneeded, $editable, $edithint, $editlabel);
8✔
227
    }
228

229
    /**
230
     * Returns whether this course format allows the activity to be hidden on course page but available.
231
     *
232
     * @param stdClass|cm_info $cm course module (may be null if we are displaying a form for adding a module)
233
     * @param stdClass|section_info $section section where this module is located or will be added to
234
     * @return bool
235
     */
236
    public function allow_stealth_module_visibility($cm, $section) {
237
        return !$section->section || $section->visible;
2✔
238
    }
239

240
    /**
241
     * Returns true if this course format uses sections.
242
     *
243
     * @return bool
244
     */
245
    public function uses_sections() {
246
        return true;
8✔
247
    }
248

249
    /**
250
     * Whether this format allows to delete sections.
251
     *
252
     * @param int|stdClass|section_info $section
253
     * @return bool
254
     */
255
    public function can_delete_section($section) {
256
        return ($this->get_section($section)->section != 0);
4✔
257
    }
258

259
    /**
260
     * Whether this format allows course index.
261
     *
262
     * @return bool
263
     */
264
    public function uses_course_index() {
265
        return false;
2✔
266
    }
267

268
    /**
269
     * Whether this format allows to indentation.
270
     *
271
     * @return bool
272
     */
273
    public function uses_indentation(): bool {
274
        return false;
8✔
275
    }
276

277
    /**
278
     * Custom action after section has been moved in AJAX mode.
279
     *
280
     * @return array This will be passed in ajax respose
281
     */
282
    public function ajax_section_move() {
283
        global $PAGE;
284
        $titles = [];
2✔
285
        $course = $this->get_course();
2✔
286
        $modinfo = get_fast_modinfo($course);
2✔
287
        $renderer = $this->get_renderer($PAGE);
2✔
288
        if ($renderer && ($sections = $modinfo->get_section_info_all())) {
2✔
289
            foreach ($sections as $number => $section) {
2✔
290
                $titles[$number] = $renderer->section_title($section, $course);
2✔
291
            }
292
        }
293
        return ['sectiontitles' => $titles, 'action' => 'move'];
2✔
294
    }
295

296
    /**
297
     * Callback used in WS core_course_edit_section when teacher performs an AJAX action on a section (show/hide).
298
     *
299
     * @param section_info|stdClass $section
300
     * @param string $action
301
     * @param int $sr
302
     * @return null|array any data for the Javascript post-processor (must be json-encodeable)
303
     */
304
    public function section_action($section, $action, $sr) {
305
        global $PAGE;
306

307
        // For show/hide actions call the parent method and return the new content for .section_availability element.
308
        $rv = parent::section_action($section, $action, $sr);
2✔
309
        $renderer = $PAGE->get_renderer('format_masonry');
2✔
310

311
        if (!($section instanceof section_info)) {
2✔
312
            $modinfo = course_modinfo::instance($this->courseid);
2✔
313
            $section = $modinfo->get_section_info($section->section);
2✔
314
        }
315
        $elementclass = $this->get_output_classname('content\\section\\availability');
2✔
316
        $availability = new $elementclass($this, $section);
2✔
317

318
        $rv['section_availability'] = $renderer->render($availability);
2✔
319
        return $rv;
2✔
320
    }
321

322
    /**
323
     * Returns the information about the ajax support in the given source format.
324
     *
325
     * @return stdClass
326
     */
327
    public function supports_ajax() {
328
        $ajaxsupport = new stdClass();
2✔
329
        $ajaxsupport->capable = true;
2✔
330
        return $ajaxsupport;
2✔
331
    }
332

333
    /**
334
     * Return the plugin configs for external functions.
335
     *
336
     * @return array the list of configuration settings
337
     */
338
    public function get_config_for_external() {
339
        // Return everything (nothing to hide).
340
        return $this->get_format_options();
2✔
341
    }
342
}
343

344
/**
345
 * Implements callback inplace_editable() allowing to edit values in-place
346
 *
347
 * @param string $itemtype
348
 * @param int $itemid
349
 * @param mixed $newvalue
350
 * @return \core\output\inplace_editable
351
 */
352
function format_masonry_inplace_editable($itemtype, $itemid, $newvalue) {
353
    global $CFG, $DB;
354
    require_once($CFG->dirroot . '/course/lib.php');
2✔
355
    if ($itemtype == 'sectionname' || $itemtype == 'sectionnamenl') {
2✔
356
        $sql = 'SELECT s.* FROM {course_sections} s JOIN {course} c ON s.course = c.id WHERE s.id = ? AND c.format = ?';
×
357
        $section = $DB->get_record_sql($sql, [$itemid, 'masonry'], MUST_EXIST);
×
358
        return course_get_format($section->course)->inplace_editable_update_section_name($section, $itemtype, $newvalue);
×
359
    }
360
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc