You are here

media_flickr.utilities.inc in Media: Flickr 7.2

Same filename and directory in other branches
  1. 7 includes/media_flickr.utilities.inc

Utility functions for Media: Flickr.

File

includes/media_flickr.utilities.inc
View source
<?php

/**
 *  @file
 *  Utility functions for Media: Flickr.
 */

/**
 *  Based on the Photo ID of a Flickr image, this will return the URL to the
 *  image itself.
 *
 *  @param $photo_id
 *    The Flickr photo code.
 *  @param $width
 *  @param $height
 *    We use this to guess the actual size provided by Flickr.
 *  @param $cached
 *    If TRUE, then we'll cache the remote URL if the attempt to save the file
 *    locally fails.
 */
function _media_flickr_photo_url($photo_id, $width = 0, $height = 0, $cached = TRUE) {
  if ($photo_id) {
    $size = _media_flickr_guess_size($width, $height);
    return _media_flickr_photo_url_from_size($photo_id, $size);
  }
}

/**
 *  This returns a cached photo stream from the Flickr farm servers.
 */
function _media_flickr_photo_remote_url($photo_id, $size) {
  $getsize = _media_flickr_sets_request('flickr.photos.getSizes', array(
    'photo_id' => $photo_id,
  ));
  if ($getsize && $getsize['@attributes']['stat'] !== 'fail') {

    // If no size was requested, or if a size was requested that doesn't exist
    // (e.g. for small images, the sizes 0..4 that _media_flickr_guess_size
    // assumes may not actually be there), use the largest size available,
    // which is the original image.
    $number_of_sizes = count($getsize['sizes']['size']);
    if (!isset($size) || $size >= $number_of_sizes) {
      $size = $number_of_sizes - 1;
    }
    return $getsize['sizes']['size'][$size]['@attributes']['source'];
  }
}

/**
 *  This is a wrapper for emfield_request_xml that includes flickr's api key.
 *
 *  @param string $method
 *  @param array $args
 *
 *  @return object
 *    A fully populated SimpleXML object.
 */
function _media_flickr_sets_request($method, $args = array()) {

  // Display an error if we don't have an API key yet.
  if (!_media_flickr_error_check()) {
    return array();
  }
  $args['api_key'] = trim(variable_get('media_flickr_api_key', ''));
  if ($secret = trim(variable_get('media_flickr_api_secret', ''))) {
    $args['secret'] = md5($secret);
  }
  $args['method'] = $method;
  $request = drupal_http_request(url(MEDIA_FLICKR_RESTPOINT, array(
    'query' => $args,
  )));
  if (!isset($request->error)) {
    $entry = simplexml_load_string($request->data);
  }
  else {
    throw new Exception("Error Processing Request. (Error: {$request->code}, {$request->error})");

    // If request wasn't successful, create object for return to avoid errors.
    $entry = new SimpleXMLElement();
  }
  return media_flickr_unserialize_xml($entry);
}

/**
 * Recursively converts a SimpleXMLElement object into an array.
 *
 * @param object $xml
 *   The original XML object.
 */
function media_flickr_unserialize_xml($xml) {
  if ($xml instanceof SimpleXMLElement) {
    $xml = (array) $xml;
  }
  if (is_array($xml)) {
    foreach ($xml as $key => $item) {
      $xml[$key] = media_flickr_unserialize_xml($item);
    }
  }
  return $xml;
}

/**
 *  This will log an error if we don't have a key yet.
 *  In addition, if the user is an admin, we'll display an error.
 */
function _media_flickr_error_check() {
  static $checked;
  if (is_null($checked)) {
    if (variable_get('media_flickr_api_key', '') == '') {
      $error = 'You do not yet have a Flickr API key set. You will need to !apply and enter your key at the !settings before Flickr images may be displayed.';
      $arguments = array(
        '!apply' => l(t('apply for a Flickr API key'), MEDIA_FLICKR_API_APPLICATION_URL),
        '!settings' => l(t('Flickr administration page'), 'admin/config/media/media-flickr'),
      );
      if (user_access('administer site configuration')) {
        drupal_set_message(t($error, $arguments), 'error');
      }
      watchdog('media_flickr', $error, $arguments);
      $checked = FALSE;
    }
    else {
      $checked = TRUE;
    }
  }
  return $checked;
}

/**
 *  This will return the appropriate array key for the image size we wish.
 *
 * @param int $height
 * @param int $width
 *
 * @return int
 */
