You are here

bpn_flickr_private.module in Bulk File Nodes 7

Hooks and functions for the bpn_flickr_private module.

File

modules/bpn_flickr_private/bpn_flickr_private.module
View source
<?php

/**
 * @file
 * Hooks and functions for the bpn_flickr_private module.
 */

/**
 * Implements hook_menu().
 */
function bpn_flickr_private_menu() {
  $items = array();
  $items['bulk_photo_nodes/auth'] = array(
    'title' => 'Authenticate Flickr Credentials',
    'page callback' => 'bpn_flickr_private_oauth_authenticate',
    'access arguments' => array(
      'create bulk photo nodes',
    ),
  );
  return $items;
}

/**
 * Implements hook_bpn_upload().
 *
 * Defines a multi-step form to use with bulk_photo_nodes.
 */
function bpn_flickr_private_bulk_photo_nodes_method() {
  return 'bpn_flickr_private_form';
}

/**
 * Form constructor for the private flickr form.
 *
 * @see bpn_flickr_private_form_step_1()
 * @see bpn_flickr_private_form_step_2()
 * @see bpn_flickr_private_form_step_3()
 * @ingroup forms
 */
function bpn_flickr_private_form($form, &$form_state, $node_type) {
  if (empty($form_state['step'])) {
    $form_state['step'] = 1;
  }
  $form_state['node_type'] = $node_type;
  $form_callback = 'bpn_flickr_private_form_step_' . $form_state['step'];
  if (function_exists($form_callback)) {
    return call_user_func($form_callback, $form, $form_state);
  }
}

/**
 * Form constructor for Step 1: Select flickr user.
 *
 * @see bpn_flickr_private_disconnect()
 * @see bpn_flickr_private_form_step_1_submit()
 * @ingroup forms
 */
function bpn_flickr_private_form_step_1($form, &$form_state) {

  // Check if the flickrapi module is authenticated.
  module_load_include('module', 'flickrapi');
  $authenticated = _flickrapi_is_authenticated();
  if (!$authenticated) {
    drupal_set_message(t('The Flickr settings have not been established yet.'));
  }
  $form['flickr_private'] = array(
    '#prefix' => '<div class="bpn-upload-option">' . t('OR') . '</div><div class="bpn-flickr bpn-flickr-private">',
    '#suffix' => '</div>',
  );
  $form['flickr_private']['header'] = array(
    '#markup' => '<h3>' . t('Upload Images from your Flickr Account') . '</h3>',
  );
  if ($authenticated) {
    $flickr_user = bpn_flickr_private_get_api();
    if (!$flickr_user) {
      $form['flickr_private']['username'] = array(
        '#markup' => '<div class="description">' . t('Authenticate with your Flickr account.') . '</div>',
      );
    }
    $value = bpn_flickr_private_get_api() ? t('Next') : t('Authenticate');
    $form['flickr_private']['next'] = array(
      '#type' => 'submit',
      '#value' => $value,
    );
    if (bpn_flickr_private_get_api()) {
      $flickr_username = bpn_flickr_private_test_login();
      if (!empty($flickr_username['username'])) {
        $form['flickr_private']['username'] = array(
          '#markup' => '<div class="description">' . t('Authenticated as ') . $flickr_username['username'] . t('. Select image(s) on next page') . '</div>',
        );
      }
      $form['flickr_private']['remove'] = array(
        '#type' => 'submit',
        '#value' => 'Authenticate as a new user',
        '#submit' => array(
          'bpn_flickr_private_disconnect',
        ),
      );
    }
    $form['#submit'][] = 'bpn_flickr_private_form_step_1_submit';
  }
  return $form;
}

/**
 * Form submission handler for bpn_flickr_private_form_step_1().
 *
 * De-authenticates a user's Flickr account.
 *
 * @see bpn_flickr_private_form_step_1_submit()
 */
function bpn_flickr_private_disconnect($form, &$form_state) {
  bpn_flickr_private_oauth_new();
  $form_state['step'] = 2;
  $form_state['rebuild'] = TRUE;
}

/**
 * Form submission handler for bpn_flickr_private_form_step_1().
 *
 * Redirects the user to Flickr for authentication.
 *
 * @see bpn_flickr_private_disconnect()
 */
