<?php
/**
 * @file
 * User Relationship Blocks implementation
 * @author Jeff Smick (creator)
 * @author Alex Karshakevich (maintainer) http://drupal.org/user/183217
 */

/**
 * Constants
 */
define('UR_BLOCK_ALL_TYPES', 'all');

define('UR_BLOCK_SEPARATOR', '-');

define('UR_BLOCK_MY', 'my');
define('UR_BLOCK_USER', 'user');

/**
 * Implements hook_user_relationships_type_delete().
 */
function user_relationship_blocks_user_relationships_type_delete($rtype) {
  db_delete('user_relationship_blocks')
    ->condition('bid', '%-' . UR_BLOCK_SEPARATOR . $rtype->rtid . '%', 'LIKE')
    ->execute();
}

/**
 * Implementation for hook_theme
 */
function user_relationship_blocks_theme() {
  return array(
    'user_relationship_block_subject' => array(
      'variables' => array('account' => NULL, 'rtid' => NULL, 'extra' => NULL)
    ),

    'user_relationships_block' => array(
      'variables' => array('account' => NULL, 'settings' => NULL, 'extra' => NULL),
      'path'      => drupal_get_path('module', 'user_relationship_blocks') . '/templates',
      'template'  => 'user_relationships-block',
    ),
    'user_relationships_pending_block' => array(
      'variables' => array('account' => NULL, 'settings' => NULL),
      'path'      => drupal_get_path('module', 'user_relationship_blocks') . '/templates',
      'template'  => 'user_relationships-pending_block',
    ),
    'user_relationships_actions_block' => array(
      'variables' => array('account' => NULL, 'settings' => NULL),
      'path'      => drupal_get_path('module', 'user_relationship_blocks') . '/templates',
      'template'  => 'user_relationships-actions_block',
    ),
  );
}


/**
 * Theme function to generate the title of a block
 */
function theme_user_relationship_block_subject($variables) {
  $bid = $variables['bid'];
  $account = $variables['account'];
  $rtid = $variables['rtid'];
  $extra = $variables['extra'];
  if ($bid == 'pending') {
    return t('Relationship requests');
  }
  elseif ($bid == 'actions') {
    return t('Relationship actions');
  }
  //one-way relationships need special wording depending on the direction
  //this implies that we're showing a single relationship, no need to check for UR_BLOCK_ALL_TYPES
  elseif ($extra == 'you_to_them') {
    global $user;
    $rtype = user_relationships_type_load($rtid);
    if ($account->uid == $user->uid) {
      return t('I am a @rel_name of', user_relationships_type_translations($rtype));
    }
    else {
      return t('@username is a @rel_name of', array('@username' => format_username($account)) + user_relationships_type_translations($rtype));
    }
  }
  else {
    global $user;
    if ($rtid == UR_BLOCK_ALL_TYPES) {
      $output = ($account->uid == $user->uid) ? t('My relationships') : t("@username's relationships", array('@username' => format_username($account)));
    }
    else {
      $rtype = user_relationships_type_load($rtid);
      $output = ($account->uid == $user->uid)
                ? t('My @rel_name', user_relationships_type_translations($rtype))
                : t("@username's @rel_name", array('@username' => format_username($account)) + user_relationships_type_translations($rtype));
    }
    return $output;
  }
}



/*****************************
 *
 * "Private" helper methods
 *
 *****************************/


/**
 * helper function user_relationship_blocks_block delegates to when $op == 'configure'
 */