function _media_flickr_guess_size($width = 0, $height = 0) {
  $max = max($width, $height);
  if ($max) {
    foreach (array(
      '0' => 75,
      '1' => 100,
      '2' => 240,
      '3' => 500,
      '4' => 1024,
    ) as $size => $value) {
      if ($max <= $value) {
        return $size;
      }
    }
  }

  // If we don't have width or height set, then get the original size.
  return NULL;
}
function _media_flickr_photo_url_from_size($photo_id, $size = NULL) {

  // Check to make sure we have a valid photo code.
  if (is_numeric($photo_id)) {
    $filepath = _media_flickr_photo_remote_url($photo_id, $size);

    // URLize that path...
    $filepath = url($filepath, array(
      'absolute' => TRUE,
    ));
    return $filepath;
  }
}
function _media_flickr_photoset_photo_id($uri, $refresh = FALSE) {
  $wrapper = file_stream_wrapper_get_instance_by_uri($uri);
  $parts = $wrapper
    ->get_parameters();
  if (isset($parts['search'])) {
    $photos = _media_flickr_sets_request('flickr.photos.search', array(
      'text' => $parts['search'],
      'per_page' => 1,
      'media' => 'photos',
    ));
    if ($photos && $photos['@attributes']['stat'] !== 'fail') {
      return $photos['photos']['photo']['@attributes']['id'];
    }
  }
  elseif (isset($parts['s'])) {
    if ($parts['s'] === 'photostream') {
      if (isset($parts['u'])) {
        $photos = _media_flickr_sets_request('flickr.people.getPublicPhotos', array(
          'user_id' => $parts['u'],
          'per_page' => 1,
          'media' => 'photos',
        ));
        if ($photos && $photos['@attributes']['stat'] !== 'fail') {
          return $photos['photos']['photo']['@attributes']['id'];
        }
      }
    }
    else {
      $photos = _media_flickr_sets_request('flickr.photosets.getPhotos', array(
        'photoset_id' => $parts['s'],
        'per_page' => 1,
        'media' => 'photos',
      ));
      if ($photos && $photos['@attributes']['stat'] !== 'fail') {
        return $photos['photoset']['photo']['@attributes']['id'];
      }
    }
  }
}
function _media_flickr_photoset_image_url($uri, $width = 0, $height = 0, $refresh = FALSE) {
  $photo_id = media_flickr_photoset_photo_id($uri, $refresh);
  return media_flickr_image_url($photo_id, $width, $height, $refresh);
}
function _media_flickr_original_url($uri, $refresh = FALSE) {
  $wrapper = file_stream_wrapper_get_instance_by_uri($uri);
  return $wrapper
    ->interpolateUrl();
}
function _media_flickr_photo_exists($photo_id) {
  $info = _media_flickr_sets_request('flickr.photos.getInfo', array(
    'photo_id' => $photo_id,
  ));
  return $info && $info['@attributes']['stat'] !== 'fail';
}
function _media_flickr_photoset_exists($photoset_id) {
  $info = _media_flickr_sets_request('flickr.photosets.getInfo', array(
    'photoset_id' => $photoset_id,
  ));
  return $info && $info['@attributes']['stat'] !== 'fail' ? TRUE : FALSE;
}

/**
 * Find Flickr user ID.
 *
 * @param array $parts
 *
 * @return string user NSID
 *   Return Flickr NSID. If nothing found, returns a empty string.
 * @throws \Exception
 */
function _media_flickr_get_user_id(array $parts) {
  $user_id = '';
  if (isset($parts['p'])) {
    $media_id = $parts['p'];
    $media_info = _media_flickr_sets_request('flickr.photos.getInfo', array(
      'photo_id' => $media_id,
    ));
    if ($media_info['@attributes']['stat'] !== 'fail') {
      $user_id = $media_info['photo']['owner']['@attributes']['nsid'];
    }
  }

  // It is is a photo set?
  if (isset($parts['s'])) {
    $media_id = $parts['s'];
    $media_info = _media_flickr_sets_request('flickr.photosets.getInfo', array(
      'photoset_id' => $media_id,
    ));
    if ($media_info['@attributes']['stat'] !== 'fail') {
      $user_id = $media_info['photoset']['@attributes']['owner'];
    }
  }
  return $user_id;
}

/**
 * Build the streamwrapper URI if the remote media exists.
 * @param array $parts
 *
 * @return string $uri
 */
function _media_flickr_build_uri($parts) {
  $user_id = _media_flickr_get_user_id($parts);
  if ($user_id) {
    $parts['u'] = $user_id;
  }
  if ($parts['u']) {
    if (isset($parts['p'])) {
      $uri = file_stream_wrapper_uri_normalize('flickr://u/' . $parts['u'] . "/p/" . $parts['p']);
      if (_media_flickr_photo_exists($parts['p'])) {
        return $uri;
      }
    }
    elseif (isset($parts['s'])) {
      $uri = file_stream_wrapper_uri_normalize('flickr://u/' . $parts['u'] . "/s/" . $parts['s']);
      if ($parts['s'] === 'photostream' || _media_flickr_photoset_exists($parts['s'])) {
        return $uri;
      }
    }
  }
  if (isset($parts['search'])) {
    return file_stream_wrapper_uri_normalize('flickr://search/' . $parts['search']);
  }
  return '';
}

/**
 * Flickr media parse helper function. Search the original url for valid data.
 *
 * @param $url
 *   The original URL or embed code to parse.
 *
 * @return string
 *   The unique URI for the file, based on its stream wrapper, or NULL.
 */