function bpn_flickr_private_form_step_1_submit($form, &$form_state) {
  if (bpn_flickr_private_get_api()) {

    // If the user has already authenticated.
    $form_state['step'] = 2;
    $form_state['rebuild'] = TRUE;
  }
  else {
    bpn_flickr_private_oauth_new();
  }
}

/**
 * Authenticates a flickr user.
 */
function bpn_flickr_private_oauth_new() {
  global $user;
  module_load_include('module', 'oauth_common');
  $callback = url('bulk_photo_nodes/auth', array(
    'absolute' => TRUE,
  ));

  // Set up a new OAuth Consumer and Client if it cannot be loaded.
  $consumer = DrupalOAuthConsumer::load(variable_get('flickrapi_api_key', ''), FALSE);
  if (!$consumer) {
    $consumer = new DrupalOAuthConsumer(variable_get('flickrapi_api_key', ''), variable_get('flickrapi_api_secret', ''));
    $consumer
      ->write();
  }
  $sig_method = DrupalOAuthClient::signatureMethod();
  $client = new DrupalOAuthClient($consumer, NULL, $sig_method);
  try {
    if ($request_token = $client
      ->getRequestToken('http://www.flickr.com/services/oauth/request_token', array(
      'callback' => $callback,
    ))) {
      $request_token->uid = $user->uid;
      $request_token
        ->write();
    }
  } catch (Exception $e) {
    drupal_set_message(t('You API key and secret do not seem to match.'), 'error');
    variable_del('flickrapi_api_key');
    variable_del('flickrapi_api_secret');
    drupal_goto('admin/config/media/flickrapi');
  }

  // Save current address.
  $_SESSION['bulk_photo_node_url'] = implode('/', arg());
  $auth_url = $client
    ->getAuthorizationUrl('http://www.flickr.com/services/oauth/authorize', array(
    'callback' => $callback,
    'params' => array(
      'perms' => variable_get('flickrapi_access_permissions', array(
        'read',
      )),
    ),
  ));

  // Send the user to the Flickr page which redirects
  // back to the Drupal site after accepting.
  drupal_goto($auth_url);
}

/**
 * Handle OAuth authentication after step 1.
 */
function bpn_flickr_private_oauth_authenticate() {
  $access_token = bpn_flickr_private_get_token();
  drupal_set_message(t('Succesfully verified'));
  drupal_goto($_SESSION['bulk_photo_node_url'], array(
    'query' => array(
      'bpn_flickr_private' => 1,
    ),
  ));
}

/**
 * Form constructor for Step 2: Pick what images to load.
 */
