7cd2d39f756ced5308c2a0963d551d2d0a656476
[moodle.git] / repository / remotemoodle / repository.class.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_remotemoodle class
20  * This plugin allowed to connect a retrieve a file from another Moodle site
21  * This is a subclass of repository class
22  *
23  * @since 2.0
24  * @package moodlecore
25  * @subpackage repository
26  * @copyright 2009 Jerome Mouneyrac
27  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28  */
30 require_once($CFG->dirroot.'/repository/lib.php');
33 class repository_remotemoodle extends repository {
35     /**
36      * Constructor
37      * @global <type> $SESSION
38      * @global <type> $action
39      * @global <type> $CFG
40      * @param <type> $repositoryid
41      * @param <type> $context
42      * @param <type> $options
43      */
44     public function __construct($repositoryid, $context = SITEID, $options = array()) {
45         global $SESSION, $action, $CFG;
46         parent::__construct($repositoryid, $context, $options);
47         $this->mnet = get_mnet_environment();
48     }
50     /**
51      * Retrieve a file for a user of the Moodle client calling this function
52      * The file is encoded in base64
53      * @global <type> $DB
54      * @global <type> $USER
55      * @param <type> $username
56      * @param <type> $source
57      * @return <type>
58      */
59     public function retrieveFile($username, $source) {
60         global $DB, $USER;
62         $remoteclient = get_mnet_remote_client();
64         ///check the the user is known
65         ///he has to be previously connected to the server site in order to be in the database
66         //TODO: MDL-21318 this looks problematic, because global $USER would need to be set back after this,
67         //      also is the user allowed to roam?
68         $USER = $DB->get_record('user',array('username' => $username, 'mnethostid' => $remoteclient->id));
69         if (empty($USER)) {
70             throw new mnet_server_exception(9012, get_string('usernotfound', 'repository_remotemoodle',  $username));
71         }
73         $file = unserialize(base64_decode($source));
74         $contextid = $file[0];
75         $filearea = $file[1];
76         $itemid = $file[2];
77         $filepath = $file[3];
78         $filename = $file[4];
80         ///check that the user has read permission on this file
81         $browser = get_file_browser();
82         $fileinfo = $browser->get_file_info(get_context_instance_by_id($contextid), $filearea, $itemid, $filepath, $filename);
83         if (empty($fileinfo)) {
84             throw new mnet_server_exception(9013, get_string('usercannotaccess', 'repository_remotemoodle',  $file));
85         }
87         ///retrieve the file with file API functions and return it encoded in base64
88         $fs = get_file_storage();
89         $sf = $fs->get_file($contextid, $filearea, $itemid, $filepath, $filename);
90         $contents = base64_encode($sf->get_content());
91         return array($contents, $sf->get_filename());
92     }
94     /**
95      * Retrieve file list for a user of the Moodle client calling this function
96      * @global <type> $DB
97      * @global <type> $USER
98      * @global <type> $CFG
99      * @param <type> $username
100      * @param <type> $search
101      * @return <type>
102      */
103     public function getFileList($username, $search) {
104         global $DB, $USER, $CFG;
106         $remoteclient = get_mnet_remote_client();
107         ///check the the user is known
108         ///he has to be previously connected to the server site in order to be in the database
109         //TODO: MDL-21318 this looks problematic, because global $USER would need to be set back after this,
110         //      also is the user allowed to roam?
111         $USER = $DB->get_record('user',array('username' => $username, 'mnethostid' => $remoteclient->id));
112         if (empty($USER)) {
113             throw new mnet_server_exception(9012, get_string('usernotfound', 'repository_remotemoodle',  $username));
114         }
116         try {
117             return repository::get_user_file_tree($search);
118         }
119         catch (Exception $e) {
120             throw new mnet_server_exception(9014, get_string('failtoretrievelist', 'repository_remotemoodle'));
121         }
122     }
124     /**
125      * Display the file listing - no login required
126      * @global <type> $SESSION
127      * @param <type> $ajax
128      * @return <type>
129      */
130     public function print_login($ajax = true) {
131         global $SESSION;
132         return $this->get_listing();
133     }
135     /**
136      * Display the file listing for the search term
137      * @param <type> $search_text
138      * @return <type>
139      */
140     public function search($search_text) {
141         return $this->get_listing('', '', $search_text);
142     }
144     /**
145      * Retrieve the file listing - file picker function
146      * @global <type> $CFG
147      * @global <type> $DB
148      * @global <type> $USER
149      * @param <type> $encodedpath
150      * @param <type> $search
151      * @return <type>
152      */
153     public function get_listing($encodedpath = '', $page = '', $search = '') {
154         global $CFG, $DB, $USER;
156         ///check that the host has a version >2.0
157         ///for that we check that the host has the getFileList() method implemented
158         ///We also check that this method has been activated (if it is not
159         ///the method will not be returned by the system method system/listMethods)
160         require_once($CFG->dirroot . '/mnet/xmlrpc/client.php');
162         ///check that the peer has been setup
163         if (!array_key_exists('peer',$this->options)) {
164             echo json_encode(array('e'=>get_string('error').' 9010: '.get_string('hostnotfound','repository_remotemoodle')));
165             exit;
166         }
168         $host = $DB->get_record('mnet_host',array('id' => $this->options['peer'])); //need to retrieve the host url
170         ///check that the peer host exists into the database
171         if (empty($host)) {
172            echo json_encode(array('e'=>get_string('error').' 9011: '.get_string('hostnotfound','repository_remotemoodle')));
173            exit;
174         }
176         $mnet_peer = new mnet_peer();
177         $mnet_peer->set_wwwroot($host->wwwroot);
178         $client = new mnet_xmlrpc_client();
179         $client->set_method('system/listMethods');
180         $client->send($mnet_peer);
181         $services = $client->response;
182         if (array_search('repository/remotemoodle/repository.class.php/getFileList', $services) === false) {
183             echo json_encode(array('e'=>get_string('connectionfailure','repository_remotemoodle')));
184             exit;
185         }
187         ///connect to the remote moodle and retrieve the list of files
188         $client->set_method('repository/remotemoodle/repository.class.php/getFileList');
189         $client->add_param($USER->username);
190         $client->add_param($search);
192         ///call the method and manage host error
193         if (!$client->send($mnet_peer)) {
194             $message =" ";
195             foreach ($client->error as $errormessage) {
196                 $message .= "ERROR: $errormessage . ";
197             }
198             echo json_encode(array('e'=>$message)); //display all error messages
199             exit;
200         }
202         $services = $client->response;
203         ///display error message if we could retrieve the list or if nothing were returned
204         if (empty($services)) {
205             echo json_encode(array('e'=>get_string('failtoretrievelist','repository_remotemoodle')));
206             exit;
207         }
209         return $services;
210     }
214     /**
215      * Download a file
216      * @global object $CFG
217      * @param string $url the url of file
218      * @param string $file save location
219      * @return string the location of the file
220      * @see curl package
221      */
222     public function get_file($url, $file = '') {
223         global $CFG, $DB, $USER;
225         ///set mnet environment and set the mnet host
226         require_once($CFG->dirroot . '/mnet/xmlrpc/client.php');
227         $host = $DB->get_record('mnet_host',array('id' => $this->options['peer'])); //retrieve the host url
228         $mnet_peer = new mnet_peer();
229         $mnet_peer->set_wwwroot($host->wwwroot);
231         ///create the client and set the method to call
232         $client = new mnet_xmlrpc_client();
233         $client->set_method('repository/remotemoodle/repository.class.php/retrieveFile');
234         $client->add_param($USER->username);
235         $client->add_param($url);
237         ///call the method and manage host error
238         if (!$client->send($mnet_peer)) {
239             $message =" ";
240             foreach ($client->error as $errormessage) {
241                 $message .= "ERROR: $errormessage . ";
242             }
243             echo json_encode(array('e'=>$message));
244             exit;
245         }
247         $services = $client->response; //service contains the file content in the first case of the array,
248                                        //and the filename in the second
250         //the content has been encoded in base64, need to decode it
251         $content = base64_decode($services[0]);
252         $file = $services[1]; //filename
254         ///create a temporary folder with a file
255         $path = $this->prepare_file($file);
256         ///fill the file with the content
257         $fp = fopen($path, 'w');
258         fwrite($fp,$content);
259         fclose($fp);
261         return $path;
263     }
265     /**
266      * Add Instance settings input to Moodle form
267      * @global <type> $CFG
268      * @global <type> $DB
269      * @param <type> $
270      */
271     public function instance_config_form($mform) {
272         global $CFG, $DB;
274         //retrieve only Moodle peers
275         $hosts = $DB->get_records_sql('  SELECT
276                                     h.id,
277                                     h.wwwroot,
278                                     h.ip_address,
279                                     h.name,
280                                     h.public_key,
281                                     h.public_key_expires,
282                                     h.transport,
283                                     h.portno,
284                                     h.last_connect_time,
285                                     h.last_log_id,
286                                     h.applicationid,
287                                     a.name as app_name,
288                                     a.display_name as app_display_name,
289                                     a.xmlrpc_server_url
290                                 FROM {mnet_host} h
291                                     JOIN {mnet_application} a ON h.applicationid=a.id
292                                 WHERE
293                                     h.id <> ? AND
294                                     h.deleted = 0 AND
295                                     a.name = ? AND
296                                     h.name <> ?',
297                         array($CFG->mnet_localhost_id, 'moodle', 'All Hosts'));
298         $peers = array();
299         foreach($hosts as $host) {
300             $peers[$host->id] = $host->name;
301         }
304         $mform->addElement('select', 'peer', get_string('peer', 'repository_remotemoodle'),$peers);
305         $mform->addRule('peer', get_string('required'), 'required', null, 'client');
307         if (empty($peers)) {
308             $mform->addElement('static', null, '',  get_string('nopeer','repository_remotemoodle'));
309         }
310     }
312     /**
313      * Names of the instance settings
314      * @return <type>
315      */
316     public static function get_instance_option_names() {
317         ///the administrator just need to set a peer
318         return array('peer');
319     }
320     public function supported_returntypes() {
321         return FILE_INTERNAL;
322     }