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

ewallah / moodle-format_masonry / 14536268610

18 Apr 2025 01:58PM UTC coverage: 98.75%. Remained the same
14536268610

push

github

rdebleu
405

237 of 240 relevant lines covered (98.75%)

7.67 hits per line

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

97.52
/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 2013-2024 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 2013-2024 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) {
8✔
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);
8✔
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);
10✔
75
        if ((string)$section->name !== '') {
10✔
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);
8✔
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
                'numsections' => ['default' => $courseconfig->numsections, 'type' => PARAM_INT],
2✔
139
                'hiddensections' => ['type' => PARAM_INT, 'default' => 1],
2✔
140
                'coursedisplay' => ['type' => PARAM_INT, 'default' => 1],
2✔
141
                'borderwidth' => ['type' => PARAM_INT, 'default' => 1],
2✔
142
                'bordercolor' => ['type' => PARAM_TEXT, 'default' => '#F0F0F0'],
2✔
143
                'backcolor' => ['type' => PARAM_TEXT, 'default' => '#F0F0F0'], ];
2✔
144
        }
145
        if ($foreditform && !isset($courseformatoptions['coursedisplay']['label'])) {
14✔
146
            $courseconfig = get_config('moodlecourse');
2✔
147
            $max = (int)$courseconfig->maxsections;
2✔
148
            $sectionmenu = [];
2✔
149
            for ($i = 0; $i <= $max; $i++) {
2✔
150
                $sectionmenu[$i] = "$i";
2✔
151
            }
152
            $courseoptionsedit = [
2✔
153
                'numsections' => [
2✔
154
                    'label' => new \lang_string('numberweeks'),
2✔
155
                    'element_type' => 'select',
2✔
156
                    'element_attributes' => [$sectionmenu],
2✔
157
                ],
2✔
158
                'hiddensections' => [
2✔
159
                    'label' => 'hidden1',
2✔
160
                    'element_type' => 'hidden',
2✔
161
                    'element_attributes' => [[1 => new \lang_string('hiddensectionsinvisible')]],
2✔
162
                ],
2✔
163
                'coursedisplay' => [
2✔
164
                    'label' => 'hidden2',
2✔
165
                    'element_type' => 'hidden',
2✔
166
                    'element_attributes' => [[COURSE_DISPLAY_SINGLEPAGE => new \lang_string('coursedisplay_single')]],
2✔
167
                ],
2✔
168
                'borderwidth' => [
2✔
169
                    'label' => new \lang_string('borderwidth', 'format_masonry'),
2✔
170
                    'element_type' => 'select',
2✔
171
                    'element_attributes' => [[0 => '0', 1 => '1', 2 => '2']],
2✔
172
                ],
2✔
173
                'bordercolor' => [
2✔
174
                    'label' => new \lang_string('bordercolor', 'format_masonry'),
2✔
175
                    'element_type' => 'text',
2✔
176
                    'element_attributes' => [['value' => $courseformatoptions['bordercolor']['default']]],
2✔
177
                ],
2✔
178
                'backcolor' => [
2✔
179
                    'label' => new \lang_string('colordisplay', 'format_masonry'),
2✔
180
                    'element_type' => 'text',
2✔
181
                    'help' => 'colordisplay',
2✔
182
                    'help_component' => 'format_masonry',
2✔
183
                    'element_attributes' => [['value' => $courseformatoptions['backcolor']['default']]],
2✔
184
                ],
2✔
185
            ];
2✔
186
            $courseformatoptions = array_merge_recursive($courseformatoptions, $courseoptionsedit);
2✔
187
        }
188
        return $courseformatoptions;
14✔
189
    }
190

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

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

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

246
    /**
247
     * Returns true if this course format uses sections.
248
     *
249
     * @return bool
250
     */
251
    public function uses_sections() {
252
        return true;
6✔
253
    }
254

255
    /**
256
     * Whether this format allows to delete sections.
257
     *
258
     * @param int|stdClass|section_info $section
259
     * @return bool
260
     */
261
    public function can_delete_section($section) {
262
        return ($this->get_section($section)->section != 0);
4✔
263
    }
264

265
    /**
266
     * Whether this format allows course index.
267
     *
268
     * @return bool
269
     */
270
    public function uses_course_index() {
271
        return false;
2✔
272
    }
273

274
    /**
275
     * Whether this format allows to indentation.
276
     *
277
     * @return bool
278
     */
279
    public function uses_indentation(): bool {
280
        return false;
8✔
281
    }
282

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

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

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

317
        if (!($section instanceof section_info)) {
2✔
318
            $modinfo = course_modinfo::instance($this->courseid);
2✔
319
            $section = $modinfo->get_section_info($section->section);
2✔
320
        }
321
        $elementclass = $this->get_output_classname('content\\section\\availability');
2✔
322
        $availability = new $elementclass($this, $section);
2✔
323

324
        $rv['section_availability'] = $renderer->render($availability);
2✔
325
        return $rv;
2✔
326
    }
327

328
    /**
329
     * Returns the information about the ajax support in the given source format.
330
     *
331
     * @return stdClass
332
     */
333
    public function supports_ajax() {
334
        $ajaxsupport = new stdClass();
2✔
335
        $ajaxsupport->capable = true;
2✔
336
        return $ajaxsupport;
2✔
337
    }
338

339
    /**
340
     * Return the plugin configs for external functions.
341
     *
342
     * @return array the list of configuration settings
343
     */
344
    public function get_config_for_external() {
345
        // Return everything (nothing to hide).
346
        return $this->get_format_options();
2✔
347
    }
348
}
349

350
/**
351
 * Implements callback inplace_editable() allowing to edit values in-place
352
 *
353
 * @param string $itemtype
354
 * @param int $itemid
355
 * @param mixed $newvalue
356
 * @return \core\output\inplace_editable
357
 */
358
function format_masonry_inplace_editable($itemtype, $itemid, $newvalue) {
359
    global $CFG, $DB;
360
    require_once($CFG->dirroot . '/course/lib.php');
2✔
361
    if ($itemtype == 'sectionname' || $itemtype == 'sectionnamenl') {
2✔
362
        $sql = 'SELECT s.* FROM {course_sections} s JOIN {course} c ON s.course = c.id WHERE s.id = ? AND c.format = ?';
×
363
        $section = $DB->get_record_sql($sql, [$itemid, 'masonry'], MUST_EXIST);
×
364
        return course_get_format($section->course)->inplace_editable_update_section_name($section, $itemtype, $newvalue);
×
365
    }
366
}
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