function bpn_flickr_private_form_step_2($form, &$form_state) {
  module_load_include('module', 'oauth_common');
  $form['#bpn_chosen_form'] = array(
    '#type' => 'value',
    '#value' => TRUE,
  );
  $form['photo_container_selector'] = array(
    '#type' => 'fieldset',
    '#tree' => TRUE,
    '#weight' => -2,
  );

  // Get photosets.
  $sets = bpn_flickr_private_get_sets();
  $photosets = array();
  if (!empty($sets)) {
    foreach ($sets['photoset'] as $photoset) {
      if ($photoset['photos'] > 0) {
        $photosets[$photoset['id']] = $photoset['title'];
      }
    }
  }
  asort($photosets);
  $form['photo_container_selector']['photo_container_type'] = array(
    '#type' => 'select',
    '#options' => array(
      t('Photos') => array(
        'photostream' => 'Photostream',
      ),
      t('Sets') => $photosets,
    ),
    '#title' => t('View flickr photos from:'),
  );
  $count = isset($form_state['num_photos_checked']) ? intval($form_state['num_photos_checked']) : 0;
  $form['photo_container_selector']['stats'] = array(
    '#markup' => '<div class="bpn-flickr-selected-count">' . t('Photos selected:') . ' <span class="bpn-flickr-count">' . $count . '</span></div>',
    '#attached' => array(
      'js' => array(
        drupal_get_path('module', 'bpn_flickr') . '/js/bpn_flickr.js',
      ),
    ),
  );
  $form['photo_container_selector']['update'] = array(
    '#type' => 'submit',
    '#value' => 'Update',
    '#submit' => array(
      'bpn_flickr_private_photos_state',
      'bpn_flickr_private_update_photos',
    ),
  );
  $form['photo_container_photos']['photostream'] = array(
    '#attributes' => array(
      'class' => array(
        'clearfix',
      ),
    ),
    '#type' => 'container',
    '#tree' => TRUE,
  );
  $page = empty($form_state['flickr_page']) ? 1 : $form_state['flickr_page'];
  $photo_set = empty($form_state['photo_set']) ? 'photostream' : $form_state['photo_set'];
  if ($photo_set == 'photostream') {
    $photos_response = bpn_flickr_private_get_photos($page);
    $pages = $photos_response['photos']['pages'];
    $photos = $photos_response['photos']['photo'];
  }
  else {
    $photos_response = bpn_flickr_private_get_set($photo_set, $page);
    $photos = $photos_response['photoset']['photo'];
    $pages = $photos_response['photoset']['pages'];
  }
  if (!empty($photos)) {
    if ($pages > 1) {
      $form['flickr_pager'] = array(
        '#type' => 'container',
        '#tree' => TRUE,
        '#weight' => -1,
      );
      if ($page != 1) {
        $form['flickr_pager']['flickr_prev'] = array(
          '#type' => 'submit',
          '#value' => 'Previous Page',
          '#submit' => array(
            'bpn_flickr_private_photos_state',
            'bpn_flickr_private_pager_prev',
          ),
        );
      }
      $form['flickr_pager']['pager_text'] = array(
        '#preix' => '<span>',
        '#markup' => "Page {$page} of " . $pages,
        '#suffix' => '</span>',
      );
      $form['flickr_pager']['flickr_page'] = array(
        '#type' => 'value',
        '#value' => $page,
      );
      if ($page != $pages) {
        $form['flickr_pager']['flickr_next'] = array(
          '#type' => 'submit',
          '#value' => 'Next Page',
          '#submit' => array(
            'bpn_flickr_private_photos_state',
            'bpn_flickr_private_pager_next',
          ),
        );
      }
    }
    foreach ($photos as $key => $photo) {
      $id = $photo['id'];
      $has_values = !empty($form_state['checked_photos']);
      $default_value = $has_values && in_array($id, $form_state['checked_photos']);
      $form['photo_container_photos']['photostream'][$id] = array(
        '#type' => 'checkbox',
        '#default_value' => $default_value,
        '#prefix' => '<div class="bpn-flickr-thumbnail"><div class="inner">' . theme('image', array(
          'path' => $photo['url_q'],
        )),
        '#title' => empty($photo['title']) ? t('Untitled') : $photo['title'],
        '#suffix' => '</div></div>',
      );
    }
  }
  $form['submit'] = array(
    '#prefix' => '<div class="bpn-continue">',
    '#type' => 'submit',
    '#value' => t('Done Adding Photos - Continue'),
    '#suffix' => '</div>',
  );
  $form['#submit'] = array(
    'bpn_flickr_private_photos_state',
    'bpn_flickr_private_form_step_2_submit',
  );
  $form['#attributes'] = array(
    'class' => array(
      'clearfix',
    ),
  );
  return $form;
}

/**
 * Form submission handler for bpn_flickr_private_form_step_2().
 */
function bpn_flickr_private_form_step_2_submit($form, &$form_state) {
  $operations = array();
  foreach ($form_state['checked_photos'] as $key => $flickr_id) {
    $operations[] = array(
      'bpn_flickr_download_photos',
      array(
        $flickr_id,
      ),
    );
  }
  $batch = array(
    'title' => t('Importing photos from flickr.'),
    'finished' => 'bpn_flickr_private_batch_finished',
    'operations' => $operations,
  );
  batch_set($batch);
  $form_state['step'] = 3;
  $form_state['rebuild'] = TRUE;
}

/**
 * Batch finished callback used by bpn_flickr_private_form_step_2_submit().
 */
function bpn_flickr_private_batch_finished($success, $results, $operations) {
  if ($success) {
    drupal_set_message(t('@count Photos imported.', array(
      '@count' => count($results),
    )));
  }
  else {
    $error_operation = reset($operations);
    drupal_set_message(t('An error occurred while processing @operation with arguments : @args', array(
      '@operation' => $error_operation[0],
      '@args' => print_r($error_operation[0], TRUE),
    )));
  }
  $_SESSION['saved_files'] = $results;
}

