Update the docs about medialibrary to be compatible with groups v2 and v3

Created on 31 January 2024, 10 months ago
Updated 8 February 2024, 9 months ago

Problem/Motivation

The docs in https://www.drupal.org/docs/contributed-modules/group-media/using-group-... is using the group v1 groupcontent, so it needs to be updated to reflect the groupRelationship instead.
Also I refactored a little bit to allow:
- Detection of multiple groups per node.
- Detect node from medialibrary "media_library_opener_parameters" exposed input property, so it makes it work whenever picking table or grid medialibrary (If not it looses the group and/or the node from request).
- Use intersection of group plugins and media types rather than using exception.
- Let implementer choose if wants confined media or list public media too.


use Drupal\views\Plugin\views\query\QueryPluginBase;
use Drupal\views\ViewExecutable;
use Drupal\group\Entity\Group;
use Drupal\group\Entity\GroupRelationship;
use Drupal\node\Entity\Node;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;


/**
 * Implements hook_views_query_alter().
 */
function group_media_library_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  if ($view->id() == 'media_library') {
    // When media_library is being used to add
    // media to a node, we try to limit
    // the available media to only those that belong
    // to the group the node belongs to.
    // We have no way of knowing if media_library
    // is being used in this context, so we try
    // to get the group id from the current URL.
    $groups = [];
    $group = \Drupal::request()->attributes->get('group');
    if (empty($group) || !$group instanceof Group) {
      $node = \Drupal::request()->attributes->get('node');
      if (empty($node) && isset($view->getExposedInput()['media_library_opener_parameters']['entity_type_id'])) {
        if ($view->getExposedInput()['media_library_opener_parameters']['entity_type_id'] == 'node') {
          $exposed_nid = $view->getExposedInput()['media_library_opener_parameters']['entity_id'];
          $node = Node::load($exposed_nid);
        }
      }
      if (!empty($node) && $node instanceof Node) {
        foreach (GroupRelationship::loadByEntity($node) as $group_relationships) {
          // If it's linked to more than one then it will grab the group
          // entity->id of the last linked group only so push to groups array
          $group_id = $group_relationships->gid->entity->id();
          $groups[] = Group::load($group_id);
        }
      }
    } else {
      // add group from request to array to be as iterable as it was
      // a node with multiple relationships to multiple groups.
      $groups[] = $group;
    }

    if(!empty($groups)) {
      $media_ids = [];
      \Drupal::messenger()->addMessage(t('Adding new media with this dialog will grant access to this media for group members.'));
      foreach ($groups as $group) {
        if (!empty($group) && $group instanceof Group) {
          // Get all media types (bundles).
          $bundle_info = \Drupal::service('entity_type.bundle.info')->getBundleInfo('media');
          $bundle_info_plugin_prefixed = array_map(fn($media_bundle): string => "group_media:$media_bundle", array_keys($bundle_info));
          $installed_plugins = \Drupal::service('group_relation_type.manager')->getInstalled($group->getGroupType());
          // which media types/bundles are enabled as group relationship
          $media_plugins = array_intersect($bundle_info_plugin_prefixed,$installed_plugins->getInstanceIds());
          // Get group relationship for each media bundle.
          foreach ($media_plugins as $media_plugin) {
            try {
              $group_relationships = $group->getRelationships($media_plugin);
            } catch (PluginNotFoundException $exception) {
              continue;
            }

            if (!empty($group_relationships)) {
              // Get id of each media.
              foreach ($group_relationships as $group_relationship) {
                $media_ids[] = $group_relationship->get('entity_id')->getValue()[0]['target_id'];
              }
            }
          }
        }
      }
      // Restrict media to only those in group.
      // if needs to list only media of this group or public media.
      // Comment next if block if you want to list public media too.
      if(empty($media_ids)) {
        $media_ids[] = -1;
      }
      if (!empty($media_ids)) {
        $media_relationship_data = $query->setWhereGroup('AND');
        $query->addWhere($media_relationship_data, 'media_field_data.mid', $media_ids, 'IN');
      }
    }
  }
}

📌 Task
Status

Needs review

Version

4.0

Component

Code

Created by

🇪🇸Spain aleix

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @aleix
  • 🇪🇸Spain aleix

    Note that media library checks itself in Drupal\media_library\MediaLibraryUiBuilder::checkAccess that user has 'view media' permission and also that has createAccess of bundle that has opened the media library.
    So, despite the aparently fine forbid of "Create article content" in /admin/people/permissions and allow of "Entity: Add element article entities" in /admin/group/types/manage/GROUPTYPE/permissions, esults in allowing the content creation,
    the medialibrary accesshandler check will forbid adding media.

    So both general and group permissions must be given.

  • 🇧🇪Belgium msnassar

    Hello @aleix did you have a look into Group media library extra module. It comes with pluggable solution for changing the behavior of the media library view when it is being opened from a group context.
    The module depends on Group media library which solves other issues when using media library with groups. Including 🐛 Incorrect Access Check on Media Library RTBC

  • 🇪🇸Spain aleix

    Thank's @msnassar , Yes! looks promising, nice work! kudos for your contribution. (btw are you planning to request merging it with group media?)

    For my use case, I need a basic functionality of media library by now, but I think that if a project requires something more powerful, it will require the use of your modules ( Or going to entity browser).

    But anyway, the docs of this module also needs to be there and matching the use case of nowadays group module requirements.

    Again, thank's for spending all the time coding there!

  • 🇧🇪Belgium msnassar

    @aleix There is no plan to add the modules mentioned in #5 to group media. This is because, they can be used without the group media module. Both has submodules to integrate with group media.

Production build 0.71.5 2024