You are here

facebook_album.module in Facebook Album 7.3

File

facebook_album.module
View source
<?php

/**
 * @file facebook_album.module
 *
 * Creates the block for display and menu items for configuration
 */
DEFINE('API_BASE_URL', 'https://graph.facebook.com/');
DEFINE('API_AUTH_PATH', 'oauth/');

/**
 * Implements menu_hook()
 *
 * Setup routes to their appropriate functions
 */
function facebook_album_menu() {
  $items = [];
  $items['admin/config/services/facebook_album'] = [
    'title' => 'Facebook Album Settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => [
      'facebook_album_admin_form',
      'system_admin_menu_block_page',
    ],
    'access arguments' => [
      'facebook album',
    ],
    'file' => 'facebook_album.admin.inc',
    'type' => MENU_NORMAL_ITEM,
  ];
  $items['facebook_album/%/get/albums'] = [
    'title' => 'Fetch Albums',
    'page callback' => 'facebook_album_ajax_get_albums',
    'page arguments' => [
      1,
    ],
    'access arguments' => [
      'access content',
    ],
    'type' => MENU_CALLBACK,
  ];
  $items['facebook_album/%/get/albums/next/%'] = [
    'title' => 'Fetch Next Albums',
    'page callback' => 'facebook_album_ajax_get_albums_next',
    'page arguments' => [
      5,
      1,
    ],
    'access arguments' => [
      'access content',
    ],
    'type' => MENU_CALLBACK,
  ];
  $items['facebook_album/%/get/album/%'] = [
    'title' => 'Fetch Album Photos',
    'page callback' => 'facebook_album_ajax_get_album',
    'page arguments' => [
      4,
      1,
    ],
    'access arguments' => [
      'access content',
    ],
    'type' => MENU_CALLBACK,
  ];
  $items['facebook_album/%/get/album/%/next/%'] = [
    'title' => 'Fetch Next Album Photos',
    'page callback' => 'facebook_album_ajax_get_album_next',
    'page arguments' => [
      4,
      6,
      1,
    ],
    'access arguments' => [
      'access content',
    ],
    'type' => MENU_CALLBACK,
  ];
  $items['facebook_album/%/get/photo/%'] = [
    'title' => 'Fetch Photo Url',
    'page callback' => 'facebook_album_ajax_get_photo_url',
    'page arguments' => [
      4,
      1,
    ],
    'access arguments' => [
      'access content',
    ],
    'type' => MENU_CALLBACK,
  ];
  return $items;
}

/**
 * Implements hook_permission()
 */
function facebook_album_permission() {
  return [
    'facebook album' => [
      'title' => t('Administer Facebook Album'),
      'description' => t('Change settings for the Facebook Album Module'),
    ],
  ];
}

/**
 * Implements hook_theme()
 */
function facebook_album_theme($existing, $type, $theme, $path) {
  return [
    'facebook_album_covers' => [
      'variables' => [
        'settings' => NULL,
        'photos' => NULL,
      ],
      'template' => 'templates/facebook_album_covers',
    ],
    'facebook_album_photos' => [
      'variables' => [
        'settings' => NULL,
        'photos' => NULL,
      ],
      'template' => 'templates/facebook_album_photos',
    ],
  ];
}

/**
 * Implements hook_block_info().
 */
function facebook_album_block_info() {
  $blocks = [];
  $num_blocks = variable_get('facebook_album_block_num', 1);
  for ($i = 1; $i <= $num_blocks; $i++) {
    $blocks['facebook_album_' . $i] = [
      'info' => t('Facebook Album Gallery @num', [
        '@num' => $i,
      ]),
    ];
  }
  return $blocks;
}

/**
 * Implements hook_block_configure().
 */