function user_relationship_blocks_block_configure($delta) {

  //pad array with nulls before calling list() to avoid php notices
  $exploded = explode(UR_BLOCK_SEPARATOR, $delta);
  while (count($exploded) < 3) {
    $exploded[] = NULL;
  }
  list($block, $rtid, $extra) = $exploded;

  // No form needed for the pending block so don't even bother
  if ($block == 'pending') {
    return;
  }

  //current block settings
  $settings = user_relationship_blocks_block_save($delta);

  if ($block != 'actions') {
    if ($rtid == UR_BLOCK_ALL_TYPES) {
      $relationship_name = t('All');
    }
    else {
      $type = user_relationships_type_load($rtid);
      $relationship_name = user_relationships_type_get_name($type);
    }

    $form['size'] = array(
      '#type'           => 'textfield',
      '#size'           => 4,
      '#weight'         => 1,
      '#required'       => TRUE,
      '#title'          => t('Number of relationships to display in block'),
      '#description'    => t('Enter the maximum number of relationships to display in this block.'),
      '#default_value'  => $settings->size,
      '#validate'       => array('user_relationships_ui_setting_validation' => array(array(
        'is_positive' => array('size' => t('Number of relationships to display must be an integer greater than 0.'))
      )))
    );

    $user_identifier = ($block == UR_BLOCK_MY) ? t('currently logged in user') : t('author whose node is being viewed');
    $msg = t("NOTE: This block displays @rel_name relationships of the @user_identifier.", array('@rel_name' => $relationship_name, '@user_identifier' => $user_identifier));

    if ($extra) {
      $relation = $extra == 'you_to_them' ? t('requester') : t('requestee');
      $msg .= "\n" . t("Because this relationship is one-way this block will show relationships where the @user_identifier is the @relation", array('@user_identifier' => $user_identifier, '@relation' => $relation));
    }

    //$sort_var = "{$var}_sort";
    $form['sort'] = array(
      '#type'     => 'radios',
      '#title'    => t('Which relationships should be displayed'),
      '#options'  => array(
        'newest' => t('Newest'),
        'oldest' => t('Oldest'),
        'random' => t('Random'),
      ),
      '#default_value' => $settings->sort,
      '#required'      => TRUE,
      '#weight'        => 3,
      '#suffix'        => $msg,
    );
  }

  $form['bid'] = array(
    '#type'   => 'hidden',
    '#value'  => $delta,
  );
  return $form;
}


/**
 * helper function user_relationship_blocks_block delegates to when $op == 'view'
 */
function user_relationship_blocks_block_view($delta) {
  global $user;

  //pad array with nulls before calling list() to avoid php notices
  $exploded = explode(UR_BLOCK_SEPARATOR, $delta);
  while (count($exploded) < 3) {
    $exploded[] = NULL;
  }
  list($block_type, $rtid, $extra) = $exploded;

  $is_my_block = ($block_type == UR_BLOCK_MY || in_array($block_type, array('pending')));
  if ($is_my_block && !$user->uid) {
    return;
  }

  $settings = user_relationship_blocks_block_save($delta);
  $settings->rtid = $rtid;
  $settings->block_type = $block_type;

  // determine which user's relationships to display
  if ($is_my_block) {
    // Only allow access if the user has permissions to view his own
    // relationships.
    if (user_relationships_ui_check_access('view', $user, user_relationships_type_load($rtid))) {
      $account = $user;
    }
  }
  elseif ($uid = _user_relationship_blocks_get_uid($delta)) {
    $account_loaded = user_load($uid);
    if ($account_loaded && user_relationships_ui_check_access('view', $account_loaded, user_relationships_type_load($rtid))) {
      $account = $account_loaded;
    }
  }

  if (!empty($account)) {
    $add_to_string = in_array($block_type, array('pending', 'actions')) ? "_{$block_type}" : '';
    return array(
      'subject' => theme('user_relationship_block_subject', array('bid' => $delta, 'account' => $account, 'rtid' => $rtid, 'extra' => $extra)),
      'content' => theme("user_relationships{$add_to_string}_block", array('account' => $account, 'settings' => $settings, 'extra' => $extra)),
    );
  }
}


/**
 * Figure out which account is currently viewed.
 *
 * @param $delta
 *   The delta of the block that is currently viewed.
 *
 * @return
 *   Either the uid of the user owning the displayed profile, node or blog.
 */
function _user_relationship_blocks_get_uid($delta) {

  // Call hook, this allows other modules to declare other ways to detect the
  // currently viewed user.
  foreach (module_implements('user_relationship_blocks_get_uid') as $module) {
    $function = $module . '_user_relationship_blocks_get_uid';
    if ($uid = $function($delta)) {
      return $uid;
    }
  }

  if ($node = menu_get_object()) {
    return $node->uid;
  }
  if ($user = menu_get_object('user')) {
    return $user->uid;
  }
  if (arg(0) == 'blog' && arg(1) > 0) {
    return arg(1);
  }
}


/**
 * helper function user_relationship_blocks_block delegates to when $op == 'list'
 */
