"MDL-13766, always display personal repositories"
[moodle.git] / repository / lib.php
CommitLineData
12c79bfd 1<?php
2 // $Id$
1cf56396 3
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///////////////////////////////////////////////////////////////////////////
26
aca64b79 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 */
38
39
40
19add4c0 41require_once(dirname(dirname(__FILE__)) . '/config.php');
9bdd9eee 42require_once(dirname(dirname(__FILE__)) . '/lib/filelib.php');
43require_once(dirname(dirname(__FILE__)) . '/lib/formslib.php');
44// File picker javascript code
45require_once(dirname(dirname(__FILE__)) . '/repository/javascript.php');
1cf56396 46
a6600395 47/**
48 * A repository_type is a repository plug-in. It can be Box.net, Flick-r, ...
49 * A repository type can be edited, sorted and hidden. It is mandatory for an
50 * administrator to create a repository type in order to be able to create
51 * some instances of this type.
52 *
53 * Coding note:
54 * - a repository_type object is mapped to the "repository" database table
55 * - "typename" attibut maps the "type" database field. It is unique.
56 * - general "options" for a repository type are saved in the config_plugin table
eb239694 57 * - when you delete a repository, all instances are deleted, and general
58 * options are also deleted from database
a6600395 59 * - When you create a type for a plugin that can't have multiple instances, a
60 * instance is automatically created.
61 */
62class repository_type {
63
64
65 /**
66 * Type name (no whitespace) - A type name is unique
67 * Note: for a user-friendly type name see get_readablename()
68 * @var String
69 */
70 private $_typename;
71
72
73 /**
74 * Options of this type
75 * They are general options that any instance of this type would share
76 * e.g. API key
77 * These options are saved in config_plugin table
78 * @var array
79 */
7a3b93c1 80 private $_options;
a6600395 81
82
83 /**
84 * Is the repository type visible or hidden
85 * If false (hidden): no instances can be created, edited, deleted, showned , used...
86 * @var boolean
87 */
7a3b93c1 88 private $_visible;
a6600395 89
90
91 /**
92 * 0 => not ordered, 1 => first position, 2 => second position...
93 * A not order type would appear in first position (should never happened)
94 * @var integer
95 */
96 private $_sortorder;
97
98 /**
99 * repository_type constructor
100 * @global <type> $CFG
101 * @param integer $typename
102 * @param array $typeoptions
103 * @param boolean $visible
104 * @param integer $sortorder (don't really need set, it will be during create() call)
105 */
7a3b93c1 106 public function __construct($typename = '', $typeoptions = array(), $visible = false, $sortorder = 0) {
a6600395 107 global $CFG;
108
109 //set type attributs
110 $this->_typename = $typename;
111 $this->_visible = $visible;
112 $this->_sortorder = $sortorder;
46dd6bb0 113
a6600395 114 //set options attribut
115 $this->_options = array();
1b79955a 116 $options = repository_static_function($typename,'get_type_option_names');
a6600395 117 //check that the type can be setup
06e65e1e 118 if (!empty($options)) {
a6600395 119 //set the type options
120 foreach ($options as $config) {
7a3b93c1 121 if (array_key_exists($config,$typeoptions)) {
122 $this->_options[$config] = $typeoptions[$config];
a6600395 123 }
124 }
125 }
126 }
127
128 /**
129 * Get the type name (no whitespace)
130 * For a human readable name, use get_readablename()
131 * @return String the type name
132 */
7a3b93c1 133 public function get_typename() {
a6600395 134 return $this->_typename;
135 }
136
137 /**
138 * Return a human readable and user-friendly type name
139 * @return string user-friendly type name
140 */
7a3b93c1 141 public function get_readablename() {
a6600395 142 return get_string('repositoryname','repository_'.$this->_typename);
143 }
144
145 /**
146 * Return general options
147 * @return array the general options
148 */
7a3b93c1 149 public function get_options() {
a6600395 150 return $this->_options;
151 }
152
153 /**
154 * Return visibility
155 * @return boolean
156 */
7a3b93c1 157 public function get_visible() {
a6600395 158 return $this->_visible;
159 }
160
161 /**
162 * Return order / position of display in the file picker
163 * @return integer
164 */
7a3b93c1 165 public function get_sortorder() {
a6600395 166 return $this->_sortorder;
167 }
168
169 /**
170 * Create a repository type (the type name must not already exist)
171 * @global object $DB
172 */
7a3b93c1 173 public function create() {
a6600395 174 global $DB;
175
176 //check that $type has been set
177 $timmedtype = trim($this->_typename);
178 if (empty($timmedtype)) {
7a3b93c1 179 throw new repository_exception('emptytype', 'repository');
a6600395 180 }
181
182 //set sortorder as the last position in the list
7a3b93c1 183 if (!isset($this->_sortorder) || $this->_sortorder == 0 ) {
a6600395 184 $sql = "SELECT MAX(sortorder) FROM {repository}";
185 $this->_sortorder = 1 + $DB->get_field_sql($sql);
186 }
187
188 //only create a new type if it doesn't already exist
189 $existingtype = $DB->get_record('repository', array('type'=>$this->_typename));
7a3b93c1 190 if (!$existingtype) {
191 //create the type
192 $newtype = new stdclass;
193 $newtype->type = $this->_typename;
194 $newtype->visible = $this->_visible;
195 $newtype->sortorder = $this->_sortorder;
196 $DB->insert_record('repository', $newtype);
197
198 //save the options in DB
199 $this->update_options();
200
edb50637 201 //if the plugin type has no multiple instance (e.g. has no instance option name) so it wont
7a3b93c1 202 //be possible for the administrator to create a instance
203 //in this case we need to create an instance
edb50637 204 $instanceoptionnames = repository_static_function($this->_typename, 'get_instance_option_names');
205 if (empty($instanceoptionnames)) {
7a3b93c1 206 $instanceoptions = array();
207 $instanceoptions['name'] = $this->_typename;
208 repository_static_function($this->_typename, 'create', $this->_typename, 0, get_system_context(), $instanceoptions);
209 }
948c2860 210
211 //run init function
212 repository_static_function($this->_typename,"plugin_init");
213
7a3b93c1 214 } else {
a6600395 215 throw new repository_exception('existingrepository', 'repository');
216 }
217 }
218
219
220 /**
221 * Update plugin options into the config_plugin table
222 * @param array $options
223 * @return boolean
224 */
7a3b93c1 225 public function update_options($options = null) {
226 if (!empty($options)) {
a6600395 227 $this->_options = $options;
228 }
229
230 foreach ($this->_options as $name => $value) {
231 set_config($name,$value,$this->_typename);
232 }
233
234 return true;
235 }
236
237 /**
238 * Update visible database field with the value given as parameter
239 * or with the visible value of this object
240 * This function is private.
241 * For public access, have a look to switch_and_update_visibility()
242 * @global object $DB
243 * @param boolean $visible
244 * @return boolean
245 */
7a3b93c1 246 private function update_visible($visible = null) {
a6600395 247 global $DB;
248
7a3b93c1 249 if (!empty($visible)) {
a6600395 250 $this->_visible = $visible;
251 }
7a3b93c1 252 else if (!isset($this->_visible)) {
a6600395 253 throw new repository_exception('updateemptyvisible', 'repository');
254 }
255
256 return $DB->set_field('repository', 'visible', $this->_visible, array('type'=>$this->_typename));
257 }
258
259 /**
260 * Update database sortorder field with the value given as parameter
261 * or with the sortorder value of this object
262 * This function is private.
263 * For public access, have a look to move_order()
264 * @global object $DB
265 * @param integer $sortorder
266 * @return boolean
267 */
7a3b93c1 268 private function update_sortorder($sortorder = null) {
a6600395 269 global $DB;
270
7a3b93c1 271 if (!empty($sortorder) && $sortorder!=0) {
a6600395 272 $this->_sortorder = $sortorder;
273 }
274 //if sortorder is not set, we set it as the ;ast position in the list
7a3b93c1 275 else if (!isset($this->_sortorder) || $this->_sortorder == 0 ) {
a6600395 276 $sql = "SELECT MAX(sortorder) FROM {repository}";
277 $this->_sortorder = 1 + $DB->get_field_sql($sql);
278 }
279
280 return $DB->set_field('repository', 'sortorder', $this->_sortorder, array('type'=>$this->_typename));
281 }
282
283 /**
284 * Change order of the type with its adjacent upper or downer type
285 * (database fields are updated)
286 * Algorithm details:
287 * 1. retrieve all types in an array. This array is sorted by sortorder,
288 * and the array keys start from 0 to X (incremented by 1)
289 * 2. switch sortorder values of this type and its adjacent type
290 * @global object $DB
291 * @param string $move "up" or "down"
292 */
293 public function move_order($move) {
294 global $DB;
a6600395 295
7a3b93c1 296 $types = repository_get_types(); // retrieve all types
297
298 /// retrieve this type into the returned array
299 $i = 0;
300 while (!isset($indice) && $i<count($types)) {
301 if ($types[$i]->get_typename() == $this->_typename) {
a6600395 302 $indice = $i;
303 }
304 $i++;
305 }
306
7a3b93c1 307 /// retrieve adjacent indice
a6600395 308 switch ($move) {
309 case "up":
310 $adjacentindice = $indice - 1;
7a3b93c1 311 break;
a6600395 312 case "down":
313 $adjacentindice = $indice + 1;
7a3b93c1 314 break;
a6600395 315 default:
7a3b93c1 316 throw new repository_exception('movenotdefined', 'repository');
a6600395 317 }
318
319 //switch sortorder of this type and the adjacent type
320 //TODO: we could reset sortorder for all types. This is not as good in performance term, but
321 //that prevent from wrong behaviour on a screwed database. As performance are not important in this particular case
322 //it worth to change the algo.
7a3b93c1 323 if ($adjacentindice>=0 && !empty($types[$adjacentindice])) {
a6600395 324 $DB->set_field('repository', 'sortorder', $this->_sortorder, array('type'=>$types[$adjacentindice]->get_typename()));
325 $this->update_sortorder($types[$adjacentindice]->get_sortorder());
326 }
327 }
328
329 /**
330 * 1. Switch the visibility OFF if it's ON, and ON if it's OFF.
331 * 2. Update the type
332 * @return <type>
333 */
7a3b93c1 334 public function switch_and_update_visibility() {
a6600395 335 $this->_visible = !$this->_visible;
336 return $this->update_visible();
337 }
338
339
340 /**
eb239694 341 * Delete a repository_type (general options are removed from config_plugin
342 * table, and all instances are deleted)
a6600395 343 * @global object $DB
344 * @return boolean
345 */
7a3b93c1 346 public function delete() {
a6600395 347 global $DB;
46dd6bb0 348
349 //delete all instances of this type
12c79bfd 350 $instances = repository_get_instances(array(),null,false,$this->_typename);
7a3b93c1 351 foreach ($instances as $instance) {
46dd6bb0 352 $instance->delete();
353 }
354
eb239694 355 //delete all general options
7a3b93c1 356 foreach ($this->_options as $name => $value) {
eb239694 357 set_config($name, null, $this->_typename);
358 }
359
a6600395 360 return $DB->delete_records('repository', array('type' => $this->_typename));
361 }
362}
363
364/**
365 * Return a type for a given type name.
366 * @global object $DB
367 * @param string $typename the type name
368 * @return integer
369 */
7a3b93c1 370function repository_get_type_by_typename($typename) {
a6600395 371 global $DB;
372
7a3b93c1 373 if (!$record = $DB->get_record('repository',array('type' => $typename))) {
a6600395 374 return false;
375 }
376
377 return new repository_type($typename, (array)get_config($typename), $record->visible, $record->sortorder);
378}
379
380/**
381 * Return a type for a given type id.
382 * @global object $DB
383 * @param string $typename the type name
384 * @return integer
385 */
7a3b93c1 386function repository_get_type_by_id($id) {
a6600395 387 global $DB;
388
7a3b93c1 389 if (!$record = $DB->get_record('repository',array('id' => $id))) {
a6600395 390 return false;
391 }
392
393 return new repository_type($record->type, (array)get_config($record->type), $record->visible, $record->sortorder);
394}
395
396/**
397 * Return all repository types ordered by sortorder
398 * first type in returnedarray[0], second type in returnedarray[1], ...
399 * @global object $DB
bbcd4860 400 * @param boolean $visible can return types by visiblity, return all types if null
a6600395 401 * @return array Repository types
402 */
7a3b93c1 403function repository_get_types($visible=null) {
a6600395 404 global $DB;
405
406 $types = array();
bbcd4860 407 $params = null;
408 if (!empty($visible)) {
409 $params = array('visible' => $visible);
410 }
7a3b93c1 411 if ($records = $DB->get_records('repository',$params,'sortorder')) {
a6600395 412 foreach($records as $type) {
46dd6bb0 413 $types[] = new repository_type($type->type, (array)get_config($type->type), $type->visible, $type->sortorder);
a6600395 414 }
415 }
416
417 return $types;
418}
419
420/**
8d419e59 421 * This is the base class of the repository class
422 *
423 * To use repository plugin, see:
424 * http://docs.moodle.org/en/Development:Repository_How_to_Create_Plugin
425 *
426 * class repository is an abstract class, some functions must be implemented in subclass.
427 *
428 * See an example: repository/boxnet/repository.class.php
429 *
430 * A few notes:
431 * // for ajax file picker, this will print a json string to tell file picker
432 * // how to build a login form
433 * $repo->print_login();
434 * // for ajax file picker, this will return a files list.
435 * $repo->get_listing();
436 * // this function will be used for non-javascript version.
437 * $repo->print_listing();
438 * // print a search box
439 * $repo->print_search();
440 *
441 * @package repository
442 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
a6600395 443 */
fca079c5 444abstract class repository {
4a65c39a 445 public $id;
446 public $context;
447 public $options;
948c2860 448 public $readonly;
1cf56396 449
450 /**
3f24ea1e 451 * 1. Initialize context and options
452 * 2. Accept necessary parameters
453 *
8dcd5deb 454 * @param integer $repositoryid
455 * @param integer $contextid
456 * @param array $options
1cf56396 457 */
948c2860 458 public function __construct($repositoryid, $contextid = SITEID, $options = array(), $readonly = 0) {
4a65c39a 459 $this->id = $repositoryid;
460 $this->context = get_context_instance_by_id($contextid);
948c2860 461 $this->readonly = $readonly;
4a65c39a 462 $this->options = array();
fca079c5 463 if (is_array($options)) {
4a65c39a 464 $options = array_merge($this->get_option(), $options);
465 } else {
466 $options = $this->get_option();
467 }
b1339e98 468 $this->options = array();
4a65c39a 469 foreach ($options as $n => $v) {
470 $this->options[$n] = $v;
82669dc4 471 }
d31af46a 472 $this->name = $this->get_name();
1cf56396 473 }
474
8dcd5deb 475 /**
3f24ea1e 476 * set options for repository instance
477 *
8dcd5deb 478 * @param string $name
3f24ea1e 479 * @param mixed $value
8dcd5deb 480 */
fca079c5 481 public function __set($name, $value) {
82669dc4 482 $this->options[$name] = $value;
483 }
1cf56396 484
8dcd5deb 485 /**
3f24ea1e 486 * get options for repository instance
487 *
488 * @param string $name
489 * @return mixed
8dcd5deb 490 */
fca079c5 491 public function __get($name) {
7a3b93c1 492 if (array_key_exists($name, $this->options)) {
82669dc4 493 return $this->options[$name];
494 }
495 trigger_error('Undefined property: '.$name, E_USER_NOTICE);
496 return null;
497 }
1cf56396 498
8dcd5deb 499 /**
3f24ea1e 500 * test option name
501 *
502 * @param string name
8dcd5deb 503 */
fca079c5 504 public function __isset($name) {
82669dc4 505 return isset($this->options[$name]);
1cf56396 506 }
507
8dcd5deb 508 /**
3f24ea1e 509 * Return the name of the repository class
8dcd5deb 510 * @return <type>
511 */
fca079c5 512 public function __toString() {
82669dc4 513 return 'Repository class: '.__CLASS__;
514 }
4a65c39a 515
c425472d 516 /**
66dc47bc 517 * Download a file, this function can be overridden by
518 * subclass.
3f24ea1e 519 *
8dcd5deb 520 * @global object $CFG
c425472d 521 * @param string $url the url of file
522 * @param string $file save location
3f24ea1e 523 * @return string the location of the file
b1339e98 524 * @see curl package
c425472d 525 */
bb2c046d 526 public function get_file($url, $file = '') {
c425472d 527 global $CFG;
c9260130 528 if (!file_exists($CFG->dataroot.'/temp/download')) {
529 mkdir($CFG->dataroot.'/temp/download/', 0777, true);
1e28c767 530 }
7a3b93c1 531 if (is_dir($CFG->dataroot.'/temp/download')) {
c9260130 532 $dir = $CFG->dataroot.'/temp/download/';
1e28c767 533 }
7a3b93c1 534 if (empty($file)) {
84df43de 535 $file = uniqid('repo').'_'.time().'.tmp';
536 }
7a3b93c1 537 if (file_exists($dir.$file)) {
84df43de 538 $file = uniqid('m').$file;
c425472d 539 }
84df43de 540 $fp = fopen($dir.$file, 'w');
541 $c = new curl;
542 $c->download(array(
7a3b93c1 543 array('url'=>$url, 'file'=>$fp)
544 ));
84df43de 545 return $dir.$file;
82669dc4 546 }
1cf56396 547
1cf56396 548 /**
66dc47bc 549 * Print a list or return formatted string, can be overridden by subclass
82669dc4 550 *
551 * @param string $list
3f24ea1e 552 * @param boolean $print false, return html, otherwise, print it directly
8dcd5deb 553 * @return <type>
554 */
fca079c5 555 public function print_listing($listing = array(), $print=true) {
7a3b93c1 556 if (empty($listing)) {
0f59046f 557 $listing = $this->get_listing();
558 }
fca079c5 559 if (empty($listing)) {
560 $str = '';
561 } else {
562 $count = 0;
563 $str = '<table>';
7a3b93c1 564 foreach ($listing as $v) {
fca079c5 565 $str .= '<tr id="entry_'.$count.'">';
566 $str .= '<td><input type="checkbox" /></td>';
567 $str .= '<td>'.$v['name'].'</td>';
568 $str .= '<td>'.$v['size'].'</td>';
569 $str .= '<td>'.$v['date'].'</td>';
570 $str .= '</tr>';
571 $count++;
572 }
d1fe3452 573 $str .= '</table>';
82669dc4 574 }
7a3b93c1 575 if ($print) {
82669dc4 576 echo $str;
577 return null;
578 } else {
579 return $str;
580 }
1cf56396 581 }
eb239694 582
583 /**
66dc47bc 584 * Return the name of this instance, can be overridden.
eb239694 585 * @global <type> $DB
586 * @return <type>
587 */
7a3b93c1 588 public function get_name() {
d31af46a 589 global $DB;
590 // We always verify instance id from database,
591 // so we always know repository name before init
592 // a repository, so we don't enquery repository
593 // name from database again here.
594 if (isset($this->options['name'])) {
595 return $this->options['name'];
596 } else {
597 if ( $repo = $DB->get_record('repository_instances', array('id'=>$this->id)) ) {
598 return $repo->name;
599 } else {
600 return '';
601 }
602 }
603 }
aa754fe3 604
82669dc4 605 /**
3f24ea1e 606 * Provide repository instance information for Ajax
8dcd5deb 607 * @global object $CFG
4a65c39a 608 * @return object
82669dc4 609 */
b1339e98 610 final public function ajax_info() {
4a65c39a 611 global $CFG;
612 $repo = new stdclass;
27051e43 613 $repo->id = $this->id;
d31af46a 614 $repo->name = $this->get_name();
4a65c39a 615 $repo->type = $this->options['type'];
6fe8b022 616 $repo->icon = $CFG->httpswwwroot.'/repository/'.$repo->type.'/icon.png';
4a65c39a 617 return $repo;
618 }
1cf56396 619
b1339e98 620 /**
621 * Create an instance for this plug-in
8dcd5deb 622 * @global object $CFG
623 * @global object $DB
624 * @param string $type the type of the repository
625 * @param integer $userid the user id
626 * @param object $context the context
627 * @param array $params the options for this instance
628 * @return <type>
b1339e98 629 */
948c2860 630 final public static function create($type, $userid, $context, $params, $readonly=0) {
b1339e98 631 global $CFG, $DB;
632 $params = (array)$params;
633 require_once($CFG->dirroot . '/repository/'. $type . '/repository.class.php');
634 $classname = 'repository_' . $type;
3023078f 635 if ($repo = $DB->get_record('repository', array('type'=>$type))) {
636 $record = new stdclass;
637 $record->name = $params['name'];
638 $record->typeid = $repo->id;
639 $record->timecreated = time();
640 $record->timemodified = time();
641 $record->contextid = $context->id;
948c2860 642 $record->readonly = $readonly;
3023078f 643 $record->userid = $userid;
644 $id = $DB->insert_record('repository_instances', $record);
0a6221f9 645 $options = array();
edb50637 646 $configs = call_user_func($classname . '::get_instance_option_names');
647 foreach ($configs as $config) {
648 $options[$config] = $params[$config];
3023078f 649 }
edb50637 650
3023078f 651 if (!empty($id)) {
652 unset($options['name']);
c9f9f911 653 $instance = repository_get_instance($id);
3023078f 654 $instance->set_option($options);
655 return $id;
656 } else {
657 return null;
b1339e98 658 }
b1339e98 659 } else {
660 return null;
661 }
662 }
8dcd5deb 663
82669dc4 664 /**
4a65c39a 665 * delete a repository instance
8dcd5deb 666 * @global object $DB
667 * @return <type>
82669dc4 668 */
7a3b93c1 669 final public function delete() {
4a65c39a 670 global $DB;
122defc5 671 $DB->delete_records('repository_instances', array('id'=>$this->id));
4a65c39a 672 return true;
673 }
8dcd5deb 674
4a65c39a 675 /**
676 * Hide/Show a repository
8dcd5deb 677 * @global object $DB
678 * @param string $hide
679 * @return <type>
4a65c39a 680 */
7a3b93c1 681 final public function hide($hide = 'toggle') {
4a65c39a 682 global $DB;
683 if ($entry = $DB->get_record('repository', array('id'=>$this->id))) {
684 if ($hide === 'toggle' ) {
685 if (!empty($entry->visible)) {
686 $entry->visible = 0;
687 } else {
688 $entry->visible = 1;
689 }
690 } else {
691 if (!empty($hide)) {
692 $entry->visible = 0;
693 } else {
694 $entry->visible = 1;
695 }
696 }
697 return $DB->update_record('repository', $entry);
698 }
699 return false;
700 }
1cf56396 701
702 /**
82669dc4 703 * Cache login details for repositories
8dcd5deb 704 * @global object $DB
82669dc4 705 * @param string $username
706 * @param string $password
8dcd5deb 707 * @param integer $userid The id of specific user
708 * @return integer Id of the record
1cf56396 709 */
b6558c3b 710 public function store_login($username = '', $password = '', $userid = 1) {
fca079c5 711 global $DB;
712
713 $repository = new stdclass;
4a65c39a 714 if (!empty($this->id)) {
715 $repository->id = $this->id;
19add4c0 716 } else {
717 $repository->userid = $userid;
718 $repository->repositorytype = $this->type;
b6558c3b 719 $repository->contextid = $this->context->id;
19add4c0 720 }
fca079c5 721 if ($entry = $DB->get_record('repository', $repository)) {
722 $repository->id = $entry->id;
723 $repository->username = $username;
724 $repository->password = $password;
725 return $DB->update_record('repository', $repository);
726 } else {
727 $repository->username = $username;
728 $repository->password = $password;
729 return $DB->insert_record('repository', $repository);
730 }
1cf56396 731 }
732
1cf56396 733 /**
4a65c39a 734 * Save settings for repository instance
8dcd5deb 735 * $repo->set_option(array('api_key'=>'f2188bde132', 'name'=>'dongsheng'));
736 * @global object $DB
737 * @param array $options settings
4a65c39a 738 * @return int Id of the record
1cf56396 739 */
7a3b93c1 740 public function set_option($options = array()) {
4a65c39a 741 global $DB;
7a3b93c1 742
122defc5 743 if (!empty($options['name'])) {
744 $r = new object();
745 $r->id = $this->id;
746 $r->name = $options['name'];
747 $DB->update_record('repository_instances', $r);
748 unset($options['name']);
749 }
27051e43 750 foreach ($options as $name=>$value) {
751 if ($id = $DB->get_field('repository_instance_config', 'id', array('name'=>$name, 'instanceid'=>$this->id))) {
752 if ($value===null) {
753 return $DB->delete_records('repository_instance_config', array('name'=>$name, 'instanceid'=>$this->id));
754 } else {
755 return $DB->set_field('repository_instance_config', 'value', $value, array('id'=>$id));
756 }
757 } else {
758 if ($value===null) {
759 return true;
760 }
761 $config = new object();
762 $config->instanceid = $this->id;
763 $config->name = $name;
764 $config->value = $value;
765 return $DB->insert_record('repository_instance_config', $config);
766 }
4a65c39a 767 }
27051e43 768 return true;
1cf56396 769 }
1cf56396 770
4a65c39a 771 /**
772 * Get settings for repository instance
8dcd5deb 773 * @global object $DB
774 * @param <type> $config
4a65c39a 775 * @return array Settings
776 */
7a3b93c1 777 public function get_option($config = '') {
4a65c39a 778 global $DB;
27051e43 779 $entries = $DB->get_records('repository_instance_config', array('instanceid'=>$this->id));
780 $ret = array();
781 if (empty($entries)) {
782 return $ret;
4a65c39a 783 }
7a3b93c1 784 foreach($entries as $entry) {
27051e43 785 $ret[$entry->name] = $entry->value;
4a65c39a 786 }
787 if (!empty($config)) {
788 return $ret[$config];
789 } else {
790 return $ret;
791 }
792 }
bf1fccf0 793
4a65c39a 794 /**
795 * Given a path, and perhaps a search, get a list of files.
796 *
e6be3a69 797 * The format of the returned array must be:
f7639c37 798 * array(
f6812a21 799 * 'path' => (string) path for the current folder
f7639c37 800 * 'dynload' => (bool) use dynamic loading,
f6812a21 801 * 'manage' => (string) link to file manager,
f7639c37 802 * 'nologin' => (bool) requires login,
d31af46a 803 * 'nosearch' => (bool) no search link,
f7639c37 804 * 'upload' => array( // upload manager
805 * 'name' => (string) label of the form element,
806 * 'id' => (string) id of the form element
807 * ),
808 * 'list' => array(
809 * array( // file
810 * 'title' => (string) file name,
3c9e53c0 811 * 'date' => (string) file last modification time, usually userdate(...),
f6812a21 812 * 'size' => (int) file size,
3c9e53c0 813 * 'thumbnail' => (string) url to thumbnail for the file,
336bb44b 814 * 'source' => plugin-dependent unique path to the file (id, url, path, etc.),
815 * 'url'=> the accessible url of file
f7639c37 816 * ),
3c9e53c0 817 * array( // folder - same as file, but no 'source'.
f7639c37 818 * 'title' => (string) folder name,
f6812a21 819 * 'path' => (string) path to this folder
3c9e53c0 820 * 'date' => (string) folder last modification time, usually userdate(...),
f6812a21 821 * 'size' => 0,
3c9e53c0 822 * 'thumbnail' => (string) url to thumbnail for the folder,
823 * 'children' => array( // an empty folder needs to have 'children' defined, but empty.
824 * // content (files and folders)
f7639c37 825 * )
e6be3a69 826 * ),
f7639c37 827 * )
828 * )
829 *
4a65c39a 830 * @param string $parent The parent path, this parameter can
831 * a folder name, or a identification of folder
4a65c39a 832 * @return array the list of files, including meta infomation
833 */
353d5cf3 834 abstract public function get_listing($parent = '/');
1cf56396 835
fbd508b4 836 /**
353d5cf3 837 * Search files in repository
838 * When doing global search, $search_text will be used as
839 * keyword.
840 *
fbd508b4 841 * @return mixed, see get_listing()
842 */
353d5cf3 843 public function search($search_text) {
844 $list = array();
845 $list['list'] = array();
846 return false;
fbd508b4 847 }
848
d68c527f 849 /**
850 * Logout from repository instance
851 * By default, this function will return a login form
852 *
853 * @return string
854 */
855 public function logout(){
856 return $this->print_login();
857 }
858
859 /**
860 * To check whether the user is logged in.
861 *
862 * @return boolean
863 */
864 public function check_login(){
865 return true;
866 }
867
1cf56396 868
4a65c39a 869 /**
870 * Show the login screen, if required
871 * This is an abstract function, it must be overriden.
4a65c39a 872 */
1d66f2b2 873 public function print_login(){
874 return $this->get_listing();
875 }
1cf56396 876
4a65c39a 877 /**
878 * Show the search screen, if required
4a65c39a 879 * @return null
880 */
2b9feb5f 881 public function print_search() {
882 echo '<input type="hidden" name="repo_id" value="'.$this->id.'" />';
883 echo '<input type="hidden" name="ctx_id" value="'.$this->context->id.'" />';
884 echo '<input type="hidden" name="seekey" value="'.sesskey().'" />';
8d419e59 885 echo '<label>'.get_string('keyword', 'repository').': </label><br/><input name="s" value="" /><br/>';
2b9feb5f 886 return true;
887 }
4a65c39a 888
455860ce 889 /**
890 * is it possible to do glboal search?
891 * @return boolean
892 */
7a3b93c1 893 public function global_search() {
455860ce 894 return false;
895 }
896
8dcd5deb 897 /**
a6600395 898 * Defines operations that happen occasionally on cron
8dcd5deb 899 * @return <type>
900 */
a6600395 901 public function cron() {
902 return true;
903 }
904
7892948d 905 /**
83a018ed 906 * function which is run when the type is created (moodle administrator add the plugin)
7892948d 907 */
948c2860 908 public static function plugin_init(){
7892948d 909 }
910
a6600395 911 /**
06e65e1e 912 * Edit/Create Admin Settings Moodle form
913 * @param object $ Moodle form (passed by reference)
a6600395 914 */
daff8f50 915 public function type_config_form(&$mform) {
4a65c39a 916 }
06e65e1e 917
918 /**
919 * Edit/Create Instance Settings Moodle form
920 * @param object $ Moodle form (passed by reference)
a6600395 921 */
06e65e1e 922 public function instance_config_form(&$mform) {
a6600395 923 }
4a65c39a 924
a6600395 925 /**
926 * Return names of the general options
927 * By default: no general option name
928 * @return array
929 */
1b79955a 930 public static function get_type_option_names() {
a6600395 931 return array();
932 }
933
934 /**
935 * Return names of the instance options
936 * By default: no instance option name
937 * @return array
938 */
7a3b93c1 939 public static function get_instance_option_names() {
a6600395 940 return array();
8b65d45c 941 }
8b65d45c 942}
837ebb78 943
944/**
4a65c39a 945 * exception class for repository api
837ebb78 946 */
4a65c39a 947class repository_exception extends moodle_exception {
8b65d45c 948}
4ed43890 949
2057487c 950/**
951 * Check context
952 * @param int $ctx_id
953 * @return boolean
954 */
7a3b93c1 955function repository_check_context($ctx_id) {
2057487c 956 global $USER;
7a3b93c1 957
2057487c 958 $context = get_context_instance_by_id($ctx_id);
959 $level = $context->contextlevel;
7a3b93c1 960
2057487c 961 if ($level == CONTEXT_COURSE) {
962 if (!has_capability('moodle/course:view', $context)) {
963 return false;
964 } else {
965 return true;
966 }
7a3b93c1 967 } else if ($level == CONTEXT_USER) {
2057487c 968 $c = get_context_instance(CONTEXT_USER, $USER->id);
969 if ($c->id == $ctx_id) {
970 return true;
971 } else {
972 return false;
973 }
7a3b93c1 974 } else if ($level == CONTEXT_SYSTEM) {
2057487c 975 // it is always ok in system level
70fbd90e 976 return true;
2057487c 977 }
978 return false;
979}
4a65c39a 980
bbcd4860 981/**
982 * Return all types that you a user can create/edit and which are also visible
983 * Note: Mostly used in order to know if at least one editable type has been set
984 * @return array types
985 */
7a3b93c1 986function repository_get_editable_types() {
bbcd4860 987 $types= repository_get_types(true);
988 $editabletypes = array();
7a3b93c1 989 foreach ($types as $type) {
edb50637 990 $instanceoptionnames = repository_static_function($type->get_typename(), 'get_instance_option_names');
991 if (!empty($instanceoptionnames)) {
bbcd4860 992 $editabletypes[]=$type;
993 }
994 }
995 return $editabletypes;
996}
997
837ebb78 998/**
4a65c39a 999 * Return repository instances
8dcd5deb 1000 * @global object $DB
1001 * @global object $CFG
1002 * @global object $USER
12c79bfd 1003 * @param object $contexts contexts for which the instances are set
8dcd5deb 1004 * @param integer $userid
46dd6bb0 1005 * @param boolean $onlyvisible if visible == true, return visible instances only,
4a65c39a 1006 * otherwise, return all instances
a6600395 1007 * @param string $type a type name to retrieve
4a65c39a 1008 * @return array repository instances
837ebb78 1009 */
7a3b93c1 1010function repository_get_instances($contexts=array(), $userid = null, $onlyvisible = true, $type=null) {
38e55442 1011 global $DB, $CFG, $USER;
7a3b93c1 1012
38e55442 1013 $params = array();
1265fc59 1014 $sql = 'SELECT i.*, r.type AS repositorytype, r.sortorder, r.visible FROM {repository} r, {repository_instances} i WHERE ';
46dd6bb0 1015 $sql .= 'i.typeid = r.id ';
7a3b93c1 1016
4a65c39a 1017 if (!empty($userid) && is_numeric($userid)) {
46dd6bb0 1018 $sql .= ' AND (i.userid = 0 or i.userid = ?)';
4a65c39a 1019 $params[] = $userid;
1020 }
7a3b93c1 1021
12c79bfd 1022 foreach ($contexts as $context) {
7a3b93c1 1023 if (empty($firstcontext)) {
12c79bfd 1024 $firstcontext = true;
1025 $sql .= ' AND ((i.contextid = ?)';
46dd6bb0 1026 } else {
12c79bfd 1027 $sql .= ' OR (i.contextid = ?)';
46dd6bb0 1028 }
12c79bfd 1029 $params[] = $context->id;
38e55442 1030 }
7a3b93c1 1031
7892948d 1032 if (!empty($firstcontext)) {
1033 $sql .=')';
12c79bfd 1034 }
aca64b79 1035
7a3b93c1 1036 if ($onlyvisible == true) {
4a65c39a 1037 $sql .= ' AND (r.visible = 1)';
1038 }
7a3b93c1 1039
1040 if (isset($type)) {
a6600395 1041 $sql .= ' AND (r.type = ?)';
1042 $params[] = $type;
1043 }
1265fc59 1044 $sql .= ' order by r.sortorder, i.name';
7a3b93c1 1045
1046 if (!$repos = $DB->get_records_sql($sql, $params)) {
38e55442 1047 $repos = array();
1048 }
7a3b93c1 1049
4a65c39a 1050 $ret = array();
7a3b93c1 1051 foreach ($repos as $repo) {
1052 require_once($CFG->dirroot . '/repository/'. $repo->repositorytype.'/repository.class.php');
27051e43 1053 $options['visible'] = $repo->visible;
1054 $options['name'] = $repo->name;
1055 $options['type'] = $repo->repositorytype;
1056 $options['typeid'] = $repo->typeid;
4a65c39a 1057 $classname = 'repository_' . $repo->repositorytype;
948c2860 1058 $ret[] = new $classname($repo->id, $repo->contextid, $options, $repo->readonly);
4a65c39a 1059 }
1060 return $ret;
38e55442 1061}
4ed43890 1062
837ebb78 1063/**
1064 * Get single repository instance
8dcd5deb 1065 * @global object $DB
1066 * @global object $CFG
1067 * @param integer $id repository id
837ebb78 1068 * @return object repository instance
1069 */
7a3b93c1 1070function repository_get_instance($id) {
19add4c0 1071 global $DB, $CFG;
27051e43 1072 $sql = 'SELECT i.*, r.type AS repositorytype, r.visible FROM {repository} r, {repository_instances} i WHERE ';
1073 $sql .= 'i.typeid = r.id AND ';
1074 $sql .= 'i.id = '.$id;
19add4c0 1075
27051e43 1076 if(!$instance = $DB->get_record_sql($sql)) {
19add4c0 1077 return false;
1078 }
e6be3a69 1079 require_once($CFG->dirroot . '/repository/'. $instance->repositorytype
7a3b93c1 1080 . '/repository.class.php');
19add4c0 1081 $classname = 'repository_' . $instance->repositorytype;
27051e43 1082 $options['typeid'] = $instance->typeid;
1083 $options['type'] = $instance->repositorytype;
1084 $options['name'] = $instance->name;
948c2860 1085 return new $classname($instance->id, $instance->contextid, $options, $instance->readonly);
19add4c0 1086}
837ebb78 1087
8dcd5deb 1088/**
66dc47bc 1089 * call a static function
8dcd5deb 1090 * @global <type> $CFG
1091 * @param <type> $plugin
1092 * @param <type> $function
a6600395 1093 * @param type $nocallablereturnvalue default value if function not found
1094 * it's mostly used when you don't want to display an error but
1095 * return a boolean
8dcd5deb 1096 * @return <type>
1097 */
4a65c39a 1098function repository_static_function($plugin, $function) {
97f7393d 1099 global $CFG;
4a65c39a 1100
a6600395 1101 //check that the plugin exists
1102 $typedirectory = $CFG->dirroot . '/repository/'. $plugin . '/repository.class.php';
7a3b93c1 1103 if (!file_exists($typedirectory)) {
1104 throw new repository_exception('invalidplugin', 'repository');
a6600395 1105 }
1106
4a65c39a 1107 $pname = null;
1108 if (is_object($plugin) || is_array($plugin)) {
1109 $plugin = (object)$plugin;
1110 $pname = $plugin->name;
1111 } else {
1112 $pname = $plugin;
97f7393d 1113 }
4a65c39a 1114
1115 $args = func_get_args();
1116 if (count($args) <= 2) {
1117 $args = array();
1118 }
1119 else {
1120 array_shift($args);
1121 array_shift($args);
1122 }
1123
a6600395 1124 require_once($typedirectory);
4a65c39a 1125 return call_user_func_array(array('repository_' . $plugin, $function), $args);
97f7393d 1126}
d8eb6e18 1127
837ebb78 1128/**
1129 * Move file from download folder to file pool using FILE API
8dcd5deb 1130 * @global object $DB
1131 * @global object $CFG
1132 * @global object $USER
1133 * @param string $path file path in download folder
1134 * @param string $name file name
1135 * @param integer $itemid item id to identify a file in filepool
1136 * @param string $filearea file area
837ebb78 1137 * @return array information of file in file pool
1138 */
c9260130 1139function repository_move_to_filepool($path, $name, $itemid, $filearea = 'user_draft') {
d8eb6e18 1140 global $DB, $CFG, $USER;
1141 $context = get_context_instance(CONTEXT_USER, $USER->id);
313cc398 1142 $now = time();
d8eb6e18 1143 $entry = new object();
55b4bb1d 1144 $entry->filearea = $filearea;
d8eb6e18 1145 $entry->contextid = $context->id;
1146 $entry->filename = $name;
c9260130 1147 $entry->filepath = '/'.uniqid().'/';
313cc398 1148 $entry->timecreated = $now;
1149 $entry->timemodified = $now;
c2762f06 1150 if(is_numeric($itemid)) {
1151 $entry->itemid = $itemid;
1152 } else {
1153 $entry->itemid = 0;
1154 }
d8eb6e18 1155 $entry->mimetype = mimeinfo('type', $path);
1156 $entry->userid = $USER->id;
1157 $fs = get_file_storage();
1158 $browser = get_file_browser();
1159 if ($file = $fs->create_file_from_pathname($entry, $path)) {
c9260130 1160 $delete = unlink($path);
d8eb6e18 1161 $ret = $browser->get_file_info($context, $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename());
7a3b93c1 1162 if(!empty($ret)) {
c0fa8cba 1163 return array('url'=>$ret->get_url(),'id'=>$file->get_itemid(), 'file'=>$file->get_filename());
3023078f 1164 } else {
1165 return null;
1166 }
d8eb6e18 1167 } else {
1168 return null;
1169 }
1170}
1171
5a3b9db9 1172/**
1173 * Save file to local filesystem pool
1174 * @param string $elname name of element
5a3b9db9 1175 * @param string $filearea
1176 * @param string $filepath
1177 * @param string $filename - use specified filename, if not specified name of uploaded file used
1178 * @param bool $override override file if exists
5a3b9db9 1179 * @return mixed stored_file object or false if error; may throw exception if duplicate found
1180 */
313cc398 1181function repository_store_to_filepool($elname, $filearea='user_draft', $filepath='/', $filename = '', $override = false) {
5a3b9db9 1182 global $USER;
1183 if (!isset($_FILES[$elname])) {
1184 return false;
1185 }
1186
313cc398 1187 if (!$filename) {
1188 $filename = $_FILES[$elname]['name'];
1189 }
5a3b9db9 1190 $context = get_context_instance(CONTEXT_USER, $USER->id);
1191 $itemid = (int)substr(hexdec(uniqid()), 0, 9)+rand(1,100);
1192 $fs = get_file_storage();
1193 $browser = get_file_browser();
1194
1195 if ($file = $fs->get_file($context->id, $filearea, $itemid, $filepath, $filename)) {
1196 if ($override) {
1197 $file->delete();
1198 } else {
1199 return false;
1200 }
1201 }
1202
1203 $file_record = new object();
1204 $file_record->contextid = $context->id;
1205 $file_record->filearea = $filearea;
1206 $file_record->itemid = $itemid;
1207 $file_record->filepath = $filepath;
1208 $file_record->filename = $filename;
1209 $file_record->userid = $USER->id;
1210
1211 $file = $fs->create_file_from_pathname($file_record, $_FILES[$elname]['tmp_name']);
1212 $info = $browser->get_file_info($context, $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename());
1213 $ret = array('url'=>$info->get_url(),'id'=>$itemid, 'file'=>$file->get_filename());
1214 return $ret;
1215}
1216
8dcd5deb 1217/**
1218 * TODO: write comment
1219 */
a6600395 1220final class repository_instance_form extends moodleform {
4a65c39a 1221 protected $instance;
1222 protected $plugin;
1223
8dcd5deb 1224 /**
1225 * TODO: write comment
1226 * @global <type> $CFG
1227 */
4a65c39a 1228 public function definition() {
1229 global $CFG;
1230 // type of plugin, string
1231 $this->plugin = $this->_customdata['plugin'];
27051e43 1232 $this->typeid = $this->_customdata['typeid'];
faaa613d 1233 $this->contextid = $this->_customdata['contextid'];
4a65c39a 1234 $this->instance = (isset($this->_customdata['instance'])
1235 && is_subclass_of($this->_customdata['instance'], 'repository'))
1236 ? $this->_customdata['instance'] : null;
1237
1238 $mform =& $this->_form;
1239 $strrequired = get_string('required');
1240
1241 $mform->addElement('hidden', 'edit', ($this->instance) ? $this->instance->id : 0);
1242 $mform->addElement('hidden', 'new', $this->plugin);
1243 $mform->addElement('hidden', 'plugin', $this->plugin);
27051e43 1244 $mform->addElement('hidden', 'typeid', $this->typeid);
faaa613d 1245 $mform->addElement('hidden', 'contextid', $this->contextid);
4a65c39a 1246
1247 $mform->addElement('text', 'name', get_string('name'), 'maxlength="100" size="30"');
1248 $mform->addRule('name', $strrequired, 'required', null, 'client');
1249
1e97f196 1250 if (!$this->instance->readonly) {
1251 //add fields
1252 if (!$this->instance) {
1253 $result = repository_static_function($this->plugin, 'instance_config_form', $mform);
1254 } else {
1255 $result = $this->instance->instance_config_form($mform);
1256 }
1257
1258 // and set the data if we have some.
1259 if ($this->instance) {
1260 $data = array();
1261 $data['name'] = $this->instance->name;
1262 foreach ($this->instance->get_instance_option_names() as $config) {
1263 if (!empty($this->instance->$config)) {
1264 $data[$config] = $this->instance->$config;
1265 } else {
1266 $data[$config] = '';
1267 }
27051e43 1268 }
1e97f196 1269 $this->set_data($data);
4a65c39a 1270 }
4a65c39a 1271 }
1e97f196 1272 else {
1273 if ($this->instance) {
1274 $data = array();
1275 $data['name'] = $this->instance->name;
1276 $this->set_data($data);
1277 }
1278 }
1279
46dd6bb0 1280 $this->add_action_buttons(true, get_string('save','repository'));
4a65c39a 1281 }
1282
8dcd5deb 1283 /**
1284 * TODO: write comment
1285 * @global <type> $DB
1286 * @param <type> $data
1287 * @return <type>
1288 */
4a65c39a 1289 public function validation($data) {
1290 global $DB;
1291
1292 $errors = array();
27051e43 1293 if ($DB->count_records('repository_instances', array('name' => $data['name'], 'typeid' => $data['typeid'])) > 1) {
4a65c39a 1294 $errors = array('name' => get_string('err_uniquename', 'repository'));
1295 }
1296
1297 $pluginerrors = array();
1298 if ($this->instance) {
1299 //$pluginerrors = $this->instance->admin_config_validation($data);
1300 } else {
1301 //$pluginerrors = repository_static_function($this->plugin, 'admin_config_validation', $data);
1302 }
1303 if (is_array($pluginerrors)) {
1304 $errors = array_merge($errors, $pluginerrors);
1305 }
1306 return $errors;
1307 }
1308}
a6600395 1309
1310
1311/**
1312 * Display a form with the general option fields of a type
1313 */
c295f9ff 1314final class repository_type_form extends moodleform {
a6600395 1315 protected $instance;
1316 protected $plugin;
1317
1318 /**
1319 * Definition of the moodleform
1320 * @global object $CFG
1321 */
1322 public function definition() {
1323 global $CFG;
1324 // type of plugin, string
1325 $this->plugin = $this->_customdata['plugin'];
1326 $this->instance = (isset($this->_customdata['instance'])
1327 && is_a($this->_customdata['instance'], 'repository_type'))
1328 ? $this->_customdata['instance'] : null;
1329
1330 $mform =& $this->_form;
1331 $strrequired = get_string('required');
4d5948f1 1332
a6600395 1333 $mform->addElement('hidden', 'edit', ($this->instance) ? $this->instance->get_typename() : 0);
1334 $mform->addElement('hidden', 'new', $this->plugin);
1335 $mform->addElement('hidden', 'plugin', $this->plugin);
06e65e1e 1336 // let the plugin add its specific fields
1337 if (!$this->instance) {
daff8f50 1338 $result = repository_static_function($this->plugin, 'type_config_form', $mform);
a6600395 1339 } else {
7a3b93c1 1340 $classname = 'repository_' . $this->instance->get_typename();
daff8f50 1341 $result = call_user_func(array($classname,'type_config_form'),$mform);
a6600395 1342 }
1343
1344 // and set the data if we have some.
1345 if ($this->instance) {
1346 $data = array();
1b79955a 1347 $option_names = call_user_func(array($classname,'get_type_option_names'));
a6600395 1348 $instanceoptions = $this->instance->get_options();
1349 foreach ($option_names as $config) {
1350 if (!empty($instanceoptions[$config])) {
1351 $data[$config] = $instanceoptions[$config];
1352 } else {
1353 $data[$config] = '';
1354 }
1355 }
1356 $this->set_data($data);
1357 }
46dd6bb0 1358 $this->add_action_buttons(true, get_string('save','repository'));
a6600395 1359 }
a6600395 1360}
1361
1362
1363/**
1364 * Display a repository instance list (with edit/delete/create links)
1365 * @global object $CFG
1366 * @global object $USER
1367 * @param object $context the context for which we display the instance
a6600395 1368 * @param string $typename if set, we display only one type of instance
1369 */
7a3b93c1 1370function repository_display_instances_list($context, $typename = null) {
1371 global $CFG, $USER;
2a06d06e 1372
7a3b93c1 1373 $output = print_box_start('generalbox','',true);
1374 //if the context is SYSTEM, so we call it from administration page
1375 $admin = ($context->id == SYSCONTEXTID) ? true : false;
1376 if ($admin) {
1377 $baseurl = $CFG->httpswwwroot . '/admin/repositoryinstance.php?sesskey=' . sesskey();
1378 $output .= "<div ><h2 style='text-align: center'>" . get_string('siteinstances', 'repository') . " ";
1379 $output .= "</h2></div>";
1380 } else {
1381 $baseurl = $CFG->httpswwwroot . '/repository/manage_instances.php?contextid=' . $context->id . '&amp;sesskey=' . sesskey();
1382 }
1383
1384 $namestr = get_string('name');
1385 $pluginstr = get_string('plugin', 'repository');
1386 $settingsstr = get_string('settings');
1387 $deletestr = get_string('delete');
1388 $updown = get_string('updown', 'repository');
1389 $plugins = get_list_of_plugins('repository');
1390 //retrieve list of instances. In administration context we want to display all
1391 //instances of a type, even if this type is not visible. In course/user context we
1392 //want to display only visible instances, but for every type types. The repository_get_instances()
1393 //third parameter displays only visible type.
1394 $instances = repository_get_instances(array($context),null,!$admin,$typename);
1395 $instancesnumber = count($instances);
1396 $alreadyplugins = array();
1397
1398 $table = new StdClass;
1399 $table->head = array($namestr, $pluginstr, $deletestr, $settingsstr);
1400 $table->align = array('left', 'left', 'center','center');
1401 $table->data = array();
1402
1403 $updowncount = 1;
1404
1405 foreach ($instances as $i) {
1406 $settings = '';
948c2860 1407 $delete = '';
1e97f196 1408 $settings .= '<a href="' . $baseurl . '&amp;type='.$typename.'&amp;edit=' . $i->id . '">' . $settingsstr . '</a>' . "\n";
948c2860 1409 if (!$i->readonly) {
948c2860 1410 $delete .= '<a href="' . $baseurl . '&amp;type='.$typename.'&amp;delete=' . $i->id . '">' . $deletestr . '</a>' . "\n";
1411 }
7a3b93c1 1412
1413 $type = repository_get_type_by_id($i->typeid);
1414 $table->data[] = array($i->name, $type->get_readablename(), $delete, $settings);
1415
1416 //display a grey row if the type is defined as not visible
1417 if (isset($type) && !$type->get_visible()) {
1418 $table->rowclass[] = 'dimmed_text';
1419 } else {
1420 $table->rowclass[] = '';
1421 }
1422
1423 if (!in_array($i->name, $alreadyplugins)) {
1424 $alreadyplugins[] = $i->name;
1425 }
1426 }
1427 $output .= print_table($table, true);
1428 $instancehtml = '<div>';
1429 $addable = 0;
1430
1431 //if no type is set, we can create all type of instance
1432 if (!$typename) {
1433 $instancehtml .= '<h3>';
1434 $instancehtml .= get_string('createrepository', 'repository');
1435 $instancehtml .= '</h3><ul>';
1436 foreach ($plugins as $p) {
1437 $type = repository_get_type_by_typename($p);
1438 if (!empty($type) && $type->get_visible()) {
edb50637 1439 $instanceoptionnames = repository_static_function($p, 'get_instance_option_names');
1440 if (!empty($instanceoptionnames)) {
7a3b93c1 1441 $instancehtml .= '<li><a href="'.$baseurl.'&amp;new='.$p.'">'.get_string('create', 'repository')
1442 .' "'.get_string('repositoryname', 'repository_'.$p).'" '
1443 .get_string('instance', 'repository').'</a></li>';
1444 $addable++;
1445 }
a6600395 1446 }
1447 }
7a3b93c1 1448 $instancehtml .= '</ul>';
a6600395 1449
edb50637 1450 } else {
1451 $instanceoptionnames = repository_static_function($typename, 'get_instance_option_names');
1452 if (!empty($instanceoptionnames)) { //create a unique type of instance
7a3b93c1 1453 $addable = 1;
1454 $instancehtml .= "<form action='".$baseurl."&amp;new=".$typename."' method='post'>
1455 <p style='text-align:center'><input type='submit' value='".get_string('createinstance', 'repository')."'/></p>
7892948d 1456 </form>";
edb50637 1457 }
7a3b93c1 1458 }
1459
1460 if ($addable) {
1461 $instancehtml .= '</div>';
1462 $output .= $instancehtml;
1463 }
a6600395 1464
7a3b93c1 1465 $output .= print_box_end(true);
a6600395 1466
7a3b93c1 1467 //print the list + creation links
1468 print($output);
a6600395 1469}