/**
 * Batch operation: Downloads a single image from flickr.
 *
 * Downloads the largest image size available to the public files directory.
 * Also fetches extra information about the image, such as size, date taken,
 * etc.
 *
 * @param string $flickr_id
 *   The flickr id of the image.
 */
function bpn_flickr_private_download_photos($flickr_id, &$context) {

  // Set batch message.
  $context['message'] = t('Importing image with flickr id: "@id"', array(
    '@id' => $flickr_id,
  ));
  $flickr_sizes = bpn_flickr_private_get_photo($flickr_id);
  $extra_info = bpn_flickr_private_get_info($flickr_id);
  $largest_size = count($flickr_sizes) - 1;
  $extra_info['photo']['exif_width'] = $flickr_sizes[$largest_size]['width'];
  $extra_info['photo']['exif_height'] = $flickr_sizes[$largest_size]['height'];

  // Get URL to download  image from.
  $parsed_url = parse_url($flickr_sizes[$largest_size]['source']);
  $filename = substr($parsed_url['path'], strrpos($parsed_url['path'], '/') + 1);

  // Request and save the image.
  $downloaded_file = drupal_http_request($flickr_sizes[$largest_size]['source']);
  $destination_uri = file_stream_wrapper_uri_normalize('public://' . $filename);
  $file_uri = file_unmanaged_save_data($downloaded_file->data, $destination_uri);

  // Convert the saved file to a file object.
  $file_object = bpn_flickr_file_uri_to_object($file_uri);
  file_save($file_object);
  $context['results'][] = array(
    'extra_info' => $extra_info['photo'],
    'file_object' => $file_object,
  );
}

/**
 * Step 3 of the Flickr Private form.
 */
function bpn_flickr_private_form_step_3($form, &$form_state) {
  return bulk_photo_nodes_add_form($form, $form_state, $form_state['node_type']);
}

/**
 * Flickr submit handler.
 */
function bpn_flickr_private_form_submit($form, &$form_state) {
  $form_state['rebuild'] = TRUE;
  if (isset($form_state['values']['username']) && !empty($form_state['values']['username'])) {
    $form_state['flickr_username'] = $form_state['values']['username'];
    $form_state['step'] = 2;
  }
}

/**
 * Sets a custom POST URL to make private calls.
 */
function _bpn_flickr_private_custom_post($url, $data) {
  global $user;
  $query = db_select('oauth_common_token', 't')
    ->fields('t');
  $query
    ->join('oauth_common_consumer', 'c', 'c.csid = t.csid');
  $query
    ->condition('c.consumer_key', variable_get('flickrapi_api_key', ''));
  $query
    ->condition('c.secret', variable_get('flickrapi_api_secret', ''));
  $query
    ->condition('t.uid', $user->uid);
  $result = $query
    ->execute();
  $token = DrupalOAuthToken::fromResult($result);
  $consumer = DrupalOAuthConsumer::load(variable_get('flickrapi_api_key', ''), FALSE);
  $sig_method = FlickrApiOAuthClient::signatureMethod();
  $client = new FlickrApiOAuthClient($consumer, $token, $sig_method);
  $response = $client
    ->get($url, array(
    'token' => TRUE,
    'params' => $data,
  ));
  return $response;
}

/**
 * Gets the photosets for a user.
 */
function bpn_flickr_private_get_sets() {
  $flickr = bpn_flickr_private_get_api();
  return $flickr
    ->photosets_getList();
}

/**
 * Wraps PHPFlickr::people_findByUsername.
 */
function bpn_flickr_private_get_user($username) {
  $flickr = bpn_flickr_private_get_api();
  return $flickr
    ->people_findByUsername($username);
}

/**
 * Form submission handler for bpn_flickr_private_form_step_2().
 */
