<?php
// $Id: user_relationship_blocks.module,v 1.1.2.12 2008/02/24 23:12:36 sprsquish Exp $

/**
 * Constants
 */
define('UR_BLOCK_ALL_TYPES',  'all');

define('UR_BLOCK_SEPARATOR',  '-');

define('UR_BLOCK_MY',   'my');
define('UR_BLOCK_USER', 'user');

define('UR_BLOCK_DEFAULT_SIZE', 10);
define('UR_BLOCK_DEFAULT_SORT', 'newest');



/**
 * Implementation for hook_block
 */
function user_relationship_blocks_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op != 'list') {
    list($block, $rtid, $extra) = explode(UR_BLOCK_SEPARATOR, $delta);
  }

  switch ($op) {
    case 'list':      return _user_relationship_blocks_hook_list();
    case 'configure': return _user_relationship_blocks_form($block, $rtid, $extra);
    case 'save':      return _user_relationship_blocks_save($edit);
    case 'view':      return _user_relationship_blocks_view($block, $rtid, $extra);
  }
}


/**
 * helper function user_relationship_blocks_block delegates to when $op == 'list'
 */
function _user_relationship_blocks_hook_list() {
  $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')),
    $usr.UR_BLOCK_ALL_TYPES => array('info' => t('User Relationships: All relationships')),
    'pending' => array('info' => t('My Pending Relationships')),
    'actions' => array('info' => t('User Relationships: Actions')),
  );

  $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(
        UR_BLOCK_SEPARATOR.'you_to_them' => t('(You to Them)'), 
        UR_BLOCK_SEPARATOR.'them_to_you' => t('(Them to You)'),
      );
    }

    foreach ($extras as $token => $extra) {
      $block_types = array(
        "{$my_delta}{$token}"   => 'My Relationships: @type @extra',
        "{$usr_delta}{$token}"  => 'User Relationships: @type @extra',
      );
      foreach ($block_types as $delta => $title) {
        $blocks[$delta] = array(
          'info' => t($title, array(
            '@type'   => $type->plural_name,
            '@extra'  => $extra
          )),
          'cache' => BLOCK_NO_CACHE,
        );
      }
    }
  }

  return $blocks;
}


/**
 * helper function user_relationship_blocks_block delegates to when $op == 'configure'
 */
function _user_relationship_blocks_form($block, $rtid, $extra) {
  // No form for these so don't even bother
  $no_form_blocks = array('pending', 'actions');
  if (in_array($block, $no_form_blocks)) { return; }

  if ($rtid == UR_BLOCK_ALL_TYPES) {
    $relationship_name = 'All';
  }
  else {
    $type = user_relationships_type_load($rtid);
    $relationship_name = $type->name;
  }
  

  $form = array();

  $var = "user_relationships_block_{$block}_t_{$rtid}_size";
  $form[$var] = array(
    '#type'           => 'textfield',
    '#title'          => t('Number of relationships to display in block'),
    '#description'    => t('Enter the maximum number of relationships to display in this block.'),
    '#size'           => 4,
    '#default_value'  => variable_get($var, UR_BLOCK_DEFAULT_SIZE),
    '#weight'         => 1,
    '#required'       => TRUE,
    '#validate'       => array('user_relationships_setting_validation' => array(array(
      'is_numeric' => array('msg' => t('Number of users must be an integer greater than 0.'))
    )))
  );

  $usr_msg = ($block == UR_BLOCK_MY) ? 'currently logged in user' : 'author whose node is being viewed';
  $msg = "NOTE: This block displays @relationship_name relationships of the {$usr_msg}.";

  if ($extra) {
    $relation = $extra == 'you_to_them' ? t('requester') : t('requestee');
    $msg .= "\nBecause this relationship is one-way this block will show relationships where the {$usr_msg} is the {$relation}";
  }

  $var = "user_relationships_block_{$block}_t_{$rtid}_sort";
  $form[$var] = array(
    '#type'          => 'radios',
    '#title'         => t('Which relationships should be displayed'),
    '#options'       => array( 
      'newest' => t('Newest'), 
      'oldest' => t('Oldest'), 
      'random' => t('Random'),
    ),
    '#default_value' => variable_get($var, UR_BLOCK_DEFAULT_SORT),
    '#required'      => TRUE,
    '#weight'        => 3,
    '#suffix'        => t($msg, array('@relationship_name' => $relationship_name)),
  );

  return $form;
}


