See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * This plugin is used to access flickr pictures 19 * 20 * @since Moodle 2.0 21 * @package repository_flickr_public 22 * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 require_once($CFG->dirroot . '/repository/lib.php'); 26 require_once($CFG->libdir.'/flickrlib.php'); 27 require_once (__DIR__ . '/image.php'); 28 29 /** 30 * repository_flickr_public class 31 * This one is used to create public repository 32 * You can set up a public account in admin page, so everyone can access 33 * flickr photos from this plugin 34 * 35 * @since Moodle 2.0 36 * @package repository_flickr_public 37 * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} 38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 39 */ 40 class repository_flickr_public extends repository { 41 private $flickr; 42 public $photos; 43 44 /** 45 * Stores sizes of images to prevent multiple API call 46 */ 47 static private $sizes = array(); 48 49 /** 50 * constructor method 51 * 52 * @global object $CFG 53 * @global object $SESSION 54 * @param int $repositoryid 55 * @param int $context 56 * @param array $options 57 * @param boolean $readonly 58 */ 59 public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array(), $readonly=0) { 60 global $CFG, $SESSION; 61 parent::__construct($repositoryid, $context, $options,$readonly); 62 $this->api_key = $this->get_option('api_key'); 63 $this->flickr = new phpFlickr($this->api_key); 64 $this->flickr_account = $this->get_option('email_address'); 65 $this->usewatermarks = $this->get_option('usewatermarks'); 66 67 $account = optional_param('flickr_account', '', PARAM_RAW); 68 $fulltext = optional_param('flickr_fulltext', '', PARAM_RAW); 69 if (empty($fulltext)) { 70 $fulltext = optional_param('s', '', PARAM_RAW); 71 } 72 $tag = optional_param('flickr_tag', '', PARAM_RAW); 73 $license = optional_param('flickr_license', '', PARAM_RAW); 74 75 $this->sess_account = 'flickr_public_'.$this->id.'_account'; 76 $this->sess_tag = 'flickr_public_'.$this->id.'_tag'; 77 $this->sess_text = 'flickr_public_'.$this->id.'_text'; 78 79 if (!empty($account) or !empty($fulltext) or !empty($tag) or !empty($license)) { 80 $SESSION->{$this->sess_tag} = $tag; 81 $SESSION->{$this->sess_text} = $fulltext; 82 $SESSION->{$this->sess_account} = $account; 83 } 84 } 85 86 /** 87 * save api_key in config table 88 * @param array $options 89 * @return boolean 90 */ 91 public function set_option($options = array()) { 92 if (!empty($options['api_key'])) { 93 set_config('api_key', trim($options['api_key']), 'flickr_public'); 94 } 95 unset($options['api_key']); 96 return parent::set_option($options); 97 } 98 99 /** 100 * get api_key from config table 101 * 102 * @param string $config 103 * @return mixed 104 */ 105 public function get_option($config = '') { 106 if ($config==='api_key') { 107 return trim(get_config('flickr_public', 'api_key')); 108 } else { 109 $options['api_key'] = trim(get_config('flickr_public', 'api_key')); 110 } 111 return parent::get_option($config); 112 } 113 114 /** 115 * is global_search available? 116 * 117 * @return boolean 118 */ 119 public function global_search() { 120 if (empty($this->flickr_account)) { 121 return false; 122 } else { 123 return true; 124 } 125 } 126 127 /** 128 * check if flickr account 129 * @return boolean 130 */ 131 public function check_login() { 132 return !empty($this->flickr_account); 133 } 134 135 /** 136 * construct login form 137 * 138 * @param boolean $ajax 139 * @return array 140 */ 141 public function print_login() { 142 if ($this->options['ajax']) { 143 $ret = array(); 144 $fulltext = new stdClass(); 145 $fulltext->label = get_string('fulltext', 'repository_flickr_public').': '; 146 $fulltext->id = 'el_fulltext'; 147 $fulltext->type = 'text'; 148 $fulltext->name = 'flickr_fulltext'; 149 150 $tag = new stdClass(); 151 $tag->label = get_string('tag', 'repository_flickr_public').': '; 152 $tag->id = 'el_tag'; 153 $tag->type = 'text'; 154 $tag->name = 'flickr_tag'; 155 156 $email_field = new stdClass(); 157 $email_field->label = get_string('username', 'repository_flickr_public').': '; 158 $email_field->id = 'account'; 159 $email_field->type = 'text'; 160 $email_field->name = 'flickr_account'; 161 162 $commercial = new stdClass(); 163 $commercial->label = get_string('commercialuse', 'repository_flickr_public').': '; 164 $commercial->id = 'flickr_commercial_id'; 165 $commercial->type = 'checkbox'; 166 $commercial->name = 'flickr_commercial'; 167 $commercial->value = 'yes'; 168 169 $modification = new stdClass(); 170 $modification->label = get_string('modification', 'repository_flickr_public').': '; 171 $modification->id = 'flickr_modification_id'; 172 $modification->type = 'checkbox'; 173 $modification->name = 'flickr_modification'; 174 $modification->value = 'yes'; 175 176 $ret['login'] = array($fulltext, $tag, $email_field, $commercial, $modification); 177 $ret['login_btn_label'] = get_string('search'); 178 $ret['login_btn_action'] = 'search'; 179 return $ret; 180 } else { 181 echo '<table>'; 182 echo '<tr><td><label>'.get_string('fulltext', 'repository_flickr_public').'</label></td>'; 183 echo '<td><input type="text" name="flickr_fulltext" /></td></tr>'; 184 echo '<tr><td><label>'.get_string('tag', 'repository_flickr_public').'</label></td>'; 185 echo '<td><input type="text" name="flickr_tag" /></td></tr>'; 186 echo '<tr><td><label>'.get_string('username', 'repository_flickr_public').'</label></td>'; 187 echo '<td><input type="text" name="flickr_account" /></td></tr>'; 188 189 echo '<tr><td><label>'.get_string('commercialuse', 'repository_flickr_public').'</label></td>'; 190 echo '<td>'; 191 echo '<input type="checkbox" name="flickr_commercial" value="yes" />'; 192 echo '</td></tr>'; 193 194 echo '<tr><td><label>'.get_string('modification', 'repository_flickr_public').'</label></td>'; 195 echo '<td>'; 196 echo '<input type="checkbox" name="flickr_modification" value="yes" />'; 197 echo '</td></tr>'; 198 199 echo '</table>'; 200 201 echo '<input type="hidden" name="action" value="search" />'; 202 echo '<input type="submit" value="'.get_string('search', 'repository').'" />'; 203 } 204 } 205 206 /** 207 * destroy session 208 * 209 * @return object 210 */ 211 public function logout() { 212 global $SESSION; 213 unset($SESSION->{$this->sess_tag}); 214 unset($SESSION->{$this->sess_text}); 215 unset($SESSION->{$this->sess_account}); 216 return $this->print_login(); 217 } 218 219 public function license4moodle ($license_id) { 220 $license = array( 221 '0' => 'allrightsreserved', 222 '1' => 'cc-nc-sa', 223 '2' => 'cc-nc', 224 '3' => 'cc-nc-nd', 225 '4' => 'cc', 226 '5' => 'cc-sa', 227 '6' => 'cc-nd', 228 '7' => 'other' 229 ); 230 return $license[$license_id]; 231 } 232 233 /** 234 * search images on flickr 235 * 236 * @param string $search_text 237 * @return array 238 */ 239 public function search($search_text, $page = 0) { 240 global $SESSION; 241 $ret = array(); 242 if (empty($page)) { 243 $page = 1; 244 } 245 246 if (!empty($this->flickr_account)) { 247 $people = $this->flickr->people_findByEmail($this->flickr_account); 248 $this->nsid = $people['nsid']; 249 } 250 if (!empty($SESSION->{$this->sess_account})) { 251 $people = $this->flickr->people_findByEmail($SESSION->{$this->sess_account}); 252 $this->nsid = $people['nsid']; 253 } 254 if (empty($this->nsid)) { 255 $this->nsid = null; 256 // user specify a flickr account, but it is not valid 257 if (!empty($this->flickr_account) or !empty($SESSION->{$this->sess_account})) { 258 $ret['e'] = get_string('invalidemail', 'repository_flickr_public'); 259 return $ret; 260 } 261 } 262 263 // including all licenses by default 264 $licenses = array(1=>1, 2, 3, 4, 5, 6, 7); 265 266 $commercial = optional_param('flickr_commercial', '', PARAM_RAW); 267 $modification = optional_param('flickr_modification', '', PARAM_RAW); 268 269 if ($commercial == 'yes') { 270 // including 271 // 4: Attribution License 272 // 5: Attribution ShareAlike 273 // 6: Attribution NoDerives 274 // 7: unknown license 275 unset($licenses[1], $licenses[2], $licenses[3]); 276 } 277 if ($modification == 'yes') { 278 // including 279 // 1: Attribution NonCommercial ShareAlike 280 // 2: Attribution NonCommercial 281 // 4: Attribution License 282 // 5: Attribution ShareAlike 283 // 7: unknown license 284 unset($licenses[3], $licenses[6]); 285 } 286 //if ($modification == 'sharealike') { 287 // including 288 // 1: Attribution NonCommercial ShareAlike 289 // 5: Attribution ShareAlike 290 //unset($licenses[2], $licenses[3], $licenses[4], $licenses[6], $licenses[7]); 291 //} 292 293 $licenses = implode(',', $licenses); 294 295 $tag = !empty($SESSION->{$this->sess_tag}) ? $SESSION->{$this->sess_tag} : null; 296 $text = !empty($SESSION->{$this->sess_text}) ? $SESSION->{$this->sess_text} : null; 297 $nsid = !empty($this->nsid) ? $this->nsid : null; 298 299 $photos = $this->flickr->photos_search( 300 array( 301 'tags' => $tag, 302 'page' => $page, 303 'per_page' => 24, 304 'user_id' => $nsid, 305 'license' => $licenses, 306 'text' => $text, 307 'extras' => 'original_format,license,date_upload,last_update', 308 'media' => 'photos' 309 ) 310 ); 311 $ret['total'] = $photos['total']; 312 $ret['perpage'] = $photos['perpage']; 313 if (empty($photos)) { 314 $ret['list'] = array(); 315 return $ret; 316 } 317 $ret = $this->build_list($photos, $page, $ret); 318 $ret['list'] = array_filter($ret['list'], array($this, 'filter')); 319 return $ret; 320 } 321 322 /** 323 * return an image list 324 * 325 * @param string $path 326 * @param int $page 327 * @return array 328 */ 329 public function get_listing($path = '', $page = 1) { 330 $people = $this->flickr->people_findByEmail($this->flickr_account); 331 $this->nsid = $people['nsid']; 332 $photos = $this->flickr->people_getPublicPhotos($people['nsid'], 'original_format,license,date_upload,last_update', 333 24, $page); 334 $ret = array(); 335 336 return $this->build_list($photos, $page, $ret); 337 } 338 339 /** 340 * build an image list 341 * 342 * @param array $photos 343 * @param int $page 344 * @return array 345 */ 346 private function build_list($photos, $page, &$ret) { 347 global $OUTPUT; 348 349 if (!empty($this->nsid)) { 350 $photos_url = $this->flickr->urls_getUserPhotos($this->nsid); 351 $ret['manage'] = $photos_url; 352 } 353 $ret['list'] = array(); 354 $ret['nosearch'] = true; 355 $ret['norefresh'] = true; 356 $ret['logouttext'] = get_string('backtosearch', 'repository_flickr_public'); 357 $ret['pages'] = $photos['pages']; 358 if (is_int($page) && $page <= $ret['pages']) { 359 $ret['page'] = $page; 360 } else { 361 $ret['page'] = 1; 362 } 363 if (!empty($photos['photo'])) { 364 foreach ($photos['photo'] as $p) { 365 if(empty($p['title'])) { 366 $p['title'] = get_string('notitle', 'repository_flickr'); 367 } 368 if (isset($p['originalformat'])) { 369 $format = $p['originalformat']; 370 } else { 371 $format = 'jpg'; 372 } 373 $format = '.'.$format; 374 if (substr($p['title'], strlen($p['title'])-strlen($format)) != $format) { 375 // append author id 376 // $p['title'] .= '-'.$p['owner']; 377 // append file extension 378 $p['title'] .= $format; 379 } 380 // Get the thumbnail source URL. 381 $thumbnailsource = $this->flickr->buildPhotoURL($p, 'Square'); 382 if (!@getimagesize($thumbnailsource)) { 383 // Use the file extension icon as a thumbnail if the original thumbnail does not exist to avoid 384 // displaying broken thumbnails in the repository. 385 $thumbnailsource = $OUTPUT->image_url(file_extension_icon($p['title'], 90))->out(false); 386 } 387 388 // Perform a HEAD request to the image to obtain it's Content-Length. 389 $curl = new curl(); 390 $curl->head($this->get_link($p['id'])); 391 392 // The photo sizes are statically cached, so we can retrieve image dimensions without another API call. 393 $bestsize = $this->get_best_size($p['id']); 394 395 $ret['list'][] = array( 396 'title' => $p['title'], 397 'source' => $p['id'], 398 'id' => $p['id'], 399 'thumbnail' => $thumbnailsource, 400 'datecreated' => $p['dateupload'], 401 'datemodified' => $p['lastupdate'], 402 'size' => (int)($curl->get_info()['download_content_length']), 403 'image_width' => $bestsize['width'], 404 'image_height' => $bestsize['height'], 405 'url' => 'http://www.flickr.com/photos/' . $p['owner'] . '/' . $p['id'], 406 'license' => $this->license4moodle($p['license']), 407 'author' => $p['owner'], 408 ); 409 } 410 } 411 return $ret; 412 } 413 414 /** 415 * Print a search form 416 * 417 * @return string 418 */ 419 public function print_search() { 420 $str = ''; 421 $str .= '<input type="hidden" name="repo_id" value="'.$this->id.'" />'; 422 $str .= '<input type="hidden" name="ctx_id" value="'.$this->context->id.'" />'; 423 $str .= '<input type="hidden" name="seekey" value="'.sesskey().'" />'; 424 $str .= '<label>'.get_string('fulltext', 'repository_flickr_public').'</label><br/><input name="s" value="" /><br/>'; 425 $str .= '<label>'.get_string('tag', 'repository_flickr_public').'</label><br /><input type="text" name="flickr_tag" /><br />'; 426 return $str; 427 } 428 429 /** 430 * Return photo url by given photo id 431 * @param string $photoid 432 * @return string 433 */ 434 private function build_photo_url($photoid) { 435 $bestsize = $this->get_best_size($photoid); 436 if (!isset($bestsize['source'])) { 437 throw new repository_exception('cannotdownload', 'repository'); 438 } 439 return $bestsize['source']; 440 } 441 442 /** 443 * Returns the best size for a photo 444 * 445 * @param string $photoid the photo identifier 446 * @return array of information provided by the API 447 */ 448 protected function get_best_size($photoid) { 449 if (!isset(self::$sizes[$photoid])) { 450 // Sizes are returned from smallest to greatest. 451 self::$sizes[$photoid] = $this->flickr->photos_getSizes($photoid); 452 } 453 $sizes = self::$sizes[$photoid]; 454 $bestsize = array(); 455 if (is_array($sizes)) { 456 while ($bestsize = array_pop($sizes)) { 457 // Make sure the source is set. Exit the loop if found. 458 if (isset($bestsize['source'])) { 459 break; 460 } 461 } 462 } 463 return $bestsize; 464 } 465 466 public function get_link($photoid) { 467 return $this->build_photo_url($photoid); 468 } 469 470 /** 471 * 472 * @global object $CFG 473 * @param string $photoid 474 * @param string $file 475 * @return string 476 */ 477 public function get_file($photoid, $file = '') { 478 global $CFG; 479 480 $info = $this->flickr->photos_getInfo($photoid); 481 482 // If we can read the original secret, it means that we have access to the original picture. 483 if (isset($info['originalsecret'])) { 484 $source = $this->flickr->buildPhotoURL($info, 'original'); 485 } else { 486 $source = $this->build_photo_url($photoid); 487 } 488 // Make sure the source image exists. 489 if (!@getimagesize($source)) { 490 throw new moodle_exception('cannotdownload', 'repository'); 491 } 492 493 if ($info['owner']['realname']) { 494 $author = $info['owner']['realname']; 495 } else { 496 $author = $info['owner']['username']; 497 } 498 $copyright = get_string('author', 'repository') . ': ' . $author; 499 500 $result = parent::get_file($source, $file); 501 $path = $result['path']; 502 503 if (!empty($this->usewatermarks)) { 504 $img = new moodle_image($path); 505 $img->watermark($copyright, array(10,10), array('ttf'=>true, 'fontsize'=>12))->saveas($path); 506 } 507 508 return array('path'=>$path, 'author'=>$info['owner']['realname'], 'license'=>$this->license4moodle($info['license'])); 509 } 510 511 /** 512 * Add Instance settings input to Moodle form 513 * @param object $mform 514 */ 515 public static function instance_config_form($mform) { 516 $mform->addElement('text', 'email_address', get_string('emailaddress', 'repository_flickr_public')); 517 $mform->setType('email_address', PARAM_RAW_TRIMMED); // This is for sending to flickr. Not our job to validate it. 518 $mform->addElement('checkbox', 'usewatermarks', get_string('watermark', 'repository_flickr_public')); 519 $mform->setDefault('usewatermarks', 0); 520 } 521 522 /** 523 * Names of the instance settings 524 * @return array 525 */ 526 public static function get_instance_option_names() { 527 return array('email_address', 'usewatermarks'); 528 } 529 530 /** 531 * Add Plugin settings input to Moodle form 532 * @param object $mform 533 */ 534 public static function type_config_form($mform, $classname = 'repository') { 535 $api_key = get_config('flickr_public', 'api_key'); 536 if (empty($api_key)) { 537 $api_key = ''; 538 } 539 $strrequired = get_string('required'); 540 541 $mform->addElement('text', 'api_key', get_string('apikey', 'repository_flickr_public'), array('value'=>$api_key,'size' => '40')); 542 $mform->setType('api_key', PARAM_RAW_TRIMMED); 543 $mform->addRule('api_key', $strrequired, 'required', null, 'client'); 544 545 $mform->addElement('static', null, '', get_string('information','repository_flickr_public')); 546 } 547 548 /** 549 * Names of the plugin settings 550 * @return array 551 */ 552 public static function get_type_option_names() { 553 return array('api_key', 'pluginname'); 554 } 555 556 /** 557 * is run when moodle administrator add the plugin 558 */ 559 public static function plugin_init() { 560 //here we create a default instance for this type 561 562 $id = repository::static_function('flickr_public','create', 'flickr_public', 0, context_system::instance(), array('name'=>'', 'email_address' => null, 'usewatermarks' => false), 0); 563 if (empty($id)) { 564 return false; 565 } else { 566 return true; 567 } 568 } 569 public function supported_filetypes() { 570 return array('web_image'); 571 } 572 public function supported_returntypes() { 573 return (FILE_INTERNAL | FILE_EXTERNAL); 574 } 575 576 /** 577 * Return the source information 578 * 579 * @param string $photoid photo id 580 * @return string|null 581 */ 582 public function get_file_source_info($photoid) { 583 return $this->build_photo_url($photoid); 584 } 585 586 /** 587 * Is this repository accessing private data? 588 * 589 * @return bool 590 */ 591 public function contains_private_data() { 592 return false; 593 } 594 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body