function bpn_flickr_private_photos_state($form, &$form_state) {
  if (empty($form_state['checked_photos'])) {
    $form_state['checked_photos'] = array_keys($form_state['values']['photostream'], 1);
  }
  else {
    $currently_checked = array_keys($form_state['values']['photostream'], 1);
    $unique_merged = array_unique(array_merge($form_state['checked_photos'], $currently_checked));
    $form_state['checked_photos'] = $unique_merged;
  }
  $form_state['num_photos_checked'] = count($form_state['checked_photos']);
  $form_state['rebuild'] = TRUE;
}

/**
 * Form submission handler for bpn_flickr_private_form_step_2().
 */
function bpn_flickr_private_pager_next($form, &$form_state) {
  $form_state['flickr_page'] = $form_state['values']['flickr_pager']['flickr_page'] + 1;
}

/**
 * Form submission handler for bpn_flickr_private_form_step_2().
 */
function bpn_flickr_private_pager_prev($form, &$form_state) {
  $form_state['flickr_page'] = $form_state['values']['flickr_pager']['flickr_page'] - 1;
}

/**
 * Form submission handler for bpn_flickr_private_form_step_2().
 */
function bpn_flickr_private_update_photos($form, &$form_state) {
  $form_state['photo_set'] = $form_state['values']['photo_container_selector']['photo_container_type'];
  $form_state['flickr_page'] = 1;
  $form_state['rebuild'] = TRUE;
}

/**
 * Returns a file object which can be passed to file_save().
 *
 * @param string $uri
 *   a string containing the uri, path, or filename.
 *
 * @return mixed
 *   a file object, or false on error.
 *
 * @todo replace with calls to this function with file_uri_to_object() when
 * http://drupal.org/node/685818 is fixed in core.
 */
function bpn_flickr_private_file_uri_to_object($uri) {
  global $user;
  $uri = file_stream_wrapper_uri_normalize($uri);
  $wrapper = file_stream_wrapper_get_instance_by_uri($uri);
  $file = new stdClass();
  $file->uid = $user->uid;
  $file->filename = basename($uri);
  $file->uri = $uri;
  $file->filemime = file_get_mimetype($uri);

  // This is gagged because some uris will not support it.
  $file->filesize = @filesize($uri);
  $file->timestamp = REQUEST_TIME;
  $file->status = 1;
  return $file;
}

/**
 * Gets the Flickr API object for use in API calls.
 *
 * @return object
 *   The PHP Flickr object
 */
function bpn_flickr_private_get_api() {
  global $user;
  $flickr =& drupal_static(__FUNCTION__);
  if (!isset($flickr)) {
    $query = db_select('oauth_common_token', 't')
      ->fields('t');
    $query
      ->join('oauth_common_consumer', 'c', 'c.csid = t.csid');
    $query
      ->condition('c.consumer_key', variable_get('flickrapi_api_key', ''));
    $query
      ->condition('c.secret', variable_get('flickrapi_api_secret', ''));
    $query
      ->condition('t.uid', $user->uid);
    $result = $query
      ->execute();
    $token = DrupalOAuthToken::fromResult($result);
    if (!$token) {
      return FALSE;
    }
    $flickr = new phpFlickr($token->key, $token->secret);
    $flickr
      ->setCustomPost('_bpn_flickr_private_custom_post');
  }
  return $flickr;
}

/**
 * Gets the flickr token.
 *
 * @return string
 *   The user's access token to make flickr API calls with.
 */
function bpn_flickr_private_get_token() {
  global $user;
  module_load_include('module', 'oauth_common');
  $oauth_token = NULL;
  $oauth_verifier = NULL;
  if (isset($_GET['oauth_token'])) {
    $oauth_token = $_GET['oauth_token'];
  }
  if (isset($_GET['oauth_verifier'])) {
    $oauth_verifier = $_GET['oauth_verifier'];
  }
  $consumer = DrupalOAuthConsumer::load(variable_get('flickrapi_api_key', ''), FALSE);
  $request_token = DrupalOAuthToken::loadByKey($oauth_token, $consumer, OAUTH_COMMON_TOKEN_TYPE_REQUEST);
  $client = new DrupalOAuthClient($consumer, $request_token);
  $num_deleted = db_delete('oauth_common_token')
    ->condition('uid', $user->uid)
    ->execute();
  $access_token = $client
    ->getAccessToken('http://www.flickr.com/services/oauth/access_token', array(
    'verifier' => $oauth_verifier,
  ));
  $request_token
    ->delete();
  $access_token->uid = $user->uid;
  $access_token
    ->write();
  return $access_token;
}

