From dc8733b46c734052e87148d25d62516b5f3e1c40 Mon Sep 17 00:00:00 2001
From: Haritha C <harithachandrasekaran16@gmail.com>
Date: Sun, 16 Mar 2025 14:22:50 +0530
Subject: [PATCH 1/5] Fixed the field entity ui issues

---
 .../OperationProvider.php                     | 74 ++++++++++++-------
 1 file changed, 47 insertions(+), 27 deletions(-)

diff --git a/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php b/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
index 6d9c66d2..d9dca4f8 100644
--- a/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
+++ b/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
@@ -57,40 +57,60 @@ class OperationProvider implements OperationProviderInterface {
 
     $ui_allowed = !$this->groupRelationType->isEnforced() && !$this->groupRelationType->isCodeOnly();
     if ($relationship_type_id = $this->getRelationshipTypeId($group_type)) {
-      $route_params = ['group_relationship_type' => $relationship_type_id];
-      $operations['configure'] = [
-        'title' => $this->t('Configure'),
-        'url' => new Url('entity.group_relationship_type.edit_form', $route_params),
-      ];
-
-      if ($ui_allowed) {
-        $operations['uninstall'] = [
-          'title' => $this->t('Uninstall'),
-          'weight' => 99,
-          'url' => new Url('entity.group_relationship_type.delete_form', $route_params),
+        $route_params = ['group_relationship_type' => $relationship_type_id];
+        $operations['configure'] = [
+            'title' => $this->t('Configure'),
+            'url' => new Url('entity.group_relationship_type.edit_form', $route_params),
         ];
-      }
 
-      // This could be in its own decorator, but then it would live in a module
-      // of its own purely for field_ui support. So let's keep it here.
-      if ($this->moduleHandler->moduleExists('field_ui')) {
-        $relationship_type = $this->entityTypeManager()->getStorage('group_relationship_type')->load($relationship_type_id);
-        $operations += field_ui_entity_operation($relationship_type);
-      }
-    }
+        if ($ui_allowed) {
+            $operations['uninstall'] = [
+                'title' => $this->t('Uninstall'),
+                'weight' => 99,
+                'url' => new Url('entity.group_relationship_type.delete_form', $route_params),
+            ];
+        }
+
+        // Use a safer alternative to field_ui_entity_operation()
+        if ($this->moduleHandler->moduleExists('field_ui')) {
+            $relationship_type = $this->entityTypeManager()->getStorage('group_relationship_type')->load($relationship_type_id);
+            if ($relationship_type) {
+                $operations += $this->getEntityOperations($relationship_type);
+            }
+        }
+    } 
     elseif ($ui_allowed) {
-      $operations['install'] = [
-        'title' => $this->t('Install'),
-        'url' => new Url('entity.group_relationship_type.add_form', [
-          'group_type' => $group_type->id(),
-          'plugin_id' => $this->pluginId,
-        ]),
-      ];
+        $operations['install'] = [
+            'title' => $this->t('Install'),
+            'url' => new Url('entity.group_relationship_type.add_form', [
+                'group_type' => $group_type->id(),
+                'plugin_id' => $this->pluginId,
+            ]),
+        ];
     }
 
     return $operations;
-  }
+}
 
+/**
+ * Provides entity operation links, replacing field_ui_entity_operation().
+ */
+protected function getEntityOperations($entity) {
+    $operations = [];
+    if ($entity->hasLinkTemplate('edit-form')) {
+        $operations['edit'] = [
+            'title' => $this->t('Edit'),
+            'url' => $entity->toUrl('edit-form'),
+        ];
+    }
+    if ($entity->hasLinkTemplate('delete-form')) {
+        $operations['delete'] = [
+            'title' => $this->t('Delete'),
+            'url' => $entity->toUrl('delete-form'),
+        ];
+    }
+    return $operations;
+}
   /**
    * {@inheritdoc}
    */
-- 
GitLab


From b5d052005da3292bdb90c9a1872e8f84737ea22c Mon Sep 17 00:00:00 2001
From: Haritha C <harithachandrasekaran16@gmail.com>
Date: Sun, 16 Mar 2025 15:49:39 +0530
Subject: [PATCH 2/5] updated test case issue

---
 tests/src/Functional/EntityOperationsTest.php | 52 ++++++++++++-------
 1 file changed, 33 insertions(+), 19 deletions(-)

