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