function _media_flickr_media_parse($url) {

  // Flickr short form URL.
  $patterns = array(
    '@flic\\.kr/(p|s)/([0-9A-Za-z]+)@i',
  );
  foreach ($patterns as $pattern) {
    preg_match($pattern, $url, $matches);
    if (isset($matches[1])) {
      $long_id = _media_flickr_shorturl($matches[2]);
      if ($long_id) {
        if ($matches[1] === 'p') {
          return _media_flickr_build_uri(array(
            'p' => $long_id,
          ));
        }
        return _media_flickr_build_uri(array(
          's' => $long_id,
        ));
      }
    }
  }

  // The following are single images.
  $patterns = array(
    '@flickr\\.com/photos/([0-9A-Za-z\\@\\&\\$_-]+)/([0-9]+)/in/photostream@i',
    '@flickr\\.com/photos/([0-9A-Za-z\\@\\&\\$_-]+)/([0-9]+)/in/set-([0-9]+)@i',
    '@flickr\\.com/photos/([0-9A-Za-z\\@\\&\\$_-]+)/([0-9]+)/in/faves-([0-9]+)@i',
    '@flickr\\.com/photos/([0-9A-Za-z\\@\\&\\$_-]+)/([0-9]+)/?$@i',
    '@flickr\\.com/photos/([0-9A-Za-z\\@\\&\\$_-]+)/([0-9]+)/in/pool-([0-9A-Za-z\\@\\&\\$_-]+)@i',
    '@flickr\\.com/photos/([0-9A-Za-z\\@\\&\\$_-]+)/([0-9]+)/in/explore-([0-9]+)@i',
    '@flickr\\.com/photos/([0-9A-Za-z\\@\\&\\$_-]+)/([0-9]+)/in/album-([0-9]+)@i',
  );
  foreach ($patterns as $pattern) {
    preg_match($pattern, $url, $matches);
    if (isset($matches[1]) && isset($matches[2])) {
      return _media_flickr_build_uri(array(
        'u' => $matches[1],
        'p' => $matches[2],
      ));
    }
  }

  // Next we look for photosets/albums.
  $patterns = array(
    '@flickr\\.com/photos/([0-9A-Za-z\\@\\&\\$_-]+)/sets/([0-9]+)@i',
    '@flickr\\.com/photos/([0-9A-Za-z\\@\\&\\$_-]+)/albums/([0-9]+)@i',
  );
  foreach ($patterns as $pattern) {
    preg_match($pattern, $url, $matches);
    if (isset($matches[1]) && isset($matches[2])) {
      return _media_flickr_build_uri(array(
        'u' => $matches[1],
        's' => $matches[2],
      ));
    }
  }

  // Then we look for photostreams of the entire user.
  $patterns = array(
    '@flickr\\.com/photos/([0-9A-Za-z\\@\\&\\$_-]+)/?$@i',
    '@flickr\\.com/photos/([0-9A-Za-z\\@\\&\\$_-]+)/show/?$@i',
  );
  foreach ($patterns as $pattern) {
    preg_match($pattern, $url, $matches);
    if (isset($matches[1])) {
      return _media_flickr_build_uri(array(
        'u' => $matches[1],
        's' => 'photostream',
      ));
    }
  }

  // Finally we look for searches.
  $patterns = array(
    '@flickr\\.com/search/?\\?q=([^& ]+)@i',
    '@flickr\\.com/search/show/?\\?q=([^& ]+)@i',
  );
  foreach ($patterns as $pattern) {
    preg_match($pattern, $url, $matches);
    if (isset($matches[1])) {
      return _media_flickr_build_uri(array(
        'search' => $matches[1],
      ));
    }
  }
  return '';
}

/**
 * Convert Flickr short form ID to long form. Short form is a base58
 * with a reduced alphabet.
 *
 * @param $num string
 *   ID parsed from short URL form.
 *
 * @return int
 *   Full media ID.
 */
function _media_flickr_shorturl($num) {
  $alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
  $decoded = 0;
  $multi = 1;
  while ($num != '') {
    $digit = $num[strlen($num) - 1];
    $decoded += $multi * strpos($alphabet, $digit);
    $multi *= strlen($alphabet);
    $num = substr($num, 0, -1);
  }
  return $decoded;
}

Functions

Namesort descending Description
media_flickr_unserialize_xml Recursively converts a SimpleXMLElement object into an array.
_media_flickr_build_uri Build the streamwrapper URI if the remote media exists.
_media_flickr_error_check This will log an error if we don't have a key yet. In addition, if the user is an admin, we'll display an error.
_media_flickr_get_user_id Find Flickr user ID.
_media_flickr_guess_size This will return the appropriate array key for the image size we wish.
_media_flickr_media_parse Flickr media parse helper function. Search the original url for valid data.
_media_flickr_original_url
_media_flickr_photoset_exists
_media_flickr_photoset_image_url
_media_flickr_photoset_photo_id
_media_flickr_photo_exists
_media_flickr_photo_remote_url This returns a cached photo stream from the Flickr farm servers.
_media_flickr_photo_url Based on the Photo ID of a Flickr image, this will return the URL to the image itself.
_media_flickr_photo_url_from_size
_media_flickr_sets_request This is a wrapper for emfield_request_xml that includes flickr's api key.
_media_flickr_shorturl Convert Flickr short form ID to long form. Short form is a base58 with a reduced alphabet.