diff --git a/tests/src/Functional/EntityOperationsTest.php b/tests/src/Functional/EntityOperationsTest.php
index ce73834a..6028ee7b 100644
--- a/tests/src/Functional/EntityOperationsTest.php
+++ b/tests/src/Functional/EntityOperationsTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\group\Functional;
 
+use Drupal\group\Entity\GroupRole;
 use Drupal\group\PermissionScopeInterface;
 use Drupal\user\RoleInterface;
 
@@ -37,28 +38,41 @@ class EntityOperationsTest extends GroupBrowserTestBase {
    * @dataProvider provideEntityOperationScenarios
    */
   public function testEntityOperations($visible, $invisible, $permissions = [], $modules = []) {
-    $group = $this->createGroup(['type' => $this->createGroupType()->id()]);
+    $group_type = $this->createGroupType();
+    $group = $this->createGroup(['type' => $group_type->id()]);
 
+    // Assign permissions if provided.
     if (!empty($permissions)) {
-      $this->createGroupRole([
+      $role = GroupRole::create([
         'group_type' => $group->bundle(),
-        'scope' => PermissionScopeInterface::INSIDER_ID,
-        'global_role' => RoleInterface::AUTHENTICATED_ID,
+        'id' => 'custom-role',
+        'label' => 'Custom Role',
         'permissions' => $permissions,
       ]);
+      $role->save();
     }
 
+    // Install required modules.
     if (!empty($modules)) {
-      $this->container->get('module_installer')->install($modules, TRUE);
+      $module_handler = \Drupal::service('module_handler');
+      $module_installer = \Drupal::service('module_installer');
+      foreach ($modules as $module) {
+        if (!$module_handler->moduleExists($module)) {
+          $module_installer->install([$module], TRUE);
+        }
+      }
     }
 
-    $this->drupalGet('admin/group');
+    // Navigate to the group administration page.
+    $this->drupalGet('/admin/structure/group');
 
+    // Verify visible links.
     foreach ($visible as $path => $label) {
       $this->assertSession()->linkExists($label);
       $this->assertSession()->linkByHrefExists($path);
     }
 
+    // Verify invisible links.
     foreach ($invisible as $path => $label) {
       $this->assertSession()->linkNotExists($label);
       $this->assertSession()->linkByHrefNotExists($path);
@@ -72,21 +86,21 @@ class EntityOperationsTest extends GroupBrowserTestBase {
     $scenarios['withoutAccess'] = [
       [],
       [
-        'group/1/edit' => 'Edit',
-        'group/1/members' => 'Members',
-        'group/1/delete' => 'Delete',
-        'group/1/revisions' => 'Revisions',
+        '/group/1/edit' => 'Edit',
+        '/group/1/members' => 'Members',
+        '/group/1/delete' => 'Delete',
+        '/group/1/revisions' => 'Revisions',
       ],
     ];
 
     $scenarios['withAccess'] = [
       [
-        'group/1/edit' => 'Edit',
-        'group/1/delete' => 'Delete',
-        'group/1/revisions' => 'Revisions',
+        '/group/1/edit' => 'Edit',
+        '/group/1/delete' => 'Delete',
+        '/group/1/revisions' => 'Revisions',
       ],
       [
-        'group/1/members' => 'Members',
+        '/group/1/members' => 'Members',
       ],
       [
         'view group',
@@ -99,10 +113,10 @@ class EntityOperationsTest extends GroupBrowserTestBase {
 
     $scenarios['withAccessAndViews'] = [
       [
-        'group/1/edit' => 'Edit',
-        'group/1/members' => 'Members',
-        'group/1/delete' => 'Delete',
-        'group/1/revisions' => 'Revisions',
+        '/group/1/edit' => 'Edit',
+        '/group/1/members' => 'Members',
+        '/group/1/delete' => 'Delete',
+        '/group/1/revisions' => 'Revisions',
       ],
       [],
       [
@@ -117,5 +131,5 @@ class EntityOperationsTest extends GroupBrowserTestBase {
 
     return $scenarios;
   }
-
+  
 }
-- 
GitLab


From dd304d08eb7312c426b706e21c55b9f0788869ae Mon Sep 17 00:00:00 2001
From: Haritha C <harithachandrasekaran16@gmail.com>
Date: Tue, 18 Mar 2025 08:39:44 +0530
Subject: [PATCH 3/5] updated php unit test issues

---
 .../OperationProvider.php                     | 25 ++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php b/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
index d9dca4f8..76d8431f 100644
--- a/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
+++ b/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
@@ -12,6 +12,7 @@ use Drupal\group\Entity\GroupTypeInterface;
 use Drupal\group\Plugin\Group\Relation\GroupRelationTypeManagerInterface;
 use Drupal\group\Plugin\Group\RelationHandler\OperationProviderInterface;
 use Drupal\group\Plugin\Group\RelationHandler\OperationProviderTrait;
+use Drupal\Core\Entity\EntityInterface;
 
 /**
  * Provides operations for group relations.
@@ -75,7 +76,7 @@ class OperationProvider implements OperationProviderInterface {
         if ($this->moduleHandler->moduleExists('field_ui')) {
             $relationship_type = $this->entityTypeManager()->getStorage('group_relationship_type')->load($relationship_type_id);
             if ($relationship_type) {
-                $operations += $this->getEntityOperations($relationship_type);
+           $operations += $this->getFieldUiOperations($relationship_type);
             }
         }
     } 
@@ -92,6 +93,28 @@ class OperationProvider implements OperationProviderInterface {
     return $operations;
 }
 
+/**
+ * Generates Field UI operations.
+ */
+protected function getFieldUiOperations(EntityInterface $entity): array {
+  $operations = [];
+  $entity_type_id = $entity->getEntityTypeId();
+
+  // Ensure we only add Field UI operations for entities that support it.
+  if (in_array($entity_type_id, ['node', 'taxonomy_term', 'user', 'group'])) {
+      $route_name = "entity.{$entity_type_id}.field_ui_fields";
+
+      if ($this->currentUser->hasPermission('administer ' . $entity_type_id . ' fields')) {
+          $operations['manage_fields'] = [
+              'title' => $this->t('Manage fields'),
+              'url' => Url::fromRoute($route_name, [$entity_type_id => $entity->id()]),
+          ];
+      }
+  }
+
+  return $operations;
+}
+
 /**
  * Provides entity operation links, replacing field_ui_entity_operation().
  */
-- 
GitLab


From 36748141706f7b4d0983cc16ad2d5b954a50a0d9 Mon Sep 17 00:00:00 2001
From: Sander Wind <sander@alserdamedia.nl>
Date: Fri, 21 Mar 2025 10:46:47 +0100
Subject: [PATCH 4/5] Use FieldUiHooks::entityOperation() to keep it DRY

---
 .../OperationProvider.php                     | 95 ++++++-------------
 1 file changed, 27 insertions(+), 68 deletions(-)

diff --git a/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php b/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
index 76d8431f..b2362c05 100644
--- a/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
+++ b/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
@@ -7,12 +7,12 @@ use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Session\AccountProxyInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\Core\Url;
+use Drupal\field_ui\Hook\FieldUiHooks;
 use Drupal\group\Entity\GroupInterface;
 use Drupal\group\Entity\GroupTypeInterface;
 use Drupal\group\Plugin\Group\Relation\GroupRelationTypeManagerInterface;
 use Drupal\group\Plugin\Group\RelationHandler\OperationProviderInterface;
 use Drupal\group\Plugin\Group\RelationHandler\OperationProviderTrait;
-use Drupal\Core\Entity\EntityInterface;
 
 /**
  * Provides operations for group relations.
@@ -58,82 +58,41 @@ class OperationProvider implements OperationProviderInterface {
 
     $ui_allowed = !$this->groupRelationType->isEnforced() && !$this->groupRelationType->isCodeOnly();
     if ($relationship_type_id = $this->getRelationshipTypeId($group_type)) {
-        $route_params = ['group_relationship_type' => $relationship_type_id];
-        $operations['configure'] = [
-            'title' => $this->t('Configure'),
-            'url' => new Url('entity.group_relationship_type.edit_form', $route_params),
-        ];
+      $route_params = ['group_relationship_type' => $relationship_type_id];
+      $operations['configure'] = [
+        'title' => $this->t('Configure'),
+        'url' => new Url('entity.group_relationship_type.edit_form', $route_params),
+      ];
 
-        if ($ui_allowed) {
-            $operations['uninstall'] = [
-                'title' => $this->t('Uninstall'),
-                'weight' => 99,
-                'url' => new Url('entity.group_relationship_type.delete_form', $route_params),
-            ];
-        }
+      if ($ui_allowed) {
+        $operations['uninstall'] = [
+          'title' => $this->t('Uninstall'),
+          'weight' => 99,
+          'url' => new Url('entity.group_relationship_type.delete_form', $route_params),
+        ];
+      }
 
-        // Use a safer alternative to field_ui_entity_operation()
-        if ($this->moduleHandler->moduleExists('field_ui')) {
-            $relationship_type = $this->entityTypeManager()->getStorage('group_relationship_type')->load($relationship_type_id);
-            if ($relationship_type) {
-           $operations += $this->getFieldUiOperations($relationship_type);
-            }
+      // Use a safer alternative to field_ui_entity_operation()
+      if ($this->moduleHandler->moduleExists('field_ui')) {
+        $relationship_type = $this->entityTypeManager()->getStorage('group_relationship_type')->load($relationship_type_id);
+        if ($relationship_type) {
+          $operations += new FieldUiHooks()->entityOperation($relationship_type);
         }
-    } 
+      }
+    }
     elseif ($ui_allowed) {
-        $operations['install'] = [
-            'title' => $this->t('Install'),
-            'url' => new Url('entity.group_relationship_type.add_form', [
-                'group_type' => $group_type->id(),
-                'plugin_id' => $this->pluginId,
-            ]),
-        ];
+      $operations['install'] = [
+        'title' => $this->t('Install'),
+        'url' => new Url('entity.group_relationship_type.add_form', [
+          'group_type' => $group_type->id(),
+          'plugin_id' => $this->pluginId,
+        ]),
+      ];
     }
 
     return $operations;
-}
-
-/**
- * Generates Field UI operations.
- */
-protected function getFieldUiOperations(EntityInterface $entity): array {
-  $operations = [];
-  $entity_type_id = $entity->getEntityTypeId();
-
-  // Ensure we only add Field UI operations for entities that support it.
-  if (in_array($entity_type_id, ['node', 'taxonomy_term', 'user', 'group'])) {
-      $route_name = "entity.{$entity_type_id}.field_ui_fields";
-
-      if ($this->currentUser->hasPermission('administer ' . $entity_type_id . ' fields')) {
-          $operations['manage_fields'] = [
-              'title' => $this->t('Manage fields'),
-              'url' => Url::fromRoute($route_name, [$entity_type_id => $entity->id()]),
-          ];
-      }
   }
 
-  return $operations;
-}
-
-/**
- * Provides entity operation links, replacing field_ui_entity_operation().
- */
-protected function getEntityOperations($entity) {
-    $operations = [];
-    if ($entity->hasLinkTemplate('edit-form')) {
-        $operations['edit'] = [
-            'title' => $this->t('Edit'),
-            'url' => $entity->toUrl('edit-form'),
-        ];
-    }
-    if ($entity->hasLinkTemplate('delete-form')) {
-        $operations['delete'] = [
-            'title' => $this->t('Delete'),
-            'url' => $entity->toUrl('delete-form'),
-        ];
-    }
-    return $operations;
-}
   /**
    * {@inheritdoc}
    */
-- 
GitLab


From cda033eae8c028d8a4fb44a5f3abf29b6dcdedc4 Mon Sep 17 00:00:00 2001
From: Sander Wind <sander@alserdamedia.nl>
Date: Fri, 21 Mar 2025 11:16:37 +0100
Subject: [PATCH 5/5] Determine the correct Field UI entity operation method

---
 .../Group/RelationHandlerDefault/OperationProvider.php   | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php b/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
index b2362c05..5de37c9b 100644
--- a/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
+++ b/src/Plugin/Group/RelationHandlerDefault/OperationProvider.php
@@ -76,7 +76,14 @@ class OperationProvider implements OperationProviderInterface {
       if ($this->moduleHandler->moduleExists('field_ui')) {
         $relationship_type = $this->entityTypeManager()->getStorage('group_relationship_type')->load($relationship_type_id);
         if ($relationship_type) {
-          $operations += new FieldUiHooks()->entityOperation($relationship_type);
+          // Try using the right method for adding the Field UI entity operations.
+          $operations += match (TRUE) {
+            // Drupal version >= 11.1.x.
+            method_exists(FieldUiHooks::class, 'entityOperation') => (new FieldUiHooks())->entityOperation($relationship_type),
+            // Drupal version < 11.1.x.
+            function_exists('field_ui_entity_operation') => field_ui_entity_operation($relationship_type),
+            default => [],
+          };
         }
       }
     }
-- 
GitLab