function user_relationship_blocks_block_info() {
  $my   = UR_BLOCK_MY . UR_BLOCK_SEPARATOR;
  $usr  = UR_BLOCK_USER . UR_BLOCK_SEPARATOR;
  // return list of all blocks defined by the module
  $blocks = array(
    $my . UR_BLOCK_ALL_TYPES  => array('info' => t('My Relationships: All relationships'), 'cache' => DRUPAL_NO_CACHE),
    $usr . UR_BLOCK_ALL_TYPES => array('info' => t('User Relationships: All relationships'), 'cache' => DRUPAL_NO_CACHE),
    'pending' => array('info' => t('My Pending Relationships'), 'cache' => DRUPAL_NO_CACHE),
    'actions' => array('info' => t('User Relationships: Actions'), 'cache' => DRUPAL_NO_CACHE),
  );

  $types = user_relationships_types_load();
  foreach ($types as $type) {
    $my_delta   = "{$my}{$type->rtid}";
    $usr_delta  = "{$usr}{$type->rtid}";

    $extras = array('' => '');

    if ($type->is_oneway) {
      $extras = array(
        //add a little explanation about one-way relationships
        UR_BLOCK_SEPARATOR . 'you_to_them' => t('(You to Them, backward direction)'),
        UR_BLOCK_SEPARATOR . 'them_to_you' => t('(Them to You, normal direction)'),
      );
    }

    foreach ($extras as $token => $extra) {
      $block_types = array(
        "{$my_delta}{$token}" => t('My Relationships: @rel_name_plural @extra', array('@extra' => $extra) + user_relationships_type_translations($type)),
        "{$usr_delta}{$token}" => t('User Relationships: @rel_name_plural @extra', array('@extra' => $extra) + user_relationships_type_translations($type)),
      );
      foreach ($block_types as $bid => $title) {
        $blocks[$bid] = array(
          'info' => $title,
          'cache' => DRUPAL_NO_CACHE,
        );
      }
    }
  }

  return $blocks;
}


/**
 * Push or pull the settings from the database
 */
function user_relationship_blocks_block_save($delta = NULL, $edit = NULL) {
  $settings = drupal_static(__FUNCTION__, array());

  if (isset($edit)) {
    if (empty($edit['bid'])) {
      $edit['bid'] = $edit['delta'];
    }
    db_merge('user_relationship_blocks')
      ->key(array(
        'bid' => isset($edit['bid']) ? $edit['bid'] : $edit['delta'],
      ))
      ->fields(array(
        'size' => $edit['size'],
        'sort' => $edit['sort'],
      ))
      ->execute();
    $settings[$delta] = (object) $edit;
  }
  elseif ($delta && (!isset($settings[$delta]) || !$settings[$delta])) {
    $settings[$delta] = db_query("SELECT * FROM {user_relationship_blocks} WHERE bid = :bid", array(':bid' => $delta))->fetchObject();
    if (!$settings[$delta]) {
      // No overridden settings yet, return default array.
      $settings[$delta] = (object) array(
        'size' => 10,
        'bid' => $delta,
        'sort' => 'newest',
      );
    }
    return $settings[$delta];
  }
  else {
    $settings = db_query("SELECT * FROM {user_relationship_blocks}")->fetchAllAssoc('bid');
    return $settings;
  }
}

/**
 * Template pre processor for the main block view
 */
function template_preprocess_user_relationships_block(&$variables) {
  $account  = &$variables['account'];
  $settings = &$variables['settings'];
  $extra    = &$variables['extra'];

  $query_opts = array('include_user_info' => TRUE);

  if (empty($settings->sort)) {
    $settings->sort = 'newest';
  }
  if (empty($settings->size)) {
    $settings->size = 10;
  }

  // select the appropriate set of relationships based on admin's configuration settings
  switch ($settings->sort) {
    case 'newest':
      $query_opts['order'] = array('changed', 'DESC');
      break;
    case 'oldest':
      $query_opts['order'] = array('changed', 'ASC');
      break;
    case 'random':
      $query_opts['order'] = 'RAND()';
      break;
  }

  $query_opts['limit'] = $settings->size;

  $key = $extra ? ($extra == 'you_to_them' ? 'requester_id' : 'requestee_id') : 'user';
  $args = array($key => $account->uid, 'approved' => TRUE);

  if ($settings->rtid != UR_BLOCK_ALL_TYPES) {
    $args['rtid'] = $settings->rtid;
  }

  $variables['relationships'] = user_relationships_load($args, $query_opts);
}


/**
 * Template pre processor for the pending relationships block
 */
function template_preprocess_user_relationships_pending_block(&$variables) {
  $account = &$variables['account'];

  $variables['relationships'] = user_relationships_load(array('user' => $account->uid, 'approved' => FALSE), array('include_user_info' => TRUE));
}


/**
 * Template pre processor for the relationship actions block
 */
function template_preprocess_user_relationships_actions_block(&$variables) {
  $user     = &$variables['user'];
  $account  = &$variables['account'];

  if ($user != $account) {
    $variables['current_relationships'] = user_relationships_ui_actions_between($user, $account, array('remove' => 1));
  }

  $variables['actions'] = user_relationships_ui_actions_between($user, $account, array('add' => 1, 'requested' => 1, 'received' => 1));
}
