"MDL-23823 allow users pick same file multi times in html editor"
[moodle.git] / repository / recent / lib.php
1 <?php
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/>.
18 /**
19  * repository_recent class is used to browse recent used files
20  *
21  * @since 2.0
22  * @package moodlecore
23  * @subpackage repository
24  * @copyright 2010 Dongsheng Cai <dongsheng@moodle.com>
25  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26  */
28 define('DEFAULT_RECENT_FILES_NUM', 50);
29 class repository_recent extends repository {
31     /**
32      * Initialize recent plugin
33      * @param int $repositoryid
34      * @param int $context
35      * @param array $options
36      */
37     public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
38         parent::__construct($repositoryid, $context, $options);
39         $number = get_config('recent', 'recentfilesnumber');
40         $number = (int)$number;
41         if (empty($number)) {
42             $this->number = DEFAULT_RECENT_FILES_NUM;
43         } else {
44             $this->number = $number;
45         }
46     }
48     /**
49      * recent plugin doesn't require login, so list all files
50      * @return mixed
51      */
52     public function print_login() {
53         return $this->get_listing();
54     }
56     private function get_recent_files($limitfrom = 0, $limit = DEFAULT_RECENT_FILES_NUM) {
57         // XXX: get current itemid
58         global $USER, $DB, $itemid;
59         $sql = 'SELECT * FROM {files} files1
60                 JOIN (SELECT contenthash, filename, MAX(id) AS id
61                 FROM {files}
62                 WHERE (userid = ? AND filename != ?) OR (filearea = ? AND itemid = ?)
63                 GROUP BY contenthash, filename) files2 ON files1.id = files2.id
64                 ORDER BY files1.timemodified DESC';
65         $params = array('userid'=>$USER->id, 'filename'=>'.', 'filearea'=>'draft', 'itemid'=>$itemid);
66         $rs = $DB->get_recordset_sql($sql, $params, $limitfrom, $limit);
67         $result = array();
68         foreach ($rs as $file_record) {
69             $info = array();
70             $info['contextid'] = $file_record->contextid;
71             $info['itemid'] = $file_record->itemid;
72             $info['filearea'] = $file_record->filearea;
73             $info['component'] = $file_record->component;
74             $info['filepath'] = $file_record->filepath;
75             $info['filename'] = $file_record->filename;
76             $result[$file_record->pathnamehash] = $info;
77         }
78         $rs->close();
79         return $result;
80     }
82     /**
83      * Get file listing
84      *
85      * @param string $encodedpath
86      * @param string $path not used by this plugin
87      * @return mixed
88      */
89     public function get_listing($encodedpath = '', $page = '') {
90         global $CFG, $USER, $OUTPUT;
91         $ret = array();
92         $ret['dynload'] = true;
93         $ret['nosearch'] = true;
94         $ret['nologin'] = true;
95         $list = array();
96         $files = $this->get_recent_files(0, $this->number);
98         try {
99             foreach ($files as $file) {
100                 $params = base64_encode(serialize($file));
101                 $node = array(
102                     'title' => $file['filename'],
103                     'shorttitle' => $this->get_short_filename($file['filename'], 12),
104                     'size' => 0,
105                     'date' => '',
106                     'source'=> $params,
107                     'thumbnail' => $OUTPUT->pix_url(file_extension_icon($file['filename'], 32))->out(false),
108                 );
109                 $list[] = $node;
110             }
111         } catch (Exception $e) {
112             throw new repository_exception('emptyfilelist', 'repository_recent');
113         }
114         $ret['list'] = array_filter($list, array($this, 'filter'));
115         return $ret;
116     }
118     public static function get_type_option_names() {
119         return array('recentfilesnumber', 'pluginname');
120     }
122     public function type_config_form($mform) {
123         parent::type_config_form($mform);
124         $number = get_config('repository_recent', 'recentfilesnumber');
125         if (empty($number)) {
126             $number = DEFAULT_RECENT_FILES_NUM;
127         }
128         $mform->addElement('text', 'recentfilesnumber', get_string('recentfilesnumber', 'repository_recent'));
129         $mform->setDefault('recentfilesnumber', $number);
130     }
132     /**
133      * This plugin doesn't support to link to external links
134      *
135      * @return int
136      */
137     public function supported_returntypes() {
138         return FILE_INTERNAL;
139     }
140     /**
141      * Copy a file to file area
142      *
143      * @global object $USER
144      * @global object $DB
145      * @param string $encoded The information of file, it is base64 encoded php serialized data
146      * @param string $draftitemid itemid
147      * @param string $new_filename The intended name of file
148      * @param string $new_filepath the new path in draft area
149      * @return array The information of file
150      */
151     public function copy_to_area($encoded, $draftitemid, $new_filepath, $new_filename) {
152         global $USER, $DB;
154         $user_context = get_context_instance(CONTEXT_USER, $USER->id);
156         $fs = get_file_storage();
158         $params = unserialize(base64_decode($encoded));
160         $contextid  = clean_param($params['contextid'], PARAM_INT);
161         $fileitemid = clean_param($params['itemid'], PARAM_INT);
162         $filename = clean_param($params['filename'], PARAM_FILE);
163         $filepath = clean_param($params['filepath'], PARAM_PATH);;
164         $filearea = clean_param($params['filearea'], PARAM_ALPHAEXT);
165         $component = clean_param($params['component'], PARAM_ALPHAEXT);
167         // XXX:
168         // When user try to pick a file from other filearea, normally file api will use file browse to
169         // operate the files with capability check, but in some areas, users don't have permission to
170         // browse the files (for example, forum_attachment area).
171         //
172         // To get 'recent' plugin working, we need to use lower level file_stoarge class to bypass the
173         // capability check, we will use a better workaround to improve it.
174         if ($stored_file = $fs->get_file($contextid, $component, $filearea, $fileitemid, $filepath, $filename)) {
175             if ($USER->id != $stored_file->get_userid()) {
176                 throw new moodle_exception('errornotyourfile', 'repository');
177             }
178             $file_record = array('contextid'=>$user_context->id, 'component'=>'user', 'filearea'=>'draft',
179                 'itemid'=>$draftitemid, 'filepath'=>$new_filepath, 'filename'=>$new_filename);
180             if ($file = $fs->get_file($user_context->id, 'user', 'draft', $draftitemid, $new_filepath, $new_filename)) {
181                 $info = array();
182                 $info['title']  = $file->get_filename();
183                 $info['itemid'] = $file->get_itemid();
184                 $info['filesize']  = $file->get_filesize();
185                 $info['contextid'] = $file->get_contextid();
186                 return $info;
187             }
188             $fs->create_file_from_storedfile($file_record, $stored_file);
189         }
191         $info = array();
192         $info['title']  = $new_filename;
193         $info['itemid'] = $draftitemid;
194         $info['filesize']  = $stored_file->get_filesize();
195         $info['contextid'] = $user_context->id;
197         return $info;
198     }