-1

The Gist:

Is it possible (and advisable) to use Organic Groups memberships to control access to Entityforms?

Explanation:

I use OG groups for content access on an institutional site. All users have OG memberships that reflect the institutional department(s) they belong to. Nodes, views, and taxonomy terms all have fields (OG Audience) specifying which groups can view them.

For example, Admissions Office employees can access any content marked as accessible to the 'Admissions Office' OG group. Students can likewise access any content marked as accessible to the 'Students' OG group, etc.

Then comes Entity Forms. I'd love to have the same OG association for them, but as far as I can tell, this isn't supported (don't know if that's an OG or an Entity Form thing).

For an example of this, I have an "Academic Alert" eform type that only members of the 'Faculty' OG group should have access to/be able to submit. The group already exists, but how do I connect my eform types to my groups? Is that possible?

Ideas I've Toyed With:

  1. Rules - I know I should theoretically be able to create an eform access rule that hides the form from users without a certain group membership. This is less appealing because it means I have to create a Rule for every group that needs exclusive access to an eform--and then I have to manage a long list of groups and a long list of access rules. Additionally, the access rule simply hides the eform body, so links to the eforms still show up in menus for users that can't actually submit them.

  2. Custom module - I'm thinking of writing a module that allows me to specify an OG Audience for each entityform type (I'll somehow have to store a mapping, perhaps in a field or variable). Then I'll have to write custom access checks to compare the current user's OG memberships to the groups that "own" the entityform type being created. Someone please save my life and tell me there's a better solution than this. :)

Any thoughts, insights, clues, or direction would be very appreciated. Thanks!

2

I wrote a small custom module called og_entityforms that uses the Chain Menu Access API.

The basics:

  1. Use hook_menu_alter() to chain a custom access callback to whatever eform pages you want to restrict. The result of the custom access callback is AND-ed with the result of the original callback to determine the access permission.

  2. In the custom access callback og_entityforms_entityform_access() do your custom checking. I simply check to see if the user is a member of any of the groups that I want to have access to the eform.

    • If it interests you, I also implement hook_form_alter() and add a 'Group Visibility' field to the entityform_type_form. That field is a multi-select list of groups. When the form is submitted, those groups are stored in a variable, and that variable is what I use in my access checks to tell which groups should have access to the eform.

The code:

/**
 * Implements hook_menu_alter().
 */
function og_entityforms_menu_alter(&$items) {
  $mappings = array(
    'og_entityforms_entityform_access' => array(
      'eform/submit/%entityform_empty',
      'eform/%entityform_type/confirm',
      'entityform/%entityform',
      'entityform/%entityform/edit',
      'entityform/%entityform/view',
    ),
    // 'og_entityforms_submissions_access' => array(
    //   'eform/%entityform_type/submissions',  
    //  ),
  );
  foreach($mappings as $access_callback=>$paths) {
    foreach($paths as $path) {
      if (isset($items[$path]['access callback'])) {
        $args = isset($items[$path]['access arguments'])? $items[$path]['access arguments'] : array();
        chain_menu_access_chain($items, $path, $access_callback, $args, FALSE);
      }
    }
  }
}

/**
 * Access callback for entityforms.
 * 
 * The result of this function gets ANDed with the result of entityform_access()
 * to make the final access permission.
 *
 * @param $op
 *   The operation being performed. One of 'view', 'update', 'create', 'delete'
 *   or just 'edit' (being the same as 'create' or 'update').
 * @param $entityform
 *   Optionally a entityform or a entityform type to check access for. If nothing is
 *   given, access for all entityforms is determined.
 * @param $account
 *   The user to check for. Leave it to NULL to check for the global user.
 * 
 * @return boolean
 *   Whether access is allowed or not.
 * 
 * @see og_entityforms_entity_info_alter()
 * @see entityform_entity_info()
 */
function og_entityforms_entityform_access($op, $entityform = NULL, $account = NULL) {
  $type = is_object($entityform)? $entityform->type : $entityform;

  // Get entityform access groups.
  $access_groups = variable_get(_og_entityforms_variable($type), array());
  if (empty($access_groups)) {
    return TRUE;
  }

  // Get user (do not restrict user 1).
  if (is_null($account)) {
    global $user;
    $account = $user;
    if ($account->uid === 1 || user_access('administer group', $account)) return TRUE;
  }

  // See if the user is a member of any access groups.
  $has_group_access = FALSE;
  $user_groups = og_get_entity_groups('user', $account);
  foreach($access_groups as $gid) {
    if (array_search($gid, $user_groups['node']) !== FALSE) {
      $has_group_access = TRUE;
      break;
    }
  }

  return $has_group_access;
}

