Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
/lib/ -> flickrlib.php (source)

Differences Between: [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]

   1  <?php
   2  /**
   3   * phpFlickr Class 2.2.0
   4   * Written by Dan Coulter (dan@dancoulter.com)
   5   * Sourceforge Project Page: {@link http://www.sourceforge.net/projects/phpflickr/}
   6   * Released under GNU Lesser General Public License ({@link http://www.gnu.org/copyleft/lgpl.html})
   7   * For more information about the class and upcoming tools and toys using it,
   8   * visit {@link http://www.phpflickr.com/} or {@link http://phpflickr.sourceforge.net}
   9   *
  10   *   For installation instructions, open the README.txt file packaged with this
  11   *   class. If you don't have a copy, you can see it at:
  12   *    {@link http://www.phpflickr.com/README.txt}
  13   *
  14   *   Please submit all problems or questions to the Help Forum on my project page:
  15   *     {@link http://sourceforge.net/forum/forum.php?forum_id=469652}
  16   *
  17   * Modified by Dongsheng Cai <dongsheng@moodle.com>
  18   * ChangeLog:
  19   *   1. Remove PEAR HTTP LIB, use curl.class.php (created by myself)
  20   *   2. Remove PEAR DB LIB
  21   *   3. Remove all cache code, it will implement in curl class.
  22   *   4. Clean up session code
  23   *
  24   * Modified by David Mudrak <david@moodle.com>
  25   * ChangeLog:
  26   *   1. upload() method uses Moodle stored_file
  27   *   2. upload() method supports all params provided by http://www.flickr.com/services/api/upload.api.html
  28   *   3. auth() method shows debugging warning as this library cannot be used any
  29   *      more for calling Flickr API that requires authentication.
  30   *
  31   * @package moodlecore
  32   * @subpackage 3rd-party
  33   */
  34  
  35  /**
  36   * Flickr Class
  37   * @package moodlecore
  38   * @subpackage 3rd-party
  39   */
  40  class phpFlickr {
  41      var $api_key;
  42      var $secret;
  43      var $REST = 'https://api.flickr.com/services/rest/';
  44      var $Upload = 'https://api.flickr.com/services/upload/';
  45      var $Replace = 'https://api.flickr.com/services/replace/';
  46      var $req;
  47      var $response;
  48      var $parsed_response;
  49      var $die_on_error;
  50      var $error_code;
  51      var $error_msg;
  52      var $token;
  53      var $php_version;
  54  
  55      /**
  56       * When your database cache table hits this many rows, a cleanup
  57       * will occur to get rid of all of the old rows and cleanup the
  58       * garbage in the table.  For most personal apps, 1000 rows should
  59       * be more than enough.  If your site gets hit by a lot of traffic
  60       * or you have a lot of disk space to spare, bump this number up.
  61       * You should try to set it high enough that the cleanup only
  62       * happens every once in a while, so this will depend on the growth
  63       * of your table.
  64       *
  65       * @global object
  66       */
  67  
  68      function __construct ($api_key, $secret = NULL, $token = '')
  69      {
  70          global $CFG;
  71          //The API Key must be set before any calls can be made.  You can
  72          //get your own at http://www.flickr.com/services/api/misc.api_keys.html
  73          $this->api_key = $api_key;
  74          $this->secret = $secret;
  75          $this->die_on_error = false;
  76          $this->service = "flickr";
  77          $this->token = $token;
  78          //Find the PHP version and store it for future reference
  79          $this->php_version = explode("-", phpversion());
  80          $this->php_version = explode(".", $this->php_version[0]);
  81          $this->curl = new curl(array('cache'=>true, 'module_cache'=>'repository'));
  82      }
  83  
  84      function request ($command, $args = array())
  85      {
  86          //Sends a request to Flickr's REST endpoint via POST.
  87          if (substr($command,0,7) != "flickr.") {
  88              $command = "flickr." . $command;
  89          }
  90  
  91          //Process arguments, including method and login data.
  92          if ($command == 'flickr.upload') {
  93              $photo = $args['photo'];
  94              if (empty($args['is_public'])) {
  95                  $args['is_public'] = 0;
  96              }
  97              if (empty($args['is_friend'])) {
  98                  $args['is_friend'] = 0;
  99              }
 100              if (empty($args['is_family'])) {
 101                  $args['is_family'] = 0;
 102              }
 103              if (empty($args['hidden'])) {
 104                  $args['hidden'] = 1;
 105              }
 106              $args = array("api_key" => $this->api_key,
 107                            "title" => $args['title'],
 108                            "description" => $args['description'],
 109                            "tags" => $args['tags'],
 110                            "is_public" => $args['is_public'],
 111                            "is_friend" => $args['is_friend'],
 112                            "is_family" => $args['is_family'],
 113                            "safety_level" => $args['safety_level'],
 114                            "content_type" => $args['content_type'],
 115                            "hidden" => $args['hidden']);
 116          } else {
 117              $args = array_merge(array("method" => $command, "format" => "php_serial", "api_key" => $this->api_key), $args);
 118          }
 119  
 120          if (!empty($this->token)) {
 121              $args = array_merge($args, array("auth_token" => $this->token));
 122          }
 123  
 124          ksort($args);
 125          $auth_sig = "";
 126          foreach ($args as $key => $data) {
 127              $auth_sig .= $key . $data;
 128          }
 129  
 130          if (!empty($this->secret)) {
 131              $api_sig = md5($this->secret . $auth_sig);
 132              $args['api_sig'] = $api_sig;
 133          }
 134  
 135          //$this->req->addHeader("Connection", "Keep-Alive");
 136          if ($command != 'flickr.upload') {
 137              $ret = $this->curl->post($this->REST, $args);
 138              $this->parsed_response = $this->clean_text_nodes(unserialize($ret));
 139          } else {
 140              $args['photo'] = $photo;
 141              $xml = simplexml_load_string($this->curl->post($this->Upload, $args));
 142  
 143              if ($xml['stat'] == 'fail') {
 144                  $this->parsed_response = array('stat' => (string) $xml['stat'], 'code' => (int) $xml->err['code'], 'message' => (string) $xml->err['msg']);
 145              } elseif ($xml['stat'] == 'ok') {
 146                  $this->parsed_response = array('stat' => (string) $xml['stat'], 'photoid' => (int) $xml->photoid);
 147                  $this->response = true;
 148              }
 149          }
 150  
 151          if ($this->parsed_response['stat'] == 'fail') {
 152              if ($this->die_on_error) die("The Flickr API returned the following error: #{$this->parsed_response['code']} - {$this->parsed_response['message']}");
 153              else {
 154                  $this->error_code = $this->parsed_response['code'];
 155                  $this->error_msg = $this->parsed_response['message'];
 156                  $this->parsed_response = false;
 157              }
 158          } else {
 159              $this->error_code = false;
 160              $this->error_msg = false;
 161          }
 162          return $this->response;
 163      }
 164  
 165      function clean_text_nodes($arr) {
 166          if (!is_array($arr)) {
 167              return $arr;
 168          } elseif (count($arr) == 0) {
 169              return $arr;
 170          } elseif (count($arr) == 1 && array_key_exists('_content', $arr)) {
 171              return $arr['_content'];
 172          } else {
 173              foreach ($arr as $key => $element) {
 174                  $arr[$key] = $this->clean_text_nodes($element);
 175              }
 176              return($arr);
 177          }
 178      }
 179  
 180      function setToken($token)
 181      {
 182          // Sets an authentication token to use instead of the session variable
 183          $this->token = $token;
 184      }
 185  
 186      function setProxy($server, $port)
 187      {
 188          // Sets the proxy for all phpFlickr calls.
 189          //$this->req->setProxy($server, $port);
 190      }
 191  
 192      function getErrorCode()
 193      {
 194          // Returns the error code of the last call.  If the last call did not
 195          // return an error. This will return a false boolean.
 196          return $this->error_code;
 197      }
 198  
 199      function getErrorMsg()
 200      {
 201          // Returns the error message of the last call.  If the last call did not
 202          // return an error. This will return a false boolean.
 203          return $this->error_msg;
 204      }
 205  
 206      /** These functions are front ends for the flickr calls */
 207  
 208      function buildPhotoURL ($photo, $size = "Medium")
 209      {
 210          //receives an array (can use the individual photo data returned
 211          //from an API call) and returns a URL (doesn't mean that the
 212          //file size exists)
 213          $sizes = array(
 214                  "square" => "_s",
 215                  "thumbnail" => "_t",
 216                  "small" => "_m",
 217                  "medium" => "",
 218                  "large" => "_b",
 219                  "original" => "_o"
 220                  );
 221  
 222          $size = strtolower($size);
 223          if (!array_key_exists($size, $sizes)) {
 224              $size = "medium";
 225          }
 226  
 227          if ($size == "original") {
 228              $url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['originalsecret'] . "_o" . "." . $photo['originalformat'];
 229          } else {
 230              $url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['secret'] . $sizes[$size] . ".jpg";
 231          }
 232          return $url;
 233      }
 234  
 235      function getFriendlyGeodata($lat, $lon) {
 236          /** I've added this method to get the friendly geodata (i.e. 'in New York, NY') that the
 237           * website provides, but isn't available in the API. I'm providing this service as long
 238           * as it doesn't flood my server with requests and crash it all the time.
 239           */
 240          return unserialize(file_get_contents('http://phpflickr.com/geodata/?format=php&lat=' . $lat . '&lon=' . $lon));
 241      }
 242  
 243      function auth ($perms = "write", $remember_uri = true)
 244      {
 245  
 246          debugging('The flickrlib.php cannot be used for authenticated Flickr API calls.
 247              Flickr does not support their legacy auth API any more. Use the new flickrclient.php instead.');
 248  
 249          // Redirects to Flickr's authentication piece if there is no valid token.
 250          // If remember_uri is set to false, the callback script (included) will
 251          // redirect to its default page.
 252          if ($remember_uri) {
 253              $redirect = qualified_me(); // TODO: this is not used, why?
 254          }
 255          $api_sig = md5($this->secret . "api_key" . $this->api_key . "perms" . $perms);
 256          $url = 'http://www.flickr.com/services/auth/?api_key=' . $this->api_key . "&perms=" .  $perms . '&api_sig='. $api_sig;
 257          return $url;
 258      }
 259  
 260      /**
 261       * To use the phpFlickr::call method, pass a string containing the API method you want
 262       * to use and an associative array of arguments.  For example:
 263       * $result = $f->call("flickr.photos.comments.getList", array("photo_id"=>'34952612'));
 264       * This method will allow you to make calls to arbitrary methods that haven't been
 265       * implemented in phpFlickr yet.
 266       */
 267  
 268      function call($method, $arguments)
 269      {
 270          $this->request($method, $arguments);
 271          return $this->parsed_response ? $this->parsed_response : false;
 272      }
 273  
 274      /**
 275       * These functions are the direct implementations of flickr calls.
 276       * For method documentation, including arguments, visit the address
 277       * included in a comment in the function.
 278       */
 279  
 280      /** Activity methods */
 281      function activity_userComments ($per_page = NULL, $page = NULL)
 282      {
 283          /** http://www.flickr.com/services/api/flickr.activity.userComments.html */
 284          $this->request('flickr.activity.userComments', array("per_page" => $per_page, "page" => $page));
 285          return $this->parsed_response ? $this->parsed_response['items']['item'] : false;
 286      }
 287  
 288      function activity_userPhotos ($timeframe = NULL, $per_page = NULL, $page = NULL)
 289      {
 290          /** http://www.flickr.com/services/api/flickr.activity.userPhotos.html */
 291          $this->request('flickr.activity.userPhotos', array("timeframe" => $timeframe, "per_page" => $per_page, "page" => $page));
 292          return $this->parsed_response ? $this->parsed_response['items']['item'] : false;
 293      }
 294  
 295      /** Authentication methods */
 296      function auth_checkToken ()
 297      {
 298          /** http://www.flickr.com/services/api/flickr.auth.checkToken.html */
 299          $this->request('flickr.auth.checkToken');
 300          return $this->parsed_response ? $this->parsed_response['auth'] : false;
 301      }
 302  
 303      function auth_getFrob ()
 304      {
 305          /** http://www.flickr.com/services/api/flickr.auth.getFrob.html */
 306          $this->request('flickr.auth.getFrob');
 307          return $this->parsed_response ? $this->parsed_response['frob'] : false;
 308      }
 309  
 310      function auth_getFullToken ($mini_token)
 311      {
 312          /** http://www.flickr.com/services/api/flickr.auth.getFullToken.html */
 313          $this->request('flickr.auth.getFullToken', array('mini_token'=>$mini_token));
 314          return $this->parsed_response ? $this->parsed_response['auth'] : false;
 315      }
 316  
 317      function auth_getToken ($frob)
 318      {
 319          /** http://www.flickr.com/services/api/flickr.auth.getToken.html */
 320          $this->request('flickr.auth.getToken', array('frob'=>$frob));
 321          $this->token = $this->parsed_response['auth']['token'];
 322          return $this->parsed_response ? $this->parsed_response['auth'] : false;
 323      }
 324  
 325      /** Blogs methods */
 326      function blogs_getList ()
 327      {
 328          /** http://www.flickr.com/services/api/flickr.blogs.getList.html */
 329          $this->request('flickr.blogs.getList');
 330          return $this->parsed_response ? $this->parsed_response['blogs']['blog'] : false;
 331      }
 332  
 333      function blogs_postPhoto($blog_id, $photo_id, $title, $description, $blog_password = NULL)
 334      {
 335          /** http://www.flickr.com/services/api/flickr.blogs.postPhoto.html */
 336          $this->request('flickr.blogs.postPhoto', array('blog_id'=>$blog_id, 'photo_id'=>$photo_id, 'title'=>$title, 'description'=>$description, 'blog_password'=>$blog_password), TRUE);
 337          return $this->parsed_response ? true : false;
 338      }
 339  
 340      /** Contacts Methods */
 341      function contacts_getList ($filter = NULL, $page = NULL, $per_page = NULL)
 342      {
 343          /** http://www.flickr.com/services/api/flickr.contacts.getList.html */
 344          $this->request('flickr.contacts.getList', array('filter'=>$filter, 'page'=>$page, 'per_page'=>$per_page));
 345          return $this->parsed_response ? $this->parsed_response['contacts'] : false;
 346      }
 347  
 348      function contacts_getPublicList($user_id, $page = NULL, $per_page = NULL)
 349      {
 350          /** http://www.flickr.com/services/api/flickr.contacts.getPublicList.html */
 351          $this->request('flickr.contacts.getPublicList', array('user_id'=>$user_id, 'page'=>$page, 'per_page'=>$per_page));
 352          return $this->parsed_response ? $this->parsed_response['contacts'] : false;
 353      }
 354  
 355      /** Favorites Methods */
 356      function favorites_add ($photo_id)
 357      {
 358          /** http://www.flickr.com/services/api/flickr.favorites.add.html */
 359          $this->request('flickr.favorites.add', array('photo_id'=>$photo_id), TRUE);
 360          return $this->parsed_response ? true : false;
 361      }
 362  
 363      function favorites_getList($user_id = NULL, $extras = NULL, $per_page = NULL, $page = NULL)
 364      {
 365          /** http://www.flickr.com/services/api/flickr.favorites.getList.html */
 366          if (is_array($extras)) { $extras = implode(",", $extras); }
 367          $this->request("flickr.favorites.getList", array("user_id"=>$user_id, "extras"=>$extras, "per_page"=>$per_page, "page"=>$page));
 368          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 369      }
 370  
 371      function favorites_getPublicList($user_id = NULL, $extras = NULL, $per_page = NULL, $page = NULL)
 372      {
 373          /** http://www.flickr.com/services/api/flickr.favorites.getPublicList.html */
 374          if (is_array($extras)) {
 375              $extras = implode(",", $extras);
 376          }
 377          $this->request("flickr.favorites.getPublicList", array("user_id"=>$user_id, "extras"=>$extras, "per_page"=>$per_page, "page"=>$page));
 378          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 379      }
 380  
 381      function favorites_remove($photo_id)
 382      {
 383          /** http://www.flickr.com/services/api/flickr.favorites.remove.html */
 384          $this->request("flickr.favorites.remove", array("photo_id"=>$photo_id), TRUE);
 385          return $this->parsed_response ? true : false;
 386      }
 387  
 388      /** Groups Methods */
 389      function groups_browse ($cat_id = NULL)
 390      {
 391          /** http://www.flickr.com/services/api/flickr.groups.browse.html */
 392          $this->request("flickr.groups.browse", array("cat_id"=>$cat_id));
 393          return $this->parsed_response ? $this->parsed_response['category'] : false;
 394      }
 395  
 396      function groups_getInfo ($group_id)
 397      {
 398          /** http://www.flickr.com/services/api/flickr.groups.getInfo.html */
 399          $this->request("flickr.groups.getInfo", array("group_id"=>$group_id));
 400          return $this->parsed_response ? $this->parsed_response['group'] : false;
 401      }
 402  
 403      function groups_search ($text, $per_page=NULL, $page=NULL)
 404      {
 405          /** http://www.flickr.com/services/api/flickr.groups.search.html */
 406          $this->request("flickr.groups.search", array("text"=>$text,"per_page"=>$per_page,"page"=>$page));
 407          return $this->parsed_response ? $this->parsed_response['groups'] : false;
 408      }
 409  
 410      /** Groups Pools Methods */
 411      function groups_pools_add ($photo_id, $group_id)
 412      {
 413          /** http://www.flickr.com/services/api/flickr.groups.pools.add.html */
 414          $this->request("flickr.groups.pools.add", array("photo_id"=>$photo_id, "group_id"=>$group_id), TRUE);
 415          return $this->parsed_response ? true : false;
 416      }
 417  
 418      function groups_pools_getContext ($photo_id, $group_id)
 419      {
 420          /** http://www.flickr.com/services/api/flickr.groups.pools.getContext.html */
 421          $this->request("flickr.groups.pools.getContext", array("photo_id"=>$photo_id, "group_id"=>$group_id));
 422          return $this->parsed_response ? $this->parsed_response : false;
 423      }
 424  
 425      function groups_pools_getGroups ($page = NULL, $per_page = NULL)
 426      {
 427          /** http://www.flickr.com/services/api/flickr.groups.pools.getGroups.html */
 428          $this->request("flickr.groups.pools.getGroups", array('page'=>$page, 'per_page'=>$per_page));
 429          return $this->parsed_response ? $this->parsed_response['groups'] : false;
 430      }
 431  
 432      function groups_pools_getPhotos ($group_id, $tags = NULL, $user_id = NULL, $extras = NULL, $per_page = NULL, $page = NULL)
 433      {
 434          /** http://www.flickr.com/services/api/flickr.groups.pools.getPhotos.html */
 435          if (is_array($extras)) {
 436              $extras = implode(",", $extras);
 437          }
 438          $this->request("flickr.groups.pools.getPhotos", array("group_id"=>$group_id, "tags"=>$tags, "user_id"=>$user_id, "extras"=>$extras, "per_page"=>$per_page, "page"=>$page));
 439          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 440      }
 441  
 442      function groups_pools_remove ($photo_id, $group_id)
 443      {
 444          /** http://www.flickr.com/services/api/flickr.groups.pools.remove.html */
 445          $this->request("flickr.groups.pools.remove", array("photo_id"=>$photo_id, "group_id"=>$group_id), TRUE);
 446          return $this->parsed_response ? true : false;
 447      }
 448  
 449      /** Interestingness methods */
 450      function interestingness_getList($date = NULL, $extras = NULL, $per_page = NULL, $page = NULL)
 451      {
 452          /** http://www.flickr.com/services/api/flickr.interestingness.getList.html */
 453          if (is_array($extras)) {
 454              $extras = implode(",", $extras);
 455          }
 456  
 457          $this->request("flickr.interestingness.getList", array("date"=>$date, "extras"=>$extras, "per_page"=>$per_page, "page"=>$page));
 458          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 459      }
 460  
 461      /** People methods */
 462      function people_findByEmail ($find_email)
 463      {
 464          /** http://www.flickr.com/services/api/flickr.people.findByEmail.html */
 465          $this->request("flickr.people.findByEmail", array("find_email"=>$find_email));
 466          return $this->parsed_response ? $this->parsed_response['user'] : false;
 467      }
 468  
 469      function people_findByUsername ($username)
 470      {
 471          /** http://www.flickr.com/services/api/flickr.people.findByUsername.html */
 472          $this->request("flickr.people.findByUsername", array("username"=>$username));
 473          return $this->parsed_response ? $this->parsed_response['user'] : false;
 474      }
 475  
 476      function people_getInfo($user_id)
 477      {
 478          /** http://www.flickr.com/services/api/flickr.people.getInfo.html */
 479          $this->request("flickr.people.getInfo", array("user_id"=>$user_id));
 480          return $this->parsed_response ? $this->parsed_response['person'] : false;
 481      }
 482  
 483      function people_getPublicGroups($user_id)
 484      {
 485          /** http://www.flickr.com/services/api/flickr.people.getPublicGroups.html */
 486          $this->request("flickr.people.getPublicGroups", array("user_id"=>$user_id));
 487          return $this->parsed_response ? $this->parsed_response['groups']['group'] : false;
 488      }
 489  
 490      function people_getPublicPhotos($user_id, $extras = NULL, $per_page = NULL, $page = NULL) {
 491          /** http://www.flickr.com/services/api/flickr.people.getPublicPhotos.html */
 492          if (is_array($extras)) {
 493              $extras = implode(",", $extras);
 494          }
 495  
 496          $this->request("flickr.people.getPublicPhotos", array("user_id"=>$user_id, "extras"=>$extras, "per_page"=>$per_page, "page"=>$page));
 497          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 498      }
 499  
 500      function people_getUploadStatus()
 501      {
 502          /** http://www.flickr.com/services/api/flickr.people.getUploadStatus.html */
 503          /** Requires Authentication */
 504          $this->request("flickr.people.getUploadStatus");
 505          return $this->parsed_response ? $this->parsed_response['user'] : false;
 506      }
 507  
 508  
 509      /** Photos Methods */
 510      function photos_addTags ($photo_id, $tags)
 511      {
 512          /** http://www.flickr.com/services/api/flickr.photos.addTags.html */
 513          $this->request("flickr.photos.addTags", array("photo_id"=>$photo_id, "tags"=>$tags), TRUE);
 514          return $this->parsed_response ? true : false;
 515      }
 516  
 517      function photos_delete($photo_id)
 518      {
 519          /** http://www.flickr.com/services/api/flickr.photos.delete.html */
 520          $this->request("flickr.photos.delete", array("photo_id"=>$photo_id), TRUE);
 521          return $this->parsed_response ? true : false;
 522      }
 523  
 524      function photos_getAllContexts ($photo_id)
 525      {
 526          /** http://www.flickr.com/services/api/flickr.photos.getAllContexts.html */
 527          $this->request("flickr.photos.getAllContexts", array("photo_id"=>$photo_id));
 528          return $this->parsed_response ? $this->parsed_response : false;
 529      }
 530  
 531      function photos_getContactsPhotos ($count = NULL, $just_friends = NULL, $single_photo = NULL, $include_self = NULL, $extras = NULL)
 532      {
 533          /** http://www.flickr.com/services/api/flickr.photos.getContactsPhotos.html */
 534          $this->request("flickr.photos.getContactsPhotos", array("count"=>$count, "just_friends"=>$just_friends, "single_photo"=>$single_photo, "include_self"=>$include_self, "extras"=>$extras));
 535          return $this->parsed_response ? $this->parsed_response['photos']['photo'] : false;
 536      }
 537  
 538      function photos_getContactsPublicPhotos ($user_id, $count = NULL, $just_friends = NULL, $single_photo = NULL, $include_self = NULL, $extras = NULL)
 539      {
 540          /** http://www.flickr.com/services/api/flickr.photos.getContactsPublicPhotos.html */
 541          $this->request("flickr.photos.getContactsPublicPhotos", array("user_id"=>$user_id, "count"=>$count, "just_friends"=>$just_friends, "single_photo"=>$single_photo, "include_self"=>$include_self, "extras"=>$extras));
 542          return $this->parsed_response ? $this->parsed_response['photos']['photo'] : false;
 543      }
 544  
 545      function photos_getContext ($photo_id)
 546      {
 547          /** http://www.flickr.com/services/api/flickr.photos.getContext.html */
 548          $this->request("flickr.photos.getContext", array("photo_id"=>$photo_id));
 549          return $this->parsed_response ? $this->parsed_response : false;
 550      }
 551  
 552      function photos_getCounts ($dates = NULL, $taken_dates = NULL)
 553      {
 554          /** http://www.flickr.com/services/api/flickr.photos.getCounts.html */
 555          $this->request("flickr.photos.getCounts", array("dates"=>$dates, "taken_dates"=>$taken_dates));
 556          return $this->parsed_response ? $this->parsed_response['photocounts']['photocount'] : false;
 557      }
 558  
 559      function photos_getExif ($photo_id, $secret = NULL)
 560      {
 561          /** http://www.flickr.com/services/api/flickr.photos.getExif.html */
 562          $this->request("flickr.photos.getExif", array("photo_id"=>$photo_id, "secret"=>$secret));
 563          return $this->parsed_response ? $this->parsed_response['photo'] : false;
 564      }
 565  
 566      function photos_getFavorites($photo_id, $page = NULL, $per_page = NULL)
 567      {
 568          /** http://www.flickr.com/services/api/flickr.photos.getFavorites.html */
 569          $this->request("flickr.photos.getFavorites", array("photo_id"=>$photo_id, "page"=>$page, "per_page"=>$per_page));
 570          return $this->parsed_response ? $this->parsed_response['photo'] : false;
 571      }
 572  
 573      function photos_getInfo($photo_id, $secret = NULL)
 574      {
 575          /** http://www.flickr.com/services/api/flickr.photos.getInfo.html */
 576          $this->request("flickr.photos.getInfo", array("photo_id"=>$photo_id, "secret"=>$secret));
 577          return $this->parsed_response ? $this->parsed_response['photo'] : false;
 578      }
 579  
 580      function photos_getNotInSet($min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL, $privacy_filter = NULL, $extras = NULL, $per_page = NULL, $page = NULL)
 581      {
 582          /** http://www.flickr.com/services/api/flickr.photos.getNotInSet.html */
 583          if (is_array($extras)) {
 584              $extras = implode(",", $extras);
 585          }
 586          $this->request("flickr.photos.getNotInSet", array("min_upload_date"=>$min_upload_date, "max_upload_date"=>$max_upload_date, "min_taken_date"=>$min_taken_date, "max_taken_date"=>$max_taken_date, "privacy_filter"=>$privacy_filter, "extras"=>$extras, "per_page"=>$per_page, "page"=>$page));
 587          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 588      }
 589  
 590      function photos_getPerms($photo_id)
 591      {
 592          /** http://www.flickr.com/services/api/flickr.photos.getPerms.html */
 593          $this->request("flickr.photos.getPerms", array("photo_id"=>$photo_id));
 594          return $this->parsed_response ? $this->parsed_response['perms'] : false;
 595      }
 596  
 597      function photos_getRecent($extras = NULL, $per_page = NULL, $page = NULL)
 598      {
 599          /** http://www.flickr.com/services/api/flickr.photos.getRecent.html */
 600  
 601          if (is_array($extras)) {
 602              $extras = implode(",", $extras);
 603          }
 604          $this->request("flickr.photos.getRecent", array("extras"=>$extras, "per_page"=>$per_page, "page"=>$page));
 605          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 606      }
 607  
 608      function photos_getSizes($photo_id)
 609      {
 610          /** http://www.flickr.com/services/api/flickr.photos.getSizes.html */
 611          $this->request("flickr.photos.getSizes", array("photo_id"=>$photo_id));
 612          return $this->parsed_response ? $this->parsed_response['sizes']['size'] : false;
 613      }
 614  
 615      function photos_getUntagged($min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL, $privacy_filter = NULL, $extras = NULL, $per_page = NULL, $page = NULL)
 616      {
 617          /** http://www.flickr.com/services/api/flickr.photos.getUntagged.html */
 618          if (is_array($extras)) {
 619              $extras = implode(",", $extras);
 620          }
 621          $this->request("flickr.photos.getUntagged", array("min_upload_date"=>$min_upload_date, "max_upload_date"=>$max_upload_date, "min_taken_date"=>$min_taken_date, "max_taken_date"=>$max_taken_date, "privacy_filter"=>$privacy_filter, "extras"=>$extras, "per_page"=>$per_page, "page"=>$page));
 622          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 623      }
 624  
 625      function photos_getWithGeoData($args = NULL) {
 626          /** See the documentation included with the photos_search() function.
 627           * I'm using the same style of arguments for this function. The only
 628           * difference here is that this doesn't require any arguments. The
 629           * flickr.photos.search method requires at least one search parameter.
 630           */
 631          /** http://www.flickr.com/services/api/flickr.photos.getWithGeoData.html */
 632          if (is_null($args)) {
 633              $args = array();
 634          }
 635          $this->request("flickr.photos.getWithGeoData", $args);
 636          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 637      }
 638  
 639      function photos_getWithoutGeoData($args = NULL) {
 640          /** See the documentation included with the photos_search() function.
 641           * I'm using the same style of arguments for this function. The only
 642           * difference here is that this doesn't require any arguments. The
 643           * flickr.photos.search method requires at least one search parameter.
 644           */
 645          /** http://www.flickr.com/services/api/flickr.photos.getWithoutGeoData.html */
 646          if (is_null($args)) {
 647              $args = array();
 648          }
 649          $this->request("flickr.photos.getWithoutGeoData", $args);
 650          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 651      }
 652  
 653      function photos_recentlyUpdated($min_date = NULL, $extras = NULL, $per_page = NULL, $page = NULL)
 654      {
 655          /** http://www.flickr.com/services/api/flickr.photos.getUntagged.html */
 656          if (is_array($extras)) {
 657              $extras = implode(",", $extras);
 658          }
 659          $this->request("flickr.photos.recentlyUpdated", array("min_date"=>$min_date, "extras"=>$extras, "per_page"=>$per_page, "page"=>$page));
 660          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 661      }
 662  
 663      function photos_removeTag($tag_id)
 664      {
 665          /** http://www.flickr.com/services/api/flickr.photos.removeTag.html */
 666          $this->request("flickr.photos.removeTag", array("tag_id"=>$tag_id), TRUE);
 667          return $this->parsed_response ? true : false;
 668      }
 669  
 670      function photos_search($args)
 671      {
 672          /** This function strays from the method of arguments that I've
 673           * used in the other functions for the fact that there are just
 674           * so many arguments to this API method. What you'll need to do
 675           * is pass an associative array to the function containing the
 676           * arguments you want to pass to the API.  For example:
 677           *   $photos = $f->photos_search(array("tags"=>"brown,cow", "tag_mode"=>"any"));
 678           * This will return photos tagged with either "brown" or "cow"
 679           * or both. See the API documentation (link below) for a full
 680           * list of arguments.
 681           */
 682  
 683          /** http://www.flickr.com/services/api/flickr.photos.search.html */
 684          $this->request("flickr.photos.search", $args);
 685          return $this->parsed_response ? $this->parsed_response['photos'] : false;
 686      }
 687  
 688      function photos_setContentType ($photo_id, $content_type) {
 689          /** http://www.flickr.com/services/api/flickr.photos.setContentType.html */
 690          return $this->call('flickr.photos.setContentType', array('photo_id' => $photo_id, 'content_type' => $content_type));
 691      }
 692  
 693      function photos_setDates($photo_id, $date_posted = NULL, $date_taken = NULL, $date_taken_granularity = NULL)
 694      {
 695          /** http://www.flickr.com/services/api/flickr.photos.setDates.html */
 696          $this->request("flickr.photos.setDates", array("photo_id"=>$photo_id, "date_posted"=>$date_posted, "date_taken"=>$date_taken, "date_taken_granularity"=>$date_taken_granularity), TRUE);
 697          return $this->parsed_response ? true : false;
 698      }
 699  
 700      function photos_setMeta($photo_id, $title, $description)
 701      {
 702          /** http://www.flickr.com/services/api/flickr.photos.setMeta.html */
 703          $this->request("flickr.photos.setMeta", array("photo_id"=>$photo_id, "title"=>$title, "description"=>$description), TRUE);
 704          return $this->parsed_response ? true : false;
 705      }
 706  
 707      function photos_setPerms($photo_id, $is_public, $is_friend, $is_family, $perm_comment, $perm_addmeta)
 708      {
 709          /** http://www.flickr.com/services/api/flickr.photos.setPerms.html */
 710          $this->request("flickr.photos.setPerms", array("photo_id"=>$photo_id, "is_public"=>$is_public, "is_friend"=>$is_friend, "is_family"=>$is_family, "perm_comment"=>$perm_comment, "perm_addmeta"=>$perm_addmeta), TRUE);
 711          return $this->parsed_response ? true : false;
 712      }
 713  
 714      function photos_setSafetyLevel ($photo_id, $safety_level, $hidden = null) {
 715          /** http://www.flickr.com/services/api/flickr.photos.setSafetyLevel.html */
 716          return $this->call('flickr.photos.setSafetyLevel', array('photo_id' => $photo_id, 'safety_level' => $safety_level, 'hidden' => $hidden));
 717      }
 718  
 719  
 720      function photos_setTags($photo_id, $tags)
 721      {
 722          /** http://www.flickr.com/services/api/flickr.photos.setTags.html */
 723          $this->request("flickr.photos.setTags", array("photo_id"=>$photo_id, "tags"=>$tags), TRUE);
 724          return $this->parsed_response ? true : false;
 725      }
 726  
 727      /** Photos - Comments Methods */
 728      function photos_comments_addComment($photo_id, $comment_text) {
 729          /** http://www.flickr.com/services/api/flickr.photos.comments.addComment.html */
 730          $this->request("flickr.photos.comments.addComment", array("photo_id" => $photo_id, "comment_text"=>$comment_text), TRUE);
 731          return $this->parsed_response ? $this->parsed_response['comment'] : false;
 732      }
 733  
 734      function photos_comments_deleteComment($comment_id) {
 735          /** http://www.flickr.com/services/api/flickr.photos.comments.deleteComment.html */
 736          $this->request("flickr.photos.comments.deleteComment", array("comment_id" => $comment_id), TRUE);
 737          return $this->parsed_response ? true : false;
 738      }
 739  
 740      function photos_comments_editComment($comment_id, $comment_text) {
 741          /** http://www.flickr.com/services/api/flickr.photos.comments.editComment.html */
 742          $this->request("flickr.photos.comments.editComment", array("comment_id" => $comment_id, "comment_text"=>$comment_text), TRUE);
 743          return $this->parsed_response ? true : false;
 744      }
 745  
 746      function photos_comments_getList($photo_id)
 747      {
 748          /** http://www.flickr.com/services/api/flickr.photos.comments.getList.html */
 749          $this->request("flickr.photos.comments.getList", array("photo_id"=>$photo_id));
 750          return $this->parsed_response ? $this->parsed_response['comments'] : false;
 751      }
 752  
 753      /** Photos - Geo Methods */
 754      function photos_geo_getLocation($photo_id)
 755      {
 756          /** http://www.flickr.com/services/api/flickr.photos.geo.getLocation.html */
 757          $this->request("flickr.photos.geo.getLocation", array("photo_id"=>$photo_id));
 758          return $this->parsed_response ? $this->parsed_response['photo'] : false;
 759      }
 760  
 761      function photos_geo_getPerms($photo_id)
 762      {
 763          /** http://www.flickr.com/services/api/flickr.photos.geo.getPerms.html */
 764          $this->request("flickr.photos.geo.getPerms", array("photo_id"=>$photo_id));
 765          return $this->parsed_response ? $this->parsed_response['perms'] : false;
 766      }
 767  
 768      function photos_geo_removeLocation($photo_id)
 769      {
 770          /** http://www.flickr.com/services/api/flickr.photos.geo.removeLocation.html */
 771          $this->request("flickr.photos.geo.removeLocation", array("photo_id"=>$photo_id), TRUE);
 772          return $this->parsed_response ? true : false;
 773      }
 774  
 775      function photos_geo_setLocation($photo_id, $lat, $lon, $accuracy = NULL)
 776      {
 777          /** http://www.flickr.com/services/api/flickr.photos.geo.setLocation.html */
 778          $this->request("flickr.photos.geo.setLocation", array("photo_id"=>$photo_id, "lat"=>$lat, "lon"=>$lon, "accuracy"=>$accuracy), TRUE);
 779          return $this->parsed_response ? true : false;
 780      }
 781  
 782      function photos_geo_setPerms($photo_id, $is_public, $is_contact, $is_friend, $is_family)
 783      {
 784          /** http://www.flickr.com/services/api/flickr.photos.geo.setPerms.html */
 785          $this->request("flickr.photos.geo.setPerms", array("photo_id"=>$photo_id, "is_public"=>$is_public, "is_contact"=>$is_contact, "is_friend"=>$is_friend, "is_family"=>$is_family), TRUE);
 786          return $this->parsed_response ? true : false;
 787      }
 788  
 789      /** Photos - Licenses Methods */
 790      function photos_licenses_getInfo()
 791      {
 792          /** http://www.flickr.com/services/api/flickr.photos.licenses.getInfo.html */
 793          $this->request("flickr.photos.licenses.getInfo");
 794          return $this->parsed_response ? $this->parsed_response['licenses']['license'] : false;
 795      }
 796  
 797      function photos_licenses_setLicense($photo_id, $license_id)
 798      {
 799          /** http://www.flickr.com/services/api/flickr.photos.licenses.setLicense.html */
 800          /** Requires Authentication */
 801          $this->request("flickr.photos.licenses.setLicense", array("photo_id"=>$photo_id, "license_id"=>$license_id), TRUE);
 802          return $this->parsed_response ? true : false;
 803      }
 804  
 805      /** Photos - Notes Methods */
 806      function photos_notes_add($photo_id, $note_x, $note_y, $note_w, $note_h, $note_text)
 807      {
 808          /** http://www.flickr.com/services/api/flickr.photos.notes.add.html */
 809          $this->request("flickr.photos.notes.add", array("photo_id" => $photo_id, "note_x" => $note_x, "note_y" => $note_y, "note_w" => $note_w, "note_h" => $note_h, "note_text" => $note_text), TRUE);
 810          return $this->parsed_response ? $this->parsed_response['note'] : false;
 811      }
 812  
 813      function photos_notes_delete($note_id)
 814      {
 815          /** http://www.flickr.com/services/api/flickr.photos.notes.delete.html */
 816          $this->request("flickr.photos.notes.delete", array("note_id" => $note_id), TRUE);
 817          return $this->parsed_response ? true : false;
 818      }
 819  
 820      function photos_notes_edit($note_id, $note_x, $note_y, $note_w, $note_h, $note_text)
 821      {
 822          /** http://www.flickr.com/services/api/flickr.photos.notes.edit.html */
 823          $this->request("flickr.photos.notes.edit", array("note_id" => $note_id, "note_x" => $note_x, "note_y" => $note_y, "note_w" => $note_w, "note_h" => $note_h, "note_text" => $note_text), TRUE);
 824          return $this->parsed_response ? true : false;
 825      }
 826  
 827      /** Photos - Transform Methods */
 828      function photos_transform_rotate($photo_id, $degrees)
 829      {
 830          /** http://www.flickr.com/services/api/flickr.photos.transform.rotate.html */
 831          $this->request("flickr.photos.transform.rotate", array("photo_id" => $photo_id, "degrees" => $degrees), TRUE);
 832          return $this->parsed_response ? true : false;
 833      }
 834  
 835      /** Photos - Upload Methods */
 836      function photos_upload_checkTickets($tickets)
 837      {
 838          /** http://www.flickr.com/services/api/flickr.photos.upload.checkTickets.html */
 839          if (is_array($tickets)) {
 840              $tickets = implode(",", $tickets);
 841          }
 842          $this->request("flickr.photos.upload.checkTickets", array("tickets" => $tickets), TRUE);
 843          return $this->parsed_response ? $this->parsed_response['uploader']['ticket'] : false;
 844      }
 845  
 846      /** Photosets Methods */
 847      function photosets_addPhoto($photoset_id, $photo_id)
 848      {
 849          /** http://www.flickr.com/services/api/flickr.photosets.addPhoto.html */
 850          $this->request("flickr.photosets.addPhoto", array("photoset_id" => $photoset_id, "photo_id" => $photo_id), TRUE);
 851          return $this->parsed_response ? true : false;
 852      }
 853  
 854      function photosets_create($title, $description, $primary_photo_id)
 855      {
 856          /** http://www.flickr.com/services/api/flickr.photosets.create.html */
 857          $this->request("flickr.photosets.create", array("title" => $title, "primary_photo_id" => $primary_photo_id, "description" => $description), TRUE);
 858          return $this->parsed_response ? $this->parsed_response['photoset'] : false;
 859      }
 860  
 861      function photosets_delete($photoset_id)
 862      {
 863          /** http://www.flickr.com/services/api/flickr.photosets.delete.html */
 864          $this->request("flickr.photosets.delete", array("photoset_id" => $photoset_id), TRUE);
 865          return $this->parsed_response ? true : false;
 866      }
 867  
 868      function photosets_editMeta($photoset_id, $title, $description = NULL)
 869      {
 870          /** http://www.flickr.com/services/api/flickr.photosets.editMeta.html */
 871          $this->request("flickr.photosets.editMeta", array("photoset_id" => $photoset_id, "title" => $title, "description" => $description), TRUE);
 872          return $this->parsed_response ? true : false;
 873      }
 874  
 875      function photosets_editPhotos($photoset_id, $primary_photo_id, $photo_ids)
 876      {
 877          /** http://www.flickr.com/services/api/flickr.photosets.editPhotos.html */
 878          $this->request("flickr.photosets.editPhotos", array("photoset_id" => $photoset_id, "primary_photo_id" => $primary_photo_id, "photo_ids" => $photo_ids), TRUE);
 879          return $this->parsed_response ? true : false;
 880      }
 881  
 882      function photosets_getContext($photo_id, $photoset_id)
 883      {
 884          /** http://www.flickr.com/services/api/flickr.photosets.getContext.html */
 885          $this->request("flickr.photosets.getContext", array("photo_id" => $photo_id, "photoset_id" => $photoset_id));
 886          return $this->parsed_response ? $this->parsed_response : false;
 887      }
 888  
 889      function photosets_getInfo($photoset_id)
 890      {
 891          /** http://www.flickr.com/services/api/flickr.photosets.getInfo.html */
 892          $this->request("flickr.photosets.getInfo", array("photoset_id" => $photoset_id));
 893          return $this->parsed_response ? $this->parsed_response['photoset'] : false;
 894      }
 895  
 896      function photosets_getList($user_id = NULL)
 897      {
 898          /** http://www.flickr.com/services/api/flickr.photosets.getList.html */
 899          $this->request("flickr.photosets.getList", array("user_id" => $user_id));
 900          return $this->parsed_response ? $this->parsed_response['photosets'] : false;
 901      }
 902  
 903      function photosets_getPhotos($photoset_id, $extras = NULL, $privacy_filter = NULL, $per_page = NULL, $page = NULL)
 904      {
 905          /** http://www.flickr.com/services/api/flickr.photosets.getPhotos.html */
 906          $this->request("flickr.photosets.getPhotos", array("photoset_id" => $photoset_id, "extras" => $extras, "privacy_filter" => $privacy_filter, "per_page" => $per_page, "page" => $page));
 907          return $this->parsed_response ? $this->parsed_response['photoset'] : false;
 908      }
 909  
 910      function photosets_orderSets($photoset_ids)
 911      {
 912          /** http://www.flickr.com/services/api/flickr.photosets.orderSets.html */
 913          if (is_array($photoset_ids)) {
 914              $photoset_ids = implode(",", $photoset_ids);
 915          }
 916          $this->request("flickr.photosets.orderSets", array("photoset_ids" => $photoset_ids), TRUE);
 917          return $this->parsed_response ? true : false;
 918      }
 919  
 920      function photosets_removePhoto($photoset_id, $photo_id)
 921      {
 922          /** http://www.flickr.com/services/api/flickr.photosets.removePhoto.html */
 923          $this->request("flickr.photosets.removePhoto", array("photoset_id" => $photoset_id, "photo_id" => $photo_id), TRUE);
 924          return $this->parsed_response ? true : false;
 925      }
 926  
 927      /** Photosets Comments Methods */
 928      function photosets_comments_addComment($photoset_id, $comment_text) {
 929          /** http://www.flickr.com/services/api/flickr.photosets.comments.addComment.html */
 930          $this->request("flickr.photosets.comments.addComment", array("photoset_id" => $photoset_id, "comment_text"=>$comment_text), TRUE);
 931          return $this->parsed_response ? $this->parsed_response['comment'] : false;
 932      }
 933  
 934      function photosets_comments_deleteComment($comment_id) {
 935          /** http://www.flickr.com/services/api/flickr.photosets.comments.deleteComment.html */
 936          $this->request("flickr.photosets.comments.deleteComment", array("comment_id" => $comment_id), TRUE);
 937          return $this->parsed_response ? true : false;
 938      }
 939  
 940      function photosets_comments_editComment($comment_id, $comment_text) {
 941          /** http://www.flickr.com/services/api/flickr.photosets.comments.editComment.html */
 942          $this->request("flickr.photosets.comments.editComment", array("comment_id" => $comment_id, "comment_text"=>$comment_text), TRUE);
 943          return $this->parsed_response ? true : false;
 944      }
 945  
 946      function photosets_comments_getList($photoset_id)
 947      {
 948          /** http://www.flickr.com/services/api/flickr.photosets.comments.getList.html */
 949          $this->request("flickr.photosets.comments.getList", array("photoset_id"=>$photoset_id));
 950          return $this->parsed_response ? $this->parsed_response['comments'] : false;
 951      }
 952  
 953      /** Places Methods */
 954      function places_resolvePlaceId ($place_id) {
 955          /** http://www.flickr.com/services/api/flickr.places.resolvePlaceId.html */
 956          $rsp = $this->call('flickr.places.resolvePlaceId', array('place_id' => $place_id));
 957          return $rsp ? $rsp['location'] : $rsp;
 958      }
 959  
 960      function places_resolvePlaceURL ($url) {
 961          /** http://www.flickr.com/services/api/flickr.places.resolvePlaceURL.html */
 962          $rsp = $this->call('flickr.places.resolvePlaceURL', array('url' => $url));
 963          return $rsp ? $rsp['location'] : $rsp;
 964      }
 965  
 966      /** Prefs Methods */
 967      function prefs_getContentType () {
 968          /** http://www.flickr.com/services/api/flickr.prefs.getContentType.html */
 969          $rsp = $this->call('flickr.prefs.getContentType', array());
 970          return $rsp ? $rsp['person'] : $rsp;
 971      }
 972  
 973      function prefs_getHidden () {
 974          /** http://www.flickr.com/services/api/flickr.prefs.getHidden.html */
 975          $rsp = $this->call('flickr.prefs.getHidden', array());
 976          return $rsp ? $rsp['person'] : $rsp;
 977      }
 978  
 979      function prefs_getPrivacy () {
 980          /** http://www.flickr.com/services/api/flickr.prefs.getPrivacy.html */
 981          $rsp = $this->call('flickr.prefs.getPrivacy', array());
 982          return $rsp ? $rsp['person'] : $rsp;
 983      }
 984  
 985      function prefs_getSafetyLevel () {
 986          /** http://www.flickr.com/services/api/flickr.prefs.getSafetyLevel.html */
 987          $rsp = $this->call('flickr.prefs.getSafetyLevel', array());
 988          return $rsp ? $rsp['person'] : $rsp;
 989      }
 990  
 991      /** Reflection Methods */
 992      function reflection_getMethodInfo($method_name)
 993      {
 994          /** http://www.flickr.com/services/api/flickr.reflection.getMethodInfo.html */
 995          $this->request("flickr.reflection.getMethodInfo", array("method_name" => $method_name));
 996          return $this->parsed_response ? $this->parsed_response : false;
 997      }
 998  
 999      function reflection_getMethods()
1000      {
1001          /** http://www.flickr.com/services/api/flickr.reflection.getMethods.html */
1002          $this->request("flickr.reflection.getMethods");
1003          return $this->parsed_response ? $this->parsed_response['methods']['method'] : false;
1004      }
1005  
1006      /** Tags Methods */
1007      function tags_getHotList($period = NULL, $count = NULL)
1008      {
1009          /** http://www.flickr.com/services/api/flickr.tags.getHotList.html */
1010          $this->request("flickr.tags.getHotList", array("period" => $period, "count" => $count));
1011          return $this->parsed_response ? $this->parsed_response['hottags'] : false;
1012      }
1013  
1014      function tags_getListPhoto($photo_id)
1015      {
1016          /** http://www.flickr.com/services/api/flickr.tags.getListPhoto.html */
1017          $this->request("flickr.tags.getListPhoto", array("photo_id" => $photo_id));
1018          return $this->parsed_response ? $this->parsed_response['photo']['tags']['tag'] : false;
1019      }
1020  
1021      function tags_getListUser($user_id = NULL)
1022      {
1023          /** http://www.flickr.com/services/api/flickr.tags.getListUser.html */
1024          $this->request("flickr.tags.getListUser", array("user_id" => $user_id));
1025          return $this->parsed_response ? $this->parsed_response['who']['tags']['tag'] : false;
1026      }
1027  
1028      function tags_getListUserPopular($user_id = NULL, $count = NULL)
1029      {
1030          /** http://www.flickr.com/services/api/flickr.tags.getListUserPopular.html */
1031          $this->request("flickr.tags.getListUserPopular", array("user_id" => $user_id, "count" => $count));
1032          return $this->parsed_response ? $this->parsed_response['who']['tags']['tag'] : false;
1033      }
1034  
1035      function tags_getListUserRaw($tag)
1036      {
1037          /** http://www.flickr.com/services/api/flickr.tags.getListUserRaw.html */
1038          $this->request("flickr.tags.getListUserRaw", array("tag" => $tag));
1039          return $this->parsed_response ? $this->parsed_response['who']['tags']['tag'][0]['raw'] : false;
1040      }
1041  
1042      function tags_getRelated($tag)
1043      {
1044          /** http://www.flickr.com/services/api/flickr.tags.getRelated.html */
1045          $this->request("flickr.tags.getRelated", array("tag" => $tag));
1046          return $this->parsed_response ? $this->parsed_response['tags'] : false;
1047      }
1048  
1049      function test_echo($args = array())
1050      {
1051          /** http://www.flickr.com/services/api/flickr.test.echo.html */
1052          $this->request("flickr.test.echo", $args);
1053          return $this->parsed_response ? $this->parsed_response : false;
1054      }
1055  
1056      function test_login()
1057      {
1058          /** http://www.flickr.com/services/api/flickr.test.login.html */
1059          $this->request("flickr.test.login");
1060          return $this->parsed_response ? $this->parsed_response['user'] : false;
1061      }
1062  
1063      function urls_getGroup($group_id)
1064      {
1065          /** http://www.flickr.com/services/api/flickr.urls.getGroup.html */
1066          $this->request("flickr.urls.getGroup", array("group_id"=>$group_id));
1067          return $this->parsed_response ? $this->parsed_response['group']['url'] : false;
1068      }
1069  
1070      function urls_getUserPhotos($user_id = NULL)
1071      {
1072          /** http://www.flickr.com/services/api/flickr.urls.getUserPhotos.html */
1073          $this->request("flickr.urls.getUserPhotos", array("user_id"=>$user_id));
1074          return $this->parsed_response ? $this->parsed_response['user']['url'] : false;
1075      }
1076  
1077      function urls_getUserProfile($user_id = NULL)
1078      {
1079          /** http://www.flickr.com/services/api/flickr.urls.getUserProfile.html */
1080          $this->request("flickr.urls.getUserProfile", array("user_id"=>$user_id));
1081          return $this->parsed_response ? $this->parsed_response['user']['url'] : false;
1082      }
1083  
1084      function urls_lookupGroup($url)
1085      {
1086          /** http://www.flickr.com/services/api/flickr.urls.lookupGroup.html */
1087          $this->request("flickr.urls.lookupGroup", array("url"=>$url));
1088          return $this->parsed_response ? $this->parsed_response['group'] : false;
1089      }
1090  
1091      function urls_lookupUser($url)
1092      {
1093          /** http://www.flickr.com/services/api/flickr.photos.notes.edit.html */
1094          $this->request("flickr.urls.lookupUser", array("url"=>$url));
1095          return $this->parsed_response ? $this->parsed_response['user'] : false;
1096      }
1097  
1098      /**
1099       * Upload a photo from Moodle file pool to Flickr
1100       *
1101       * Optional meta information are title, description, tags, is_public, is_friend, is_family, safety_level,
1102       * content_type and hidden {@see http://www.flickr.com/services/api/upload.api.html}
1103       *
1104       * @param stored_file $photo stored in Moodle file pool
1105       * @param array $meta optional meta information
1106       * @return boolean
1107       */
1108      function upload(stored_file $photo, array $meta = array()) {
1109  
1110          $args = array();
1111  
1112          $args['title']          = isset($meta['title']) ? $meta['title'] : null;
1113          $args['description']    = isset($meta['description']) ? $meta['description'] : null;
1114          $args['tags']           = isset($meta['tags']) ? $meta['tags'] : null;
1115          $args['is_public']      = isset($meta['is_public']) ? $meta['is_public'] : 0;
1116          $args['is_friend']      = isset($meta['is_friend']) ? $meta['is_friend'] : 0;
1117          $args['is_family']      = isset($meta['is_family']) ? $meta['is_family'] : 0;
1118          $args['safety_level']   = isset($meta['safety_level']) ? $meta['safety_level'] : 1; // safe by default
1119          $args['content_type']   = isset($meta['content_type']) ? $meta['content_type'] : 1; // photo by default
1120          $args['hidden']         = isset($meta['hidden']) ? $meta['hidden'] : 2;             // hide from public searches by default
1121  
1122          // Do not enable the asynchronous more because then the query does not return a photo ID,
1123          // and we need a photo ID to add the photo to a set later on.
1124          // $args['async'] = 1;
1125          $args['api_key'] = $this->api_key;
1126  
1127          if (!empty($this->email)) {
1128              $args['email'] = $this->email;
1129          }
1130          if (!empty($this->password)) {
1131              $args['password'] = $this->password;
1132          }
1133          if (!empty($this->token)) {
1134              $args['auth_token'] = $this->token;
1135          }
1136  
1137          // sign the arguments using the shared secret
1138          ksort($args);
1139          $auth_sig = '';
1140          foreach ($args as $key => $data) {
1141              if (!is_null($data)) {
1142                  $auth_sig .= $key . $data;
1143              } else {
1144                  unset($args[$key]);
1145              }
1146          }
1147          if (!empty($this->secret)) {
1148              $api_sig = md5($this->secret . $auth_sig);
1149              $args['api_sig'] = $api_sig;
1150          }
1151  
1152          $args['photo'] = $photo; // $this->curl will process it correctly
1153  
1154          if ($response = $this->curl->post($this->Upload, $args)) {
1155              $xml = simplexml_load_string($response);
1156              if ($xml['stat'] == 'fail') {
1157                  $this->parsed_response = array('stat' => (string) $xml['stat'], 'code' => (int) $xml->err['code'],
1158                      'message' => (string) $xml->err['msg']);
1159              } elseif ($xml['stat'] == 'ok') {
1160                  $this->parsed_response = array('stat' => (string) $xml['stat'], 'photoid' => (int) $xml->photoid);
1161              }
1162              return true;
1163          } else {
1164              $this->parsed_response = array('stat' => 'fail', 'code' => $this->curl->get_errno(),
1165                  'message' => $this->curl->error);
1166              return false;
1167          }
1168      }
1169  }