You are here

drupagram.module in Drupagram 7

Same filename and directory in other branches
  1. 6 drupagram.module

Provides API integration with the Instagram microblogging service.

File

drupagram.module
View source
<?php

/**
 * @file
 * Provides API integration with the Instagram microblogging service.
 */
define('DRUPAGRAM_URL_APP_REGISTER', 'http://instagram.com/developer/clients/manage/');

/**
 * Implements hook_menu().
 */
function drupagram_menu() {
  $items['instagram/oauth'] = array(
    'title' => 'Instagram',
    'access callback' => TRUE,
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'drupagram_oauth_callback',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'drupagram.pages.inc',
  );
  $items['admin/config/services/drupagram'] = array(
    'title' => 'Instagram',
    'description' => 'Configure integration with Instagram (and compatible) API services.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'drupagram_admin_form',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'file' => 'drupagram.pages.inc',
  );
  $items['admin/config/services/drupagram/default'] = array(
    'title' => 'Instagram',
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items['user/%user/edit/drupagram'] = array(
    'title' => 'Instagram accounts',
    'page callback' => 'drupagram_user_settings',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'drupagram_edit_access',
    'access arguments' => array(
      1,
    ),
    'weight' => 10,
    'file' => 'drupagram.pages.inc',
    'type' => MENU_LOCAL_TASK,
  );
  $items['user/%user/edit/drupagram/global/%'] = array(
    'title' => 'Instagram accounts',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'drupagram_user_make_global',
      1,
      5,
    ),
    'access arguments' => array(
      'make drupagram accounts global',
    ),
    'file' => 'drupagram.pages.inc',
  );
  return $items;
}

/**
 * Access callback for drupagram account editing.
 */
function drupagram_edit_access($account) {
  return user_edit_access($account) && user_access('add drupagram accounts');
}

/**
 * Implements hook_permission().
 */
function drupagram_permission() {
  return array(
    'add drupagram accounts' => array(
      'title' => t('Add Instagram accounts'),
    ),
    'use global drupagram account' => array(
      'title' => t('Use the site global Instagram account'),
    ),
    'make drupagram accounts global' => array(
      'title' => t('Assign a Instagram account as the site global account.'),
    ),
    'import own media' => array(
      'title' => t('Import own media to the site.'),
    ),
  );
}

/**
 * Implements hook_user_categories().
 */
function drupagram_user_categories() {
  return array(
    array(
      'name' => 'drupagram',
      'title' => t('Instagram accounts'),
      'weight' => 3,
    ),
  );
}

/**
 * Implements hook_theme().
 */
function drupagram_theme() {
  return array(
    'drupagram_account_list_form' => array(
      'render element' => 'form',
    ),
    'drupagram_likes' => array(
      'variables' => array(
        'count' => NULL,
        'data' => array(),
      ),
      'file' => 'drupagram.theme.inc',
    ),
    'drupagram_account' => array(
      'variables' => array(
        'username' => NULL,
        'profile_picture' => NULL,
        'id' => NULL,
        'full_name' => NULL,
      ),
      'file' => 'drupagram.theme.inc',
    ),
    'drupagram_caption' => array(
      'variables' => array(
        'id' => NULL,
        'text' => NULL,
        'from' => array(),
        'created_time' => NULL,
      ),
      'file' => 'drupagram.theme.inc',
    ),
    'drupagram_likes_data' => array(
      'variables' => array(
        'data' => array(),
      ),
      'file' => 'drupagram.theme.inc',
    ),
    'drupagram_likes_data_item' => array(
      'variables' => array(
        'id' => NULL,
        'username' => NULL,
        'full_name' => NULL,
        'profile_picture' => NULL,
      ),
      'file' => 'drupagram.theme.inc',
    ),
  );
}

/**
 * Very lightweight helper function to generate a TinyURL for a given post.
 */
function drupagram_shorten_url($url) {
  if (module_exists('shorten')) {
    return shorten_url($url);
  }
  else {
    $conf = InstagramConf::instance();
    $response = drupal_http_request("http://" . $conf
      ->get('tiny_url') . "/api-create.php?url=" . $url);
    if ($response->code == 200) {
      return $response->data;
    }
    else {
      return $url;
    }
  }
}

/**
 * Implements hook_cron().
 *
 * Imports new Instagram statuses for site users, and deletes expired media.
 */