function facebook_album_block_configure($delta = '') {
  if (strpos($delta, 'facebook_album_') !== FALSE) {
    $settings = facebook_album_get_settings($delta);
    $form['fba_settings'] = [
      '#title' => t('Facebook Album Settings'),
      '#type' => 'fieldset',
      '#collapsible' => FALSE,
      '#tree' => TRUE,
    ];
    $form['fba_settings']['facebook_album_pageID'] = [
      '#type' => 'textfield',
      '#title' => t('Facebook Page ID'),
      '#default_value' => $settings['pageID'],
      '#description' => t('The page ID of the page you want to pull the albums from. For example, if your page is https://facebook.com/acromediainc, you would enter acromediainc.'),
    ];
    $form['fba_settings']['facebook_album_visibility'] = [
      '#type' => 'radios',
      '#title' => t('Album Visibility'),
      '#options' => [
        0 => t('Exclude the listed albums'),
        1 => t('Only show the specified albums'),
      ],
      '#default_value' => $settings['visibility'],
    ];
    $form['fba_settings']['facebook_album_albums'] = [
      '#type' => 'textarea',
      '#description' => t('Leave blank to show all albums. Specify albums by using their album IDs. Enter one ID per line.'),
      '#default_value' => $settings['albums'],
    ];
    $form['fba_settings']['display_settings'] = [
      '#title' => t('Album Display Settings'),
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    ];
    $form['fba_settings']['display_settings']['facebook_album_albumLimit'] = [
      '#title' => t('Album Limit'),
      '#type' => 'textfield',
      '#default_value' => $settings['albumLimit'],
      '#description' => t('Leave blank or set to 0 if you want to load all albums'),
    ];
    $form['fba_settings']['display_settings']['facebook_album_showDescription'] = [
      '#title' => t('Show Album Description'),
      '#type' => 'checkbox',
      '#default_value' => $settings['showDescription'],
    ];
    $form['fba_settings']['display_settings']['facebook_album_showLocation'] = [
      '#title' => t('Show Album Location'),
      '#type' => 'checkbox',
      '#default_value' => $settings['showLocation'],
    ];
    $form['fba_settings']['display_settings']['facebook_album_albumThumbWidth'] = [
      '#title' => t('Album Thumbnail Width'),
      '#type' => 'textfield',
      '#default_value' => $settings['albumThumbWidth'],
    ];
    $form['fba_settings']['display_settings']['facebook_album_albumThumbHeight'] = [
      '#title' => t('Album Thumbnail Height'),
      '#type' => 'textfield',
      '#default_value' => $settings['albumThumbHeight'],
    ];
    $form['fba_settings']['display_settings']['facebook_album_photoThumbWidth'] = [
      '#title' => t('Photo Thumbnail Width'),
      '#type' => 'textfield',
      '#default_value' => $settings['photoThumbWidth'],
    ];
    $form['fba_settings']['display_settings']['facebook_album_photoThumbHeight'] = [
      '#title' => t('Photo Thumbnail Height'),
      '#type' => 'textfield',
      '#default_value' => $settings['photoThumbHeight'],
    ];
    $form['fba_settings']['display_settings']['colorbox'] = [
      '#title' => t('Colorbox Settings'),
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#description' => t('Facebook Albums support displaying images in Colorbox if it is enabled.'),
    ];
    $form['fba_settings']['display_settings']['colorbox']['facebook_album_colorboxOptions'] = [
      '#title' => t('Colorbox Options'),
      '#type' => 'textarea',
      '#default_value' => $settings['colorbox'],
      '#description' => t('Specify any additional Colorbox options here. i.e. "transition:\'elastic\', speed:350"'),
    ];
    return $form;
  }
}

/**
 * Implements hook_block_save().
 */
function facebook_album_block_save($delta = '', $edit = []) {
  if (strpos($delta, 'facebook_album_') !== FALSE) {
    $edit['fba_settings']['facebook_album_albums'] = explode("\r\n", $edit['fba_settings']['facebook_album_albums']);
    variable_set('facebook_album_' . $delta, $edit['fba_settings']);
  }
}

/**
 * Implements hook_block_view().
 */
function facebook_album_block_view($delta = '') {
  $block = [];
  $app_token = variable_get('facebook_album_access_token');
  if (!isset($app_token)) {
    return $block;
  }
  if (strpos($delta, 'facebook_album_') !== FALSE) {
    $settings = facebook_album_get_settings($delta);
    $block['content'] = [
      '#markup' => '<div id="fba-delta-' . $delta . '" class="fba-container"><div class="fb-album-header"></div>' . '<div class="facebook-album-images-container"></div>' . '<div class="fb-loading-icon"></div></div>',
      '#attached' => [
        'css' => [
          drupal_get_path('module', 'facebook_album') . '/css/facebook_album.css',
          '#fba-delta-' . $delta . ' .album-thumb-wrapper i {width:' . $settings['albumThumbWidth'] . 'px;height:' . $settings['albumThumbHeight'] . 'px;}' => [
            'type' => 'inline',
          ],
          '#fba-delta-' . $delta . ' .photo-thumb-wrapper i {width:' . $settings['photoThumbWidth'] . 'px;height:' . $settings['photoThumbHeight'] . 'px;}' => [
            'type' => 'inline',
          ],
        ],
        'js' => [
          drupal_get_path('module', 'facebook_album') . '/js/facebook_album.js',
          [
            'data' => [
              'facebookAlbum' => [
                $delta => [
                  'colorboxOptions' => $settings['colorbox'],
                ],
              ],
            ],
            'type' => 'setting',
          ],
        ],
      ],
    ];
  }
  return $block;
}

