You are here

oa_subspaces.module in Open Atrium Subspaces 7.2

File

oa_subspaces.module
View source
<?php

/**
 * @file
 * Code for the Open Atrium Subgroup Intergration for Spaces feature.
 */
include_once 'oa_subspaces.features.inc';

/**
 * Name of default Parent Space field.
 */
define('OA_PARENT_SPACE', 'oa_parent_space');

/**
 * Name of caches.
 */
define('OA_SUBSPACES_CACHE_CHILDREN', 'oa_subspaces_children');
define('OA_SUBSPACES_CACHE_PARENTS', 'oa_subspaces_parents');

/**
 * Implements hook_form_alter().
 * Hook into the Node Edit form
 */
function oa_subspaces_form_node_form_alter(&$form, $form_state, $form_id) {
  $node = $form['#node'];
  if (isset($form[OA_PARENT_SPACE][LANGUAGE_NONE][0])) {
    $form['#validate'][] = 'oa_subspaces_form_node_form_validate';

    // make some shortcut pointers to make the rest of this code easier to read
    $parent_default =& $form[OA_PARENT_SPACE][LANGUAGE_NONE][0]['default'];
    $parent_admin =& $form[OA_PARENT_SPACE][LANGUAGE_NONE][0]['admin'];

    // clean up the edit form
    if (!empty($parent_admin)) {

      // Hide admin field but allow any values to persist.
      $parent_admin['#access'] = FALSE;
    }
    $parent_default['#title'] = t('Parents');
    $parent_default['#description'] = t('Inherit membership from the selected parents.');
    $type = $node->type;
    $gid = oa_core_get_space_context();
    $set_parent = FALSE;
    if (!empty($_GET[OA_PARENT_SPACE]) && is_numeric($_GET[OA_PARENT_SPACE])) {
      $gid = $_GET[OA_PARENT_SPACE];
      $set_parent = TRUE;
    }

    // Make sure user can create in this group.
    $gid = og_user_access('node', $gid, "create {$node->type} content") ? $gid : NULL;

    // See if the user could create this type without parent set.
    $admin_access = user_access('administer group') || node_access('create', $type);
    if (empty($node->nid)) {

      // If they are being granted create permission based on group permission
      // restrict the parent field to current group so don't have to deal with
      // changing values in form based on changed parent field.
      if (!$admin_access) {
        if (!$gid) {
          drupal_access_denied();
          die;
        }
        else {
          $set_parent = TRUE;
          $parent_default['#access'] = FALSE;
          $parent_default = $gid;
          drupal_set_title(t('Create @type in @title', array(
            '@type' => node_type_get_name($type),
            '@title' => $parent_default['#options'][$gid],
          )));
        }
      }
    }
    elseif (!$admin_access && !empty($form['field_oa_space_type'])) {
      $form['field_oa_space_type']['#access'] = FALSE;
      $form[OA_PARENT_SPACE]['#access'] = FALSE;
    }
    if (isset($form[OG_USER_INHERITANCE_FIELD][LANGUAGE_NONE]) && isset($form[OG_USER_INHERITANCE_PERMISSION_FIELD][LANGUAGE_NONE])) {
      $form[OG_USER_INHERITANCE_PERMISSION_FIELD][LANGUAGE_NONE]['#states'] = array(
        'visible' => array(
          ':input[name="og_user_inheritance[und]"]' => array(
            'value' => 1,
          ),
        ),
      );

      // This field acts odd when required but user doesn't have access, throws
      // a required warning when 0 is valid and works fine otherwise
      $form[OG_USER_INHERITANCE_PERMISSION_FIELD][LANGUAGE_NONE]['#required'] = FALSE;
    }

    // Fill in default value.
    if (empty($node->nid) && $set_parent && $gid && ($group = node_load($gid))) {
      $parent_default['#default_value'] = $group->title . ' (' . $group->nid . ')';
      $parent_default['#init'][$group->nid] = $parent_default['#default_value'];
    }
  }
}

/**
 * Validation function for node edit form
 */