/**
 * Get photos from a user's photostream.
 */
function bpn_flickr_private_get_set($set_id, $page = 1) {
  $flickr = bpn_flickr_private_get_api();
  $options = array(
    'photoset_id' => $set_id,
    'extras' => 'url_q',
    'privacy_filter' => NULL,
    'per_page' => 9,
    'page' => $page,
    'media' => 'photos',
  );
  extract($options);
  return $flickr
    ->photosets_getPhotos($photoset_id, $extras, $privacy_filter, $per_page, $page, $media);
}

/**
 * Get photos from a user's photostream.
 */
function bpn_flickr_private_get_photos($page = 1) {
  $flickr = bpn_flickr_private_get_api();
  $options = array(
    'user_id' => 'me',
    'safe_search' => NULL,
    'extras' => 'url_q',
    'per_page' => 9,
    'page' => $page,
  );
  extract($options);
  return $flickr
    ->people_getPhotos('me', $options);
}

/**
 * Get information from a photo on flickr.
 */
function bpn_flickr_private_get_info($photo_id) {
  $flickr = bpn_flickr_private_get_api();
  return $flickr
    ->photos_getInfo($photo_id);
}

/**
 * Get information for the authenticated user.
 */
function bpn_flickr_private_test_login() {
  $flickr = bpn_flickr_private_get_api();
  return $flickr
    ->test_login();
}

/**
 * Get sizes of a photo on flickr.
 */
function bpn_flickr_private_get_photo($photo_id) {
  $flickr = bpn_flickr_private_get_api();
  return $flickr
    ->photos_getSizes($photo_id);
}

Functions

Namesort descending Description
bpn_flickr_private_batch_finished Batch finished callback used by bpn_flickr_private_form_step_2_submit().
bpn_flickr_private_bulk_photo_nodes_method Implements hook_bpn_upload().
bpn_flickr_private_disconnect Form submission handler for bpn_flickr_private_form_step_1().
bpn_flickr_private_download_photos Batch operation: Downloads a single image from flickr.
bpn_flickr_private_file_uri_to_object Returns a file object which can be passed to file_save().
bpn_flickr_private_form Form constructor for the private flickr form.
bpn_flickr_private_form_step_1 Form constructor for Step 1: Select flickr user.
bpn_flickr_private_form_step_1_submit Form submission handler for bpn_flickr_private_form_step_1().
bpn_flickr_private_form_step_2 Form constructor for Step 2: Pick what images to load.
bpn_flickr_private_form_step_2_submit Form submission handler for bpn_flickr_private_form_step_2().
bpn_flickr_private_form_step_3 Step 3 of the Flickr Private form.
bpn_flickr_private_form_submit Flickr submit handler.
bpn_flickr_private_get_api Gets the Flickr API object for use in API calls.
bpn_flickr_private_get_info Get information from a photo on flickr.
bpn_flickr_private_get_photo Get sizes of a photo on flickr.
bpn_flickr_private_get_photos Get photos from a user's photostream.
bpn_flickr_private_get_set Get photos from a user's photostream.
bpn_flickr_private_get_sets Gets the photosets for a user.
bpn_flickr_private_get_token Gets the flickr token.
bpn_flickr_private_get_user Wraps PHPFlickr::people_findByUsername.
bpn_flickr_private_menu Implements hook_menu().
bpn_flickr_private_oauth_authenticate Handle OAuth authentication after step 1.
bpn_flickr_private_oauth_new Authenticates a flickr user.
bpn_flickr_private_pager_next Form submission handler for bpn_flickr_private_form_step_2().
bpn_flickr_private_pager_prev Form submission handler for bpn_flickr_private_form_step_2().
bpn_flickr_private_photos_state Form submission handler for bpn_flickr_private_form_step_2().
bpn_flickr_private_test_login Get information for the authenticated user.
bpn_flickr_private_update_photos Form submission handler for bpn_flickr_private_form_step_2().
_bpn_flickr_private_custom_post Sets a custom POST URL to make private calls.