"MDL-13766, repository settings page"
[moodle.git] / repository / lib.php
1 <?php // $Id$
3 ///////////////////////////////////////////////////////////////////////////
4 //                                                                       //
5 // NOTICE OF COPYRIGHT                                                   //
6 //                                                                       //
7 // Moodle - Modular Object-Oriented Dynamic Learning Environment         //
8 //          http://moodle.com                                            //
9 //                                                                       //
10 // Copyright (C) 2008 onwards  Moodle Pty Ltd   http://moodle.com        //
11 //                                                                       //
12 // This program is free software; you can redistribute it and/or modify  //
13 // it under the terms of the GNU General Public License as published by  //
14 // the Free Software Foundation; either version 2 of the License, or     //
15 // (at your option) any later version.                                   //
16 //                                                                       //
17 // This program is distributed in the hope that it will be useful,       //
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of        //
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
20 // GNU General Public License for more details:                          //
21 //                                                                       //
22 //          http://www.gnu.org/copyleft/gpl.html                         //
23 //                                                                       //
24 ///////////////////////////////////////////////////////////////////////////
26 /**
27  * This is the base class of the repository class
28  *
29  * To use repository plugin, you need to create a new folder under repository/, named as the remote
30  * repository, the subclass must be defined in  the name
32  *
33  * class repository is an abstract class, some functions must be implemented in subclass.
34  *
35  * See an example of use of this library in repository/box/repository.class.php
36  *
37  * A few notes :
38  *   // options are stored as serialized format in database
39  *   $options = array('api_key'=>'dmls97d8j3i9tn7av8y71m9eb55vrtj4',
40  *                  'auth_token'=>'', 'path_root'=>'/');
41  *   $repo    = new repository_xxx($options);
42  *   // print login page or a link to redirect to another page
43  *   $repo->print_login();
44  *   // call get_listing, and print result
45  *   $repo->print_listing();
46  *   // print a search box
47  *   $repo->print_search();
48  *
49  * @version 1.0 dev
50  * @package repository
51  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
52  */
53 require_once(dirname(dirname(__FILE__)) . '/config.php');
54 require_once($CFG->libdir.'/filelib.php');
56 abstract class repository {
57     protected $options;
58     public    $name;
59     public    $context;
60     public    $repositoryid;
61     public    $listing;
63     /**
64      * Take an array as a parameter, which contains necessary information
65      * of repository.
66      *
67      * @param string $parent The parent path, this parameter must
68      * not be the folder name, it may be a identification of folder
69      * @param string $search The text will be searched.
70      * @return array the list of files, including meta infomation
71      */
72     public function __construct($repositoryid, $context = SITEID, $options = array()){
73         $this->context      = $context;
74         $this->repositoryid = $repositoryid;
75         $this->options      = array();
76         if (is_array($options)) {
77             foreach ($options as $n => $v) {
78                 $this->options[$n] = $v;
79             }
80         }
81     }
83     public function __set($name, $value) {
84         $this->options[$name] = $value;
85     }
87     public function __get($name) {
88         if (array_key_exists($name, $this->options)){
89             return $this->options[$name];
90         }
91         trigger_error('Undefined property: '.$name, E_USER_NOTICE);
92         return null;
93     }
95     public function __isset($name) {
96         return isset($this->options[$name]);
97     }
99     public function __toString() {
100         return 'Repository class: '.__CLASS__;
101     }
102     /**
103      * Given a URL, get a file from there.
104      * @param string $url the url of file
105      * @param string $file save location
106      */
107     public function get_file($url, $file = '') {
108         global $CFG;
109         if (!file_exists($CFG->dataroot.'/repository/download')) {
110             mkdir($CFG->dataroot.'/repository/download/', 0777, true);
111         }
112         if(is_dir($CFG->dataroot.'/repository/download')) {
113             $dir = $CFG->dataroot.'/repository/download/';
114         }
115         if(empty($file)) {
116             $file = uniqid('repo').'_'.time().'.tmp';
117         }
118         if(file_exists($dir.$file)){
119             $file = uniqid('m').$file;
120         }
121         $fp = fopen($dir.$file, 'w');
122         $c = new curl;
123         $c->download(array(
124             array('url'=>$url, 'file'=>$fp)
125         ));
126         return $dir.$file;
127     }
129     /**
130      * Given a path, and perhaps a search, get a list of files.
131      *
132      * @param string $parent The parent path, this parameter can
133      * a folder name, or a identification of folder
134      * @param string $search The text will be searched.
135      * @return array the list of files, including meta infomation
136      */
137     abstract public function get_listing($parent = '/', $search = '');
139     /**
140      * Print a list or return string
141      *
142      * @param string $list
143      * $list = array(
144      *            array('name'=>'moodle.txt', 'size'=>12, 'path'=>'', 'date'=>''),
145      *            array('name'=>'repository.txt', 'size'=>32, 'path'=>'', 'date'=>''),
146      *            array('name'=>'forum.txt', 'size'=>82, 'path'=>'', 'date'=>''),
147      *         );
148      *
149      * @param boolean $print if printing the listing directly
150      *
151      */
152     public function print_listing($listing = array(), $print=true) {
153         if(empty($listing)){
154             $listing = $this->get_listing();
155         }
156         if (empty($listing)) {
157             $str = '';
158         } else {
159             $count = 0;
160             $str = '<table>';
161             foreach ($listing as $v){
162                 $str .= '<tr id="entry_'.$count.'">';
163                 $str .= '<td><input type="checkbox" /></td>';
164                 $str .= '<td>'.$v['name'].'</td>';
165                 $str .= '<td>'.$v['size'].'</td>';
166                 $str .= '<td>'.$v['date'].'</td>';
167                 $str .= '</tr>';
168                 $count++;
169             }
170             $str .= '</table>';
171         }
172         if ($print){
173             echo $str;
174             return null;
175         } else {
176             return $str;
177         }
178     }
180     /**
181      * Show the login screen, if required
182      * This is an abstract function, it must be overriden.
183      * The specific plug-in need to specify authentication types in database
184      * options field
185      * Imagine following cases:
186      * 1. no need of authentication
187      * 2. Use username and password to authenticate
188      * 3. Redirect to authentication page, in this case, the repository
189      * will callback moodle with following common parameters:
190      *    (1) boolean callback To tell moodle this is a callback
191      *    (2) int     id       Specify repository ID
192      * The callback page need to use these parameters to init
193      * the repository plug-ins correctly. Also, auth_token or ticket may
194      * attach in the callback url, these must be taken into account too.
195      *
196      */
197     abstract public function print_login();
199     /**
200      * Show the search screen, if required
201      *
202      * @return null
203      */
204     abstract public function print_search();
206     /**
207      * Cache login details for repositories
208      *
209      * @param string $username
210      * @param string $password
211      * @param string $userid The id of specific user
212      * @return array the list of files, including meta infomation
213      */
214     public function store_login($username = '', $password = '', $userid = 1, $contextid = SITEID) {
215         global $DB;
217         $repository = new stdclass;
218         if (!empty($this->repositoryid)) {
219             $repository->id = $this->repositoryid;
220         } else {
221             $repository->userid         = $userid;
222             $repository->repositorytype = $this->type;
223             $repository->contextid      = $contextid;
224         }
225         if ($entry = $DB->get_record('repository', $repository)) {
226             $repository->id = $entry->id;
227             $repository->username = $username;
228             $repository->password = $password;
229             return $DB->update_record('repository', $repository);
230         } else {
231             $repository->username = $username;
232             $repository->password = $password;
233             return $DB->insert_record('repository', $repository);
234         }
235         return false;
236     }
238     /**
239      * Defines operations that happen occasionally on cron
240      *
241      */
242     public function cron() {
243         return true;
244     }
247 /**
248  * exception class for repository api
249  *
250  */
252 class repository_exception extends moodle_exception {
255 /**
256  * Listing object describing a listing of files and directories
257  */
259 abstract class repository_listing {
262 function repository_set_option($id, $position, $config = array()){
263     global $DB;
264     $repository = new stdclass;
265     $position = (int)$position;
266     $config   = serialize($config);
267     if( $position < 1 || $position > 5){
268         print_error('invalidoption', 'repository', '', $position);
269     }
270     if ($entry = $DB->get_record('repository', array('id'=>$id))) {
271         $option = 'option'.$position;
272         $repository->id = $entry->id;
273         $repository->$option = $config;
274         return $DB->update_record('repository', $repository);
275     }
276     return false;
278 function repository_get_option($id, $position){
279     global $DB;
280     $entry = $DB->get_record('repository', array('id'=>$id));
281     $option = 'option'.$position;
282     $ret = (array)unserialize($entry->$option);
283     return $ret;
285 function repository_instances(){
286     global $DB, $CFG, $USER;
287     $contextid = 0;
288     $params = array();
289     $sql = 'SELECT * FROM {repository} r WHERE ';
290     $sql .= ' (r.userid = 0 or r.userid = ?) ';
291     $params[] = $USER->id;
292     if($contextid == SITEID) {
293         $sql .= 'AND (r.contextid = ?)';
294         $params[] = SITEID;
295     } else {
296         $sql .= 'AND (r.contextid = ? or r.contextid = ?)';
297         $params[] = SITEID;
298         $params[] = $contextid;
299     }
300     if(!$repos = $DB->get_records_sql($sql, $params)) {
301         $repos = array();
302     }
303     return $repos;
305 function repository_instance($id){
306     global $DB, $CFG;
308     if (!$instance = $DB->get_record('repository', array('id' => $id))) {
309         return false;
310     }
311     require_once($CFG->dirroot . '/repository/'. $instance->repositorytype 
312         . '/repository.class.php');
313     $classname = 'repository_' . $instance->repositorytype;
314     return new $classname($instance->id, $instance->contextid);
316 function repository_get_plugins(){
317     global $CFG;
318     $repo = $CFG->dirroot.'/repository/';
319     $ret = array();
320     if($dir = opendir($repo)){
321         while (false !== ($file = readdir($dir))) {
322             if(is_dir($file) && $file != '.' && $file != '..'
323                 && file_exists($repo.$file.'/repository.class.php')){
324                 require_once($repo.$file.'/version.php');
325                 $ret[] = array('name'=>$plugin->name,
326                         'version'=>$plugin->version,
327                         'path'=>$repo.$file,
328                         'settings'=>file_exists($repo.$file.'/settings.php'));
329             }
330         }
331     }
332     return $ret;