Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.
/lib/ -> flickrlib.php (source)

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