MDL-39571 repository_recent: query improvement
[moodle.git] / repository / recent / lib.php
CommitLineData
6fbf3c48
DC
1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
67233725 19 * This plugin is used to access recent used files
6fbf3c48 20 *
5bcfd504 21 * @since Moodle 2.0
67233725
DC
22 * @package repository_recent
23 * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org}
d078f6d3 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6fbf3c48 25 */
67233725 26require_once($CFG->dirroot . '/repository/lib.php');
6fbf3c48 27
67233725
DC
28/**
29 * repository_recent class is used to browse recent used files
30 *
5bcfd504 31 * @since Moodle 2.0
67233725
DC
32 * @package repository_recent
33 * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org}
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 */
6fbf3c48 36define('DEFAULT_RECENT_FILES_NUM', 50);
a9c139c8
NN
37
38/**
39 * DEFAULT_RECENT_FILES_TIME_LIMIT - default time limit.
40 */
41define('DEFAULT_RECENT_FILES_TIME_LIMIT', 6 * 4 * WEEKSECS);
6fbf3c48
DC
42class repository_recent extends repository {
43
a9c139c8
NN
44 /** @var int only retrieve files within the time limit */
45 protected $timelimit;
46
6fbf3c48 47 /**
e35194be 48 * Initialize recent plugin
6fbf3c48
DC
49 * @param int $repositoryid
50 * @param int $context
51 * @param array $options
52 */
53 public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
54 parent::__construct($repositoryid, $context, $options);
55 $number = get_config('recent', 'recentfilesnumber');
56 $number = (int)$number;
57 if (empty($number)) {
58 $this->number = DEFAULT_RECENT_FILES_NUM;
59 } else {
60 $this->number = $number;
61 }
a9c139c8
NN
62 $timelimit = get_config('recent', 'recentfilestimelimit');
63 $this->timelimit = (int)$timelimit;
6fbf3c48
DC
64 }
65
66 /**
67 * recent plugin doesn't require login, so list all files
68 * @return mixed
69 */
70 public function print_login() {
71 return $this->get_listing();
72 }
73
a9c139c8
NN
74 /**
75 * Only return files within the time limit
76 *
77 * @param int $limitfrom retrieve the files from
78 * @param int $limit limit number of the files
79 * @param int $timelimit only return files with the time limit
80 * @return array list of recent files
81 */
82 private function get_recent_files($limitfrom = 0, $limit = DEFAULT_RECENT_FILES_NUM, $timelimit = 0) {
0f729672
DC
83 // XXX: get current itemid
84 global $USER, $DB, $itemid;
a9c139c8
NN
85 $timelimitsql = '';
86 if ($timelimit > 0) {
87 $timelimitsql = "AND timemodified >= :timelimit";
88 $timelimitparam = ['timelimit' => time() - $timelimit];
89 }
fc4e8034
DC
90 // This SQL will ignore draft files if not owned by current user.
91 // Ignore all file references.
a9c139c8
NN
92 $sql = "SELECT files1.id, files1.contextid, files1.component, files1.filearea,
93 files1.itemid, files1.filepath, files1.filename, files1.pathnamehash
ad08c563
EL
94 FROM {files} files1
95 JOIN (
96 SELECT contenthash, filename, MAX(id) AS id
97 FROM {files}
98 WHERE userid = :userid
a9c139c8 99 AND referencefileid is NULL
ad08c563
EL
100 AND filename != :filename
101 AND ((filearea = :filearea1 AND itemid = :itemid) OR filearea != :filearea2)
a9c139c8 102 $timelimitsql
ad08c563
EL
103 GROUP BY contenthash, filename
104 ) files2 ON files1.id = files2.id
a9c139c8 105 ORDER BY files1.timemodified DESC";
ad08c563
EL
106 $params = array(
107 'userid' => $USER->id,
108 'filename' => '.',
109 'filearea1' => 'draft',
110 'itemid' => $itemid,
111 'filearea2' => 'draft');
a9c139c8
NN
112 if (isset($timelimitparam)) {
113 $params = array_merge($params, $timelimitparam);
114 }
22f944e3 115 $rs = $DB->get_recordset_sql($sql, $params, $limitfrom, $limit);
6fbf3c48
DC
116 $result = array();
117 foreach ($rs as $file_record) {
118 $info = array();
119 $info['contextid'] = $file_record->contextid;
120 $info['itemid'] = $file_record->itemid;
121 $info['filearea'] = $file_record->filearea;
16f61c70 122 $info['component'] = $file_record->component;
6fbf3c48
DC
123 $info['filepath'] = $file_record->filepath;
124 $info['filename'] = $file_record->filename;
125 $result[$file_record->pathnamehash] = $info;
126 }
127 $rs->close();
128 return $result;
129 }
130
131 /**
132 * Get file listing
133 *
134 * @param string $encodedpath
135 * @param string $path not used by this plugin
136 * @return mixed
137 */
138 public function get_listing($encodedpath = '', $page = '') {
7d3ebf4c 139 global $OUTPUT;
6fbf3c48
DC
140 $ret = array();
141 $ret['dynload'] = true;
142 $ret['nosearch'] = true;
03896eb7 143 $ret['nologin'] = true;
6fbf3c48 144 $list = array();
a9c139c8 145 $files = $this->get_recent_files(0, $this->number, $this->timelimit);
6fbf3c48
DC
146
147 try {
148 foreach ($files as $file) {
5bdf63cc
MG
149 // Check that file exists and accessible, retrieve size/date info
150 $browser = get_file_browser();
d197ea43 151 $context = context::instance_by_id($file['contextid']);
5bdf63cc
MG
152 $fileinfo = $browser->get_file_info($context, $file['component'],
153 $file['filearea'], $file['itemid'], $file['filepath'], $file['filename']);
154 if ($fileinfo) {
56964b79 155 $params = base64_encode(json_encode($file));
7d3ebf4c 156 $node = array(
559276b1 157 'title' => $fileinfo->get_visible_name(),
5bdf63cc
MG
158 'size' => $fileinfo->get_filesize(),
159 'datemodified' => $fileinfo->get_timemodified(),
160 'datecreated' => $fileinfo->get_timecreated(),
161 'author' => $fileinfo->get_author(),
162 'license' => $fileinfo->get_license(),
7d3ebf4c 163 'source'=> $params,
663640f5
DW
164 'icon' => $OUTPUT->image_url(file_file_icon($fileinfo, 24))->out(false),
165 'thumbnail' => $OUTPUT->image_url(file_file_icon($fileinfo, 90))->out(false),
7d3ebf4c 166 );
dfad252c
DM
167 if ($imageinfo = $fileinfo->get_imageinfo()) {
168 $fileurl = new moodle_url($fileinfo->get_url());
3333e7e2
DM
169 $node['realthumbnail'] = $fileurl->out(false, array('preview' => 'thumb', 'oid' => $fileinfo->get_timemodified()));
170 $node['realicon'] = $fileurl->out(false, array('preview' => 'tinyicon', 'oid' => $fileinfo->get_timemodified()));
dfad252c
DM
171 $node['image_width'] = $imageinfo['width'];
172 $node['image_height'] = $imageinfo['height'];
173 }
7d3ebf4c
MG
174 $list[] = $node;
175 }
6fbf3c48
DC
176 }
177 } catch (Exception $e) {
178 throw new repository_exception('emptyfilelist', 'repository_recent');
179 }
87628a67 180 $ret['list'] = array_filter($list, array($this, 'filter'));
6fbf3c48
DC
181 return $ret;
182 }
183
6fbf3c48 184 public static function get_type_option_names() {
a9c139c8 185 return array('recentfilesnumber', 'recentfilestimelimit', 'pluginname');
6fbf3c48
DC
186 }
187
68a7c9a6 188 public static function type_config_form($mform, $classname = 'repository') {
58eb9b9f 189 parent::type_config_form($mform, $classname);
6fbf3c48 190 $number = get_config('repository_recent', 'recentfilesnumber');
6fbf3c48
DC
191 if (empty($number)) {
192 $number = DEFAULT_RECENT_FILES_NUM;
193 }
194 $mform->addElement('text', 'recentfilesnumber', get_string('recentfilesnumber', 'repository_recent'));
6481aafb 195 $mform->setType('recentfilesnumber', PARAM_INT);
1e791d83 196 $mform->setDefault('recentfilesnumber', $number);
a9c139c8
NN
197
198 $mform->addElement('duration', 'recentfilestimelimit',
199 get_string('timelimit', 'repository_recent'), ['units' => [DAYSECS, WEEKSECS], 'optional' => true]);
200 $mform->addHelpButton('recentfilestimelimit', 'timelimit', 'repository_recent');
201 $mform->setDefault('recentfilestimelimit', DEFAULT_RECENT_FILES_TIME_LIMIT);
6fbf3c48
DC
202 }
203
204 /**
205 * This plugin doesn't support to link to external links
206 *
207 * @return int
208 */
209 public function supported_returntypes() {
210 return FILE_INTERNAL;
211 }
1bd01747 212
acb70a9b 213 /**
1bd01747
MG
214 * Repository method to make sure that user can access particular file.
215 *
216 * This is checked when user tries to pick the file from repository to deal with
217 * potential parameter substitutions is request
acb70a9b 218 *
1bd01747
MG
219 * @todo MDL-33805 remove this function when recent files are managed correctly
220 *
221 * @param string $source
222 * @return bool whether the file is accessible by current user
acb70a9b 223 */
1bd01747 224 public function file_is_accessible($source) {
2dfa16ef 225 global $USER;
56964b79
MG
226 $reference = $this->get_file_reference($source);
227 $file = self::get_moodle_file($reference);
1bd01747 228 return (!empty($file) && $file->get_userid() == $USER->id);
f392caba 229 }
acb70a9b 230
f392caba
DC
231 /**
232 * Does this repository used to browse moodle files?
233 *
234 * @return boolean
235 */
236 public function has_moodle_files() {
237 return true;
acb70a9b 238 }
31581ae6
FM
239
240 /**
241 * Is this repository accessing private data?
242 *
243 * @return bool
244 */
245 public function contains_private_data() {
246 return false;
247 }
6fbf3c48 248}