MDL-68954 repository_flickr_public: Return only photo media
[moodle.git] / repository / flickr_public / lib.php
CommitLineData
539b3d13 1<?php
10d53fd3
DC
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
67233725
DC
17/**
18 * This plugin is used to access flickr pictures
19 *
5bcfd504 20 * @since Moodle 2.0
67233725
DC
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 */
25require_once($CFG->dirroot . '/repository/lib.php');
26require_once($CFG->libdir.'/flickrlib.php');
1fcf0ca8 27require_once(__DIR__ . '/image.php');
67233725 28
539b3d13 29/**
30 * repository_flickr_public class
31 * This one is used to create public repository
49d20def
DC
32 * You can set up a public account in admin page, so everyone can access
33 * flickr photos from this plugin
539b3d13 34 *
5bcfd504 35 * @since Moodle 2.0
67233725
DC
36 * @package repository_flickr_public
37 * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org}
d078f6d3 38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
539b3d13 39 */
dc0976b8 40class repository_flickr_public extends repository {
539b3d13 41 private $flickr;
42 public $photos;
43
b2245b7e
FM
44 /**
45 * Stores sizes of images to prevent multiple API call
46 */
47 static private $sizes = array();
48
49d20def
DC
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');
2c40911a 65 $this->usewatermarks = $this->get_option('usewatermarks');
49d20def
DC
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
96297ca2 86 /**
6b2a6c90 87 * save api_key in config table
88 * @param array $options
89 * @return boolean
96297ca2 90 */
dc0976b8 91 public function set_option($options = array()) {
539b3d13 92 if (!empty($options['api_key'])) {
93 set_config('api_key', trim($options['api_key']), 'flickr_public');
94 }
95 unset($options['api_key']);
99eaca9d 96 return parent::set_option($options);
539b3d13 97 }
98
96297ca2 99 /**
6b2a6c90 100 * get api_key from config table
99eaca9d 101 *
6b2a6c90 102 * @param string $config
103 * @return mixed
96297ca2 104 */
dc0976b8 105 public function get_option($config = '') {
106 if ($config==='api_key') {
539b3d13 107 return trim(get_config('flickr_public', 'api_key'));
108 } else {
109 $options['api_key'] = trim(get_config('flickr_public', 'api_key'));
110 }
99eaca9d 111 return parent::get_option($config);
539b3d13 112 }
113
96297ca2 114 /**
6b2a6c90 115 * is global_search available?
99eaca9d 116 *
6b2a6c90 117 * @return boolean
96297ca2 118 */
dc0976b8 119 public function global_search() {
539b3d13 120 if (empty($this->flickr_account)) {
121 return false;
122 } else {
123 return true;
124 }
125 }
126
96297ca2 127 /**
49d20def 128 * check if flickr account
6b2a6c90 129 * @return boolean
96297ca2 130 */
dc0976b8 131 public function check_login() {
d68c527f 132 return !empty($this->flickr_account);
133 }
96297ca2 134
135 /**
99eaca9d 136 * construct login form
96297ca2 137 *
6b2a6c90 138 * @param boolean $ajax
139 * @return array
96297ca2 140 */
78ff2983 141 public function print_login() {
142 if ($this->options['ajax']) {
d68c527f 143 $ret = array();
6bdfef5d 144 $fulltext = new stdClass();
6b2a6c90 145 $fulltext->label = get_string('fulltext', 'repository_flickr_public').': ';
146 $fulltext->id = 'el_fulltext';
147 $fulltext->type = 'text';
148 $fulltext->name = 'flickr_fulltext';
149
6bdfef5d 150 $tag = new stdClass();
6b2a6c90 151 $tag->label = get_string('tag', 'repository_flickr_public').': ';
152 $tag->id = 'el_tag';
153 $tag->type = 'text';
154 $tag->name = 'flickr_tag';
155
6bdfef5d 156 $email_field = new stdClass();
ca0174cc 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';
45983072 161
6bdfef5d 162 $commercial = new stdClass();
16e9dccd 163 $commercial->label = get_string('commercialuse', 'repository_flickr_public').': ';
164 $commercial->id = 'flickr_commercial_id';
640bb8c1 165 $commercial->type = 'checkbox';
16e9dccd 166 $commercial->name = 'flickr_commercial';
640bb8c1 167 $commercial->value = 'yes';
9f50fb5f 168
6bdfef5d 169 $modification = new stdClass();
16e9dccd 170 $modification->label = get_string('modification', 'repository_flickr_public').': ';
171 $modification->id = 'flickr_modification_id';
640bb8c1 172 $modification->type = 'checkbox';
16e9dccd 173 $modification->name = 'flickr_modification';
640bb8c1 174 $modification->value = 'yes';
16e9dccd 175
176 $ret['login'] = array($fulltext, $tag, $email_field, $commercial, $modification);
45983072 177 $ret['login_btn_label'] = get_string('search');
da2946c9 178 $ret['login_btn_action'] = 'search';
d68c527f 179 return $ret;
78ff2983 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
16e9dccd 189 echo '<tr><td><label>'.get_string('commercialuse', 'repository_flickr_public').'</label></td>';
78ff2983 190 echo '<td>';
640bb8c1 191 echo '<input type="checkbox" name="flickr_commercial" value="yes" />';
16e9dccd 192 echo '</td></tr>';
193
194 echo '<tr><td><label>'.get_string('modification', 'repository_flickr_public').'</label></td>';
195 echo '<td>';
640bb8c1 196 echo '<input type="checkbox" name="flickr_modification" value="yes" />';
78ff2983 197 echo '</td></tr>';
198
199 echo '</table>';
200
201 echo '<input type="hidden" name="action" value="search" />';
362a728f 202 echo '<input type="submit" value="'.get_string('search', 'repository').'" />';
539b3d13 203 }
204 }
96297ca2 205
aa48f05d 206 /**
99eaca9d 207 * destroy session
aa48f05d 208 *
99eaca9d 209 * @return object
aa48f05d 210 */
211 public function logout() {
6b2a6c90 212 global $SESSION;
213 unset($SESSION->{$this->sess_tag});
214 unset($SESSION->{$this->sess_text});
215 unset($SESSION->{$this->sess_account});
aa48f05d 216 return $this->print_login();
217 }
218
1dce6261
DC
219 public function license4moodle ($license_id) {
220 $license = array(
87294fa3 221 '0' => 'allrightsreserved',
1dce6261
DC
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',
87294fa3 228 '7' => 'other'
1dce6261
DC
229 );
230 return $license[$license_id];
231 }
232
96297ca2 233 /**
99eaca9d 234 * search images on flickr
96297ca2 235 *
99eaca9d
DC
236 * @param string $search_text
237 * @return array
96297ca2 238 */
68a7c9a6 239 public function search($search_text, $page = 0) {
86e68c2d 240 global $SESSION;
d1bfc05e 241 $ret = array();
99eaca9d
DC
242 if (empty($page)) {
243 $page = 1;
244 }
245
6b2a6c90 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;
d1bfc05e 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 }
6b2a6c90 261 }
99eaca9d 262
16e9dccd 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 }
640bb8c1 286 //if ($modification == 'sharealike') {
16e9dccd 287 // including
288 // 1: Attribution NonCommercial ShareAlike
289 // 5: Attribution ShareAlike
640bb8c1
MD
290 //unset($licenses[2], $licenses[3], $licenses[4], $licenses[6], $licenses[7]);
291 //}
16e9dccd 292
293 $licenses = implode(',', $licenses);
294
da78b10c
DC
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
e8017491
MG
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 'media' => 'photos'
da78b10c
DC
308 )
309 );
009a97ce 310 $ret['total'] = $photos['total'];
311 $ret['perpage'] = $photos['perpage'];
9f50fb5f 312 if (empty($photos)) {
313 $ret['list'] = array();
314 return $ret;
315 }
c438f190 316 $ret = $this->build_list($photos, $page, $ret);
317 $ret['list'] = array_filter($ret['list'], array($this, 'filter'));
318 return $ret;
fbd508b4 319 }
96297ca2 320
321 /**
99eaca9d 322 * return an image list
96297ca2 323 *
5fa358d1 324 * @param string $path
325 * @param int $page
99eaca9d 326 * @return array
96297ca2 327 */
5fa358d1 328 public function get_listing($path = '', $page = 1) {
539b3d13 329 $people = $this->flickr->people_findByEmail($this->flickr_account);
353d5cf3 330 $this->nsid = $people['nsid'];
5fa358d1 331 $photos = $this->flickr->people_getPublicPhotos($people['nsid'], 'original_format', 24, $page);
86e68c2d 332 $ret = array();
539b3d13 333
5fa358d1 334 return $this->build_list($photos, $page, $ret);
353d5cf3 335 }
96297ca2 336
337 /**
99eaca9d 338 * build an image list
96297ca2 339 *
99eaca9d
DC
340 * @param array $photos
341 * @param int $page
342 * @return array
96297ca2 343 */
5fa358d1 344 private function build_list($photos, $page = 1, &$ret) {
e58db3a8
MG
345 global $OUTPUT;
346
6b2a6c90 347 if (!empty($this->nsid)) {
348 $photos_url = $this->flickr->urls_getUserPhotos($this->nsid);
349 $ret['manage'] = $photos_url;
350 }
539b3d13 351 $ret['list'] = array();
fdfb9cbe
DC
352 $ret['nosearch'] = true;
353 $ret['norefresh'] = true;
354 $ret['logouttext'] = get_string('backtosearch', 'repository_flickr_public');
539b3d13 355 $ret['pages'] = $photos['pages'];
5fa358d1 356 if (is_int($page) && $page <= $ret['pages']) {
357 $ret['page'] = $page;
539b3d13 358 } else {
359 $ret['page'] = 1;
360 }
353d5cf3 361 if (!empty($photos['photo'])) {
362 foreach ($photos['photo'] as $p) {
363 if(empty($p['title'])) {
364 $p['title'] = get_string('notitle', 'repository_flickr');
365 }
366 if (isset($p['originalformat'])) {
367 $format = $p['originalformat'];
368 } else {
369 $format = 'jpg';
370 }
0e51661b 371 $format = '.'.$format;
0e51661b 372 if (substr($p['title'], strlen($p['title'])-strlen($format)) != $format) {
d1bfc05e 373 // append author id
5fdc39c7 374 // $p['title'] .= '-'.$p['owner'];
d1bfc05e 375 // append file extension
4317f92f 376 $p['title'] .= $format;
0e51661b 377 }
e58db3a8
MG
378 // Get the thumbnail source URL.
379 $thumbnailsource = $this->flickr->buildPhotoURL($p, 'Square');
380 if (!@getimagesize($thumbnailsource)) {
381 // Use the file extension icon as a thumbnail if the original thumbnail does not exist to avoid
382 // displaying broken thumbnails in the repository.
383 $thumbnailsource = $OUTPUT->image_url(file_extension_icon($p['title'], 90))->out(false);
384 }
1dce6261 385 $ret['list'][] = array(
e58db3a8
MG
386 'title' => $p['title'],
387 'source' => $p['id'],
388 'id' => $p['id'],
389 'thumbnail' => $thumbnailsource,
390 'date' => '',
391 'size' => 'unknown',
392 'url' => 'http://www.flickr.com/photos/' . $p['owner'] . '/' . $p['id'],
393 'haslicense' => true,
394 'hasauthor' => true
1dce6261 395 );
539b3d13 396 }
539b3d13 397 }
353d5cf3 398 return $ret;
539b3d13 399 }
dc0976b8 400
96297ca2 401 /**
99d52655 402 * Print a search form
96297ca2 403 *
99d52655 404 * @return string
96297ca2 405 */
dc0976b8 406 public function print_search() {
b763c2d9 407 $str = '';
408 $str .= '<input type="hidden" name="repo_id" value="'.$this->id.'" />';
409 $str .= '<input type="hidden" name="ctx_id" value="'.$this->context->id.'" />';
410 $str .= '<input type="hidden" name="seekey" value="'.sesskey().'" />';
88d366e5 411 $str .= '<label>'.get_string('fulltext', 'repository_flickr_public').'</label><br/><input name="s" value="" /><br/>';
1238246b 412 $str .= '<label>'.get_string('tag', 'repository_flickr_public').'</label><br /><input type="text" name="flickr_tag" /><br />';
b763c2d9 413 return $str;
539b3d13 414 }
dc0976b8 415
d6453211
DC
416 /**
417 * Return photo url by given photo id
418 * @param string $photoid
419 * @return string
420 */
421 private function build_photo_url($photoid) {
b2245b7e
FM
422 $bestsize = $this->get_best_size($photoid);
423 if (!isset($bestsize['source'])) {
424 throw new repository_exception('cannotdownload', 'repository');
425 }
426 return $bestsize['source'];
427 }
428
429 /**
430 * Returns the best size for a photo
431 *
432 * @param string $photoid the photo identifier
433 * @return array of information provided by the API
434 */
435 protected function get_best_size($photoid) {
436 if (!isset(self::$sizes[$photoid])) {
437 // Sizes are returned from smallest to greatest.
438 self::$sizes[$photoid] = $this->flickr->photos_getSizes($photoid);
439 }
440 $sizes = self::$sizes[$photoid];
441 $bestsize = array();
442 if (is_array($sizes)) {
443 while ($bestsize = array_pop($sizes)) {
444 // Make sure the source is set. Exit the loop if found.
445 if (isset($bestsize['source'])) {
446 break;
447 }
448 }
99d52655 449 }
b2245b7e 450 return $bestsize;
99d52655
DC
451 }
452
d6453211 453 public function get_link($photoid) {
cd2b223d 454 return $this->build_photo_url($photoid);
d6453211
DC
455 }
456
96297ca2 457 /**
458 *
009a97ce 459 * @global object $CFG
d6453211 460 * @param string $photoid
009a97ce 461 * @param string $file
462 * @return string
96297ca2 463 */
d6453211 464 public function get_file($photoid, $file = '') {
539b3d13 465 global $CFG;
e58db3a8 466
d6453211 467 $info = $this->flickr->photos_getInfo($photoid);
b2245b7e
FM
468
469 // If we can read the original secret, it means that we have access to the original picture.
470 if (isset($info['originalsecret'])) {
471 $source = $this->flickr->buildPhotoURL($info, 'original');
472 } else {
473 $source = $this->build_photo_url($photoid);
539b3d13 474 }
e58db3a8
MG
475 // Make sure the source image exists.
476 if (!@getimagesize($source)) {
477 throw new moodle_exception('cannotdownload', 'repository');
478 }
479
480 if ($info['owner']['realname']) {
481 $author = $info['owner']['realname'];
482 } else {
483 $author = $info['owner']['username'];
484 }
485 $copyright = get_string('author', 'repository') . ': ' . $author;
b2245b7e 486
72a56555
MG
487 $result = parent::get_file($source, $file);
488 $path = $result['path'];
b2245b7e 489
2c40911a
DC
490 if (!empty($this->usewatermarks)) {
491 $img = new moodle_image($path);
492 $img->watermark($copyright, array(10,10), array('ttf'=>true, 'fontsize'=>12))->saveas($path);
493 }
1dce6261 494
b2245b7e 495 return array('path'=>$path, 'author'=>$info['owner']['realname'], 'license'=>$this->license4moodle($info['license']));
539b3d13 496 }
539b3d13 497
96297ca2 498 /**
792ad3aa 499 * Add Instance settings input to Moodle form
99eaca9d 500 * @param object $mform
96297ca2 501 */
4a126f17 502 public static function instance_config_form($mform) {
b8f46e17 503 $mform->addElement('text', 'email_address', get_string('emailaddress', 'repository_flickr_public'));
13eeb23c 504 $mform->setType('email_address', PARAM_RAW_TRIMMED); // This is for sending to flickr. Not our job to validate it.
2c40911a 505 $mform->addElement('checkbox', 'usewatermarks', get_string('watermark', 'repository_flickr_public'));
d55846d8 506 $mform->setDefault('usewatermarks', 0);
b8f46e17 507 }
508
96297ca2 509 /**
792ad3aa 510 * Names of the instance settings
99eaca9d 511 * @return array
96297ca2 512 */
b8f46e17 513 public static function get_instance_option_names() {
2c40911a 514 return array('email_address', 'usewatermarks');
539b3d13 515 }
516
96297ca2 517 /**
792ad3aa 518 * Add Plugin settings input to Moodle form
99eaca9d 519 * @param object $mform
96297ca2 520 */
68a7c9a6 521 public static function type_config_form($mform, $classname = 'repository') {
539b3d13 522 $api_key = get_config('flickr_public', 'api_key');
523 if (empty($api_key)) {
524 $api_key = '';
525 }
526 $strrequired = get_string('required');
d1bfc05e 527
539b3d13 528 $mform->addElement('text', 'api_key', get_string('apikey', 'repository_flickr_public'), array('value'=>$api_key,'size' => '40'));
13eeb23c 529 $mform->setType('api_key', PARAM_RAW_TRIMMED);
539b3d13 530 $mform->addRule('api_key', $strrequired, 'required', null, 'client');
d1bfc05e 531
e49eaacb 532 $mform->addElement('static', null, '', get_string('information','repository_flickr_public'));
539b3d13 533 }
b8f46e17 534
96297ca2 535 /**
792ad3aa 536 * Names of the plugin settings
49d20def 537 * @return array
96297ca2 538 */
1b79955a 539 public static function get_type_option_names() {
a5adfa26 540 return array('api_key', 'pluginname');
b8f46e17 541 }
542
96297ca2 543 /**
83a018ed 544 * is run when moodle administrator add the plugin
96297ca2 545 */
948c2860 546 public static function plugin_init() {
e49eaacb 547 //here we create a default instance for this type
539b3d13 548
0601e0ee 549 $id = repository::static_function('flickr_public','create', 'flickr_public', 0, context_system::instance(), array('name'=>'', 'email_address' => null, 'usewatermarks' => false), 0);
60c366e8 550 if (empty($id)) {
551 return false;
552 } else {
553 return true;
554 }
dbc01944 555 }
014c1ca0 556 public function supported_filetypes() {
557 return array('web_image');
558 }
41076c58
DC
559 public function supported_returntypes() {
560 return (FILE_INTERNAL | FILE_EXTERNAL);
561 }
d6453211
DC
562
563 /**
564 * Return the source information
565 *
566 * @param string $photoid photo id
567 * @return string|null
568 */
569 public function get_file_source_info($photoid) {
570 return $this->build_photo_url($photoid);
571 }
31581ae6
FM
572
573 /**
574 * Is this repository accessing private data?
575 *
576 * @return bool
577 */
578 public function contains_private_data() {
579 return false;
580 }
539b3d13 581}