MDL-13766
[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
1cf56396 41/**
fca079c5 42 * This is the base class of the repository class
82669dc4 43 *
aa754fe3 44 * To use repository plugin, you need to create a new folder under repository/, named as the remote
82669dc4 45 * repository, the subclass must be defined in the name
46
47 *
48 * class repository is an abstract class, some functions must be implemented in subclass.
49 *
c9260130 50 * See an example of use of this library in repository/boxnet/repository.class.php
82669dc4 51 *
a6600395 52 * A few notes:
82669dc4 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
c425472d 61 * @package repository
82669dc4 62 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
1cf56396 63 */
19add4c0 64require_once(dirname(dirname(__FILE__)) . '/config.php');
c5704ec6 65require_once(dirname(dirname(__FILE__)).'/lib/filelib.php');
4a65c39a 66require_once(dirname(dirname(__FILE__)).'/lib/formslib.php');
1cf56396 67
a6600395 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
eb239694 78 * - when you delete a repository, all instances are deleted, and general
79 * options are also deleted from database
a6600395 80 * - When you create a type for a plugin that can't have multiple instances, a
81 * instance is automatically created.
82 */
83class repository_type {
84
85
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;
92
93
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;
102
103
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;
110
111
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;
118
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 */
2a06d06e 127 public function __construct($typename = '', $typeoptions = array(), $visible = false, $sortorder = 0){
a6600395 128 global $CFG;
129
130 //set type attributs
131 $this->_typename = $typename;
132 $this->_visible = $visible;
133 $this->_sortorder = $sortorder;
46dd6bb0 134
a6600395 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 }
148
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 }
157
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 }
165
166 /**
167 * Return general options
168 * @return array the general options
169 */
170 public function get_options(){
171 return $this->_options;
172 }
173
174 /**
175 * Return visibility
176 * @return boolean
177 */
178 public function get_visible(){
179 return $this->_visible;
180 }
181
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 }
189
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;
196
197 //check that $type has been set
198 $timmedtype = trim($this->_typename);
199 if (empty($timmedtype)) {
200 throw new repository_exception('emptytype', 'repository');
201 }
202
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 }
208
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);
218
219 //save the options in DB
220 $this->update_options();
0a6221f9 221
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 }
a6600395 231 }
232 else {
233 throw new repository_exception('existingrepository', 'repository');
234 }
235 }
236
237
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 }
247
248 foreach ($this->_options as $name => $value) {
249 set_config($name,$value,$this->_typename);
250 }
251
252 return true;
253 }
254
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;
266
267 if (!empty($visible)){
268 $this->_visible = $visible;
269 }
270 else if (!isset($this->_visible)){
271 throw new repository_exception('updateemptyvisible', 'repository');
272 }
273
274 return $DB->set_field('repository', 'visible', $this->_visible, array('type'=>$this->_typename));
275 }
276
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;
288
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 }
297
298 return $DB->set_field('repository', 'sortorder', $this->_sortorder, array('type'=>$this->_typename));
299 }
300
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();
315
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 }
324
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 }
336
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 }
346
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 }
356
357
358 /**
eb239694 359 * Delete a repository_type (general options are removed from config_plugin
360 * table, and all instances are deleted)
a6600395 361 * @global object $DB
362 * @return boolean
363 */
364 public function delete(){
365 global $DB;
46dd6bb0 366
367 //delete all instances of this type
12c79bfd 368 $instances = repository_get_instances(array(),null,false,$this->_typename);
46dd6bb0 369 foreach($instances as $instance){
370 $instance->delete();
371 }
372
eb239694 373 //delete all general options
374 foreach ($this->_options as $name => $value){
375 set_config($name, null, $this->_typename);
376 }
377
a6600395 378 return $DB->delete_records('repository', array('type' => $this->_typename));
379 }
380}
381
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 */
388function repository_get_type_by_typename($typename){
389 global $DB;
390
391 if(!$record = $DB->get_record('repository',array('type' => $typename))) {
392 return false;
393 }
394
395 return new repository_type($typename, (array)get_config($typename), $record->visible, $record->sortorder);
396}
397
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 */
404function repository_get_type_by_id($id){
405 global $DB;
406
407 if(!$record = $DB->get_record('repository',array('id' => $id))) {
408 return false;
409 }
410
411 return new repository_type($record->type, (array)get_config($record->type), $record->visible, $record->sortorder);
412}
413
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 * @return array Repository types
419 */
420function repository_get_types(){
421 global $DB;
422
423 $types = array();
424
425 if($records = $DB->get_records('repository',null,'sortorder')) {
426 foreach($records as $type) {
46dd6bb0 427 $types[] = new repository_type($type->type, (array)get_config($type->type), $type->visible, $type->sortorder);
a6600395 428 }
429 }
430
431 return $types;
432}
433
434/**
435 *TODO: write comment
436 */
437
fca079c5 438abstract class repository {
4a65c39a 439 public $id;
440 public $context;
441 public $options;
1cf56396 442
443 /**
3f24ea1e 444 * 1. Initialize context and options
445 * 2. Accept necessary parameters
446 *
8dcd5deb 447 * @param integer $repositoryid
448 * @param integer $contextid
449 * @param array $options
1cf56396 450 */
b6558c3b 451 public function __construct($repositoryid, $contextid = SITEID, $options = array()){
4a65c39a 452 $this->id = $repositoryid;
453 $this->context = get_context_instance_by_id($contextid);
454 $this->options = array();
fca079c5 455 if (is_array($options)) {
4a65c39a 456 $options = array_merge($this->get_option(), $options);
457 } else {
458 $options = $this->get_option();
459 }
b1339e98 460 $this->options = array();
4a65c39a 461 foreach ($options as $n => $v) {
462 $this->options[$n] = $v;
82669dc4 463 }
d31af46a 464 $this->name = $this->get_name();
1cf56396 465 }
466
8dcd5deb 467 /**
3f24ea1e 468 * set options for repository instance
469 *
8dcd5deb 470 * @param string $name
3f24ea1e 471 * @param mixed $value
8dcd5deb 472 */
fca079c5 473 public function __set($name, $value) {
82669dc4 474 $this->options[$name] = $value;
475 }
1cf56396 476
8dcd5deb 477 /**
3f24ea1e 478 * get options for repository instance
479 *
480 * @param string $name
481 * @return mixed
8dcd5deb 482 */
fca079c5 483 public function __get($name) {
82669dc4 484 if (array_key_exists($name, $this->options)){
485 return $this->options[$name];
486 }
487 trigger_error('Undefined property: '.$name, E_USER_NOTICE);
488 return null;
489 }
1cf56396 490
8dcd5deb 491 /**
3f24ea1e 492 * test option name
493 *
494 * @param string name
8dcd5deb 495 */
fca079c5 496 public function __isset($name) {
82669dc4 497 return isset($this->options[$name]);
1cf56396 498 }
499
8dcd5deb 500 /**
3f24ea1e 501 * Return the name of the repository class
8dcd5deb 502 * @return <type>
503 */
fca079c5 504 public function __toString() {
82669dc4 505 return 'Repository class: '.__CLASS__;
506 }
4a65c39a 507
c425472d 508 /**
3f24ea1e 509 * Download a file from a given url
510 *
8dcd5deb 511 * @global object $CFG
c425472d 512 * @param string $url the url of file
513 * @param string $file save location
3f24ea1e 514 * @return string the location of the file
b1339e98 515 * @see curl package
c425472d 516 */
bb2c046d 517 public function get_file($url, $file = '') {
c425472d 518 global $CFG;
c9260130 519 if (!file_exists($CFG->dataroot.'/temp/download')) {
520 mkdir($CFG->dataroot.'/temp/download/', 0777, true);
1e28c767 521 }
c9260130 522 if(is_dir($CFG->dataroot.'/temp/download')) {
523 $dir = $CFG->dataroot.'/temp/download/';
1e28c767 524 }
84df43de 525 if(empty($file)) {
526 $file = uniqid('repo').'_'.time().'.tmp';
527 }
528 if(file_exists($dir.$file)){
529 $file = uniqid('m').$file;
c425472d 530 }
84df43de 531 $fp = fopen($dir.$file, 'w');
532 $c = new curl;
533 $c->download(array(
534 array('url'=>$url, 'file'=>$fp)
535 ));
536 return $dir.$file;
82669dc4 537 }
1cf56396 538
1cf56396 539 /**
82669dc4 540 * Print a list or return string
541 *
542 * @param string $list
3f24ea1e 543 * @param boolean $print false, return html, otherwise, print it directly
8dcd5deb 544 * @return <type>
545 */
fca079c5 546 public function print_listing($listing = array(), $print=true) {
0f59046f 547 if(empty($listing)){
548 $listing = $this->get_listing();
549 }
fca079c5 550 if (empty($listing)) {
551 $str = '';
552 } else {
553 $count = 0;
554 $str = '<table>';
555 foreach ($listing as $v){
556 $str .= '<tr id="entry_'.$count.'">';
557 $str .= '<td><input type="checkbox" /></td>';
558 $str .= '<td>'.$v['name'].'</td>';
559 $str .= '<td>'.$v['size'].'</td>';
560 $str .= '<td>'.$v['date'].'</td>';
561 $str .= '</tr>';
562 $count++;
563 }
d1fe3452 564 $str .= '</table>';
82669dc4 565 }
fca079c5 566 if ($print){
82669dc4 567 echo $str;
568 return null;
569 } else {
570 return $str;
571 }
1cf56396 572 }
eb239694 573
574 /**
575 * TODO: write documentation here
576 * @global <type> $DB
577 * @return <type>
578 */
d31af46a 579 public function get_name(){
580 global $DB;
581 // We always verify instance id from database,
582 // so we always know repository name before init
583 // a repository, so we don't enquery repository
584 // name from database again here.
585 if (isset($this->options['name'])) {
586 return $this->options['name'];
587 } else {
588 if ( $repo = $DB->get_record('repository_instances', array('id'=>$this->id)) ) {
589 return $repo->name;
590 } else {
591 return '';
592 }
593 }
594 }
aa754fe3 595
82669dc4 596 /**
3f24ea1e 597 * Provide repository instance information for Ajax
8dcd5deb 598 * @global object $CFG
4a65c39a 599 * @return object
82669dc4 600 */
b1339e98 601 final public function ajax_info() {
4a65c39a 602 global $CFG;
603 $repo = new stdclass;
27051e43 604 $repo->id = $this->id;
d31af46a 605 $repo->name = $this->get_name();
4a65c39a 606 $repo->type = $this->options['type'];
6fe8b022 607 $repo->icon = $CFG->httpswwwroot.'/repository/'.$repo->type.'/icon.png';
4a65c39a 608 return $repo;
609 }
1cf56396 610
b1339e98 611 /**
612 * Create an instance for this plug-in
8dcd5deb 613 * @global object $CFG
614 * @global object $DB
615 * @param string $type the type of the repository
616 * @param integer $userid the user id
617 * @param object $context the context
618 * @param array $params the options for this instance
619 * @return <type>
b1339e98 620 */
621 final public static function create($type, $userid, $context, $params) {
622 global $CFG, $DB;
623 $params = (array)$params;
624 require_once($CFG->dirroot . '/repository/'. $type . '/repository.class.php');
625 $classname = 'repository_' . $type;
3023078f 626 if ($repo = $DB->get_record('repository', array('type'=>$type))) {
627 $record = new stdclass;
628 $record->name = $params['name'];
629 $record->typeid = $repo->id;
630 $record->timecreated = time();
631 $record->timemodified = time();
632 $record->contextid = $context->id;
633 $record->userid = $userid;
634 $id = $DB->insert_record('repository_instances', $record);
0a6221f9 635 $options = array();
a6600395 636 if (call_user_func($classname . '::has_instance_config')) {
2a06d06e 637 $configs = call_user_func($classname . '::get_instance_option_names');
3023078f 638 foreach ($configs as $config) {
639 $options[$config] = $params[$config];
640 }
641 }
642 if (!empty($id)) {
643 unset($options['name']);
c9f9f911 644 $instance = repository_get_instance($id);
3023078f 645 $instance->set_option($options);
646 return $id;
647 } else {
648 return null;
b1339e98 649 }
b1339e98 650 } else {
651 return null;
652 }
653 }
8dcd5deb 654
82669dc4 655 /**
4a65c39a 656 * delete a repository instance
8dcd5deb 657 * @global object $DB
658 * @return <type>
82669dc4 659 */
b1339e98 660 final public function delete(){
4a65c39a 661 global $DB;
122defc5 662 $DB->delete_records('repository_instances', array('id'=>$this->id));
4a65c39a 663 return true;
664 }
8dcd5deb 665
4a65c39a 666 /**
667 * Hide/Show a repository
8dcd5deb 668 * @global object $DB
669 * @param string $hide
670 * @return <type>
4a65c39a 671 */
b1339e98 672 final public function hide($hide = 'toggle'){
4a65c39a 673 global $DB;
674 if ($entry = $DB->get_record('repository', array('id'=>$this->id))) {
675 if ($hide === 'toggle' ) {
676 if (!empty($entry->visible)) {
677 $entry->visible = 0;
678 } else {
679 $entry->visible = 1;
680 }
681 } else {
682 if (!empty($hide)) {
683 $entry->visible = 0;
684 } else {
685 $entry->visible = 1;
686 }
687 }
688 return $DB->update_record('repository', $entry);
689 }
690 return false;
691 }
1cf56396 692
693 /**
82669dc4 694 * Cache login details for repositories
8dcd5deb 695 * @global object $DB
82669dc4 696 * @param string $username
697 * @param string $password
8dcd5deb 698 * @param integer $userid The id of specific user
699 * @return integer Id of the record
1cf56396 700 */
b6558c3b 701 public function store_login($username = '', $password = '', $userid = 1) {
fca079c5 702 global $DB;
703
704 $repository = new stdclass;
4a65c39a 705 if (!empty($this->id)) {
706 $repository->id = $this->id;
19add4c0 707 } else {
708 $repository->userid = $userid;
709 $repository->repositorytype = $this->type;
b6558c3b 710 $repository->contextid = $this->context->id;
19add4c0 711 }
fca079c5 712 if ($entry = $DB->get_record('repository', $repository)) {
713 $repository->id = $entry->id;
714 $repository->username = $username;
715 $repository->password = $password;
716 return $DB->update_record('repository', $repository);
717 } else {
718 $repository->username = $username;
719 $repository->password = $password;
720 return $DB->insert_record('repository', $repository);
721 }
1cf56396 722 }
723
1cf56396 724 /**
4a65c39a 725 * Save settings for repository instance
8dcd5deb 726 * $repo->set_option(array('api_key'=>'f2188bde132', 'name'=>'dongsheng'));
727 * @global object $DB
728 * @param array $options settings
4a65c39a 729 * @return int Id of the record
1cf56396 730 */
4a65c39a 731 public function set_option($options = array()){
732 global $DB;
122defc5 733 if (!empty($options['name'])) {
734 $r = new object();
735 $r->id = $this->id;
736 $r->name = $options['name'];
737 $DB->update_record('repository_instances', $r);
738 unset($options['name']);
739 }
27051e43 740 foreach ($options as $name=>$value) {
741 if ($id = $DB->get_field('repository_instance_config', 'id', array('name'=>$name, 'instanceid'=>$this->id))) {
742 if ($value===null) {
743 return $DB->delete_records('repository_instance_config', array('name'=>$name, 'instanceid'=>$this->id));
744 } else {
745 return $DB->set_field('repository_instance_config', 'value', $value, array('id'=>$id));
746 }
747 } else {
748 if ($value===null) {
749 return true;
750 }
751 $config = new object();
752 $config->instanceid = $this->id;
753 $config->name = $name;
754 $config->value = $value;
755 return $DB->insert_record('repository_instance_config', $config);
756 }
4a65c39a 757 }
27051e43 758 return true;
1cf56396 759 }
1cf56396 760
4a65c39a 761 /**
762 * Get settings for repository instance
8dcd5deb 763 * @global object $DB
764 * @param <type> $config
4a65c39a 765 * @return array Settings
766 */
767 public function get_option($config = ''){
768 global $DB;
27051e43 769 $entries = $DB->get_records('repository_instance_config', array('instanceid'=>$this->id));
770 $ret = array();
771 if (empty($entries)) {
772 return $ret;
4a65c39a 773 }
27051e43 774 foreach($entries as $entry){
775 $ret[$entry->name] = $entry->value;
4a65c39a 776 }
777 if (!empty($config)) {
778 return $ret[$config];
779 } else {
780 return $ret;
781 }
782 }
bf1fccf0 783
4a65c39a 784 /**
785 * Given a path, and perhaps a search, get a list of files.
786 *
e6be3a69 787 * The format of the returned array must be:
f7639c37 788 * array(
f6812a21 789 * 'path' => (string) path for the current folder
f7639c37 790 * 'dynload' => (bool) use dynamic loading,
f6812a21 791 * 'manage' => (string) link to file manager,
f7639c37 792 * 'nologin' => (bool) requires login,
d31af46a 793 * 'nosearch' => (bool) no search link,
f7639c37 794 * 'upload' => array( // upload manager
795 * 'name' => (string) label of the form element,
796 * 'id' => (string) id of the form element
797 * ),
798 * 'list' => array(
799 * array( // file
800 * 'title' => (string) file name,
3c9e53c0 801 * 'date' => (string) file last modification time, usually userdate(...),
f6812a21 802 * 'size' => (int) file size,
3c9e53c0 803 * 'thumbnail' => (string) url to thumbnail for the file,
336bb44b 804 * 'source' => plugin-dependent unique path to the file (id, url, path, etc.),
805 * 'url'=> the accessible url of file
f7639c37 806 * ),
3c9e53c0 807 * array( // folder - same as file, but no 'source'.
f7639c37 808 * 'title' => (string) folder name,
f6812a21 809 * 'path' => (string) path to this folder
3c9e53c0 810 * 'date' => (string) folder last modification time, usually userdate(...),
f6812a21 811 * 'size' => 0,
3c9e53c0 812 * 'thumbnail' => (string) url to thumbnail for the folder,
813 * 'children' => array( // an empty folder needs to have 'children' defined, but empty.
814 * // content (files and folders)
f7639c37 815 * )
e6be3a69 816 * ),
f7639c37 817 * )
818 * )
819 *
4a65c39a 820 * @param string $parent The parent path, this parameter can
821 * a folder name, or a identification of folder
822 * @param string $search The text will be searched.
823 * @return array the list of files, including meta infomation
824 */
825 abstract public function get_listing($parent = '/', $search = '');
1cf56396 826
1cf56396 827
4a65c39a 828 /**
829 * Show the login screen, if required
830 * This is an abstract function, it must be overriden.
4a65c39a 831 */
832 abstract public function print_login();
1cf56396 833
4a65c39a 834 /**
835 * Show the search screen, if required
4a65c39a 836 * @return null
837 */
838 abstract public function print_search();
839
455860ce 840 /**
841 * is it possible to do glboal search?
842 * @return boolean
843 */
844 public function global_search(){
845 return false;
846 }
847
8dcd5deb 848 /**
a6600395 849 * Defines operations that happen occasionally on cron
8dcd5deb 850 * @return <type>
851 */
a6600395 852 public function cron() {
853 return true;
854 }
855
856 /**
857 * Return true if the plugin type has at least one general option field
858 * By default: false
859 * @return boolean
860 */
4a65c39a 861 public static function has_admin_config() {
862 return false;
863 }
864
a6600395 865 /**
866 * Return true if a plugin instance has at least one config field
867 * By default: false
868 * @return boolean
869 */
870 public static function has_instance_config() {
871 return false;
872 }
4a65c39a 873
874 /**
a6600395 875 * Return true if the plugin can have multiple instances
876 * By default: false
877 * @return boolean
4a65c39a 878 */
a6600395 879 public static function has_multiple_instances(){
880 return false;
881 }
882
883 /**
884 * Return names of the general options
885 * By default: no general option name
886 * @return array
887 */
888 public static function get_admin_option_names(){
889 return array();
890 }
891
892 /**
893 * Return names of the instance options
894 * By default: no instance option name
895 * @return array
896 */
897 public static function get_instance_option_names(){
898 return array();
8b65d45c 899 }
8b65d45c 900}
837ebb78 901
902/**
4a65c39a 903 * exception class for repository api
837ebb78 904 */
4a65c39a 905class repository_exception extends moodle_exception {
8b65d45c 906}
4ed43890 907
2057487c 908/**
909 * Check context
910 * @param int $ctx_id
911 * @return boolean
912 */
913function repository_check_context($ctx_id){
914 global $USER;
915 $context = get_context_instance_by_id($ctx_id);
916 $level = $context->contextlevel;
917 if ($level == CONTEXT_COURSE) {
918 if (!has_capability('moodle/course:view', $context)) {
919 return false;
920 } else {
921 return true;
922 }
923 } elseif ($level == CONTEXT_USER) {
924 $c = get_context_instance(CONTEXT_USER, $USER->id);
925 if ($c->id == $ctx_id) {
926 return true;
927 } else {
928 return false;
929 }
930 } elseif ($level == CONTEXT_SYSTEM) {
931 // it is always ok in system level
70fbd90e 932 return true;
2057487c 933 }
934 return false;
935}
4a65c39a 936
837ebb78 937/**
4a65c39a 938 * Return repository instances
8dcd5deb 939 * @global object $DB
940 * @global object $CFG
941 * @global object $USER
12c79bfd 942 * @param object $contexts contexts for which the instances are set
8dcd5deb 943 * @param integer $userid
46dd6bb0 944 * @param boolean $onlyvisible if visible == true, return visible instances only,
4a65c39a 945 * otherwise, return all instances
a6600395 946 * @param string $type a type name to retrieve
4a65c39a 947 * @return array repository instances
837ebb78 948 */
12c79bfd 949function repository_get_instances($contexts=array(), $userid = null, $onlyvisible = true, $type=null){
38e55442 950 global $DB, $CFG, $USER;
38e55442 951 $params = array();
1265fc59 952 $sql = 'SELECT i.*, r.type AS repositorytype, r.sortorder, r.visible FROM {repository} r, {repository_instances} i WHERE ';
46dd6bb0 953 $sql .= 'i.typeid = r.id ';
4a65c39a 954 if (!empty($userid) && is_numeric($userid)) {
46dd6bb0 955 $sql .= ' AND (i.userid = 0 or i.userid = ?)';
4a65c39a 956 $params[] = $userid;
957 }
12c79bfd 958 foreach ($contexts as $context) {
959 if (empty($firstcontext)){
960 $firstcontext = true;
961 $sql .= ' AND ((i.contextid = ?)';
46dd6bb0 962 } else {
12c79bfd 963 $sql .= ' OR (i.contextid = ?)';
46dd6bb0 964 }
12c79bfd 965 $params[] = $context->id;
38e55442 966 }
12c79bfd 967 if ($firstcontext) {
968 $sql .=')';
969 }
aca64b79 970
46dd6bb0 971 if($onlyvisible == true) {
4a65c39a 972 $sql .= ' AND (r.visible = 1)';
973 }
a6600395 974 if(isset($type)) {
975 $sql .= ' AND (r.type = ?)';
976 $params[] = $type;
977 }
1265fc59 978 $sql .= ' order by r.sortorder, i.name';
38e55442 979 if(!$repos = $DB->get_records_sql($sql, $params)) {
980 $repos = array();
981 }
4a65c39a 982 $ret = array();
983 foreach($repos as $repo) {
e6be3a69 984 require_once($CFG->dirroot . '/repository/'. $repo->repositorytype
4a65c39a 985 . '/repository.class.php');
27051e43 986 $options['visible'] = $repo->visible;
987 $options['name'] = $repo->name;
988 $options['type'] = $repo->repositorytype;
989 $options['typeid'] = $repo->typeid;
4a65c39a 990 $classname = 'repository_' . $repo->repositorytype;
27051e43 991 $ret[] = new $classname($repo->id, $repo->contextid, $options);
4a65c39a 992 }
993 return $ret;
38e55442 994}
4ed43890 995
837ebb78 996/**
997 * Get single repository instance
8dcd5deb 998 * @global object $DB
999 * @global object $CFG
1000 * @param integer $id repository id
837ebb78 1001 * @return object repository instance
1002 */
c9f9f911 1003function repository_get_instance($id){
19add4c0 1004 global $DB, $CFG;
27051e43 1005 $sql = 'SELECT i.*, r.type AS repositorytype, r.visible FROM {repository} r, {repository_instances} i WHERE ';
1006 $sql .= 'i.typeid = r.id AND ';
1007 $sql .= 'i.id = '.$id;
19add4c0 1008
27051e43 1009 if(!$instance = $DB->get_record_sql($sql)) {
19add4c0 1010 return false;
1011 }
e6be3a69 1012 require_once($CFG->dirroot . '/repository/'. $instance->repositorytype
19add4c0 1013 . '/repository.class.php');
1014 $classname = 'repository_' . $instance->repositorytype;
27051e43 1015 $options['typeid'] = $instance->typeid;
1016 $options['type'] = $instance->repositorytype;
1017 $options['name'] = $instance->name;
1018 return new $classname($instance->id, $instance->contextid, $options);
19add4c0 1019}
837ebb78 1020
8dcd5deb 1021/**
1022 * TODO: write documentation
1023 * @global <type> $CFG
1024 * @param <type> $plugin
1025 * @param <type> $function
a6600395 1026 * @param type $nocallablereturnvalue default value if function not found
1027 * it's mostly used when you don't want to display an error but
1028 * return a boolean
8dcd5deb 1029 * @return <type>
1030 */
4a65c39a 1031function repository_static_function($plugin, $function) {
97f7393d 1032 global $CFG;
4a65c39a 1033
a6600395 1034 //check that the plugin exists
1035 $typedirectory = $CFG->dirroot . '/repository/'. $plugin . '/repository.class.php';
1036 if (!file_exists($typedirectory)) {
1037 throw new repository_exception('invalidplugin', 'repository');
1038 }
1039
4a65c39a 1040 $pname = null;
1041 if (is_object($plugin) || is_array($plugin)) {
1042 $plugin = (object)$plugin;
1043 $pname = $plugin->name;
1044 } else {
1045 $pname = $plugin;
97f7393d 1046 }
4a65c39a 1047
1048 $args = func_get_args();
1049 if (count($args) <= 2) {
1050 $args = array();
1051 }
1052 else {
1053 array_shift($args);
1054 array_shift($args);
1055 }
1056
a6600395 1057 require_once($typedirectory);
4a65c39a 1058 return call_user_func_array(array('repository_' . $plugin, $function), $args);
97f7393d 1059}
d8eb6e18 1060
837ebb78 1061/**
1062 * Move file from download folder to file pool using FILE API
b1339e98 1063 * @TODO Need review
8dcd5deb 1064 * @global object $DB
1065 * @global object $CFG
1066 * @global object $USER
1067 * @param string $path file path in download folder
1068 * @param string $name file name
1069 * @param integer $itemid item id to identify a file in filepool
1070 * @param string $filearea file area
837ebb78 1071 * @return array information of file in file pool
1072 */
c9260130 1073function repository_move_to_filepool($path, $name, $itemid, $filearea = 'user_draft') {
d8eb6e18 1074 global $DB, $CFG, $USER;
1075 $context = get_context_instance(CONTEXT_USER, $USER->id);
313cc398 1076 $now = time();
d8eb6e18 1077 $entry = new object();
55b4bb1d 1078 $entry->filearea = $filearea;
d8eb6e18 1079 $entry->contextid = $context->id;
1080 $entry->filename = $name;
c9260130 1081 $entry->filepath = '/'.uniqid().'/';
313cc398 1082 $entry->timecreated = $now;
1083 $entry->timemodified = $now;
c2762f06 1084 if(is_numeric($itemid)) {
1085 $entry->itemid = $itemid;
1086 } else {
1087 $entry->itemid = 0;
1088 }
d8eb6e18 1089 $entry->mimetype = mimeinfo('type', $path);
1090 $entry->userid = $USER->id;
1091 $fs = get_file_storage();
1092 $browser = get_file_browser();
1093 if ($file = $fs->create_file_from_pathname($entry, $path)) {
c9260130 1094 $delete = unlink($path);
d8eb6e18 1095 $ret = $browser->get_file_info($context, $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename());
3023078f 1096 if(!empty($ret)){
c0fa8cba 1097 return array('url'=>$ret->get_url(),'id'=>$file->get_itemid(), 'file'=>$file->get_filename());
3023078f 1098 } else {
1099 return null;
1100 }
d8eb6e18 1101 } else {
1102 return null;
1103 }
1104}
1105
5a3b9db9 1106/**
1107 * Save file to local filesystem pool
1108 * @param string $elname name of element
5a3b9db9 1109 * @param string $filearea
1110 * @param string $filepath
1111 * @param string $filename - use specified filename, if not specified name of uploaded file used
1112 * @param bool $override override file if exists
5a3b9db9 1113 * @return mixed stored_file object or false if error; may throw exception if duplicate found
1114 */
313cc398 1115function repository_store_to_filepool($elname, $filearea='user_draft', $filepath='/', $filename = '', $override = false) {
5a3b9db9 1116 global $USER;
1117 if (!isset($_FILES[$elname])) {
1118 return false;
1119 }
1120
313cc398 1121 if (!$filename) {
1122 $filename = $_FILES[$elname]['name'];
1123 }
5a3b9db9 1124 $context = get_context_instance(CONTEXT_USER, $USER->id);
1125 $itemid = (int)substr(hexdec(uniqid()), 0, 9)+rand(1,100);
1126 $fs = get_file_storage();
1127 $browser = get_file_browser();
1128
1129 if ($file = $fs->get_file($context->id, $filearea, $itemid, $filepath, $filename)) {
1130 if ($override) {
1131 $file->delete();
1132 } else {
1133 return false;
1134 }
1135 }
1136
1137 $file_record = new object();
1138 $file_record->contextid = $context->id;
1139 $file_record->filearea = $filearea;
1140 $file_record->itemid = $itemid;
1141 $file_record->filepath = $filepath;
1142 $file_record->filename = $filename;
1143 $file_record->userid = $USER->id;
1144
1145 $file = $fs->create_file_from_pathname($file_record, $_FILES[$elname]['tmp_name']);
1146 $info = $browser->get_file_info($context, $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename());
1147 $ret = array('url'=>$info->get_url(),'id'=>$itemid, 'file'=>$file->get_filename());
1148 return $ret;
1149}
1150
837ebb78 1151/**
1152 * Return javascript to create file picker to browse repositories
8dcd5deb 1153 * @global object $CFG
1154 * @global object $USER
1155 * @param object $context the context
e6be3a69 1156 * @return array
837ebb78 1157 */
49a1ce19 1158function repository_get_client($context){
f3a6f85b 1159 global $CFG, $USER;
c2762f06 1160 $suffix = uniqid();
0eaa8c5c 1161 $sesskey = sesskey();
336bb44b 1162 $strsaveas = get_string('saveas', 'repository').': ';
a347291c 1163 $stradd = get_string('add', 'repository');
c5704ec6 1164 $strback = get_string('back', 'repository');
d0b5d122 1165 $strcancel = get_string('cancel');
c5704ec6 1166 $strclose = get_string('close', 'repository');
aae85978 1167 $strccache = get_string('cleancache', 'repository');
b82bcbcb 1168 $strcopying = get_string('copying', 'repository');
55b4bb1d 1169 $strdownbtn = get_string('getfile', 'repository');
64be2d6c 1170 $strdownload = get_string('downloadsucc', 'repository');
a347291c 1171 $strdate = get_string('date', 'repository').': ';
1172 $strerror = get_string('error', 'repository');
9ccfe7aa 1173 $strfilenotnull = get_string('filenotnull', 'repository');
7dfb3c1c 1174 $strrefresh = get_string('refresh', 'repository');
a347291c 1175 $strinvalidjson = get_string('invalidjson', 'repository');
1176 $strlistview = get_string('listview', 'repository');
1177 $strlogout = get_string('logout', 'repository');
1178 $strloading = get_string('loading', 'repository');
1179 $strthumbview = get_string('thumbview', 'repository');
1180 $strtitle = get_string('title', 'repository');
ae8d6f23 1181 $strmgr = get_string('manageurl', 'repository');
64be2d6c 1182 $strnoenter = get_string('noenter', 'repository');
a347291c 1183 $strsave = get_string('save', 'repository');
1184 $strsaved = get_string('saved', 'repository');
1185 $strsaving = get_string('saving', 'repository');
1186 $strsize = get_string('size', 'repository').': ';
1187 $strsync = get_string('sync', 'repository');
1188 $strsearch = get_string('search', 'repository');
64be2d6c 1189 $strsearching = get_string('searching', 'repository');
a347291c 1190 $strsubmit = get_string('submit', 'repository');
8a1d4a46 1191 $strpreview = get_string('preview', 'repository');
a347291c 1192 $strupload = get_string('upload', 'repository');
1193 $struploading = get_string('uploading', 'repository');
d373f63f 1194 $css = <<<EOD
19f1d262 1195<style type="text/css">
efd47773 1196.repo-list{list-style-type:none;padding:0}
1197.repo-list li{border-bottom:1px dotted gray;margin-bottom: 1em;}
70fbd90e 1198.repo-name{display:block;padding: 3px;margin-bottom: 5px}
efd47773 1199.paging{margin:10px 5px; clear:both;}
1200.paging a{padding: 4px;border: 1px solid #CCC}
1201.repo-path{margin: 4px;border-bottom: 1px dotted gray;}
1202.repo-path a{padding: 4px;}
1203.rename-form{text-align:center}
1204.rename-form p{margin: 1em;}
1205.upload-form{margin: 2em 0;text-align:center}
1206p.upload a{font-size: 14px;background: #ccc;color:white;padding: 5px}
19f1d262 1207p.upload a:hover {background: grey;color:white}
1208.file_name{color:green;}
1209.file_date{color:blue}
1210.file_size{color:gray}
1211.grid{width:80px; float:left;text-align:center;}
336bb44b 1212.grid div{width: 80px; overflow: hidden}
ede057f3 1213.grid p{margin:0;padding:0;background: #FFFFCC}
1214.grid .label{height:48px}
1215.grid span{background: #EEF9EB;color:gray}
efd47773 1216#panel-$suffix{padding:0;margin:0; text-align:left;}
1217#file-picker-$suffix{font-size:12px;}
056995f2 1218#file-picker-$suffix strong{background:#FFFFCC}
ede057f3 1219#file-picker-$suffix a{color: #336699}
1220#file-picker-$suffix a:hover{background:#003366;color:white}
455860ce 1221#repo-viewbar-$suffix{width:300px;float:left}
1222#search-div-$suffix{float:right}
7dfb3c1c 1223#repo-tb-$suffix{padding: .8em;background: #FFFFCC;color:white;text-align:center}
19f1d262 1224</style>
1225<style type="text/css">
6fe8b022 1226@import "$CFG->httpswwwroot/lib/yui/resize/assets/skins/sam/resize.css";
1227@import "$CFG->httpswwwroot/lib/yui/container/assets/skins/sam/container.css";
1228@import "$CFG->httpswwwroot/lib/yui/layout/assets/skins/sam/layout.css";
1229@import "$CFG->httpswwwroot/lib/yui/button/assets/skins/sam/button.css";
1230@import "$CFG->httpswwwroot/lib/yui/assets/skins/sam/treeview.css";
19f1d262 1231</style>
d373f63f 1232EOD;
1233
1234 $js = <<<EOD
6fe8b022 1235<script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/yahoo-dom-event/yahoo-dom-event.js"></script>
1236<script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/element/element-beta-min.js"></script>
1237<script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/treeview/treeview-min.js"></script>
1238<script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/dragdrop/dragdrop-min.js"></script>
1239<script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/container/container-min.js"></script>
1240<script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/resize/resize-beta-min.js"></script>
1241<script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/layout/layout-beta-min.js"></script>
1242<script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/connection/connection-min.js"></script>
1243<script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/json/json-min.js"></script>
1244<script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/button/button-min.js"></script>
1245<script type="text/javascript" src="$CFG->httpswwwroot/lib/yui/selector/selector-beta-min.js"></script>
19f1d262 1246<script type="text/javascript">
de57d6f5 1247//<![CDATA[
cf493e89 1248var active_instance = null;
1249function repository_callback(id){
1250 active_instance.req(id, '', 0);
1251}
19f1d262 1252var repository_client_$suffix = (function() {
1253// private static field
1254var dver = '1.0';
1255// private static methods
1256function alert_version(){
1257 alert(dver);
1258}
1259function _client(){
1260 // public varible
1261 this.name = 'repository_client_$suffix';
1262 // private varible
1263 var Dom = YAHOO.util.Dom, Event = YAHOO.util.Event, layout = null, resize = null;
1264 var IE_QUIRKS = (YAHOO.env.ua.ie && document.compatMode == "BackCompat");
1265 var IE_SYNC = (YAHOO.env.ua.ie == 6 || (YAHOO.env.ua.ie == 7 && IE_QUIRKS));
1266 var PANEL_BODY_PADDING = (10*2);
1267 var btn_list = {label: '$strlistview', value: 'l', checked: true, onclick: {fn: _client.viewlist}};
1268 var btn_thumb = {label: '$strthumbview', value: 't', onclick: {fn: _client.viewthumb}};
1269 var repo_list = null;
1270 var resize = null;
1271 var panel = new YAHOO.widget.Panel('file-picker-$suffix', {
1272 draggable: true,
1273 close: true,
1274 modal: true,
1275 underlay: 'none',
19f1d262 1276 zindex: 666666,
1277 xy: [50, Dom.getDocumentScrollTop()+20]
1278 });
1279 // construct code section
1280 {
1281 panel.setHeader('$strtitle');
1282 panel.setBody('<div id="layout-$suffix"></div>');
1283 panel.beforeRenderEvent.subscribe(function() {
1284 Event.onAvailable('layout-$suffix', function() {
1285 layout = new YAHOO.widget.Layout('layout-$suffix', {
70fbd90e 1286 height: 480, width: 630,
19f1d262 1287 units: [
e6be3a69 1288 {position: 'top', height: 32, resize: false,
455860ce 1289 body:'<div class="yui-buttongroup" id="repo-viewbar-$suffix"></div><div id="search-div-$suffix"></div>', gutter: '2'},
70fbd90e 1290 {position: 'left', width: 200, resize: true,
7dfb3c1c 1291 body:'<ul class="repo-list" id="repo-list-$suffix"></ul>', gutter: '0 5 0 2', minWidth: 150, maxWidth: 300 },
e6be3a69 1292 {position: 'center', body: '<div id="panel-$suffix"></div>',
19f1d262 1293 scroll: true, gutter: '0 2 0 0' }
1294 ]
c5704ec6 1295 });
19f1d262 1296 layout.render();
1297 });
1298 });
1299 resize = new YAHOO.util.Resize('file-picker-$suffix', {
1300 handles: ['br'],
1301 autoRatio: true,
1302 status: true,
1303 minWidth: 380,
1304 minHeight: 400
1305 });
1306 resize.on('resize', function(args) {
1307 var panelHeight = args.height;
1308 var headerHeight = this.header.offsetHeight; // Content + Padding + Border
1309 var bodyHeight = (panelHeight - headerHeight);
1310 var bodyContentHeight = (IE_QUIRKS) ? bodyHeight : bodyHeight - PANEL_BODY_PADDING;
1311 Dom.setStyle(this.body, 'height', bodyContentHeight + 'px');
1312 if (IE_SYNC) {
1313 this.sizeUnderlay();
1314 this.syncIframe();
c5704ec6 1315 }
19f1d262 1316 layout.set('height', bodyContentHeight);
1317 layout.set('width', (args.width - PANEL_BODY_PADDING));
1318 layout.resize();
1319
1320 }, panel, true);
1321 _client.viewbar = new YAHOO.widget.ButtonGroup({
1322 id: 'btngroup-$suffix',
1323 name: 'buttons',
1324 disabled: true,
1325 container: 'repo-viewbar-$suffix'
1326 });
1327 }
1328 // public method
1329 this.show = function(){
1330 panel.show();
1331 }
1332 this.hide = function(){
1333 panel.hide();
1334 }
1335 this.create_picker = function(){
1336 // display UI
1337 panel.render();
1338 _client.viewbar.addButtons([btn_list, btn_thumb]);
1339 // init repository list
1340 repo_list = new YAHOO.util.Element('repo-list-$suffix');
1341 repo_list.on('contentReady', function(e){
aae85978 1342 var searchbar = new YAHOO.util.Element('search-div-$suffix');
7dfb3c1c 1343 searchbar.get('element').innerHTML = '<input id="search-input-$suffix" /><button id="search-btn-$suffix">$strsearch</button>';
aae85978 1344 var searchbtn = new YAHOO.util.Element('search-btn-$suffix');
1345 searchbtn.callback = {
1346 success: function(o) {
1347 var panel = new YAHOO.util.Element('panel-$suffix');
1348 try {
1349 if(!o.responseText){
1350 var panel = new YAHOO.util.Element('panel-$suffix');
1351 panel.get('element').innerHTML = 'no';
1352 return;
1353 }
1354 var json = YAHOO.lang.JSON.parse(o.responseText);
1355 } catch(e) {
1356 alert('$strinvalidjson - '+o.responseText);
1357 }
1358 _client.ds = {};
1359 if(!json.list || json.list.length<1){
1360 var panel = new YAHOO.util.Element('panel-$suffix');
1361 panel.get('element').innerHTML = 'no';
1362 return;
1363 }
1364 _client.ds.list = json.list;
1365 if(_client.ds.list) {
1366 if(_client.viewmode) {
1367 _client.viewthumb();
1368 } else {
1369 _client.viewlist();
1370 }
1371 var input_ctl = new YAHOO.util.Element('search-input-$suffix');
1372 input_ctl.get('element').value='';
1373 }
1374 }
1375 }
1376 searchbtn.input_ctl = new YAHOO.util.Element('search-input-$suffix');
1377 searchbtn.on('click', function(e){
1378 var keyword = this.input_ctl.get('value');
1379 var params = [];
1380 params['s'] = keyword;
1381 params['env']=_client.env;
1382 params['action']='gsearch';
1383 params['sesskey']='$sesskey';
1384 params['ctx_id']=$context->id;
1385 _client.loading('load');
1386 var trans = YAHOO.util.Connect.asyncRequest('POST',
1387 '$CFG->httpswwwroot/repository/ws.php?action=gsearch', this.callback, _client.postdata(params));
1388 });
19f1d262 1389 for(var i=0; i<_client.repos.length; i++) {
1390 var repo = _client.repos[i];
c145b657 1391 var li = document.createElement('li');
19f1d262 1392 li.id = 'repo-$suffix-'+repo.id;
1393 var icon = document.createElement('img');
1394 icon.src = repo.icon;
1395 icon.width = '16';
1396 icon.height = '16';
19f1d262 1397 var link = document.createElement('a');
1398 link.href = '###';
1399 link.id = 'repo-call-$suffix-'+repo.id;
70fbd90e 1400 link.appendChild(icon);
19f1d262 1401 link.className = 'repo-name';
1402 link.onclick = function(){
1403 var re = /repo-call-$suffix-(\d+)/i;
1404 var id = this.id.match(re);
c0fa8cba 1405 repository_client_$suffix.req(id[1], '', 0);
19f1d262 1406 }
70fbd90e 1407 link.innerHTML += ' '+repo.name;
19f1d262 1408 li.appendChild(link);
19f1d262 1409 this.appendChild(li);
1410 repo = null;
e1f29368 1411 }
19f1d262 1412 });
1413 }
1414}
1415
1416// public static varible
1417_client.repos = [];
1418_client.repositoryid = 0;
1419// _client.ds save all data received from server side
e6be3a69 1420_client.ds = null;
19f1d262 1421_client.viewmode = 0;
1422_client.viewbar =null;
1423
1424// public static mehtod
1425_client.postdata = function(obj) {
1426 var str = '';
1427 for(k in obj) {
1428 if(obj[k] instanceof Array) {
1429 for(i in obj[k]) {
1430 str += (encodeURIComponent(k) +'[]='+encodeURIComponent(obj[k][i]));
1431 str += '&';
c5704ec6 1432 }
19f1d262 1433 } else {
1434 str += encodeURIComponent(k) +'='+encodeURIComponent(obj[k]);
1435 str += '&';
c5704ec6 1436 }
19f1d262 1437 }
1438 return str;
1439}
b82bcbcb 1440_client.loading = function(type, name){
19f1d262 1441 var panel = new YAHOO.util.Element('panel-$suffix');
1442 panel.get('element').innerHTML = '';
1443 var content = document.createElement('div');
b82bcbcb 1444 content.style.textAlign='center';
1445 var para = document.createElement('P');
1446 var img = document.createElement('IMG');
1447 if(type=='load'){
1448 img.src = '$CFG->pixpath/i/loading.gif';
1449 para.innerHTML = '$strloading';
1450 }else{
1451 img.src = '$CFG->pixpath/i/progressbar.gif';
056995f2 1452 para.innerHTML = '$strcopying <strong>'+name+'</strong>';
b82bcbcb 1453 }
1454 content.appendChild(para);
1455 content.appendChild(img);
1456 //content.innerHTML = '';
19f1d262 1457 panel.get('element').appendChild(content);
1458}
d05ef4a3 1459_client.rename = function(oldname, url, icon, repo_id){
19f1d262 1460 var panel = new YAHOO.util.Element('panel-$suffix');
efd47773 1461 var html = '<div class="rename-form">';
d05ef4a3 1462 _client.repositoryid=repo_id;
a67af354 1463 html += '<p><img src="'+icon+'" /></p>';
336bb44b 1464 html += '<p><label for="newname-$suffix">$strsaveas</label>';
1465 html += '<input type="text" id="newname-$suffix" value="'+oldname+'" /></p>';
a67af354 1466 /**
0eaa8c5c 1467 html += '<p><label for="syncfile-$suffix">$strsync</label> ';
336bb44b 1468 html += '<input type="checkbox" id="syncfile-$suffix" /></p>';
a67af354 1469 */
336bb44b 1470 html += '<p><input type="hidden" id="fileurl-$suffix" value="'+url+'" />';
19f1d262 1471 html += '<a href="###" onclick="repository_client_$suffix.viewfiles()">$strback</a> ';
b748c971 1472 html += '<input type="button" onclick="repository_client_$suffix.download()" value="$strdownbtn" />';
d0b5d122 1473 html += '<input type="button" onclick="repository_client_$suffix.hide()" value="$strcancel" /></p>';
19f1d262 1474 html += '</div>';
1475 panel.get('element').innerHTML = html;
1476}
cf493e89 1477_client.popup = function(url){
1478 active_instance = repository_client_$suffix;
1479 _client.win = window.open(url,'repo_auth', 'location=0,status=0,scrollbars=0,width=500,height=300');
1480 return false;
1481}
19f1d262 1482_client.print_login = function(){
1483 var panel = new YAHOO.util.Element('panel-$suffix');
1484 var data = _client.ds.login;
1485 var str = '';
1486 for(var k in data){
1487 str += '<p>';
cf493e89 1488 if(data[k].type=='popup'){
1489 str += '<a href="###" onclick="repository_client_$suffix.popup(\''+data[k].url+'\')">test</a>';
1490 }else{
1491 var lable_id = '';
1492 var field_id = '';
1493 var field_value = '';
1494 if(data[k].id){
1495 lable_id = ' for="'+data[k].id+'"';
1496 field_id = ' id="'+data[k].id+'"';
1497 }
1498 if (data[k].label) {
1499 str += '<label'+lable_id+'>'+data[k].label+'</label><br/>';
1500 }
1501 if(data[k].value){
1502 field_value = ' value="'+data[k].value+'"';
1503 }
1504 str += '<input type="'+data[k].type+'"'+' name="'+data[k].name+'"'+field_id+field_value+' />';
c5704ec6 1505 }
19f1d262 1506 str += '</p>';
1507 }
1508 str += '<p><input type="button" onclick="repository_client_$suffix.login()" value="$strsubmit" /></p>';
1509 panel.get('element').innerHTML = str;
1510}
c5704ec6 1511
19f1d262 1512_client.viewfiles = function(){
1513 if(_client.viewmode) {
1514 _client.viewthumb();
1515 } else {
1516 _client.viewlist();
1517 }
1518}
7dfb3c1c 1519_client.print_header = function(){
c0fa8cba 1520 var panel = new YAHOO.util.Element('panel-$suffix');
7dfb3c1c 1521 var str = '';
1522 str += '<div id="repo-tb-$suffix"></div>';
1523 str += _client.uploadcontrol();
1524 panel.set('innerHTML', str);
c0fa8cba 1525 _client.makepath();
19f1d262 1526}
7dfb3c1c 1527_client.print_footer = function(){
1528 var panel = new YAHOO.util.Element('panel-$suffix');
1529 panel.get('element').innerHTML += _client.makepage();
1530 panel.get('element').innerHTML += _client.uploadcontrol();
1531 var oDiv = document.getElementById('repo-tb-$suffix');
1532 if(!_client.ds.nosearch){
1533 var search = document.createElement('A');
1534 search.href = '###';
1535 search.innerHTML = '<img src="$CFG->pixpath/a/search.png" /> $strsearch';
1536 oDiv.appendChild(search);
1537 search.onclick = function() {
1538 repository_client_$suffix.search(repository_client_$suffix.repositoryid);
1539 }
1540 }
1541 // weather we use cache for this instance, this button will reload listing anyway
1542 var ccache = document.createElement('A');
1543 ccache.href = '###';
1544 ccache.innerHTML = '<img src="$CFG->pixpath/a/refresh.png" /> $strrefresh';
1545 oDiv.appendChild(ccache);
1546 ccache.onclick = function() {
1547 var params = [];
1548 params['env']=_client.env;
1549 params['sesskey']='$sesskey';
1550 params['ctx_id']=$context->id;
1551 params['repo_id']=repository_client_$suffix.repositoryid;
1552 _client.loading('load');
1553 var trans = YAHOO.util.Connect.asyncRequest('POST',
1554 '$CFG->httpswwwroot/repository/ws.php?action=ccache', repository_client_$suffix.req_cb, _client.postdata(params));
1555 }
1556 if(_client.ds.manage){
1557 var mgr = document.createElement('A');
1558 mgr.innerHTML = '<img src="$CFG->pixpath/a/setting.png" /> $strmgr';
1559 mgr.href = _client.ds.manage;
1560 mgr.target = "_blank";
1561 oDiv.appendChild(mgr);
1562 }
1563 if(!_client.ds.nologin){
1564 var logout = document.createElement('A');
1565 logout.href = '###';
1566 logout.innerHTML = '<img src="$CFG->pixpath/a/logout.png" /> $strlogout';
1567 oDiv.appendChild(logout);
1568 logout.onclick = function() {
1569 repository_client_$suffix.req(repository_client_$suffix.repositoryid, 1, 1);
1570 }
1571 }
1572}
0291df49 1573_client.viewthumb = function(ds){
c0fa8cba 1574 _client.viewmode = 1;
19f1d262 1575 var panel = new YAHOO.util.Element('panel-$suffix');
1576 _client.viewbar.check(1);
0291df49 1577 var list = null;
1578 var args = arguments.length;
1579 if(args == 1){
1580 list = ds;
1581 } else {
1582 // from button
1583 list = _client.ds.list;
1584 }
7dfb3c1c 1585 _client.print_header();
0291df49 1586 var count = 0;
19f1d262 1587 for(k in list){
1588 var el = document.createElement('div');
1589 el.className='grid';
c145b657 1590 var frame = document.createElement('DIV');
1591 frame.style.textAlign='center';
19f1d262 1592 var img = document.createElement('img');
1593 img.src = list[k].thumbnail;
c0fa8cba 1594 var link = document.createElement('A');
1595 link.href='###';
1596 link.id = 'img-id-'+String(count);
1597 link.appendChild(img);
1598 frame.appendChild(link);
19f1d262 1599 var title = document.createElement('div');
336bb44b 1600 if(list[k].children){
1601 title.innerHTML = '<i><u>'+list[k].title+'</i></u>';
1602 } else {
8a1d4a46 1603 if(list[k].url)
1604 title.innerHTML = '<p><a target="_blank" href="'+list[k].url+'">$strpreview</a></p>';
ede057f3 1605 title.innerHTML += '<span>'+list[k].title+"</span>";
336bb44b 1606 }
1607 title.className = 'label';
c145b657 1608 el.appendChild(frame);
19f1d262 1609 el.appendChild(title);
1610 panel.get('element').appendChild(el);
0291df49 1611 if(list[k].children){
7dfb3c1c 1612 var folder = new YAHOO.util.Element(link.id);
1613 folder.ds = list[k].children;
1614 folder.on('contentReady', function(){
1615 this.on('click', function(){
1616 if(_client.ds.dynload){
1617 // TODO: get file list dymanically
1618 }else{
1619 _client.viewthumb(this.ds);
1620 }
1621 });
0291df49 1622 });
1623 } else {
7dfb3c1c 1624 var file = new YAHOO.util.Element(link.id);
1625 file.title = list[k].title;
1626 file.value = list[k].source;
1627 file.icon = list[k].thumbnail;
772de6c7 1628 if(list[k].repo_id){
7dfb3c1c 1629 file.repo_id = list[k].repo_id;
772de6c7 1630 }else{
7dfb3c1c 1631 file.repo_id = _client.repositoryid;
772de6c7 1632 }
7dfb3c1c 1633 file.on('contentReady', function(){
1634 this.on('click', function(){
1635 repository_client_$suffix.rename(this.title, this.value, this.icon, this.repo_id);
1636 });
c0fa8cba 1637 });
0291df49 1638 }
1639 count++;
19f1d262 1640 }
7dfb3c1c 1641 _client.print_footer();
19f1d262 1642}
1643_client.buildtree = function(node, level){
19a10884 1644 if(node.children){
1645 node.title = '<i><u>'+node.title+'</u></i>';
1646 }
e6be3a69 1647 var info = {label:node.title, title:"$strdate"+node.date+' '+'$strsize'+node.size};
1648 var tmpNode = new YAHOO.widget.TextNode(info, level, false);
19f1d262 1649 var tooltip = new YAHOO.widget.Tooltip(tmpNode.labelElId, {
1650 context:tmpNode.labelElId, text:info.title});
d05ef4a3 1651 if(node.repo_id){
1652 tmpNode.repo_id=node.repo_id;
1653 }else{
1654 tmpNode.repo_id=_client.repositoryid;
1655 }
19f1d262 1656 tmpNode.filename = node.title;
1657 tmpNode.value = node.source;
a67af354 1658 tmpNode.icon = node.thumbnail;
19f1d262 1659 if(node.children){
1660 tmpNode.isLeaf = false;
19f1d262 1661 if (node.path) {
1662 tmpNode.path = node.path;
1663 } else {
1664 tmpNode.path = '';
d373f63f 1665 }
19f1d262 1666 for(var c in node.children){
1667 _client.buildtree(node.children[c], tmpNode);
c5704ec6 1668 }
19f1d262 1669 } else {
1670 tmpNode.isLeaf = true;
1671 tmpNode.onLabelClick = function() {
d05ef4a3 1672 repository_client_$suffix.rename(this.filename, this.value, this.icon, this.repo_id);
d373f63f 1673 }
19f1d262 1674 }
1675}
d373f63f 1676_client.dynload = function (node, fnLoadComplete){
1677 var callback = {
1678 success: function(o) {
1679 try {
1680 var json = YAHOO.lang.JSON.parse(o.responseText);
1681 } catch(e) {
a347291c 1682 alert('$strinvalidjson - '+o.responseText);
d373f63f 1683 }
1c7bf190 1684 for(k in json.list){
1685 _client.buildtree(json.list[k], node);
1686 }
d373f63f 1687 o.argument.fnLoadComplete();
1688 },
1689 failure:function(oResponse){
a347291c 1690 alert('$strerror');
d373f63f 1691 oResponse.argument.fnLoadComplete();
1692 },
1693 argument:{"node":node, "fnLoadComplete": fnLoadComplete},
1694 timeout:600
1695 }
0eaa8c5c 1696 var params = [];
1697 params['p']=node.path;
1698 params['env']=_client.env;
1699 params['sesskey']='$sesskey';
1700 params['ctx_id']=$context->id;
1701 params['repo_id']=_client.repositoryid;
1702 var trans = YAHOO.util.Connect.asyncRequest('POST',
6fe8b022 1703 '$CFG->httpswwwroot/repository/ws.php?action=list', callback, _client.postdata(params));
d373f63f 1704}
19f1d262 1705_client.viewlist = function(){
c0fa8cba 1706 _client.viewmode = 0;
19f1d262 1707 var panel = new YAHOO.util.Element('panel-$suffix');
1708 _client.viewbar.check(0);
1709 list = _client.ds.list;
7dfb3c1c 1710 _client.print_header();
f3c5853d 1711 panel.get('element').innerHTML += '<div id="treediv-$suffix"></div>';
1712 var tree = new YAHOO.widget.TreeView('treediv-$suffix');
19f1d262 1713 if(_client.ds.dynload) {
1714 tree.setDynamicLoad(_client.dynload, 1);
1715 } else {
1716 }
1717 for(k in list){
1718 _client.buildtree(list[k], tree.getRoot());
1719 }
1720 tree.draw();
7dfb3c1c 1721 _client.print_footer();
19f1d262 1722}
1723_client.upload = function(){
1724 var u = _client.ds.upload;
19f1d262 1725 var aform = document.getElementById(u.id);
1726 var parent = document.getElementById(u.id+'_div');
9ccfe7aa 1727 var d = document.getElementById(_client.ds.upload.id+'-file');
1728 if(d.value!='' && d.value!=null){
1729 var container = document.createElement('DIV');
1730 container.id = u.id+'_loading';
1731 container.style.textAlign='center';
1732 var img = document.createElement('IMG');
1733 img.src = '$CFG->pixpath/i/progressbar.gif';
1734 var para = document.createElement('p');
1735 para.innerHTML = '$struploading';
1736 container.appendChild(para);
1737 container.appendChild(img);
1738 parent.appendChild(container);
1739 YAHOO.util.Connect.setForm(aform, true, true);
1740 var trans = YAHOO.util.Connect.asyncRequest('POST',
6fe8b022 1741 '$CFG->httpswwwroot/repository/ws.php?action=upload&sesskey=$sesskey&ctx_id=$context->id&repo_id='
9ccfe7aa 1742 +_client.repositoryid,
1743 _client.upload_cb);
1744 }else{
1745 alert('$strfilenotnull');
1746 }
19f1d262 1747}
1748_client.upload_cb = {
1749 upload: function(o){
5a3b9db9 1750 try {
1751 var ret = YAHOO.lang.JSON.parse(o.responseText);
1752 } catch(e) {
1753 alert('$strinvalidjson - '+o.responseText);
1754 }
1755 if(ret && ret.e){
1756 var panel = new YAHOO.util.Element('panel-$suffix');
1757 panel.get('element').innerHTML = ret.e;
1758 return;
1759 }
1760 if(ret){
1761 alert('$strsaved');
1762 repository_client_$suffix.end(ret);
1763 }else{
1764 alert('$strinvalidjson');
1765 }
19f1d262 1766 }
1767}
1768_client.uploadcontrol = function() {
1769 var str = '';
1770 if(_client.ds.upload){
efd47773 1771 str += '<div id="'+_client.ds.upload.id+'_div" class="upload-form">';
19f1d262 1772 str += '<form id="'+_client.ds.upload.id+'" onsubmit="return false">';
5a3b9db9 1773 str += '<label for="'+_client.ds.upload.id+'-file">'+_client.ds.upload.label+'</label>';
1774 str += '<input type="file" id="'+_client.ds.upload.id+'-file" name="repo_upload_file" />';
19f1d262 1775 str += '<p class="upload"><a href="###" onclick="return repository_client_$suffix.upload();">$strupload</a></p>';
1776 str += '</form>';
1777 str += '</div>';
19f1d262 1778 }
1779 return str;
1780}
1781_client.makepage = function(){
1782 var str = '';
1783 if(_client.ds.pages){
efd47773 1784 str += '<div class="paging" id="paging-$suffix">';
19f1d262 1785 for(var i = 1; i <= _client.ds.pages; i++) {
1786 str += '<a onclick="repository_client_$suffix.req('+_client.repositoryid+', '+i+', 0)" href="###">';
1787 str += String(i);
1788 str += '</a> ';
d373f63f 1789 }
19f1d262 1790 str += '</div>';
1791 }
1792 return str;
1793}
27051e43 1794_client.makepath = function(){
c0fa8cba 1795 if(_client.viewmode == 0) {
1796 return;
1797 }
1798 var panel = new YAHOO.util.Element('panel-$suffix');
27051e43 1799 var p = _client.ds.path;
1800 if(p && p.length!=0){
c0fa8cba 1801 var oDiv = document.createElement('DIV');
1802 oDiv.id = "path-$suffix";
efd47773 1803 oDiv.className = "repo-path";
c0fa8cba 1804 panel.get('element').appendChild(oDiv);
27051e43 1805 for(var i = 0; i < _client.ds.path.length; i++) {
31640be2 1806 var link = document.createElement('A');
1807 link.href = "###";
1808 link.innerHTML = _client.ds.path[i].name;
1809 link.id = 'path-'+i+'-el';
1810 var sep = document.createElement('SPAN');
1811 sep.innerHTML = '/';
1812 oDiv.appendChild(link);
1813 oDiv.appendChild(sep);
1814 var el = new YAHOO.util.Element(link.id);
1815 el.id = _client.repositoryid;
1816 el.path = _client.ds.path[i].path;
1817 el.on('click', function(){
1818 repository_client_$suffix.req(this.id, this.path, 0);
1819 });
27051e43 1820 }
27051e43 1821 }
27051e43 1822}
19f1d262 1823// send download request
1824_client.download = function(){
1825 var title = document.getElementById('newname-$suffix').value;
1826 var file = document.getElementById('fileurl-$suffix').value;
b82bcbcb 1827 _client.loading('download', title);
0eaa8c5c 1828 var params = [];
1829 params['env']=_client.env;
1830 params['file']=file;
1831 params['title']=title;
1832 params['sesskey']='$sesskey';
1833 params['ctx_id']=$context->id;
1834 params['repo_id']=_client.repositoryid;
e6be3a69 1835 var trans = YAHOO.util.Connect.asyncRequest('POST',
7dfb3c1c 1836 '$CFG->httpswwwroot/repository/ws.php?action=download', _client.download_cb, _client.postdata(params));
19f1d262 1837}
1838// send login request
1839_client.login = function(){
0eaa8c5c 1840 var params = [];
19f1d262 1841 var data = _client.ds.login;
1842 for (var k in data) {
7dfb3c1c 1843 if(data[k].type!='popup'){
1844 var el = document.getElementsByName(data[k].name)[0];
1845 params[data[k].name] = '';
1846 if(el.type == 'checkbox') {
1847 params[data[k].name] = el.checked;
1848 } else {
1849 params[data[k].name] = el.value;
1850 }
d373f63f 1851 }
19f1d262 1852 }
1853 params['env'] = _client.env;
1854 params['ctx_id'] = $context->id;
0eaa8c5c 1855 params['sesskey']= '$sesskey';
b82bcbcb 1856 _client.loading('load');
e6be3a69 1857 var trans = YAHOO.util.Connect.asyncRequest('POST',
7dfb3c1c 1858 '$CFG->httpswwwroot/repository/ws.php?action=sign', _client.req_cb, _client.postdata(params));
19f1d262 1859}
1860_client.end = function(str){
c0fa8cba 1861 if(_client.env=='form'){
1862 _client.target.value = str['id'];
1863 }else{
1864 _client.target.value = str['url'];
5fdb8260 1865 _client.target.onchange();
c0fa8cba 1866 }
1867 _client.formcallback(str['file']);
19f1d262 1868 _client.instance.hide();
1869 _client.viewfiles();
1870}
122defc5 1871_client.hide = function(){
1872 _client.instance.hide();
1873 _client.viewfiles();
1874}
7dfb3c1c 1875// request file list or login
1876_client.req = function(id, path, reset) {
1877 _client.viewbar.set('disabled', false);
1878 _client.loading('load');
1879 _client.repositoryid = id;
1880 if (reset == 1) {
1881 action = 'logout';
1882 } else {
1883 action = 'list';
1884 }
1885 var params = [];
1886 params['p'] = path;
1887 params['reset']=reset;
1888 params['env']=_client.env;
1889 params['action']=action;
1890 params['sesskey']='$sesskey';
1891 params['ctx_id']=$context->id;
1892 params['repo_id']=id;
1893 var trans = YAHOO.util.Connect.asyncRequest('POST', '$CFG->httpswwwroot/repository/ws.php?action='+action, _client.req_cb, _client.postdata(params));
1894}
1895_client.search = function(id){
1896 var data = window.prompt("$strsearching");
1897 if(data == '') {
1898 alert('$strnoenter');
1899 return;
1900 }else if(data == null){
1901 return;
1902 }
1903 _client.viewbar.set('disabled', false);
1904 _client.loading('load');
1905 var params = [];
1906 params['s']=data;
1907 params['env']=_client.env;
1908 params['sesskey']='$sesskey';
1909 params['ctx_id']=$context->id;
1910 params['repo_id']=id;
1911 var trans = YAHOO.util.Connect.asyncRequest('POST', '$CFG->httpswwwroot/repository/ws.php?action=search', _client.req_cb, _client.postdata(params));
1912}
1913_client.req_cb = {
19f1d262 1914 success: function(o) {
1915 var panel = new YAHOO.util.Element('panel-$suffix');
1916 try {
1917 var ret = YAHOO.lang.JSON.parse(o.responseText);
1918 } catch(e) {
1919 alert('$strinvalidjson - '+o.responseText);
1920 };
c145b657 1921 if(ret && ret.e){
19f1d262 1922 panel.get('element').innerHTML = ret.e;
1923 return;
d373f63f 1924 }
19f1d262 1925 _client.ds = ret;
7dfb3c1c 1926 if(!_client.ds){
1927 return;
1928 }else if(_client.ds && _client.ds.login){
19f1d262 1929 _client.print_login();
1930 } else if(_client.ds.list) {
1931 if(_client.viewmode) {
1932 _client.viewthumb();
1933 } else {
1934 _client.viewlist();
c5704ec6 1935 }
c5704ec6 1936 }
19f1d262 1937 }
1938}
7dfb3c1c 1939_client.download_cb = {
19f1d262 1940 success: function(o) {
1941 var panel = new YAHOO.util.Element('panel-$suffix');
1942 try {
1943 var ret = YAHOO.lang.JSON.parse(o.responseText);
1944 } catch(e) {
1945 alert('$strinvalidjson - '+o.responseText);
c5704ec6 1946 }
c145b657 1947 if(ret && ret.e){
19f1d262 1948 panel.get('element').innerHTML = ret.e;
1949 return;
1950 }
3023078f 1951 if(ret){
1952 repository_client_$suffix.end(ret);
1953 }else{
1954 alert('$strinvalidjson');
1955 }
19f1d262 1956 }
1957}
19f1d262 1958
1959return _client;
1960})();
c5704ec6 1961EOD;
1962
12c79bfd 1963 $repos = repository_get_instances(array($context,get_system_context()));
c5704ec6 1964 foreach($repos as $repo) {
4b844d63 1965 $js .= "\r\n";
4a65c39a 1966 $js .= 'repository_client_'.$suffix.'.repos.push('.json_encode($repo->ajax_info()).');'."\n";
c5704ec6 1967 }
4b844d63 1968 $js .= "\r\n";
c5704ec6 1969
1970 $js .= <<<EOD
b748c971 1971function openpicker_$suffix(params) {
1972 if(!repository_client_$suffix.instance) {
1973 repository_client_$suffix.env = params.env;
1974 repository_client_$suffix.target = params.target;
c0fa8cba 1975 if(params.type){
1976 repository_client_$suffix.filetype = params.filetype;
1977 } else {
1978 repository_client_$suffix.filetype = 'all';
1979 }
b748c971 1980 repository_client_$suffix.instance = new repository_client_$suffix();
1981 repository_client_$suffix.instance.create_picker();
1982 if(params.callback){
1983 repository_client_$suffix.formcallback = params.callback;
c5704ec6 1984 } else {
b748c971 1985 repository_client_$suffix.formcallback = function(){};
c5704ec6 1986 }
b748c971 1987 } else {
1988 repository_client_$suffix.instance.show();
c5704ec6 1989 }
b748c971 1990}
de57d6f5 1991//]]>
1992</script>
c5704ec6 1993EOD;
d373f63f 1994 return array('css'=>$css, 'js'=>$js, 'suffix'=>$suffix);
c5704ec6 1995}
4a65c39a 1996
8dcd5deb 1997/**
1998 * TODO: write comment
1999 */
a6600395 2000final class repository_instance_form extends moodleform {
4a65c39a 2001 protected $instance;
2002 protected $plugin;
2003
8dcd5deb 2004 /**
2005 * TODO: write comment
2006 * @global <type> $CFG
2007 */
4a65c39a 2008 public function definition() {
2009 global $CFG;
2010 // type of plugin, string
2011 $this->plugin = $this->_customdata['plugin'];
27051e43 2012 $this->typeid = $this->_customdata['typeid'];
faaa613d 2013 $this->contextid = $this->_customdata['contextid'];
4a65c39a 2014 $this->instance = (isset($this->_customdata['instance'])
2015 && is_subclass_of($this->_customdata['instance'], 'repository'))
2016 ? $this->_customdata['instance'] : null;
2017
2018 $mform =& $this->_form;
2019 $strrequired = get_string('required');
2020
2021 $mform->addElement('hidden', 'edit', ($this->instance) ? $this->instance->id : 0);
2022 $mform->addElement('hidden', 'new', $this->plugin);
2023 $mform->addElement('hidden', 'plugin', $this->plugin);
27051e43 2024 $mform->addElement('hidden', 'typeid', $this->typeid);
faaa613d 2025 $mform->addElement('hidden', 'contextid', $this->contextid);
4a65c39a 2026
2027 $mform->addElement('text', 'name', get_string('name'), 'maxlength="100" size="30"');
2028 $mform->addRule('name', $strrequired, 'required', null, 'client');
2029
2030 // let the plugin add the fields they want (either statically or not)
a6600395 2031 if (repository_static_function($this->plugin, 'has_instance_config')) {
4a65c39a 2032 if (!$this->instance) {
a6600395 2033 $result = repository_static_function($this->plugin, 'instance_config_form', $mform);
4a65c39a 2034 } else {
a6600395 2035 $result = $this->instance->instance_config_form($mform);
4a65c39a 2036 }
2037 }
2038
2039 // and set the data if we have some.
2040 if ($this->instance) {
2041 $data = array();
2042 $data['name'] = $this->instance->name;
a6600395 2043 foreach ($this->instance->get_instance_option_names() as $config) {
27051e43 2044 if (!empty($this->instance->$config)) {
2045 $data[$config] = $this->instance->$config;
2046 } else {
2047 $data[$config] = '';
2048 }
4a65c39a 2049 }
2050 $this->set_data($data);
2051 }
46dd6bb0 2052 $this->add_action_buttons(true, get_string('save','repository'));
4a65c39a 2053 }
2054
8dcd5deb 2055 /**
2056 * TODO: write comment
2057 * @global <type> $DB
2058 * @param <type> $data
2059 * @return <type>
2060 */
4a65c39a 2061 public function validation($data) {
2062 global $DB;
2063
2064 $errors = array();
27051e43 2065 if ($DB->count_records('repository_instances', array('name' => $data['name'], 'typeid' => $data['typeid'])) > 1) {
4a65c39a 2066 $errors = array('name' => get_string('err_uniquename', 'repository'));
2067 }
2068
2069 $pluginerrors = array();
2070 if ($this->instance) {
2071 //$pluginerrors = $this->instance->admin_config_validation($data);
2072 } else {
2073 //$pluginerrors = repository_static_function($this->plugin, 'admin_config_validation', $data);
2074 }
2075 if (is_array($pluginerrors)) {
2076 $errors = array_merge($errors, $pluginerrors);
2077 }
2078 return $errors;
2079 }
2080}
a6600395 2081
2082
2083/**
2084 * Display a form with the general option fields of a type
2085 */
2086final class repository_admin_form extends moodleform {
2087 protected $instance;
2088 protected $plugin;
2089
2090 /**
2091 * Definition of the moodleform
2092 * @global object $CFG
2093 */
2094 public function definition() {
2095 global $CFG;
2096 // type of plugin, string
2097 $this->plugin = $this->_customdata['plugin'];
2098 $this->instance = (isset($this->_customdata['instance'])
2099 && is_a($this->_customdata['instance'], 'repository_type'))
2100 ? $this->_customdata['instance'] : null;
2101
2102 $mform =& $this->_form;
2103 $strrequired = get_string('required');
4d5948f1 2104
a6600395 2105 $mform->addElement('hidden', 'edit', ($this->instance) ? $this->instance->get_typename() : 0);
2106 $mform->addElement('hidden', 'new', $this->plugin);
2107 $mform->addElement('hidden', 'plugin', $this->plugin);
a6600395 2108 // let the plugin add the fields they want (either statically or not)
2109 if (repository_static_function($this->plugin, 'has_admin_config')) {
2110 if (!$this->instance) {
2111 $result = repository_static_function($this->plugin, 'admin_config_form', $mform);
2112 } else {
2113 $classname = 'repository_' . $this->instance->get_typename();
2114 $result = call_user_func(array($classname,'admin_config_form'),$mform);
2115 }
2116 }
2117
2118 // and set the data if we have some.
2119 if ($this->instance) {
2120 $data = array();
2121 $option_names = call_user_func(array($classname,'get_admin_option_names'));
2122 $instanceoptions = $this->instance->get_options();
2123 foreach ($option_names as $config) {
2124 if (!empty($instanceoptions[$config])) {
2125 $data[$config] = $instanceoptions[$config];
2126 } else {
2127 $data[$config] = '';
2128 }
2129 }
2130 $this->set_data($data);
2131 }
46dd6bb0 2132 $this->add_action_buttons(true, get_string('save','repository'));
a6600395 2133 }
2134
2135}
2136
2137
2138/**
2139 * Display a repository instance list (with edit/delete/create links)
2140 * @global object $CFG
2141 * @global object $USER
2142 * @param object $context the context for which we display the instance
a6600395 2143 * @param string $typename if set, we display only one type of instance
2144 */
faaa613d 2145function repository_display_instances_list($context, $typename = null){
a6600395 2146 global $CFG, $USER;
4d5948f1 2147
faaa613d 2148 $output = print_box_start('generalbox','',true);
2149 //if the context is SYSTEM, so we call it from administration page
2150 $admin = ($context->id == SYSCONTEXTID) ? true : false;
2151 if($admin) {
6fe8b022 2152 $baseurl = $CFG->httpswwwroot . '/admin/repositoryinstance.php?sesskey=' . sesskey();
4d5948f1 2153 $output .= "<div ><h2 style='text-align: center'>" . get_string('siteinstances', 'repository') . " ";
faaa613d 2154 $output .= "</h2></div>";
2155 } else {
6fe8b022 2156 $baseurl = $CFG->httpswwwroot . '/repository/manage_instances.php?contextid=' . $context->id . '&amp;sesskey=' . sesskey();
a6600395 2157
faaa613d 2158 }
12c79bfd 2159
a6600395 2160 $namestr = get_string('name');
2161 $pluginstr = get_string('plugin', 'repository');
4d5948f1 2162 $settingsstr = get_string('settings');
2163 $deletestr = get_string('delete');
a6600395 2164 $updown = get_string('updown', 'repository');
2165 $plugins = get_list_of_plugins('repository');
2a06d06e 2166 //retrieve list of instances. In administration context we want to display all
faaa613d 2167 //instances of a type, even if this type is not visible. In course/user context we
2168 //want to display only visible instances, but for every type types. The repository_get_instances()
aca64b79 2169 //third parameter displays only visible type.
12c79bfd 2170 $instances = repository_get_instances(array($context),null,!$admin,$typename);
a6600395 2171 $instancesnumber = count($instances);
2172 $alreadyplugins = array();
2173 $table = new StdClass;
4d5948f1 2174 $table->head = array($namestr, $pluginstr, $deletestr, $settingsstr);
2175 $table->align = array('left', 'left', 'center','center');
a6600395 2176 $table->data = array();
2177 $updowncount=1;
2178 foreach ($instances as $i) {
4d5948f1 2179 $settings = '';
2180 $settings .= '<a href="' . $baseurl . '&amp;type='.$typename.'&amp;edit=' . $i->id . '">' . $settingsstr . '</a>' . "\n";
2181 $delete = '<a href="' . $baseurl . '&amp;type='.$typename.'&amp;delete=' . $i->id . '">' . $deletestr . '</a>' . "\n";
2182
faaa613d 2183 $type = repository_get_type_by_id($i->typeid);
4d5948f1 2184 $table->data[] = array($i->name, $type->get_readablename(), $delete, $settings);
2185
2a06d06e 2186 //display a grey row if the type is defined as not visible
2187 if (isset($type) && !$type->get_visible()){
2188 $table->rowclass[] = 'dimmed_text';
2189 } else{
2190 $table->rowclass[] = '';
2191 }
2192
a6600395 2193 if (!in_array($i->name, $alreadyplugins)) {
2194 $alreadyplugins[] = $i->name;
2195 }
2196 }
2197 $output .= print_table($table, true);
4d5948f1 2198 $instancehtml = '<div>';
a6600395 2199 $addable = 0;
2200
2201 //if no type is set, we can create all type of instance
2202 if (!$typename) {
4d5948f1 2203 $instancehtml .= '<h3>';
2204 $instancehtml .= get_string('createrepository', 'repository');
2205 $instancehtml .= '</h3><ul>';
a6600395 2206 foreach ($plugins as $p) {
faaa613d 2207 $type = repository_get_type_by_typename($p);
aca64b79 2208 if (!empty($type) && $type->get_visible()) {
faaa613d 2209 if (repository_static_function($p, 'has_multiple_instances')){
2210 $instancehtml .= '<li><a href="'.$baseurl.'&amp;new='.$p.'">'.get_string('create', 'repository')
2211 .' "'.get_string('repositoryname', 'repository_'.$p).'" '
2212 .get_string('instance', 'repository').'</a></li>';
2213 $addable++;
2214 }
2215 }
a6600395 2216 }
4d5948f1 2217 $instancehtml .= '</ul>';
a6600395 2218 }
2219 //create a unique type of instance
2220 else {
2221 if (repository_static_function($typename, 'has_multiple_instances')){
2a06d06e 2222 $addable = 1;
4d5948f1 2223 $instancehtml .= "<form action='".$baseurl."&amp;new=".$typename."' method='post'>
2224 <p style='text-align:center'><input type='submit' value='".get_string('createinstance', 'repository')."'/></p>
2225 </form>";
a6600395 2226 }
2227 }
2228
a6600395 2229 if ($addable) {
2230 $instancehtml .= '</div>';
2231 $output .= $instancehtml;
2232 }
2233
faaa613d 2234 $output .= print_box_end(true);
a6600395 2235
2236 //print the list + creation links
2237 print($output);
a6600395 2238}