function drupagram_cron() {
  if (!variable_get('drupagram_import', TRUE)) {
    return;
  }

  // Pull up a list of Instagram accounts that are flagged for updating,
  // sorted by how long it's been since we last updated them. This ensures
  // that the most out-of-date accounts get updated first.
  module_load_include('inc', 'drupagram');
  $result = db_query_range("SELECT drupagram_id FROM {drupagram_account} WHERE import = :import ORDER BY last_refresh ASC", 0, 20, array(
    ':import' => 1,
  ));
  foreach ($result as $account) {

    // drupagram_fetch_user_feed($account->drupagram_id);
    drupagram_fetch_recent_items($account->drupagram_id);
  }

  // Nuke old items.
  if ($age = variable_get('drupagram_expire', 0)) {
    db_delete('drupagram')
      ->condition('created_time', REQUEST_TIME - $age, '<')
      ->execute();
  }
}

/**
 * Implements hook_filter_info().
 */
function drupagram_filter_info() {
  $filters['drupagram_username'] = array(
    'title' => t('Instagram @username converter'),
    'description' => t('Converts Instagram-style @usernames into links to Instagram account pages.'),
    'process callback' => '_drupagram_filter_username',
    'tips callback' => '_drupagram_filter_tip_username',
  );
  $filters['drupagram_hashtag'] = array(
    'title' => t('Instagram #hashtag converter'),
    'description' => t('Converts Instagram-style #hashtags into links to hashtags.org.'),
    'process callback' => '_drupagram_filter_hashtag',
    'tips callback' => '_drupagram_filter_tip_hashtag',
  );
  return $filters;
}

/**
 * Filter tips callback function for $filters[0] in hook_filter_info().
 */
function _drupagram_filter_tip_username($filter, $format, $long = FALSE) {
  return t('Instagram-style @usernames are linked to their Instagram account pages.');
}

/**
 * Filter tips callback function for $filters[1] in hook_filter_info().
 */
function _drupagram_filter_tip_hashtag($format, $long = FALSE) {
  return t('Instagram-style #hashtags are linked to !url.', array(
    '!url' => '<a href="http://search.drupagram.com/">search.drupagram.com</a>',
  ));
}

/**
 * Callback for drupagram @username converter
 */
function _drupagram_filter_username($text, $filter) {
  $prefix = '@';
  $conf = InstagramConf::instance();
  $destination = 'http://' . $conf
    ->get('host') . '/';
  return _drupagram_filter_text($text, $prefix, $destination);
}

/**
 * Callback for drupagram #hashtag converter
 */
function _drupagram_filter_hashtag($text, $filter) {
  $prefix = '#';
  $conf = InstagramConf::instance();
  $destination = 'http://' . $conf
    ->get('search') . '/search?q=%23';
  return _drupagram_filter_text($text, $prefix, $destination);
}

/**
 * This helper function converts Instagram-style @usernames and #hashtags into
 * actual links.
 */
function _drupagram_filter_text($text, $prefix, $destination) {
  $matches = array(
    '/\\>' . $prefix . '([a-z0-9_]+)/i',
    '/^' . $prefix . '([a-z0-9_]+)/i',
    '/(\\s+)' . $prefix . '([a-z0-9_]+)/i',
  );
  $replacements = array(
    '><a href="' . $destination . '/${1}">' . $prefix . '${1}</a>',
    '<a href="' . $destination . '/${1}">' . $prefix . '${1}</a>',
    '${1}<a href="' . $destination . '/${2}">' . $prefix . '${2}</a>',
  );
  return preg_replace($matches, $replacements, $text);
}

/**
 * Implements hook_user_load().
 */
function drupagram_user_load($accounts) {
  foreach ($accounts as $uid => $account) {
    $accounts[$uid]->drupagram_accounts = module_invoke_all('drupagram_accounts', $account);
  }
}

/**
 * Implements hook_drupagram_accounts(). We want to move this into a
 * separate module eventually, but sticking the code here and using a hook
 * lets other modules solve the 'what accounts can a user post with' problem
 * in cleaner ways.
 *
 * @return
 *   array with Instagram accounts
 */
