1

I'm using the Drupal Group module and I've added content to a Drupal group I've created. I've also added users to this Group.

Works well: Drupal users have to login to see this content in that group.

Now I'm looking at User Experience (UX) improvements: If a non-logged in user visits a URL for a node that belongs to a group, then I'd like to redirect them to the login page and then redirect them back to that page.

I know how to do the 2 redirects ( How to redirect a user after login in Drupal the proper way - I got this working for something else ). But I don't know how to get the group(s) that a node belongs to. Is there a standard call? on the Node object or via another object I can get hold of?

So far I found this: Find out to which group the entity belongs to by route. It's a code fragment for a class. I added in the constructor with params that correspond to the said services and member variables.

It runs, but doesn't work: calling $group = \Drupal::service('mysite_custom_module.current_group')->getGroupFromRoute(); returns $group as null

My code I've written based on: Find out to which group the entity belongs to by route

(Note - by me posting this code example here below doesn't mean I'm fixated on getting this particular approach to work. I would surely be very happy with any solution that answers my main question: "How to get the Drupal Group that the node belongs to / redirect anonymous to login page if they land on node belonging to group" )

web/modules/custom/mysite_custom_module/mysite_custom_module.services.yml

services:
  mysite_custom_module.current_group:
    class: Drupal\mysite_custom_module\CurrentGroup
    arguments: ['@current_route_match', '@entity_type.manager']

web/modules/custom/mysite_custom_module/mysite_custom_module.module

/** 
 * https://www.thesavvyfew.com/insights/how-redirect-user-after-login-drupal-proper-way
 *
 * Implements hook_form_FORM_ID_alter().
 */
function mysite_custom_module_module_form_user_login_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $form['#submit'][] = 'mysite_custom_module_module_user_login_form_submit';
}
/**
 * Custom submit handler for the login form.
 */
function mysite_custom_module_module_user_login_form_submit($form, FormStateInterface $form_state) {
  $originalUrlAsString = \Drupal::request()->get('return');

  $urlAsObject = Url::fromUserInput($originalUrlAsString);
  $form_state->setRedirectUrl($urlAsObject);
}



    function mysite_custom_module_module_preprocess_page(&$variables) {
      $group = \Drupal::service('mysite_custom_module_module.current_group')->getGroupFromRoute();
    
      if ( $group ) {
        if (!( \Drupal::currentUser()->isAuthenticated() ) ) {
          $originalUrl = \Drupal::service('path.current')->getPath();
          $loginWithOriginalUrl = "/user/login?return=".$originalUrl;
          //$response = new RedirectResponse(Url::fromUserInput($loginWithOriginalUrl)->toString());
          $response = new RedirectResponse($loginWithOriginalUrl);
          $response->send();
        }
      }
    }

web/modules/custom/mysite_custom_modue/src/CurrentGroup.php:

<?php

namespace Drupal\mysite_module;

// https://www.drupal.org/docs/8/modules/group-media/find-out-to-which-group-the-entity-belongs-to-by-route

class CurrentGroup {

  private $routeMatch;
  private $entityTypeManager;

  // see mysite_module/mysite_module.services.yml
  public function __construct( $current_route_match, $entity_type_manager ) {
   $this->routeMatch = $current_route_match;
   $this->entityTypeManager = $entity_type_manager;
  }


/**
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *
   * @return bool|\Drupal\group\Entity\GroupInterface
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   */
  public function getGroupByEntity(EntityInterface $entity) {
    $group = FALSE;
    if ($entity instanceof GroupInterface) {
      return $entity;
    }
    $entity_type = $entity->getEntityTypeId();
    $group_content_type = 'membership_group_type-group_' . $entity_type . '-' . $entity->bundle();
    // Load all the group content for this entity.
    /** @var \Drupal\group\Entity\GroupContent $group_content */
    $group_content = $this->entityTypeManager->getStorage('group_content')
      ->loadByProperties([
        'type' => $group_content_type,
        'entity_id' => $entity->id(),
      ]);
    // Assuming that the content can be related only to 1 group.
    $group_content = reset($group_content);
    if (!empty($group_content)) {
      $group = $group_content->getGroup();
    }
    return $group;
  }

  /**
   * Get the group from the current route match.
   *
   * @return bool|\Drupal\group\Entity\GroupInterface
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   */
  public function getGroupFromRoute() {
    $entity = FALSE;
    $parameters = $this->routeMatch->getParameters()->all();
    if (!empty($parameters['group']) && is_numeric($parameters['group'])) {
      $group = Group::load($parameters['group']);
      return $group;
    }
    if (!empty($parameters)) {
      foreach ($parameters as $parameter) {
        if ($parameter instanceof EntityInterface) {
          $entity = $parameter;
          break;
        }
      }
    }
    if ($entity) {
      return $this->getGroupByEntity($entity);
    }
    return FALSE;
  }
}
5
0

Service name mismatch: in your module file mysite_custom_module.module you are calling your service with \Drupal::service('mysite_custom_module_module.current_group'); but in mysite_custom_module.services.yml you define it as mysite_custom_module.current_group

Also, are you sure your Route does define parameters? Can you show the route definition code?

10
  • I think that was a search replace typo. I did the replace to keep the customer's name in confidence. I'll check it though. Mar 19 at 9:31
  • if by route you mean what's defined here: web/modules/custom/mysite_custom_module/mysite_custom_module.services.yml then yes - see the code for this in my question above - there are 2 parameters - arguments: ['@current_route_match', '@entity_type.manager'] which are subsequently passed to the constructor __construct for CurrentGroup - again see above. Mar 19 at 9:36
  • I mean the content of your *.routing.yml if you use any. Otherwise, what's the URL for the page of interest? maybe that's helpful
    – theuni
    Mar 19 at 9:39
  • Do I need routing in this situation? The particular solution I had tried Find out to which group the entity belongs to by route doesn't specify a route. Also, it's one solution I've found so far. I don't necessarily have to use it - if we consider the main question: "How to get the Drupal Group that the node belongs to / redirect anonymous to login page if they land on node belonging to group" - I would be happy with any answer to this, not just the specific code example I've given Mar 19 at 9:45
  • 1
    Nevermind, since you are not using a *.routing.yml you are not using a custom route (and you don't necessarily need one) but probably a route from core or the group module itself (that's why I am asking about the URL). I don't see any striking problems with the approach you posted but without further information it's hard to say what's wrong
    – theuni
    Mar 19 at 10:04
0

Answering my own question:

How do I get group to which the node belongs

Install: Entity Group Field which is an add-on / companion module for use with the Drupal Group module.

Which provides an additional field (a 'computed' field) which automatically takes its value which is the Drupal Group that the content 'belongs' to. If the content doesn't belong to any group, then the field is not set.

The field is setable when editing or creating the content.

In terms of configuring the content type, the field only shows in the Manage Form Display section, so that you can position it for when editing the content.

Entity Group Field was discovered here: Group | Contributed Modules - see this page for other modules that extend Group functionality.

and redirect anonymous users to the login page if they land on it?

A simple 'blanket' approach to this is to change the access denied URL to /user/login in the settings in admin/config/system/site-information, see under 'Default 403 (access denied) page'. (Credit to my colleague Dylan for his thought that in most cases redirect to login ought to be OK, instead of Access Denied)

I've now implemented the above 2 steps and am finding them to work, from testing so far.

A further step I've not tried is to try to get the access denied redirect to work only for Group-only content, by programmatically getting the aforementioned above computed field value, if it is available from the Node object.

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.