/**
 * Implements hook_form_alter().
 */
function og_entityforms_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id === 'entityform_type_form') {
    $eform_type = $form['type']['#default_value'];

    $options = array();
    foreach(og_get_all_group() as $gid) {
      $group = node_load($gid);
      $options[$gid] =  $group->title;
    }

    $form['data']['access_set']['og_groups'] = array(
      '#title' => t('Group Visibility'),
      '#description' => t('The group(s) that should be able to view/submit eforms of this type. Optional, leave empty to skip restricting access by group membership.'),
      '#type' => 'select',
      '#options' => $options,
      '#default_value' => variable_get(_og_entityforms_variable($eform_type), NULL),
      '#multiple' => TRUE,
    );

    $form['#submit'][] = 'og_entityforms_set_entityform_type_groups';
    $form_state['og_entityforms']['original_name'] = $eform_type;
  }
}

/**
 * Save the organic groups that have access to an entityform type.
 */
function og_entityforms_set_entityform_type_groups(&$form, &$form_state) {
  $eform_type = $form_state['values']['type'];

  // Make sure to update variable names when the entityform types changes.
  if ($eform_type !== $form_state['og_entityforms']['original_name']) {
    variable_del(_og_entityforms_variable($form_state['og_entityforms']['original_name']));
  }

  // Set the groups variable for this entityform type.
  $var = _og_entityforms_variable($eform_type);
  if (isset($form_state['values']['data']['access_set']['og_groups']) && !empty($form_state['values']['data']['access_set']['og_groups'])) {
    variable_set($var, $form_state['values']['data']['access_set']['og_groups']);
  }
  // Remove the variable if the groups field is empty and previously had values.
  else if (variable_get($var, 'VAR_NOT_SET') != 'VAR_NOT_SET') {
    variable_del($var);
  }
}

/**
 * A simple helper function for generating og entityforms variable names.
 * 
 * @param string $eform_type
 *  Machine name of the entityform type to get groups variable for.
 * 
 * @return string
 *  The variable name (to be used in variable_get(), variable_set(), or
 * variable_del().
 */
function _og_entityforms_variable($eform_type) {
  return 'og_entityforms_' . $eform_type . '_groups';
}
2

had exactly the same problem. What I ended up doing is as follows:

1) create entityform, add your fields etc

2) create, of course, OG group and OG content type.

3) to your OG content type add entity ref field, referencing entityform type.

Now every time you create new node of that type you will be able to reference any of your created entityforms.

Very important - make sure that they can't access entityforms directly under

/eform/submit/

you can do something like

if (arg(0) == "eform" && arg(1) == "submit" && (not admin)) -> redirect

there are other things that you should look into as well

  • Ah, so the OC (did you mean OG?) content type you're referring to in step 2 is a wrapper content type (node bundle?) for entityforms, right? Then you can show its Entityform field as a rendered entity while handling access to the wrapper node like all other nodes. That's pretty brilliant. Any idea what the repercussions are for accessing submission? – joe_flash Apr 9 '13 at 17:06
  • sorry about "OC". Thats one of the many reasons I went with entityforms and not other module. Under "URL path settings" you can specify submit and confirm URL. I also use "redirect path" to my wrapper so everything stays there and intact! – sylwester Apr 9 '13 at 20:21
1

I wrote Entityforms and thought would let other know of some changes in Entityform 2.x that will make some of this easier.

First of all I have added hook_entityform_access alter see: http://drupal.org/node/1937526 So it should be able to connect access to an Organic Group.

Also I proposed a feature:

Reference only for Entityform Types

Add option to restrict submitting a particular Entityform Type to only work when it is used as Entity Reference. This would make it possible for Entityform Nodes module to restrict the viewing of the Entityform Type to only work when it is shown with the node(no direct url to the Entityform Type submit page).

See: http://drupal.org/node/1896712

I didn't much interest in that feature but I think it would solve the problem that @sly notes about being able to access the form direclty at eform/submit/*

I am thinking maybe a checkbox on Entityform Types for "Provide Submit Page" which would default to true.

If you have interest in making this feature happen comment on issues above.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.