/**
 * Takes all customized settings and returns them as an array per block.
 *
 * @param $delta
 *    The block delta.
 *
 * @return array
 *    Settings as specified from the settings menu in facebook_album.admin.inc
 */
function facebook_album_get_settings($delta) {
  $settings = variable_get('facebook_album_' . $delta, []);
  $display_settings = isset($settings['display_settings']) ? $settings['display_settings'] : [];
  return [
    'delta' => $delta,
    'pageID' => isset($settings['facebook_album_pageID']) ? $settings['facebook_album_pageID'] : 'acromediainc',
    'visibility' => isset($settings['facebook_album_visibility']) ? $settings['facebook_album_visibility'] : 0,
    'albums' => isset($settings['facebook_album_albums']) ? $settings['facebook_album_albums'] : [],
    'albumLimit' => isset($display_settings['facebook_album_albumLimit']) ? $display_settings['facebook_album_albumLimit'] : 3,
    'showDescription' => isset($display_settings['facebook_album_showDescription']) ? $display_settings['facebook_album_showDescription'] : 1,
    'showLocation' => isset($display_settings['facebook_album_showLocation']) ? $display_settings['facebook_album_showLocation'] : 1,
    'albumThumbWidth' => isset($display_settings['facebook_album_albumThumbWidth']) ? $display_settings['facebook_album_albumThumbWidth'] : 365,
    'albumThumbHeight' => isset($display_settings['facebook_album_albumThumbHeight']) ? $display_settings['facebook_album_albumThumbHeight'] : 250,
    'photoThumbWidth' => isset($display_settings['facebook_album_photoThumbWidth']) ? $display_settings['facebook_album_photoThumbWidth'] : 160,
    'photoThumbHeight' => isset($display_settings['facebook_album_photoThumbHeight']) ? $display_settings['facebook_album_photoThumbHeight'] : 120,
    'colorbox' => isset($display_settings['colorbox']['facebook_album_colorboxOptions']) ? $display_settings['colorbox']['facebook_album_colorboxOptions'] : '',
    'access_token' => variable_get('facebook_album_access_token', ''),
  ];
}

/**
 * Fetch the first set of photos from the specified album
 *
 * @param $id
 *    The album id to fetch photos from
 * @param $delta
 *    The Block delta for loading settings.
 *
 * @return mixed
 *    A json object containing html template
 */
function facebook_album_ajax_get_album($id, $delta) {
  return facebook_album_ajax_get_album_next($id, NULL, $delta);
}

/**
 * Fetch the next or previous set of photos from the specified album
 *
 * @param $id
 *    The album id to fetch photos from
 * @param $after
 *    The id for fetching the next or previous set of photos
 * @param $delta
 *    The Block delta for loading settings.
 *
 * @return mixed
 *    A json object containing html template
 */
function facebook_album_ajax_get_album_next($id, $after, $delta) {
  $settings = facebook_album_get_settings($delta);
  $url = _facebook_album_build_api_request($id . '/photos', [
    'access_token' => $settings['access_token'],
    'after' => $after,
    'fields' => 'url',
  ]);
  $response = _facebook_album_fetch_api_response($url);
  $module_response['data']['content'] = facebook_album_build_photo_template($settings, $response['data']);
  $module_response['data']['photo_ids'] = $response['data'];
  if (isset($response['paging']) && isset($response['paging']['next'])) {
    $module_response['data']['after'] = $response['paging']['cursors']['after'];
  }
  drupal_json_output($module_response);
}

/**
 * Fetch first set of albums specified in the settings menu.
 *
 * @param $delta
 *    The block delta.
 *
 * @return mixed
 *    A json object containing html template
 */
function facebook_album_ajax_get_albums($delta) {
  return facebook_album_ajax_get_albums_next(NULL, $delta);
}

