<?php
/**
 * @file
 * Code for the Commons Wikis feature.
 */

include_once 'commons_wikis.features.inc';

/**
* Implements hook_module_implements_alter().
*/
function commons_wikis_module_implements_alter(&$implementations, $hook) {
  // We need to override access control for revision view callbacks
  // in order to give all users permission to view wiki node revisions.
  if ($hook == 'menu_alter') {
    $group = $implementations['commons_wikis'];
    unset($implementations['commons_wikis']);
    $implementations['commons_wikis'] = $group;
  }
}

/**
 * Implements hook_menu_alter().
 */
function commons_wikis_menu_alter(&$items) {
  // Alter the two node menu revision items and change the
  // access callback to our custom one.
  $items['node/%node/revisions']['access arguments'][] = $items['node/%node/revisions']['access callback'];
  $items['node/%node/revisions']['access callback'] = 'commons_wikis_user_revision_access';

  $items['node/%node/revisions/%/view']['access arguments'][] = $items['node/%node/revisions']['access callback'];
  $items['node/%node/revisions/%/view']['access callback'] = 'commons_wikis_user_revision_access';
}

/**
 * Custom access callback for viewing revision info.
 */
function commons_wikis_user_revision_access($node = NULL, $old_callback = '_node_revision_access') {
  // Only use custom revision access for wikis. Access to other content types
  // should be handled by the standard callback.
  if ($node->type == 'wiki') {
    // The content was posted to specific groups.
    if (isset($node->og_group_ref[LANGUAGE_NONE][0]['target_id'])) {
      return og_user_access('node', $node->og_group_ref[LANGUAGE_NONE][0]['target_id'], 'update any wiki content');
    }
    // The content was posted privately to all trusted contacts.
    elseif (isset($node->og_user_group_ref[LANGUAGE_NONE][0]['target_id'])) {
      return og_user_access('user', $node->og_user_group_ref[LANGUAGE_NONE][0]['target_id'], 'update any wiki content');
    }
  }
  return $old_callback($node, 'view');
}

/**
 * Implements hook_og_user_access_alter().
 */
function commons_wikis_og_user_access_alter(&$temp_perm, $context) {
  // Only alter if we're dealing with updating wiki content.
  if ($context['string'] != 'update any wiki content') {
    return;
  }

  $account = $context['account'];
  $group = $context['group'];
  $group_type = $context['group_type'];

  $wrapper = entity_metadata_wrapper($group_type, $group);
  $entity_id = $wrapper->getIdentifier();

  $group_content_restricted = (bool) !isset($wrapper->field_og_subscribe_settings) || (isset($wrapper->field_og_subscribe_settings) && $wrapper->field_og_subscribe_settings->value() != 'anyone');
  $user_is_member = (bool) og_is_member($group_type, $entity_id, 'user', $account, array(OG_STATE_ACTIVE));

  // Allow group members to be able to edit any wiki content within the group.
  // Also grant access to non-members if both the group and content is public.
  if (user_access('edit any wiki content', $account) && (!$group_content_restricted || $user_is_member)) {
    $temp_perm['update any wiki content'] = TRUE;
  }
}

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function commons_wikis_form_node_form_alter(&$form, &$form_state, $form_id) {
  $node = $form['#node'];

  list(, , $bundle) = entity_extract_ids('node', $node);

  if ($bundle == 'wiki' && empty($node->nid)) {
    drupal_set_title(t('Create a wiki'));
  }
}

/**
 * Implements hook_form_FROM_ID_alter().
 */
function commons_wikis_form_commons_bw_partial_node_form_alter(&$form, &$form_state) {
  if (empty($form['#entity']) || $form['#entity']->type != 'wiki') {
    return;
  }

  $form['title']['#markup'] = t('Create a wiki');

  $language = $form['title_field']['#language'];
  $form['title_field'][$language][0]['value']['#title_display'] = 'invisible';
  $form['title_field'][$language][0]['value']['#placeholder'] = t('Enter a Wiki title');

  $language = $form['body']['#language'];
  $form['body'][$language][0]['#title_display'] = 'invisible';
  $form['body'][$language][0]['#resizable'] = FALSE;

  // Set fields as hideable so the forms can be compacted.
  $form['title_field']['#attributes']['class'][] = 'trigger-field';
  foreach (array('body', 'og_group_ref', 'actions') as $field) {
    if (isset($form[$field])) {
      $form[$field]['#attributes']['class'][] = 'hideable-field';
    }
  }

  $form['actions']['submit']['#value'] = t('Create');
  $form['#pre_render'][] = 'commons_wikis_form_commons_bw_partial_node_form_after_build';
}

/**
 * After-build call-back.
 * See commons_wikis_form_commons_bw_partial_node_form_alter().
 */
function commons_wikis_form_commons_bw_partial_node_form_after_build($form) {
  $language = $form['body']['#language'];
  $form['body'][$language][0]['format']['#access'] = FALSE;
  $form['body'][$language][0]['value']['#rows'] = 10;

  return $form;
}

/**
 * Implements hook_strongarm_alter().
 */
 function commons_wikis_strongarm_alter(&$items) {
  // Expose the wiki content type for integration with Commons Radioactivity
  // and Commons Groups.
  foreach (array('commons_radioactivity_entity_types', 'commons_groups_entity_types') as $key) {
    if (isset($items[$key])) {
      $items[$key]->value['node']['wiki'] = 1;
    }
  }
}

/**
 * Implements hook_node_update().
 */
function commons_wikis_node_update($node) {
  if ($node->type == 'wiki' && module_exists('message')) {
    global $user;
    commons_groups_first_contribution($user, $node);
    $message = message_create('commons_wikis_wiki_updated', array('uid' => $user->uid, 'timestamp' => REQUEST_TIME));
    $wrapper = entity_metadata_wrapper('message', $message);
    // Save reference to the node in the node reference field.
    // We use a multiple value field in case we wish to use the same
    // field for grouping messages in the future
    // (eg http://drupal.org/node/1757060).
    $wrapper->field_target_nodes[] = $node;
    $wrapper->save();
  }
}

/**
 * Implements hook_views_pre_render().
 */
function commons_wikis_views_pre_render(&$view) {
  // Improve the browsing widget empty text when displayed outside of a group.
  // TODO: Enable og_context and check group context instead of looking for an
  // empty first argument.
  if (empty($view->args[0]) && $view->name == 'commons_bw_wikis') {
    $view->display_handler->handlers['empty']['area']->options['content'] = t('No wikis have been created.');
  }
}