function drupagram_drupagram_accounts($account) {
  module_load_include('inc', 'drupagram');
  $query = db_select('drupagram_account', 'da')
    ->fields('da', array(
    'drupagram_id',
  ));
  if (user_access('use global drupagram account', $account)) {
    $or = db_or();
    $or
      ->condition('da.uid', $account->uid);
    $or
      ->condition('da.is_global', 1);
    $query
      ->condition($or);
  }
  else {
    $query
      ->condition('da.uid', $account->uid);
  }
  $drupagram_accounts = array();
  foreach ($query
    ->execute()
    ->fetchCol() as $drupagram_id) {
    $drupagram_accounts[] = drupagram_account_load($drupagram_id);
  }
  return $drupagram_accounts;
}

/**
 * Detect whether we should use oauth.
 */
function _drupagram_use_oauth() {
  return module_exists('oauth_common') && variable_get('drupagram_client_id', '') && variable_get('drupagram_client_secret', '');
}

/**
 * Implements hook_views_api().
 */
function drupagram_views_api() {
  return array(
    'api' => 2,
  );
}

/**
 * Implements hook_admin_paths_alter().
 *
 * OAuth callback disagrees with overlay.
 */
function drupagram_admin_paths_alter(&$paths) {
  $paths['user/*/edit/drupagram'] = FALSE;
}

/**
 * Retrieves a local fid of a remote image. Attempts to save it if none is found.
 */
function drupagram_local_image($path) {
  global $user;
  $uri = !empty($path) ? file_default_scheme() . '://' . basename($path) : NULL;
  $file_object = _drupagram_load_data($path);
  if (!empty($file_object)) {
    return $file_object;
  }

  // Managed operations work with a file object.
  $result = drupal_http_request($path);
  if ($result->code == 200) {
    $file_object = file_save_data($result->data, $uri, FILE_EXISTS_RENAME);
    if (!empty($file_object)) {
      if ($user->uid == 1) {
        $url = file_create_url($file_object->uri);
        drupal_set_message(t('Saved managed file: %file to destination %destination (accessible via !url, actual uri=<span id="uri">@uri</span>)', array(
          '%file' => print_r($file_object, TRUE),
          '%destination' => $uri,
          '@uri' => $file_object->uri,
          '!url' => l(t('this URL'), $url),
        )));
      }

      // Save the reference
      $a = db_insert('drupagram_local_image')
        ->fields(array(
        'path' => substr($path, 0, 255),
        'file_object' => serialize($file_object),
      ))
        ->execute();
      return $file_object;
    }
  }
  if ($user->uid == 1) {
    drupal_set_message(t('Failed to save the managed file'), 'error');
  }
}

/**
 * Fetches a path from the drupagram_local_image table.
 */
function _drupagram_load_data($path) {
  $query = db_select('drupagram_local_image', 'dli')
    ->fields('dli')
    ->condition('path', substr($path, 0, 255))
    ->execute()
    ->fetchAllAssoc('path');
  if (!empty($query)) {
    $record = array_shift($query);
    return unserialize($record->file_object);
  }
  return FALSE;
}

Functions

Namesort descending Description
drupagram_admin_paths_alter Implements hook_admin_paths_alter().
drupagram_cron Implements hook_cron().
drupagram_drupagram_accounts Implements hook_drupagram_accounts(). We want to move this into a separate module eventually, but sticking the code here and using a hook lets other modules solve the 'what accounts can a user post with' problem in cleaner ways.
drupagram_edit_access Access callback for drupagram account editing.
drupagram_filter_info Implements hook_filter_info().
drupagram_local_image Retrieves a local fid of a remote image. Attempts to save it if none is found.
drupagram_menu Implements hook_menu().
drupagram_permission Implements hook_permission().
drupagram_shorten_url Very lightweight helper function to generate a TinyURL for a given post.
drupagram_theme Implements hook_theme().
drupagram_user_categories Implements hook_user_categories().
drupagram_user_load Implements hook_user_load().
drupagram_views_api Implements hook_views_api().
_drupagram_filter_hashtag Callback for drupagram #hashtag converter
_drupagram_filter_text This helper function converts Instagram-style @usernames and #hashtags into actual links.
_drupagram_filter_tip_hashtag Filter tips callback function for $filters[1] in hook_filter_info().
_drupagram_filter_tip_username Filter tips callback function for $filters[0] in hook_filter_info().
_drupagram_filter_username Callback for drupagram @username converter
_drupagram_load_data Fetches a path from the drupagram_local_image table.
_drupagram_use_oauth Detect whether we should use oauth.

Constants

Namesort descending Description
DRUPAGRAM_URL_APP_REGISTER @file Provides API integration with the Instagram microblogging service.