2c1cbf99a8fe652873ddcff75f2e9799bf1c2c5f
[moodle.git] / repository / lib.php
1 <?php
2  // $Id$
4 ///////////////////////////////////////////////////////////////////////////
5 //                                                                       //
6 // NOTICE OF COPYRIGHT                                                   //
7 //                                                                       //
8 // Moodle - Modular Object-Oriented Dynamic Learning Environment         //
9 //          http://moodle.com                                            //
10 //                                                                       //
11 // Copyright (C) 2008 onwards  Moodle Pty Ltd   http://moodle.com        //
12 //                                                                       //
13 // This program is free software; you can redistribute it and/or modify  //
14 // it under the terms of the GNU General Public License as published by  //
15 // the Free Software Foundation; either version 2 of the License, or     //
16 // (at your option) any later version.                                   //
17 //                                                                       //
18 // This program is distributed in the hope that it will be useful,       //
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of        //
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
21 // GNU General Public License for more details:                          //
22 //                                                                       //
23 //          http://www.gnu.org/copyleft/gpl.html                         //
24 //                                                                       //
25 ///////////////////////////////////////////////////////////////////////////
27 /**
28  * About repository/lib.php:
29  * two main classes:
30  * 1. repository_type => a repository plugin, You can activate a plugin into
31  * Moodle. You also can set some general settings/options for this type of repository.
32  * All instances would share the same options (for example: a API key for the connection
33  * to the repository)
34  * 2. repository => an instance of a plugin. You can also call it an access or
35  * an account. An instance has specific settings (for example: a public url) and a specific
36  * name. That's this name which is displayed in the file picker.
37  */
41 /**
42  * This is the base class of the repository class
43  *
44  * To use repository plugin, you need to create a new folder under repository/, named as the remote
45  * repository, the subclass must be defined in  the name
47  *
48  * class repository is an abstract class, some functions must be implemented in subclass.
49  *
50  * See an example of use of this library in repository/boxnet/repository.class.php
51  *
52  * A few notes:
53  *   // print login page or a link to redirect to another page
54  *   $repo->print_login();
55  *   // call get_listing, and print result
56  *   $repo->print_listing();
57  *   // print a search box
58  *   $repo->print_search();
59  *
60  * @version 1.0 dev
61  * @package repository
62  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
63  */
64 require_once(dirname(dirname(__FILE__)) . '/config.php');
65 require_once(dirname(dirname(__FILE__)).'/lib/filelib.php');
66 require_once(dirname(dirname(__FILE__)).'/lib/formslib.php');
68 /**
69  * A repository_type is a repository plug-in. It can be Box.net, Flick-r, ...
70  * A repository type can be edited, sorted and hidden. It is mandatory for an
71  * administrator to create a repository type in order to be able to create
72  * some instances of this type.
73  *
74  * Coding note:
75  * - a repository_type object is mapped to the "repository" database table
76  * - "typename" attibut maps the "type" database field. It is unique.
77  * - general "options" for a repository type are saved in the config_plugin table
78  * - when you delete a repository, all instances are deleted, and general
79  *   options are also deleted from database
80  * - When you create a type for a plugin that can't have multiple instances, a
81  *   instance is automatically created.
82  */
83 class repository_type {
86     /**
87      * Type name (no whitespace) - A type name is unique
88      * Note: for a user-friendly type name see get_readablename()
89      * @var String
90      */
91     private $_typename;
94     /**
95      * Options of this type
96      * They are general options that any instance of this type would share
97      * e.g. API key
98      * These options are saved in config_plugin table
99      * @var array
100      */
101    private $_options;
104     /**
105      * Is the repository type visible or hidden
106      * If false (hidden): no instances can be created, edited, deleted, showned , used...
107      * @var boolean
108      */
109    private $_visible;
112     /**
113      * 0 => not ordered, 1 => first position, 2 => second position...
114      * A not order type would appear in first position (should never happened)
115      * @var integer
116      */
117     private $_sortorder;
119     /**
120      * repository_type constructor
121      * @global <type> $CFG
122      * @param integer $typename
123      * @param array $typeoptions
124      * @param boolean $visible
125      * @param integer $sortorder (don't really need set, it will be during create() call)
126      */
127     public function __construct($typename = '', $typeoptions = array(), $visible = false, $sortorder = 0){
128         global $CFG;
130         //set type attributs
131         $this->_typename = $typename;
132         $this->_visible = $visible;
133         $this->_sortorder = $sortorder;
135         //set options attribut
136         $this->_options = array();
137         //check that the type can be setup
138         if (repository_static_function($typename,"has_admin_config")){
139             $options = repository_static_function($typename,'get_admin_option_names');
140             //set the type options
141             foreach ($options as $config) {
142                 if (array_key_exists($config,$typeoptions)){
143                         $this->_options[$config] = $typeoptions[$config];
144                 }
145             }
146         }
147     }
149     /**
150      * Get the type name (no whitespace)
151      * For a human readable name, use get_readablename()
152      * @return String the type name
153      */
154     public function get_typename(){
155         return $this->_typename;
156     }
158     /**
159      * Return a human readable and user-friendly type name
160      * @return string user-friendly type name
161      */
162     public function get_readablename(){
163         return get_string('repositoryname','repository_'.$this->_typename);
164     }
166     /**
167      * Return general options
168      * @return array the general options
169      */
170     public function get_options(){
171         return $this->_options;
172     }
174     /**
175      * Return visibility
176      * @return boolean
177      */
178     public function get_visible(){
179         return $this->_visible;
180     }
182     /**
183      * Return order / position of display in the file picker
184      * @return integer
185      */
186     public function get_sortorder(){
187         return $this->_sortorder;
188     }
190     /**
191      * Create a repository type (the type name must not already exist)
192      * @global object $DB
193      */
194     public function create(){
195         global $DB;
197         //check that $type has been set
198         $timmedtype = trim($this->_typename);
199         if (empty($timmedtype)) {
200              throw new repository_exception('emptytype', 'repository');
201         }
203         //set sortorder as the last position in the list
204         if (!isset($this->_sortorder) || $this->_sortorder == 0 ){
205             $sql = "SELECT MAX(sortorder) FROM {repository}";
206             $this->_sortorder = 1 + $DB->get_field_sql($sql);
207         }
209         //only create a new type if it doesn't already exist
210         $existingtype = $DB->get_record('repository', array('type'=>$this->_typename));
211         if(!$existingtype){
212            //create the type
213            $newtype = new stdclass;
214            $newtype->type = $this->_typename;
215            $newtype->visible = $this->_visible;
216            $newtype->sortorder = $this->_sortorder;
217            $DB->insert_record('repository', $newtype);
219            //save the options in DB
220            $this->update_options();
222            //if the plugin type has no multiple and no instance config so it wont
223            //be possible for the administrator to create a instance
224            //in this case we need to create an instance
225            if (!repository_static_function($this->_typename,"has_instance_config")
226            && !repository_static_function($this->_typename,"has_multiple_instances")){
227               $instanceoptions = array();
228               $instanceoptions['name'] = $this->_typename;
229               repository_static_function($this->_typename, 'create', $this->_typename, 0, get_system_context(), $instanceoptions);
230            }
231         }
232         else {
233             throw new repository_exception('existingrepository', 'repository');
234         }
235     }
238     /**
239      * Update plugin options into the config_plugin table
240      * @param array $options
241      * @return boolean
242      */
243     public function update_options($options = null){
244         if (!empty($options)){
245             $this->_options = $options;
246         }
248         foreach ($this->_options as $name => $value) {
249             set_config($name,$value,$this->_typename);
250         }
252         return true;
253     }
255     /**
256      * Update visible database field with the value given as parameter
257      * or with the visible value of this object
258      * This function is private.
259      * For public access, have a look to switch_and_update_visibility()
260      * @global object $DB
261      * @param boolean $visible
262      * @return boolean
263      */
264     private function update_visible($visible = null){
265         global $DB;
267         if (!empty($visible)){
268             $this->_visible = $visible;
269         }
270         else if (!isset($this->_visible)){
271             throw new repository_exception('updateemptyvisible', 'repository');
272         }
274         return $DB->set_field('repository', 'visible', $this->_visible, array('type'=>$this->_typename));
275     }
277     /**
278      * Update database sortorder field with the value given as parameter
279      * or with the sortorder value of this object
280      * This function is private.
281      * For public access, have a look to move_order()
282      * @global object $DB
283      * @param integer $sortorder
284      * @return boolean
285      */
286     private function update_sortorder($sortorder = null){
287         global $DB;
289         if (!empty($sortorder) && $sortorder!=0){
290             $this->_sortorder = $sortorder;
291         }
292         //if sortorder is not set, we set it as the ;ast position in the list
293         else if (!isset($this->_sortorder) || $this->_sortorder == 0 ){
294             $sql = "SELECT MAX(sortorder) FROM {repository}";
295             $this->_sortorder = 1 + $DB->get_field_sql($sql);
296         }
298         return $DB->set_field('repository', 'sortorder', $this->_sortorder, array('type'=>$this->_typename));
299     }
301     /**
302      * Change order of the type with its adjacent upper or downer type
303      * (database fields are updated)
304      * Algorithm details:
305      * 1. retrieve all types in an array. This array is sorted by sortorder,
306      * and the array keys start from 0 to X (incremented by 1)
307      * 2. switch sortorder values of this type and its adjacent type
308      * @global object $DB
309      * @param string $move "up" or "down"
310      */
311     public function move_order($move) {
312         global $DB;
313         //retrieve all types
314         $types = repository_get_types();
316         //retrieve this type into the returned array
317          $i = 0;
318         while (!isset($indice) && $i<count($types)){
319             if ($types[$i]->get_typename() == $this->_typename){
320                 $indice = $i;
321             }
322             $i++;
323         }
325         //retrieve adjacent indice
326         switch ($move) {
327             case "up":
328                 $adjacentindice = $indice - 1;
329                 break;
330             case "down":
331                 $adjacentindice = $indice + 1;
332                 break;
333             default:
334                 throw new repository_exception('movenotdefined', 'repository');
335         }
337         //switch sortorder of this type and the adjacent type
338         //TODO: we could reset sortorder for all types. This is not as good in performance term, but
339         //that prevent from wrong behaviour on a screwed database. As performance are not important in this particular case
340         //it worth to change the algo.
341         if ($adjacentindice>=0 && !empty($types[$adjacentindice])){
342             $DB->set_field('repository', 'sortorder', $this->_sortorder, array('type'=>$types[$adjacentindice]->get_typename()));
343             $this->update_sortorder($types[$adjacentindice]->get_sortorder());
344         }
345     }
347     /**
348      * 1. Switch the visibility OFF if it's ON, and ON if it's OFF.
349      * 2. Update the type
350      * @return <type>
351      */
352     public function switch_and_update_visibility(){
353         $this->_visible = !$this->_visible;
354         return $this->update_visible();
355     }
358     /**
359      * Delete a repository_type (general options are removed from config_plugin
360      * table, and all instances are deleted)
361      * @global object $DB
362      * @return boolean
363      */
364     public function delete(){
365         global $DB;
367         //delete all instances of this type
368         $instances = repository_get_instances(array(),null,false,$this->_typename);
369         foreach($instances as $instance){
370             $instance->delete();
371         }
373         //delete all general options
374         foreach ($this->_options as $name => $value){
375             set_config($name, null, $this->_typename);
376         }
378         return $DB->delete_records('repository', array('type' => $this->_typename));
379     }
382 /**
383  * Return a type for a given type name.
384  * @global object $DB
385  * @param string $typename the type name
386  * @return integer
387  */
388 function repository_get_type_by_typename($typename){
389     global $DB;
391     if(!$record = $DB->get_record('repository',array('type' => $typename))) {
392         return false;
393     }
395     return new repository_type($typename, (array)get_config($typename), $record->visible, $record->sortorder);
398 /**
399  * Return a type for a given type id.
400  * @global object $DB
401  * @param string $typename the type name
402  * @return integer
403  */
404 function repository_get_type_by_id($id){
405     global $DB;
407     if(!$record = $DB->get_record('repository',array('id' => $id))) {
408         return false;
409     }
411     return new repository_type($record->type, (array)get_config($record->type), $record->visible, $record->sortorder);
414 /**
415  * Return all repository types ordered by sortorder
416  * first type in returnedarray[0], second type in returnedarray[1], ...
417  * @global object $DB
418  * @param boolean $visible can return types by visiblity, return all types if null
419  * @return array Repository types
420  */
421 function repository_get_types($visible=null){
422     global $DB;
424     $types = array();
425     $params = null;
426     if (!empty($visible)) {
427         $params = array('visible' => $visible);
428     }
429     if($records = $DB->get_records('repository',$params,'sortorder')) {
430         foreach($records as $type) {
431             $types[] = new repository_type($type->type, (array)get_config($type->type), $type->visible, $type->sortorder);
432         }
433     }
435     return $types;
438 /**
439  * The base class for all repository plugins
440  */
442 abstract class repository {
443     public $id;
444     public $context;
445     public $options;
447     /**
448      * 1. Initialize context and options
449      * 2. Accept necessary parameters
450      *
451      * @param integer $repositoryid
452      * @param integer $contextid
453      * @param array $options
454      */
455     public function __construct($repositoryid, $contextid = SITEID, $options = array()){
456         $this->id = $repositoryid;
457         $this->context = get_context_instance_by_id($contextid);
458         $this->options = array();
459         if (is_array($options)) {
460             $options = array_merge($this->get_option(), $options);
461         } else {
462             $options = $this->get_option();
463         }
464         $this->options = array();
465         foreach ($options as $n => $v) {
466             $this->options[$n] = $v;
467         }
468         $this->name = $this->get_name();
469     }
471     /**
472      * set options for repository instance
473      *
474      * @param string $name
475      * @param mixed $value
476      */
477     public function __set($name, $value) {
478         $this->options[$name] = $value;
479     }
481     /**
482      * get options for repository instance
483      *
484      * @param string $name
485      * @return mixed
486      */
487     public function __get($name) {
488         if (array_key_exists($name, $this->options)){
489             return $this->options[$name];
490         }
491         trigger_error('Undefined property: '.$name, E_USER_NOTICE);
492         return null;
493     }
495     /**
496      * test option name
497      *
498      * @param string name
499      */
500     public function __isset($name) {
501         return isset($this->options[$name]);
502     }
504     /**
505      * Return the name of the repository class
506      * @return <type>
507      */
508     public function __toString() {
509         return 'Repository class: '.__CLASS__;
510     }
512     /**
513      * Download a file, this function can be overridden by
514      * subclass.
515      *
516      * @global object $CFG
517      * @param string $url the url of file
518      * @param string $file save location
519      * @return string the location of the file
520      * @see curl package
521      */
522     public function get_file($url, $file = '') {
523         global $CFG;
524         if (!file_exists($CFG->dataroot.'/temp/download')) {
525             mkdir($CFG->dataroot.'/temp/download/', 0777, true);
526         }
527         if(is_dir($CFG->dataroot.'/temp/download')) {
528             $dir = $CFG->dataroot.'/temp/download/';
529         }
530         if(empty($file)) {
531             $file = uniqid('repo').'_'.time().'.tmp';
532         }
533         if(file_exists($dir.$file)){
534             $file = uniqid('m').$file;
535         }
536         $fp = fopen($dir.$file, 'w');
537         $c = new curl;
538         $c->download(array(
539             array('url'=>$url, 'file'=>$fp)
540         ));
541         return $dir.$file;
542     }
544     /**
545      * Print a list or return formatted string, can be overridden by subclass
546      *
547      * @param string $list
548      * @param boolean $print false, return html, otherwise, print it directly
549      * @return <type>
550      */
551     public function print_listing($listing = array(), $print=true) {
552         if(empty($listing)){
553             $listing = $this->get_listing();
554         }
555         if (empty($listing)) {
556             $str = '';
557         } else {
558             $count = 0;
559             $str = '<table>';
560             foreach ($listing as $v){
561                 $str .= '<tr id="entry_'.$count.'">';
562                 $str .= '<td><input type="checkbox" /></td>';
563                 $str .= '<td>'.$v['name'].'</td>';
564                 $str .= '<td>'.$v['size'].'</td>';
565                 $str .= '<td>'.$v['date'].'</td>';
566                 $str .= '</tr>';
567                 $count++;
568             }
569             $str .= '</table>';
570         }
571         if ($print){
572             echo $str;
573             return null;
574         } else {
575             return $str;
576         }
577     }
579     /**
580      * Return the name of this instance, can be overridden.
581      * @global <type> $DB
582      * @return <type>
583      */
584     public function get_name(){
585         global $DB;
586         // We always verify instance id from database,
587         // so we always know repository name before init
588         // a repository, so we don't enquery repository
589         // name from database again here.
590         if (isset($this->options['name'])) {
591             return $this->options['name'];
592         } else {
593             if ( $repo = $DB->get_record('repository_instances', array('id'=>$this->id)) ) {
594                 return $repo->name;
595             } else {
596                 return '';
597             }
598         }
599     }
601     /**
602      * Provide repository instance information for Ajax
603      * @global object $CFG
604      * @return object
605      */
606     final public function ajax_info() {
607         global $CFG;
608         $repo = new stdclass;
609         $repo->id   = $this->id;
610         $repo->name = $this->get_name();
611         $repo->type = $this->options['type'];
612         $repo->icon = $CFG->httpswwwroot.'/repository/'.$repo->type.'/icon.png';
613         return $repo;
614     }
616     /**
617      * Create an instance for this plug-in
618      * @global object $CFG
619      * @global object $DB
620      * @param string $type the type of the repository
621      * @param integer $userid the user id
622      * @param object $context the context
623      * @param array $params the options for this instance
624      * @return <type>
625      */
626     final public static function create($type, $userid, $context, $params) {
627         global $CFG, $DB;
628         $params = (array)$params;
629         require_once($CFG->dirroot . '/repository/'. $type . '/repository.class.php');
630         $classname = 'repository_' . $type;
631         if ($repo = $DB->get_record('repository', array('type'=>$type))) {
632             $record = new stdclass;
633             $record->name = $params['name'];
634             $record->typeid = $repo->id;
635             $record->timecreated  = time();
636             $record->timemodified = time();
637             $record->contextid = $context->id;
638             $record->userid    = $userid;
639             $id = $DB->insert_record('repository_instances', $record);
640             $options = array();
641             if (call_user_func($classname . '::has_instance_config')) {
642                 $configs = call_user_func($classname . '::get_instance_option_names');
643                 foreach ($configs as $config) {
644                     $options[$config] = $params[$config];
645                 }
646             }
647             if (!empty($id)) {
648                 unset($options['name']);
649                 $instance = repository_get_instance($id);
650                 $instance->set_option($options);
651                 return $id;
652             } else {
653                 return null;
654             }
655         } else {
656             return null;
657         }
658     }
660     /**
661      * delete a repository instance
662      * @global object $DB
663      * @return <type>
664      */
665     final public function delete(){
666         global $DB;
667         $DB->delete_records('repository_instances', array('id'=>$this->id));
668         return true;
669     }
671     /**
672      * Hide/Show a repository
673      * @global object $DB
674      * @param string $hide
675      * @return <type>
676      */
677     final public function hide($hide = 'toggle'){
678         global $DB;
679         if ($entry = $DB->get_record('repository', array('id'=>$this->id))) {
680             if ($hide === 'toggle' ) {
681                 if (!empty($entry->visible)) {
682                     $entry->visible = 0;
683                 } else {
684                     $entry->visible = 1;
685                 }
686             } else {
687                 if (!empty($hide)) {
688                     $entry->visible = 0;
689                 } else {
690                     $entry->visible = 1;
691                 }
692             }
693             return $DB->update_record('repository', $entry);
694         }
695         return false;
696     }
698     /**
699      * Cache login details for repositories
700      * @global object $DB
701      * @param string $username
702      * @param string $password
703      * @param integer $userid The id of specific user
704      * @return integer Id of the record
705      */
706     public function store_login($username = '', $password = '', $userid = 1) {
707         global $DB;
709         $repository = new stdclass;
710         if (!empty($this->id)) {
711             $repository->id = $this->id;
712         } else {
713             $repository->userid         = $userid;
714             $repository->repositorytype = $this->type;
715             $repository->contextid      = $this->context->id;
716         }
717         if ($entry = $DB->get_record('repository', $repository)) {
718             $repository->id = $entry->id;
719             $repository->username = $username;
720             $repository->password = $password;
721             return $DB->update_record('repository', $repository);
722         } else {
723             $repository->username = $username;
724             $repository->password = $password;
725             return $DB->insert_record('repository', $repository);
726         }
727     }
729     /**
730      * Save settings for repository instance
731      * $repo->set_option(array('api_key'=>'f2188bde132', 'name'=>'dongsheng'));
732      * @global object $DB
733      * @param array $options settings
734      * @return int Id of the record
735      */
736     public function set_option($options = array()){
737         global $DB;
738         if (!empty($options['name'])) {
739             $r = new object();
740             $r->id   = $this->id;
741             $r->name = $options['name'];
742             $DB->update_record('repository_instances', $r);
743             unset($options['name']);
744         }
745         foreach ($options as $name=>$value) {
746             if ($id = $DB->get_field('repository_instance_config', 'id', array('name'=>$name, 'instanceid'=>$this->id))) {
747                 if ($value===null) {
748                     return $DB->delete_records('repository_instance_config', array('name'=>$name, 'instanceid'=>$this->id));
749                 } else {
750                     return $DB->set_field('repository_instance_config', 'value', $value, array('id'=>$id));
751                 }
752             } else {
753                 if ($value===null) {
754                     return true;
755                 }
756                 $config = new object();
757                 $config->instanceid = $this->id;
758                 $config->name   = $name;
759                 $config->value  = $value;
760                 return $DB->insert_record('repository_instance_config', $config);
761             }
762         }
763         return true;
764     }
766     /**
767      * Get settings for repository instance
768      * @global object $DB
769      * @param <type> $config
770      * @return array Settings
771      */
772     public function get_option($config = ''){
773         global $DB;
774         $entries = $DB->get_records('repository_instance_config', array('instanceid'=>$this->id));
775         $ret = array();
776         if (empty($entries)) {
777             return $ret;
778         }
779         foreach($entries as $entry){
780             $ret[$entry->name] = $entry->value;
781         }
782         if (!empty($config)) {
783             return $ret[$config];
784         } else {
785             return $ret;
786         }
787     }
789     /**
790      * Given a path, and perhaps a search, get a list of files.
791      *
792      * The format of the returned array must be:
793      * array(
794      *   'path' => (string) path for the current folder
795      *   'dynload' => (bool) use dynamic loading,
796      *   'manage' => (string) link to file manager,
797      *   'nologin' => (bool) requires login,
798      *   'nosearch' => (bool) no search link,
799      *   'upload' => array( // upload manager
800      *     'name' => (string) label of the form element,
801      *     'id' => (string) id of the form element
802      *   ),
803      *   'list' => array(
804      *     array( // file
805      *       'title' => (string) file name,
806      *       'date' => (string) file last modification time, usually userdate(...),
807      *       'size' => (int) file size,
808      *       'thumbnail' => (string) url to thumbnail for the file,
809      *       'source' => plugin-dependent unique path to the file (id, url, path, etc.),
810      *       'url'=> the accessible url of file
811      *     ),
812      *     array( // folder - same as file, but no 'source'.
813      *       'title' => (string) folder name,
814      *       'path' => (string) path to this folder
815      *       'date' => (string) folder last modification time, usually userdate(...),
816      *       'size' => 0,
817      *       'thumbnail' => (string) url to thumbnail for the folder,
818      *       'children' => array( // an empty folder needs to have 'children' defined, but empty.
819      *         // content (files and folders)
820      *       )
821      *     ),
822      *   )
823      * )
824      *
825      * @param string $parent The parent path, this parameter can
826      * a folder name, or a identification of folder
827      * @param string $search The text will be searched.
828      * @return array the list of files, including meta infomation
829      */
830     abstract public function get_listing($parent = '/', $search = '');
833     /**
834      * Show the login screen, if required
835      * This is an abstract function, it must be overriden.
836      */
837     abstract public function print_login();
839     /**
840      * Show the search screen, if required
841      * @return null
842      */
843     abstract public function print_search();
845     /**
846      * is it possible to do glboal search?
847      * @return boolean
848      */
849     public function global_search(){
850         return false;
851     }
853     /**
854      * Defines operations that happen occasionally on cron
855      * @return <type>
856      */
857     public function cron() {
858         return true;
859     }
861     /**
862      * Return true if the plugin type has at least one general option field
863      * By default: false
864      * @return boolean
865      */
866     public static function has_admin_config() {
867         return false;
868     }
870     /**
871      * Return true if a plugin instance has at least one config field
872      * By default: false
873      * @return boolean
874      */
875     public static function has_instance_config() {
876         return false;
877     }
879     /**
880      * Return true if the plugin can have multiple instances
881      * By default: false
882      * @return boolean
883      */
884     public static function has_multiple_instances(){
885         return false;
886     }
888     /**
889      * Return names of the general options
890      * By default: no general option name
891      * @return array
892      */
893     public static function get_admin_option_names(){
894         return array();
895     }
897     /**
898      * Return names of the instance options
899      * By default: no instance option name
900      * @return array
901      */
902     public static function get_instance_option_names(){
903         return array();
904     }
907 /**
908  * exception class for repository api
909  */
910 class repository_exception extends moodle_exception {
913 /**
914  * Check context
915  * @param int $ctx_id
916  * @return boolean
917  */
918 function repository_check_context($ctx_id){
919     global $USER;
920     $context = get_context_instance_by_id($ctx_id);
921     $level = $context->contextlevel;
922     if ($level == CONTEXT_COURSE) {
923         if (!has_capability('moodle/course:view', $context)) {
924             return false;
925         } else {
926             return true;
927         }
928     } elseif ($level == CONTEXT_USER) {
929         $c = get_context_instance(CONTEXT_USER, $USER->id);
930         if ($c->id == $ctx_id) {
931             return true;
932         } else {
933             return false;
934         }
935     } elseif ($level == CONTEXT_SYSTEM) {
936         // it is always ok in system level
937         return true;
938     }
939     return false;
942 /**
943  * Return all types that you a user can create/edit and which are also visible
944  * Note: Mostly used in order to know if at least one editable type has been set
945  * @return array types
946  */
947 function repository_get_editable_types(){
948     $types= repository_get_types(true);
949     $editabletypes = array();
950     foreach ($types as $type){
951          if (repository_static_function($type->get_typename(), 'has_multiple_instances')) {
952             $editabletypes[]=$type;
953         }
954     }
955     return $editabletypes;
958 /**
959  * Return repository instances
960  * @global object $DB
961  * @global object $CFG
962  * @global object $USER
963  * @param object $contexts contexts for which the instances are set
964  * @param integer $userid
965  * @param boolean $onlyvisible if visible == true, return visible instances only,
966  *                otherwise, return all instances
967  * @param string $type a type name to retrieve
968  * @return array repository instances
969  */
970 function repository_get_instances($contexts=array(), $userid = null, $onlyvisible = true, $type=null){
971     global $DB, $CFG, $USER;
972     $params = array();
973     $sql = 'SELECT i.*, r.type AS repositorytype, r.sortorder, r.visible FROM {repository} r, {repository_instances} i WHERE ';
974     $sql .= 'i.typeid = r.id ';
975     if (!empty($userid) && is_numeric($userid)) {
976         $sql .= ' AND (i.userid = 0 or i.userid = ?)';
977         $params[] = $userid;
978     }
979     foreach ($contexts as $context) {
980         if (empty($firstcontext)){
981             $firstcontext = true;
982             $sql .= ' AND ((i.contextid = ?)';
983         } else {
984             $sql .= ' OR (i.contextid = ?)';
985         }
986         $params[] = $context->id;
987     }
988     if ($firstcontext) {
989        $sql .=')';
990     }
992     if($onlyvisible == true) {
993         $sql .= ' AND (r.visible = 1)';
994     }
995     if(isset($type)) {
996         $sql .= ' AND (r.type = ?)';
997         $params[] = $type;
998     }
999     $sql .= ' order by r.sortorder, i.name';
1000     if(!$repos = $DB->get_records_sql($sql, $params)) {
1001         $repos = array();
1002     }
1003     $ret = array();
1004     foreach($repos as $repo) {
1005         require_once($CFG->dirroot . '/repository/'. $repo->repositorytype
1006             . '/repository.class.php');
1007         $options['visible'] = $repo->visible;
1008         $options['name']    = $repo->name;
1009         $options['type']    = $repo->repositorytype;
1010         $options['typeid']  = $repo->typeid;
1011         $classname = 'repository_' . $repo->repositorytype;
1012         $ret[] = new $classname($repo->id, $repo->contextid, $options);
1013     }
1014     return $ret;
1017 /**
1018  * Get single repository instance
1019  * @global object $DB
1020  * @global object $CFG
1021  * @param integer $id repository id
1022  * @return object repository instance
1023  */
1024 function repository_get_instance($id){
1025     global $DB, $CFG;
1026     $sql = 'SELECT i.*, r.type AS repositorytype, r.visible FROM {repository} r, {repository_instances} i WHERE ';
1027     $sql .= 'i.typeid = r.id AND ';
1028     $sql .= 'i.id = '.$id;
1030     if(!$instance = $DB->get_record_sql($sql)) {
1031         return false;
1032     }
1033     require_once($CFG->dirroot . '/repository/'. $instance->repositorytype
1034         . '/repository.class.php');
1035     $classname = 'repository_' . $instance->repositorytype;
1036     $options['typeid'] = $instance->typeid;
1037     $options['type']   = $instance->repositorytype;
1038     $options['name']   = $instance->name;
1039     return new $classname($instance->id, $instance->contextid, $options);
1042 /**
1043  * call a static function
1044  * @global <type> $CFG
1045  * @param <type> $plugin
1046  * @param <type> $function
1047  * @param type $nocallablereturnvalue default value if function not found
1048  *             it's mostly used when you don't want to display an error but
1049  *             return a boolean
1050  * @return <type>
1051  */
1052 function repository_static_function($plugin, $function) {
1053     global $CFG;
1055     //check that the plugin exists
1056     $typedirectory = $CFG->dirroot . '/repository/'. $plugin . '/repository.class.php';
1057         if (!file_exists($typedirectory)) {
1058             throw new repository_exception('invalidplugin', 'repository');
1059     }
1061     $pname = null;
1062     if (is_object($plugin) || is_array($plugin)) {
1063         $plugin = (object)$plugin;
1064         $pname = $plugin->name;
1065     } else {
1066         $pname = $plugin;
1067     }
1069     $args = func_get_args();
1070     if (count($args) <= 2) {
1071         $args = array();
1072     }
1073     else {
1074         array_shift($args);
1075         array_shift($args);
1076     }
1078     require_once($typedirectory);
1079     return call_user_func_array(array('repository_' . $plugin, $function), $args);
1082 /**
1083  * Move file from download folder to file pool using FILE API
1084  * @global object $DB
1085  * @global object $CFG
1086  * @global object $USER
1087  * @param string $path file path in download folder
1088  * @param string $name file name
1089  * @param integer $itemid item id to identify a file in filepool
1090  * @param string $filearea file area
1091  * @return array information of file in file pool
1092  */
1093 function repository_move_to_filepool($path, $name, $itemid, $filearea = 'user_draft') {
1094     global $DB, $CFG, $USER;
1095     $context = get_context_instance(CONTEXT_USER, $USER->id);
1096     $now = time();
1097     $entry = new object();
1098     $entry->filearea  = $filearea;
1099     $entry->contextid = $context->id;
1100     $entry->filename  = $name;
1101     $entry->filepath  = '/'.uniqid().'/';
1102     $entry->timecreated  = $now;
1103     $entry->timemodified = $now;
1104     if(is_numeric($itemid)) {
1105         $entry->itemid = $itemid;
1106     } else {
1107         $entry->itemid = 0;
1108     }
1109     $entry->mimetype     = mimeinfo('type', $path);
1110     $entry->userid       = $USER->id;
1111     $fs = get_file_storage();
1112     $browser = get_file_browser();
1113     if ($file = $fs->create_file_from_pathname($entry, $path)) {
1114         $delete = unlink($path);
1115         $ret = $browser->get_file_info($context, $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename());
1116         if(!empty($ret)){
1117             return array('url'=>$ret->get_url(),'id'=>$file->get_itemid(), 'file'=>$file->get_filename());
1118         } else {
1119             return null;
1120         }
1121     } else {
1122         return null;
1123     }
1126 /**
1127  * Save file to local filesystem pool
1128  * @param string $elname name of element
1129  * @param string $filearea
1130  * @param string $filepath
1131  * @param string $filename - use specified filename, if not specified name of uploaded file used
1132  * @param bool $override override file if exists
1133  * @return mixed stored_file object or false if error; may throw exception if duplicate found
1134  */
1135 function repository_store_to_filepool($elname, $filearea='user_draft', $filepath='/', $filename = '', $override = false) {
1136     global $USER;
1137     if (!isset($_FILES[$elname])) {
1138         return false;
1139     }
1141     if (!$filename) {
1142         $filename = $_FILES[$elname]['name'];
1143     }
1144     $context = get_context_instance(CONTEXT_USER, $USER->id);
1145     $itemid = (int)substr(hexdec(uniqid()), 0, 9)+rand(1,100);
1146     $fs = get_file_storage();
1147     $browser = get_file_browser();
1149     if ($file = $fs->get_file($context->id, $filearea, $itemid, $filepath, $filename)) {
1150         if ($override) {
1151             $file->delete();
1152         } else {
1153             return false;
1154         }
1155     }
1157     $file_record = new object();
1158     $file_record->contextid = $context->id;
1159     $file_record->filearea  = $filearea;
1160     $file_record->itemid    = $itemid;
1161     $file_record->filepath  = $filepath;
1162     $file_record->filename  = $filename;
1163     $file_record->userid    = $USER->id;
1165     $file = $fs->create_file_from_pathname($file_record, $_FILES[$elname]['tmp_name']);
1166     $info = $browser->get_file_info($context, $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename());
1167     $ret = array('url'=>$info->get_url(),'id'=>$itemid, 'file'=>$file->get_filename());
1168     return $ret;
1171 /**
1172  * Return javascript to create file picker to browse repositories
1173  * @global object $CFG
1174  * @global object $USER
1175  * @param object $context the context
1176  * @return array
1177  */
1178 function repository_get_client($context){
1179     global $CFG, $USER;
1180     $suffix = uniqid();
1181     $sesskey = sesskey();
1182     $strsaveas    = get_string('saveas', 'repository').': ';
1183     $stradd  = get_string('add', 'repository');
1184     $strback      = get_string('back', 'repository');
1185     $strcancel    = get_string('cancel');
1186     $strclose     = get_string('close', 'repository');
1187     $strccache    = get_string('cleancache', 'repository');
1188     $strcopying   = get_string('copying', 'repository');
1189     $strdownbtn   = get_string('getfile', 'repository');
1190     $strdownload  = get_string('downloadsucc', 'repository');
1191     $strdate      = get_string('date', 'repository').': ';
1192     $strerror     = get_string('error', 'repository');
1193     $strfilenotnull = get_string('filenotnull', 'repository');
1194     $strrefresh   = get_string('refresh', 'repository');
1195     $strinvalidjson = get_string('invalidjson', 'repository');
1196     $strlistview  = get_string('listview', 'repository');
1197     $strlogout    = get_string('logout', 'repository');
1198     $strloading   = get_string('loading', 'repository');
1199     $strthumbview = get_string('thumbview', 'repository');
1200     $strtitle     = get_string('title', 'repository');
1201     $strmgr       = get_string('manageurl', 'repository');
1202     $strnoenter   = get_string('noenter', 'repository');
1203     $strsave      = get_string('save', 'repository');
1204     $strsaved     = get_string('saved', 'repository');
1205     $strsaving    = get_string('saving', 'repository');
1206     $strsize      = get_string('size', 'repository').': ';
1207     $strsync      = get_string('sync', 'repository');
1208     $strsearch    = get_string('search', 'repository');
1209     $strsearching = get_string('searching', 'repository');
1210     $strsubmit    = get_string('submit', 'repository');
1211     $strpreview   = get_string('preview', 'repository');
1212     $strupload    = get_string('upload', 'repository');
1213     $struploading = get_string('uploading', 'repository');
1214     $css = <<<EOD
1215 <style type="text/css">
1216 #panel-$suffix{padding:0;margin:0; text-align:left;}
1217 #file-picker-$suffix{font-size:12px;}
1218 #file-picker-$suffix strong{background:#FFFFCC}
1219 #file-picker-$suffix a{color: #336699}
1220 #file-picker-$suffix a:hover{background:#003366;color:white}
1221 #repo-viewbar-$suffix{width:300px;float:left}
1222 #search-div-$suffix{float:right}
1223 #repo-tb-$suffix{padding: .8em;background: #FFFFCC;color:white;text-align:center}
1224 </style>
1225 EOD;
1227     if (!isset($CFG->repo_yui_loaded)) {
1228         $css .= <<<EOD
1229 <style type="text/css">
1230 .repo-list{list-style-type:none;padding:0}
1231 .repo-list li{border-bottom:1px dotted gray;margin-bottom: 1em;}
1232 .repo-name{display:block;padding: 3px;margin-bottom: 5px}
1233 .paging{margin:10px 5px; clear:both;}
1234 .paging a{padding: 4px;border: 1px solid #CCC}
1235 .repo-path{margin: 4px;border-bottom: 1px dotted gray;}
1236 .repo-path a{padding: 4px;}
1237 .rename-form{text-align:center}
1238 .rename-form p{margin: 1em;}
1239 .upload-form{margin: 2em 0;text-align:center}
1240 p.upload a{font-size: 14px;background: #ccc;color:white;padding: 5px}
1241 p.upload a:hover {background: grey;color:white}
1242 .file_name{color:green;}
1243 .file_date{color:blue}
1244 .file_size{color:gray}
1245 .grid{width:80px; float:left;text-align:center;}
1246 .grid div{width: 80px; overflow: hidden}
1247 .grid p{margin:0;padding:0;background: #FFFFCC}
1248 .grid .label{height:48px}
1249 .grid span{background: #EEF9EB;color:gray}
1250 </style>
1251 <style type="text/css">
1252 @import "$CFG->httpswwwroot/lib/yui/resize/assets/skins/sam/resize.css";
1253 @import "$CFG->httpswwwroot/lib/yui/container/assets/skins/sam/container.css";
1254 @import "$CFG->httpswwwroot/lib/yui/layout/assets/skins/sam/layout.css";
1255 @import "$CFG->httpswwwroot/lib/yui/button/assets/skins/sam/button.css";
1256 @import "$CFG->httpswwwroot/lib/yui/assets/skins/sam/treeview.css";
1257 </style>
1258 EOD;
1260     $js = <<<EOD
1261 <script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/yahoo-dom-event/yahoo-dom-event.js"></script>
1262 <script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/element/element-beta-min.js"></script>
1263 <script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/treeview/treeview-min.js"></script>
1264 <script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/dragdrop/dragdrop-min.js"></script>
1265 <script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/container/container-min.js"></script>
1266 <script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/resize/resize-beta-min.js"></script>
1267 <script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/layout/layout-beta-min.js"></script>
1268 <script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/connection/connection-min.js"></script>
1269 <script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/json/json-min.js"></script>
1270 <script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/button/button-min.js"></script>
1271 <script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/selector/selector-beta-min.js"></script>
1272 EOD;
1273         $CFG->repo_yui_loaded = true;
1274     } else {
1275         $js = '';
1276     }
1278 $js .= <<<EOD
1279 <script type="text/javascript">
1280 //<![CDATA[
1281 var active_instance = null;
1282 function repository_callback(id){
1283     active_instance.req(id, '', 0);
1285 var repository_client_$suffix = (function() {
1286 // private static field
1287 var dver = '1.0';
1288 // private static methods
1289 function alert_version(){
1290     alert(dver);
1292 function _client(){
1293     // public varible
1294     this.name = 'repository_client_$suffix';
1295     // private varible
1296     var Dom = YAHOO.util.Dom, Event = YAHOO.util.Event, layout = null, resize = null;
1297     var IE_QUIRKS = (YAHOO.env.ua.ie && document.compatMode == "BackCompat");
1298     var IE_SYNC = (YAHOO.env.ua.ie == 6 || (YAHOO.env.ua.ie == 7 && IE_QUIRKS));
1299     var PANEL_BODY_PADDING = (10*2);
1300     var btn_list = {label: '$strlistview', value: 'l', checked: true, onclick: {fn: _client.viewlist}};
1301     var btn_thumb = {label: '$strthumbview', value: 't', onclick: {fn: _client.viewthumb}};
1302     var repo_list = null;
1303     var resize = null;
1304     var panel = new YAHOO.widget.Panel('file-picker-$suffix', {
1305         draggable: true,
1306         close: true,
1307         modal: true,
1308         underlay: 'none',
1309         zindex: 666666,
1310         xy: [50, Dom.getDocumentScrollTop()+20]
1311     });
1312     // construct code section
1313     {
1314         panel.setHeader('$strtitle');
1315         panel.setBody('<div id="layout-$suffix"></div>');
1316         panel.beforeRenderEvent.subscribe(function() {
1317             Event.onAvailable('layout-$suffix', function() {
1318                 layout = new YAHOO.widget.Layout('layout-$suffix', {
1319                     height: 480, width: 630,
1320                     units: [
1321                         {position: 'top', height: 32, resize: false,
1322                         body:'<div class="yui-buttongroup" id="repo-viewbar-$suffix"></div><div id="search-div-$suffix"></div>', gutter: '2'},
1323                         {position: 'left', width: 200, resize: true,
1324                         body:'<ul class="repo-list" id="repo-list-$suffix"></ul>', gutter: '0 5 0 2', minWidth: 150, maxWidth: 300 },
1325                         {position: 'center', body: '<div id="panel-$suffix"></div>',
1326                         scroll: true, gutter: '0 2 0 0' }
1327                     ]
1328                 });
1329                 layout.render();
1330             });
1331         });
1332         resize = new YAHOO.util.Resize('file-picker-$suffix', {
1333             handles: ['br'],
1334             autoRatio: true,
1335             status: true,
1336             minWidth: 380,
1337             minHeight: 400
1338         });
1339         resize.on('resize', function(args) {
1340             var panelHeight = args.height;
1341             var headerHeight = this.header.offsetHeight; // Content + Padding + Border
1342             var bodyHeight = (panelHeight - headerHeight);
1343             var bodyContentHeight = (IE_QUIRKS) ? bodyHeight : bodyHeight - PANEL_BODY_PADDING;
1344             Dom.setStyle(this.body, 'height', bodyContentHeight + 'px');
1345             if (IE_SYNC) {
1346                 this.sizeUnderlay();
1347                 this.syncIframe();
1348             }
1349             layout.set('height', bodyContentHeight);
1350             layout.set('width', (args.width - PANEL_BODY_PADDING));
1351             layout.resize();
1353         }, panel, true);
1354         _client.viewbar = new YAHOO.widget.ButtonGroup({
1355             id: 'btngroup-$suffix',
1356             name: 'buttons',
1357             disabled: true,
1358             container: 'repo-viewbar-$suffix'
1359             });
1360     }
1361     // public method
1362     this.show = function(){
1363         panel.show();
1364     }
1365     this.hide = function(){
1366         panel.hide();
1367     }
1368     this.create_picker = function(){
1369         // display UI
1370         panel.render();
1371         _client.viewbar.addButtons([btn_list, btn_thumb]);
1372         // init repository list
1373         repo_list = new YAHOO.util.Element('repo-list-$suffix');
1374         repo_list.on('contentReady', function(e){
1375             var searchbar = new YAHOO.util.Element('search-div-$suffix');
1376             searchbar.get('element').innerHTML = '<input id="search-input-$suffix" /><button id="search-btn-$suffix">$strsearch</button>';
1377             var searchbtn = new YAHOO.util.Element('search-btn-$suffix');
1378             searchbtn.callback = {
1379                 success: function(o) {
1380                     var panel = new YAHOO.util.Element('panel-$suffix');
1381                     try {
1382                         if(!o.responseText){
1383                             var panel = new YAHOO.util.Element('panel-$suffix');
1384                             panel.get('element').innerHTML = 'no';
1385                             return;
1386                         }
1387                         var json = YAHOO.lang.JSON.parse(o.responseText);
1388                     } catch(e) {
1389                         alert('$strinvalidjson - '+o.responseText);
1390                     }
1391                     _client.ds = {};
1392                     if(!json.list || json.list.length<1){
1393                         var panel = new YAHOO.util.Element('panel-$suffix');
1394                         panel.get('element').innerHTML = 'no';
1395                         return;
1396                     }
1397                     _client.ds.list = json.list;
1398                     if(_client.ds.list) {
1399                         if(_client.viewmode) {
1400                             _client.viewthumb();
1401                         } else {
1402                             _client.viewlist();
1403                         }
1404                         var input_ctl = new YAHOO.util.Element('search-input-$suffix');
1405                         input_ctl.get('element').value='';
1406                     }
1407                 }
1408             }
1409             searchbtn.input_ctl = new YAHOO.util.Element('search-input-$suffix');
1410             searchbtn.on('click', function(e){
1411                 var keyword = this.input_ctl.get('value');
1412                 var params = [];
1413                 params['s'] = keyword;
1414                 params['env']=_client.env;
1415                 params['action']='gsearch';
1416                 params['sesskey']='$sesskey';
1417                 params['ctx_id']=$context->id;
1418                 _client.loading('load');
1419                 var trans = YAHOO.util.Connect.asyncRequest('POST',
1420                     '$CFG->httpswwwroot/repository/ws.php?action=gsearch', this.callback, _client.postdata(params));
1421             });
1422             for(var i=0; i<_client.repos.length; i++) {
1423                 var repo = _client.repos[i];
1424                 var li = document.createElement('li');
1425                 li.id = 'repo-$suffix-'+repo.id;
1426                 var icon = document.createElement('img');
1427                 icon.src = repo.icon;
1428                 icon.width = '16';
1429                 icon.height = '16';
1430                 var link = document.createElement('a');
1431                 link.href = '###';
1432                 link.id = 'repo-call-$suffix-'+repo.id;
1433                 link.appendChild(icon);
1434                 link.className = 'repo-name';
1435                 link.onclick = function(){
1436                     var re = /repo-call-$suffix-(\d+)/i;
1437                     var id = this.id.match(re);
1438                     repository_client_$suffix.req(id[1], '', 0);
1439                 }
1440                 link.innerHTML += ' '+repo.name;
1441                 li.appendChild(link);
1442                 this.appendChild(li);
1443                 repo = null;
1444             }
1445             });
1446     }
1449 // public static varible
1450 _client.repos = [];
1451 _client.repositoryid = 0;
1452 // _client.ds save all data received from server side
1453 _client.ds = null;
1454 _client.viewmode = 0;
1455 _client.viewbar =null;
1457 // public static mehtod
1458 _client.postdata = function(obj) {
1459     var str = '';
1460     for(k in obj) {
1461         if(obj[k] instanceof Array) {
1462             for(i in obj[k]) {
1463                 str += (encodeURIComponent(k) +'[]='+encodeURIComponent(obj[k][i]));
1464                 str += '&';
1465             }
1466         } else {
1467             str += encodeURIComponent(k) +'='+encodeURIComponent(obj[k]);
1468             str += '&';
1469         }
1470     }
1471     return str;
1473 _client.loading = function(type, name){
1474     var panel = new YAHOO.util.Element('panel-$suffix');
1475     panel.get('element').innerHTML = '';
1476     var content = document.createElement('div');
1477     content.style.textAlign='center';
1478     var para = document.createElement('P');
1479     var img = document.createElement('IMG');
1480     if(type=='load'){
1481     img.src = '$CFG->pixpath/i/loading.gif';
1482     para.innerHTML = '$strloading';
1483     }else{
1484     img.src = '$CFG->pixpath/i/progressbar.gif';
1485     para.innerHTML = '$strcopying <strong>'+name+'</strong>';
1486     }
1487     content.appendChild(para);
1488     content.appendChild(img);
1489     //content.innerHTML = '';
1490     panel.get('element').appendChild(content);
1492 _client.rename = function(oldname, url, icon, repo_id){
1493     var panel = new YAHOO.util.Element('panel-$suffix');
1494     var html = '<div class="rename-form">';
1495     _client.repositoryid=repo_id;
1496     html += '<p><img src="'+icon+'" /></p>';
1497     html += '<p><label for="newname-$suffix">$strsaveas</label>';
1498     html += '<input type="text" id="newname-$suffix" value="'+oldname+'" /></p>';
1499     /**
1500     html += '<p><label for="syncfile-$suffix">$strsync</label> ';
1501     html += '<input type="checkbox" id="syncfile-$suffix" /></p>';
1502     */
1503     html += '<p><input type="hidden" id="fileurl-$suffix" value="'+url+'" />';
1504     html += '<a href="###" onclick="repository_client_$suffix.viewfiles()">$strback</a> ';
1505     html += '<input type="button" onclick="repository_client_$suffix.download()" value="$strdownbtn" />';
1506     html += '<input type="button" onclick="repository_client_$suffix.hide()" value="$strcancel" /></p>';
1507     html += '</div>';
1508     panel.get('element').innerHTML = html;
1510 _client.popup = function(url){
1511     active_instance = repository_client_$suffix;
1512     _client.win = window.open(url,'repo_auth', 'location=0,status=0,scrollbars=0,width=500,height=300');
1513     return false;
1515 _client.print_login = function(){
1516     var panel = new YAHOO.util.Element('panel-$suffix');
1517     var data = _client.ds.login;
1518     var str = '';
1519     for(var k in data){
1520         str += '<p>';
1521         if(data[k].type=='popup'){
1522             str += '<a href="###" onclick="repository_client_$suffix.popup(\''+data[k].url+'\')">test</a>';
1523         }else{
1524             var lable_id = '';
1525             var field_id = '';
1526             var field_value = '';
1527             if(data[k].id){
1528                 lable_id = ' for="'+data[k].id+'"';
1529                 field_id = ' id="'+data[k].id+'"';
1530             }
1531             if (data[k].label) {
1532                 str += '<label'+lable_id+'>'+data[k].label+'</label><br/>';
1533             }
1534             if(data[k].value){
1535                 field_value = ' value="'+data[k].value+'"';
1536             }
1537             str += '<input type="'+data[k].type+'"'+' name="'+data[k].name+'"'+field_id+field_value+' />';
1538         }
1539         str += '</p>';
1540     }
1541     str += '<p><input type="button" onclick="repository_client_$suffix.login()" value="$strsubmit" /></p>';
1542     panel.get('element').innerHTML = str;
1545 _client.viewfiles = function(){
1546     if(_client.viewmode) {
1547         _client.viewthumb();
1548     } else {
1549         _client.viewlist();
1550     }
1552 _client.print_header = function(){
1553     var panel = new YAHOO.util.Element('panel-$suffix');
1554     var str = '';
1555     str += '<div id="repo-tb-$suffix"></div>';
1556     panel.set('innerHTML', str);
1557     _client.makepath();
1559 _client.print_footer = function(){
1560     var panel = new YAHOO.util.Element('panel-$suffix');
1561     panel.get('element').innerHTML += _client.uploadcontrol();
1562     panel.get('element').innerHTML += _client.makepage();
1563     var oDiv = document.getElementById('repo-tb-$suffix');
1564     if(!_client.ds.nosearch){
1565         var search = document.createElement('A');
1566         search.href = '###';
1567         search.innerHTML = '<img src="$CFG->pixpath/a/search.png" /> $strsearch';
1568         oDiv.appendChild(search);
1569         search.onclick = function() {
1570             repository_client_$suffix.search(repository_client_$suffix.repositoryid);
1571         }
1572     }
1573     // weather we use cache for this instance, this button will reload listing anyway
1574     var ccache = document.createElement('A');
1575     ccache.href = '###';
1576     ccache.innerHTML = '<img src="$CFG->pixpath/a/refresh.png" /> $strrefresh';
1577     oDiv.appendChild(ccache);
1578     ccache.onclick = function() {
1579         var params = [];
1580         params['env']=_client.env;
1581         params['sesskey']='$sesskey';
1582         params['ctx_id']=$context->id;
1583         params['repo_id']=repository_client_$suffix.repositoryid;
1584         _client.loading('load');
1585         var trans = YAHOO.util.Connect.asyncRequest('POST',
1586             '$CFG->httpswwwroot/repository/ws.php?action=ccache', repository_client_$suffix.req_cb, _client.postdata(params));
1587     }
1588     if(_client.ds.manage){
1589         var mgr = document.createElement('A');
1590         mgr.innerHTML = '<img src="$CFG->pixpath/a/setting.png" /> $strmgr';
1591         mgr.href = _client.ds.manage;
1592         mgr.target = "_blank";
1593         oDiv.appendChild(mgr);
1594     }
1595     if(!_client.ds.nologin){
1596         var logout = document.createElement('A');
1597         logout.href = '###';
1598         logout.innerHTML = '<img src="$CFG->pixpath/a/logout.png" /> $strlogout';
1599         oDiv.appendChild(logout);
1600         logout.onclick = function() {
1601             repository_client_$suffix.req(repository_client_$suffix.repositoryid, 1, 1);
1602         }
1603     }
1605 _client.viewthumb = function(ds){
1606     _client.viewmode = 1;
1607     var panel = new YAHOO.util.Element('panel-$suffix');
1608     _client.viewbar.check(1);
1609     var list = null;
1610     var args = arguments.length;
1611     if(args == 1){
1612         list = ds;
1613     } else {
1614         // from button
1615         list = _client.ds.list;
1616     }
1617     _client.print_header();
1618     var count = 0;
1619     for(k in list){
1620         var el = document.createElement('div');
1621         el.className='grid';
1622         var frame = document.createElement('DIV');
1623         frame.style.textAlign='center';
1624         var img = document.createElement('img');
1625         img.src = list[k].thumbnail;
1626         var link = document.createElement('A');
1627         link.href='###';
1628         link.id = 'img-id-'+String(count);
1629         link.appendChild(img);
1630         frame.appendChild(link);
1631         var title = document.createElement('div');
1632         if(list[k].children){
1633             title.innerHTML = '<i><u>'+list[k].title+'</i></u>';
1634         } else {
1635             if(list[k].url)
1636                 title.innerHTML = '<p><a target="_blank" href="'+list[k].url+'">$strpreview</a></p>';
1637             title.innerHTML += '<span>'+list[k].title+"</span>";
1638         }
1639         title.className = 'label';
1640         el.appendChild(frame);
1641         el.appendChild(title);
1642         panel.get('element').appendChild(el);
1643         if(list[k].children){
1644             var folder = new YAHOO.util.Element(link.id);
1645             folder.ds = list[k].children;
1646             folder.on('contentReady', function(){
1647                 this.on('click', function(){
1648                     if(_client.ds.dynload){
1649                         // TODO: get file list dymanically
1650                     }else{
1651                         _client.viewthumb(this.ds);
1652                     }
1653                 });
1654             });
1655         } else {
1656             var file = new YAHOO.util.Element(link.id);
1657             file.title = list[k].title;
1658             file.value = list[k].source;
1659             file.icon  = list[k].thumbnail;
1660             if(list[k].repo_id){
1661                 file.repo_id = list[k].repo_id;
1662             }else{
1663                 file.repo_id = _client.repositoryid;
1664             }
1665             file.on('contentReady', function(){
1666                 this.on('click', function(){
1667                     repository_client_$suffix.rename(this.title, this.value, this.icon, this.repo_id);
1668                 });
1669             });
1670         }
1671         count++;
1672     }
1673     _client.print_footer();
1675 _client.buildtree = function(node, level){
1676     if(node.children){
1677         node.title = '<i><u>'+node.title+'</u></i>';
1678     }
1679     var info = {label:node.title, title:"$strdate"+node.date+' '+'$strsize'+node.size};
1680     var tmpNode = new YAHOO.widget.TextNode(info, level, false);
1681     var tooltip = new YAHOO.widget.Tooltip(tmpNode.labelElId, {
1682         context:tmpNode.labelElId, text:info.title});
1683     if(node.repo_id){
1684         tmpNode.repo_id=node.repo_id;
1685     }else{
1686         tmpNode.repo_id=_client.repositoryid;
1687     }
1688     tmpNode.filename = node.title;
1689     tmpNode.value  = node.source;
1690     tmpNode.icon = node.thumbnail;
1691     if(node.children){
1692         tmpNode.isLeaf = false;
1693         if (node.path) {
1694             tmpNode.path = node.path;
1695         } else {
1696             tmpNode.path = '';
1697         }
1698         for(var c in node.children){
1699             _client.buildtree(node.children[c], tmpNode);
1700         }
1701     } else {
1702         tmpNode.isLeaf = true;
1703         tmpNode.onLabelClick = function() {
1704             repository_client_$suffix.rename(this.filename, this.value, this.icon, this.repo_id);
1705         }
1706     }
1708 _client.dynload = function (node, fnLoadComplete){
1709     var callback = {
1710         success: function(o) {
1711             try {
1712                 var json = YAHOO.lang.JSON.parse(o.responseText);
1713             } catch(e) {
1714                 alert('$strinvalidjson - '+o.responseText);
1715             }
1716             for(k in json.list){
1717                 _client.buildtree(json.list[k], node);
1718             }
1719             o.argument.fnLoadComplete();
1720         },
1721         failure:function(oResponse){
1722             alert('$strerror');
1723             oResponse.argument.fnLoadComplete();
1724         },
1725         argument:{"node":node, "fnLoadComplete": fnLoadComplete},
1726         timeout:600
1727     }
1728     var params = [];
1729     params['p']=node.path;
1730     params['env']=_client.env;
1731     params['sesskey']='$sesskey';
1732     params['ctx_id']=$context->id;
1733     params['repo_id']=_client.repositoryid;
1734     var trans = YAHOO.util.Connect.asyncRequest('POST',
1735         '$CFG->httpswwwroot/repository/ws.php?action=list', callback, _client.postdata(params));
1737 _client.viewlist = function(){
1738     _client.viewmode = 0;
1739     var panel = new YAHOO.util.Element('panel-$suffix');
1740     _client.viewbar.check(0);
1741     list = _client.ds.list;
1742     _client.print_header();
1743     panel.get('element').innerHTML += '<div id="treediv-$suffix"></div>';
1744     var tree = new YAHOO.widget.TreeView('treediv-$suffix');
1745     if(_client.ds.dynload) {
1746         tree.setDynamicLoad(_client.dynload, 1);
1747     } else {
1748     }
1749     for(k in list){
1750         _client.buildtree(list[k], tree.getRoot());
1751     }
1752     tree.draw();
1753     _client.print_footer();
1755 _client.upload = function(){
1756     var u = _client.ds.upload;
1757     var aform = document.getElementById(u.id);
1758     var parent = document.getElementById(u.id+'_div');
1759     var d = document.getElementById(_client.ds.upload.id+'-file');
1760     if(d.value!='' && d.value!=null){
1761         var container = document.createElement('DIV');
1762         container.id = u.id+'_loading';
1763         container.style.textAlign='center';
1764         var img = document.createElement('IMG');
1765         img.src = '$CFG->pixpath/i/progressbar.gif';
1766         var para = document.createElement('p');
1767         para.innerHTML = '$struploading';
1768         container.appendChild(para);
1769         container.appendChild(img);
1770         parent.appendChild(container);
1771         YAHOO.util.Connect.setForm(aform, true, true);
1772         var trans = YAHOO.util.Connect.asyncRequest('POST',
1773             '$CFG->httpswwwroot/repository/ws.php?action=upload&sesskey=$sesskey&ctx_id=$context->id&repo_id='
1774                 +_client.repositoryid,
1775             _client.upload_cb);
1776     }else{
1777         alert('$strfilenotnull');
1778     }
1780 _client.upload_cb = {
1781     upload: function(o){
1782         try {
1783             var ret = YAHOO.lang.JSON.parse(o.responseText);
1784         } catch(e) {
1785             alert('$strinvalidjson - '+o.responseText);
1786         }
1787         if(ret && ret.e){
1788             var panel = new YAHOO.util.Element('panel-$suffix');
1789             panel.get('element').innerHTML = ret.e;
1790             return;
1791         }
1792         if(ret){
1793             alert('$strsaved');
1794             repository_client_$suffix.end(ret);
1795         }else{
1796             alert('$strinvalidjson');
1797         }
1798     }
1800 _client.uploadcontrol = function() {
1801     var str = '';
1802     if(_client.ds.upload){
1803         str += '<div id="'+_client.ds.upload.id+'_div" class="upload-form">';
1804         str += '<form id="'+_client.ds.upload.id+'" onsubmit="return false">';
1805         str += '<label for="'+_client.ds.upload.id+'-file">'+_client.ds.upload.label+'</label>';
1806         str += '<input type="file" id="'+_client.ds.upload.id+'-file" name="repo_upload_file" />';
1807         str += '<p class="upload"><a href="###" onclick="return repository_client_$suffix.upload();">$strupload</a></p>';
1808         str += '</form>';
1809         str += '</div>';
1810     }
1811     return str;
1813 _client.makepage = function(){
1814     var str = '';
1815     if(_client.ds.pages){
1816         str += '<div class="paging" id="paging-$suffix">';
1817         for(var i = 1; i <= _client.ds.pages; i++) {
1818             str += '<a onclick="repository_client_$suffix.req('+_client.repositoryid+', '+i+', 0)" href="###">';
1819             str += String(i);
1820             str += '</a> ';
1821         }
1822         str += '</div>';
1823     }
1824     return str;
1826 _client.makepath = function(){
1827     if(_client.viewmode == 0) {
1828         return;
1829     }
1830     var panel = new YAHOO.util.Element('panel-$suffix');
1831     var p = _client.ds.path;
1832     if(p && p.length!=0){
1833         var oDiv = document.createElement('DIV');
1834         oDiv.id = "path-$suffix";
1835         oDiv.className = "repo-path";
1836         panel.get('element').appendChild(oDiv);
1837         for(var i = 0; i < _client.ds.path.length; i++) {
1838             var link = document.createElement('A');
1839             link.href = "###";
1840             link.innerHTML = _client.ds.path[i].name;
1841             link.id = 'path-'+i+'-el';
1842             var sep = document.createElement('SPAN');
1843             sep.innerHTML = '/';
1844             oDiv.appendChild(link);
1845             oDiv.appendChild(sep);
1846             var el = new YAHOO.util.Element(link.id);
1847             el.id = _client.repositoryid;
1848             el.path = _client.ds.path[i].path;
1849             el.on('contentReady', function(){
1850                 this.on('click', function(){
1851                     repository_client_$suffix.req(this.id, this.path, 0);
1852                 })
1853             });
1854         }
1855     }
1857 // send download request
1858 _client.download = function(){
1859     var title = document.getElementById('newname-$suffix').value;
1860     var file = document.getElementById('fileurl-$suffix').value;
1861     _client.loading('download', title);
1862     var params = [];
1863     params['env']=_client.env;
1864     params['file']=file;
1865     params['title']=title;
1866     params['sesskey']='$sesskey';
1867     params['ctx_id']=$context->id;
1868     params['repo_id']=_client.repositoryid;
1869     var trans = YAHOO.util.Connect.asyncRequest('POST',
1870         '$CFG->httpswwwroot/repository/ws.php?action=download', _client.download_cb, _client.postdata(params));
1872 // send login request
1873 _client.login = function(){
1874     var params = [];
1875     var data = _client.ds.login;
1876     for (var k in data) {
1877         if(data[k].type!='popup'){
1878             var el = document.getElementsByName(data[k].name)[0];
1879             params[data[k].name] = '';
1880             if(el.type == 'checkbox') {
1881                 params[data[k].name] = el.checked;
1882             } else {
1883                 params[data[k].name] = el.value;
1884             }
1885         }
1886     }
1887     params['env'] = _client.env;
1888     params['ctx_id'] = $context->id;
1889     params['sesskey']= '$sesskey';
1890     _client.loading('load');
1891     var trans = YAHOO.util.Connect.asyncRequest('POST',
1892         '$CFG->httpswwwroot/repository/ws.php?action=sign', _client.req_cb, _client.postdata(params));
1894 _client.end = function(str){
1895     if(_client.env=='form'){
1896         _client.target.value = str['id'];
1897     }else{
1898         _client.target.value = str['url'];
1899         _client.target.onchange();
1900     }
1901     _client.formcallback(str['file']);
1902     _client.instance.hide();
1903     _client.viewfiles();
1905 _client.hide = function(){
1906     _client.instance.hide();
1907     _client.viewfiles();
1909 // request file list or login
1910 _client.req = function(id, path, reset) {
1911     _client.viewbar.set('disabled', false);
1912     _client.loading('load');
1913     _client.repositoryid = id;
1914     if (reset == 1) {
1915         action = 'logout';
1916     } else {
1917         action = 'list';
1918     }
1919     var params = [];
1920     params['p'] = path;
1921     params['reset']=reset;
1922     params['env']=_client.env;
1923     params['action']=action;
1924     params['sesskey']='$sesskey';
1925     params['ctx_id']=$context->id;
1926     params['repo_id']=id;
1927     var trans = YAHOO.util.Connect.asyncRequest('POST', '$CFG->httpswwwroot/repository/ws.php?action='+action, _client.req_cb, _client.postdata(params));
1929 _client.search = function(id){
1930     var data = window.prompt("$strsearching");
1931     if(data == '') {
1932         alert('$strnoenter');
1933         return;
1934     }else if(data == null){
1935         return;
1936     }
1937     _client.viewbar.set('disabled', false);
1938     _client.loading('load');
1939     var params = [];
1940     params['s']=data;
1941     params['env']=_client.env;
1942     params['sesskey']='$sesskey';
1943     params['ctx_id']=$context->id;
1944     params['repo_id']=id;
1945     var trans = YAHOO.util.Connect.asyncRequest('POST', '$CFG->httpswwwroot/repository/ws.php?action=search', _client.req_cb, _client.postdata(params));
1947 _client.req_cb = {
1948     success: function(o) {
1949         var panel = new YAHOO.util.Element('panel-$suffix');
1950         try {
1951             var ret = YAHOO.lang.JSON.parse(o.responseText);
1952         } catch(e) {
1953             alert('$strinvalidjson - '+o.responseText);
1954         };
1955         if(ret && ret.e){
1956             panel.get('element').innerHTML = ret.e;
1957             return;
1958         }
1959         _client.ds = ret;
1960         if(!_client.ds){
1961             return;
1962         }else if(_client.ds && _client.ds.login){
1963             _client.print_login();
1964         } else if(_client.ds.list) {
1965             if(_client.viewmode) {
1966                 _client.viewthumb();
1967             } else {
1968                 _client.viewlist();
1969             }
1970         }
1971     }
1973 _client.download_cb = {
1974     success: function(o) {
1975         var panel = new YAHOO.util.Element('panel-$suffix');
1976         try {
1977             var ret = YAHOO.lang.JSON.parse(o.responseText);
1978         } catch(e) {
1979             alert('$strinvalidjson - '+o.responseText);
1980         }
1981         if(ret && ret.e){
1982             panel.get('element').innerHTML = ret.e;
1983             return;
1984         }
1985         if(ret){
1986             repository_client_$suffix.end(ret);
1987         }else{
1988             alert('$strinvalidjson');
1989         }
1990     }
1993 return _client;
1994 })();
1995 EOD;
1997     $repos = repository_get_instances(array($context,get_system_context()));
1998     foreach($repos as $repo) {
1999         $js .= "\r\n";
2000         $js .= 'repository_client_'.$suffix.'.repos.push('.json_encode($repo->ajax_info()).');'."\n";
2001     }
2002     $js .= "\r\n";
2004     $js .= <<<EOD
2005 function openpicker_$suffix(params) {
2006     if(!repository_client_$suffix.instance) {
2007         repository_client_$suffix.env = params.env;
2008         repository_client_$suffix.target = params.target;
2009         if(params.type){
2010             repository_client_$suffix.filetype = params.filetype;
2011         } else {
2012             repository_client_$suffix.filetype = 'all';
2013         }
2014         repository_client_$suffix.instance = new repository_client_$suffix();
2015         repository_client_$suffix.instance.create_picker();
2016         if(params.callback){
2017             repository_client_$suffix.formcallback = params.callback;
2018         } else {
2019             repository_client_$suffix.formcallback = function(){};
2020         }
2021     } else {
2022         repository_client_$suffix.instance.show();
2023     }
2025 //]]>
2026 </script>
2027 EOD;
2028     return array('css'=>$css, 'js'=>$js, 'suffix'=>$suffix);
2031 /**
2032  * TODO: write comment
2033  */
2034 final class repository_instance_form extends moodleform {
2035     protected $instance;
2036     protected $plugin;
2038     /**
2039      * TODO: write comment
2040      * @global <type> $CFG
2041      */
2042     public function definition() {
2043         global $CFG;
2044         // type of plugin, string
2045         $this->plugin = $this->_customdata['plugin'];
2046         $this->typeid = $this->_customdata['typeid'];
2047         $this->contextid = $this->_customdata['contextid'];
2048         $this->instance = (isset($this->_customdata['instance'])
2049                 && is_subclass_of($this->_customdata['instance'], 'repository'))
2050             ? $this->_customdata['instance'] : null;
2052         $mform =& $this->_form;
2053         $strrequired = get_string('required');
2055         $mform->addElement('hidden', 'edit',  ($this->instance) ? $this->instance->id : 0);
2056         $mform->addElement('hidden', 'new',   $this->plugin);
2057         $mform->addElement('hidden', 'plugin', $this->plugin);
2058         $mform->addElement('hidden', 'typeid', $this->typeid);
2059         $mform->addElement('hidden', 'contextid', $this->contextid);
2061         $mform->addElement('text', 'name', get_string('name'), 'maxlength="100" size="30"');
2062         $mform->addRule('name', $strrequired, 'required', null, 'client');
2064         // let the plugin add the fields they want (either statically or not)
2065         if (repository_static_function($this->plugin, 'has_instance_config')) {
2066             if (!$this->instance) {
2067                 $result = repository_static_function($this->plugin, 'instance_config_form', $mform);
2068             } else {
2069                 $result = $this->instance->instance_config_form($mform);
2070             }
2071         }
2073         // and set the data if we have some.
2074         if ($this->instance) {
2075             $data = array();
2076             $data['name'] = $this->instance->name;
2077             foreach ($this->instance->get_instance_option_names() as $config) {
2078                 if (!empty($this->instance->$config)) {
2079                     $data[$config] = $this->instance->$config;
2080                 } else {
2081                     $data[$config] = '';
2082                 }
2083             }
2084             $this->set_data($data);
2085         }
2086         $this->add_action_buttons(true, get_string('save','repository'));
2087     }
2089     /**
2090      * TODO: write comment
2091      * @global <type> $DB
2092      * @param <type> $data
2093      * @return <type>
2094      */
2095     public function validation($data) {
2096         global $DB;
2098         $errors = array();
2099         if ($DB->count_records('repository_instances', array('name' => $data['name'], 'typeid' => $data['typeid'])) > 1) {
2100             $errors = array('name' => get_string('err_uniquename', 'repository'));
2101         }
2103         $pluginerrors = array();
2104         if ($this->instance) {
2105             //$pluginerrors = $this->instance->admin_config_validation($data);
2106         } else {
2107             //$pluginerrors = repository_static_function($this->plugin, 'admin_config_validation', $data);
2108         }
2109         if (is_array($pluginerrors)) {
2110             $errors = array_merge($errors, $pluginerrors);
2111         }
2112         return $errors;
2113     }
2117 /**
2118  * Display a form with the general option fields of a type
2119  */
2120 final class repository_admin_form extends moodleform {
2121     protected $instance;
2122     protected $plugin;
2124     /**
2125      * Definition of the moodleform
2126      * @global object $CFG
2127      */
2128     public function definition() {
2129         global $CFG;
2130         // type of plugin, string
2131         $this->plugin = $this->_customdata['plugin'];
2132         $this->instance = (isset($this->_customdata['instance'])
2133                 && is_a($this->_customdata['instance'], 'repository_type'))
2134             ? $this->_customdata['instance'] : null;
2136         $mform =& $this->_form;
2137         $strrequired = get_string('required');
2139         $mform->addElement('hidden', 'edit',  ($this->instance) ? $this->instance->get_typename() : 0);
2140         $mform->addElement('hidden', 'new',   $this->plugin);
2141         $mform->addElement('hidden', 'plugin', $this->plugin);
2142         // let the plugin add the fields they want (either statically or not)
2143         if (repository_static_function($this->plugin, 'has_admin_config')) {
2144             if (!$this->instance) {
2145                 $result = repository_static_function($this->plugin, 'admin_config_form', $mform);
2146             } else {
2147                   $classname = 'repository_' . $this->instance->get_typename();
2148                   $result = call_user_func(array($classname,'admin_config_form'),$mform);
2149             }
2150         }
2152         // and set the data if we have some.
2153         if ($this->instance) {
2154             $data = array();
2155             $option_names = call_user_func(array($classname,'get_admin_option_names'));
2156             $instanceoptions = $this->instance->get_options();
2157             foreach ($option_names as $config) {
2158                 if (!empty($instanceoptions[$config])) {
2159                     $data[$config] = $instanceoptions[$config];
2160                 } else {
2161                     $data[$config] = '';
2162                 }
2163             }
2164             $this->set_data($data);
2165         }
2166         $this->add_action_buttons(true, get_string('save','repository'));
2167     }
2172 /**
2173  * Display a repository instance list (with edit/delete/create links)
2174  * @global object $CFG
2175  * @global object $USER
2176  * @param object $context the context for which we display the instance
2177  * @param string $typename if set, we display only one type of instance
2178  */
2179 function repository_display_instances_list($context, $typename = null){
2180        global $CFG, $USER;
2182         $output = print_box_start('generalbox','',true);
2183         //if the context is SYSTEM, so we call it from administration page
2184         $admin = ($context->id == SYSCONTEXTID) ? true : false;
2185         if($admin) {
2186             $baseurl = $CFG->httpswwwroot . '/admin/repositoryinstance.php?sesskey=' . sesskey();
2187              $output .= "<div ><h2 style='text-align: center'>" . get_string('siteinstances', 'repository') . " ";
2188              $output .= "</h2></div>";
2189         } else {
2190           $baseurl = $CFG->httpswwwroot . '/repository/manage_instances.php?contextid=' . $context->id . '&amp;sesskey=' . sesskey();
2192         }
2194         $namestr = get_string('name');
2195         $pluginstr = get_string('plugin', 'repository');
2196         $settingsstr = get_string('settings');
2197         $deletestr = get_string('delete');
2198         $updown = get_string('updown', 'repository');
2199         $plugins = get_list_of_plugins('repository');
2200         //retrieve list of instances. In administration context we want to display all
2201         //instances of a type, even if this type is not visible. In course/user context we
2202         //want to display only visible instances, but for every type types. The repository_get_instances()
2203         //third parameter displays only visible type.
2204         $instances = repository_get_instances(array($context),null,!$admin,$typename);
2205         $instancesnumber = count($instances);
2206         $alreadyplugins = array();
2207         $table = new StdClass;
2208         $table->head = array($namestr, $pluginstr, $deletestr, $settingsstr);
2209         $table->align = array('left', 'left', 'center','center');
2210         $table->data = array();
2211         $updowncount=1;
2212         foreach ($instances as $i) {
2213             $settings = '';
2214             $settings .= '<a href="' . $baseurl . '&amp;type='.$typename.'&amp;edit=' . $i->id . '">' . $settingsstr . '</a>' . "\n";
2215             $delete = '<a href="' . $baseurl . '&amp;type='.$typename.'&amp;delete=' .  $i->id . '">' . $deletestr . '</a>' . "\n";
2217             $type = repository_get_type_by_id($i->typeid);
2218             $table->data[] = array($i->name, $type->get_readablename(), $delete, $settings);
2220             //display a grey row if the type is defined as not visible
2221             if (isset($type) && !$type->get_visible()){
2222                 $table->rowclass[] = 'dimmed_text';
2223             } else{
2224                 $table->rowclass[] = '';
2225             }
2227             if (!in_array($i->name, $alreadyplugins)) {
2228                 $alreadyplugins[] = $i->name;
2229             }
2230         }
2231         $output .= print_table($table, true);
2232         $instancehtml = '<div>';
2233         $addable = 0;
2235         //if no type is set, we can create all type of instance
2236         if (!$typename) {
2237             $instancehtml .= '<h3>';
2238             $instancehtml .= get_string('createrepository', 'repository');
2239             $instancehtml .= '</h3><ul>';
2240             foreach ($plugins as $p) {
2241                    $type = repository_get_type_by_typename($p);
2242                    if (!empty($type) && $type->get_visible()) {
2243                        if (repository_static_function($p, 'has_multiple_instances')){
2244                             $instancehtml .= '<li><a href="'.$baseurl.'&amp;new='.$p.'">'.get_string('create', 'repository')
2245                                 .' "'.get_string('repositoryname', 'repository_'.$p).'" '
2246                                 .get_string('instance', 'repository').'</a></li>';
2247                             $addable++;
2248                         }
2249                    }
2250             }
2251              $instancehtml .= '</ul>';
2252         }
2253         //create a unique type of instance
2254         else {
2255             if (repository_static_function($typename, 'has_multiple_instances')){
2256                 $addable = 1;
2257                 $instancehtml .= "<form action='".$baseurl."&amp;new=".$typename."' method='post'>
2258                                   <p style='text-align:center'><input type='submit' value='".get_string('createinstance', 'repository')."'/></p>
2259                                   </form>";
2260             }
2261         }
2263         if ($addable) {
2264             $instancehtml .= '</div>';
2265             $output .= $instancehtml;
2266         }
2268         $output .= print_box_end(true);
2270         //print the list + creation links
2271         print($output);