function oa_subspaces_form_node_form_validate($form, &$form_state) {
  $node = $form['#node'];
  if (!empty($node->nid) && !empty($form_state['values'][OA_PARENT_SPACE][LANGUAGE_NONE])) {
    foreach ($form_state['values'][OA_PARENT_SPACE][LANGUAGE_NONE] as $oa_parent) {
      if (!empty($oa_parent['target_id']) && $oa_parent['target_id'] == $node->nid) {
        form_set_error(OA_PARENT_SPACE, t('You cannot set the Parent Space to itself.'));
        return;
      }
    }
  }
}

/**
 * Return children of Space, regardless of the inheritance field.
 * DEPRECATED:  Use oa_core_get_groups_by_parent() instead.
 *
 * @param $group_type
 *   The group (entity) type.
 * @param $group_id
 *   The group (entity) ID.
 *
 * @return array
 *   An array of NIDs.
 */
function oa_subspaces_get_children_groups($group_type, $group_id) {
  return oa_core_get_groups_by_parent($group_id);
}

/**
 * Return parents of a Space, regardless of the inheritance field.
 * DEPRECATED: Use oa_core_get_parents() instead.
 *
 * @param $group_type
 *   The group (entity) type.
 * @param $group_id
 *   The group (entity) ID.
 *
 * @return array
 *   An array of NIDs.
 */
function oa_subspaces_get_parent_groups($group_type, $group_id) {
  return oa_core_get_parents($group_id);
}

/**
 * Implements hook_oa_clear_cache
 */