/**
 * helper function user_relationship_blocks_block delegates to when $op == 'save'
 */
function _user_relationship_blocks_save(&$edit) {
  foreach ($edit as $key => $value) {
    strpos($key, 'user_relationships_block_') !== FALSE ? variable_set($key, $value) : NULL;
  }
}


/**
 * helper function user_relationship_blocks_block delegates to when $op == 'view'
 */
function _user_relationship_blocks_view($block_type, $rtid, $extra) {
  global $user;
  if (($block_type == UR_BLOCK_MY || $block_type == 'pending') && !$user->uid) { return; }

  // determine which user's relationships to display
  if (!($account = module_invoke_all('user_relationship_blocks', 'display', $block_type, $rtid, $extra))){
    if (($block_type == 'pending' || $block_type == UR_BLOCK_MY) && $user->uid) {
      $account =& $user;
    }
    else {
      // TODO: using the URL arguments like this is bad. find a better way
      if (arg(0) == 'node' && is_numeric(arg(1))) {
        $node = node_load(arg(1));
        $account = user_load(array('uid' => $node->uid));
      }
      else if (arg(0) == 'user' && is_numeric(arg(1))) {
        $account = user_load(array('uid' => arg(1)));
      }
    }
  }

  $function = "_user_relationship_blocks_view_{$block_type}";
  if (function_exists($function)) {
    return $function($account, $block_type, $rtid, $extra);
  }

  // select the appropriate set of relationships based on admin's configuration settings
  switch (variable_get("user_relationships_block_{$block_type}_t_{$rtid}_sort", 'newest')) {
    case 'newest': $order = 'updated_at DESC'; break;
    case 'oldest': $order = 'updated_at ASC'; break;
    case 'random': $order = 'RAND()'; break;
  }

  $limit = variable_get("user_relationships_block_{$block_type}_t_{$rtid}_size", UR_BLOCK_DEFAULT_SIZE);

  $key = $extra ? ($extra == 'you_to_them' ? 'requester_id' : 'requestee_id') : 'user';
  $args = array($key => $account->uid, 'approved' => TRUE);

  if ($rtid != UR_BLOCK_ALL_TYPES) { $args['rtid'] = $rtid; }

  $relationships = user_relationships_load($args, FALSE, 'rid', $order, $limit);

  // get the content of the block
  return theme('user_relationship_block', $account, $relationships, $block_type, $rtid, $extra);
}


/**
 * Show the pending relationships block
 */
function _user_relationship_blocks_view_pending($account, $block_type, $rtype, $extra) {
  if (!$account) { return; }

  return array(
    'subject' => t('Pending Relationships'),
    'content' => theme('user_relationship_block_pending', $account, $block_type, $rtype, $extra),
  );
}


/**
 * Show user relationship actions
 */
function _user_relationship_blocks_view_actions($account, $block_type, $rtype, $extra) {
  return array(
    'subject' => t('User Relationship Actions'),
    'content' => theme('user_relationship_block_actions', $account, $block_type, $rtype, $extra),
  );
}

/**
 * In our case it's a delegator block that just pulls data in from
 * whichever function is more appropriate
 *
 * You can just override the whole thing and send back whatever content you'd like
 */
function theme_user_relationship_block($account, $relationships, $block_type, $rtid, $extra) {
  return array(
    'subject' => theme(
      'user_relationship_block_subject',
      $account, $rtid, $relationships
    ),
    'content' => theme(
      'user_relationship_block_'.($relationships ? 'content' : 'empty'),
      $account, $rtid, $relationships
    ),
  );  
}


/**
 * Generate the title of a My/User Relationships block
 */
