feb63827a21b37e01a4b1fb1a33018b606a6bc7b
[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('../config.php');
54 require_once('../lib/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->name         = 'repository_base';
74         $this->context      = $context;
75         $this->repositoryid = $repositoryid;
76         $this->options      = array();
77         if (is_array($options)) {
78             foreach ($options as $n => $v) {
79                 $this->options[$n] = $v;
80             }
81         }
82     }
84     public function __set($name, $value) {
85         $this->options[$name] = $value;
86     }
88     public function __get($name) {
89         if (array_key_exists($name, $this->options)){
90             return $this->options[$name];
91         }
92         trigger_error('Undefined property: '.$name, E_USER_NOTICE);
93         return null;
94     }
96     public function __isset($name) {
97         return isset($this->options[$name]);
98     }
100     public function __toString() {
101         return 'Repository class: '.__CLASS__;
102     }
103     /**
104      * Given a URL, get a file from there.
105      * @param string $url the url of file
106      * @param string $file save location
107      */
108     public function get_file($url, $file = '') {
109         global $CFG;
110         if (!file_exists($CFG->dataroot.'/repository/download')) {
111             mkdir($CFG->dataroot.'/repository/download/', 0777, true);
112         }
113         if(is_dir($CFG->dataroot.'/repository/download')) {
114             $dir = $CFG->dataroot.'/repository/download/';
115         }
116         if(empty($file)) {
117             $file = uniqid('repo').'_'.time().'.tmp';
118         }
119         if(file_exists($dir.$file)){
120             $file = uniqid('m').$file;
121         }
122         $fp = fopen($dir.$file, 'w');
123         $c = new curl;
124         $c->download(array(
125             array('url'=>$url, 'file'=>$fp)
126         ));
127         return $dir.$file;
128     }
130     /**
131      * Given a path, and perhaps a search, get a list of files.
132      *
133      * @param string $parent The parent path, this parameter can
134      * a folder name, or a identification of folder
135      * @param string $search The text will be searched.
136      * @return array the list of files, including meta infomation
137      */
138     abstract public function get_listing($parent = '/', $search = '');
140     /**
141      * Print a list or return string
142      *
143      * @param string $list
144      * $list = array(
145      *            array('name'=>'moodle.txt', 'size'=>12, 'path'=>'', 'date'=>''),
146      *            array('name'=>'repository.txt', 'size'=>32, 'path'=>'', 'date'=>''),
147      *            array('name'=>'forum.txt', 'size'=>82, 'path'=>'', 'date'=>''),
148      *         );
149      *
150      * @param boolean $print if printing the listing directly
151      *
152      */
153     public function print_listing($listing = array(), $print=true) {
154         if(empty($listing)){
155             $listing = $this->get_listing();
156         }
157         if (empty($listing)) {
158             $str = '';
159         } else {
160             $count = 0;
161             $str = '<table>';
162             foreach ($listing as $v){
163                 $str .= '<tr id="entry_'.$count.'">';
164                 $str .= '<td><input type="checkbox" /></td>';
165                 $str .= '<td>'.$v['name'].'</td>';
166                 $str .= '<td>'.$v['size'].'</td>';
167                 $str .= '<td>'.$v['date'].'</td>';
168                 $str .= '</tr>';
169                 $count++;
170             }
171             $str .= '</table>';
172         }
173         if ($print){
174             echo $str;
175             return null;
176         } else {
177             return $str;
178         }
179     }
181     /**
182      * Show the login screen, if required
183      * This is an abstract function, it must be overriden.
184      * The specific plug-in need to specify authentication types in database
185      * options field
186      * Imagine following cases:
187      * 1. no need of authentication
188      * 2. Use username and password to authenticate
189      * 3. Redirect to authentication page, in this case, the repository
190      * will callback moodle with following common parameters:
191      *    (1) boolean callback To tell moodle this is a callback
192      *    (2) int     id       Specify repository ID
193      * The callback page need to use these parameters to init
194      * the repository plug-ins correctly. Also, auth_token or ticket may
195      * attach in the callback url, these must be taken into account too.
196      *
197      */
198     abstract public function print_login();
200     /**
201      * Show the search screen, if required
202      *
203      * @return null
204      */
205     abstract public function print_search();
207     /**
208      * Cache login details for repositories
209      *
210      * @param string $username
211      * @param string $password
212      * @param string $userid The id of specific user
213      * @return array the list of files, including meta infomation
214      */
215     public function store_login($username = '', $password = '', $userid = -1, $contextid = SITEID) {
216         global $DB;
218         $repository = new stdclass;
219         $repository->userid         = $userid;
220         $repository->repositorytype = $this->name;
221         $repository->contextid      = $contextid;
222         if ($entry = $DB->get_record('repository', $repository)) {
223             $repository->id = $entry->id;
224             $repository->username = $username;
225             $repository->password = $password;
226             return $DB->update_record('repository', $repository);
227         } else {
228             $repository->username = $username;
229             $repository->password = $password;
230             return $DB->insert_record('repository', $repository);
231         }
232         return false;
233     }
235     /**
236      * Defines operations that happen occasionally on cron
237      *
238      */
239     public function cron() {
240         return true;
241     }
244 /**
245  * exception class for repository api
246  *
247  */
249 class repository_exception extends moodle_exception {
252 /**
253  * Listing object describing a listing of files and directories
254  */
256 abstract class repository_listing {
259 function repository_set_option($id, $position, $config = array()){
260     global $DB;
261     $repository = new stdclass;
262     $position = (int)$position;
263     $config   = serialize($config);
264     if( $position < 1 || $position > 5){
265         print_error('invalidoption', 'repository', '', $position);
266     }
267     if ($entry = $DB->get_record('repository', array('id'=>$id))) {
268         $option = 'option'.$position;
269         $repository->id = $entry->id;
270         $repository->$option = $config;
271         return $DB->update_record('repository', $repository);
272     }
273     return false;
275 function repository_get_option($id, $position){
276     global $DB;
277     $entry = $DB->get_record('repository', array('id'=>$id));
278     $option = 'option'.$position;
279     $ret = (array)unserialize($entry->$option);
280     return $ret;
282 function repository_instances(){
283     global $DB, $CFG, $USER;
284     $contextid = 0;
285     $params = array();
286     $sql = 'SELECT * FROM {repository} r WHERE ';
287     $sql .= ' (r.userid = 0 or r.userid = ?) ';
288     $params[] = $USER->id;
289     if($contextid == SITEID) {
290         $sql .= 'AND (r.contextid = ?)';
291         $params[] = SITEID;
292     } else {
293         $sql .= 'AND (r.contextid = ? or r.contextid = ?)';
294         $params[] = SITEID;
295         $params[] = $contextid;
296     }
297     if(!$repos = $DB->get_records_sql($sql, $params)) {
298         $repos = array();
299     }
300     return $repos;
302 function repository_get_plugins(){
303     global $CFG;
304     $repo = $CFG->dirroot.'/repository/';
305     $ret = array();
306     if($dir = opendir($repo)){
307         while (false !== ($file = readdir($dir))) {
308             if(is_dir($file) && $file != '.' && $file != '..'
309                 && file_exists($repo.$file.'/repository.class.php')){
310                 require_once($repo.$file.'/version.php');
311                 $ret[] = array('name'=>$plugin->name,
312                         'version'=>$plugin->version,
313                         'path'=>$repo.$file,
314                         'settings'=>file_exists($repo.$file.'/settings.php'));
315             }
316         }
317     }
318     return $ret;