function oa_subspaces_oa_clear_cache($node = NULL, $uid = NULL, $include_archived = FALSE) {
  $cid = oa_core_get_cache_id(OA_SUBSPACES_CACHE_CHILDREN, NULL, $include_archived);
  oa_core_clear_cache(OA_SUBSPACES_CACHE_CHILDREN, $cid);
  $cid = oa_core_get_cache_id(OA_SUBSPACES_CACHE_PARENTS, NULL, $include_archived);
  oa_core_clear_cache(OA_SUBSPACES_CACHE_PARENTS, $cid);
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function oa_subspaces_form_views_exposed_form_alter(&$form, &$form_state, $form_id) {
  if (!empty($form['og_group_ref_target_id'])) {
    $view = $form_state['view'];
    $exposed_form_overrides = $view->display_handler
      ->get_option('exposed_form_overrides');
    $pane_conf = $view->display_handler
      ->get_option('pane_conf');
    $settings = _oa_subspaces_find_view_settings($form_state['view'], $form_state);
    if ($settings['og_group_ref_target_id'] && is_numeric($settings['og_group_ref_target_id'])) {
      _oa_subspaces_add_element_all($form, $form_state, $settings);
      _oa_subspaces_add_element_parent($form, $form_state, $settings);
    }
  }
}

/**
 * Helper to convert a hierarchical array back to a flat list with -- in titles
 */
function _oa_subspaces_build_options($list, $depth = 0) {
  $result = array();
  if (!empty($list)) {
    foreach ($list as $nid => $sublist) {
      $result[$nid] = str_repeat('--', $depth) . $sublist['title'];
      $result += _oa_subspaces_build_options($sublist['children'], $depth + 1);
    }
  }
  return $result;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function oa_subspaces_form_views_content_views_panes_content_type_edit_form_alter(&$form, &$form_state, $form_id) {

  // Doing it to the exposed form alone doesn't work :(.
  // Need to also do it for the pane config form
  if (!empty($form['exposed']['filter-og_group_ref_target_id']['og_group_ref_target_id'])) {
    $settings = _oa_subspaces_find_view_settings($form_state['view'], $form_state);
    _oa_subspaces_add_element_all($form['exposed']['filter-og_group_ref_target_id'], $form_state, $settings, array(
      'exposed',
    ));
    _oa_subspaces_add_element_parent($form['exposed']['filter-og_group_ref_target_id'], $form_state, $settings, array(
      'exposed',
    ));
  }
}

/**
 * Helper to add a checkbox to the exposed filter
 */
function _oa_subspaces_add_checkbox(&$element, $id, $title, &$form_state, $settings, $parents = array()) {
  $parents[] = $id;
  $value = $settings[$id];
  $element[$id] = array(
    '#title' => t($title),
    '#type' => 'checkbox',
    '#default_value' => $value,
    '#parents' => $parents,
  );

  // Unchecked checkboxes need to have a NULL input or else it is still
  // considered to be a checked box
  // see form.inc form_type_checkbox_value
  if (empty($value) && isset($form_state['input'][$id])) {
    unset($form_state['input'][$id]);
  }
}

/**
 * Helper to add the 'Show subspace content' checkbox at same place as group ref.
 */
function _oa_subspaces_add_element_all(&$element, &$form_state, $settings, $parents = array()) {
  _oa_subspaces_add_checkbox($element, 'og_subspaces_view_all', 'Show subspace content', $form_state, $settings, $parents);
}

/**
 * Helper to add the 'Show parent content' checkbox at same place as group ref.
 */
function _oa_subspaces_add_element_parent(&$element, &$form_state, $settings, $parents = array()) {
  _oa_subspaces_add_checkbox($element, 'og_subspaces_view_parent', 'Show parent content', $form_state, $settings, $parents);
}

/**
 * Finding the active current configuration for each is a pane in the ***.
 */
function _oa_subspaces_find_view_settings($view = NULL, $form_state = NULL) {
  $find = array(
    'og_subspaces_view_all',
    'og_subspaces_view_parent',
    'oa_section_ref_target_id',
    'og_group_ref_target_id',
    'og_group_ref_target_id_mine',
  );
  $return = array();
  foreach ($find as $key) {

    // check for a form key that always returns a value
    // otherwise checkboxes (like og_subspaces_view_all) cannot be unchecked
    // because they don't return any result in $_GET from browser
    if (isset($_GET['og_group_ref_target_id'])) {
      $return[$key] = isset($_GET[$key]) ? $_GET[$key] : NULL;
    }
    elseif (isset($_POST['exposed'][$key])) {
      $return[$key] = $_POST['exposed'][$key];
    }
    elseif ($form_state && isset($form_state['values']['exposed'][$key])) {
      $return[$key] = $form_state['values']['exposed'][$key];
    }
    elseif ($form_state && isset($form_state['values'][$key])) {
      $return[$key] = $form_state['values'][$key];
    }
    elseif ($form_state && isset($form_state['input'][$key])) {
      $return[$key] = $form_state['input'][$key];
    }
    elseif ($form_state && isset($form_state['conf']['exposed'][$key])) {
      $return[$key] = $form_state['conf']['exposed'][$key];
    }
    elseif ($view && isset($view->exposed_raw_input[$key])) {
      $return[$key] = $view->exposed_raw_input[$key];
    }
    elseif ($view && isset($view->exposed_input[$key])) {
      $return[$key] = $view->exposed_input[$key];
    }
    elseif ($view && isset($view->display_handler->options['pane_conf'][$key])) {
      $return[$key] = $view->display_handler->options['pane_conf'][$key];
    }
    else {
      $return[$key] = FALSE;
    }
    if ($return[$key] === 'All' || !is_numeric($return[$key])) {
      $return[$key] = FALSE;
    }
  }
  if (!empty($return['og_group_ref_target_id_mine'])) {
    $return['og_group_ref_target_id'] = FALSE;
    $return['og_subspaces_view_all'] = FALSE;
    $return['og_subspaces_view_parent'] = FALSE;
  }
  elseif (isset($return['og_group_ref_target_id']) && (empty($return['og_group_ref_target_id']) || $return['og_group_ref_target_id'] == OA_SPACE_CURRENT)) {
    if ($group = oa_core_get_space_context()) {
      $return['og_group_ref_target_id'] = $group;
    }
  }
  return $return;
}

/**
 * Implements hook_views_pre_view().
 */
function oa_subspaces_views_pre_view(&$view) {

  // If we are in a View where a specific group is being filtered for in an
  // exposed filter (as opposed to selecting '- Any -' or '- Active Space -').
  $style_setting = !empty($view->display_handler->options['pane_conf']['view_settings']) ? $view->display_handler->options['pane_conf']['view_settings'] : (!empty($view->display_handler->options['style_plugin']) ? $view->display_handler->options['style_plugin'] : NULL);
  $allowed_styles = variable_get('oa_subspaces_view_og_group_ref_styles', array(
    'table',
  ));
  if ($allowed_styles && $style_setting && in_array($style_setting, $allowed_styles) && !empty($view->display_handler->default_display->options['filters']['og_group_ref_target_id']['exposed'])) {
    $settings = _oa_subspaces_find_view_settings($view);
    $og_subspaces_view_all = $settings['og_subspaces_view_all'] && $settings['og_group_ref_target_id'] && oa_core_get_groups_by_parent($settings['og_group_ref_target_id']);
    $og_subspaces_view_parent = $settings['og_subspaces_view_parent'] && $settings['og_group_ref_target_id'] && oa_core_get_parents($settings['og_group_ref_target_id']);
    if ($og_subspaces_view_all || $og_subspaces_view_parent) {

      // If parent or children filtering is turned on (and there are any parents
      // or children to be found), then we add a field so we can see what group
      // the content is coming from.
      $view->display_handler->default_display->options['fields'] = array(
        'og_group_ref' => array(
          'id' => 'og_group_ref',
          'table' => 'og_membership',
          'field' => 'og_group_ref',
          'label' => 'Space',
          'settings' => array(
            'link' => 1,
          ),
        ),
      ) + $view->display_handler->default_display->options['fields'];
    }
  }
}

/**
 * Implements hook_views_query_alter().
 */
function oa_subspaces_views_query_alter(&$view, &$query) {
  if (!empty($view->exposed_input['og_group_ref_target_id']) && is_numeric($view->exposed_input['og_group_ref_target_id']) && !empty($view->filter['og_group_ref_target_id']->options['exposed'])) {
    $settings = _oa_subspaces_find_view_settings($view);

    // Get all the parent or child groups if we are filtering for them.
    $current_group = $view->exposed_input['og_group_ref_target_id'];
    $extra_groups = array();
    if ($settings['og_subspaces_view_all']) {
      $extra_groups = array_merge($extra_groups, oa_core_get_groups_by_parent($current_group, OA_SPACE_TYPE, NULL, FALSE, NULL, TRUE));
    }
    if ($settings['og_subspaces_view_parent']) {
      $extra_groups = array_merge($extra_groups, oa_core_get_parents($current_group, OA_SPACE_TYPE, NULL, FALSE, TRUE));
    }

    // Add the extra groups to query, if there are any.
    if (!empty($extra_groups)) {
      $columns = array(
        'og_membership.gid',
        'field_data_oa_other_spaces_ref.oa_other_spaces_ref_target_id',
      );
      oa_core_view_query_modify_condition($query, $columns, $extra_groups);
    }
    if (!empty($view->exposed_input['oa_section_ref_target_id']) && is_numeric($view->exposed_input['oa_section_ref_target_id']) && !empty($view->filter['oa_section_ref_target_id']->options['exposed'])) {
      if (!empty($extra_groups)) {
        $columns = array(
          'field_data_oa_section_ref.oa_section_ref_target_id',
        );
        $extra_sections = oa_subspaces_matching_sections($view->exposed_input['oa_section_ref_target_id'], $extra_groups, array(
          $current_group,
        ));
        oa_core_view_query_modify_condition($query, $columns, $extra_sections);
      }
    }
  }
}

/**
 * Return an array of section ids with the same Name as $section_id
 * @param $entity entity or entity_id
 */
function oa_subspaces_matching_sections($entity, $groups = array(), $omit_groups = array()) {
  $cache =& drupal_static(__FUNCTION__, array());
  if (is_numeric($entity)) {

    // Get the entity.
    $entity = current(entity_load('node', array(
      $entity,
    )));
  }
  $id = $entity->nid;
  if (isset($cache[$id])) {

    // Return cached values.
    return $cache[$id];
  }
  $cache[$id] = array();
  $query = db_select('node', 'n');
  $query
    ->leftJoin('og_membership', 'f', "n.nid = f.etid");
  if (!empty($groups)) {
    $query
      ->condition('f.gid', $groups, 'IN');
  }
  if (!empty($omit_groups)) {
    $query
      ->condition('f.gid', $omit_groups, 'NOT IN');
  }
  $query
    ->fields('n', array(
    'nid',
  ))
    ->condition('f.entity_type', 'node')
    ->condition('n.status', 1)
    ->condition('n.title', $entity->title)
    ->addTag('node_access');
  $cache[$id] = $query
    ->execute()
    ->fetchCol(0);
  return $cache[$id];
}

/**
 * Implements hook_field_access().
 */
function oa_subspaces_field_access($op, $field, $entity_type, $entity, $account) {
  if (!empty($field['field_name']) && $field['field_name'] == OG_USER_INHERITANCE_PERMISSION_FIELD && $op == 'edit') {
    return user_access('administer group', $account);
  }
  return TRUE;
}

/**
 * Implements hook_og_permission_alter().
 *
 * Changes group create permissions to restricted.
 */
function oa_subspaces_og_permission_alter(&$permissions) {
  foreach (node_permissions_get_configured_types() as $type) {
    if (og_is_group_type('node', $type) && ($perms = og_list_permissions($type))) {
      foreach (array_keys($perms) as $perm_name) {

        // Group permission should onyl use the global field.
        if ($type == 'oa_group') {
          unset($permissions[$perm_name]);
        }
        elseif (!empty($permissions[$perm_name])) {
          $permissions[$perm_name]['restrict access'] = TRUE;
          $permissions[$perm_name]['default role'] = array(
            OG_ADMINISTRATOR_ROLE,
          );
          $permissions[$perm_name]['roles'] = array(
            OG_AUTHENTICATED_ROLE,
          );
        }
      }
    }
  }
}

/**
 * Implements hook_oa_core_og_content_needs_rebuild().
 */
function oa_subspaces_oa_core_og_content_needs_rebuild($node) {
  return isset($node->{OG_USER_INHERITANCE_FIELD}[LANGUAGE_NONE][0]['value']) && isset($node->original->{OG_USER_INHERITANCE_FIELD}[LANGUAGE_NONE][0]['value']) && $node->{OG_USER_INHERITANCE_FIELD}[LANGUAGE_NONE][0]['value'] != $node->original->{OG_USER_INHERITANCE_FIELD}[LANGUAGE_NONE][0]['value'];
}

Functions

Namesort descending Description
oa_subspaces_field_access Implements hook_field_access().
oa_subspaces_form_node_form_alter Implements hook_form_alter(). Hook into the Node Edit form
oa_subspaces_form_node_form_validate Validation function for node edit form
oa_subspaces_form_views_content_views_panes_content_type_edit_form_alter Implements hook_form_FORM_ID_alter().
oa_subspaces_form_views_exposed_form_alter Implements hook_form_FORM_ID_alter().
oa_subspaces_get_children_groups Return children of Space, regardless of the inheritance field. DEPRECATED: Use oa_core_get_groups_by_parent() instead.
oa_subspaces_get_parent_groups Return parents of a Space, regardless of the inheritance field. DEPRECATED: Use oa_core_get_parents() instead.
oa_subspaces_matching_sections Return an array of section ids with the same Name as $section_id
oa_subspaces_oa_clear_cache Implements hook_oa_clear_cache
oa_subspaces_oa_core_og_content_needs_rebuild Implements hook_oa_core_og_content_needs_rebuild().
oa_subspaces_og_permission_alter Implements hook_og_permission_alter().
oa_subspaces_views_pre_view Implements hook_views_pre_view().
oa_subspaces_views_query_alter Implements hook_views_query_alter().
_oa_subspaces_add_checkbox Helper to add a checkbox to the exposed filter
_oa_subspaces_add_element_all Helper to add the 'Show subspace content' checkbox at same place as group ref.
_oa_subspaces_add_element_parent Helper to add the 'Show parent content' checkbox at same place as group ref.
_oa_subspaces_build_options Helper to convert a hierarchical array back to a flat list with -- in titles
_oa_subspaces_find_view_settings Finding the active current configuration for each is a pane in the ***.

Constants

Namesort descending Description
OA_PARENT_SPACE Name of default Parent Space field.
OA_SUBSPACES_CACHE_CHILDREN Name of caches.
OA_SUBSPACES_CACHE_PARENTS