Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
/lib/ -> flickrlib.php (source)

Differences Between: [Versions 310 and 311] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]

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