function theme_user_relationship_block_subject($account, $rtid, $relationships) {
  if (!$account) { return; }

  global $user;
  $user_name = ($account->uid == $user->uid) ? 'My' : "{$account->name}'s";
  if ($rtid == UR_BLOCK_ALL_TYPES) {
    $type_name = 'Relationships';
  }
  else {
    $rtype      = user_relationships_type_load($rtid);
    $type_name  = $rtype->plural_name;
  }
  $output = t('@user @type', array('@user' => $user_name, '@type' => $type_name));
  return $output;
}


/**
 * Generate the content of a non-empty My/User Relationships block
 */
function theme_user_relationship_block_content($viewing_user, $rtid, $relationships) {
  if (!$viewing_user) { return; }

  $rows = array();
  foreach ($relationships as $relationship) {
    if ($viewing_user->uid == $relationship->requester_id) {
      $extra = $relationship->is_oneway ? t(" (You to Them)") : NULL;
      $relatee = user_load(array('uid' => $relationship->requestee_id));
    }
    else {
      $extra = $relationship->is_oneway ? t(" (Them to You)") : NULL;
      $relatee = user_load(array('uid' => $relationship->requester_id));
    }

    $title = "{$relationship->plural_name}{$extra}";

    $username = theme('username', $relatee);
    if ($rtid == UR_BLOCK_ALL_TYPES) {
      $rows[$title]['data'] = $title;
      $rows[$title]['children'][] = $username;
    }
    else {
      $rows[$title][] = $username;
    }
  }

  foreach ($rows as $title => $users) {
    $output[] = theme('item_list', array($users));
  }

  return implode('', $output);
}


/**
 * Generate the content of an empty My/User Relationships block
 */
function theme_user_relationship_block_empty($account, $rtid) {
  if (!$account) { return; }

  global $user;

  if ($rtid == UR_BLOCK_ALL_TYPES) {
    $rtype_name = 'relationships';
  }
  else {
    $rtype      = user_relationships_type_load($rtid);
    $rtype_name = $rtype->plural_name;
  }

  if ($account->uid == $user->uid) {
    return t('You have no @rels', array('@rels' => $rtype_name));
  }
  else {
    return t('!name has no @rels', array('!name' => theme('username', $account), '@rels' => $rtype_name));
  }
  
}


/**
 * Generate the content for the pending block
 */
function theme_user_relationship_block_pending($account, $block_type, $rtype, $extra) {
  if (!$account) { return; }

  global $user;

  $relationships = user_relationships_load(array('user' => $account->uid, 'approved' => 0));

  $list = array();
  foreach ($relationships as $relationship) {
    if ($user->uid == $relationship->requester_id) {
      $relation_to = $relationship->requestee_id;
      $key = t('From You');
      $controls = theme('user_relationships_pending_request_cancel_link', $user->uid, $relationship->rid);
    }
    else {
      $relation_to = $relationship->requester_id;
      $key = t('To You');
      $controls = 
        theme('user_relationships_pending_request_approve_link', $user->uid, $relationship->rid).'|'.
        theme('user_relationships_pending_request_disapprove_link', $user->uid, $relationship->rid);
    }
    $list[$key][] = t('!username (!controls)', array(
      '!username' => theme('username', user_load(array('uid' => $relation_to))),
      '!controls' => $controls
    ));
  }

  foreach ($list as $title => $users) {
    $output[] = theme('item_list', $users, $title);
  }

  if ($output) {
    return implode('', $output);
  }
  else {
    return t('No Pending Requests');
  }
}


/**
 * Generate the content for the actions block
 */
function theme_user_relationship_block_actions($account, $block_type, $rtype, $extra) {
  if (!$account) { return; }

  global $user;
  $viewer =& $user;

  $output = array();
  if ($viewer != $account && $list = _user_relationships_between($viewer, $account)) {
    $output[] = theme('item_list', $list, t('Your relationships to this user'), 'ul', array('class' => 'user_relationships'));
  }

  if ($actions = _user_relationships_actions_between($viewer, $account)) {
    $output[] = theme('item_list', $actions, t('Relationship actions'), 'ul', array('class' => 'user_relationships_actions'));
  }

  return implode('', $output);
}
