1<?php
2
3/// This page prints a particular instance of glossary
4require_once("../../config.php");
5require_once("lib.php");
6require_once($CFG->libdir . '/completionlib.php');
7require_once("$CFG->libdir/rsslib.php");
8
9$id = optional_param('id', 0, PARAM_INT);           // Course Module ID
10$g  = optional_param('g', 0, PARAM_INT);            // Glossary ID
11
12$tab  = optional_param('tab', GLOSSARY_NO_VIEW, PARAM_ALPHA);    // browsing entries by categories?
13$displayformat = optional_param('displayformat',-1, PARAM_INT);  // override of the glossary display format
14
15$mode       = optional_param('mode', '', PARAM_ALPHA);           // term entry cat date letter search author approval
16$hook       = optional_param('hook', '', PARAM_CLEAN);           // the term, entry, cat, etc... to look for based on mode
17$fullsearch = optional_param('fullsearch', 0,PARAM_INT);         // full search (concept and definition) when searching?
18$sortkey    = optional_param('sortkey', '', PARAM_ALPHA);// Sorted view: CREATION | UPDATE | FIRSTNAME | LASTNAME...
19$sortorder  = optional_param('sortorder', 'ASC', PARAM_ALPHA);   // it defines the order of the sorting (ASC or DESC)
20$offset     = optional_param('offset', 0,PARAM_INT);             // entries to bypass (for paging purposes)
21$page       = optional_param('page', 0,PARAM_INT);               // Page to show (for paging purposes)
22$show       = optional_param('show', '', PARAM_ALPHA);           // [ concept | alias ] => mode=term hook=$show
23
24if (!empty($id)) {
25    if (! $cm = get_coursemodule_from_id('glossary', $id)) {
26        print_error('invalidcoursemodule');
27    }
28    if (! $course = $DB->get_record("course", array("id"=>$cm->course))) {
29        print_error('coursemisconf');
30    }
31    if (! $glossary = $DB->get_record("glossary", array("id"=>$cm->instance))) {
32        print_error('invalidid', 'glossary');
33    }
34
35} else if (!empty($g)) {
36    if (! $glossary = $DB->get_record("glossary", array("id"=>$g))) {
37        print_error('invalidid', 'glossary');
38    }
39    if (! $course = $DB->get_record("course", array("id"=>$glossary->course))) {
40        print_error('invalidcourseid');
41    }
42    if (!$cm = get_coursemodule_from_instance("glossary", $glossary->id, $course->id)) {
43        print_error('invalidcoursemodule');
44    }
45    $id = $cm->id;
46} else {
47    print_error('invalidid', 'glossary');
48}
49$cm = cm_info::create($cm);
50
51require_course_login($course->id, true, $cm);
52$context = context_module::instance($cm->id);
53require_capability('mod/glossary:view', $context);
54
55// Prepare format_string/text options
56$fmtoptions = array(
57    'context' => $context);
58
59require_once($CFG->dirroot . '/comment/lib.php');
60comment::init();
61
62/// redirecting if adding a new entry
63if ($tab == GLOSSARY_ADDENTRY_VIEW ) {
64    redirect("edit.php?cmid=$cm->id&amp;mode=$mode");
65}
66
67/// setting the defaut number of entries per page if not set
68if ( !$entriesbypage = $glossary->entbypage ) {
69    $entriesbypage = $CFG->glossary_entbypage;
70}
71
72// If we have received a page, recalculate offset and page size.
73$pagelimit = $entriesbypage;
74if ($page > 0 && $offset == 0) {
75    $offset = $page * $entriesbypage;
76} else if ($page < 0) {
77    $offset = 0;
78    $pagelimit = 0;
79}
80
81/// setting the default values for the display mode of the current glossary
82/// only if the glossary is viewed by the first time
83if ( $dp = $DB->get_record('glossary_formats', array('name'=>$glossary->displayformat)) ) {
84/// Based on format->defaultmode, we build the defaulttab to be showed sometimes
85    $showtabs = glossary_get_visible_tabs($dp);
86    switch ($dp->defaultmode) {
87        case 'cat':
88            $defaulttab = GLOSSARY_CATEGORY_VIEW;
89
90            // Handle defaultmode if 'category' tab is disabled. Fallback to 'standard' tab.
91            if (!in_array(GLOSSARY_CATEGORY, $showtabs)) {
92                $defaulttab = GLOSSARY_STANDARD_VIEW;
93            }
94
95            break;
96        case 'date':
97            $defaulttab = GLOSSARY_DATE_VIEW;
98
99            // Handle defaultmode if 'date' tab is disabled. Fallback to 'standard' tab.
100            if (!in_array(GLOSSARY_DATE, $showtabs)) {
101                $defaulttab = GLOSSARY_STANDARD_VIEW;
102            }
103
104            break;
105        case 'author':
106            $defaulttab = GLOSSARY_AUTHOR_VIEW;
107
108            // Handle defaultmode if 'author' tab is disabled. Fallback to 'standard' tab.
109            if (!in_array(GLOSSARY_AUTHOR, $showtabs)) {
110                $defaulttab = GLOSSARY_STANDARD_VIEW;
111            }
112
113            break;
114        default:
115            $defaulttab = GLOSSARY_STANDARD_VIEW;
116    }
117/// Fetch the rest of variables
118    $printpivot = $dp->showgroup;
119    if ( $mode == '' and $hook == '' and $show == '') {
120        $mode      = $dp->defaultmode;
121        $hook      = $dp->defaulthook;
122        $sortkey   = $dp->sortkey;
123        $sortorder = $dp->sortorder;
124    }
125} else {
126    $defaulttab = GLOSSARY_STANDARD_VIEW;
127    $showtabs = array($defaulttab);
128    $printpivot = 1;
129    if ( $mode == '' and $hook == '' and $show == '') {
130        $mode = 'letter';
131        $hook = 'ALL';
132    }
133}
134
135if ( $displayformat == -1 ) {
136     $displayformat = $glossary->displayformat;
137}
138
139if ( $show ) {
140    $mode = 'term';
141    $hook = $show;
142    $show = '';
143}
144
145/// stablishing flag variables
146if ( $sortorder = strtolower($sortorder) ) {
147    if ($sortorder != 'asc' and $sortorder != 'desc') {
148        $sortorder = '';
149    }
150}
151if ( $sortkey = strtoupper($sortkey) ) {
152    if ($sortkey != 'CREATION' and
153        $sortkey != 'UPDATE' and
154        $sortkey != 'FIRSTNAME' and
155        $sortkey != 'LASTNAME'
156        ) {
157        $sortkey = '';
158    }
159}
160
161switch ( $mode = strtolower($mode) ) {
162case 'search': /// looking for terms containing certain word(s)
163    $tab = GLOSSARY_STANDARD_VIEW;
164
165    //Clean a bit the search string
166    $hook = trim(strip_tags($hook));
167
168break;
169
170case 'entry':  /// Looking for a certain entry id
171    $tab = GLOSSARY_STANDARD_VIEW;
172    if ( $dp = $DB->get_record("glossary_formats", array("name"=>$glossary->displayformat)) ) {
173        $displayformat = $dp->popupformatname;
174    }
175break;
176
177case 'cat':    /// Looking for a certain cat
178    $tab = GLOSSARY_CATEGORY_VIEW;
179
180    // Validation - we don't want to display 'category' tab if it is disabled.
181    if (!in_array(GLOSSARY_CATEGORY, $showtabs)) {
182        $tab = GLOSSARY_STANDARD_VIEW;
183    }
184
185    if ( $hook > 0 ) {
186        $category = $DB->get_record("glossary_categories", array("id"=>$hook));
187    }
188break;
189
190case 'approval':    /// Looking for entries waiting for approval
191    $tab = GLOSSARY_APPROVAL_VIEW;
192    // Override the display format with the approvaldisplayformat
193    if ($glossary->approvaldisplayformat !== 'default' && ($df = $DB->get_record("glossary_formats",
194            array("name" => $glossary->approvaldisplayformat)))) {
195        $displayformat = $df->popupformatname;
196    }
197    if ( !$hook and !$sortkey and !$sortorder) {
198        $hook = 'ALL';
199    }
200break;
201
202case 'term':   /// Looking for entries that include certain term in its concept, definition or aliases
203    $tab = GLOSSARY_STANDARD_VIEW;
204break;
205
206case 'date':
207    $tab = GLOSSARY_DATE_VIEW;
208
209    // Validation - we dont want to display 'date' tab if it is disabled.
210    if (!in_array(GLOSSARY_DATE, $showtabs)) {
211        $tab = GLOSSARY_STANDARD_VIEW;
212    }
213
214    if ( !$sortkey ) {
215        $sortkey = 'UPDATE';
216    }
217    if ( !$sortorder ) {
218        $sortorder = 'desc';
219    }
220break;
221
222case 'author':  /// Looking for entries, browsed by author
223    $tab = GLOSSARY_AUTHOR_VIEW;
224
225    // Validation - we dont want to display 'author' tab if it is disabled.
226    if (!in_array(GLOSSARY_AUTHOR, $showtabs)) {
227        $tab = GLOSSARY_STANDARD_VIEW;
228    }
229
230    if ( !$hook ) {
231        $hook = 'ALL';
232    }
233    if ( !$sortkey ) {
234        $sortkey = 'FIRSTNAME';
235    }
236    if ( !$sortorder ) {
237        $sortorder = 'asc';
238    }
239break;
240
241case 'letter':  /// Looking for entries that begin with a certain letter, ALL or SPECIAL characters
242default:
243    $tab = GLOSSARY_STANDARD_VIEW;
244    if ( !$hook ) {
245        $hook = 'ALL';
246    }
247break;
248}
249
250switch ( $tab ) {
251case GLOSSARY_IMPORT_VIEW:
252case GLOSSARY_EXPORT_VIEW:
253case GLOSSARY_APPROVAL_VIEW:
254    $showcommonelements = 0;
255break;
256
257default:
258    $showcommonelements = 1;
259break;
260}
261
262// Trigger module viewed event.
263glossary_view($glossary, $course, $cm, $context, $mode);
264
265/// Printing the heading
266$strglossaries = get_string("modulenameplural", "glossary");
267$strglossary = get_string("modulename", "glossary");
268$strallcategories = get_string("allcategories", "glossary");
269$straddentry = get_string("addentry", "glossary");
270$strnoentries = get_string("noentries", "glossary");
271$strsearchindefinition = get_string("searchindefinition", "glossary");
272$strsearch = get_string("search");
273$strwaitingapproval = get_string('waitingapproval', 'glossary');
274
275/// If we are in approval mode, prit special header
276$PAGE->set_title($glossary->name);
277$PAGE->set_heading($course->fullname);
278$url = new moodle_url('/mod/glossary/view.php', array('id'=>$cm->id));
279if (isset($mode)) {
280    $url->param('mode', $mode);
281}
282$PAGE->set_url($url);
283$PAGE->force_settings_menu();
284
285if (!empty($CFG->enablerssfeeds) && !empty($CFG->glossary_enablerssfeeds)
286    && $glossary->rsstype && $glossary->rssarticles) {
287
288    $rsstitle = format_string($course->shortname, true, array('context' => context_course::instance($course->id))) . ': '. format_string($glossary->name);
289    rss_add_http_header($context, 'mod_glossary', $glossary, $rsstitle);
290}
291
292if ($tab == GLOSSARY_APPROVAL_VIEW) {
293    require_capability('mod/glossary:approve', $context);
294    $PAGE->navbar->add($strwaitingapproval);
295    echo $OUTPUT->header();
296    echo $OUTPUT->heading($strwaitingapproval);
297} else { /// Print standard header
298    echo $OUTPUT->header();
299}
300echo $OUTPUT->heading(format_string($glossary->name), 2);
301
302// Render the activity information.
303$completiondetails = \core_completion\cm_completion_details::get_instance($cm, $USER->id);
304$activitydates = \core\activity_dates::get_dates_for_module($cm, $USER->id);
305echo $OUTPUT->activity_information($cm, $completiondetails, $activitydates);
306
307/// All this depends if whe have $showcommonelements
308if ($showcommonelements) {
309/// To calculate available options
310    $availableoptions = '';
311
312/// Decide about to print the import link
313    /*if (has_capability('mod/glossary:import', $context)) {
314        $availableoptions = '<span class="helplink">' .
315                            '<a href="' . $CFG->wwwroot . '/mod/glossary/import.php?id=' . $cm->id . '"' .
316                            '  title="' . s(get_string('importentries', 'glossary')) . '">' .
317                            get_string('importentries', 'glossary') . '</a>' .
318                            '</span>';
319    }
320/// Decide about to print the export link
321    if (has_capability('mod/glossary:export', $context)) {
322        if ($availableoptions) {
323            $availableoptions .= '&nbsp;/&nbsp;';
324        }
325        $availableoptions .='<span class="helplink">' .
326                            '<a href="' . $CFG->wwwroot . '/mod/glossary/export.php?id=' . $cm->id .
327                            '&amp;mode='.$mode . '&amp;hook=' . urlencode($hook) . '"' .
328                            '  title="' . s(get_string('exportentries', 'glossary')) . '">' .
329                            get_string('exportentries', 'glossary') . '</a>' .
330                            '</span>';
331    }*/
332
333/// Decide about to print the approval link
334    if (has_capability('mod/glossary:approve', $context)) {
335    /// Check we have pending entries
336        if ($hiddenentries = $DB->count_records('glossary_entries', array('glossaryid'=>$glossary->id, 'approved'=>0))) {
337            if ($availableoptions) {
338                $availableoptions .= '<br />';
339            }
340            $availableoptions .='<span class="helplink">' .
341                                '<a href="' . $CFG->wwwroot . '/mod/glossary/view.php?id=' . $cm->id .
342                                '&amp;mode=approval' . '"' .
343                                '  title="' . s(get_string('waitingapproval', 'glossary')) . '">' .
344                                get_string('waitingapproval', 'glossary') . ' ('.$hiddenentries.')</a>' .
345                                '</span>';
346        }
347    }
348
349/// Start to print glossary controls
350//        print_box_start('glossarycontrol clearfix');
351    echo '<div class="glossarycontrol" style="text-align: right">';
352    echo $availableoptions;
353
354/// The print icon
355    if ( $showcommonelements and $mode != 'search') {
356        if (has_capability('mod/glossary:manageentries', $context) or $glossary->allowprintview) {
357            $params = array(
358                'id'        => $cm->id,
359                'mode'      => $mode,
360                'hook'      => $hook,
361                'sortkey'   => $sortkey,
362                'sortorder' => $sortorder,
363                'offset'    => $offset,
364                'pagelimit' => $pagelimit
365            );
366            $printurl = new moodle_url('/mod/glossary/print.php', $params);
367            $printtitle = get_string('printerfriendly', 'glossary');
368            $printattributes = array(
369                'class' => 'printicon',
370                'title' => $printtitle
371            );
372            echo html_writer::link($printurl, $printtitle, $printattributes);
373        }
374    }
375/// End glossary controls
376//        print_box_end(); /// glossarycontrol
377    echo '</div><br />';
378
379//        print_box('&nbsp;', 'clearer');
380}
381
382/// Info box
383if ($glossary->intro && $showcommonelements) {
384    echo $OUTPUT->box(format_module_intro('glossary', $glossary, $cm->id), 'generalbox', 'intro');
385}
386
387/// Search box
388if ($showcommonelements ) {
389    $fullsearchchecked = false;
390    if ($fullsearch || $mode != 'search') {
391        $fullsearchchecked = true;
392    }
393
394    $check = [
395        'name' => 'fullsearch',
396        'id' => 'fullsearch',
397        'value' => '1',
398        'checked' => $fullsearchchecked,
399        'label' => $strsearchindefinition
400    ];
401
402    $checkbox = $OUTPUT->render_from_template('core/checkbox', $check);
403
404    $hiddenfields = [
405        (object) ['name' => 'id', 'value' => $cm->id],
406        (object) ['name' => 'mode', 'value' => 'search'],
407    ];
408    $data = [
409        'action' => new moodle_url('/mod/glossary/view.php'),
410        'hiddenfields' => $hiddenfields,
411        'otherfields' => $checkbox,
412        'inputname' => 'hook',
413        'query' => ($mode == 'search') ? s($hook) : '',
414        'searchstring' => get_string('search'),
415        'extraclasses' => 'my-2'
416    ];
417    echo $OUTPUT->render_from_template('core/search_input', $data);
418}
419
420/// Show the add entry button if allowed
421if (has_capability('mod/glossary:write', $context) && $showcommonelements ) {
422    echo '<div class="singlebutton glossaryaddentry">';
423    echo "<form class=\"form form-inline mb-1\" id=\"newentryform\" method=\"get\" action=\"$CFG->wwwroot/mod/glossary/edit.php\">";
424    echo '<div>';
425    echo "<input type=\"hidden\" name=\"cmid\" value=\"$cm->id\" />";
426    echo '<input type="submit" value="'.get_string('addentry', 'glossary').'" class="btn btn-secondary" />';
427    echo '</div>';
428    echo '</form>';
429    echo "</div>\n";
430}
431
432
433require("tabs.php");
434
435require("sql.php");
436
437/// printing the entries
438$entriesshown = 0;
439$currentpivot = '';
440$paging = NULL;
441
442if ($allentries) {
443
444    //Decide if we must show the ALL link in the pagebar
445    $specialtext = '';
446    if ($glossary->showall) {
447        $specialtext = get_string("allentries","glossary");
448    }
449
450    //Build paging bar
451    $baseurl = new moodle_url('/mod/glossary/view.php', ['id' => $id, 'mode' => $mode, 'hook' => $hook,
452        'sortkey' => $sortkey, 'sortorder' => $sortorder, 'fullsearch' => $fullsearch]);
453    $paging = glossary_get_paging_bar($count, $page, $entriesbypage, $baseurl->out() . '&amp;',
454        9999, 10, '&nbsp;&nbsp;', $specialtext, -1);
455
456    echo '<div class="paging">';
457    echo $paging;
458    echo '</div>';
459
460    //load ratings
461    require_once($CFG->dirroot.'/rating/lib.php');
462    if ($glossary->assessed != RATING_AGGREGATE_NONE) {
463        $ratingoptions = new stdClass;
464        $ratingoptions->context = $context;
465        $ratingoptions->component = 'mod_glossary';
466        $ratingoptions->ratingarea = 'entry';
467        $ratingoptions->items = $allentries;
468        $ratingoptions->aggregate = $glossary->assessed;//the aggregation method
469        $ratingoptions->scaleid = $glossary->scale;
470        $ratingoptions->userid = $USER->id;
471        $ratingoptions->returnurl = $CFG->wwwroot.'/mod/glossary/view.php?id='.$cm->id;
472        $ratingoptions->assesstimestart = $glossary->assesstimestart;
473        $ratingoptions->assesstimefinish = $glossary->assesstimefinish;
474
475        $rm = new rating_manager();
476        $allentries = $rm->get_ratings($ratingoptions);
477    }
478
479    foreach ($allentries as $entry) {
480
481        // Setting the pivot for the current entry
482        if ($printpivot) {
483            $pivot = $entry->{$pivotkey};
484            $upperpivot = core_text::strtoupper($pivot);
485            $pivottoshow = core_text::strtoupper(format_string($pivot, true, $fmtoptions));
486
487            // Reduce pivot to 1cc if necessary.
488            if (!$fullpivot) {
489                $upperpivot = core_text::substr($upperpivot, 0, 1);
490                $pivottoshow = core_text::substr($pivottoshow, 0, 1);
491            }
492
493            // If there's a group break.
494            if ($currentpivot != $upperpivot) {
495                $currentpivot = $upperpivot;
496
497                // print the group break if apply
498
499                echo '<div>';
500                echo '<table cellspacing="0" class="glossarycategoryheader">';
501
502                echo '<tr>';
503                if ($userispivot) {
504                // printing the user icon if defined (only when browsing authors)
505                    echo '<th align="left">';
506                    $user = mod_glossary_entry_query_builder::get_user_from_record($entry);
507                    echo $OUTPUT->user_picture($user, array('courseid'=>$course->id));
508                    $pivottoshow = fullname($user, has_capability('moodle/site:viewfullnames', context_course::instance($course->id)));
509                } else {
510                    echo '<th >';
511                }
512
513                echo $OUTPUT->heading($pivottoshow, 3);
514                echo "</th></tr></table></div>\n";
515            }
516        }
517
518        /// highlight the term if necessary
519        if ($mode == 'search') {
520            //We have to strip any word starting by + and take out words starting by -
521            //to make highlight works properly
522            $searchterms = explode(' ', $hook);    // Search for words independently
523            foreach ($searchterms as $key => $searchterm) {
524                if (preg_match('/^\-/',$searchterm)) {
525                    unset($searchterms[$key]);
526                } else {
527                    $searchterms[$key] = preg_replace('/^\+/','',$searchterm);
528                }
529                //Avoid highlight of <2 len strings. It's a well known hilight limitation.
530                if (strlen($searchterm) < 2) {
531                    unset($searchterms[$key]);
532                }
533            }
534            $strippedsearch = implode(' ', $searchterms);    // Rebuild the string
535            $entry->highlight = $strippedsearch;
536        }
537
538        /// and finally print the entry.
539        glossary_print_entry($course, $cm, $glossary, $entry, $mode, $hook,1,$displayformat);
540        $entriesshown++;
541    }
542    // The all entries value may be a recordset or an array.
543    if ($allentries instanceof moodle_recordset) {
544        $allentries->close();
545    }
546}
547if ( !$entriesshown ) {
548    echo $OUTPUT->box(get_string("noentries","glossary"), "generalbox boxaligncenter boxwidthwide");
549}
550
551if (!empty($formsent)) {
552    // close the form properly if used
553    echo "</div>";
554    echo "</form>";
555}
556
557if ( $paging ) {
558    echo '<hr />';
559    echo '<div class="paging">';
560    echo $paging;
561    echo '</div>';
562}
563echo '<br />';
564glossary_print_tabbed_table_end();
565
566/// Finish the page
567echo $OUTPUT->footer();
568