/**
 * Fetch the next or previous set of cover photos from the specified page ID.
 *
 * @param $after
 *    The id for fetching the next set of albums.
 * @param $delta
 *    The block delta.
 *
 * @return mixed
 *    A json object containing an html template and after id
 */
function facebook_album_ajax_get_albums_next($after, $delta) {
  $settings = facebook_album_get_settings($delta);
  $limit = $settings['albumLimit'];
  if ($limit < 1) {
    $limit = NULL;
  }
  else {

    // ensure that ID's can't be passed in to retrieve albums.
    // if limit has been set to a non-zero number.
    $after = NULL;
  }
  $url = _facebook_album_build_api_request($settings['pageID'] . '/albums', [
    'access_token' => $settings['access_token'],
    'after' => $after,
    'limit' => $limit,
    'fields' => 'location,description,name,cover_photo.fields(images)',
  ]);
  $response = _facebook_album_fetch_api_response($url);
  $module_response['data']['content'] = facebook_album_build_cover_template($settings, $response['data']);
  if (isset($response['paging']) && isset($response['paging']['next']) && $limit == NULL) {
    $module_response['data']['after'] = $response['paging']['cursors']['after'];
  }
  else {
    $module_response['data']['after'] = NULL;
  }
  drupal_json_output($module_response);
}

/**
 * Fetch an individual photo url from a Facebook album photo
 *
 * @param $id
 *    The photo id.
 * @param $delta
 *    The block delta.
 *
 * @return json
 */
function facebook_album_ajax_get_photo_url($id, $delta) {
  $settings = facebook_album_get_settings($delta);
  $module_response = [
    'data' => NULL,
  ];
  $url = _facebook_album_build_api_request($id, [
    'access_token' => $settings['access_token'],
    'fields' => 'images,name',
  ]);
  $response = _facebook_album_fetch_api_response($url);
  if (!isset($response['error'])) {
    $module_response['data']['url'] = $response['images'][0]['source'];
    $module_response['data']['name'] = isset($response['name']) ? $response['name'] : '';
  }
  drupal_json_output($module_response);
}

/**
 * Build the template for displaying album photos
 *
 * @param $settings
 *    An array of settings
 * @param $placeholders
 *
 * @return mixed
 *    A prebuilt block of html containing all album photos
 */
function facebook_album_build_photo_template($settings, $placeholders) {
  return theme('facebook_album_photos', [
    'settings' => $settings,
    'photos' => $placeholders,
  ]);
}

/**
 * Build the template for displaying albums with a filtered data set
 *
 * @param $settings
 *    An array of settings
 * @param $albums
 *    An array of albums from the facebook API
 *
 * @return mixed
 **    A prebuilt block of html containing all albums
 */
function facebook_album_build_cover_template($settings, $albums) {
  $filtered_content = facebook_album_filter_albums($albums, $settings['albums'], $settings['visibility']);
  return theme('facebook_album_covers', [
    'settings' => $settings,
    'photos' => $filtered_content,
  ]);
}

/**
 * The Facebook API does not allow us to specify which albums to load or
 * exclude so after loading the albums we'll simply filter for any albums
 * we want to display
 *
 * @param $albums
 *    An array of albums from the facebook API
 * @param array $album_ids
 *    Album IDs used to determine a whitelist or blacklist of albums from
 * @param bool $include
 *    A flag, that if true, includes all albums specified in $albumIDs,
 *   otherwise it excludes all albums in $albumIDs
 *
 * @return array
 *    An array of filtered albums
 */
function facebook_album_filter_albums($albums, $album_ids = [], $include = TRUE) {
  if (isset($album_ids[0]) && ($album_ids[0] != '' || $album_ids[0] == 0)) {
    $include = (bool) $include;
    $albums = array_filter($albums, function ($album) use ($album_ids, $include) {
      return $include === in_array($album['id'], $album_ids);
    });
  }
  return $albums;
}

/**
 * Utility function to build the API call for accessing Facebook's Graph API
 *
 * @param string $call_path
 *    An extra path to be appended to the api's base url i.e. (albums/)
 * @param array $parameters
 *    Query string parameters to be appended to the api's base url
 *
 * @return string
 *    A built url for the facebook api
 */
function _facebook_album_build_api_request($call_path = '', $parameters = []) {
  $query = http_build_query($parameters);
  return $call_path . '?' . $query;
}

