Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 * Glossary Random block.
19
 *
20
 * @package   block_glossary_random
21
 * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
define('BGR_RANDOMLY',     '0');
26
define('BGR_LASTMODIFIED', '1');
27
define('BGR_NEXTONE',      '2');
28
define('BGR_NEXTALPHA',    '3');
29
 
30
class block_glossary_random extends block_base {
31
 
32
    /**
33
     * @var cm_info|stdClass has properties 'id' (course module id) and 'uservisible'
34
     *     (whether the glossary is visible to the current user)
35
     */
36
    protected $glossarycm = null;
37
 
38
    /** @var stdClass course data. */
39
    public $course;
40
 
41
    function init() {
42
        $this->title = get_string('pluginname','block_glossary_random');
43
    }
44
 
45
    function specialization() {
46
        global $CFG, $DB;
47
 
48
        require_once($CFG->libdir . '/filelib.php');
49
 
50
        $this->course = $this->page->course;
51
 
52
        // load userdefined title and make sure it's never empty
53
        if (empty($this->config->title)) {
54
            $this->title = get_string('pluginname','block_glossary_random');
55
        } else {
56
            $this->title = format_string($this->config->title, true, ['context' => $this->context]);
57
        }
58
 
59
        if (empty($this->config->glossary)) {
60
            return false;
61
        }
62
 
63
        if (!isset($this->config->nexttime)) {
64
            $this->config->nexttime = 0;
65
        }
66
 
67
        //check if it's time to put a new entry in cache
68
        if (time() > $this->config->nexttime) {
69
 
70
            if (!($cm = $this->get_glossary_cm()) || !$cm->uservisible) {
71
                // Skip generating of the cache if we can't display anything to the current user.
72
                return false;
73
            }
74
 
75
            // place glossary concept and definition in $pref->cache
76
            if (!$numberofentries = $DB->count_records('glossary_entries',
77
                                                       array('glossaryid'=>$this->config->glossary, 'approved'=>1))) {
78
                $this->config->cache = get_string('noentriesyet','block_glossary_random');
79
                $this->instance_config_commit();
80
            }
81
 
82
            $glossaryctx = context_module::instance($cm->id);
83
 
1441 ariadna 84
            $entries = $DB->get_records_sql('SELECT id, concept, definition, definitionformat, definitiontrust
85
                                               FROM {glossary_entries}
86
                                              WHERE glossaryid = ? AND approved = 1
87
                                              ORDER BY timemodified ASC', [$this->config->glossary]);
1 efrain 88
 
1441 ariadna 89
            // Reset entries keys, so subsequent selection by index works correctly.
90
            $entries = array_values($entries);
1 efrain 91
 
1441 ariadna 92
            if (empty($entries)) {
93
                $text = get_string('noentriesyet', 'block_glossary_random');
94
            } else {
95
                // Now picking out the correct entry from the array.
96
                switch ($this->config->type) {
97
                    case BGR_RANDOMLY:
98
                        $i = ($numberofentries > 1) ? rand(1, $numberofentries) : 1;
99
                        if (count($entries) == 1) {
100
                            $entry = reset($entries);
101
                        } else {
102
                            $entry = $entries[$i - 1];
103
                        }
104
                        break;
1 efrain 105
 
1441 ariadna 106
                    case BGR_NEXTONE:
107
                        // The array is already sorted by last modified.
108
                        if (isset($this->config->previous)) {
109
                            $i = $this->config->previous + 1;
110
                        } else {
111
                            $i = 1;
112
                        }
113
                        if ($i > $numberofentries) {  // Loop back to beginning.
114
                            $i = 1;
115
                        }
116
                        if (count($entries) == 1) {
117
                            $entry = reset($entries);
118
                        } else {
119
                            $entry = $entries[$i - 1];
120
                        }
121
                        break;
1 efrain 122
 
1441 ariadna 123
                    case BGR_NEXTALPHA:
124
                        // Now sort the array in regard to the current language.
125
                        usort($entries, function($a, $b) {
126
                            return format_string($a->concept) <=> format_string($b->concept);
127
                        });
128
                        if (isset($this->config->previous)) {
129
                            $i = $this->config->previous + 1;
130
                        } else {
131
                            $i = 1;
132
                        }
133
                        if ($i > $numberofentries) {  // Loop back to beginning.
134
                            $i = 1;
135
                        }
136
                        if (count($entries) == 1) {
137
                            $entry = $entries;
138
                        } else {
139
                            $entry = $entries[$i - 1];
140
                        }
141
                        break;
1 efrain 142
 
1441 ariadna 143
                    default:  // BGR_LASTMODIFIED
144
                        // The array is already sorted by last modified.
145
                        $i = $numberofentries;
146
                        if (count($entries) == 1) {
147
                            $entry = reset($entries);
148
                        } else {
149
                            $entry = array_pop($entries);
150
                        }
151
                        break;
152
                }
153
                if (empty($this->config->showconcept) || (!isset($entry->concept))) {
1 efrain 154
                    $text = '';
155
                } else {
1441 ariadna 156
                    $text = "<h3>" . format_string($entry->concept, true, ["context" => $glossaryctx]) . "</h3>";
1 efrain 157
                }
158
 
159
                $options = new stdClass();
1441 ariadna 160
                if (isset($entry->definitiontrust)) {
161
                    $options->trusted = $entry->definitiontrust;
162
                }
1 efrain 163
                $options->overflowdiv = true;
1441 ariadna 164
                if (isset($entry->definitiontrust) && isset($entry->id) && isset($entry->definition)) {
165
                    $entry->definition = file_rewrite_pluginfile_urls($entry->definition, 'pluginfile.php', $glossaryctx->id,
166
                        'mod_glossary', 'entry', $entry->id);
167
                    $text .= format_text($entry->definition, $entry->definitionformat, $options);
168
                }
1 efrain 169
                $this->config->nexttime = usergetmidnight(time()) + DAYSECS * $this->config->refresh;
170
                $this->config->previous = $i;
1441 ariadna 171
            }
1 efrain 172
 
173
            // store the text
174
            $this->config->cache = $text;
175
            $this->instance_config_commit();
176
        }
177
    }
178
 
179
    /**
180
     * Replace the instance's configuration data with those currently in $this->config;
181
     */
182
    function instance_config_commit($nolongerused = false) {
183
        // Unset config variables that are no longer used.
184
        unset($this->config->globalglossary);
185
        unset($this->config->courseid);
186
        parent::instance_config_commit($nolongerused);
187
    }
188
 
189
    /**
190
     * Checks if glossary is available - it should be either located in the same course or be global
191
     *
192
     * @return null|cm_info|stdClass object with properties 'id' (course module id) and 'uservisible'
193
     */
194
    protected function get_glossary_cm() {
195
        global $DB;
196
        if (empty($this->config->glossary)) {
197
            // No glossary is configured.
198
            return null;
199
        }
200
 
201
        if (!empty($this->glossarycm)) {
202
            return $this->glossarycm;
203
        }
204
 
205
        if (!empty($this->page->course->id)) {
206
            // First check if glossary belongs to the current course (we don't need to make any DB queries to find it).
207
            $modinfo = get_fast_modinfo($this->page->course);
208
            if (isset($modinfo->instances['glossary'][$this->config->glossary])) {
209
                $this->glossarycm = $modinfo->instances['glossary'][$this->config->glossary];
210
                if ($this->glossarycm->uservisible) {
211
                    // The glossary is in the same course and is already visible to the current user,
212
                    // no need to check if it is global, save on DB query.
213
                    return $this->glossarycm;
214
                }
215
            }
216
        }
217
 
218
        // Find course module id for the given glossary, only if it is global.
219
        $cm = $DB->get_record_sql("SELECT cm.id, cm.visible AS uservisible
220
              FROM {course_modules} cm
221
                   JOIN {modules} md ON md.id = cm.module
222
                   JOIN {glossary} g ON g.id = cm.instance
223
             WHERE g.id = :instance AND md.name = :modulename AND g.globalglossary = 1",
224
            ['instance' => $this->config->glossary, 'modulename' => 'glossary']);
225
 
226
        if ($cm) {
227
            // This is a global glossary, create an object with properties 'id' and 'uservisible'. We don't need any
228
            // other information so why bother retrieving it. Full access check is skipped for global glossaries for
229
            // performance reasons.
230
            $this->glossarycm = $cm;
231
        } else if (empty($this->glossarycm)) {
232
            // Glossary does not exist. Remove it in the config so we don't repeat this check again later.
233
            $this->config->glossary = 0;
234
            $this->instance_config_commit();
235
        }
236
 
237
        return $this->glossarycm;
238
    }
239
 
240
    function instance_allow_multiple() {
241
    // Are you going to allow multiple instances of each block?
242
    // If yes, then it is assumed that the block WILL USE per-instance configuration
243
        return true;
244
    }
245
 
246
    function get_content() {
247
        if ($this->content !== null) {
248
            return $this->content;
249
        }
250
        $this->content = (object)['text' => '', 'footer' => ''];
251
 
252
        if (!$cm = $this->get_glossary_cm()) {
253
            if ($this->user_can_edit()) {
254
                $this->content->text = get_string('notyetconfigured', 'block_glossary_random');
255
            }
256
            return $this->content;
257
        }
258
 
259
        if (empty($this->config->cache)) {
260
            $this->config->cache = '';
261
        }
262
 
263
        if ($cm->uservisible) {
264
            // Show glossary if visible and place links in footer.
265
            $this->content->text = $this->config->cache;
266
            if (has_capability('mod/glossary:write', context_module::instance($cm->id))) {
267
                $this->content->footer = html_writer::link(new moodle_url('/mod/glossary/edit.php', ['cmid' => $cm->id]),
268
                    format_string($this->config->addentry)) . '<br/>';
269
            }
270
 
271
            $this->content->footer .= html_writer::link(new moodle_url('/mod/glossary/view.php', ['id' => $cm->id]),
272
                format_string($this->config->viewglossary));
273
        } else {
274
            // Otherwise just place some text, no link.
275
            $this->content->footer = format_string($this->config->invisible);
276
        }
277
 
278
        return $this->content;
279
    }
280
 
281
    /**
282
     * Return the plugin config settings for external functions.
283
     *
284
     * @return stdClass the configs for both the block instance and plugin
285
     * @since Moodle 3.8
286
     */
287
    public function get_config_for_external() {
288
        // Return all settings for all users since it is safe (no private keys, etc..).
289
        $configs = !empty($this->config) ? $this->config : new stdClass();
290
 
291
        return (object) [
292
            'instance' => $configs,
293
            'plugin' => new stdClass(),
294
        ];
295
    }
296
 
297
    /**
298
     * This block shouldn't be added to a page if the glossary module is disabled.
299
     *
300
     * @param moodle_page $page
301
     * @return bool
302
     */
303
    public function can_block_be_added(moodle_page $page): bool {
304
        $pluginclass = \core_plugin_manager::resolve_plugininfo_class('mod');
305
        return $pluginclass::get_enabled_plugin('glossary');
306
    }
307
}