MDL-68931 core: No feedback link on footer if the feature is disabled
[moodle.git] / lib / classes / userfeedback.php
CommitLineData
2cbe9eaf
SR
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 * This file contains the core_userfeedback class
19 *
20 * @package core
21 * @copyright 2020 Shamim Rezaie <shamim@moodle.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26
27/**
28 * This Class contains helper functions for user feedback functionality.
29 *
30 * @copyright 2020 Shamim Rezaie <shamim@moodle.com>
31 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32 */
33class core_userfeedback {
34 /**
35 * @var int Ask user to give feedback a few days after each major upgrade.
36 */
37 public const REMIND_AFTER_UPGRADE = 1;
38
39 /**
40 * @var int Ask user to give feedback periodically.
41 */
42 public const REMIND_PERIODICALLY = 2;
43
44 /**
45 * @var int Do not ask user to give feedback.
46 */
47 public const REMIND_NEVER = 3;
d74a8268
SR
48
49 /**
50 * Displays the feedback reminder block.
51 */
52 public static function print_reminder_block(): void {
53 global $PAGE;
54
55 static $jscalled = false;
56
57 $actions = [
58 [
59 'title' => get_string('calltofeedback_give'),
60 'url' => '#',
61 'data' => [
62 'action' => 'give',
a3a9539b
SR
63 'record' => 1,
64 'hide' => 1,
d74a8268
SR
65 ],
66 ],
67 [
68 'title' => get_string('calltofeedback_remind'),
69 'url' => '#',
70 'data' => [
71 'action' => 'remind',
a3a9539b
SR
72 'record' => 1,
73 'hide' => 1,
d74a8268
SR
74 ],
75 ],
76 ];
77 $icon = [
78 'pix' => 'i/bullhorn',
79 'component' => 'core'
80 ];
81
82 \core\notification::add_call_to_action($icon, get_string('calltofeedback'), $actions, 'core/userfeedback');
83
84 if (!$jscalled) {
85 $jscalled = true;
86 // Calling the following more than once will register event listeners twice.
87 $PAGE->requires->js_call_amd('core/userfeedback', 'registerEventListeners');
88 }
89 }
90
91 /**
92 * Indicates whether the feedback reminder block should be shown or not.
93 *
94 * @return bool
95 */
96 public static function should_display_reminder(): bool {
97 global $CFG;
98
4cdcd23f 99 if (static::can_give_feedback()) {
d74a8268
SR
100 $give = get_user_preferences('core_userfeedback_give');
101 $remind = get_user_preferences('core_userfeedback_remind');
102
103 $lastactiontime = max($give ?: 0, $remind ?: 0);
104
105 switch ($CFG->userfeedback_nextreminder) {
106 case self::REMIND_AFTER_UPGRADE:
107 $lastupgrade = self::last_major_upgrade_time();
108 if ($lastupgrade >= $lastactiontime) {
109 return $lastupgrade + ($CFG->userfeedback_remindafter * DAYSECS) < time();
110 }
111 break;
112 case self::REMIND_PERIODICALLY:
113 return $lastactiontime + ($CFG->userfeedback_remindafter * DAYSECS) < time();
114 break;
115 }
116 }
117 return false;
118 }
119
a3a9539b
SR
120 /**
121 * Prepare and return the URL of the feedback site
122 *
123 * @return moodle_url
124 */
125 public static function make_link(): moodle_url {
126 global $CFG, $PAGE;
a3a9539b
SR
127
128 $baseurl = $CFG->userfeedback_url ?? 'https://feedback.moodle.org/lms';
129 $lang = clean_param(current_language(), PARAM_LANG); // Avoid breaking WS because of incorrect package langs.
130 $moodleurl = $CFG->wwwroot;
131 $moodleversion = $CFG->release;
132 $theme = $PAGE->theme->name;
ee8a4fbb 133 $themeversion = get_config('theme_'.$theme, 'version');
a3a9539b
SR
134
135 $url = new moodle_url($baseurl, [
136 'lang' => $lang,
137 'moodle_url' => $moodleurl,
138 'moodle_version' => $moodleversion,
139 'theme' => $theme,
140 'theme_version' => $themeversion,
141 'newtest' => 'Y', // Respondents might be using the same device/browser to fill out the survey.
142 // The newtest param resets the session.
143 ]);
144
145 return $url;
146 }
147
4cdcd23f
SR
148 /**
149 * Whether the current can give feedback.
150 *
151 * @return bool
152 */
153 public static function can_give_feedback(): bool {
154 global $CFG;
155
156 return $CFG->enableuserfeedback && isloggedin() && !isguestuser();
157 }
158
d74a8268
SR
159 /**
160 * Returns the last major upgrade time
161 *
162 * @return int
163 */
164 private static function last_major_upgrade_time(): int {
165 global $DB;
166
167 $targetversioncast = $DB->sql_cast_char2real('targetversion');
168 $versioncast = $DB->sql_cast_char2real('version');
169
170 // A time difference more than 3 months has to be a core upgrade.
20146e3f 171 // Also, passing IGNORE_MULTIPLE because we are only interested in the first field and LIMIT is not cross-DB.
d74a8268
SR
172 $time = $DB->get_field_sql("SELECT timemodified
173 FROM {upgrade_log}
174 WHERE plugin = 'core' AND $targetversioncast - $versioncast > 30000
20146e3f 175 ORDER BY timemodified DESC", null, IGNORE_MULTIPLE);
d74a8268
SR
176
177 return (int)$time;
178 }
2cbe9eaf 179}