/**
 * Make a curl request to the specified url and return
 * a converted response
 *
 * @param $path
 *    The api path to make a request to
 *
 * @return mixed
 *    A response rendered as an array
 */
function _facebook_album_fetch_api_response($path) {

  // For consistency
  $cid = 'fba:' . str_replace("/", ":", $path);

  // Check cache first before calling API
  if ($cache = cache_get($cid)) {
    $response = $cache->data;
  }
  else {

    // Add api base.
    $url = API_BASE_URL . '/' . $path;

    // Setup cURL call.
    $cURL = curl_init();
    curl_setopt($cURL, CURLOPT_URL, $url);
    curl_setopt($cURL, CURLOPT_HTTPGET, TRUE);
    curl_setopt($cURL, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($cURL, CURLOPT_HTTPHEADER, [
      'Content-Type: application/json',
      'Accept: application/json',
    ]);
    $result = curl_exec($cURL);
    $content_type = curl_getinfo($cURL, CURLINFO_CONTENT_TYPE);
    curl_close($cURL);
    $response = _facebook_album_api_response_to_array($content_type, $result);

    // Cache it if good.
    if (!isset($response['error'])) {
      cache_set($cid, $response, 'cache');
    }
  }
  return $response;
}

/**
 * Convert the API response into an array based on the content type
 * Currently only, json and plain-text responses are supported
 *
 * @param $content_type
 *    The type of content returned in the response. I.e. (json, plain-text,
 *   html)
 * @param $response
 *    The actual response to convert
 *
 * @return mixed
 *    A response converted to an array
 */
function _facebook_album_api_response_to_array($content_type, $response) {
  if (strstr($content_type, 'plain')) {
    $a = explode(',', $response);
    foreach ($a as $response) {
      $b = explode('=', $response);
      $array[$b[0]] = $b[1];
    }
    $response = $array;
  }
  else {
    if (strstr($content_type, 'json')) {
      $response = json_decode($response, TRUE);
    }
    else {
      $response['error']['message'] = t("Unrecognized response type. Unable to parse data.");
      $response['error']['code'] = 10000;
    }
  }
  if (!isset($response['data'])) {
    $response['data'] = [];
  }
  return $response;
}

/**
 * Translate API errors into a user friendly error.
 *
 * @param $code
 *    The error code returned from the facebook API or internally
 * @param $message
 *    The corresponding message to that error code, if there is one
 *
 * @return string
 *    A user friendly error message
 */
function _facebook_album_translate_api_error($code, $message) {
  switch ($code) {
    case 1:
      $message = "Unable to retrieve data from Facebook. This could be due to an invalid Application ID/Application Secret or Facebook is temporarily unreachable.";
      break;
    case 10000:
      $message = "Unable to verify data from Facebook at this time. Please try again.";
      break;
    default:
  }
  return t($message);
}

Functions

Namesort descending Description
facebook_album_ajax_get_album Fetch the first set of photos from the specified album
facebook_album_ajax_get_albums Fetch first set of albums specified in the settings menu.
facebook_album_ajax_get_albums_next Fetch the next or previous set of cover photos from the specified page ID.
facebook_album_ajax_get_album_next Fetch the next or previous set of photos from the specified album
facebook_album_ajax_get_photo_url Fetch an individual photo url from a Facebook album photo
facebook_album_block_configure Implements hook_block_configure().
facebook_album_block_info Implements hook_block_info().
facebook_album_block_save Implements hook_block_save().
facebook_album_block_view Implements hook_block_view().
facebook_album_build_cover_template Build the template for displaying albums with a filtered data set
facebook_album_build_photo_template Build the template for displaying album photos
facebook_album_filter_albums The Facebook API does not allow us to specify which albums to load or exclude so after loading the albums we'll simply filter for any albums we want to display
facebook_album_get_settings Takes all customized settings and returns them as an array per block.
facebook_album_menu Implements menu_hook()
facebook_album_permission Implements hook_permission()
facebook_album_theme Implements hook_theme()
_facebook_album_api_response_to_array Convert the API response into an array based on the content type Currently only, json and plain-text responses are supported
_facebook_album_build_api_request Utility function to build the API call for accessing Facebook's Graph API
_facebook_album_fetch_api_response Make a curl request to the specified url and return a converted response
_facebook_album_translate_api_error Translate API errors into a user friendly error.