From a1332bb41712ac236ad78cd356dc2cbc4ee7dc31 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Wed, 5 Dec 2018 10:04:22 +0100 Subject: [PATCH 001/111] Fix config import --- og.module | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/og.module b/og.module index d4bf89737..e9cb91f0b 100755 --- a/og.module +++ b/og.module @@ -379,7 +379,7 @@ function og_og_role_insert(OgRoleInterface $role) { } $add_id = 'og_membership_add_single_role_action.' . $role->getName(); - if (!Action::load($add_id)) { + if (!Action::load($add_id) && !\Drupal::isConfigSyncing()) { $action = Action::create([ 'id' => $add_id, 'type' => 'og_membership', @@ -392,7 +392,7 @@ function og_og_role_insert(OgRoleInterface $role) { $action->trustData()->save(); } $remove_id = 'og_membership_remove_single_role_action.' . $role->getName(); - if (!Action::load($remove_id)) { + if (!Action::load($remove_id) && !\Drupal::isConfigSyncing()) { $action = Action::create([ 'id' => $remove_id, 'type' => 'og_membership', From 45751449a8ac3e603b3691e3c3694572e89cee9c Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Tue, 11 Dec 2018 12:04:19 +0100 Subject: [PATCH 002/111] Update test matrix. - Disable deprecated versions of PHP and Drupal core. - Start testing on Drupal 8.7.x and PHP 7.3, but still allow failures. --- .travis.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index f121c28ab..60ff7dbe9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,30 +2,27 @@ language: php sudo: true php: - - 5.6 - - 7.0 - 7.1 - 7.2 + - 7.3 env: global: - COMPOSER_MEMORY_LIMIT=2G matrix: - - TEST_SUITE=8.5.x - TEST_SUITE=8.6.x + - TEST_SUITE=8.7.x - TEST_SUITE=PHP_CodeSniffer # Only run the coding standards check once. matrix: exclude: - - php: 5.6 - env: TEST_SUITE=PHP_CodeSniffer - - php: 7.0 - env: TEST_SUITE=PHP_CodeSniffer - php: 7.1 env: TEST_SUITE=PHP_CodeSniffer + - php: 7.2 + env: TEST_SUITE=PHP_CodeSniffer allow_failures: - - env: TEST_SUITE=8.6.x + - env: TEST_SUITE=8.7.x mysql: database: og From 47887293ed642a099f733ff9e7e935c4bd911842 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Tue, 11 Dec 2018 12:21:35 +0100 Subject: [PATCH 003/111] Replace drupal_set_message() with the Messenger service. --- src/Controller/SubscriptionController.php | 25 +++++++++++++------ src/Form/GroupSubscribeForm.php | 2 +- src/Form/GroupUnsubscribeConfirmForm.php | 2 +- tests/src/Unit/SubscriptionControllerTest.php | 24 ++++++++---------- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/Controller/SubscriptionController.php b/src/Controller/SubscriptionController.php index a320562d9..776bccb03 100644 --- a/src/Controller/SubscriptionController.php +++ b/src/Controller/SubscriptionController.php @@ -5,6 +5,7 @@ use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Url; use Drupal\og\OgAccessInterface; use Drupal\og\OgMembershipInterface; @@ -21,7 +22,6 @@ */ class SubscriptionController extends ControllerBase { - /** * OG access service. * @@ -29,14 +29,24 @@ class SubscriptionController extends ControllerBase { */ protected $ogAccess; + /** + * The messenger service. + * + * @var \Drupal\Core\Messenger\MessengerInterface + */ + protected $messenger; + /** * Constructs a SubscriptionController object. * * @param \Drupal\og\OgAccessInterface $og_access * The OG access service. + * @param \Drupal\Core\Messenger\MessengerInterface $messenger + * The messenger service. */ - public function __construct(OgAccessInterface $og_access) { + public function __construct(OgAccessInterface $og_access, MessengerInterface $messenger) { $this->ogAccess = $og_access; + $this->messenger = $messenger; } /** @@ -44,7 +54,8 @@ public function __construct(OgAccessInterface $og_access) { */ public static function create(ContainerInterface $container) { return new static( - $container->get('og.access') + $container->get('og.access'), + $container->get('messenger') ); } @@ -83,12 +94,12 @@ public function subscribe($entity_type_id, EntityInterface $group, OgMembershipT if ($this->config('user.settings')->get('register') === USER_REGISTER_ADMINISTRATORS_ONLY) { $params = [':login' => $user_login_url]; - drupal_set_message($this->t('In order to join any group, you must login. After you have successfully done so, you will need to request membership again.', $params)); + $this->messenger->addMessage($this->t('In order to join any group, you must login. After you have successfully done so, you will need to request membership again.', $params)); } else { $user_register_url = Url::fromRoute('user.register', [], $destination)->toString(); $params = [':register' => $user_register_url, ':login' => $user_login_url]; - drupal_set_message($this->t('In order to join any group, you must login or register a new account. After you have successfully done so, you will need to request membership again.', $params)); + $this->messenger->addMessage($this->t('In order to join any group, you must login or register a new account. After you have successfully done so, you will need to request membership again.', $params)); } return new RedirectResponse(Url::fromRoute('user.page')->setAbsolute(TRUE)->toString()); @@ -119,7 +130,7 @@ public function subscribe($entity_type_id, EntityInterface $group, OgMembershipT } if ($redirect) { - drupal_set_message($message, 'warning'); + $this->messenger->addMessage($message, 'warning'); return new RedirectResponse($group->toUrl()->setAbsolute(TRUE)->toString()); } @@ -164,7 +175,7 @@ public function unsubscribe(ContentEntityInterface $group) { if ($group instanceof EntityOwnerInterface && $group->getOwnerId() == $user->id()) { // The user is the manager of the group. - drupal_set_message($this->t('As the manager of %group, you can not leave the group.', ['%group' => $group->label()])); + $this->messenger->addMessage($this->t('As the manager of %group, you can not leave the group.', ['%group' => $group->label()])); return new RedirectResponse($group->toUrl() ->setAbsolute() diff --git a/src/Form/GroupSubscribeForm.php b/src/Form/GroupSubscribeForm.php index d77fc69a4..0ce927acc 100644 --- a/src/Form/GroupSubscribeForm.php +++ b/src/Form/GroupSubscribeForm.php @@ -235,7 +235,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $group = $membership->getGroup(); $message = $membership->isActive() ? $this->t('Your are now subscribed to the group.') : $this->t('Your subscription request was sent.'); - drupal_set_message($message); + $this->messenger()->addMessage($message); // User doesn't have access to the group entity, so redirect to front page, // otherwise back to the group entity. diff --git a/src/Form/GroupUnsubscribeConfirmForm.php b/src/Form/GroupUnsubscribeConfirmForm.php index 08f4fa0aa..8dd459bb1 100644 --- a/src/Form/GroupUnsubscribeConfirmForm.php +++ b/src/Form/GroupUnsubscribeConfirmForm.php @@ -62,7 +62,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $form_state->setRedirectUrl($redirect); $membership->delete(); - drupal_set_message($this->t('You have unsubscribed from the group.')); + $this->messenger()->addMessage($this->t('You have unsubscribed from the group.')); } } diff --git a/tests/src/Unit/SubscriptionControllerTest.php b/tests/src/Unit/SubscriptionControllerTest.php index db2e2e67f..0d3efe2d0 100644 --- a/tests/src/Unit/SubscriptionControllerTest.php +++ b/tests/src/Unit/SubscriptionControllerTest.php @@ -5,6 +5,7 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityFormBuilderInterface; +use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Url; use Drupal\og\Controller\SubscriptionController; @@ -50,6 +51,13 @@ class SubscriptionControllerTest extends UnitTestCase { */ protected $ogAccess; + /** + * The mocked messenger service. + * + * @var \Drupal\Core\Messenger\MessengerInterface|\Prophecy\Prophecy\ObjectProphecy + */ + protected $messenger; + /** * The OG membership entity. * @@ -79,6 +87,7 @@ public function setUp() { $this->group = $this->prophesize(ContentEntityInterface::class); $this->membershipManager = $this->prophesize(MembershipManagerInterface::class); $this->ogAccess = $this->prophesize(OgAccessInterface::class); + $this->messenger = $this->prophesize(MessengerInterface::class); $this->ogMembership = $this->prophesize(OgMembershipInterface::class); $this->url = $this->prophesize(Url::class); $this->user = $this->prophesize(AccountInterface::class); @@ -255,21 +264,8 @@ public function testGroupManager($state) { * Invoke the unsubscribe method. */ protected function unsubscribe() { - $controller = new SubscriptionController($this->ogAccess->reveal()); + $controller = new SubscriptionController($this->ogAccess->reveal(), $this->messenger->reveal()); $controller->unsubscribe($this->group->reveal()); } } - -// @todo Delete after https://www.drupal.org/node/1858196 is in. -namespace Drupal\og\Controller; - -if (!function_exists('drupal_set_message')) { - - /** - * Mocking for drupal_set_message(). - */ - function drupal_set_message() { - } - -} From 07df1f56a3e49240a5a7d36e797429a8e64d2557 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Tue, 11 Dec 2018 12:24:22 +0100 Subject: [PATCH 004/111] Declare minimum version compatibility for Drupal core. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 86b654504..22da708b0 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "source": "https://cgit.drupalcode.org/og" }, "require": { - "drupal/core": "~8.5" + "drupal/core": "~8.6" }, "require-dev": { "drupal/coder": "~8.2" From 5a4c2225cace54b4a9ebe21e44ba684a79d0da04 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Tue, 11 Dec 2018 15:57:52 +0100 Subject: [PATCH 005/111] Use cache api to store the group relation map --- src/GroupTypeManager.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/GroupTypeManager.php b/src/GroupTypeManager.php index adc596830..7ed4554ae 100644 --- a/src/GroupTypeManager.php +++ b/src/GroupTypeManager.php @@ -6,7 +6,7 @@ use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Routing\RouteBuilderInterface; -use Drupal\Core\State\StateInterface; +use Drupal\Core\Cache\CacheBackendInterface; use Drupal\og\Event\GroupCreationEvent; use Drupal\og\Event\GroupCreationEventInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -57,11 +57,11 @@ class GroupTypeManager implements GroupTypeManagerInterface { protected $eventDispatcher; /** - * The state service. + * The cache backend. * - * @var \Drupal\Core\State\StateInterface + * @var \Drupal\Core\Cache\CacheBackendInterface */ - protected $state; + protected $cache; /** * The OG permission manager. @@ -142,8 +142,8 @@ class GroupTypeManager implements GroupTypeManagerInterface { * The service providing information about bundles. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher * The event dispatcher. - * @param \Drupal\Core\State\StateInterface $state - * The state service. + * @param \Drupal\Core\Cache\CacheBackendInterface $cache + * The cache backend. * @param \Drupal\og\PermissionManagerInterface $permission_manager * The OG permission manager. * @param \Drupal\og\OgRoleManagerInterface $og_role_manager @@ -153,11 +153,11 @@ class GroupTypeManager implements GroupTypeManagerInterface { * @param \Drupal\og\OgGroupAudienceHelperInterface $group_audience_helper * The OG group audience helper. */ - public function __construct(ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, EventDispatcherInterface $event_dispatcher, StateInterface $state, PermissionManagerInterface $permission_manager, OgRoleManagerInterface $og_role_manager, RouteBuilderInterface $route_builder, OgGroupAudienceHelperInterface $group_audience_helper) { + public function __construct(ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, EventDispatcherInterface $event_dispatcher, CacheBackendInterface $cache, PermissionManagerInterface $permission_manager, OgRoleManagerInterface $og_role_manager, RouteBuilderInterface $route_builder, OgGroupAudienceHelperInterface $group_audience_helper) { $this->configFactory = $config_factory; $this->entityTypeBundleInfo = $entity_type_bundle_info; $this->eventDispatcher = $event_dispatcher; - $this->state = $state; + $this->cache = $cache; $this->permissionManager = $permission_manager; $this->ogRoleManager = $og_role_manager; $this->routeBuilder = $route_builder; @@ -331,7 +331,7 @@ public function resetGroupMap() { */ public function resetGroupRelationMap() { $this->groupRelationMap = []; - $this->state->delete(self::GROUP_RELATION_MAP_CACHE_KEY); + $this->cache->delete(self::GROUP_RELATION_MAP_CACHE_KEY); } /** @@ -370,7 +370,7 @@ protected function refreshGroupMap() { */ protected function refreshGroupRelationMap() { // Retrieve a cached version of the map if it exists. - if ($group_relation_map = $this->state->get(self::GROUP_RELATION_MAP_CACHE_KEY)) { + if ($group_relation_map = $this->cache->get(self::GROUP_RELATION_MAP_CACHE_KEY)) { $this->groupRelationMap = $group_relation_map; return; } @@ -395,7 +395,7 @@ protected function refreshGroupRelationMap() { } } // Cache the map. - $this->state->set(self::GROUP_RELATION_MAP_CACHE_KEY, $this->groupRelationMap); + $this->cache->set(self::GROUP_RELATION_MAP_CACHE_KEY, $this->groupRelationMap); } } From dc20d0182069dd5cfbe9cc8c715ab054a519cecc Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Tue, 11 Dec 2018 15:07:57 +0100 Subject: [PATCH 006/111] Clarify how to work with all membership states. Fixes #335 and #336. --- og.module | 6 +----- src/Cache/Context/OgMembershipStateCacheContext.php | 8 +------- src/Controller/SubscriptionController.php | 8 +------- src/MembershipManager.php | 11 ++++++----- src/MembershipManagerInterface.php | 8 ++++++-- src/Og.php | 12 ++++++++---- src/OgMembershipInterface.php | 5 +++++ 7 files changed, 28 insertions(+), 30 deletions(-) diff --git a/og.module b/og.module index d4bf89737..6825d9938 100755 --- a/og.module +++ b/og.module @@ -53,11 +53,7 @@ function og_entity_insert(EntityInterface $entity) { // Other modules that implement hook_entity_insert() might already have // created a membership ahead of us. - if (!Og::getMembership($entity, $entity->getOwner(), [ - OgMembershipInterface::STATE_ACTIVE, - OgMembershipInterface::STATE_PENDING, - OgMembershipInterface::STATE_BLOCKED, - ])) { + if (!Og::getMembership($entity, $entity->getOwner(), OgMembershipInterface::STATES)) { $membership = Og::createMembership($entity, $entity->getOwner()); $membership->save(); } diff --git a/src/Cache/Context/OgMembershipStateCacheContext.php b/src/Cache/Context/OgMembershipStateCacheContext.php index a3b0b7f6c..425f74d54 100644 --- a/src/Cache/Context/OgMembershipStateCacheContext.php +++ b/src/Cache/Context/OgMembershipStateCacheContext.php @@ -76,14 +76,8 @@ public function getContext() { return self::NO_CONTEXT; } - $states = [ - OgMembershipInterface::STATE_ACTIVE, - OgMembershipInterface::STATE_PENDING, - OgMembershipInterface::STATE_BLOCKED, - ]; - /** @var \Drupal\og\OgMembershipInterface $membership */ - $membership = $this->membershipManager->getMembership($group, $this->user, $states); + $membership = $this->membershipManager->getMembership($group, $this->user, OgMembershipInterface::STATES); return $membership ? $membership->getState() : self::NO_CONTEXT; } diff --git a/src/Controller/SubscriptionController.php b/src/Controller/SubscriptionController.php index 776bccb03..2d289261b 100644 --- a/src/Controller/SubscriptionController.php +++ b/src/Controller/SubscriptionController.php @@ -157,13 +157,7 @@ public function subscribe($entity_type_id, EntityInterface $group, OgMembershipT public function unsubscribe(ContentEntityInterface $group) { $user = $this->currentUser(); - $states = [ - OgMembershipInterface::STATE_ACTIVE, - OgMembershipInterface::STATE_PENDING, - OgMembershipInterface::STATE_BLOCKED, - ]; - - if (!$membership = Og::getMembership($group, $user, $states)) { + if (!$membership = Og::getMembership($group, $user, OgMembershipInterface::STATES)) { // User is not a member. throw new AccessDeniedHttpException(); } diff --git a/src/MembershipManager.php b/src/MembershipManager.php index 7677d35f4..221c42419 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -81,6 +81,10 @@ public function getUserGroups(AccountInterface $user, array $states = [OgMembers * {@inheritdoc} */ public function getMemberships(AccountInterface $user, array $states = [OgMembershipInterface::STATE_ACTIVE]) { + // When an empty array is passed, retrieve memberships with all possible + // states. + $states = $states ?: OgMembership::STATES; + // Get a string identifier of the states, so we can retrieve it from cache. sort($states); $states_identifier = implode('|', array_unique($states)); @@ -101,11 +105,8 @@ public function getMemberships(AccountInterface $user, array $states = [OgMember $query = $this->entityTypeManager ->getStorage('og_membership') ->getQuery() - ->condition('uid', $user->id()); - - if ($states) { - $query->condition('state', $states, 'IN'); - } + ->condition('uid', $user->id()) + ->condition('state', $states, 'IN'); $results = $query->execute(); diff --git a/src/MembershipManagerInterface.php b/src/MembershipManagerInterface.php index d117645bb..3a9c6503d 100644 --- a/src/MembershipManagerInterface.php +++ b/src/MembershipManagerInterface.php @@ -61,7 +61,9 @@ public function getUserGroups(AccountInterface $user, array $states = [OgMembers * @param \Drupal\Core\Session\AccountInterface $user * The user to get groups for. * @param array $states - * (optional) Array with the state to return. Defaults to active. + * (optional) Array with the states to return. Defaults to only returning + * active memberships. In order to retrieve all memberships regardless of + * state, pass `OgMembershipInterface::STATES`. * * @return \Drupal\og\OgMembershipInterface[] * An array of OgMembership entities, keyed by ID. @@ -76,7 +78,9 @@ public function getMemberships(AccountInterface $user, array $states = [OgMember * @param \Drupal\Core\Session\AccountInterface $user * The user to get the membership for. * @param array $states - * (optional) Array with the state to return. Defaults to active. + * (optional) Array with the states to return. Defaults to only returning + * active memberships. In order to retrieve all memberships regardless of + * state, pass `OgMembershipInterface::STATES`. * * @return \Drupal\og\OgMembershipInterface|null * The OgMembership entity. NULL will be returned if no membership is diff --git a/src/Og.php b/src/Og.php index 1aa2361e5..2a794717f 100644 --- a/src/Og.php +++ b/src/Og.php @@ -133,9 +133,11 @@ public static function createField($plugin_id, $entity_type, $bundle, array $set * @param \Drupal\Core\Session\AccountInterface $user * The user to get groups for. * @param array $states - * (optional) Array with the state to return. Defaults to active. + * (optional) Array with the states to return. Defaults to only returning + * active memberships. In order to retrieve all memberships regardless of + * state, pass `OgMembershipInterface::STATES`. * - * @return \Drupal\og\Entity\OgMembership[] + * @return \Drupal\og\OgMembershipInterface[] * An array of OgMembership entities, keyed by ID. */ public static function getMemberships(AccountInterface $user, array $states = [OgMembershipInterface::STATE_ACTIVE]) { @@ -152,9 +154,11 @@ public static function getMemberships(AccountInterface $user, array $states = [O * @param \Drupal\Core\Session\AccountInterface $user * The user to get the membership for. * @param array $states - * (optional) Array with the state to return. Defaults to active. + * (optional) Array with the states to return. Defaults to only returning + * active memberships. In order to retrieve all memberships regardless of + * state, pass `OgMembershipInterface::STATES`. * - * @return \Drupal\og\Entity\OgMembership|null + * @return \Drupal\og\OgMembershipInterface|null * The OgMembership entity. NULL will be returned if no membership is * available that matches the passed in $states. */ diff --git a/src/OgMembershipInterface.php b/src/OgMembershipInterface.php index cecd1808b..91df40768 100644 --- a/src/OgMembershipInterface.php +++ b/src/OgMembershipInterface.php @@ -38,6 +38,11 @@ interface OgMembershipInterface extends ContentEntityInterface, EntityOwnerInter */ const STATE_BLOCKED = 'blocked'; + /** + * An array containing all possible group membership states. + */ + const STATES = [self::STATE_ACTIVE, self::STATE_PENDING, self::STATE_BLOCKED]; + /** * The default group membership type that is the bundle of group membership. */ From ae3d36700770f0e06bc2355ec65969b206505253 Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Mon, 19 Nov 2018 10:10:55 +0100 Subject: [PATCH 007/111] Fix Travis CI Integration --- scripts/travis-ci/run-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/travis-ci/run-test.sh b/scripts/travis-ci/run-test.sh index aafaab4a7..07797a6a9 100755 --- a/scripts/travis-ci/run-test.sh +++ b/scripts/travis-ci/run-test.sh @@ -11,7 +11,7 @@ mysql_to_ramdisk() { sudo service mysql start } -TEST_DIRS=($MODULE_DIR/tests $MODULE_DIR/og_ui/tests) +TEST_DIRS=($DRUPAL_DIR/modules/og/tests $DRUPAL_DIR/modules/og/og_ui/tests) case "$1" in PHP_CodeSniffer) From ec10371d5f1f7eeb78c5050912f882d0ca7a8b93 Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Mon, 19 Nov 2018 10:22:25 +0100 Subject: [PATCH 008/111] Dump the composer log --- .travis.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 60ff7dbe9..4e95a0631 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,14 +36,11 @@ before_script: - phpenv config-rm xdebug.ini || true # Make sure Composer is up to date. - - composer self-update + - composer -vvv self-update # Remember the current directory for later use in the Drupal installation. - MODULE_DIR=$(pwd) - # Install Composer dependencies for OG. - - composer install - # Navigate out of module directory to prevent blown stack by recursive module # lookup. - cd .. @@ -59,13 +56,13 @@ before_script: # Download Drupal console so we can run the test for it. Skip this for the # coding standards test. - - test ${TEST_SUITE} == "PHP_CodeSniffer" || composer require --dev drupal/console:~1.0 --working-dir=$DRUPAL_DIR + - test ${TEST_SUITE} == "PHP_CodeSniffer" || composer -vvv require --dev drupal/console:~1.0 --working-dir=$DRUPAL_DIR # Install Composer dependencies for core. Skip this for the coding standards test. - - test ${TEST_SUITE} == "PHP_CodeSniffer" || composer install --working-dir=$DRUPAL_DIR + - test ${TEST_SUITE} == "PHP_CodeSniffer" || composer -vvv install --working-dir=$DRUPAL_DIR # PHPUnit 6 is required when running tests on PHP 7.x. - - test ${TEST_SUITE} == "PHP_CodeSniffer" || test ${TRAVIS_PHP_VERSION:0:3} == "5.6" || composer require --dev phpunit/phpunit:~6 --update-with-dependencies --working-dir=$DRUPAL_DIR + - test ${TEST_SUITE} == "PHP_CodeSniffer" || test ${TRAVIS_PHP_VERSION:0:3} == "5.6" || composer -vvv require --dev phpunit/phpunit:~6 --update-with-dependencies --working-dir=$DRUPAL_DIR # Start a web server on port 8888 in the background. - test ${TEST_SUITE} == "PHP_CodeSniffer" || nohup php -S localhost:8888 --docroot $DRUPAL_DIR > /dev/null 2>&1 & From 2230fab5a7861e4b0aee2288475252b8a9f936e8 Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Mon, 19 Nov 2018 10:33:49 +0100 Subject: [PATCH 009/111] Disable all deprecations --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4e95a0631..d904322fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -76,4 +76,7 @@ before_script: # Export database variable for kernel tests. - export SIMPLETEST_DB=mysql://root:@127.0.0.1/og + # Disable all deprecations + - export SYMFONY_DEPRECATIONS_HELPER=disabled + script: DRUPAL_DIR=$DRUPAL_DIR MODULE_DIR=$MODULE_DIR $MODULE_DIR/scripts/travis-ci/run-test.sh $TEST_SUITE From 04349aca03705ec54725a5842f9338f5bad466cf Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Mon, 19 Nov 2018 10:50:42 +0100 Subject: [PATCH 010/111] Test Drupal 8.7.x with PHP 7.2 only --- .travis.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d904322fa..615d54195 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,8 +19,12 @@ matrix: exclude: - php: 7.1 env: TEST_SUITE=PHP_CodeSniffer - - php: 7.2 - env: TEST_SUITE=PHP_CodeSniffer + - php: 5.6 + env: TEST_SUITE=8.7.x + - php: 7.0 + env: TEST_SUITE=8.7.x + - php: 7.1 + env: TEST_SUITE=8.7.x allow_failures: - env: TEST_SUITE=8.7.x From c1fe12339f04bf2e79a7beb3d644aa5a0254f6b9 Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Mon, 19 Nov 2018 10:51:50 +0100 Subject: [PATCH 011/111] Sort excludes similar to env.matrix --- .travis.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 615d54195..c635ee185 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,14 +17,18 @@ env: # Only run the coding standards check once. matrix: exclude: - - php: 7.1 - env: TEST_SUITE=PHP_CodeSniffer - php: 5.6 env: TEST_SUITE=8.7.x - php: 7.0 env: TEST_SUITE=8.7.x - php: 7.1 env: TEST_SUITE=8.7.x + - php: 5.6 + env: TEST_SUITE=PHP_CodeSniffer + - php: 7.0 + env: TEST_SUITE=PHP_CodeSniffer + - php: 7.1 + env: TEST_SUITE=PHP_CodeSniffer allow_failures: - env: TEST_SUITE=8.7.x From 99dd5a0c7f94351a1c3a347b814430e1bee339be Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Mon, 19 Nov 2018 10:53:49 +0100 Subject: [PATCH 012/111] Remove SYMFONY_DEPRECATIONS_HELPER again --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index c635ee185..797dff82d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -84,7 +84,4 @@ before_script: # Export database variable for kernel tests. - export SIMPLETEST_DB=mysql://root:@127.0.0.1/og - # Disable all deprecations - - export SYMFONY_DEPRECATIONS_HELPER=disabled - script: DRUPAL_DIR=$DRUPAL_DIR MODULE_DIR=$MODULE_DIR $MODULE_DIR/scripts/travis-ci/run-test.sh $TEST_SUITE From 66bf8c0f58c426b45e7ef1dad793f8c5b8efc5e2 Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Mon, 19 Nov 2018 10:56:33 +0100 Subject: [PATCH 013/111] Remove verbose flags from composer --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 797dff82d..0d99ba865 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,7 @@ before_script: - phpenv config-rm xdebug.ini || true # Make sure Composer is up to date. - - composer -vvv self-update + - composer self-update # Remember the current directory for later use in the Drupal installation. - MODULE_DIR=$(pwd) @@ -64,13 +64,13 @@ before_script: # Download Drupal console so we can run the test for it. Skip this for the # coding standards test. - - test ${TEST_SUITE} == "PHP_CodeSniffer" || composer -vvv require --dev drupal/console:~1.0 --working-dir=$DRUPAL_DIR + - test ${TEST_SUITE} == "PHP_CodeSniffer" || composer require --dev drupal/console:~1.0 --working-dir=$DRUPAL_DIR # Install Composer dependencies for core. Skip this for the coding standards test. - - test ${TEST_SUITE} == "PHP_CodeSniffer" || composer -vvv install --working-dir=$DRUPAL_DIR + - test ${TEST_SUITE} == "PHP_CodeSniffer" || composer install --working-dir=$DRUPAL_DIR # PHPUnit 6 is required when running tests on PHP 7.x. - - test ${TEST_SUITE} == "PHP_CodeSniffer" || test ${TRAVIS_PHP_VERSION:0:3} == "5.6" || composer -vvv require --dev phpunit/phpunit:~6 --update-with-dependencies --working-dir=$DRUPAL_DIR + - test ${TEST_SUITE} == "PHP_CodeSniffer" || test ${TRAVIS_PHP_VERSION:0:3} == "5.6" || composer require --dev phpunit/phpunit:~6 --update-with-dependencies --working-dir=$DRUPAL_DIR # Start a web server on port 8888 in the background. - test ${TEST_SUITE} == "PHP_CodeSniffer" || nohup php -S localhost:8888 --docroot $DRUPAL_DIR > /dev/null 2>&1 & From afceeaab238dc18e60aec2f05e2d80c205a001ba Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Tue, 11 Dec 2018 16:36:30 +0100 Subject: [PATCH 014/111] Revert Matrix change --- .travis.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0d99ba865..0b8c19376 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,17 +17,9 @@ env: # Only run the coding standards check once. matrix: exclude: - - php: 5.6 - env: TEST_SUITE=8.7.x - - php: 7.0 - env: TEST_SUITE=8.7.x - php: 7.1 - env: TEST_SUITE=8.7.x - - php: 5.6 env: TEST_SUITE=PHP_CodeSniffer - - php: 7.0 - env: TEST_SUITE=PHP_CodeSniffer - - php: 7.1 + - php: 7.2 env: TEST_SUITE=PHP_CodeSniffer allow_failures: - env: TEST_SUITE=8.7.x From 73ae911b5ada2bc7b9870743a5687e348575b508 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Wed, 12 Dec 2018 09:36:46 +0100 Subject: [PATCH 015/111] Rename the constant to `ALL_STATES`. --- og.module | 2 +- src/Cache/Context/OgMembershipStateCacheContext.php | 2 +- src/Controller/SubscriptionController.php | 2 +- src/MembershipManager.php | 2 +- src/MembershipManagerInterface.php | 4 ++-- src/Og.php | 4 ++-- src/OgMembershipInterface.php | 6 +++++- 7 files changed, 13 insertions(+), 9 deletions(-) diff --git a/og.module b/og.module index 6825d9938..2dd22f4fd 100755 --- a/og.module +++ b/og.module @@ -53,7 +53,7 @@ function og_entity_insert(EntityInterface $entity) { // Other modules that implement hook_entity_insert() might already have // created a membership ahead of us. - if (!Og::getMembership($entity, $entity->getOwner(), OgMembershipInterface::STATES)) { + if (!Og::getMembership($entity, $entity->getOwner(), OgMembershipInterface::ALL_STATES)) { $membership = Og::createMembership($entity, $entity->getOwner()); $membership->save(); } diff --git a/src/Cache/Context/OgMembershipStateCacheContext.php b/src/Cache/Context/OgMembershipStateCacheContext.php index 425f74d54..c3c1b36a9 100644 --- a/src/Cache/Context/OgMembershipStateCacheContext.php +++ b/src/Cache/Context/OgMembershipStateCacheContext.php @@ -77,7 +77,7 @@ public function getContext() { } /** @var \Drupal\og\OgMembershipInterface $membership */ - $membership = $this->membershipManager->getMembership($group, $this->user, OgMembershipInterface::STATES); + $membership = $this->membershipManager->getMembership($group, $this->user, OgMembershipInterface::ALL_STATES); return $membership ? $membership->getState() : self::NO_CONTEXT; } diff --git a/src/Controller/SubscriptionController.php b/src/Controller/SubscriptionController.php index 2d289261b..62c793f52 100644 --- a/src/Controller/SubscriptionController.php +++ b/src/Controller/SubscriptionController.php @@ -157,7 +157,7 @@ public function subscribe($entity_type_id, EntityInterface $group, OgMembershipT public function unsubscribe(ContentEntityInterface $group) { $user = $this->currentUser(); - if (!$membership = Og::getMembership($group, $user, OgMembershipInterface::STATES)) { + if (!$membership = Og::getMembership($group, $user, OgMembershipInterface::ALL_STATES)) { // User is not a member. throw new AccessDeniedHttpException(); } diff --git a/src/MembershipManager.php b/src/MembershipManager.php index 221c42419..d35a7e88e 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -83,7 +83,7 @@ public function getUserGroups(AccountInterface $user, array $states = [OgMembers public function getMemberships(AccountInterface $user, array $states = [OgMembershipInterface::STATE_ACTIVE]) { // When an empty array is passed, retrieve memberships with all possible // states. - $states = $states ?: OgMembership::STATES; + $states = $states ?: OgMembership::ALL_STATES; // Get a string identifier of the states, so we can retrieve it from cache. sort($states); diff --git a/src/MembershipManagerInterface.php b/src/MembershipManagerInterface.php index 3a9c6503d..d35afdf70 100644 --- a/src/MembershipManagerInterface.php +++ b/src/MembershipManagerInterface.php @@ -63,7 +63,7 @@ public function getUserGroups(AccountInterface $user, array $states = [OgMembers * @param array $states * (optional) Array with the states to return. Defaults to only returning * active memberships. In order to retrieve all memberships regardless of - * state, pass `OgMembershipInterface::STATES`. + * state, pass `OgMembershipInterface::ALL_STATES`. * * @return \Drupal\og\OgMembershipInterface[] * An array of OgMembership entities, keyed by ID. @@ -80,7 +80,7 @@ public function getMemberships(AccountInterface $user, array $states = [OgMember * @param array $states * (optional) Array with the states to return. Defaults to only returning * active memberships. In order to retrieve all memberships regardless of - * state, pass `OgMembershipInterface::STATES`. + * state, pass `OgMembershipInterface::ALL_STATES`. * * @return \Drupal\og\OgMembershipInterface|null * The OgMembership entity. NULL will be returned if no membership is diff --git a/src/Og.php b/src/Og.php index 2a794717f..238ee90d1 100644 --- a/src/Og.php +++ b/src/Og.php @@ -135,7 +135,7 @@ public static function createField($plugin_id, $entity_type, $bundle, array $set * @param array $states * (optional) Array with the states to return. Defaults to only returning * active memberships. In order to retrieve all memberships regardless of - * state, pass `OgMembershipInterface::STATES`. + * state, pass `OgMembershipInterface::ALL_STATES`. * * @return \Drupal\og\OgMembershipInterface[] * An array of OgMembership entities, keyed by ID. @@ -156,7 +156,7 @@ public static function getMemberships(AccountInterface $user, array $states = [O * @param array $states * (optional) Array with the states to return. Defaults to only returning * active memberships. In order to retrieve all memberships regardless of - * state, pass `OgMembershipInterface::STATES`. + * state, pass `OgMembershipInterface::ALL_STATES`. * * @return \Drupal\og\OgMembershipInterface|null * The OgMembership entity. NULL will be returned if no membership is diff --git a/src/OgMembershipInterface.php b/src/OgMembershipInterface.php index 91df40768..2f6a4911f 100644 --- a/src/OgMembershipInterface.php +++ b/src/OgMembershipInterface.php @@ -41,7 +41,11 @@ interface OgMembershipInterface extends ContentEntityInterface, EntityOwnerInter /** * An array containing all possible group membership states. */ - const STATES = [self::STATE_ACTIVE, self::STATE_PENDING, self::STATE_BLOCKED]; + const ALL_STATES = [ + self::STATE_ACTIVE, + self::STATE_PENDING, + self::STATE_BLOCKED, + ]; /** * The default group membership type that is the bundle of group membership. From 65c95a892ff88b6f9e12911122ee218a6f49f2d5 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Tue, 11 Dec 2018 11:53:02 +0100 Subject: [PATCH 016/111] Avoid double caching of OgMembership entities. Fixes #445 --- src/MembershipManager.php | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index d35a7e88e..fbcdd6581 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -97,25 +97,20 @@ public function getMemberships(AccountInterface $user, array $states = [OgMember ]; $identifier = implode(':', $identifier); - // Return cached result if it exists. - if (isset($this->cache[$identifier])) { - return $this->cache[$identifier]; - } - - $query = $this->entityTypeManager - ->getStorage('og_membership') - ->getQuery() - ->condition('uid', $user->id()) - ->condition('state', $states, 'IN'); + // Use cached result if it exists. + if (!isset($this->cache[$identifier])) { + $query = $this->entityTypeManager + ->getStorage('og_membership') + ->getQuery() + ->condition('uid', $user->id()) + ->condition('state', $states, 'IN'); - $results = $query->execute(); + $this->cache[$identifier] = $query->execute(); + } - /** @var \Drupal\og\Entity\OgMembership[] $memberships */ - $this->cache[$identifier] = $this->entityTypeManager + return $this->entityTypeManager ->getStorage('og_membership') - ->loadMultiple($results); - - return $this->cache[$identifier]; + ->loadMultiple($this->cache[$identifier]); } /** From 7df64cb3e63be831ac40c796c874a2c5b79fd81e Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Tue, 11 Dec 2018 23:44:27 +0100 Subject: [PATCH 017/111] Provide a method to retrieve group memberships by role. --- src/MembershipManager.php | 106 +++++- src/MembershipManagerInterface.php | 17 + .../Entity/GroupMembershipManagerTest.php | 354 +++++++++++++++++- 3 files changed, 452 insertions(+), 25 deletions(-) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index fbcdd6581..1b961ccc6 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -83,17 +83,13 @@ public function getUserGroups(AccountInterface $user, array $states = [OgMembers public function getMemberships(AccountInterface $user, array $states = [OgMembershipInterface::STATE_ACTIVE]) { // When an empty array is passed, retrieve memberships with all possible // states. - $states = $states ?: OgMembership::ALL_STATES; - - // Get a string identifier of the states, so we can retrieve it from cache. - sort($states); - $states_identifier = implode('|', array_unique($states)); + $states = $this->prepareConditionArray($states, OgMembership::ALL_STATES); $identifier = [ __METHOD__, 'user', $user->id(), - $states_identifier, + implode('|', $states), ]; $identifier = implode(':', $identifier); @@ -108,9 +104,7 @@ public function getMemberships(AccountInterface $user, array $states = [OgMember $this->cache[$identifier] = $query->execute(); } - return $this->entityTypeManager - ->getStorage('og_membership') - ->loadMultiple($this->cache[$identifier]); + return $this->loadMemberships($this->cache[$identifier]); } /** @@ -127,6 +121,59 @@ public function getMembership(EntityInterface $group, AccountInterface $user, ar return NULL; } + /** + * {@inheritdoc} + */ + public function getGroupMembershipsByRoleNames(EntityInterface $group, array $role_names, array $states = [OgMembershipInterface::STATE_ACTIVE]) { + if (empty($role_names)) { + throw new \InvalidArgumentException('The array of role names should not be empty.'); + } + + // In case the 'member' role is one of the requested roles, we just need to + // return all memberships. We can safely ignore all other roles. + $retrieve_all_memberships = FALSE; + if (in_array(OgRoleInterface::AUTHENTICATED, $role_names)) { + $retrieve_all_memberships = TRUE; + $role_names = [OgRoleInterface::AUTHENTICATED]; + } + + $role_names = $this->prepareConditionArray($role_names); + $states = $this->prepareConditionArray($states, OgMembership::ALL_STATES); + + $identifier = [ + __METHOD__, + $group->id(), + implode('|', $role_names), + implode('|', $states), + ]; + $identifier = implode(':', $identifier); + + // Only query the database if no cached result exists. + if (!isset($this->cache[$identifier])) { + $entity_type_id = $group->getEntityTypeId(); + + $query = $this->entityTypeManager + ->getStorage('og_membership') + ->getQuery() + ->condition('entity_type', $entity_type_id) + ->condition('entity_id', $group->id()) + ->condition('state', $states, 'IN'); + + if (!$retrieve_all_memberships) { + $bundle_id = $group->bundle(); + $role_ids = array_map(function ($role_name) use ($entity_type_id, $bundle_id) { + return implode('-', [$entity_type_id, $bundle_id, $role_name]); + }, $role_names); + + $query->condition('roles', $role_ids, 'IN'); + } + + $this->cache[$identifier] = $query->execute(); + } + + return $this->loadMemberships($this->cache[$identifier]); + } + /** * {@inheritdoc} */ @@ -318,4 +365,45 @@ public function reset() { $this->cache = []; } + /** + * Prepares a conditional array for use in a cache identifier and query. + * + * This will filter out any duplicate values from the array and sort the + * values so that a consistent cache identifier can be generated. Optionally + * it can substitute an empty array with a default value. + * + * @param array $value + * The array to prepare. + * @param array|null $default + * An optional default value to use in case the passed in value is empty. If + * set to NULL this will be ignored. + * + * @return array + * The prepared array. + */ + protected function prepareConditionArray(array $value, array $default = NULL) { + // Fall back to the default value if the passed in value is empty and a + // default value is given. + if (empty($value) && $default !== NULL) { + $value = $default; + } + sort($value); + return array_unique($value); + } + + /** + * Returns the full membership entities with the given memberships IDs. + * + * @param array $ids + * The IDs of the memberships to load. + * + * @return \Drupal\Core\Entity\EntityInterface[] + * The membership entities. + */ + protected function loadMemberships(array $ids) { + return $this->entityTypeManager + ->getStorage('og_membership') + ->loadMultiple($ids); + } + } diff --git a/src/MembershipManagerInterface.php b/src/MembershipManagerInterface.php index d35afdf70..8192bc1a0 100644 --- a/src/MembershipManagerInterface.php +++ b/src/MembershipManagerInterface.php @@ -88,6 +88,23 @@ public function getMemberships(AccountInterface $user, array $states = [OgMember */ public function getMembership(EntityInterface $group, AccountInterface $user, array $states = [OgMembershipInterface::STATE_ACTIVE]); + /** + * Returns the memberships of the given group filtered by role name. + * + * @param \Drupal\Core\Entity\EntityInterface $group + * The group entity for which to return the memberships. + * @param array $role_names + * An array of role names to filter by. + * @param array $states + * (optional) Array with the states to return. Defaults to only returning + * active memberships. In order to retrieve all memberships regardless of + * state, pass `OgMembershipInterface::ALL_STATES`. + * + * @return \Drupal\Core\Entity\EntityInterface[] + * The membership entities. + */ + public function getGroupMembershipsByRoleNames(EntityInterface $group, array $role_names, array $states = [OgMembershipInterface::STATE_ACTIVE]); + /** * Creates an OG membership. * diff --git a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php index 705b81918..965dd1301 100644 --- a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php +++ b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php @@ -9,8 +9,12 @@ use Drupal\entity_test\Entity\EntityTest; use Drupal\node\Entity\Node; use Drupal\node\Entity\NodeType; +use Drupal\og\Entity\OgRole; use Drupal\og\Og; use Drupal\og\OgGroupAudienceHelperInterface; +use Drupal\og\OgMembershipInterface; +use Drupal\og\OgRoleInterface; +use Drupal\Tests\og\Traits\OgMembershipCreationTrait; use Drupal\user\Entity\User; /** @@ -21,6 +25,8 @@ */ class GroupMembershipManagerTest extends KernelTestBase { + use OgMembershipCreationTrait; + /** * {@inheritdoc} */ @@ -47,6 +53,13 @@ class GroupMembershipManagerTest extends KernelTestBase { */ protected $groupContent; + /** + * Test users. + * + * @var \Drupal\user\UserInterface[] + */ + protected $users; + /** * The entity type manager. * @@ -54,6 +67,13 @@ class GroupMembershipManagerTest extends KernelTestBase { */ protected $entityTypeManager; + /** + * The membership manager. This is the system under test. + * + * @var \Drupal\og\MembershipManagerInterface + */ + protected $membershipManager; + /** * {@inheritdoc} */ @@ -70,12 +90,14 @@ protected function setUp() { $this->installSchema('system', 'sequences'); $this->entityTypeManager = $this->container->get('entity_type.manager'); + $this->membershipManager = $this->container->get('og.membership_manager'); $this->groups = []; // Create group admin user. $group_admin = User::create(['name' => $this->randomString()]); $group_admin->save(); + $this->users[0] = $group_admin; // Create four groups of two different entity types. for ($i = 0; $i < 2; $i++) { @@ -156,10 +178,7 @@ protected function setUp() { * @dataProvider groupContentProvider */ public function testGetGroupIds($group_type_id, $group_bundle, array $expected) { - /** @var \Drupal\og\MembershipManagerInterface $membership_manager */ - $membership_manager = \Drupal::service('og.membership_manager'); - - $result = $membership_manager->getGroupIds($this->groupContent, $group_type_id, $group_bundle); + $result = $this->membershipManager->getGroupIds($this->groupContent, $group_type_id, $group_bundle); // Check that the correct number of results is returned. $this->assertEquals(count($expected, COUNT_RECURSIVE), count($result, COUNT_RECURSIVE)); @@ -181,8 +200,6 @@ public function testGetGroupIds($group_type_id, $group_bundle, array $expected) * @covers ::getGroups */ public function testStaticCache() { - /** @var \Drupal\og\MembershipManagerInterface $membership_manager */ - $membership_manager = \Drupal::service('og.membership_manager'); $bundle_rev = mb_strtolower($this->randomMachineName()); $bundle_with_bundle = mb_strtolower($this->randomMachineName()); EntityTestBundle::create(['id' => $bundle_with_bundle, 'label' => $bundle_with_bundle])->save(); @@ -222,11 +239,11 @@ public function testStaticCache() { // ensure that the next assertions are addressing the proper issue. $this->assertEquals($group_content_rev->id(), $group_content_with_bundle->id()); - $group_content_rev_group = $membership_manager->getGroups($group_content_rev); + $group_content_rev_group = $this->membershipManager->getGroups($group_content_rev); /** @var \Drupal\node\NodeInterface $group */ $group = reset($group_content_rev_group['node']); $this->assertEquals($this->groups['node'][0]->id(), $group->id()); - $group_content_with_bundle_group = $membership_manager->getGroups($group_content_with_bundle); + $group_content_with_bundle_group = $this->membershipManager->getGroups($group_content_with_bundle); $group = reset($group_content_with_bundle_group['node']); $this->assertEquals($this->groups['node'][1]->id(), $group->id()); } @@ -247,10 +264,7 @@ public function testStaticCache() { * @dataProvider groupContentProvider */ public function testGetGroups($group_type_id, $group_bundle, array $expected) { - /** @var \Drupal\og\MembershipManagerInterface $membership_manager */ - $membership_manager = \Drupal::service('og.membership_manager'); - - $result = $membership_manager->getGroups($this->groupContent, $group_type_id, $group_bundle); + $result = $this->membershipManager->getGroups($this->groupContent, $group_type_id, $group_bundle); // Check that the correct number of results is returned. $this->assertEquals(count($expected, COUNT_RECURSIVE), count($result, COUNT_RECURSIVE)); @@ -289,10 +303,7 @@ public function testGetGroups($group_type_id, $group_bundle, array $expected) { * @dataProvider groupContentProvider */ public function testGetGroupCount($group_type_id, $group_bundle, array $expected) { - /** @var \Drupal\og\MembershipManagerInterface $membership_manager */ - $membership_manager = \Drupal::service('og.membership_manager'); - - $result = $membership_manager->getGroupCount($this->groupContent, $group_type_id, $group_bundle); + $result = $this->membershipManager->getGroupCount($this->groupContent, $group_type_id, $group_bundle); // Check that the correct results is returned. $this->assertEquals(count($expected, COUNT_RECURSIVE) - count($expected), $result); @@ -318,4 +329,315 @@ public function groupContentProvider() { ]; } + /** + * Tests retrieval of group memberships filtered by role names. + * + * @covers ::getGroupMembershipsByRoleNames + */ + public function testGetGroupMembershipsByRoleNames() { + $this->createTestMemberships(); + + // Check that an exception is thrown if no role names are passed. + try { + $this->membershipManager->getGroupMembershipsByRoleNames($this->groups['node'][0], []); + $this->fail('MembershipManager::getGroupsMembershipsByRoleNames() throws an exception when called without passing any role names.'); + } + catch (\InvalidArgumentException $e) { + // Expected result. + } + + // Define a test matrix to iterate over. We're not using a data provider + // because the large number of test cases would slow down the test too much. + $matrix = [ + 'node' => [ + 0 => [ + // All memberships with all possible states. The authenticated role + // covers all memberships. + [ + 'roles' => [OgRoleInterface::AUTHENTICATED], + 'states' => OgMembershipInterface::ALL_STATES, + 'expected_memberships' => [0, 1, 4, 7], + ], + // All memberships with all possible states, by passing an empty + // states array, and passing all defined roles. + [ + 'roles' => [ + OgRoleInterface::AUTHENTICATED, + OgRoleInterface::ADMINISTRATOR, + 'moderator', + ], + 'states' => [], + 'expected_memberships' => [0, 1, 4, 7], + ], + // Pending members. + [ + 'roles' => [OgRoleInterface::AUTHENTICATED], + 'states' => [OgMembershipInterface::STATE_PENDING], + 'expected_memberships' => [4], + ], + ], + 1 => [ + // All administrators. + [ + 'roles' => [OgRoleInterface::ADMINISTRATOR], + 'states' => [], + 'expected_memberships' => [2, 6], + ], + // Pending administrators. + [ + 'roles' => [OgRoleInterface::ADMINISTRATOR], + 'states' => [OgMembershipInterface::STATE_PENDING], + 'expected_memberships' => [2], + ], + // Blocked administrators. There are none. + [ + 'roles' => [OgRoleInterface::ADMINISTRATOR], + 'states' => [OgMembershipInterface::STATE_BLOCKED], + 'expected_memberships' => [], + ], + // Pending and blocked administrators and moderators. Should be the + // same result as the pending administrators, since there are no + // moderators or blocked users. + [ + 'roles' => [OgRoleInterface::ADMINISTRATOR, 'moderator'], + 'states' => [ + OgMembershipInterface::STATE_BLOCKED, + OgMembershipInterface::STATE_PENDING, + ], + 'expected_memberships' => [2], + ], + // Switch the order of the arguments, this should not affect the + // result. + [ + 'roles' => ['moderator', OgRoleInterface::ADMINISTRATOR], + 'states' => [ + OgMembershipInterface::STATE_PENDING, + OgMembershipInterface::STATE_BLOCKED, + ], + 'expected_memberships' => [2], + ], + // There are no pending or blocked moderators. + [ + 'roles' => ['moderator'], + 'states' => [ + OgMembershipInterface::STATE_BLOCKED, + OgMembershipInterface::STATE_PENDING, + ], + 'expected_memberships' => [], + ], + ], + ], + 'entity_test' => [ + 0 => [ + // The first test entity group doesn't have any moderators or admins. + // Check that duplicated array values doesn't affect the result. + [ + 'roles' => [ + 'moderator', + OgRoleInterface::ADMINISTRATOR, + 'moderator', + 'moderator', + OgRoleInterface::ADMINISTRATOR, + ], + 'states' => [ + OgMembershipInterface::STATE_ACTIVE, + OgMembershipInterface::STATE_BLOCKED, + OgMembershipInterface::STATE_PENDING, + OgMembershipInterface::STATE_PENDING, + OgMembershipInterface::STATE_BLOCKED, + OgMembershipInterface::STATE_ACTIVE, + ], + 'expected_memberships' => [], + ], + ], + // Check active members. + [ + 'roles' => [ + OgRoleInterface::AUTHENTICATED, + ], + 'states' => [ + OgMembershipInterface::STATE_ACTIVE, + ], + 'expected_memberships' => [0, 3], + ], + 1 => [ + // There are two blocked users in the second test entity group. + [ + 'roles' => [ + OgRoleInterface::AUTHENTICATED, + OgRoleInterface::ADMINISTRATOR, + 'moderator', + ], + 'states' => [ + OgMembershipInterface::STATE_BLOCKED, + ], + 'expected_memberships' => [4, 7], + ], + // There is one blocked moderator. + [ + 'roles' => [ + OgRoleInterface::ADMINISTRATOR, + 'moderator', + ], + 'states' => [ + OgMembershipInterface::STATE_BLOCKED, + ], + 'expected_memberships' => [4], + ], + ], + ], + ]; + + foreach ($matrix as $entity_type_id => $groups) { + foreach ($groups as $group_key => $test_cases) { + foreach ($test_cases as $test_case) { + $group = $this->groups[$entity_type_id][$group_key]; + $role_names = $test_case['roles']; + $states = $test_case['states']; + $expected_memberships = $test_case['expected_memberships']; + + /** @var \Drupal\og\OgMembershipInterface[] $actual_memberships */ + $actual_memberships = $this->membershipManager->getGroupMembershipsByRoleNames($group, $role_names, $states); + + $this->assertEquals(count($expected_memberships), count($actual_memberships)); + + foreach ($expected_memberships as $expected_membership_key) { + $expected_user_id = $this->users[$expected_membership_key]->id(); + foreach ($actual_memberships as $actual_membership) { + if ($actual_membership->getOwnerId() == $expected_user_id) { + // Match found. + continue 2; + } + } + // The expected membership was not returned. Fail the test. + $this->fail("The membership for user $expected_membership_key is present in the result."); + } + } + } + } + } + + /** + * Creates a number of users that are members of the test groups. + */ + protected function createTestMemberships() { + // Create a 'moderator' role in each of the test group types. + foreach (['node', 'entity_test'] as $entity_type_id) { + for ($i = 0; $i < 2; $i++) { + $bundle = "${entity_type_id}_$i"; + $og_role = OgRole::create(); + $og_role + ->setName('moderator') + ->setGroupType($entity_type_id) + ->setGroupBundle($bundle) + ->save(); + } + } + + // Create test users with different membership states in the various groups. + // Note that the group admin (test user 0) is also a member of all groups. + $matrix = [ + // A user which is an active member of the first node group. + 1 => [ + 'node' => [ + 0 => [ + 'state' => OgMembershipInterface::STATE_ACTIVE, + 'roles' => [OgRoleInterface::AUTHENTICATED], + ], + ], + ], + + // A user which is a pending administrator of the second node group. + 2 => [ + 'node' => [ + 1 => [ + 'state' => OgMembershipInterface::STATE_PENDING, + 'roles' => [OgRoleInterface::ADMINISTRATOR], + ], + ], + ], + + // A user which is an active member of both test entity groups. + 3 => [ + 'entity_test' => [ + 0 => [ + 'state' => OgMembershipInterface::STATE_ACTIVE, + 'roles' => [OgRoleInterface::AUTHENTICATED], + ], + 1 => [ + 'state' => OgMembershipInterface::STATE_ACTIVE, + 'roles' => [OgRoleInterface::AUTHENTICATED], + ], + ], + ], + + // A user which is a pending member of the first node group and a blocked + // moderator in the second test entity group. + 4 => [ + 'node' => [ + 0 => [ + 'state' => OgMembershipInterface::STATE_PENDING, + 'roles' => [OgRoleInterface::AUTHENTICATED], + ], + ], + 'entity_test' => [ + 1 => [ + 'state' => OgMembershipInterface::STATE_BLOCKED, + 'roles' => ['moderator'], + ], + ], + ], + + // A user which is not subscribed to any of the groups. + 5 => [], + + // A user which is both an administrator and a moderator in the second + // node group. + 6 => [ + 'node' => [ + 1 => [ + 'state' => OgMembershipInterface::STATE_ACTIVE, + 'roles' => [OgRoleInterface::ADMINISTRATOR, 'moderator'], + ], + ], + ], + + // A troll who is banned everywhere. + 7 => [ + 'node' => [ + 0 => [ + 'state' => OgMembershipInterface::STATE_BLOCKED, + 'roles' => [OgRoleInterface::AUTHENTICATED], + ], + 1 => [ + 'state' => OgMembershipInterface::STATE_BLOCKED, + 'roles' => [OgRoleInterface::AUTHENTICATED], + ], + ], + 'entity_test' => [ + 0 => [ + 'state' => OgMembershipInterface::STATE_BLOCKED, + 'roles' => [OgRoleInterface::AUTHENTICATED], + ], + 1 => [ + 'state' => OgMembershipInterface::STATE_BLOCKED, + 'roles' => [OgRoleInterface::AUTHENTICATED], + ], + ], + ], + ]; + + foreach ($matrix as $user_key => $entity_types) { + $user = User::create(['name' => $this->randomString()]); + $user->save(); + $this->users[$user_key] = $user; + foreach ($entity_types as $entity_type_id => $groups) { + foreach ($groups as $group_key => $membership_info) { + $group = $this->groups[$entity_type_id][$group_key]; + $this->createOgMembership($group, $user, $membership_info['roles'], $membership_info['state']); + } + } + } + } + } From 5bd6f87cd33c991718a5e3c229481e2ea09230d1 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Wed, 12 Dec 2018 15:56:49 +0100 Subject: [PATCH 018/111] Avoid needlessly invoking EntityStorageInterface::loadMultiple(). --- src/MembershipManager.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index 1b961ccc6..745166f23 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -401,6 +401,10 @@ protected function prepareConditionArray(array $value, array $default = NULL) { * The membership entities. */ protected function loadMemberships(array $ids) { + if (empty($ids)) { + return []; + } + return $this->entityTypeManager ->getStorage('og_membership') ->loadMultiple($ids); From 8205988580ab6cf89999ea8648e0a61fe6d0cb28 Mon Sep 17 00:00:00 2001 From: Francesco Date: Tue, 18 Dec 2018 16:02:55 +0200 Subject: [PATCH 019/111] Use the best fitting assertion for comparing array sizes. Co-Authored-By: pfrenssen --- tests/src/Kernel/Entity/GroupMembershipManagerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php index 965dd1301..ee62142bf 100644 --- a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php +++ b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php @@ -499,7 +499,7 @@ public function testGetGroupMembershipsByRoleNames() { /** @var \Drupal\og\OgMembershipInterface[] $actual_memberships */ $actual_memberships = $this->membershipManager->getGroupMembershipsByRoleNames($group, $role_names, $states); - $this->assertEquals(count($expected_memberships), count($actual_memberships)); + $this->assertSameSize($expected_memberships, $actual_memberships); foreach ($expected_memberships as $expected_membership_key) { $expected_user_id = $this->users[$expected_membership_key]->id(); From ff5f382f719641c82597fcefda8d39010fe85af2 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Thu, 20 Dec 2018 12:29:45 +0100 Subject: [PATCH 020/111] Use state service. --- og.services.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/og.services.yml b/og.services.yml index 34a31b286..fae318a62 100644 --- a/og.services.yml +++ b/og.services.yml @@ -42,7 +42,7 @@ services: arguments: ['@entity_type.manager', '@entity_field.manager'] og.group_type_manager: class: Drupal\og\GroupTypeManager - arguments: ['@config.factory', '@entity_type.manager', '@entity_type.bundle.info', '@event_dispatcher', '@state', '@og.permission_manager', '@og.role_manager', '@router.builder', '@og.group_audience_helper'] + arguments: ['@config.factory', '@entity_type.manager', '@entity_type.bundle.info', '@event_dispatcher', '@cache.data', '@og.permission_manager', '@og.role_manager', '@router.builder', '@og.group_audience_helper'] og.membership_manager: class: Drupal\og\MembershipManager arguments: ['@entity_type.manager', '@og.group_audience_helper'] From c14520e30355f737156289646e2dff0557710d9a Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Thu, 20 Dec 2018 12:56:23 +0100 Subject: [PATCH 021/111] Fixed tests --- tests/src/Unit/GroupTypeManagerTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/src/Unit/GroupTypeManagerTest.php b/tests/src/Unit/GroupTypeManagerTest.php index c00815481..7773fb5f1 100644 --- a/tests/src/Unit/GroupTypeManagerTest.php +++ b/tests/src/Unit/GroupTypeManagerTest.php @@ -2,13 +2,13 @@ namespace Drupal\Tests\og\Unit; +use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Config\Config; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Routing\RouteBuilderInterface; -use Drupal\Core\State\StateInterface; use Drupal\og\Event\GroupCreationEvent; use Drupal\og\Event\GroupCreationEventInterface; use Drupal\og\GroupTypeManager; @@ -87,11 +87,11 @@ class GroupTypeManagerTest extends UnitTestCase { protected $permissionEvent; /** - * The state prophecy used in the test. + * The cache prophecy used in the test. * - * @var \Drupal\Core\State\StateInterface|\Prophecy\Prophecy\ObjectProphecy + * @var \Drupal\Core\Cache\CacheBackendInterface|\Prophecy\Prophecy\ObjectProphecy */ - protected $state; + protected $cache; /** * The OG permission manager prophecy used in the test. @@ -135,7 +135,7 @@ public function setUp() { $this->ogRoleManager = $this->prophesize(OgRoleManagerInterface::class); $this->permissionEvent = $this->prophesize(PermissionEventInterface::class); $this->permissionManager = $this->prophesize(PermissionManagerInterface::class); - $this->state = $this->prophesize(StateInterface::class); + $this->cache = $this->prophesize(CacheBackendInterface::class); $this->routeBuilder = $this->prophesize(RouteBuilderInterface::class); $this->groupAudienceHelper = $this->prophesize(OgGroupAudienceHelperInterface::class); } From 0058f69f1868718ce6a38f5306bedfdc669a0adb Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Thu, 20 Dec 2018 12:56:53 +0100 Subject: [PATCH 022/111] Fixed tests --- tests/src/Unit/GroupTypeManagerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Unit/GroupTypeManagerTest.php b/tests/src/Unit/GroupTypeManagerTest.php index 7773fb5f1..37ebdc1b3 100644 --- a/tests/src/Unit/GroupTypeManagerTest.php +++ b/tests/src/Unit/GroupTypeManagerTest.php @@ -331,7 +331,7 @@ protected function createGroupManager() { $this->entityTypeManager->reveal(), $this->entityTypeBundleInfo->reveal(), $this->eventDispatcher->reveal(), - $this->state->reveal(), + $this->cache->reveal(), $this->permissionManager->reveal(), $this->ogRoleManager->reveal(), $this->routeBuilder->reveal(), From 69df86671557414a7fc88929c0c37d137ff029d5 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Fri, 21 Dec 2018 11:05:21 +0100 Subject: [PATCH 023/111] Added early exit --- og.module | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/og.module b/og.module index 5e803aa4a..a4cba3e1c 100755 --- a/og.module +++ b/og.module @@ -374,8 +374,13 @@ function og_og_role_insert(OgRoleInterface $role) { return; } + // Do not create config while config import is in progress. + if (\Drupal::isConfigSyncing()) { + return; + } + $add_id = 'og_membership_add_single_role_action.' . $role->getName(); - if (!Action::load($add_id) && !\Drupal::isConfigSyncing()) { + if (!Action::load($add_id)) { $action = Action::create([ 'id' => $add_id, 'type' => 'og_membership', @@ -388,7 +393,7 @@ function og_og_role_insert(OgRoleInterface $role) { $action->trustData()->save(); } $remove_id = 'og_membership_remove_single_role_action.' . $role->getName(); - if (!Action::load($remove_id) && !\Drupal::isConfigSyncing()) { + if (!Action::load($remove_id)) { $action = Action::create([ 'id' => $remove_id, 'type' => 'og_membership', From 2cb601c79fac4cbf7eb99aba64d279035488d9b8 Mon Sep 17 00:00:00 2001 From: Chris Burgess Date: Mon, 24 Dec 2018 13:26:39 +1300 Subject: [PATCH 024/111] Issue #455 - Early exit if no memberships to process --- og.install | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/og.install b/og.install index d657d4709..80ad218cf 100644 --- a/og.install +++ b/og.install @@ -28,9 +28,14 @@ function og_update_8001(&$sandbox) { \Drupal::entityDefinitionUpdateManager()->installFieldStorageDefinition('entity_bundle', 'og_membership', 'og', $storage_definition); $sandbox['#finished'] = 0; + $sandbox['batch_size'] = 500; $sandbox['current'] = 0; $sandbox['total'] = $storage->getQuery()->count()->execute(); - $sandbox['batch_size'] = 500; + + if (!$sandbox['total']) { + $sandbox['#finished'] = 1; + return t('No OG memberships found.'); + } } // Update the existing memberships to include the group bundle ID. From 940b6c915958a6f7b2aaf5e31abc14cb6f09f42e Mon Sep 17 00:00:00 2001 From: Chris Burgess Date: Tue, 8 Jan 2019 11:06:28 +1300 Subject: [PATCH 025/111] Show uid in LogicException for existing membership When using OG with migrations, the module can generate a series of import failures with exceptions that could be more useful. [error] LogicException: An OG membership already exists for group of entity-type node and ID: 8553 in Drupal\og\Entity\OgMembership->preSave() (line 466 of /var/www/localhost/drupal/web/modules/contrib/og/src/Entity/OgMembership.php). [error] An OG membership already exists for group of entity-type node and ID: 8553 (/var/www/localhost/drupal/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php:783) [error] LogicException: An OG membership already exists for group of entity-type node and ID: 11100 in Drupal\og\Entity\OgMembership->preSave() (line 466 of /var/www/localhost/drupal/web/modules/contrib/og/src/Entity/OgMembership.php). [error] An OG membership already exists for group of entity-type node and ID: 11100 (/var/www/localhost/drupal/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php:783) [error] LogicException: An OG membership already exists for group of entity-type node and ID: 11113 in Drupal\og\Entity\OgMembership->preSave() (line 466 of /var/www/localhost/drupal/web/modules/contrib/og/src/Entity/OgMembership.php). [error] An OG membership already exists for group of entity-type node and ID: 11113 (/var/www/localhost/drupal/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php:783) Including the uid in these exceptions will make the reported error more actionable; that information probably would be implicit when the exception is surfaced through a subscribe UI but is not apparent when migrating thousands of user memberships. --- src/Entity/OgMembership.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index c9ccf9788..668340c7e 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -463,7 +463,7 @@ public function preSave(EntityStorageInterface $storage) { ->execute(); if ($count) { - throw new \LogicException(sprintf('An OG membership already exists for group of entity-type %s and ID: %s', $entity_type_id, $this->getGroup()->id())); + throw new \LogicException(sprintf('An OG membership already exists for uid %s in group of entity-type %s and ID: %s', $this->get('uid')->target_id, $entity_type_id, $this->getGroup()->id())); } parent::preSave($storage); From 480ca7ad41cad294dbdb546feff392ec286b7b56 Mon Sep 17 00:00:00 2001 From: Joshua Brauer Date: Sat, 12 Jan 2019 14:01:35 -0700 Subject: [PATCH 026/111] Fix minor typo. Also issue 3014111 on d.o --- src/Form/GroupSubscribeForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Form/GroupSubscribeForm.php b/src/Form/GroupSubscribeForm.php index 0ce927acc..0afbabcfb 100644 --- a/src/Form/GroupSubscribeForm.php +++ b/src/Form/GroupSubscribeForm.php @@ -234,7 +234,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { /** @var EntityInterface $group */ $group = $membership->getGroup(); - $message = $membership->isActive() ? $this->t('Your are now subscribed to the group.') : $this->t('Your subscription request was sent.'); + $message = $membership->isActive() ? $this->t('You are now subscribed to the group.') : $this->t('Your subscription request was sent.'); $this->messenger()->addMessage($message); // User doesn't have access to the group entity, so redirect to front page, From a244dc58d8932de7113cef36dfd64be06e3e6e3e Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Sat, 12 Jan 2019 19:22:23 -0700 Subject: [PATCH 027/111] Update src/Form/GroupSubscribeForm.php Yes! Co-Authored-By: jbrauer --- src/Form/GroupSubscribeForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Form/GroupSubscribeForm.php b/src/Form/GroupSubscribeForm.php index 0afbabcfb..822ee96cc 100644 --- a/src/Form/GroupSubscribeForm.php +++ b/src/Form/GroupSubscribeForm.php @@ -234,7 +234,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { /** @var EntityInterface $group */ $group = $membership->getGroup(); - $message = $membership->isActive() ? $this->t('You are now subscribed to the group.') : $this->t('Your subscription request was sent.'); + $message = $membership->isActive() ? $this->t('You are now subscribed to the group.') : $this->t('Your subscription request has been sent.'); $this->messenger()->addMessage($message); // User doesn't have access to the group entity, so redirect to front page, From 29055eee1345609641f0d39f4e8716248b713d19 Mon Sep 17 00:00:00 2001 From: pebosi Date: Fri, 1 Feb 2019 11:08:00 +0000 Subject: [PATCH 028/111] Add default access check --- config/optional/views.view.og_members_overview.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config/optional/views.view.og_members_overview.yml b/config/optional/views.view.og_members_overview.yml index ad531e3ab..9b14d1dba 100644 --- a/config/optional/views.view.og_members_overview.yml +++ b/config/optional/views.view.og_members_overview.yml @@ -22,8 +22,9 @@ display: position: 0 display_options: access: - type: none - options: { } + type: perm + options: + perm: 'access content' cache: type: none options: { } From 0bed4e91693487f37d18b2bc5461f16e5b163034 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Tue, 12 Mar 2019 11:31:41 +0100 Subject: [PATCH 029/111] Update views.view.og_members_overview.yml --- config/optional/views.view.og_members_overview.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/optional/views.view.og_members_overview.yml b/config/optional/views.view.og_members_overview.yml index 9b14d1dba..702d9f7a0 100644 --- a/config/optional/views.view.og_members_overview.yml +++ b/config/optional/views.view.og_members_overview.yml @@ -357,10 +357,10 @@ display: entity_type: og_membership entity_field: state plugin_id: field - roles: - id: roles + roles_target_id: + id: roles_target_id table: og_membership__roles - field: roles + field: roles_target_id relationship: none group_type: group admin_label: '' From 604822f9d76acb87dbed3f0d9192f486fb6d96ee Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Thu, 14 Mar 2019 14:53:45 +0100 Subject: [PATCH 030/111] Use full pager on member overview --- config/optional/views.view.og_members_overview.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/config/optional/views.view.og_members_overview.yml b/config/optional/views.view.og_members_overview.yml index 9b14d1dba..4a8fbc31e 100644 --- a/config/optional/views.view.og_members_overview.yml +++ b/config/optional/views.view.og_members_overview.yml @@ -3,6 +3,7 @@ status: true dependencies: module: - og + - options - user _core: default_config_hash: RnChWtrF4u0Q13iQMFypL0Uz6IsB4NY6ZTk_LorSbJg @@ -47,12 +48,17 @@ display: sort_asc_label: Asc sort_desc_label: Desc pager: - type: mini + type: full options: - items_per_page: 10 + items_per_page: 50 offset: 0 id: 0 total_pages: null + tags: + previous: ‹‹ + next: ›› + first: '« First' + last: 'Last »' expose: items_per_page: false items_per_page_label: 'Items per page' @@ -61,9 +67,7 @@ display: items_per_page_options_all_label: '- All -' offset: false offset_label: Offset - tags: - previous: ‹‹ - next: ›› + quantity: 9 style: type: table options: From ca79e890784f55ec667e3839340fdae0095aac3d Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Wed, 20 Mar 2019 13:06:39 +0100 Subject: [PATCH 031/111] Retrieve the bundle directly from the membership. It is not necessary to load the full entity for this. --- src/Plugin/Action/AddSingleOgMembershipRole.php | 2 +- src/Plugin/Action/RemoveSingleOgMembershipRole.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Plugin/Action/AddSingleOgMembershipRole.php b/src/Plugin/Action/AddSingleOgMembershipRole.php index 0283ca106..67dc79045 100644 --- a/src/Plugin/Action/AddSingleOgMembershipRole.php +++ b/src/Plugin/Action/AddSingleOgMembershipRole.php @@ -26,7 +26,7 @@ public function execute(OgMembership $membership = NULL) { $role_name = $this->configuration['role_name']; $role_id = implode('-', [ $membership->getGroupEntityType(), - $membership->getGroup()->bundle(), + $membership->getGroupBundle(), $role_name, ]); // Only add the role if it is valid and doesn't exist yet. diff --git a/src/Plugin/Action/RemoveSingleOgMembershipRole.php b/src/Plugin/Action/RemoveSingleOgMembershipRole.php index c269bc3e2..53c70a6c3 100644 --- a/src/Plugin/Action/RemoveSingleOgMembershipRole.php +++ b/src/Plugin/Action/RemoveSingleOgMembershipRole.php @@ -25,7 +25,7 @@ public function execute(OgMembership $membership = NULL) { $role_name = $this->configuration['role_name']; $role_id = implode('-', [ $membership->getGroupEntityType(), - $membership->getGroup()->bundle(), + $membership->getGroupBundle(), $role_name, ]); // Skip removing the role from the membership if it doesn't have it. From 170d479172d256080c3b8c3dc8865958424bf123 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Wed, 20 Mar 2019 18:47:59 +0100 Subject: [PATCH 032/111] Fix tests --- tests/src/Kernel/Views/OgAdminMembersViewTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/src/Kernel/Views/OgAdminMembersViewTest.php b/tests/src/Kernel/Views/OgAdminMembersViewTest.php index 0a41fbc16..277848675 100644 --- a/tests/src/Kernel/Views/OgAdminMembersViewTest.php +++ b/tests/src/Kernel/Views/OgAdminMembersViewTest.php @@ -27,6 +27,7 @@ class OgAdminMembersViewTest extends ViewsKernelTestBase { 'field', 'node', 'og', + 'options', 'views', ]; From 4d5e9212ba4aae64329150d831c09b682e9c8979 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Thu, 18 Apr 2019 20:08:46 +0200 Subject: [PATCH 033/111] Update OgGroupContentOperationAccessTest.php --- tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php index 5a8573817..cca5740d6 100644 --- a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php +++ b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php @@ -174,7 +174,7 @@ protected function setUp() { } // Create a 'blocked' user. This user is identical to the normal - // 'authenticated' member, except that she has the 'blocked' state. + // 'authenticated' member, except that it has the 'blocked' state. $this->users['blocked'] = User::create(['name' => $this->randomString()]); $this->users['blocked']->save(); $this->createOgMembership($this->group, $this->users['blocked'], NULL, OgMembershipInterface::STATE_BLOCKED); From 1506df01211f158d8c4fb15c2a9fb7f0d6d37f44 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Thu, 18 Apr 2019 20:16:49 +0200 Subject: [PATCH 034/111] Update SelectionHandlerTest.php --- tests/src/Kernel/Entity/SelectionHandlerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/src/Kernel/Entity/SelectionHandlerTest.php b/tests/src/Kernel/Entity/SelectionHandlerTest.php index 5e84de5d4..a399bf57b 100644 --- a/tests/src/Kernel/Entity/SelectionHandlerTest.php +++ b/tests/src/Kernel/Entity/SelectionHandlerTest.php @@ -133,14 +133,14 @@ public function testSelectionHandler() { /** * Testing OG selection handler results. * - * We need to verify that each user get the groups he own in the normal widget + * We verify that each user gets the groups it owns in the normal widget * and the other users group's in the other groups widget and vice versa. */ public function testSelectionHandlerResults() { $user1_groups = $this->createGroups(2, $this->user1); $user2_groups = $this->createGroups(2, $this->user2); - // Checking that the user get the groups he mange. + // Check that the user gets the groups he manages. $this->setCurrentAccount($this->user1); $groups = $this->selectionHandler->getReferenceableEntities(); $this->assertEquals($user1_groups, array_keys($groups[$this->groupBundle])); From 790640c0a41e5e1c6d8f7bf84549827415d7ed20 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Thu, 18 Apr 2019 20:42:17 +0200 Subject: [PATCH 035/111] Update tests/src/Kernel/Entity/SelectionHandlerTest.php --- tests/src/Kernel/Entity/SelectionHandlerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Kernel/Entity/SelectionHandlerTest.php b/tests/src/Kernel/Entity/SelectionHandlerTest.php index a399bf57b..9335431ad 100644 --- a/tests/src/Kernel/Entity/SelectionHandlerTest.php +++ b/tests/src/Kernel/Entity/SelectionHandlerTest.php @@ -140,7 +140,7 @@ public function testSelectionHandlerResults() { $user1_groups = $this->createGroups(2, $this->user1); $user2_groups = $this->createGroups(2, $this->user2); - // Check that the user gets the groups he manages. + // Check that the user gets the groups it manages. $this->setCurrentAccount($this->user1); $groups = $this->selectionHandler->getReferenceableEntities(); $this->assertEquals($user1_groups, array_keys($groups[$this->groupBundle])); From 5f550c04c9164af82d314c4c96cb243d836d6c32 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Fri, 19 Apr 2019 12:37:20 +0200 Subject: [PATCH 036/111] Update tests/src/Kernel/Entity/SelectionHandlerTest.php --- tests/src/Kernel/Entity/SelectionHandlerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Kernel/Entity/SelectionHandlerTest.php b/tests/src/Kernel/Entity/SelectionHandlerTest.php index 9335431ad..6226bd34e 100644 --- a/tests/src/Kernel/Entity/SelectionHandlerTest.php +++ b/tests/src/Kernel/Entity/SelectionHandlerTest.php @@ -140,7 +140,7 @@ public function testSelectionHandlerResults() { $user1_groups = $this->createGroups(2, $this->user1); $user2_groups = $this->createGroups(2, $this->user2); - // Check that the user gets the groups it manages. + // Check that users get the groups they manage. $this->setCurrentAccount($this->user1); $groups = $this->selectionHandler->getReferenceableEntities(); $this->assertEquals($user1_groups, array_keys($groups[$this->groupBundle])); From c5da003e627b4a9a24b496712fd0a15411351a25 Mon Sep 17 00:00:00 2001 From: Amitai Burstein Date: Sun, 21 Apr 2019 18:05:18 +0200 Subject: [PATCH 037/111] Update tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php Co-Authored-By: MPParsley --- tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php index cca5740d6..782013b04 100644 --- a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php +++ b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php @@ -174,7 +174,7 @@ protected function setUp() { } // Create a 'blocked' user. This user is identical to the normal - // 'authenticated' member, except that it has the 'blocked' state. + // 'authenticated' member, except that they have the 'blocked' state. $this->users['blocked'] = User::create(['name' => $this->randomString()]); $this->users['blocked']->save(); $this->createOgMembership($this->group, $this->users['blocked'], NULL, OgMembershipInterface::STATE_BLOCKED); From 38a1ae3577a53d98c14720fe0b2c17978a639562 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Mon, 22 Apr 2019 11:20:45 +0200 Subject: [PATCH 038/111] Document technical debt. --- src/Og.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Og.php b/src/Og.php index 238ee90d1..a29d30682 100644 --- a/src/Og.php +++ b/src/Og.php @@ -337,6 +337,8 @@ public static function invalidateCache() { static::$cache = []; // Invalidate the entity property cache. + // @todo We should not clear the entity type and field definition caches. + // @see https://github.com/Gizra/og/issues/219 \Drupal::entityTypeManager()->clearCachedDefinitions(); \Drupal::service('entity_field.manager')->clearCachedFieldDefinitions(); From 05dab443db9c90f91a249ce4d76561b36ab2e417 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Mon, 22 Apr 2019 12:00:21 +0200 Subject: [PATCH 039/111] Use gender neutral language in documentation. --- .../Kernel/Access/OgGroupContentOperationAccessTest.php | 2 +- tests/src/Kernel/Entity/SelectionHandlerTest.php | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php index 5a8573817..782013b04 100644 --- a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php +++ b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php @@ -174,7 +174,7 @@ protected function setUp() { } // Create a 'blocked' user. This user is identical to the normal - // 'authenticated' member, except that she has the 'blocked' state. + // 'authenticated' member, except that they have the 'blocked' state. $this->users['blocked'] = User::create(['name' => $this->randomString()]); $this->users['blocked']->save(); $this->createOgMembership($this->group, $this->users['blocked'], NULL, OgMembershipInterface::STATE_BLOCKED); diff --git a/tests/src/Kernel/Entity/SelectionHandlerTest.php b/tests/src/Kernel/Entity/SelectionHandlerTest.php index 5e84de5d4..ac29542c8 100644 --- a/tests/src/Kernel/Entity/SelectionHandlerTest.php +++ b/tests/src/Kernel/Entity/SelectionHandlerTest.php @@ -133,14 +133,15 @@ public function testSelectionHandler() { /** * Testing OG selection handler results. * - * We need to verify that each user get the groups he own in the normal widget - * and the other users group's in the other groups widget and vice versa. + * We need to verify that each user gets the groups they own in the normal + * widget and the other users' groups in the other groups widget and vice + * versa. */ public function testSelectionHandlerResults() { $user1_groups = $this->createGroups(2, $this->user1); $user2_groups = $this->createGroups(2, $this->user2); - // Checking that the user get the groups he mange. + // Checking that the user gets the groups they manage. $this->setCurrentAccount($this->user1); $groups = $this->selectionHandler->getReferenceableEntities(); $this->assertEquals($user1_groups, array_keys($groups[$this->groupBundle])); From 0f488cf18fcec74a198dc17dde77d572d74796df Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Mon, 22 Apr 2019 12:13:18 +0200 Subject: [PATCH 040/111] Require tests to pass on Drupal 8.7. Add experimental testing on Drupal 8.8. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0b8c19376..bce5b36f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ env: matrix: - TEST_SUITE=8.6.x - TEST_SUITE=8.7.x + - TEST_SUITE=8.8.x - TEST_SUITE=PHP_CodeSniffer # Only run the coding standards check once. @@ -22,7 +23,7 @@ matrix: - php: 7.2 env: TEST_SUITE=PHP_CodeSniffer allow_failures: - - env: TEST_SUITE=8.7.x + - env: TEST_SUITE=8.8.x mysql: database: og From 2e74eddfa641eacfac8cf73611d4f821266fbad8 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Mon, 22 Apr 2019 12:46:10 +0200 Subject: [PATCH 041/111] Drupal 8.7 requires a field name to be present when creating a comment. --- tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php index 782013b04..001ec3815 100644 --- a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php +++ b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php @@ -235,6 +235,7 @@ protected function setUp() { 'comment_type' => $bundle_id, 'entity_id' => $this->group->id(), 'entity_type' => 'entity_test', + 'field_name' => 'an_imaginary_field', OgGroupAudienceHelperInterface::DEFAULT_FIELD => [['target_id' => $this->group->id()]], ]; break; From 68cc7095294852689a5fecc99641a867b0f0ea86 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Mon, 22 Apr 2019 13:40:18 +0200 Subject: [PATCH 042/111] Declare which properties are intended to be exported for membership types. This is required starting with Drupal 8.7. Ref. https://www.drupal.org/node/2949023 --- src/Entity/OgMembershipType.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Entity/OgMembershipType.php b/src/Entity/OgMembershipType.php index 821b29966..c1719c5fe 100644 --- a/src/Entity/OgMembershipType.php +++ b/src/Entity/OgMembershipType.php @@ -25,6 +25,11 @@ * entity_keys = { * "id" = "type", * "label" = "name" + * }, + * config_export = { + * "type", + * "name", + * "description" * } * ) */ From 9d76e0c1fadb83d73bfceb812868d980c072ca6f Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Mon, 22 Apr 2019 14:46:02 +0200 Subject: [PATCH 043/111] Trying to install invalid schemas for the System module has been deprecated in Drupal 8.7. Ref. https://www.drupal.org/node/3003360 --- tests/src/Kernel/Action/ActionTestBase.php | 2 +- tests/src/Kernel/GroupManagerSubscriptionTest.php | 2 +- tests/src/Kernel/GroupTypeConditionTest.php | 2 +- tests/src/Kernel/OgDeleteOrphansTest.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/src/Kernel/Action/ActionTestBase.php b/tests/src/Kernel/Action/ActionTestBase.php index adc59c38a..cb6c1a309 100644 --- a/tests/src/Kernel/Action/ActionTestBase.php +++ b/tests/src/Kernel/Action/ActionTestBase.php @@ -84,7 +84,7 @@ public function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); - $this->installSchema('system', ['queue', 'sequences']); + $this->installSchema('system', ['sequences']); $this->membershipManager = $this->container->get('og.membership_manager'); $this->groupTypeManager = $this->container->get('og.group_type_manager'); diff --git a/tests/src/Kernel/GroupManagerSubscriptionTest.php b/tests/src/Kernel/GroupManagerSubscriptionTest.php index aa932451d..a6e185dfe 100644 --- a/tests/src/Kernel/GroupManagerSubscriptionTest.php +++ b/tests/src/Kernel/GroupManagerSubscriptionTest.php @@ -63,7 +63,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', ['queue', 'sequences']); + $this->installSchema('system', ['sequences']); // Create a group type. NodeType::create([ diff --git a/tests/src/Kernel/GroupTypeConditionTest.php b/tests/src/Kernel/GroupTypeConditionTest.php index ff2c52320..bd610108a 100644 --- a/tests/src/Kernel/GroupTypeConditionTest.php +++ b/tests/src/Kernel/GroupTypeConditionTest.php @@ -61,7 +61,7 @@ protected function setUp() { $this->installEntitySchema('entity_test'); $this->installEntitySchema('node'); $this->installEntitySchema('user'); - $this->installSchema('system', ['queue', 'sequences']); + $this->installSchema('system', ['sequences']); // Create three test groups of different types. for ($i = 0; $i < 2; $i++) { diff --git a/tests/src/Kernel/OgDeleteOrphansTest.php b/tests/src/Kernel/OgDeleteOrphansTest.php index 17fa75f3c..0afe7dc24 100644 --- a/tests/src/Kernel/OgDeleteOrphansTest.php +++ b/tests/src/Kernel/OgDeleteOrphansTest.php @@ -61,7 +61,7 @@ public function setUp() { $this->installEntitySchema('user'); $this->installEntitySchema('node'); $this->installSchema('node', 'node_access'); - $this->installSchema('system', ['queue', 'sequences']); + $this->installSchema('system', ['sequences']); /** @var \Drupal\og\OgDeleteOrphansPluginManager $plugin_manager */ $plugin_manager = \Drupal::service('plugin.manager.og.delete_orphans'); From 5d4278d55b80b89b04bcfec7eb7e43bc3a023ec4 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Mon, 22 Apr 2019 14:59:58 +0200 Subject: [PATCH 044/111] The `context` annotation has been deprecated in favor of `context_definitions` in Drupal 8.7. Ref. https://www.drupal.org/node/3016699 This breaks backwards compatibility with Drupal 8.6 which does not yet support the `context_definitions` annotation. --- .travis.yml | 1 - composer.json | 2 +- src/Plugin/Condition/GroupType.php | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index bce5b36f0..c9a113c28 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ env: global: - COMPOSER_MEMORY_LIMIT=2G matrix: - - TEST_SUITE=8.6.x - TEST_SUITE=8.7.x - TEST_SUITE=8.8.x - TEST_SUITE=PHP_CodeSniffer diff --git a/composer.json b/composer.json index 22da708b0..1adee5f32 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "source": "https://cgit.drupalcode.org/og" }, "require": { - "drupal/core": "~8.6" + "drupal/core": "~8.7" }, "require-dev": { "drupal/coder": "~8.2" diff --git a/src/Plugin/Condition/GroupType.php b/src/Plugin/Condition/GroupType.php index f6a3b64bd..a80f9a982 100644 --- a/src/Plugin/Condition/GroupType.php +++ b/src/Plugin/Condition/GroupType.php @@ -16,7 +16,7 @@ * @Condition( * id = "og_group_type", * label = @Translation("Group type"), - * context = { + * context_definitions = { * "og" = @ContextDefinition("entity", label = @Translation("Group")) * } * ) From 4ca9ec70db8007a184d3048e3a764f365a67ad23 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Mon, 22 Apr 2019 15:09:32 +0200 Subject: [PATCH 045/111] Use newer versions of deprecated classes and traits. --- tests/src/Functional/OgComplexWidgetTest.php | 9 ++++----- tests/src/Kernel/Entity/EntityCreateAccessTest.php | 4 ++-- tests/src/Kernel/Views/OgAdminMembersViewTest.php | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/src/Functional/OgComplexWidgetTest.php b/tests/src/Functional/OgComplexWidgetTest.php index 1d54bc9d8..c8b565f15 100644 --- a/tests/src/Functional/OgComplexWidgetTest.php +++ b/tests/src/Functional/OgComplexWidgetTest.php @@ -7,9 +7,9 @@ use Drupal\node\Entity\Node; use Drupal\og\Og; use Drupal\og\OgGroupAudienceHelperInterface; -use Drupal\simpletest\BrowserTestBase; -use Drupal\simpletest\ContentTypeCreationTrait; -use Drupal\simpletest\NodeCreationTrait; +use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\node\Traits\ContentTypeCreationTrait; +use Drupal\Tests\node\Traits\NodeCreationTrait; /** * Tests the complex widget. @@ -88,7 +88,6 @@ public function testFields($field, $field_name) { $this->assertSession()->statusCodeEquals(200); // Retrieve the post that was created from the database. - /** @var QueryInterface $query */ $query = $this->container->get('entity_type.manager')->getStorage('node')->getQuery(); $result = $query ->condition('type', 'post') @@ -97,7 +96,7 @@ public function testFields($field, $field_name) { ->execute(); $post_nid = reset($result); - /** @var \Drupal\node\Entity\NodeInterface $post */ + /** @var \Drupal\node\NodeInterface $post */ $post = Node::load($post_nid); // Check that the post references the group correctly. diff --git a/tests/src/Kernel/Entity/EntityCreateAccessTest.php b/tests/src/Kernel/Entity/EntityCreateAccessTest.php index 0c919b11a..c135319fc 100644 --- a/tests/src/Kernel/Entity/EntityCreateAccessTest.php +++ b/tests/src/Kernel/Entity/EntityCreateAccessTest.php @@ -7,8 +7,8 @@ use Drupal\node\Entity\NodeType; use Drupal\og\Og; use Drupal\og\OgGroupAudienceHelperInterface; -use Drupal\simpletest\ContentTypeCreationTrait; -use Drupal\simpletest\NodeCreationTrait; +use Drupal\Tests\node\Traits\ContentTypeCreationTrait; +use Drupal\Tests\node\Traits\NodeCreationTrait; use Drupal\user\Entity\Role; use Drupal\user\Entity\User; diff --git a/tests/src/Kernel/Views/OgAdminMembersViewTest.php b/tests/src/Kernel/Views/OgAdminMembersViewTest.php index 277848675..5565b070b 100644 --- a/tests/src/Kernel/Views/OgAdminMembersViewTest.php +++ b/tests/src/Kernel/Views/OgAdminMembersViewTest.php @@ -5,7 +5,7 @@ use Drupal\node\Entity\Node; use Drupal\node\Entity\NodeType; use Drupal\og\Og; -use Drupal\simpletest\UserCreationTrait; +use Drupal\Tests\user\Traits\UserCreationTrait; use Drupal\Tests\views\Kernel\ViewsKernelTestBase; use Drupal\views\Views; From 67cdc1112088942f1da634a5730ae17a6e84a7c3 Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Mon, 22 Apr 2019 15:46:08 +0200 Subject: [PATCH 046/111] Allow to use release candidates for testing. --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 1adee5f32..2719c766d 100644 --- a/composer.json +++ b/composer.json @@ -14,5 +14,6 @@ }, "require-dev": { "drupal/coder": "~8.2" - } + }, + "minimum-stability": "RC" } From 13a989d72bec9308800a249039f31805caf6e4ad Mon Sep 17 00:00:00 2001 From: Pieter Frenssen Date: Tue, 23 Apr 2019 13:08:45 +0200 Subject: [PATCH 047/111] Provide a method to retrieve the membership IDs of a given group filtered by role name. This is equivalent to getGroupMembershipIdsByRoleNames() but avoids to load the full entity objects. --- src/MembershipManager.php | 11 +++- src/MembershipManagerInterface.php | 21 ++++++- .../Entity/GroupMembershipManagerTest.php | 61 +++++++++++++++++-- 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index 745166f23..d9c15ee68 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -124,7 +124,7 @@ public function getMembership(EntityInterface $group, AccountInterface $user, ar /** * {@inheritdoc} */ - public function getGroupMembershipsByRoleNames(EntityInterface $group, array $role_names, array $states = [OgMembershipInterface::STATE_ACTIVE]) { + public function getGroupMembershipIdsByRoleNames(EntityInterface $group, array $role_names, array $states = [OgMembershipInterface::STATE_ACTIVE]) { if (empty($role_names)) { throw new \InvalidArgumentException('The array of role names should not be empty.'); } @@ -171,7 +171,14 @@ public function getGroupMembershipsByRoleNames(EntityInterface $group, array $ro $this->cache[$identifier] = $query->execute(); } - return $this->loadMemberships($this->cache[$identifier]); + return $this->cache[$identifier]; + } + + /** + * {@inheritdoc} + */ + public function getGroupMembershipsByRoleNames(EntityInterface $group, array $role_names, array $states = [OgMembershipInterface::STATE_ACTIVE]) { + return $this->loadMemberships($this->getGroupMembershipIdsByRoleNames($group, $role_names, $states)); } /** diff --git a/src/MembershipManagerInterface.php b/src/MembershipManagerInterface.php index 8192bc1a0..64674eb54 100644 --- a/src/MembershipManagerInterface.php +++ b/src/MembershipManagerInterface.php @@ -88,13 +88,32 @@ public function getMemberships(AccountInterface $user, array $states = [OgMember */ public function getMembership(EntityInterface $group, AccountInterface $user, array $states = [OgMembershipInterface::STATE_ACTIVE]); + /** + * Returns the membership IDs of the given group filtered by role name. + * + * @param \Drupal\Core\Entity\EntityInterface $group + * The group entity for which to return the memberships. + * @param array $role_names + * An array of role names to filter by. In order to retrieve a list of all + * membership IDs, pass `[OgRoleInterface::AUTHENTICATED]`. + * @param array $states + * (optional) Array with the states to return. Defaults to only returning + * active membership IDs. In order to retrieve all membership IDs regardless + * of state, pass `OgMembershipInterface::ALL_STATES`. + * + * @return \Drupal\Core\Entity\EntityInterface[] + * The membership entities. + */ + public function getGroupMembershipIdsByRoleNames(EntityInterface $group, array $role_names, array $states = [OgMembershipInterface::STATE_ACTIVE]); + /** * Returns the memberships of the given group filtered by role name. * * @param \Drupal\Core\Entity\EntityInterface $group * The group entity for which to return the memberships. * @param array $role_names - * An array of role names to filter by. + * An array of role names to filter by. In order to retrieve a list of all + * memberships, pass `[OgRoleInterface::AUTHENTICATED]`. * @param array $states * (optional) Array with the states to return. Defaults to only returning * active memberships. In order to retrieve all memberships regardless of diff --git a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php index ee62142bf..f18c06ee6 100644 --- a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php +++ b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php @@ -335,11 +335,47 @@ public function groupContentProvider() { * @covers ::getGroupMembershipsByRoleNames */ public function testGetGroupMembershipsByRoleNames() { + $retrieve_membership_owner_id = function (OgMembershipInterface $membership) { + return $membership->getOwnerId(); + }; + $this->doTestGetGroupMembershipsByRoleNames('getGroupMembershipsByRoleNames', $retrieve_membership_owner_id); + } + + /** + * Tests retrieval of group membership IDs filtered by role names. + * + * @covers ::getGroupMembershipIdsByRoleNames + */ + public function testGetGroupMembershipIdsByRoleNames() { + $membership_storage = $this->container->get('entity_type.manager')->getStorage('og_membership'); + $retrieve_membership_owner_id = function ($membership_id) use ($membership_storage) { + /** @var \Drupal\og\OgMembershipInterface $membership */ + $membership = $membership_storage->load($membership_id); + return $membership->getOwnerId(); + }; + $this->doTestGetGroupMembershipsByRoleNames('getGroupMembershipIdsByRoleNames', $retrieve_membership_owner_id); + } + + /** + * Tests retrieval of group memberships or their IDs filtered by role names. + * + * Contains the actual test logic of ::testGetGroupMembershipsByRoleNames() + * and ::testGetGroupMembershipIdsByRoleNames(). + * + * @param string $method_name + * The name of the method under test. Can be one of the following: + * - 'getGroupMembershipIdsByRoleNames' + * - 'getGroupMembershipsByRoleNames'. + * @param callable $retrieve_membership_owner_id + * A callable that will retrieve the ID of the owner of the membership or + * membership ID. + */ + protected function doTestGetGroupMembershipsByRoleNames($method_name, callable $retrieve_membership_owner_id) { $this->createTestMemberships(); // Check that an exception is thrown if no role names are passed. try { - $this->membershipManager->getGroupMembershipsByRoleNames($this->groups['node'][0], []); + $this->membershipManager->$method_name($this->groups['node'][0], []); $this->fail('MembershipManager::getGroupsMembershipsByRoleNames() throws an exception when called without passing any role names.'); } catch (\InvalidArgumentException $e) { @@ -348,6 +384,23 @@ public function testGetGroupMembershipsByRoleNames() { // Define a test matrix to iterate over. We're not using a data provider // because the large number of test cases would slow down the test too much. + // The test matrix has the following structure: + // @code + // [ + // // The machine name of the group entity type being tested. + // {entity_type_id} => [ + // // The key of the test group as created in ::setUp(). + // {group_key} => [ // + // // The roles being passed to the method. + // 'roles' => [{role_id}], + // // The membership states being passed to the method. + // 'states' => [{state_id}], + // // The memberships that should be returned by the method. + // 'expected_memberships' => [{expected_membership_id}], + // ], + // ], + // ]; + // @endcode $matrix = [ 'node' => [ 0 => [ @@ -496,15 +549,13 @@ public function testGetGroupMembershipsByRoleNames() { $states = $test_case['states']; $expected_memberships = $test_case['expected_memberships']; - /** @var \Drupal\og\OgMembershipInterface[] $actual_memberships */ - $actual_memberships = $this->membershipManager->getGroupMembershipsByRoleNames($group, $role_names, $states); - + $actual_memberships = $this->membershipManager->$method_name($group, $role_names, $states); $this->assertSameSize($expected_memberships, $actual_memberships); foreach ($expected_memberships as $expected_membership_key) { $expected_user_id = $this->users[$expected_membership_key]->id(); foreach ($actual_memberships as $actual_membership) { - if ($actual_membership->getOwnerId() == $expected_user_id) { + if ($retrieve_membership_owner_id($actual_membership) == $expected_user_id) { // Match found. continue 2; } From 7fd066edd1309d11032125585f481cb0ab3f5363 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Tue, 23 Apr 2019 13:40:58 +0200 Subject: [PATCH 048/111] Update views.view.og_members_overview.yml --- config/optional/views.view.og_members_overview.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/optional/views.view.og_members_overview.yml b/config/optional/views.view.og_members_overview.yml index 73f78e701..9f851c2ce 100644 --- a/config/optional/views.view.og_members_overview.yml +++ b/config/optional/views.view.og_members_overview.yml @@ -25,7 +25,7 @@ display: access: type: perm options: - perm: 'access content' + perm: 'access user profiles' cache: type: none options: { } From 8997552a430d0e0b057e8c7720f07e34dae96eeb Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Tue, 23 Apr 2019 13:55:35 +0200 Subject: [PATCH 049/111] Apply suggestions from code review Co-Authored-By: pfrenssen --- src/MembershipManager.php | 3 ++- src/MembershipManagerInterface.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index d9c15ee68..6e03f7395 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -178,7 +178,8 @@ public function getGroupMembershipIdsByRoleNames(EntityInterface $group, array $ * {@inheritdoc} */ public function getGroupMembershipsByRoleNames(EntityInterface $group, array $role_names, array $states = [OgMembershipInterface::STATE_ACTIVE]) { - return $this->loadMemberships($this->getGroupMembershipIdsByRoleNames($group, $role_names, $states)); + $ids = $this->getGroupMembershipIdsByRoleNames($group, $role_names, $states); + return $this->loadMemberships($ids); } /** diff --git a/src/MembershipManagerInterface.php b/src/MembershipManagerInterface.php index 64674eb54..c987128bf 100644 --- a/src/MembershipManagerInterface.php +++ b/src/MembershipManagerInterface.php @@ -89,7 +89,7 @@ public function getMemberships(AccountInterface $user, array $states = [OgMember public function getMembership(EntityInterface $group, AccountInterface $user, array $states = [OgMembershipInterface::STATE_ACTIVE]); /** - * Returns the membership IDs of the given group filtered by role name. + * Returns the membership IDs of the given group filtered by role names. * * @param \Drupal\Core\Entity\EntityInterface $group * The group entity for which to return the memberships. From 85a76b6fa0cc9f7f7381645a1bdc610089f35ee1 Mon Sep 17 00:00:00 2001 From: Maarten Segers Date: Tue, 23 Apr 2019 16:38:48 +0200 Subject: [PATCH 050/111] 433 Remove deprecated setting for use_queue --- og_ui/src/Form/AdminSettingsForm.php | 1 - 1 file changed, 1 deletion(-) diff --git a/og_ui/src/Form/AdminSettingsForm.php b/og_ui/src/Form/AdminSettingsForm.php index ef8d86cf0..57ba41f70 100644 --- a/og_ui/src/Form/AdminSettingsForm.php +++ b/og_ui/src/Form/AdminSettingsForm.php @@ -145,7 +145,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $this->config('og.settings') ->set('group_manager_full_access', $form_state->getValue('og_group_manager_full_access')) ->set('node_access_strict', $form_state->getValue('og_node_access_strict')) - ->set('use_queue', $form_state->getValue('og_use_queue')) ->set('delete_orphans', $form_state->getValue('og_delete_orphans')) ->set('delete_orphans_plugin_id', $form_state->getValue('og_delete_orphans_plugin_id')) ->save(); From ce403417b04f50eb724461312ebf052ec211cef8 Mon Sep 17 00:00:00 2001 From: Insasse Date: Fri, 16 Nov 2018 15:48:38 +0100 Subject: [PATCH 051/111] fix plugin not found exception during kernel tests --- src/Plugin/Field/FieldType/OgListString.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/Plugin/Field/FieldType/OgListString.php diff --git a/src/Plugin/Field/FieldType/OgListString.php b/src/Plugin/Field/FieldType/OgListString.php new file mode 100644 index 000000000..3b15cf6e0 --- /dev/null +++ b/src/Plugin/Field/FieldType/OgListString.php @@ -0,0 +1,21 @@ + label' pairs, i.e. 'US States': IL => Illinois, IA => Iowa, IN => Indiana."), + * category = @Translation("Text"), + * default_widget = "options_select", + * default_formatter = "list_default", + * ) + */ +class OgListString extends ListStringItem { + +} From 7b8845b414173a5b7fae3b0d15736d8dead6dcc4 Mon Sep 17 00:00:00 2001 From: Justin Ludwig Date: Tue, 10 Jan 2017 18:36:57 -0800 Subject: [PATCH 052/111] Adds basic UI for adding, editing and removing group memberships --- og.links.task.yml | 13 +++++ og.routing.yml | 25 +++++++++ src/Controller/OgAdminMembersController.php | 28 ++++++++++ src/Entity/OgMembership.php | 42 ++++++++++++-- src/Event/OgAdminRoutesEvent.php | 8 ++- src/EventSubscriber/OgEventSubscriber.php | 19 +++++++ src/Form/OgMembershipDeleteForm.php | 54 ++++++++++++++++++ src/Form/OgMembershipForm.php | 50 +++++++++++++++++ .../OgRoleSelection.php | 56 +++++++++++++++++++ 9 files changed, 288 insertions(+), 7 deletions(-) create mode 100644 src/Form/OgMembershipDeleteForm.php create mode 100644 src/Form/OgMembershipForm.php create mode 100644 src/Plugin/EntityReferenceSelection/OgRoleSelection.php diff --git a/og.links.task.yml b/og.links.task.yml index 854c7df83..2b013250d 100644 --- a/og.links.task.yml +++ b/og.links.task.yml @@ -1,2 +1,15 @@ og.og_admin_routes: deriver: \Drupal\og\Plugin\Derivative\OgLocalTask +entity.og_membership.canonical: + route_name: entity.og_membership.canonical + base_route: entity.og_membership.canonical + title: View +entity.og_membership.edit_form: + route_name: entity.og_membership.edit_form + base_route: entity.og_membership.canonical + title: Edit +entity.og_membership.delete_form: + route_name: entity.og_membership.delete_form + base_route: entity.og_membership.canonical + title: Delete + weight: 10 diff --git a/og.routing.yml b/og.routing.yml index 06a78558e..b34566143 100644 --- a/og.routing.yml +++ b/og.routing.yml @@ -43,3 +43,28 @@ og.remove_multiple_roles_confirm: _form: '\Drupal\og\Form\OgRemoveMultipleRolesForm' requirements: _custom_access: '\Drupal\og\Form\OgRemoveMultipleRolesForm::access' + +entity.og_membership.canonical: + path: 'group/{entity_type_id}/{group}/admin/membership/{og_membership}' + defaults: + _title: 'Membership' + _entity_view: 'og_membership.full' + requirements: + _permission: 'administer group' + options: + parameters: + type: entity:{entity_type_id} + +entity.og_membership.edit_form: + path: 'group/{entity_type_id}/{group}/admin/membership/{og_membership}/edit' + defaults: + _entity_form: 'og_membership.edit' + requirements: + _permission: 'administer group' + +entity.og_membership.delete_form: + path: 'group/{entity_type_id}/{group}/admin/membership/{og_membership}/delete' + defaults: + _entity_form: 'og_membership.delete' + requirements: + _permission: 'administer group' diff --git a/src/Controller/OgAdminMembersController.php b/src/Controller/OgAdminMembersController.php index 9eb723aea..67b5256ff 100644 --- a/src/Controller/OgAdminMembersController.php +++ b/src/Controller/OgAdminMembersController.php @@ -4,6 +4,7 @@ use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\og\Entity\OgMembership; use Drupal\views\Views; /** @@ -30,4 +31,31 @@ public function membersList(RouteMatchInterface $route_match) { return Views::getView('og_members_overview')->executeDisplay('default', $arguments); } + /** + * Provides the add member submission form. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match service. + * + * @return array + * The member add form. + */ + public function addMember(RouteMatchInterface $route_match) { + /** @var \Drupal\og\Entity\OgMembershipType $membership_type */ + $membership_type = $route_match->getParameter('membership_type'); + $group_type_id = $route_match->getRouteObject()->getOption('_og_entity_type_id'); + + /** @var \Drupal\Core\Entity\EntityInterface $group */ + $group = $route_match->getParameter($group_type_id); + + /** @var \Drupal\og\Entity\OgMembership $og_membership */ + $og_membership = OgMembership::create([ + 'type' => $membership_type->id(), + 'entity_type' => $group->getEntityType()->id(), + 'entity_id' => $group->id(), + ]); + + return $this->entityFormBuilder()->getForm($og_membership, 'add'); + } + } diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index 668340c7e..bad2852c7 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -67,15 +67,35 @@ * }, * handlers = { * "views_data" = "Drupal\og\OgMembershipViewsData", + * "list_builder" = "Drupal\Core\Entity\EntityListBuilder", + * "view_builder" = "Drupal\Core\Entity\EntityViewBuilder", * "form" = { * "subscribe" = "Drupal\og\Form\GroupSubscribeForm", * "unsubscribe" = "Drupal\og\Form\GroupUnsubscribeConfirmForm", + * "add" = "Drupal\og\Form\OgMembershipForm", + * "edit" = "Drupal\og\Form\OgMembershipForm", + * "delete" = "Drupal\og\Form\OgMembershipDeleteForm", * }, + * }, + * links = { + * "edit-form" = "/group/{entity_type_id}/{group}/admin/membership/{og_membership}/edit", + * "delete-form" = "/group/{entity_type_id}/{group}/admin/membership/{og_membership}/delete", + * "canonical" = "/group/{entity_type_id}/{group}/admin/membership/{og_membership}" * } * ) */ class OgMembership extends ContentEntityBase implements OgMembershipInterface { + /** + * {@inheritdoc} + */ + protected function urlRouteParameters($rel) { + $uri_route_parameters = parent::urlRouteParameters($rel); + $uri_route_parameters['entity_type_id'] = $this->getGroupEntityType(); + $uri_route_parameters['group'] = $this->getGroupId(); + return $uri_route_parameters; + } + /** * {@inheritdoc} */ @@ -358,7 +378,19 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields['uid'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Member User ID')) ->setDescription(t('The user ID of the member.')) - ->setSetting('target_type', 'user'); + ->setSetting('target_type', 'user') + ->setDisplayOptions('form', [ + 'type' => 'entity_reference_autocomplete', + 'weight' => -1, + 'settings' => [ + 'match_operator' => 'CONTAINS', + 'size' => '60', + 'placeholder' => '', + ], + ]) + ->setDisplayConfigurable('view', TRUE) + ->setDisplayConfigurable('form', TRUE) + ->setRequired(TRUE); $fields['entity_type'] = BaseFieldDefinition::create('string') ->setLabel(t('Group entity type')) @@ -381,12 +413,14 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setLabel(t('Roles')) ->setDescription(t('The OG roles related to an OG membership entity.')) ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) - ->setDisplayOptions('view', [ - 'label' => 'hidden', - 'type' => 'entity_reference_label', + ->setDisplayOptions('form', [ + 'type' => 'options_buttons', 'weight' => 0, ]) ->setSetting('target_type', 'og_role'); + ->setSetting('handler', 'og:og_role') + ->setDisplayConfigurable('view', TRUE) + ->setDisplayConfigurable('form', TRUE); $fields['created'] = BaseFieldDefinition::create('created') ->setLabel(t('Create')) diff --git a/src/Event/OgAdminRoutesEvent.php b/src/Event/OgAdminRoutesEvent.php index 575ccf90c..bb506ee9d 100644 --- a/src/Event/OgAdminRoutesEvent.php +++ b/src/Event/OgAdminRoutesEvent.php @@ -2,6 +2,7 @@ namespace Drupal\og\Event; +use Drupal\Component\Utility\NestedArray; use Symfony\Component\EventDispatcher\Event; /** @@ -40,8 +41,9 @@ public function getRoutes($entity_type_id) { $routes_info[$name] = $route_info; - // Add default values. - $routes_info[$name] += [ + // Add default values. NestedArray::mergeDeep allows deep data to not be + // overwritten with the defaults. + $routes_info[$name] = NestedArray::mergeDeep($routes_info[$name], [ 'description' => '', 'requirements' => [ @@ -63,7 +65,7 @@ public function getRoutes($entity_type_id) { '_controller' => $route_info['controller'], '_title' => $route_info['title'], ], - ]; + ]); } return $routes_info; diff --git a/src/EventSubscriber/OgEventSubscriber.php b/src/EventSubscriber/OgEventSubscriber.php index 3463cd3f2..c8c2c0b05 100644 --- a/src/EventSubscriber/OgEventSubscriber.php +++ b/src/EventSubscriber/OgEventSubscriber.php @@ -363,6 +363,25 @@ public function provideOgAdminRoutes(OgAdminRoutesEventInterface $event) { ], ]; + $routes_info['add_membership'] = [ + 'controller' => '\Drupal\og\Controller\OgAdminMembersController::addMember', + 'title' => 'Add members', + 'path' => 'membership/add/{membership_type}', + 'defaults' => [ + 'membership_type' => 'default', + ], + 'requirements' => [ + '_og_user_access_group' => 'administer group', + ], + 'options' => [ + 'parameters' => [ + 'membership_type' => [ + 'type' => 'entity:og_membership_type', + ], + ], + ], + ]; + $event->setRoutesInfo($routes_info); } diff --git a/src/Form/OgMembershipDeleteForm.php b/src/Form/OgMembershipDeleteForm.php new file mode 100644 index 000000000..b5cb2b77e --- /dev/null +++ b/src/Form/OgMembershipDeleteForm.php @@ -0,0 +1,54 @@ +getEntity(); + + return $this->t("%user has been unsubscribed from %group.", [ + '%user' => $membership->getUser()->getDisplayName(), + '%group' => $membership->getGroup()->label(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function logDeletionMessage() { + /** @var \Drupal\og\Entity\OgMembership $entity */ + $membership = $this->getEntity(); + + $this->logger('og')->notice("OG Membership: Deleted the @membership_type membership for the user uid: @uid to the group of the entity-type @group_type and ID: @gid", [ + '@membership_type' => $membership->getType(), + '@uid' => $membership->getUser()->id(), + '@group_type' => $membership->getGroupEntityType(), + '@gid' => $membership->getGroupId(), + ]); + } + + /** + * {@inheritdoc} + */ + public function getQuestion() { + /** @var \Drupal\og\Entity\OgMembership $entity */ + $membership = $this->getEntity(); + + return $this->t("Are you sure you want to unsubscribe %user from %group?", [ + '%user' => $membership->getUser()->getDisplayName(), + '%group' => $membership->getGroup()->label(), + ]); + } + +} diff --git a/src/Form/OgMembershipForm.php b/src/Form/OgMembershipForm.php new file mode 100644 index 000000000..1f35cbeea --- /dev/null +++ b/src/Form/OgMembershipForm.php @@ -0,0 +1,50 @@ +getEntity(); + + $form['#title'] = $this->t('Add member to %group', ['%group' => $entity->getGroup()->label()]); + $form['entity_type'] = ['#value' => $entity->getEntityType()->id()]; + $form['entity_id'] = ['#value' => $entity->getGroup()->id()]; + + if ($entity->getType() != 'default') { + $form['membership_type'] = [ + '#title' => $this->t('Membership type'), + '#type' => 'item', + '#markup' => $entity->type->entity->label(), + '#weight' => -2, + ]; + } + + if ($this->operation == 'edit') { + $form['#title'] = $this->t('Edit membership in %group', ['%group' => $entity->getGroup()->label()]); + $form['uid']['#access'] = FALSE; + $form['member'] = [ + '#title' => t('Member name'), + '#type' => 'item', + '#markup' => $entity->getUser()->getDisplayName(), + '#weight' => -10, + ]; + } + + return $form; + } + +} diff --git a/src/Plugin/EntityReferenceSelection/OgRoleSelection.php b/src/Plugin/EntityReferenceSelection/OgRoleSelection.php new file mode 100644 index 000000000..cd3cc42fa --- /dev/null +++ b/src/Plugin/EntityReferenceSelection/OgRoleSelection.php @@ -0,0 +1,56 @@ + 'og_role', + ]; + return \Drupal::service('plugin.manager.entity_reference_selection')->getInstance($options); + } + + /** + * {@inheritdoc} + */ + protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') { + $query = parent::buildEntityQuery($match, $match_operator); + + $entity = $this->configuration['entity']; + // The entity does not always exist, for example during validation. + // @todo figure out how to always add the full conditions, especially if + // this can be abused to reference incompatible roles. + if (is_null($entity)) { + return $query; + } + + $group_type = $entity->getGroupEntityType(); + $group_bundle = $entity->getGroup()->bundle(); + $query->condition('group_type', $group_type, '='); + $query->condition('group_bundle', $group_bundle, '='); + $query->condition($query->orConditionGroup() + ->condition('role_type', NULL, 'IS NULL') + ->condition('role_type', 'required', '<>')); + return $query; + } + +} From 9c01614dec34fa3b9624232365ae3babd9056525 Mon Sep 17 00:00:00 2001 From: Justin Ludwig Date: Mon, 30 Jan 2017 10:36:44 -0800 Subject: [PATCH 053/111] Adds a bit of polish to the membership UI: including adding operation links to the membership overview view and more finely tuning access control --- ..._display.og_membership.default.default.yml | 13 ++++ ..._display.og_membership.default.default.yml | 16 ++++- .../views.view.og_members_overview.yml | 51 ++++++++++++++++ og.links.action.yml | 5 ++ og.module | 41 +++++++++++++ og.routing.yml | 12 ++-- src/Controller/OgController.php | 61 +++++++++++++++++++ src/Entity/OgMembership.php | 8 +-- src/EventSubscriber/OgEventSubscriber.php | 7 ++- src/Form/OgMembershipForm.php | 14 ++++- 10 files changed, 211 insertions(+), 17 deletions(-) create mode 100644 og.links.action.yml create mode 100644 src/Controller/OgController.php diff --git a/config/install/core.entity_form_display.og_membership.default.default.yml b/config/install/core.entity_form_display.og_membership.default.default.yml index 08b77f3bf..1a3300f39 100644 --- a/config/install/core.entity_form_display.og_membership.default.default.yml +++ b/config/install/core.entity_form_display.og_membership.default.default.yml @@ -18,4 +18,17 @@ content: rows: 2 placeholder: '' third_party_settings: { } + roles: + type: options_buttons + weight: 0 + settings: { } + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: -1 + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } hidden: { } diff --git a/config/install/core.entity_view_display.og_membership.default.default.yml b/config/install/core.entity_view_display.og_membership.default.default.yml index 4d19f8b4e..468f4dd18 100644 --- a/config/install/core.entity_view_display.og_membership.default.default.yml +++ b/config/install/core.entity_view_display.og_membership.default.default.yml @@ -14,7 +14,21 @@ content: og_membership_request: label: above type: basic_string - weight: 0 + weight: 2 settings: { } third_party_settings: { } + roles: + type: entity_reference_label + weight: 1 + label: above + settings: + link: false + third_party_settings: { } + uid: + type: entity_reference_label + weight: 0 + label: above + settings: + link: true + third_party_settings: { } hidden: { } diff --git a/config/optional/views.view.og_members_overview.yml b/config/optional/views.view.og_members_overview.yml index 9f851c2ce..cf158dae4 100644 --- a/config/optional/views.view.og_members_overview.yml +++ b/config/optional/views.view.og_members_overview.yml @@ -426,6 +426,57 @@ display: entity_type: og_membership entity_field: roles plugin_id: field + operations: + id: operations + table: og_membership + field: operations + relationship: none + group_type: group + admin_label: '' + label: 'Operations links' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + destination: true + entity_type: og_membership + plugin_id: entity_operations filters: { } sorts: { } header: { } diff --git a/og.links.action.yml b/og.links.action.yml new file mode 100644 index 000000000..b83b68f6d --- /dev/null +++ b/og.links.action.yml @@ -0,0 +1,5 @@ +og_membership.add: + route_name: entity.node.og_admin_routes.add_membership + title: 'Add a member' + appears_on: + - entity.node.og_admin_routes.members diff --git a/og.module b/og.module index a4cba3e1c..825738181 100755 --- a/og.module +++ b/og.module @@ -173,6 +173,23 @@ function og_entity_access(EntityInterface $entity, $operation, AccountInterface return AccessResult::forbidden(); } +/** + * Implements hook_ENTITY_TYPE_access(). + */ +function og_og_membership_access(EntityInterface $entity, $operation, AccountInterface $account) { + $group = $entity->getGroup(); + + // If the user has permission to administer all groups, allow access. + if ($account->hasPermission('administer group')) { + return AccessResult::allowed(); + } + + // Someone with the manage members permission should be able to do pretty much + // anything with memberships. + // @TODO: if this turns out to be untrue, do some operation checking. + return \Drupal::service('og.access')->userAccess($group, 'manage members', $account); +} + /** * Implements hook_entity_create_access(). */ @@ -225,6 +242,30 @@ function og_entity_create_access(AccountInterface $account, array $context, $bun return $required ? AccessResult::forbiddenIf($node_access_strict) : AccessResult::neutral(); } +/** + * Implements hook_ENTITY_TYPE_entity_create_access(). + */ +function og_og_membership_create_access(AccountInterface $account, array $context, $bundle) { + // If the user has permission to administer all groups, allow access. + if ($account->hasPermission('administer group')) { + return AccessResult::allowed(); + } + + $group = $entity->getGroup(); + + // If we don't have a group, we can't really determine access other than + // checking global account permissions. + if ($group === NULL) { + return AccessResult::neutral(); + } + + $add_users = \Drupal::service('og.access')->userAccess($group, 'add user', $account); + if ($add_users->isAllowed()) { + return $add_users; + } + return \Drupal::service('og.access')->userAccess($group, 'manage members', $account); +} + /** * Implements hook_entity_bundle_field_info(). * diff --git a/og.routing.yml b/og.routing.yml index b34566143..aca397880 100644 --- a/og.routing.yml +++ b/og.routing.yml @@ -45,26 +45,26 @@ og.remove_multiple_roles_confirm: _custom_access: '\Drupal\og\Form\OgRemoveMultipleRolesForm::access' entity.og_membership.canonical: - path: 'group/{entity_type_id}/{group}/admin/membership/{og_membership}' + path: 'group/{entity_type_id}/{group}/admin/members/{og_membership}' defaults: _title: 'Membership' _entity_view: 'og_membership.full' requirements: - _permission: 'administer group' + _entity_access: 'og_membership.view' options: parameters: type: entity:{entity_type_id} entity.og_membership.edit_form: - path: 'group/{entity_type_id}/{group}/admin/membership/{og_membership}/edit' + path: 'group/{entity_type_id}/{group}/admin/members/{og_membership}/edit' defaults: _entity_form: 'og_membership.edit' requirements: - _permission: 'administer group' + _entity_access: 'og_membership.edit' entity.og_membership.delete_form: - path: 'group/{entity_type_id}/{group}/admin/membership/{og_membership}/delete' + path: 'group/{entity_type_id}/{group}/admin/members/{og_membership}/delete' defaults: _entity_form: 'og_membership.delete' requirements: - _permission: 'administer group' + _entity_access: 'og_membership.delete' diff --git a/src/Controller/OgController.php b/src/Controller/OgController.php new file mode 100644 index 000000000..29c75d903 --- /dev/null +++ b/src/Controller/OgController.php @@ -0,0 +1,61 @@ +getRouteObject()->getOption('_og_entity_type_id'); + + /** @var \Drupal\Core\Entity\EntityInterface $group */ + $group = $route_match->getParameter($parameter_name); + + $arguments = [$group->getEntityTypeId(), $group->id()]; + return Views::getView('og_members_overview')->executeDisplay('default', $arguments); + } + + /** + * Provides the add member submission form. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match service. + * + * @return array + * The member add form. + */ + public function addMember(RouteMatchInterface $route_match) { + /** @var \Drupal\og\Entity\OgMembershipType $membership_type */ + //$membership_type = $route_match->getParameter('membership_type'); + //$group_type_id = $route_match->getRouteObject()->getOption('_og_entity_type_id'); + + /** @var \Drupal\Core\Entity\EntityInterface $group */ + //$group = $route_match->getParameter($group_type_id); + + /** @var \Drupal\og\Entity\OgMembership $og_membership */ + $og_membership = OgMembership::create([ + 'type' => 'default', + 'entity_type' => 'node', + 'entity_id' => 8, + ]); + + return $this->entityFormBuilder()->getForm($og_membership, 'add'); + } + +} diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index bad2852c7..04ae47cce 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -78,9 +78,9 @@ * }, * }, * links = { - * "edit-form" = "/group/{entity_type_id}/{group}/admin/membership/{og_membership}/edit", - * "delete-form" = "/group/{entity_type_id}/{group}/admin/membership/{og_membership}/delete", - * "canonical" = "/group/{entity_type_id}/{group}/admin/membership/{og_membership}" + * "edit-form" = "/group/{entity_type_id}/{group}/admin/members/{og_membership}/edit", + * "delete-form" = "/group/{entity_type_id}/{group}/admin/members/{og_membership}/delete", + * "canonical" = "/group/{entity_type_id}/{group}/admin/members/{og_membership}" * } * ) */ @@ -384,7 +384,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { 'weight' => -1, 'settings' => [ 'match_operator' => 'CONTAINS', - 'size' => '60', + 'size' => 60, 'placeholder' => '', ], ]) diff --git a/src/EventSubscriber/OgEventSubscriber.php b/src/EventSubscriber/OgEventSubscriber.php index c8c2c0b05..859fbe933 100644 --- a/src/EventSubscriber/OgEventSubscriber.php +++ b/src/EventSubscriber/OgEventSubscriber.php @@ -357,7 +357,7 @@ public function provideOgAdminRoutes(OgAdminRoutesEventInterface $event) { 'description' => 'Manage members', 'path' => 'members', 'requirements' => [ - '_og_user_access_group' => 'administer group', + '_og_user_access_group' => 'administer group|manage members', // Views module must be enabled. '_module_dependencies' => 'views', ], @@ -366,12 +366,13 @@ public function provideOgAdminRoutes(OgAdminRoutesEventInterface $event) { $routes_info['add_membership'] = [ 'controller' => '\Drupal\og\Controller\OgAdminMembersController::addMember', 'title' => 'Add members', - 'path' => 'membership/add/{membership_type}', + 'path' => 'members/add/{membership_type}', 'defaults' => [ 'membership_type' => 'default', ], + // @TODO switch to an entity create access callback once it works better. 'requirements' => [ - '_og_user_access_group' => 'administer group', + '_og_user_access_group' => 'administer group|manage members|add user', ], 'options' => [ 'parameters' => [ diff --git a/src/Form/OgMembershipForm.php b/src/Form/OgMembershipForm.php index 1f35cbeea..d2eb6a47b 100644 --- a/src/Form/OgMembershipForm.php +++ b/src/Form/OgMembershipForm.php @@ -18,11 +18,14 @@ class OgMembershipForm extends ContentEntityForm { public function form(array $form, FormStateInterface $form_state) { $form = parent::form($form, $form_state); + /** @var \Drupal\og\Entity\OgMembership $entity */ $entity = $this->getEntity(); + /** @var \Drupal\Core\Entity\ContentEntityInterface $group */ + $group = $entity->getGroup(); - $form['#title'] = $this->t('Add member to %group', ['%group' => $entity->getGroup()->label()]); + $form['#title'] = $this->t('Add member to %group', ['%group' => $group->label()]); $form['entity_type'] = ['#value' => $entity->getEntityType()->id()]; - $form['entity_id'] = ['#value' => $entity->getGroup()->id()]; + $form['entity_id'] = ['#value' => $group->id()]; if ($entity->getType() != 'default') { $form['membership_type'] = [ @@ -34,7 +37,7 @@ public function form(array $form, FormStateInterface $form_state) { } if ($this->operation == 'edit') { - $form['#title'] = $this->t('Edit membership in %group', ['%group' => $entity->getGroup()->label()]); + $form['#title'] = $this->t('Edit membership in %group', ['%group' => $group->label()]); $form['uid']['#access'] = FALSE; $form['member'] = [ '#title' => t('Member name'), @@ -44,6 +47,11 @@ public function form(array $form, FormStateInterface $form_state) { ]; } + // Require the 'manage members' permission to be able to edit roles. + $form['roles']['#access'] = \Drupal::service('og.access') + ->userAccess($group, 'manage members') + ->isAllowed(); + return $form; } From c4781e8f047c91f980560a66fef1474f182828c6 Mon Sep 17 00:00:00 2001 From: Justin Ludwig Date: Mon, 30 Jan 2017 11:47:56 -0800 Subject: [PATCH 054/111] Adds PR #222 since they work well together and this avoids merge conflicts --- og.links.action.yml | 6 ++ og.links.menu.yml | 5 ++ og.routing.yml | 32 +++++++ src/Entity/OgMembership.php | 3 +- src/Entity/OgMembershipType.php | 15 ++++ src/Form/OgMembershipTypeForm.php | 128 ++++++++++++++++++++++++++++ src/OgMembershipTypeListBuilder.php | 55 ++++++++++++ 7 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 og.links.menu.yml create mode 100644 src/Form/OgMembershipTypeForm.php create mode 100644 src/OgMembershipTypeListBuilder.php diff --git a/og.links.action.yml b/og.links.action.yml index b83b68f6d..3bd58d842 100644 --- a/og.links.action.yml +++ b/og.links.action.yml @@ -3,3 +3,9 @@ og_membership.add: title: 'Add a member' appears_on: - entity.node.og_admin_routes.members + +og_membership.type_add: + route_name: og_membership.type_add + title: 'Add membership type' + appears_on: + - entity.og_membership_type.collection diff --git a/og.links.menu.yml b/og.links.menu.yml new file mode 100644 index 000000000..b91d6607f --- /dev/null +++ b/og.links.menu.yml @@ -0,0 +1,5 @@ +entity.og_membership_type.collection: + title: 'Membership types' + parent: system.admin_structure + description: 'Create and manage fields, forms, and display settings for OG memberships.' + route_name: entity.og_membership_type.collection diff --git a/og.routing.yml b/og.routing.yml index aca397880..0d00f4c1f 100644 --- a/og.routing.yml +++ b/og.routing.yml @@ -68,3 +68,35 @@ entity.og_membership.delete_form: _entity_form: 'og_membership.delete' requirements: _entity_access: 'og_membership.delete' + +entity.og_membership_type.collection: + path: '/admin/structure/membership-types' + defaults: + _entity_list: 'og_membership_type' + _title: 'Membership types' + requirements: + _permission: 'administer group' + +entity.og_membership_type.edit_form: + path: '/admin/structure/membership-types/manage/{og_membership_type}' + defaults: + _entity_form: 'og_membership_type.edit' + requirements: + _permission: 'administer group' + + +entity.og_membership_type.delete_form: + path: '/admin/structure/membership-types/manage/{og_membership_type}/delete' + defaults: + _entity_form: 'og_membership_type.delete' + _title: 'Delete' + requirements: + _entity_access: 'og_membership_type.delete' + +og_membership.type_add: + path: '/admin/structure/membership-types/add' + defaults: + _entity_form: 'og_membership_type.add' + _title: 'Add membership type' + requirements: + _permission: 'administer group' diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index 04ae47cce..4e9133ba0 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -81,7 +81,8 @@ * "edit-form" = "/group/{entity_type_id}/{group}/admin/members/{og_membership}/edit", * "delete-form" = "/group/{entity_type_id}/{group}/admin/members/{og_membership}/delete", * "canonical" = "/group/{entity_type_id}/{group}/admin/members/{og_membership}" - * } + * }, + * field_ui_base_route = "entity.og_membership_type.edit_form" * ) */ class OgMembership extends ContentEntityBase implements OgMembershipInterface { diff --git a/src/Entity/OgMembershipType.php b/src/Entity/OgMembershipType.php index c1719c5fe..1f7eb957a 100644 --- a/src/Entity/OgMembershipType.php +++ b/src/Entity/OgMembershipType.php @@ -20,6 +20,16 @@ * @ConfigEntityType( * id = "og_membership_type", * label = @Translation("OG membership type"), + * handlers = { + * "access" = "Drupal\Core\Entity\EntityAccessControlHandler", + * "form" = { + * "add" = "Drupal\og\Form\OgMembershipTypeForm", + * "edit" = "Drupal\og\Form\OgMembershipTypeForm", + * "delete" = "Drupal\Core\Entity\EntityDeleteForm" + * }, + * "list_builder" = "Drupal\og\OgMembershipTypeListBuilder" + * }, + * admin_permission = "administer group", * config_prefix = "og_membership_type", * bundle_of = "og_membership", * entity_keys = { @@ -30,6 +40,11 @@ * "type", * "name", * "description" + * }, + * links = { + * "edit-form" = "/admin/structure/membership-types/manage/{membership_type}", + * "delete-form" = "/admin/structure/membership-types/manage/{membership_type}/delete", + * "collection" = "/admin/structure/membership-types", * } * ) */ diff --git a/src/Form/OgMembershipTypeForm.php b/src/Form/OgMembershipTypeForm.php new file mode 100644 index 000000000..f34d69dc1 --- /dev/null +++ b/src/Form/OgMembershipTypeForm.php @@ -0,0 +1,128 @@ +entityManager = $entity_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function form(array $form, FormStateInterface $form_state) { + $form = parent::form($form, $form_state); + + $type = $this->entity; + if ($this->operation == 'add') { + $form['#title'] = $this->t('Add membership type'); + } + else { + $form['#title'] = $this->t('Edit %label membership type', array('%label' => $type->label())); + } + + $form['name'] = array( + '#title' => $this->t('Name'), + '#type' => 'textfield', + '#default_value' => $type->label(), + '#description' => $this->t('The human-readable name of this membership type.'), + '#required' => TRUE, + '#size' => 30, + ); + + $form['type'] = array( + '#type' => 'machine_name', + '#default_value' => $type->id(), + '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH, + '#machine_name' => array( + 'exists' => ['Drupal\og\Entity\OgMembershipType', 'load'], + 'source' => array('name'), + ), + '#description' => $this->t('A unique machine-readable name for this membership type. It must only contain lowercase letters, numbers, and underscores.'), + ); + return $this->protectBundleIdElement($form); + } + + /** + * {@inheritdoc} + */ + protected function actions(array $form, FormStateInterface $form_state) { + $actions = parent::actions($form, $form_state); + $actions['submit']['#value'] = $this->t('Save membership type'); + $actions['delete']['#value'] = $this->t('Delete membership type'); + return $actions; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + parent::validateForm($form, $form_state); + + $id = trim($form_state->getValue('type')); + // '0' is invalid, since elsewhere we check it using empty(). + if ($id == '0') { + $form_state->setErrorByName('type', $this->t("Invalid machine-readable name. Enter a name other than %invalid.", array('%invalid' => $id))); + } + } + + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state) { + $type = $this->entity; + $type->set('type', trim($type->id())); + $type->set('name', trim($type->label())); + + $status = $type->save(); + + $t_args = array('%name' => $type->label()); + + if ($status == SAVED_UPDATED) { + drupal_set_message($this->t('The membership type %name has been updated.', $t_args)); + } + elseif ($status == SAVED_NEW) { + drupal_set_message($this->t('The membership type %name has been added.', $t_args)); + $context = array_merge($t_args, array('link' => $type->link($this->t('View'), 'collection'))); + $this->logger('og')->notice('Added membership type %name.', $context); + } + + $fields = $this->entityManager->getFieldDefinitions('og_membership', $type->id()); + + $this->entityManager->clearCachedFieldDefinitions(); + $form_state->setRedirectUrl($type->urlInfo('collection')); + } + +} diff --git a/src/OgMembershipTypeListBuilder.php b/src/OgMembershipTypeListBuilder.php new file mode 100644 index 000000000..efaf58587 --- /dev/null +++ b/src/OgMembershipTypeListBuilder.php @@ -0,0 +1,55 @@ + $entity->label(), + 'class' => array('menu-label'), + ); + return $row + parent::buildRow($entity); + } + + /** + * {@inheritdoc} + */ + public function getDefaultOperations(EntityInterface $entity) { + $operations = parent::getDefaultOperations($entity); + // Place the edit operation after the operations added by field_ui.module + // which have the weights 15, 20, 25. + if (isset($operations['edit'])) { + $operations['edit']['weight'] = 30; + } + return $operations; + } + + /** + * {@inheritdoc} + */ + public function render() { + $build = parent::render(); + return $build; + } + +} From 03772c8939969a1e99a90a8476a0a3deae272405 Mon Sep 17 00:00:00 2001 From: Justin Ludwig Date: Wed, 1 Feb 2017 13:59:38 -0800 Subject: [PATCH 055/111] Adds membership type page to facilitate when multiple membership types exist. Additional cleanup as well. --- og.links.action.yml | 2 +- og.module | 7 ++- og.routing.yml | 12 ++++ src/Controller/OgAdminMembersController.php | 56 ++++++++++++++++++- src/Controller/OgController.php | 61 --------------------- src/Entity/OgMembership.php | 1 + src/EventSubscriber/OgEventSubscriber.php | 18 ++---- src/Form/OgMembershipDeleteForm.php | 2 +- src/Form/OgMembershipForm.php | 36 +++++++++++- 9 files changed, 114 insertions(+), 81 deletions(-) diff --git a/og.links.action.yml b/og.links.action.yml index 3bd58d842..255492af4 100644 --- a/og.links.action.yml +++ b/og.links.action.yml @@ -1,5 +1,5 @@ og_membership.add: - route_name: entity.node.og_admin_routes.add_membership + route_name: entity.node.og_admin_routes.add_membership_page title: 'Add a member' appears_on: - entity.node.og_admin_routes.members diff --git a/og.module b/og.module index 825738181..3ac40d544 100755 --- a/og.module +++ b/og.module @@ -176,9 +176,14 @@ function og_entity_access(EntityInterface $entity, $operation, AccountInterface /** * Implements hook_ENTITY_TYPE_access(). */ -function og_og_membership_access(EntityInterface $entity, $operation, AccountInterface $account) { +function og_og_membership_access(OgMembershipInterface $entity, $operation, AccountInterface $account) { $group = $entity->getGroup(); + // Do not allow deleting the group owner's membership. + if (($operation === 'delete') && ($group instanceof EntityOwnerInterface) && ($group->getOwnerId() == $entity->getUser()->id())) { + return AccessResult::forbidden(); + } + // If the user has permission to administer all groups, allow access. if ($account->hasPermission('administer group')) { return AccessResult::allowed(); diff --git a/og.routing.yml b/og.routing.yml index 0d00f4c1f..f8d9e0776 100644 --- a/og.routing.yml +++ b/og.routing.yml @@ -55,6 +55,18 @@ entity.og_membership.canonical: parameters: type: entity:{entity_type_id} +entity.og_membership.add_form: + path: 'group/{entity_type_id}/{group}/admin/members/add/{membership_type}' + defaults: + _controller: '\Drupal\og\Controller\OgAdminMembersController::addForm' + _title: 'Add member' + requirements: + _og_user_access_group: 'administer group|manage members|add user' + options: + parameters: + membership_type: + type: entity:og_membership_type + entity.og_membership.edit_form: path: 'group/{entity_type_id}/{group}/admin/members/{og_membership}/edit' defaults: diff --git a/src/Controller/OgAdminMembersController.php b/src/Controller/OgAdminMembersController.php index 67b5256ff..bc76d174c 100644 --- a/src/Controller/OgAdminMembersController.php +++ b/src/Controller/OgAdminMembersController.php @@ -3,9 +3,14 @@ namespace Drupal\og\Controller; use Drupal\Core\Controller\ControllerBase; +use Drupal\Core\Entity\Controller\EntityController; +use Drupal\Core\Entity\EntityTypeBundleInfoInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Link; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\og\Entity\OgMembership; use Drupal\views\Views; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * OgAdminMembersController class. @@ -31,6 +36,51 @@ public function membersList(RouteMatchInterface $route_match) { return Views::getView('og_members_overview')->executeDisplay('default', $arguments); } + /** + * Displays add membership links for available membership types. + * + * Returns default membership type if that's all that exists. + * + * @return array + * A render array for a list of the node types that can be added; however, + * if there is only one node type defined for the site, the function + * will return the default add member form. + */ + public function addPage(RouteMatchInterface $route_match) { + $bundles = $this->entityTypeManager()->getStorage('og_membership_type')->loadMultiple(); + if ($bundles && count($bundles) == 1) { + $type = reset($types); + return $this->addForm($route_match); + } + + $build = [ + '#theme' => 'entity_add_list', + '#bundles' => [], + ]; + + $bundle_entity_type = $this->entityTypeManager()->getDefinition('og_membership_type'); + $build['#cache']['tags'] = $bundle_entity_type->getListCacheTags(); + + $group_type_id = $route_match->getRouteObject()->getOption('_og_entity_type_id'); + + /** @var \Drupal\Core\Entity\EntityInterface $group */ + $group = $route_match->getParameter($group_type_id); + $entity_type_id = $group->getEntityType()->id(); + + foreach ($bundles as $bundle_name => $bundle_info) { + $build['#bundles'][$bundle_name] = [ + 'label' => $bundle_info['name'], + 'add_link' => Link::createFromRoute( + $bundle_info['name'], + "entity.$entity_type_id.og_admin_routes.add_membership", + [$entity_type_id => $group->id(), 'membership_type' => $bundle_name] + ), + ]; + } + + return $build; + } + /** * Provides the add member submission form. * @@ -40,9 +90,13 @@ public function membersList(RouteMatchInterface $route_match) { * @return array * The member add form. */ - public function addMember(RouteMatchInterface $route_match) { + public function addForm(RouteMatchInterface $route_match) { /** @var \Drupal\og\Entity\OgMembershipType $membership_type */ $membership_type = $route_match->getParameter('membership_type'); + if ($membership_type === NULL) { + $membership_type = $this->entityTypeManager->getStorage('og_membership_type')->load('default'); + } + $group_type_id = $route_match->getRouteObject()->getOption('_og_entity_type_id'); /** @var \Drupal\Core\Entity\EntityInterface $group */ diff --git a/src/Controller/OgController.php b/src/Controller/OgController.php index 29c75d903..e69de29bb 100644 --- a/src/Controller/OgController.php +++ b/src/Controller/OgController.php @@ -1,61 +0,0 @@ -getRouteObject()->getOption('_og_entity_type_id'); - - /** @var \Drupal\Core\Entity\EntityInterface $group */ - $group = $route_match->getParameter($parameter_name); - - $arguments = [$group->getEntityTypeId(), $group->id()]; - return Views::getView('og_members_overview')->executeDisplay('default', $arguments); - } - - /** - * Provides the add member submission form. - * - * @param \Drupal\Core\Routing\RouteMatchInterface $route_match - * The route match service. - * - * @return array - * The member add form. - */ - public function addMember(RouteMatchInterface $route_match) { - /** @var \Drupal\og\Entity\OgMembershipType $membership_type */ - //$membership_type = $route_match->getParameter('membership_type'); - //$group_type_id = $route_match->getRouteObject()->getOption('_og_entity_type_id'); - - /** @var \Drupal\Core\Entity\EntityInterface $group */ - //$group = $route_match->getParameter($group_type_id); - - /** @var \Drupal\og\Entity\OgMembership $og_membership */ - $og_membership = OgMembership::create([ - 'type' => 'default', - 'entity_type' => 'node', - 'entity_id' => 8, - ]); - - return $this->entityFormBuilder()->getForm($og_membership, 'add'); - } - -} diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index 4e9133ba0..61c48032f 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -59,6 +59,7 @@ * fieldable = TRUE, * bundle_entity_type = "og_membership_type", * entity_keys = { + * "uuid" = "uuid", * "id" = "id", * "bundle" = "type", * }, diff --git a/src/EventSubscriber/OgEventSubscriber.php b/src/EventSubscriber/OgEventSubscriber.php index 859fbe933..22a2a9b34 100644 --- a/src/EventSubscriber/OgEventSubscriber.php +++ b/src/EventSubscriber/OgEventSubscriber.php @@ -363,24 +363,14 @@ public function provideOgAdminRoutes(OgAdminRoutesEventInterface $event) { ], ]; - $routes_info['add_membership'] = [ - 'controller' => '\Drupal\og\Controller\OgAdminMembersController::addMember', - 'title' => 'Add members', - 'path' => 'members/add/{membership_type}', - 'defaults' => [ - 'membership_type' => 'default', - ], + $routes_info['add_membership_page'] = [ + 'controller' => '\Drupal\og\Controller\OgAdminMembersController::addPage', + 'title' => 'Add member', + 'path' => 'members/add', // @TODO switch to an entity create access callback once it works better. 'requirements' => [ '_og_user_access_group' => 'administer group|manage members|add user', ], - 'options' => [ - 'parameters' => [ - 'membership_type' => [ - 'type' => 'entity:og_membership_type', - ], - ], - ], ]; $event->setRoutesInfo($routes_info); diff --git a/src/Form/OgMembershipDeleteForm.php b/src/Form/OgMembershipDeleteForm.php index b5cb2b77e..5e905b99b 100644 --- a/src/Form/OgMembershipDeleteForm.php +++ b/src/Form/OgMembershipDeleteForm.php @@ -30,7 +30,7 @@ protected function logDeletionMessage() { /** @var \Drupal\og\Entity\OgMembership $entity */ $membership = $this->getEntity(); - $this->logger('og')->notice("OG Membership: Deleted the @membership_type membership for the user uid: @uid to the group of the entity-type @group_type and ID: @gid", [ + $this->logger('og')->notice("OG Membership: deleted the @membership_type membership for the user uid: @uid to the group of the entity-type @group_type and ID: @gid", [ '@membership_type' => $membership->getType(), '@uid' => $membership->getUser()->id(), '@group_type' => $membership->getGroupEntityType(), diff --git a/src/Form/OgMembershipForm.php b/src/Form/OgMembershipForm.php index d2eb6a47b..edb2a2fba 100644 --- a/src/Form/OgMembershipForm.php +++ b/src/Form/OgMembershipForm.php @@ -16,13 +16,12 @@ class OgMembershipForm extends ContentEntityForm { * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { - $form = parent::form($form, $form_state); - /** @var \Drupal\og\Entity\OgMembership $entity */ $entity = $this->getEntity(); /** @var \Drupal\Core\Entity\ContentEntityInterface $group */ $group = $entity->getGroup(); + $form = parent::form($form, $form_state); $form['#title'] = $this->t('Add member to %group', ['%group' => $group->label()]); $form['entity_type'] = ['#value' => $entity->getEntityType()->id()]; $form['entity_id'] = ['#value' => $group->id()]; @@ -55,4 +54,37 @@ public function form(array $form, FormStateInterface $form_state) { return $form; } + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state) { + $membership = $this->entity; + $insert = $membership->isNew(); + $membership->save(); + + $membership_link = $membership->link($this->t('View')); + + $context = [ + '@membership_type' => $membership->getType(), + '@uid' => $membership->getUser()->id(), + '@group_type' => $membership->getGroupEntityType(), + '@gid' => $membership->getGroupId(), + 'link' => $membership_link, + ]; + + $t_args = array( + '%user' => $membership->getUser()->link(), + '%group' => $membership->getGroup()->link(), + ); + + if ($insert) { + $this->logger('og')->notice('OG Membership: added the @membership_type membership for the use uid @uid to the group of the entity-type @group_type and ID @gid.', $context); + drupal_set_message($this->t('Added %user to %group.', $t_args)); + return; + } + + $this->logger('og')->notice('OG Membership: updated the @membership_type membership for the use uid @uid to the group of the entity-type @group_type and ID @gid.', $context); + drupal_set_message($this->t('Updated the membership for %user to %group.', $t_args)); + } + } From 147b4c936d30c89378e34902f0e46e090770db18 Mon Sep 17 00:00:00 2001 From: Justin Ludwig Date: Fri, 3 Feb 2017 16:56:22 -0800 Subject: [PATCH 056/111] Ensures that only valid members/roles can be selected. Also some misc cleanup --- og.routing.yml | 11 ++ src/Controller/OgAutocompleteController.php | 112 +++++++++++ src/Controller/OgAutocompleteMatcher.php | 109 ++++++++++ src/Controller/OgController.php | 0 src/Element/OgAutocomplete.php | 63 ++++++ src/Entity/OgMembership.php | 7 +- src/MembershipManager.php | 39 ++++ src/MembershipManagerInterface.php | 13 ++ .../OgRoleSelection.php | 2 +- .../OgUserSelection.php | 187 ++++++++++++++++++ .../Field/FieldWidget/OgAutocomplete.php | 53 +++++ .../UniqueOgMembershipConstraint.php | 26 +++ .../UniqueOgMembershipConstraintValidator.php | 39 ++++ .../Constraint/ValidOgRoleConstraint.php | 25 +++ .../ValidOgRoleConstraintValidator.php | 41 ++++ 15 files changed, 724 insertions(+), 3 deletions(-) create mode 100644 src/Controller/OgAutocompleteController.php create mode 100644 src/Controller/OgAutocompleteMatcher.php delete mode 100644 src/Controller/OgController.php create mode 100644 src/Element/OgAutocomplete.php create mode 100644 src/Plugin/EntityReferenceSelection/OgUserSelection.php create mode 100644 src/Plugin/Field/FieldWidget/OgAutocomplete.php create mode 100644 src/Plugin/Validation/Constraint/UniqueOgMembershipConstraint.php create mode 100644 src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php create mode 100644 src/Plugin/Validation/Constraint/ValidOgRoleConstraint.php create mode 100644 src/Plugin/Validation/Constraint/ValidOgRoleConstraintValidator.php diff --git a/og.routing.yml b/og.routing.yml index f8d9e0776..5d5fd1267 100644 --- a/og.routing.yml +++ b/og.routing.yml @@ -112,3 +112,14 @@ og_membership.type_add: _title: 'Add membership type' requirements: _permission: 'administer group' + +og.entity_autocomplete: + path: '/group/{entity_type_id}/{group}/autocomplete/{target_type}/{selection_handler}/{selection_settings_key}' + defaults: + _controller: '\Drupal\og\Controller\OgAutocompleteController:handleAutocomplete' + requirements: + _access: 'TRUE' + options: + parameters: + group: + type: entity:{entity_type_id} diff --git a/src/Controller/OgAutocompleteController.php b/src/Controller/OgAutocompleteController.php new file mode 100644 index 000000000..b8a6fae11 --- /dev/null +++ b/src/Controller/OgAutocompleteController.php @@ -0,0 +1,112 @@ +matcher = $matcher; + $this->keyValue = $key_value; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.autocomplete_matcher'), + $container->get('keyvalue')->get('entity_autocomplete') + ); + } + + /** + * Autocomplete the label of an entity. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request object that contains the typed tags. + * @param \Drupal\Core\Entity\EntityInterface $group + * The group context for this autocomplete. + * @param string $target_type + * The ID of the target entity type. + * @param string $selection_handler + * The plugin ID of the entity reference selection handler. + * @param string $selection_settings_key + * The hashed key of the key/value entry that holds the selection handler + * settings. + * + * @return \Symfony\Component\HttpFoundation\JsonResponse + * The matched entity labels as a JSON response. + * + * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + * Thrown if the selection settings key is not found in the key/value store + * or if it does not match the stored data. + */ + public function handleAutocomplete(Request $request, $group, $target_type, $selection_handler, $selection_settings_key) { + $matches = array(); + // Get the typed string from the URL, if it exists. + if ($input = $request->query->get('q')) { + $typed_string = Tags::explode($input); + $typed_string = Unicode::strtolower(array_pop($typed_string)); + + // Selection settings are passed in as a hashed key of a serialized array + // stored in the key/value store. + $selection_settings = $this->keyValue->get($selection_settings_key, FALSE); + if ($selection_settings !== FALSE) { + $selection_settings_hash = Crypt::hmacBase64(serialize($selection_settings) . $target_type . $selection_handler, Settings::getHashSalt()); + if ($selection_settings_hash !== $selection_settings_key) { + // Disallow access when the selection settings hash does not match the + // passed-in key. + throw new AccessDeniedHttpException('Invalid selection settings key.'); + } + } + else { + // Disallow access when the selection settings key is not found in the + // key/value store. + throw new AccessDeniedHttpException(); + } + + $selection_settings['group'] = $group; + $matches = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string); + } + + return new JsonResponse($matches); + } + +} diff --git a/src/Controller/OgAutocompleteMatcher.php b/src/Controller/OgAutocompleteMatcher.php new file mode 100644 index 000000000..4ccc8854a --- /dev/null +++ b/src/Controller/OgAutocompleteMatcher.php @@ -0,0 +1,109 @@ +matcher = $matcher; + $this->keyValue = $key_value; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.autocomplete_matcher'), + $container->get('keyvalue')->get('entity_autocomplete') + ); + } + + /** + * Autocomplete the label of an entity. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request object that contains the typed tags. + * @param string $target_type + * The ID of the target entity type. + * @param string $selection_handler + * The plugin ID of the entity reference selection handler. + * @param string $selection_settings_key + * The hashed key of the key/value entry that holds the selection handler + * settings. + * + * @return \Symfony\Component\HttpFoundation\JsonResponse + * The matched entity labels as a JSON response. + * + * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + * Thrown if the selection settings key is not found in the key/value store + * or if it does not match the stored data. + */ + public function handleAutocomplete(Request $request, $group, $target_type, $selection_handler, $selection_settings_key) { + $matches = array(); + // Get the typed string from the URL, if it exists. + if ($input = $request->query->get('q')) { + $typed_string = Tags::explode($input); + $typed_string = Unicode::strtolower(array_pop($typed_string)); + + // Selection settings are passed in as a hashed key of a serialized array + // stored in the key/value store. + $selection_settings = $this->keyValue->get($selection_settings_key, FALSE); + if ($selection_settings !== FALSE) { + $selection_settings_hash = Crypt::hmacBase64(serialize($selection_settings) . $target_type . $selection_handler, Settings::getHashSalt()); + if ($selection_settings_hash !== $selection_settings_key) { + // Disallow access when the selection settings hash does not match the + // passed-in key. + throw new AccessDeniedHttpException('Invalid selection settings key.'); + } + } + else { + // Disallow access when the selection settings key is not found in the + // key/value store. + throw new AccessDeniedHttpException(); + } + + $matches = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string); + } + + return new JsonResponse($matches); + } + +} diff --git a/src/Controller/OgController.php b/src/Controller/OgController.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/Element/OgAutocomplete.php b/src/Element/OgAutocomplete.php new file mode 100644 index 000000000..395b52059 --- /dev/null +++ b/src/Element/OgAutocomplete.php @@ -0,0 +1,63 @@ +id(); + } + + // Store the selection settings in the key/value store and pass a hashed key + // in the route parameters. + $selection_settings = isset($element['#selection_settings']) ? $element['#selection_settings'] : []; + $data = serialize($selection_settings) . $element['#target_type'] . $element['#selection_handler']; + $selection_settings_key = Crypt::hmacBase64($data, Settings::getHashSalt()); + + $key_value_storage = \Drupal::keyValue('entity_autocomplete'); + if (!$key_value_storage->has($selection_settings_key)) { + $key_value_storage->set($selection_settings_key, $selection_settings); + } + + $element['#autocomplete_route_name'] = 'og.entity_autocomplete'; + $element['#autocomplete_route_parameters'] = array( + 'target_type' => $element['#target_type'], + 'selection_handler' => $element['#selection_handler'], + 'selection_settings_key' => $selection_settings_key, + 'entity_type_id' => $element['#og_group']->getEntityTypeId(), + 'group' => $element['#og_group']->id(), + ); + + return $element; + } + +} diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index 61c48032f..594ac9706 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -381,6 +381,8 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setLabel(t('Member User ID')) ->setDescription(t('The user ID of the member.')) ->setSetting('target_type', 'user') + ->setSetting('handler', 'og:user') + ->setConstraints(['UniqueOgMembership' => []]) ->setDisplayOptions('form', [ 'type' => 'entity_reference_autocomplete', 'weight' => -1, @@ -415,12 +417,13 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setLabel(t('Roles')) ->setDescription(t('The OG roles related to an OG membership entity.')) ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) + ->setSetting('target_type', 'og_role') + ->setSetting('handler', 'og:og_role') + ->setConstraints(['ValidOgRole' => []]) ->setDisplayOptions('form', [ 'type' => 'options_buttons', 'weight' => 0, ]) - ->setSetting('target_type', 'og_role'); - ->setSetting('handler', 'og:og_role') ->setDisplayConfigurable('view', TRUE) ->setDisplayConfigurable('form', TRUE); diff --git a/src/MembershipManager.php b/src/MembershipManager.php index 6e03f7395..6e4153ad5 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -121,6 +121,45 @@ public function getMembership(EntityInterface $group, AccountInterface $user, ar return NULL; } + /** + * {@inheritdoc} + */ + public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]) { + // Get a string identifier of the states, so we can retrieve it from cache. + sort($states); + $states_identifier = implode('|', array_unique($states)); + + $identifier = [ + __METHOD__, + $group->id(), + $states_identifier, + ]; + $identifier = implode(':', $identifier); + + // Return cached result if it exists. + if (isset($this->cache[$identifier])) { + return $this->cache[$identifier]; + } + + $query = $this->entityTypeManager + ->getStorage('og_membership') + ->getQuery() + ->condition('entity_id', $group->id()); + + if ($states) { + $query->condition('state', $states, 'IN'); + } + + $results = $query->execute(); + + /** @var \Drupal\og\Entity\OgMembership[] $memberships */ + $this->cache[$identifier] = $this->entityTypeManager + ->getStorage('og_membership') + ->loadMultiple($results); + + return $this->cache[$identifier]; + } + /** * {@inheritdoc} */ diff --git a/src/MembershipManagerInterface.php b/src/MembershipManagerInterface.php index c987128bf..bbfdc57b2 100644 --- a/src/MembershipManagerInterface.php +++ b/src/MembershipManagerInterface.php @@ -70,6 +70,19 @@ public function getUserGroups(AccountInterface $user, array $states = [OgMembers */ public function getMemberships(AccountInterface $user, array $states = [OgMembershipInterface::STATE_ACTIVE]); + /** + * Returns the group memberships for a given group. + * + * @param \Drupal\Core\Entity\EntityInterface $group + * The group to get the membership for. + * @param array $states + * (optional) Array with the state to return. Defaults to active. + * + * @return \Drupal\og\OgMembershipInterface[] + * An array of OgMembership entities, keyed by ID. + */ + public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]); + /** * Returns the group membership for a given user and group. * diff --git a/src/Plugin/EntityReferenceSelection/OgRoleSelection.php b/src/Plugin/EntityReferenceSelection/OgRoleSelection.php index cd3cc42fa..1ba446822 100644 --- a/src/Plugin/EntityReferenceSelection/OgRoleSelection.php +++ b/src/Plugin/EntityReferenceSelection/OgRoleSelection.php @@ -35,7 +35,7 @@ public function getSelectionHandler() { protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') { $query = parent::buildEntityQuery($match, $match_operator); - $entity = $this->configuration['entity']; + $entity = isset($this->configuration['entity']) ? $this->configuration['entity'] : NULL; // The entity does not always exist, for example during validation. // @todo figure out how to always add the full conditions, especially if // this can be abused to reference incompatible roles. diff --git a/src/Plugin/EntityReferenceSelection/OgUserSelection.php b/src/Plugin/EntityReferenceSelection/OgUserSelection.php new file mode 100644 index 000000000..07f078cca --- /dev/null +++ b/src/Plugin/EntityReferenceSelection/OgUserSelection.php @@ -0,0 +1,187 @@ +connection = $connection; + $this->userStorage = $entity_manager->getStorage('user'); + $this->membershipManager = $membership_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity.manager'), + $container->get('module_handler'), + $container->get('current_user'), + $container->get('database'), + $container->get('og.membership_manager') + ); + } + /** + * Get the selection handler of the field. + * + * @return DefaultSelection + * Returns the selection handler. + */ + public function getSelectionHandler() { + $options = [ + 'target_type' => 'user', + ]; + return \Drupal::service('plugin.manager.entity_reference_selection')->getInstance($options); + } + + /** + * {@inheritdoc} + */ + protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') { + $query = parent::buildEntityQuery($match, $match_operator); + + // Anon can't be a group member. + $query->condition('uid', 0, '<>'); + + // The user entity doesn't have a label column. + if (isset($match)) { + $query->condition('name', $match, $match_operator); + } + + // Adding the permission check is sadly insufficient for users: core + // requires us to also know about the concept of 'blocked' and 'active'. + if (!$this->currentUser->hasPermission('administer users')) { + $query->condition('status', 1); + } + + $group = NULL; + if (isset($this->configuration['entity'])) { + $entity = $this->configuration['entity']; + $group = is_callable([$entity, 'getGroup']) ? $entity->getGroup() : NULL; + } + + if (isset($this->configuration['handler_settings']['group'])) { + $group = $this->configuration['handler_settings']['group']; + } + // The entity does not always exist, for example during validation. + // @todo figure out how to always add the full conditions. + if ($group === NULL) { + return $query; + } + + // @todo Excluding group members with a join would perform much better than + // loading each membership associated with the group. + $member_uids = []; + /** @var \Drupal\og\Entity\OgMembership $membership */ + foreach ($this->membershipManager->getGroupMemberships($group) as $membership) { + $member_uids[] = $membership->getUser()->id(); + } + + if (count($member_uids) > 0) { + $query->condition('uid', $member_uids, 'NOT IN'); + } + + return $query; + } + + /** + * {@inheritdoc} + */ + public function createNewEntity($entity_type_id, $bundle, $label, $uid) { + $user = parent::createNewEntity($entity_type_id, $bundle, $label, $uid); + + // In order to create a referenceable user, it needs to be active. + if (!$this->currentUser->hasPermission('administer users')) { + /** @var \Drupal\user\UserInterface $user */ + $user->activate(); + } + + return $user; + } + + /** + * {@inheritdoc} + */ + public function validateReferenceableNewEntities(array $entities) { + $entities = parent::validateReferenceableNewEntities($entities); + // Mirror the conditions checked in buildEntityQuery(). + if (!$this->currentUser->hasPermission('administer users')) { + $entities = array_filter($entities, function ($user) { + /** @var \Drupal\user\UserInterface $user */ + return $user->isActive(); + }); + } + return $entities; + } + +} diff --git a/src/Plugin/Field/FieldWidget/OgAutocomplete.php b/src/Plugin/Field/FieldWidget/OgAutocomplete.php new file mode 100644 index 000000000..7d8a6bfcf --- /dev/null +++ b/src/Plugin/Field/FieldWidget/OgAutocomplete.php @@ -0,0 +1,53 @@ +getEntity(); + if (!is_callable([$entity, 'getGroup'])) { + return $element; + } + + $element['target_id']['#type'] = 'og_autocomplete'; + $element['target_id']['#og_group'] = $entity->getGroup(); + + return $element; + } + + public function errorElement(array $element, ConstraintViolationInterface $error, array $form, FormStateInterface $form_state) { + return $element; + } + + +} diff --git a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraint.php b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraint.php new file mode 100644 index 000000000..905bc6a28 --- /dev/null +++ b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraint.php @@ -0,0 +1,26 @@ +getEntity(); + // Only applicable to new memberships. + if (!$entity->isNew()) { + return; + } + + $new_member_uid = $value->getValue()[0]['target_id']; + $membership_manager = \Drupal::service('og.membership_manager'); + foreach ($membership_manager->getGroupMemberships($entity->getGroup()) as $membership) { + if ((string) $membership->getUser()->id() === (string) $new_member_uid) { + $this->context->addViolation($constraint->NotUniqueMembership, ['%user' => $membership->getUser()->getDisplayName()]); + return; + } + } + } + +} diff --git a/src/Plugin/Validation/Constraint/ValidOgRoleConstraint.php b/src/Plugin/Validation/Constraint/ValidOgRoleConstraint.php new file mode 100644 index 000000000..6e66a3f30 --- /dev/null +++ b/src/Plugin/Validation/Constraint/ValidOgRoleConstraint.php @@ -0,0 +1,25 @@ +getEntity(); + if (!$entity) { + // Entity with that entity ID does not exists. This could happen if a + // stale entity is passed for validation. + return; + } + + $group_type = $entity->getGroup()->getEntityTypeId(); + $group_bundle = $entity->getGroup()->bundle(); + + foreach ($value->referencedEntities() as $og_role) { + if ($og_role->getGroupType() !== $group_type || $og_role->getGroupBundle() !== $group_bundle) { + $this->context->addViolation($constraint->NotValidRole); + } + } + + } + +} From b0046beb40c751bd3df2eb636ab521529ad624f1 Mon Sep 17 00:00:00 2001 From: Justin Ludwig Date: Fri, 10 Feb 2017 23:57:10 -0800 Subject: [PATCH 057/111] Adds a general membership add page for when multiple membership types exist, an access control handlers for adding membership and does some general cleanup --- ..._display.og_membership.default.default.yml | 2 +- config/schema/og.schema.yml | 15 ++ og.module | 38 +---- og.routing.yml | 32 ++-- og.services.yml | 5 + src/Access/OgMembershipAddAccessCheck.php | 67 ++++++++ src/Controller/OgAdminMembersController.php | 108 +++++++++--- src/Controller/OgAutocompleteController.php | 5 +- src/Controller/OgAutocompleteMatcher.php | 2 +- src/Element/OgAutocomplete.php | 14 +- src/Entity/OgMembership.php | 3 +- src/Entity/OgMembershipType.php | 32 ++++ src/EventSubscriber/OgEventSubscriber.php | 3 +- src/Form/OgMembershipDeleteForm.php | 1 - src/Form/OgMembershipForm.php | 4 +- src/Form/OgMembershipTypeForm.php | 26 ++- src/OgMembershipAccessControlHandler.php | 155 ++++++++++++++++++ src/OgMembershipTypeListBuilder.php | 14 +- .../OgRoleSelection.php | 26 ++- .../OgUserSelection.php | 13 +- .../Field/FieldWidget/OgAutocomplete.php | 13 +- .../UniqueOgMembershipConstraintValidator.php | 1 - .../Constraint/ValidOgRoleConstraint.php | 3 +- .../ValidOgRoleConstraintValidator.php | 1 - 24 files changed, 436 insertions(+), 147 deletions(-) create mode 100644 src/Access/OgMembershipAddAccessCheck.php create mode 100644 src/OgMembershipAccessControlHandler.php diff --git a/config/install/core.entity_form_display.og_membership.default.default.yml b/config/install/core.entity_form_display.og_membership.default.default.yml index 1a3300f39..0332b58f8 100644 --- a/config/install/core.entity_form_display.og_membership.default.default.yml +++ b/config/install/core.entity_form_display.og_membership.default.default.yml @@ -24,7 +24,7 @@ content: settings: { } third_party_settings: { } uid: - type: entity_reference_autocomplete + type: og_autocomplete weight: -1 settings: match_operator: CONTAINS diff --git a/config/schema/og.schema.yml b/config/schema/og.schema.yml index 4f08e369b..aa919cd2b 100644 --- a/config/schema/og.schema.yml +++ b/config/schema/og.schema.yml @@ -193,3 +193,18 @@ condition.plugin.og_group_type: type: sequence sequence: type: string + +# Copied and adapted from core.entity.schema.yml +field.widget.settings.og_autocomplete: + type: mapping + label: 'OG context based entity reference autocomplete with display format settings' + mapping: + match_operator: + type: string + label: 'Autocomplete matching' + size: + type: integer + label: 'Size of textfield' + placeholder: + type: label + label: 'Placeholder' diff --git a/og.module b/og.module index 3ac40d544..785b7021c 100755 --- a/og.module +++ b/og.module @@ -17,6 +17,7 @@ use Drupal\og\Entity\OgRole; use Drupal\og\Og; use Drupal\og\OgGroupAudienceHelperInterface; use Drupal\og\OgMembershipInterface; +use Drupal\og\OgMembershipTypeInterface; use Drupal\og\OgRoleInterface; use Drupal\system\Entity\Action; use Drupal\user\EntityOwnerInterface; @@ -176,11 +177,9 @@ function og_entity_access(EntityInterface $entity, $operation, AccountInterface /** * Implements hook_ENTITY_TYPE_access(). */ -function og_og_membership_access(OgMembershipInterface $entity, $operation, AccountInterface $account) { - $group = $entity->getGroup(); - - // Do not allow deleting the group owner's membership. - if (($operation === 'delete') && ($group instanceof EntityOwnerInterface) && ($group->getOwnerId() == $entity->getUser()->id())) { +function og_og_membership_type_access(OgMembershipTypeInterface $entity, $operation, AccountInterface $account) { + // Do not allow deleting the default membership type. + if (($operation === 'delete') && ($entity->id() === 'default')) { return AccessResult::forbidden(); } @@ -189,10 +188,7 @@ function og_og_membership_access(OgMembershipInterface $entity, $operation, Acco return AccessResult::allowed(); } - // Someone with the manage members permission should be able to do pretty much - // anything with memberships. - // @TODO: if this turns out to be untrue, do some operation checking. - return \Drupal::service('og.access')->userAccess($group, 'manage members', $account); + return AccessResult::forbidden(); } /** @@ -247,30 +243,6 @@ function og_entity_create_access(AccountInterface $account, array $context, $bun return $required ? AccessResult::forbiddenIf($node_access_strict) : AccessResult::neutral(); } -/** - * Implements hook_ENTITY_TYPE_entity_create_access(). - */ -function og_og_membership_create_access(AccountInterface $account, array $context, $bundle) { - // If the user has permission to administer all groups, allow access. - if ($account->hasPermission('administer group')) { - return AccessResult::allowed(); - } - - $group = $entity->getGroup(); - - // If we don't have a group, we can't really determine access other than - // checking global account permissions. - if ($group === NULL) { - return AccessResult::neutral(); - } - - $add_users = \Drupal::service('og.access')->userAccess($group, 'add user', $account); - if ($add_users->isAllowed()) { - return $add_users; - } - return \Drupal::service('og.access')->userAccess($group, 'manage members', $account); -} - /** * Implements hook_entity_bundle_field_info(). * diff --git a/og.routing.yml b/og.routing.yml index 5d5fd1267..1b9e3c959 100644 --- a/og.routing.yml +++ b/og.routing.yml @@ -44,6 +44,18 @@ og.remove_multiple_roles_confirm: requirements: _custom_access: '\Drupal\og\Form\OgRemoveMultipleRolesForm::access' +og.entity_autocomplete: + path: '/group/{entity_type_id}/{group}/autocomplete/{target_type}/{selection_handler}/{selection_settings_key}' + defaults: + _controller: '\Drupal\og\Controller\OgAutocompleteController:handleAutocomplete' + requirements: + _access: 'TRUE' + options: + parameters: + group: + type: entity:{entity_type_id} + +# OG Membership entity routes entity.og_membership.canonical: path: 'group/{entity_type_id}/{group}/admin/members/{og_membership}' defaults: @@ -61,11 +73,10 @@ entity.og_membership.add_form: _controller: '\Drupal\og\Controller\OgAdminMembersController::addForm' _title: 'Add member' requirements: - _og_user_access_group: 'administer group|manage members|add user' + _og_membership_add_access: 'TRUE' options: parameters: - membership_type: - type: entity:og_membership_type + type: entity:{entity_type_id} entity.og_membership.edit_form: path: 'group/{entity_type_id}/{group}/admin/members/{og_membership}/edit' @@ -81,6 +92,7 @@ entity.og_membership.delete_form: requirements: _entity_access: 'og_membership.delete' +# OG Membership type entity routes entity.og_membership_type.collection: path: '/admin/structure/membership-types' defaults: @@ -94,8 +106,7 @@ entity.og_membership_type.edit_form: defaults: _entity_form: 'og_membership_type.edit' requirements: - _permission: 'administer group' - + _entity_access: 'administer group' entity.og_membership_type.delete_form: path: '/admin/structure/membership-types/manage/{og_membership_type}/delete' @@ -112,14 +123,3 @@ og_membership.type_add: _title: 'Add membership type' requirements: _permission: 'administer group' - -og.entity_autocomplete: - path: '/group/{entity_type_id}/{group}/autocomplete/{target_type}/{selection_handler}/{selection_settings_key}' - defaults: - _controller: '\Drupal\og\Controller\OgAutocompleteController:handleAutocomplete' - requirements: - _access: 'TRUE' - options: - parameters: - group: - type: entity:{entity_type_id} diff --git a/og.services.yml b/og.services.yml index fae318a62..4a2c9c3d3 100644 --- a/og.services.yml +++ b/og.services.yml @@ -4,6 +4,11 @@ services: arguments: ['@entity_type.manager', '@og.access'] tags: - { name: access_check, applies_to: _og_user_access_group } + access_check.og.membership.add: + class: Drupal\og\Access\OgMembershipAddAccessCheck + arguments: ['@entity_type.manager', '@og.access'] + tags: + - { name: access_check, applies_to: _og_membership_add_access } cache_context.og_group_context: class: 'Drupal\og\Cache\Context\OgGroupContextCacheContext' arguments: ['@og.context'] diff --git a/src/Access/OgMembershipAddAccessCheck.php b/src/Access/OgMembershipAddAccessCheck.php new file mode 100644 index 000000000..4eccfe310 --- /dev/null +++ b/src/Access/OgMembershipAddAccessCheck.php @@ -0,0 +1,67 @@ +entityTypeManager = $entity_type_manager; + } + + /** + * Checks access to create the entity type and bundle for the given route. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The parametrized route. + * @param \Drupal\Core\Session\AccountInterface $account + * The currently logged in account. + * + * @return \Drupal\Core\Access\AccessResultInterface + * The access result. + */ + public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) { + $og_membership_type = $route_match->getParameter('membership_type'); + if (is_object($og_membership_type)) { + $og_membership_type = $og_membership_type->id(); + } + + if ($entity_type_id = $route_match->getParameter('entity_type_id')) { + $group = $this->entityTypeManager + ->getStorage($route_match->getParameter('entity_type_id')) + ->load($route_match->getParameter('group')); + } + else { + $entity_type_id = $route->getOption('_og_entity_type_id'); + $group = $route_match->getParameter($entity_type_id); + } + + $context = ['group' => $group]; + + return $this->entityTypeManager + ->getAccessControlHandler('og_membership') + ->createAccess($og_membership_type, $account, $context, TRUE); + } + +} diff --git a/src/Controller/OgAdminMembersController.php b/src/Controller/OgAdminMembersController.php index bc76d174c..fc2d1301f 100644 --- a/src/Controller/OgAdminMembersController.php +++ b/src/Controller/OgAdminMembersController.php @@ -3,12 +3,12 @@ namespace Drupal\og\Controller; use Drupal\Core\Controller\ControllerBase; -use Drupal\Core\Entity\Controller\EntityController; -use Drupal\Core\Entity\EntityTypeBundleInfoInterface; +use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Link; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\og\Entity\OgMembership; +use Drupal\og\Og; use Drupal\views\Views; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -17,6 +17,32 @@ */ class OgAdminMembersController extends ControllerBase { + /** + * The entity manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * Constructs a new EntityController. + * + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. + */ + public function __construct(EntityTypeManagerInterface $entity_type_manager) { + $this->entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity_type.manager') + ); + } + /** * Display list of members that belong to the group. * @@ -27,10 +53,8 @@ class OgAdminMembersController extends ControllerBase { * The members overview View. */ public function membersList(RouteMatchInterface $route_match) { - $parameter_name = $route_match->getRouteObject()->getOption('_og_entity_type_id'); - /** @var \Drupal\Core\Entity\EntityInterface $group */ - $group = $route_match->getParameter($parameter_name); + $group = $this->getGroupFromRoute($route_match); $arguments = [$group->getEntityTypeId(), $group->id()]; return Views::getView('og_members_overview')->executeDisplay('default', $arguments); @@ -47,9 +71,8 @@ public function membersList(RouteMatchInterface $route_match) { * will return the default add member form. */ public function addPage(RouteMatchInterface $route_match) { - $bundles = $this->entityTypeManager()->getStorage('og_membership_type')->loadMultiple(); - if ($bundles && count($bundles) == 1) { - $type = reset($types); + $membership_type_list = $this->entityTypeManager()->getStorage('og_membership_type')->loadMultiple(); + if ($membership_type_list && count($membership_type_list) == 1) { return $this->addForm($route_match); } @@ -61,20 +84,18 @@ public function addPage(RouteMatchInterface $route_match) { $bundle_entity_type = $this->entityTypeManager()->getDefinition('og_membership_type'); $build['#cache']['tags'] = $bundle_entity_type->getListCacheTags(); - $group_type_id = $route_match->getRouteObject()->getOption('_og_entity_type_id'); + $group = $this->getGroupFromRoute($route_match); - /** @var \Drupal\Core\Entity\EntityInterface $group */ - $group = $route_match->getParameter($group_type_id); - $entity_type_id = $group->getEntityType()->id(); - - foreach ($bundles as $bundle_name => $bundle_info) { - $build['#bundles'][$bundle_name] = [ - 'label' => $bundle_info['name'], - 'add_link' => Link::createFromRoute( - $bundle_info['name'], - "entity.$entity_type_id.og_admin_routes.add_membership", - [$entity_type_id => $group->id(), 'membership_type' => $bundle_name] - ), + $add_link_params = [ + 'group' => $group->id(), + 'entity_type_id' => $group->getEntityType()->id(), + ]; + + foreach ($membership_type_list as $membership_type_id => $og_membership_type) { + $add_link_params['membership_type'] = $membership_type_id; + $build['#bundles'][$membership_type_id] = [ + 'label' => $og_membership_type->label(), + 'add_link' => Link::createFromRoute($og_membership_type->label(), "entity.og_membership.add_form", $add_link_params), ]; } @@ -93,18 +114,18 @@ public function addPage(RouteMatchInterface $route_match) { public function addForm(RouteMatchInterface $route_match) { /** @var \Drupal\og\Entity\OgMembershipType $membership_type */ $membership_type = $route_match->getParameter('membership_type'); + if (is_object($membership_type)) { + $membership_type = $membership_type->id(); + } if ($membership_type === NULL) { - $membership_type = $this->entityTypeManager->getStorage('og_membership_type')->load('default'); + $membership_type = 'default'; } - $group_type_id = $route_match->getRouteObject()->getOption('_og_entity_type_id'); - - /** @var \Drupal\Core\Entity\EntityInterface $group */ - $group = $route_match->getParameter($group_type_id); + $group = $this->getGroupFromRoute($route_match); /** @var \Drupal\og\Entity\OgMembership $og_membership */ $og_membership = OgMembership::create([ - 'type' => $membership_type->id(), + 'type' => $membership_type, 'entity_type' => $group->getEntityType()->id(), 'entity_id' => $group->id(), ]); @@ -112,4 +133,37 @@ public function addForm(RouteMatchInterface $route_match) { return $this->entityFormBuilder()->getForm($og_membership, 'add'); } + /** + * Determines the group associated with a route using this controller. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match service. + * + * @return \Drupal\Core\Entity\EntityInterface + * The group entity associated with the route. + */ + protected function getGroupFromRoute(RouteMatchInterface $route_match) { + $group = NULL; + + if ($group_type_id = $route_match->getRouteObject()->getOption('_og_entity_type_id')) { + $group = $route_match->getParameter($group_type_id); + } + + $entity_type = $route_match->getParameter('entity_type_id'); + $group_id = $route_match->getParameter('group'); + if ($entity_type && $group_id) { + $group = $this->entityTypeManager->getStorage($entity_type)->load($group_id); + } + + if ($group instanceof ContentEntityInterface === FALSE) { + throw new \Exception('No group context was not found in the route match.'); + } + + if (!Og::isGroup($group->getEntityTypeId(), $group->bundle())) { + throw new \Exception('The entity context found in the route match is not a valid group.'); + } + + return $group; + } + } diff --git a/src/Controller/OgAutocompleteController.php b/src/Controller/OgAutocompleteController.php index b8a6fae11..448615ed6 100644 --- a/src/Controller/OgAutocompleteController.php +++ b/src/Controller/OgAutocompleteController.php @@ -5,6 +5,7 @@ use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\Tags; use Drupal\Component\Utility\Unicode; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Entity\EntityAutocompleteMatcher; use Drupal\Core\KeyValueStore\KeyValueStoreInterface; @@ -78,8 +79,8 @@ public static function create(ContainerInterface $container) { * Thrown if the selection settings key is not found in the key/value store * or if it does not match the stored data. */ - public function handleAutocomplete(Request $request, $group, $target_type, $selection_handler, $selection_settings_key) { - $matches = array(); + public function handleAutocomplete(Request $request, EntityInterface $group, $target_type, $selection_handler, $selection_settings_key) { + $matches = []; // Get the typed string from the URL, if it exists. if ($input = $request->query->get('q')) { $typed_string = Tags::explode($input); diff --git a/src/Controller/OgAutocompleteMatcher.php b/src/Controller/OgAutocompleteMatcher.php index 4ccc8854a..4731dca3d 100644 --- a/src/Controller/OgAutocompleteMatcher.php +++ b/src/Controller/OgAutocompleteMatcher.php @@ -77,7 +77,7 @@ public static function create(ContainerInterface $container) { * or if it does not match the stored data. */ public function handleAutocomplete(Request $request, $group, $target_type, $selection_handler, $selection_settings_key) { - $matches = array(); + $matches = []; // Get the typed string from the URL, if it exists. if ($input = $request->query->get('q')) { $typed_string = Tags::explode($input); diff --git a/src/Element/OgAutocomplete.php b/src/Element/OgAutocomplete.php index 395b52059..9047564b8 100644 --- a/src/Element/OgAutocomplete.php +++ b/src/Element/OgAutocomplete.php @@ -3,17 +3,12 @@ namespace Drupal\og\Element; use Drupal\Component\Utility\Crypt; -use Drupal\Component\Utility\Tags; use Drupal\Core\Entity\Element\EntityAutocomplete; -use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface; -use Drupal\Core\Entity\EntityReferenceSelection\SelectionWithAutocreateInterface; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Render\Element\Textfield; use Drupal\Core\Site\Settings; /** - * @todo + * Provides an entity autocomplete with OG group context. * * The #default_value accepted by this element is either an entity object or an * array of entity objects. @@ -22,6 +17,9 @@ */ class OgAutocomplete extends EntityAutocomplete { + /** + * {@inheritdoc} + */ public static function processEntityAutocomplete(array &$element, FormStateInterface $form_state, array &$complete_form) { // Nothing to do if there is no target entity type. if (empty($element['#target_type'])) { @@ -49,13 +47,13 @@ public static function processEntityAutocomplete(array &$element, FormStateInter } $element['#autocomplete_route_name'] = 'og.entity_autocomplete'; - $element['#autocomplete_route_parameters'] = array( + $element['#autocomplete_route_parameters'] = [ 'target_type' => $element['#target_type'], 'selection_handler' => $element['#selection_handler'], 'selection_settings_key' => $selection_settings_key, 'entity_type_id' => $element['#og_group']->getEntityTypeId(), 'group' => $element['#og_group']->id(), - ); + ]; return $element; } diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index 594ac9706..3e40b1e87 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -67,6 +67,7 @@ * "bundle" = "type", * }, * handlers = { + * "access" = "Drupal\og\OgMembershipAccessControlHandler", * "views_data" = "Drupal\og\OgMembershipViewsData", * "list_builder" = "Drupal\Core\Entity\EntityListBuilder", * "view_builder" = "Drupal\Core\Entity\EntityViewBuilder", @@ -384,7 +385,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setSetting('handler', 'og:user') ->setConstraints(['UniqueOgMembership' => []]) ->setDisplayOptions('form', [ - 'type' => 'entity_reference_autocomplete', + 'type' => 'og_autocomplete', 'weight' => -1, 'settings' => [ 'match_operator' => 'CONTAINS', diff --git a/src/Entity/OgMembershipType.php b/src/Entity/OgMembershipType.php index 1f7eb957a..c725e8bf6 100644 --- a/src/Entity/OgMembershipType.php +++ b/src/Entity/OgMembershipType.php @@ -3,6 +3,7 @@ namespace Drupal\og\Entity; use Drupal\Core\Config\Entity\ConfigEntityBase; +use Drupal\field\Entity\FieldConfig; use Drupal\og\OgMembershipTypeInterface; /** @@ -62,4 +63,35 @@ public function id() { return $this->type; } + /** + * {@inheritdoc} + */ + public function save() { + $status = parent::save(); + + if ($status === SAVED_NEW) { + FieldConfig::create([ + 'field_name' => 'og_membership_request', + 'entity_type' => 'og_membership', + 'bundle' => $this->id(), + 'label' => 'Request Membership', + 'description' => 'Explain the motivation for your request to join this group.', + 'translatable' => TRUE, + 'settings' => [], + ])->save(); + } + + return $status; + } + + /** + * {@inheritdoc} + */ + public function delete() { + if ($this->id() === 'default') { + throw \Exception("The default OG membership type cannot be deleted."); + } + parent::delete(); + } + } diff --git a/src/EventSubscriber/OgEventSubscriber.php b/src/EventSubscriber/OgEventSubscriber.php index 22a2a9b34..b0f495890 100644 --- a/src/EventSubscriber/OgEventSubscriber.php +++ b/src/EventSubscriber/OgEventSubscriber.php @@ -367,9 +367,8 @@ public function provideOgAdminRoutes(OgAdminRoutesEventInterface $event) { 'controller' => '\Drupal\og\Controller\OgAdminMembersController::addPage', 'title' => 'Add member', 'path' => 'members/add', - // @TODO switch to an entity create access callback once it works better. 'requirements' => [ - '_og_user_access_group' => 'administer group|manage members|add user', + '_og_membership_add_access' => 'TRUE', ], ]; diff --git a/src/Form/OgMembershipDeleteForm.php b/src/Form/OgMembershipDeleteForm.php index 5e905b99b..a5b84b0dd 100644 --- a/src/Form/OgMembershipDeleteForm.php +++ b/src/Form/OgMembershipDeleteForm.php @@ -3,7 +3,6 @@ namespace Drupal\og\Form; use Drupal\Core\Entity\ContentEntityDeleteForm; -use Drupal\Core\Form\FormStateInterface; /** * Provides a form for deleting a node. diff --git a/src/Form/OgMembershipForm.php b/src/Form/OgMembershipForm.php index edb2a2fba..00a6adb90 100644 --- a/src/Form/OgMembershipForm.php +++ b/src/Form/OgMembershipForm.php @@ -72,10 +72,10 @@ public function save(array $form, FormStateInterface $form_state) { 'link' => $membership_link, ]; - $t_args = array( + $t_args = [ '%user' => $membership->getUser()->link(), '%group' => $membership->getGroup()->link(), - ); + ]; if ($insert) { $this->logger('og')->notice('OG Membership: added the @membership_type membership for the use uid @uid to the group of the entity-type @group_type and ID @gid.', $context); diff --git a/src/Form/OgMembershipTypeForm.php b/src/Form/OgMembershipTypeForm.php index f34d69dc1..3a6369d08 100644 --- a/src/Form/OgMembershipTypeForm.php +++ b/src/Form/OgMembershipTypeForm.php @@ -9,7 +9,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Form handler for og membership type forms. + * Form handler for OG membership type forms. */ class OgMembershipTypeForm extends BundleEntityFormBase { @@ -50,28 +50,28 @@ public function form(array $form, FormStateInterface $form_state) { $form['#title'] = $this->t('Add membership type'); } else { - $form['#title'] = $this->t('Edit %label membership type', array('%label' => $type->label())); + $form['#title'] = $this->t('Edit %label membership type', ['%label' => $type->label()]); } - $form['name'] = array( + $form['name'] = [ '#title' => $this->t('Name'), '#type' => 'textfield', '#default_value' => $type->label(), '#description' => $this->t('The human-readable name of this membership type.'), '#required' => TRUE, '#size' => 30, - ); + ]; - $form['type'] = array( + $form['type'] = [ '#type' => 'machine_name', '#default_value' => $type->id(), '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH, - '#machine_name' => array( + '#machine_name' => [ 'exists' => ['Drupal\og\Entity\OgMembershipType', 'load'], - 'source' => array('name'), - ), + 'source' => ['name'], + ], '#description' => $this->t('A unique machine-readable name for this membership type. It must only contain lowercase letters, numbers, and underscores.'), - ); + ]; return $this->protectBundleIdElement($form); } @@ -94,7 +94,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) { $id = trim($form_state->getValue('type')); // '0' is invalid, since elsewhere we check it using empty(). if ($id == '0') { - $form_state->setErrorByName('type', $this->t("Invalid machine-readable name. Enter a name other than %invalid.", array('%invalid' => $id))); + $form_state->setErrorByName('type', $this->t("Invalid machine-readable name. Enter a name other than %invalid.", ['%invalid' => $id])); } } @@ -108,19 +108,17 @@ public function save(array $form, FormStateInterface $form_state) { $status = $type->save(); - $t_args = array('%name' => $type->label()); + $t_args = ['%name' => $type->label()]; if ($status == SAVED_UPDATED) { drupal_set_message($this->t('The membership type %name has been updated.', $t_args)); } elseif ($status == SAVED_NEW) { drupal_set_message($this->t('The membership type %name has been added.', $t_args)); - $context = array_merge($t_args, array('link' => $type->link($this->t('View'), 'collection'))); + $context = array_merge($t_args, ['link' => $type->link($this->t('View'), 'collection')]); $this->logger('og')->notice('Added membership type %name.', $context); } - $fields = $this->entityManager->getFieldDefinitions('og_membership', $type->id()); - $this->entityManager->clearCachedFieldDefinitions(); $form_state->setRedirectUrl($type->urlInfo('collection')); } diff --git a/src/OgMembershipAccessControlHandler.php b/src/OgMembershipAccessControlHandler.php new file mode 100644 index 000000000..8938c107a --- /dev/null +++ b/src/OgMembershipAccessControlHandler.php @@ -0,0 +1,155 @@ +entityTypeId = $entity_type->id(); + $this->entityType = $entity_type; + $this->ogAccess = $og_access; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { + return new static( + $entity_type, + $container->get('og.access') + ); + } + + /** + * {@inheritdoc} + */ + protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) { + $group = $entity->getGroup(); + + // Do not allow deleting the group owner's membership. + if (($operation === 'delete') && ($group instanceof EntityOwnerInterface) && ($group->getOwnerId() == $entity->getUser()->id())) { + return AccessResult::forbidden(); + } + + // If the user has permission to administer all groups, allow access. + if ($account->hasPermission('administer group')) { + return AccessResult::allowed(); + } + + $permissions = [OgAccess::ADMINISTER_GROUP_PERMISSION, 'manager members']; + foreach ($permissions as $permission) { + $result = $this->ogAccess->userAccess($group, $permission, $account); + if ($result->isAllowed()) { + return $result; + } + } + + return AccessResult::neutral(); + + } + + /** + * {@inheritdoc} + */ + public function createAccess($entity_bundle = NULL, AccountInterface $account = NULL, array $context = [], $return_as_object = FALSE) { + $account = $this->prepareUser($account); + $context += [ + 'entity_type_id' => $this->entityTypeId, + 'langcode' => LanguageInterface::LANGCODE_DEFAULT, + ]; + + $cid = 'create:' . $context['group']->getEntityTypeId() . ':' . $context['group']->id(); + if ($entity_bundle) { + $cid .= ':' . $entity_bundle; + } + + if (($access = $this->getCache($cid, 'create', $context['langcode'], $account)) !== NULL) { + // Cache hit, no work necessary. + return $return_as_object ? $access : $access->isAllowed(); + } + + // Invoke hook_entity_create_access() and hook_ENTITY_TYPE_create_access(). + // Hook results take precedence over overridden implementations of + // EntityAccessControlHandler::checkCreateAccess(). Entities that have + // checks that need to be done before the hook is invoked should do so by + // overriding this method. + // We grant access to the entity if both of these conditions are met: + // - No modules say to deny access. + // - At least one module says to grant access. + $args = [$account, $context, $entity_bundle]; + $access = array_merge( + $this->moduleHandler()->invokeAll('entity_create_access', $args), + $this->moduleHandler()->invokeAll($this->entityTypeId . '_create_access', $args) + ); + + $return = $this->processAccessHookResults($access); + + // Also execute the default access check except when the access result is + // already forbidden, as in that case, it can not be anything else. + if (!$return->isForbidden()) { + $return = $return->orIf($this->checkCreateAccess($account, $context, $entity_bundle)); + } + $result = $this->setCache($return, $cid, 'create', $context['langcode'], $account); + return $return_as_object ? $result : $result->isAllowed(); + } + + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + // If the user has permission to administer all groups, allow access. + if ($account->hasPermission('administer group')) { + return AccessResult::allowed(); + } + + $group = $context['group']; + + // If we don't have a group, we can't really determine access other than + // checking global account permissions. + if ($group === NULL) { + return AccessResult::neutral(); + } + + $permissions = [ + OgAccess::ADMINISTER_GROUP_PERMISSION, + 'add user', + 'manager members', + ]; + foreach ($permissions as $permission) { + $result = $this->ogAccess->userAccess($group, $permission, $account); + if ($result->isAllowed()) { + return $result; + } + } + + return AccessResult::neutral(); + } + +} diff --git a/src/OgMembershipTypeListBuilder.php b/src/OgMembershipTypeListBuilder.php index efaf58587..47f992ab4 100644 --- a/src/OgMembershipTypeListBuilder.php +++ b/src/OgMembershipTypeListBuilder.php @@ -24,10 +24,10 @@ public function buildHeader() { * {@inheritdoc} */ public function buildRow(EntityInterface $entity) { - $row['title'] = array( + $row['title'] = [ 'data' => $entity->label(), - 'class' => array('menu-label'), - ); + 'class' => ['menu-label'], + ]; return $row + parent::buildRow($entity); } @@ -44,12 +44,4 @@ public function getDefaultOperations(EntityInterface $entity) { return $operations; } - /** - * {@inheritdoc} - */ - public function render() { - $build = parent::render(); - return $build; - } - } diff --git a/src/Plugin/EntityReferenceSelection/OgRoleSelection.php b/src/Plugin/EntityReferenceSelection/OgRoleSelection.php index 1ba446822..fe7dcafe5 100644 --- a/src/Plugin/EntityReferenceSelection/OgRoleSelection.php +++ b/src/Plugin/EntityReferenceSelection/OgRoleSelection.php @@ -35,18 +35,26 @@ public function getSelectionHandler() { protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') { $query = parent::buildEntityQuery($match, $match_operator); - $entity = isset($this->configuration['entity']) ? $this->configuration['entity'] : NULL; - // The entity does not always exist, for example during validation. - // @todo figure out how to always add the full conditions, especially if - // this can be abused to reference incompatible roles. - if (is_null($entity)) { + // @todo implement an easier, more consistent way to get the group type. At + // the moment, this works either for checkboxes or OG Autocomplete widget + // types on entities that have a getGroup() method. It also does not work + // properly every time; for example during validation. + $group = NULL; + if (isset($this->configuration['entity'])) { + $entity = $this->configuration['entity']; + $group = is_callable([$entity, 'getGroup']) ? $entity->getGroup() : NULL; + } + + if (isset($this->configuration['handler_settings']['group'])) { + $group = $this->configuration['handler_settings']['group']; + } + + if ($group === NULL) { return $query; } - $group_type = $entity->getGroupEntityType(); - $group_bundle = $entity->getGroup()->bundle(); - $query->condition('group_type', $group_type, '='); - $query->condition('group_bundle', $group_bundle, '='); + $query->condition('group_type', $group->getEntityTypeId(), '='); + $query->condition('group_bundle', $group->bundle(), '='); $query->condition($query->orConditionGroup() ->condition('role_type', NULL, 'IS NULL') ->condition('role_type', 'required', '<>')); diff --git a/src/Plugin/EntityReferenceSelection/OgUserSelection.php b/src/Plugin/EntityReferenceSelection/OgUserSelection.php index 07f078cca..ebb0a6451 100644 --- a/src/Plugin/EntityReferenceSelection/OgUserSelection.php +++ b/src/Plugin/EntityReferenceSelection/OgUserSelection.php @@ -3,14 +3,11 @@ namespace Drupal\og\Plugin\EntityReferenceSelection; use Drupal\Core\Database\Connection; -use Drupal\Core\Database\Query\SelectInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection; use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; use Drupal\og\MembershipManagerInterface; -use Drupal\user\RoleInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -91,10 +88,11 @@ public static function create(ContainerInterface $container, array $configuratio $container->get('og.membership_manager') ); } + /** * Get the selection handler of the field. * - * @return DefaultSelection + * @return Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection * Returns the selection handler. */ public function getSelectionHandler() { @@ -124,6 +122,10 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') $query->condition('status', 1); } + // @todo implement an easier, more consistent way to get the group type. At + // the moment, this works either for checkboxes or OG Autocomplete widget + // types on entities that have a getGroup() method. It also does not work + // properly every time; for example during validation. $group = NULL; if (isset($this->configuration['entity'])) { $entity = $this->configuration['entity']; @@ -133,8 +135,7 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') if (isset($this->configuration['handler_settings']['group'])) { $group = $this->configuration['handler_settings']['group']; } - // The entity does not always exist, for example during validation. - // @todo figure out how to always add the full conditions. + if ($group === NULL) { return $query; } diff --git a/src/Plugin/Field/FieldWidget/OgAutocomplete.php b/src/Plugin/Field/FieldWidget/OgAutocomplete.php index 7d8a6bfcf..0a2aa4042 100644 --- a/src/Plugin/Field/FieldWidget/OgAutocomplete.php +++ b/src/Plugin/Field/FieldWidget/OgAutocomplete.php @@ -2,20 +2,13 @@ namespace Drupal\og\Plugin\Field\FieldWidget; - use Symfony\Component\Validator\ConstraintViolationInterface; -use Drupal\Component\Utility\Html; -use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Field\FieldFilteredMarkup; use Drupal\Core\Field\FieldItemListInterface; -use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteWidget; use Drupal\Core\Form\FormStateInterface; -use Drupal\og\OgAccess; -use Drupal\user\Entity\User; /** - * Plugin implementation of the 'entity_reference autocomplete' widget. + * Plugin implementation of the 'og_autocomplete' widget. * * @FieldWidget( * id = "og_autocomplete", @@ -45,9 +38,11 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen return $element; } + /** + * {@inheritdoc} + */ public function errorElement(array $element, ConstraintViolationInterface $error, array $form, FormStateInterface $form_state) { return $element; } - } diff --git a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php index 5febf77f9..9f9f50c81 100644 --- a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php @@ -2,7 +2,6 @@ namespace Drupal\og\Plugin\Validation\Constraint; -use Drupal\og\Og; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; diff --git a/src/Plugin/Validation/Constraint/ValidOgRoleConstraint.php b/src/Plugin/Validation/Constraint/ValidOgRoleConstraint.php index 6e66a3f30..6fdbc8bdf 100644 --- a/src/Plugin/Validation/Constraint/ValidOgRoleConstraint.php +++ b/src/Plugin/Validation/Constraint/ValidOgRoleConstraint.php @@ -5,8 +5,7 @@ use Symfony\Component\Validator\Constraint; /** - * @todo - * + * Ensures that a valid OG role for the group entity type/bundle is selected. * * @Constraint( * id = "ValidOgRole", diff --git a/src/Plugin/Validation/Constraint/ValidOgRoleConstraintValidator.php b/src/Plugin/Validation/Constraint/ValidOgRoleConstraintValidator.php index b5e91544e..e54730d80 100644 --- a/src/Plugin/Validation/Constraint/ValidOgRoleConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/ValidOgRoleConstraintValidator.php @@ -2,7 +2,6 @@ namespace Drupal\og\Plugin\Validation\Constraint; -use Drupal\og\Og; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; From 272863c696aaa8e0a3df40de40a13101571d4327 Mon Sep 17 00:00:00 2001 From: Justin Ludwig Date: Thu, 11 May 2017 17:59:11 -0700 Subject: [PATCH 058/111] OG membership UI code cleanup etc based on PR review feedback --- og.module | 15 ++- og.routing.yml | 58 +++++++--- og_ui/og_ui.module | 12 +- src/Access/OgMembershipAddAccessCheck.php | 38 +++--- src/Controller/OgAdminMembersController.php | 96 +++++---------- src/Controller/OgAutocompleteController.php | 2 +- src/Controller/OgAutocompleteMatcher.php | 109 ------------------ src/Entity/OgMembership.php | 4 +- src/Entity/OgMembershipType.php | 3 +- src/Form/OgMembershipDeleteForm.php | 2 +- src/Form/OgMembershipForm.php | 50 +++++++- src/OgMembershipAccessControlHandler.php | 2 +- .../OgRoleSelection.php | 2 +- .../UniqueOgMembershipConstraintValidator.php | 10 +- 14 files changed, 182 insertions(+), 221 deletions(-) delete mode 100644 src/Controller/OgAutocompleteMatcher.php diff --git a/og.module b/og.module index 785b7021c..5e0862f2c 100755 --- a/og.module +++ b/og.module @@ -179,7 +179,7 @@ function og_entity_access(EntityInterface $entity, $operation, AccountInterface */ function og_og_membership_type_access(OgMembershipTypeInterface $entity, $operation, AccountInterface $account) { // Do not allow deleting the default membership type. - if (($operation === 'delete') && ($entity->id() === 'default')) { + if ($operation === 'delete' && $entity->id() === OgMembershipInterface::TYPE_DEFAULT) { return AccessResult::forbidden(); } @@ -191,6 +191,19 @@ function og_og_membership_type_access(OgMembershipTypeInterface $entity, $operat return AccessResult::forbidden(); } +/** + * Implements hook_ENTITY_TYPE_access(). + */ +function og_og_membership_access(OgMembershipInterface $entity, $operation, AccountInterface $account) { + $group = $entity->getGroup(); + if ($operation === 'delete' && $group->get('uid')->entity->id() === $entity->getUser()->id()) { + return AccessResult::forbidden(); + } + + return \Drupal::service('og.access') + ->userAccess($entity->getGroup(), 'manage members'); +} + /** * Implements hook_entity_create_access(). */ diff --git a/og.routing.yml b/og.routing.yml index 1b9e3c959..f4cf16330 100644 --- a/og.routing.yml +++ b/og.routing.yml @@ -1,7 +1,7 @@ # Routes for Organic groups. og.subscribe: - path: 'group/{entity_type_id}/{group}/subscribe/{membership_type}' + path: 'group/{entity_type_id}/{group}/subscribe/{og_membership_type}' defaults: _controller: '\Drupal\og\Controller\SubscriptionController::subscribe' _title: 'Join Group' @@ -15,8 +15,6 @@ og.subscribe: parameters: group: type: entity:{entity_type_id} - membership_type: - type: entity:og_membership_type og.unsubscribe: path: 'group/{entity_type_id}/{group}/unsubscribe' @@ -56,32 +54,49 @@ og.entity_autocomplete: type: entity:{entity_type_id} # OG Membership entity routes -entity.og_membership.canonical: - path: 'group/{entity_type_id}/{group}/admin/members/{og_membership}' - defaults: - _title: 'Membership' - _entity_view: 'og_membership.full' - requirements: - _entity_access: 'og_membership.view' - options: - parameters: - type: entity:{entity_type_id} - entity.og_membership.add_form: - path: 'group/{entity_type_id}/{group}/admin/members/add/{membership_type}' + path: 'group/{entity_type_id}/{group}/admin/members/add/{og_membership_type}' defaults: _controller: '\Drupal\og\Controller\OgAdminMembersController::addForm' _title: 'Add member' requirements: _og_membership_add_access: 'TRUE' options: + _admin_route: 'TRUE' + parameters: + group: + type: entity:{entity_type_id} + og_membership_type: + type: entity:og_membership_type + +# The canonical route is the same as the edit-form route because we need a +# canonical route for various functionality to work properly, but a standard +# entity view for OG memberships tends to feel quite stub-like. +entity.og_membership.canonical: + path: 'group/{entity_type_id}/{group}/admin/members/{og_membership}/edit' + defaults: + _entity_form: 'og_membership.edit' + options: + _admin_route: 'TRUE' parameters: - type: entity:{entity_type_id} + group: + type: entity:{entity_type_id} + og_membership: + type: entity:og_membership + requirements: + _entity_access: 'og_membership.edit' entity.og_membership.edit_form: path: 'group/{entity_type_id}/{group}/admin/members/{og_membership}/edit' defaults: _entity_form: 'og_membership.edit' + options: + _admin_route: 'TRUE' + parameters: + group: + type: entity:{entity_type_id} + og_membership: + type: entity:og_membership requirements: _entity_access: 'og_membership.edit' @@ -89,6 +104,13 @@ entity.og_membership.delete_form: path: 'group/{entity_type_id}/{group}/admin/members/{og_membership}/delete' defaults: _entity_form: 'og_membership.delete' + options: + _admin_route: 'TRUE' + parameters: + group: + type: entity:{entity_type_id} + og_membership: + type: entity:og_membership requirements: _entity_access: 'og_membership.delete' @@ -106,7 +128,7 @@ entity.og_membership_type.edit_form: defaults: _entity_form: 'og_membership_type.edit' requirements: - _entity_access: 'administer group' + _permission: 'administer group' entity.og_membership_type.delete_form: path: '/admin/structure/membership-types/manage/{og_membership_type}/delete' @@ -114,7 +136,7 @@ entity.og_membership_type.delete_form: _entity_form: 'og_membership_type.delete' _title: 'Delete' requirements: - _entity_access: 'og_membership_type.delete' + _permission: 'og_membership_type.delete' og_membership.type_add: path: '/admin/structure/membership-types/add' diff --git a/og_ui/og_ui.module b/og_ui/og_ui.module index f319c4ed0..f09da9234 100644 --- a/og_ui/og_ui.module +++ b/og_ui/og_ui.module @@ -19,10 +19,16 @@ use Drupal\og_ui\BundleFormAlter; * Implements hook_form_alter(). */ function og_ui_form_alter(array &$form, FormStateInterface $form_state, $form_id) { - if ($form_state->getFormObject() instanceof BundleEntityFormBase) { - (new BundleFormAlter($form_state->getFormObject()->getEntity())) - ->formAlter($form, $form_state); + if (!$form_state->getFormObject() instanceof BundleEntityFormBase) { + return; } + + $entity_type = $form_state->getFormObject()->getEntity(); + if ($entity_type->getEntityTypeId() === 'og_membership_type') { + return; + } + + (new BundleFormAlter($entity_type))->formAlter($form, $form_state); } /** diff --git a/src/Access/OgMembershipAddAccessCheck.php b/src/Access/OgMembershipAddAccessCheck.php index 4eccfe310..922543e5b 100644 --- a/src/Access/OgMembershipAddAccessCheck.php +++ b/src/Access/OgMembershipAddAccessCheck.php @@ -2,14 +2,18 @@ namespace Drupal\og\Access; +use Drupal\Core\Access\AccessResult; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Routing\Access\AccessInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Session\AccountInterface; -use Symfony\Component\Routing\Route; +use Drupal\og\Og; +use Drupal\og\OgMembershipInterface; +use Drupal\og\OgMembershipTypeInterface; /** - * Determines access to for node add pages. + * Determines access to for membership add pages. */ class OgMembershipAddAccessCheck implements AccessInterface { @@ -37,31 +41,37 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager) { * The parametrized route. * @param \Drupal\Core\Session\AccountInterface $account * The currently logged in account. + * @param \Drupal\Core\Entity\EntityInterface $group + * The group entity. + * @param \Drupal\og\OgMembershipTypeInterface $og_membership_type + * The membership type entity. * * @return \Drupal\Core\Access\AccessResultInterface * The access result. */ - public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) { - $og_membership_type = $route_match->getParameter('membership_type'); - if (is_object($og_membership_type)) { - $og_membership_type = $og_membership_type->id(); + public function access(RouteMatchInterface $route_match, AccountInterface $account, EntityInterface $group = NULL, OgMembershipTypeInterface $og_membership_type = NULL) { + // The $group param will be null if it is from the + // Drupal\og\Event\OgAdminRoutesEvent rather than the routing.yml version. + if (is_null($group)) { + $entity_type_id = $route_match->getRouteObject() + ->getOption('_og_entity_type_id'); + $group = $route_match->getParameter($entity_type_id); } - if ($entity_type_id = $route_match->getParameter('entity_type_id')) { - $group = $this->entityTypeManager - ->getStorage($route_match->getParameter('entity_type_id')) - ->load($route_match->getParameter('group')); + if (!Og::isGroup($group->getEntityTypeId(), $group->bundle())) { + return AccessResult::forbidden(); } - else { - $entity_type_id = $route->getOption('_og_entity_type_id'); - $group = $route_match->getParameter($entity_type_id); + + $membership_type_id = OgMembershipInterface::TYPE_DEFAULT; + if (!is_null($og_membership_type)) { + $membership_type_id = $og_membership_type->id(); } $context = ['group' => $group]; return $this->entityTypeManager ->getAccessControlHandler('og_membership') - ->createAccess($og_membership_type, $account, $context, TRUE); + ->createAccess($membership_type_id, $account, $context, TRUE); } } diff --git a/src/Controller/OgAdminMembersController.php b/src/Controller/OgAdminMembersController.php index fc2d1301f..51e73114b 100644 --- a/src/Controller/OgAdminMembersController.php +++ b/src/Controller/OgAdminMembersController.php @@ -4,11 +4,14 @@ use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Link; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\og\Entity\OgMembership; use Drupal\og\Og; +use Drupal\og\OgMembershipInterface; +use Drupal\og\OgMembershipTypeInterface; use Drupal\views\Views; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -53,9 +56,8 @@ public static function create(ContainerInterface $container) { * The members overview View. */ public function membersList(RouteMatchInterface $route_match) { - /** @var \Drupal\Core\Entity\EntityInterface $group */ - $group = $this->getGroupFromRoute($route_match); - + $group_type_id = $route_match->getRouteObject()->getOption('_og_entity_type_id'); + $group = $route_match->getParameter($group_type_id); $arguments = [$group->getEntityTypeId(), $group->id()]; return Views::getView('og_members_overview')->executeDisplay('default', $arguments); } @@ -66,14 +68,22 @@ public function membersList(RouteMatchInterface $route_match) { * Returns default membership type if that's all that exists. * * @return array - * A render array for a list of the node types that can be added; however, - * if there is only one node type defined for the site, the function - * will return the default add member form. + * A render array for a list of the og membership types that can be added; + * however, if there is only one og membership type defined for the site, + * the function will return the default add member form. */ public function addPage(RouteMatchInterface $route_match) { - $membership_type_list = $this->entityTypeManager()->getStorage('og_membership_type')->loadMultiple(); - if ($membership_type_list && count($membership_type_list) == 1) { - return $this->addForm($route_match); + $entity_type_id = $route_match->getRouteObject() + ->getOption('_og_entity_type_id'); + + $group = $route_match->getParameter($entity_type_id); + + $membership_types = $this->entityTypeManager + ->getStorage('og_membership_type') + ->loadMultiple(); + + if ($membership_types && count($membership_types) == 1) { + return $this->addForm($group, $membership_types[OgMembershipInterface::TYPE_DEFAULT]); } $build = [ @@ -81,21 +91,21 @@ public function addPage(RouteMatchInterface $route_match) { '#bundles' => [], ]; - $bundle_entity_type = $this->entityTypeManager()->getDefinition('og_membership_type'); - $build['#cache']['tags'] = $bundle_entity_type->getListCacheTags(); - - $group = $this->getGroupFromRoute($route_match); + $build['#cache']['tags'] = $this->entityTypeManager + ->getDefinition('og_membership_type') + ->getListCacheTags(); $add_link_params = [ 'group' => $group->id(), 'entity_type_id' => $group->getEntityType()->id(), ]; - foreach ($membership_type_list as $membership_type_id => $og_membership_type) { - $add_link_params['membership_type'] = $membership_type_id; + foreach ($membership_types as $membership_type_id => $og_membership_type) { + $add_link_params['og_membership_type'] = $membership_type_id; $build['#bundles'][$membership_type_id] = [ 'label' => $og_membership_type->label(), - 'add_link' => Link::createFromRoute($og_membership_type->label(), "entity.og_membership.add_form", $add_link_params), + 'description' => NULL, + 'add_link' => Link::createFromRoute($og_membership_type->label(), 'entity.og_membership.add_form', $add_link_params), ]; } @@ -105,27 +115,18 @@ public function addPage(RouteMatchInterface $route_match) { /** * Provides the add member submission form. * - * @param \Drupal\Core\Routing\RouteMatchInterface $route_match - * The route match service. + * @param \Drupal\Core\Entity\EntityInterface $group + * The group entity. + * @param \Drupal\og\OgMembershipTypeInterface $og_membership_type + * The membership type entity. * * @return array * The member add form. */ - public function addForm(RouteMatchInterface $route_match) { - /** @var \Drupal\og\Entity\OgMembershipType $membership_type */ - $membership_type = $route_match->getParameter('membership_type'); - if (is_object($membership_type)) { - $membership_type = $membership_type->id(); - } - if ($membership_type === NULL) { - $membership_type = 'default'; - } - - $group = $this->getGroupFromRoute($route_match); - + public function addForm(EntityInterface $group, OgMembershipTypeInterface $og_membership_type) { /** @var \Drupal\og\Entity\OgMembership $og_membership */ $og_membership = OgMembership::create([ - 'type' => $membership_type, + 'type' => $og_membership_type->id(), 'entity_type' => $group->getEntityType()->id(), 'entity_id' => $group->id(), ]); @@ -133,37 +134,4 @@ public function addForm(RouteMatchInterface $route_match) { return $this->entityFormBuilder()->getForm($og_membership, 'add'); } - /** - * Determines the group associated with a route using this controller. - * - * @param \Drupal\Core\Routing\RouteMatchInterface $route_match - * The route match service. - * - * @return \Drupal\Core\Entity\EntityInterface - * The group entity associated with the route. - */ - protected function getGroupFromRoute(RouteMatchInterface $route_match) { - $group = NULL; - - if ($group_type_id = $route_match->getRouteObject()->getOption('_og_entity_type_id')) { - $group = $route_match->getParameter($group_type_id); - } - - $entity_type = $route_match->getParameter('entity_type_id'); - $group_id = $route_match->getParameter('group'); - if ($entity_type && $group_id) { - $group = $this->entityTypeManager->getStorage($entity_type)->load($group_id); - } - - if ($group instanceof ContentEntityInterface === FALSE) { - throw new \Exception('No group context was not found in the route match.'); - } - - if (!Og::isGroup($group->getEntityTypeId(), $group->bundle())) { - throw new \Exception('The entity context found in the route match is not a valid group.'); - } - - return $group; - } - } diff --git a/src/Controller/OgAutocompleteController.php b/src/Controller/OgAutocompleteController.php index 448615ed6..7f976976e 100644 --- a/src/Controller/OgAutocompleteController.php +++ b/src/Controller/OgAutocompleteController.php @@ -16,7 +16,7 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; /** - * Defines a route controller for entity autocomplete form elements. + * Defines a route controller for OG autocomplete form elements. */ class OgAutocompleteController extends ControllerBase { diff --git a/src/Controller/OgAutocompleteMatcher.php b/src/Controller/OgAutocompleteMatcher.php deleted file mode 100644 index 4731dca3d..000000000 --- a/src/Controller/OgAutocompleteMatcher.php +++ /dev/null @@ -1,109 +0,0 @@ -matcher = $matcher; - $this->keyValue = $key_value; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('entity.autocomplete_matcher'), - $container->get('keyvalue')->get('entity_autocomplete') - ); - } - - /** - * Autocomplete the label of an entity. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * The request object that contains the typed tags. - * @param string $target_type - * The ID of the target entity type. - * @param string $selection_handler - * The plugin ID of the entity reference selection handler. - * @param string $selection_settings_key - * The hashed key of the key/value entry that holds the selection handler - * settings. - * - * @return \Symfony\Component\HttpFoundation\JsonResponse - * The matched entity labels as a JSON response. - * - * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException - * Thrown if the selection settings key is not found in the key/value store - * or if it does not match the stored data. - */ - public function handleAutocomplete(Request $request, $group, $target_type, $selection_handler, $selection_settings_key) { - $matches = []; - // Get the typed string from the URL, if it exists. - if ($input = $request->query->get('q')) { - $typed_string = Tags::explode($input); - $typed_string = Unicode::strtolower(array_pop($typed_string)); - - // Selection settings are passed in as a hashed key of a serialized array - // stored in the key/value store. - $selection_settings = $this->keyValue->get($selection_settings_key, FALSE); - if ($selection_settings !== FALSE) { - $selection_settings_hash = Crypt::hmacBase64(serialize($selection_settings) . $target_type . $selection_handler, Settings::getHashSalt()); - if ($selection_settings_hash !== $selection_settings_key) { - // Disallow access when the selection settings hash does not match the - // passed-in key. - throw new AccessDeniedHttpException('Invalid selection settings key.'); - } - } - else { - // Disallow access when the selection settings key is not found in the - // key/value store. - throw new AccessDeniedHttpException(); - } - - $matches = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string); - } - - return new JsonResponse($matches); - } - -} diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index 3e40b1e87..0b8448948 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -82,7 +82,7 @@ * links = { * "edit-form" = "/group/{entity_type_id}/{group}/admin/members/{og_membership}/edit", * "delete-form" = "/group/{entity_type_id}/{group}/admin/members/{og_membership}/delete", - * "canonical" = "/group/{entity_type_id}/{group}/admin/members/{og_membership}" + * "canonical" = "/group/{entity_type_id}/{group}/admin/members/{og_membership}/edit" * }, * field_ui_base_route = "entity.og_membership_type.edit_form" * ) @@ -379,7 +379,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setSetting('target_type', 'og_membership_type'); $fields['uid'] = BaseFieldDefinition::create('entity_reference') - ->setLabel(t('Member User ID')) + ->setLabel(t('Username')) ->setDescription(t('The user ID of the member.')) ->setSetting('target_type', 'user') ->setSetting('handler', 'og:user') diff --git a/src/Entity/OgMembershipType.php b/src/Entity/OgMembershipType.php index c725e8bf6..ad106a40a 100644 --- a/src/Entity/OgMembershipType.php +++ b/src/Entity/OgMembershipType.php @@ -4,6 +4,7 @@ use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\field\Entity\FieldConfig; +use Drupal\og\OgMembershipInterface; use Drupal\og\OgMembershipTypeInterface; /** @@ -88,7 +89,7 @@ public function save() { * {@inheritdoc} */ public function delete() { - if ($this->id() === 'default') { + if ($this->id() === OgMembershipInterface::TYPE_DEFAULT) { throw \Exception("The default OG membership type cannot be deleted."); } parent::delete(); diff --git a/src/Form/OgMembershipDeleteForm.php b/src/Form/OgMembershipDeleteForm.php index a5b84b0dd..72ea01e7f 100644 --- a/src/Form/OgMembershipDeleteForm.php +++ b/src/Form/OgMembershipDeleteForm.php @@ -5,7 +5,7 @@ use Drupal\Core\Entity\ContentEntityDeleteForm; /** - * Provides a form for deleting a node. + * Provides a form for deleting an OG membership. */ class OgMembershipDeleteForm extends ContentEntityDeleteForm { diff --git a/src/Form/OgMembershipForm.php b/src/Form/OgMembershipForm.php index 00a6adb90..27d6d6331 100644 --- a/src/Form/OgMembershipForm.php +++ b/src/Form/OgMembershipForm.php @@ -2,8 +2,14 @@ namespace Drupal\og\Form; +use Drupal\Component\Datetime\TimeInterface; use Drupal\Core\Entity\ContentEntityForm; +use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Form\FormStateInterface; +use Drupal\og\OgAccessInterface; +use Drupal\og\OgMembershipInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Form controller for the group content edit forms. @@ -12,6 +18,42 @@ */ class OgMembershipForm extends ContentEntityForm { + /** + * The OG access service. + * + * @var \Drupal\og\OgAccess + */ + protected $ogAccess; + + /** + * Constructs a MessageForm object. + * + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. + * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info + * The entity type bundle service. + * @param \Drupal\Component\Datetime\TimeInterface $time + * The time service. + * @param \Drupal\og\OgAccessInterface $og_access + * The OG access service. + */ + public function __construct(EntityManagerInterface $entity_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, OgAccessInterface $og_access) { + parent::__construct($entity_manager, $entity_type_bundle_info, $time); + $this->ogAccess = $og_access; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.manager'), + $container->get('entity_type.bundle.info'), + $container->get('datetime.time'), + $container->get('og.access') + ); + } + /** * {@inheritdoc} */ @@ -26,11 +68,11 @@ public function form(array $form, FormStateInterface $form_state) { $form['entity_type'] = ['#value' => $entity->getEntityType()->id()]; $form['entity_id'] = ['#value' => $group->id()]; - if ($entity->getType() != 'default') { + if ($entity->getType() != OgMembershipInterface::TYPE_DEFAULT) { $form['membership_type'] = [ '#title' => $this->t('Membership type'), '#type' => 'item', - '#markup' => $entity->type->entity->label(), + '#plain_text' => $entity->type->entity->label(), '#weight' => -2, ]; } @@ -39,7 +81,7 @@ public function form(array $form, FormStateInterface $form_state) { $form['#title'] = $this->t('Edit membership in %group', ['%group' => $group->label()]); $form['uid']['#access'] = FALSE; $form['member'] = [ - '#title' => t('Member name'), + '#title' => $this->t('Member name'), '#type' => 'item', '#markup' => $entity->getUser()->getDisplayName(), '#weight' => -10, @@ -47,7 +89,7 @@ public function form(array $form, FormStateInterface $form_state) { } // Require the 'manage members' permission to be able to edit roles. - $form['roles']['#access'] = \Drupal::service('og.access') + $form['roles']['#access'] = $this->ogAccess ->userAccess($group, 'manage members') ->isAllowed(); diff --git a/src/OgMembershipAccessControlHandler.php b/src/OgMembershipAccessControlHandler.php index 8938c107a..97688aae3 100644 --- a/src/OgMembershipAccessControlHandler.php +++ b/src/OgMembershipAccessControlHandler.php @@ -12,7 +12,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Defines a default implementation for entity access control handler. + * Defines the OG membershipimplementation for entity access control handler. */ class OgMembershipAccessControlHandler extends EntityAccessControlHandler implements EntityHandlerInterface { diff --git a/src/Plugin/EntityReferenceSelection/OgRoleSelection.php b/src/Plugin/EntityReferenceSelection/OgRoleSelection.php index fe7dcafe5..c6f2a52f8 100644 --- a/src/Plugin/EntityReferenceSelection/OgRoleSelection.php +++ b/src/Plugin/EntityReferenceSelection/OgRoleSelection.php @@ -19,7 +19,7 @@ class OgRoleSelection extends DefaultSelection { /** * Get the selection handler of the field. * - * @return DefaultSelection + * @return Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection * Returns the selection handler. */ public function getSelectionHandler() { diff --git a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php index 9f9f50c81..63ee80d08 100644 --- a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php @@ -19,13 +19,21 @@ public function validate($value, Constraint $constraint) { return; } + /* @var \Drupal\og\Entity\OgMembership $entity */ $entity = $value->getEntity(); + // Only applicable to new memberships. if (!$entity->isNew()) { return; } - $new_member_uid = $value->getValue()[0]['target_id']; + // The default entity reference constraint adds a violation in this case. + $value = $value->getValue(); + if (!isset($value[0]) || !isset($value[0]['target_id'])) { + return; + } + + $new_member_uid = $value[0]['target_id']; $membership_manager = \Drupal::service('og.membership_manager'); foreach ($membership_manager->getGroupMemberships($entity->getGroup()) as $membership) { if ((string) $membership->getUser()->id() === (string) $new_member_uid) { From bdb22b2f8e676dd98f3d6250fe2f9d070458ff14 Mon Sep 17 00:00:00 2001 From: Justin Ludwig Date: Sat, 13 May 2017 02:15:23 -0700 Subject: [PATCH 059/111] Additional OG membership UI tweaks and fixes. --- og.links.action.yml | 5 +- og.module | 13 ++- src/Entity/OgMembership.php | 18 +++- src/Og.php | 17 ++++ src/Plugin/Derivative/OgActionLink.php | 84 +++++++++++++++++++ .../GroupSubscribeFormatter.php | 1 + 6 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 src/Plugin/Derivative/OgActionLink.php diff --git a/og.links.action.yml b/og.links.action.yml index 255492af4..c70c87d8a 100644 --- a/og.links.action.yml +++ b/og.links.action.yml @@ -1,8 +1,5 @@ og_membership.add: - route_name: entity.node.og_admin_routes.add_membership_page - title: 'Add a member' - appears_on: - - entity.node.og_admin_routes.members + deriver: \Drupal\og\Plugin\Derivative\OgActionLink og_membership.type_add: route_name: og_membership.type_add diff --git a/og.module b/og.module index 5e0862f2c..c578e6408 100755 --- a/og.module +++ b/og.module @@ -196,7 +196,18 @@ function og_og_membership_type_access(OgMembershipTypeInterface $entity, $operat */ function og_og_membership_access(OgMembershipInterface $entity, $operation, AccountInterface $account) { $group = $entity->getGroup(); - if ($operation === 'delete' && $group->get('uid')->entity->id() === $entity->getUser()->id()) { + + // If there's a group owner, don't let them leave. + if ( + isset($group_fields['uid']) + && $operation === 'delete' + && $group_fields['uid']->entity->id() === $entity->getUser()->id() + ) { + return AccessResult::forbidden(); + } + + // Ensure that there's at least one member in the group. + if ($operation === 'delete' && count(Og::getGroupMemberships($group)) === 1) { return AccessResult::forbidden(); } diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index 0b8448948..30fa58d4e 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -409,10 +409,24 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setLabel(t('Group entity ID')) ->setDescription(t('The entity ID of the group.')); - $fields['state'] = BaseFieldDefinition::create('string') + $fields['state'] = BaseFieldDefinition::create('list_string') ->setLabel(t('State')) ->setDescription(t('The user membership state: active, pending, or blocked.')) - ->setDefaultValue(OgMembershipInterface::STATE_ACTIVE); + ->setDefaultValue(OgMembershipInterface::STATE_ACTIVE) + ->setSettings([ + 'allowed_values' => [ + OgMembershipInterface::STATE_ACTIVE => t('Active'), + OgMembershipInterface::STATE_PENDING => t('Pending'), + OgMembershipInterface::STATE_BLOCKED => t('Blocked'), + ], + ]) + ->setDisplayOptions('form', [ + 'type' => 'options_buttons', + 'weight' => 0, + ]) + ->setDisplayConfigurable('view', TRUE) + ->setDisplayConfigurable('form', TRUE) + ->setRequired(TRUE); $fields['roles'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Roles')) diff --git a/src/Og.php b/src/Og.php index a29d30682..da330c192 100644 --- a/src/Og.php +++ b/src/Og.php @@ -168,6 +168,23 @@ public static function getMembership(EntityInterface $group, AccountInterface $u return $membership_manager->getMembership($group, $user, $states); } + /** + * Returns the group memberships for a given group. + * + * @param \Drupal\Core\Entity\EntityInterface $group + * The group to get the membership for. + * @param array $states + * (optional) Array with the state to return. Defaults to active. + * + * @return \Drupal\og\OgMembershipInterface[] + * An array of OgMembership entities, keyed by ID. + */ + public static function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]) { + /** @var \Drupal\og\MembershipManagerInterface $membership_manager */ + $membership_manager = \Drupal::service('og.membership_manager'); + return $membership_manager->getGroupMemberships($group, $states); + } + /** * Creates an OG membership. * diff --git a/src/Plugin/Derivative/OgActionLink.php b/src/Plugin/Derivative/OgActionLink.php new file mode 100644 index 000000000..cd2ca2f73 --- /dev/null +++ b/src/Plugin/Derivative/OgActionLink.php @@ -0,0 +1,84 @@ +groupTypeManager = $group_type_manager; + $this->routeProvider = $route_provider; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static( + $container->get('og.group_type_manager'), + $container->get('router.route_provider') + ); + } + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions($base_plugin_definition) { + $derivatives = []; + + foreach (array_keys($this->groupTypeManager->getGroupMap()) as $entity_type_id) { + $route_name = "entity.$entity_type_id.og_admin_routes.add_membership_page"; + + if (!$this->routeProvider->getRoutesByNames([$route_name])) { + // Route not found. + continue; + } + + $derivatives["og_membership.$entity_type_id.add"] = [ + 'route_name' => $route_name, + 'title' => $this->t('Add a member'), + 'appears_on' => ["entity.$entity_type_id.og_admin_routes.members"], + ]; + } + + foreach ($derivatives as &$entry) { + $entry += $base_plugin_definition; + } + + return $derivatives; + } + +} diff --git a/src/Plugin/Field/FieldFormatter/GroupSubscribeFormatter.php b/src/Plugin/Field/FieldFormatter/GroupSubscribeFormatter.php index ab3431c3d..ca19e00d4 100644 --- a/src/Plugin/Field/FieldFormatter/GroupSubscribeFormatter.php +++ b/src/Plugin/Field/FieldFormatter/GroupSubscribeFormatter.php @@ -141,6 +141,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) { $parameters = [ 'entity_type_id' => $group->getEntityTypeId(), 'group' => $group->id(), + 'og_membership_type' => OgMembershipInterface::TYPE_DEFAULT, ]; $url = Url::fromRoute('og.subscribe', $parameters); From 0ebb8f5d744fea181d97e3df67fc439fee5f1302 Mon Sep 17 00:00:00 2001 From: Justin Ludwig Date: Thu, 1 Jun 2017 13:26:43 -0700 Subject: [PATCH 060/111] OG Membership UI: Fixes PluginNotFoundException in tests. --- og.routing.yml | 10 +--------- src/Controller/OgAdminMembersController.php | 2 -- src/Controller/SubscriptionController.php | 6 +++--- tests/src/Functional/GroupSubscribeFormatterTest.php | 2 +- tests/src/Kernel/Access/AccessByOgMembershipTest.php | 1 + tests/src/Kernel/Access/OgAccessHookTest.php | 1 + tests/src/Kernel/Access/OgEntityAccessTest.php | 1 + .../Access/OgGroupContentOperationAccessTest.php | 1 + tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php | 1 + tests/src/Kernel/Entity/EntityCreateAccessTest.php | 1 + tests/src/Kernel/Entity/GetBundleByBundleTest.php | 1 + tests/src/Kernel/Entity/GetGroupContentTest.php | 1 + tests/src/Kernel/Entity/GetMembershipsTest.php | 1 + tests/src/Kernel/Entity/GetUserGroupsTest.php | 1 + tests/src/Kernel/Entity/GroupAudienceTest.php | 1 + tests/src/Kernel/Entity/GroupMembershipManagerTest.php | 1 + tests/src/Kernel/Entity/GroupTypeTest.php | 2 +- .../Kernel/Entity/OgMembershipRoleReferenceTest.php | 5 +++-- tests/src/Kernel/Entity/OgMembershipTest.php | 1 + tests/src/Kernel/Entity/OgRoleTest.php | 1 + .../src/Kernel/Entity/OgStandardReferenceItemTest.php | 9 ++++++++- tests/src/Kernel/Entity/ReferenceStringIdTest.php | 9 ++++++++- tests/src/Kernel/Entity/SelectionHandlerTest.php | 1 + .../Views/OgStandardReferenceRelationshipTest.php | 1 + tests/src/Kernel/Form/GroupSubscribeFormTest.php | 1 + tests/src/Kernel/GroupTypeConditionTest.php | 1 + tests/src/Kernel/OgDeleteOrphansTest.php | 1 + tests/src/Kernel/OgRoleManagerTest.php | 1 + 28 files changed, 45 insertions(+), 20 deletions(-) diff --git a/og.routing.yml b/og.routing.yml index f4cf16330..df629a9e6 100644 --- a/og.routing.yml +++ b/og.routing.yml @@ -5,7 +5,7 @@ og.subscribe: defaults: _controller: '\Drupal\og\Controller\SubscriptionController::subscribe' _title: 'Join Group' - membership_type: default + og_membership_type: default requirements: # Only authenticated users can subscribe to group, but we do allow anonymous # users to reach this route. They will be redirect to login page or be given @@ -66,8 +66,6 @@ entity.og_membership.add_form: parameters: group: type: entity:{entity_type_id} - og_membership_type: - type: entity:og_membership_type # The canonical route is the same as the edit-form route because we need a # canonical route for various functionality to work properly, but a standard @@ -81,8 +79,6 @@ entity.og_membership.canonical: parameters: group: type: entity:{entity_type_id} - og_membership: - type: entity:og_membership requirements: _entity_access: 'og_membership.edit' @@ -95,8 +91,6 @@ entity.og_membership.edit_form: parameters: group: type: entity:{entity_type_id} - og_membership: - type: entity:og_membership requirements: _entity_access: 'og_membership.edit' @@ -109,8 +103,6 @@ entity.og_membership.delete_form: parameters: group: type: entity:{entity_type_id} - og_membership: - type: entity:og_membership requirements: _entity_access: 'og_membership.delete' diff --git a/src/Controller/OgAdminMembersController.php b/src/Controller/OgAdminMembersController.php index 51e73114b..0fc4b48bf 100644 --- a/src/Controller/OgAdminMembersController.php +++ b/src/Controller/OgAdminMembersController.php @@ -3,13 +3,11 @@ namespace Drupal\og\Controller; use Drupal\Core\Controller\ControllerBase; -use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Link; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\og\Entity\OgMembership; -use Drupal\og\Og; use Drupal\og\OgMembershipInterface; use Drupal\og\OgMembershipTypeInterface; use Drupal\views\Views; diff --git a/src/Controller/SubscriptionController.php b/src/Controller/SubscriptionController.php index 62c793f52..e32831ded 100644 --- a/src/Controller/SubscriptionController.php +++ b/src/Controller/SubscriptionController.php @@ -66,14 +66,14 @@ public static function create(ContainerInterface $container) { * The entity type of the group entity. * @param \Drupal\Core\Entity\EntityInterface $group * The entity ID of the group entity. - * @param \Drupal\og\OgMembershipTypeInterface $membership_type + * @param \Drupal\og\OgMembershipTypeInterface $og_membership_type * The membership type to be used for creating the membership. * * @return mixed * Redirect user or show access denied if they are not allowed to subscribe, * otherwise provide a subscribe confirmation form. */ - public function subscribe($entity_type_id, EntityInterface $group, OgMembershipTypeInterface $membership_type) { + public function subscribe($entity_type_id, EntityInterface $group, OgMembershipTypeInterface $og_membership_type) { if (!$group instanceof ContentEntityInterface) { // Not a valid entity. throw new AccessDeniedHttpException(); @@ -138,7 +138,7 @@ public function subscribe($entity_type_id, EntityInterface $group, OgMembershipT throw new AccessDeniedHttpException(); } - $membership = Og::createMembership($group, $user, $membership_type->id()); + $membership = Og::createMembership($group, $user, $og_membership_type->id()); $form = $this->entityFormBuilder()->getForm($membership, 'subscribe'); return $form; diff --git a/tests/src/Functional/GroupSubscribeFormatterTest.php b/tests/src/Functional/GroupSubscribeFormatterTest.php index 04cccc0ca..11a092880 100644 --- a/tests/src/Functional/GroupSubscribeFormatterTest.php +++ b/tests/src/Functional/GroupSubscribeFormatterTest.php @@ -19,7 +19,7 @@ class GroupSubscribeFormatterTest extends BrowserTestBase { /** * {@inheritdoc} */ - public static $modules = ['node', 'og']; + public static $modules = ['node', 'og', 'options']; /** * Test entity group. diff --git a/tests/src/Kernel/Access/AccessByOgMembershipTest.php b/tests/src/Kernel/Access/AccessByOgMembershipTest.php index 37c50ead3..0594d0a07 100644 --- a/tests/src/Kernel/Access/AccessByOgMembershipTest.php +++ b/tests/src/Kernel/Access/AccessByOgMembershipTest.php @@ -36,6 +36,7 @@ class AccessByOgMembershipTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Access/OgAccessHookTest.php b/tests/src/Kernel/Access/OgAccessHookTest.php index 275770da7..799e05088 100644 --- a/tests/src/Kernel/Access/OgAccessHookTest.php +++ b/tests/src/Kernel/Access/OgAccessHookTest.php @@ -33,6 +33,7 @@ class OgAccessHookTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Access/OgEntityAccessTest.php b/tests/src/Kernel/Access/OgEntityAccessTest.php index b26be94a0..ddd86d6e7 100644 --- a/tests/src/Kernel/Access/OgEntityAccessTest.php +++ b/tests/src/Kernel/Access/OgEntityAccessTest.php @@ -25,6 +25,7 @@ class OgEntityAccessTest extends KernelTestBase { 'user', 'field', 'og', + 'options', 'entity_test', ]; diff --git a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php index 001ec3815..b70fa6d53 100644 --- a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php +++ b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php @@ -32,6 +32,7 @@ class OgGroupContentOperationAccessTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php b/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php index 99ae6e631..de0471227 100644 --- a/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php +++ b/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php @@ -24,6 +24,7 @@ class DrupalConsoleAddFieldTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Entity/EntityCreateAccessTest.php b/tests/src/Kernel/Entity/EntityCreateAccessTest.php index c135319fc..e0d225fd5 100644 --- a/tests/src/Kernel/Entity/EntityCreateAccessTest.php +++ b/tests/src/Kernel/Entity/EntityCreateAccessTest.php @@ -31,6 +31,7 @@ class EntityCreateAccessTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Entity/GetBundleByBundleTest.php b/tests/src/Kernel/Entity/GetBundleByBundleTest.php index 24ed030ed..d89e83614 100644 --- a/tests/src/Kernel/Entity/GetBundleByBundleTest.php +++ b/tests/src/Kernel/Entity/GetBundleByBundleTest.php @@ -24,6 +24,7 @@ class GetBundleByBundleTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Entity/GetGroupContentTest.php b/tests/src/Kernel/Entity/GetGroupContentTest.php index c360b7440..b35cd0f58 100644 --- a/tests/src/Kernel/Entity/GetGroupContentTest.php +++ b/tests/src/Kernel/Entity/GetGroupContentTest.php @@ -26,6 +26,7 @@ class GetGroupContentTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Entity/GetMembershipsTest.php b/tests/src/Kernel/Entity/GetMembershipsTest.php index b8e813337..58088897d 100644 --- a/tests/src/Kernel/Entity/GetMembershipsTest.php +++ b/tests/src/Kernel/Entity/GetMembershipsTest.php @@ -28,6 +28,7 @@ class GetMembershipsTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Entity/GetUserGroupsTest.php b/tests/src/Kernel/Entity/GetUserGroupsTest.php index d183fdb74..543c35791 100644 --- a/tests/src/Kernel/Entity/GetUserGroupsTest.php +++ b/tests/src/Kernel/Entity/GetUserGroupsTest.php @@ -26,6 +26,7 @@ class GetUserGroupsTest extends KernelTestBase { 'user', 'field', 'og', + 'options', 'entity_test', ]; diff --git a/tests/src/Kernel/Entity/GroupAudienceTest.php b/tests/src/Kernel/Entity/GroupAudienceTest.php index d1132d337..de907ca91 100644 --- a/tests/src/Kernel/Entity/GroupAudienceTest.php +++ b/tests/src/Kernel/Entity/GroupAudienceTest.php @@ -29,6 +29,7 @@ class GroupAudienceTest extends KernelTestBase { 'entity_test', 'field', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php index f18c06ee6..ac5950ae8 100644 --- a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php +++ b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php @@ -35,6 +35,7 @@ class GroupMembershipManagerTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Entity/GroupTypeTest.php b/tests/src/Kernel/Entity/GroupTypeTest.php index c3f16144e..eed80eb73 100644 --- a/tests/src/Kernel/Entity/GroupTypeTest.php +++ b/tests/src/Kernel/Entity/GroupTypeTest.php @@ -15,7 +15,7 @@ class GroupTypeTest extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = ['field', 'node', 'og', 'system', 'user']; + public static $modules = ['field', 'node', 'og', 'options', 'system', 'user']; /** * The group type manager. diff --git a/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php b/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php index 98a669fc0..019c70cdd 100644 --- a/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php +++ b/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php @@ -20,11 +20,12 @@ class OgMembershipRoleReferenceTest extends KernelTestBase { * {@inheritdoc} */ public static $modules = [ - 'og', 'field', 'node', - 'user', + 'og', + 'options', 'system', + 'user', ]; /** diff --git a/tests/src/Kernel/Entity/OgMembershipTest.php b/tests/src/Kernel/Entity/OgMembershipTest.php index e238d2528..e97725faf 100644 --- a/tests/src/Kernel/Entity/OgMembershipTest.php +++ b/tests/src/Kernel/Entity/OgMembershipTest.php @@ -30,6 +30,7 @@ class OgMembershipTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Entity/OgRoleTest.php b/tests/src/Kernel/Entity/OgRoleTest.php index 728e90444..932495d20 100644 --- a/tests/src/Kernel/Entity/OgRoleTest.php +++ b/tests/src/Kernel/Entity/OgRoleTest.php @@ -24,6 +24,7 @@ class OgRoleTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php b/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php index 7e336ad35..3ed486df0 100644 --- a/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php +++ b/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php @@ -18,7 +18,14 @@ class OgStandardReferenceItemTest extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = ['user', 'entity_test', 'field', 'og', 'system']; + public static $modules = [ + 'user', + 'entity_test', + 'field', + 'og', + 'options', + 'system', + ]; protected $bundles; protected $fieldName; diff --git a/tests/src/Kernel/Entity/ReferenceStringIdTest.php b/tests/src/Kernel/Entity/ReferenceStringIdTest.php index d7575dd0e..3ea0c4b5e 100644 --- a/tests/src/Kernel/Entity/ReferenceStringIdTest.php +++ b/tests/src/Kernel/Entity/ReferenceStringIdTest.php @@ -17,7 +17,14 @@ class ReferenceStringIdTest extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = ['user', 'entity_test', 'field', 'og', 'system']; + public static $modules = [ + 'user', + 'entity_test', + 'field', + 'og', + 'options', + 'system', + ]; /** * Array of test bundles. The first is a group, the second group content. diff --git a/tests/src/Kernel/Entity/SelectionHandlerTest.php b/tests/src/Kernel/Entity/SelectionHandlerTest.php index b3dc7be53..3673be1d3 100644 --- a/tests/src/Kernel/Entity/SelectionHandlerTest.php +++ b/tests/src/Kernel/Entity/SelectionHandlerTest.php @@ -34,6 +34,7 @@ class SelectionHandlerTest extends KernelTestBase { 'entity_reference', 'node', 'og', + 'options', ]; /** diff --git a/tests/src/Kernel/EntityReference/Views/OgStandardReferenceRelationshipTest.php b/tests/src/Kernel/EntityReference/Views/OgStandardReferenceRelationshipTest.php index 03beeacfa..1a12e55d3 100644 --- a/tests/src/Kernel/EntityReference/Views/OgStandardReferenceRelationshipTest.php +++ b/tests/src/Kernel/EntityReference/Views/OgStandardReferenceRelationshipTest.php @@ -43,6 +43,7 @@ class OgStandardReferenceRelationshipTest extends ViewsKernelTestBase { 'views', 'og_standard_reference_test_views', 'og', + 'options', ]; /** diff --git a/tests/src/Kernel/Form/GroupSubscribeFormTest.php b/tests/src/Kernel/Form/GroupSubscribeFormTest.php index 6b0fccafd..5b85cde8e 100644 --- a/tests/src/Kernel/Form/GroupSubscribeFormTest.php +++ b/tests/src/Kernel/Form/GroupSubscribeFormTest.php @@ -29,6 +29,7 @@ class GroupSubscribeFormTest extends KernelTestBase { 'field', 'node', 'og', + 'options', ]; /** diff --git a/tests/src/Kernel/GroupTypeConditionTest.php b/tests/src/Kernel/GroupTypeConditionTest.php index bd610108a..7ee4361c6 100644 --- a/tests/src/Kernel/GroupTypeConditionTest.php +++ b/tests/src/Kernel/GroupTypeConditionTest.php @@ -22,6 +22,7 @@ class GroupTypeConditionTest extends KernelTestBase { 'field', 'node', 'og', + 'options', 'system', 'user', ]; diff --git a/tests/src/Kernel/OgDeleteOrphansTest.php b/tests/src/Kernel/OgDeleteOrphansTest.php index 0afe7dc24..e658644ae 100644 --- a/tests/src/Kernel/OgDeleteOrphansTest.php +++ b/tests/src/Kernel/OgDeleteOrphansTest.php @@ -26,6 +26,7 @@ class OgDeleteOrphansTest extends KernelTestBase { 'entity_reference', 'node', 'og', + 'options', ]; /** diff --git a/tests/src/Kernel/OgRoleManagerTest.php b/tests/src/Kernel/OgRoleManagerTest.php index f226fe7a4..2d8378b94 100644 --- a/tests/src/Kernel/OgRoleManagerTest.php +++ b/tests/src/Kernel/OgRoleManagerTest.php @@ -23,6 +23,7 @@ class OgRoleManagerTest extends KernelTestBase { 'field', 'node', 'og', + 'options', ]; /** From b1421b9dcb464c71f83d2b91eee6ffa286044bc5 Mon Sep 17 00:00:00 2001 From: Justin Ludwig Date: Mon, 16 Oct 2017 12:19:58 -0700 Subject: [PATCH 061/111] API update: getUser() to getOwner(). --- og.module | 2 +- src/Form/OgMembershipDeleteForm.php | 6 +++--- src/Form/OgMembershipForm.php | 6 +++--- src/OgMembershipAccessControlHandler.php | 2 +- src/Plugin/EntityReferenceSelection/OgUserSelection.php | 2 +- .../Constraint/UniqueOgMembershipConstraintValidator.php | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/og.module b/og.module index c578e6408..0ac1b7a19 100755 --- a/og.module +++ b/og.module @@ -201,7 +201,7 @@ function og_og_membership_access(OgMembershipInterface $entity, $operation, Acco if ( isset($group_fields['uid']) && $operation === 'delete' - && $group_fields['uid']->entity->id() === $entity->getUser()->id() + && $group_fields['uid']->entity->id() === $entity->getOwner()->id() ) { return AccessResult::forbidden(); } diff --git a/src/Form/OgMembershipDeleteForm.php b/src/Form/OgMembershipDeleteForm.php index 72ea01e7f..eaa049d8c 100644 --- a/src/Form/OgMembershipDeleteForm.php +++ b/src/Form/OgMembershipDeleteForm.php @@ -17,7 +17,7 @@ protected function getDeletionMessage() { $membership = $this->getEntity(); return $this->t("%user has been unsubscribed from %group.", [ - '%user' => $membership->getUser()->getDisplayName(), + '%user' => $membership->getOwner()->getDisplayName(), '%group' => $membership->getGroup()->label(), ]); } @@ -31,7 +31,7 @@ protected function logDeletionMessage() { $this->logger('og')->notice("OG Membership: deleted the @membership_type membership for the user uid: @uid to the group of the entity-type @group_type and ID: @gid", [ '@membership_type' => $membership->getType(), - '@uid' => $membership->getUser()->id(), + '@uid' => $membership->getOwner()->id(), '@group_type' => $membership->getGroupEntityType(), '@gid' => $membership->getGroupId(), ]); @@ -45,7 +45,7 @@ public function getQuestion() { $membership = $this->getEntity(); return $this->t("Are you sure you want to unsubscribe %user from %group?", [ - '%user' => $membership->getUser()->getDisplayName(), + '%user' => $membership->getOwner()->getDisplayName(), '%group' => $membership->getGroup()->label(), ]); } diff --git a/src/Form/OgMembershipForm.php b/src/Form/OgMembershipForm.php index 27d6d6331..703a51a45 100644 --- a/src/Form/OgMembershipForm.php +++ b/src/Form/OgMembershipForm.php @@ -83,7 +83,7 @@ public function form(array $form, FormStateInterface $form_state) { $form['member'] = [ '#title' => $this->t('Member name'), '#type' => 'item', - '#markup' => $entity->getUser()->getDisplayName(), + '#markup' => $entity->getOwner()->getDisplayName(), '#weight' => -10, ]; } @@ -108,14 +108,14 @@ public function save(array $form, FormStateInterface $form_state) { $context = [ '@membership_type' => $membership->getType(), - '@uid' => $membership->getUser()->id(), + '@uid' => $membership->getOwner()->id(), '@group_type' => $membership->getGroupEntityType(), '@gid' => $membership->getGroupId(), 'link' => $membership_link, ]; $t_args = [ - '%user' => $membership->getUser()->link(), + '%user' => $membership->getOwner()->link(), '%group' => $membership->getGroup()->link(), ]; diff --git a/src/OgMembershipAccessControlHandler.php b/src/OgMembershipAccessControlHandler.php index 97688aae3..d9b352dc1 100644 --- a/src/OgMembershipAccessControlHandler.php +++ b/src/OgMembershipAccessControlHandler.php @@ -54,7 +54,7 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter $group = $entity->getGroup(); // Do not allow deleting the group owner's membership. - if (($operation === 'delete') && ($group instanceof EntityOwnerInterface) && ($group->getOwnerId() == $entity->getUser()->id())) { + if (($operation === 'delete') && ($group instanceof EntityOwnerInterface) && ($group->getOwnerId() == $entity->getOwner()->id())) { return AccessResult::forbidden(); } diff --git a/src/Plugin/EntityReferenceSelection/OgUserSelection.php b/src/Plugin/EntityReferenceSelection/OgUserSelection.php index ebb0a6451..47d23eadf 100644 --- a/src/Plugin/EntityReferenceSelection/OgUserSelection.php +++ b/src/Plugin/EntityReferenceSelection/OgUserSelection.php @@ -145,7 +145,7 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') $member_uids = []; /** @var \Drupal\og\Entity\OgMembership $membership */ foreach ($this->membershipManager->getGroupMemberships($group) as $membership) { - $member_uids[] = $membership->getUser()->id(); + $member_uids[] = $membership->getOwner()->id(); } if (count($member_uids) > 0) { diff --git a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php index 63ee80d08..c830cc67a 100644 --- a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php @@ -36,8 +36,8 @@ public function validate($value, Constraint $constraint) { $new_member_uid = $value[0]['target_id']; $membership_manager = \Drupal::service('og.membership_manager'); foreach ($membership_manager->getGroupMemberships($entity->getGroup()) as $membership) { - if ((string) $membership->getUser()->id() === (string) $new_member_uid) { - $this->context->addViolation($constraint->NotUniqueMembership, ['%user' => $membership->getUser()->getDisplayName()]); + if ((string) $membership->getOwner()->id() === (string) $new_member_uid) { + $this->context->addViolation($constraint->NotUniqueMembership, ['%user' => $membership->getOwner()->getDisplayName()]); return; } } From 2c5d94fd9c3281e8bb067aa1b3a8e9b1dacbf1d1 Mon Sep 17 00:00:00 2001 From: Justin Ludwig Date: Fri, 3 Nov 2017 14:34:50 -0700 Subject: [PATCH 062/111] Credit: zerolab | OgAdminRoutesEvent array merge fix. Important parameters were being overwritten. --- src/Event/OgAdminRoutesEvent.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Event/OgAdminRoutesEvent.php b/src/Event/OgAdminRoutesEvent.php index bb506ee9d..4ae012172 100644 --- a/src/Event/OgAdminRoutesEvent.php +++ b/src/Event/OgAdminRoutesEvent.php @@ -43,7 +43,7 @@ public function getRoutes($entity_type_id) { // Add default values. NestedArray::mergeDeep allows deep data to not be // overwritten with the defaults. - $routes_info[$name] = NestedArray::mergeDeep($routes_info[$name], [ + $defaults = [ 'description' => '', 'requirements' => [ @@ -65,7 +65,9 @@ public function getRoutes($entity_type_id) { '_controller' => $route_info['controller'], '_title' => $route_info['title'], ], - ]); + ]; + + $routes_info[$name] = NestedArray::mergeDeep($defaults, $routes_info[$name]); } return $routes_info; From a270ce61b14fb7731b9953eed648c334b31cae4f Mon Sep 17 00:00:00 2001 From: Joachim Noreiko Date: Tue, 29 May 2018 14:52:30 +0100 Subject: [PATCH 063/111] Fixed entity reference selection plugin loading all membership entities for the group to exclude existing members from the available user entities. --- .../OgUserSelection.php | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/Plugin/EntityReferenceSelection/OgUserSelection.php b/src/Plugin/EntityReferenceSelection/OgUserSelection.php index 47d23eadf..285352d33 100644 --- a/src/Plugin/EntityReferenceSelection/OgUserSelection.php +++ b/src/Plugin/EntityReferenceSelection/OgUserSelection.php @@ -3,6 +3,7 @@ namespace Drupal\og\Plugin\EntityReferenceSelection; use Drupal\Core\Database\Connection; +use Drupal\Core\Database\Query\SelectInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection; use Drupal\Core\Extension\ModuleHandlerInterface; @@ -122,6 +123,17 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') $query->condition('status', 1); } + return $query; + } + + /** + * {@inheritdoc} + */ + public function entityQueryAlter(SelectInterface $query) { + // Exclude users who are already in the current group. + // This has to be done on the SQL query rather than the entity query, + // because a reverse relationship to the OG membership entity is needed. + // @todo implement an easier, more consistent way to get the group type. At // the moment, this works either for checkboxes or OG Autocomplete widget // types on entities that have a getGroup() method. It also does not work @@ -140,19 +152,12 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') return $query; } - // @todo Excluding group members with a join would perform much better than - // loading each membership associated with the group. - $member_uids = []; - /** @var \Drupal\og\Entity\OgMembership $membership */ - foreach ($this->membershipManager->getGroupMemberships($group) as $membership) { - $member_uids[] = $membership->getOwner()->id(); - } + // Left join to the OG membership base table. + $query->leftJoin('og_membership', 'ogm', "base_table.uid = ogm.uid"); - if (count($member_uids) > 0) { - $query->condition('uid', $member_uids, 'NOT IN'); - } - - return $query; + // Exclude any users who are in the current group. + $query->condition('ogm.entity_type', $group->getEntityTypeId(), '!='); + $query->condition('ogm.entity_id', $group->id(), '!='); } /** From d456eb72dee005281964d8bedc52d331415c7ba6 Mon Sep 17 00:00:00 2001 From: Joachim Noreiko Date: Tue, 29 May 2018 15:01:14 +0100 Subject: [PATCH 064/111] Added method to MembershipManager to get the count of members in a group. --- src/MembershipManager.php | 17 +++++++++++++++++ src/MembershipManagerInterface.php | 13 +++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index 6e4153ad5..c7808d0b0 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -160,6 +160,23 @@ public function getGroupMemberships(EntityInterface $group, array $states = [OgM return $this->cache[$identifier]; } + /** + * {@inheritdoc} + */ + public function getGroupMembershipCount(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]) { + $query = $this->entityTypeManager + ->getStorage('og_membership') + ->getQuery() + ->condition('entity_id', $group->id()); + + if ($states) { + $query->condition('state', $states, 'IN'); + } + + $query->count(); + return $query->execute(); + } + /** * {@inheritdoc} */ diff --git a/src/MembershipManagerInterface.php b/src/MembershipManagerInterface.php index bbfdc57b2..583a2f588 100644 --- a/src/MembershipManagerInterface.php +++ b/src/MembershipManagerInterface.php @@ -83,6 +83,19 @@ public function getMemberships(AccountInterface $user, array $states = [OgMember */ public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]); + /** + * Returns the number of group memberships for a given group. + * + * @param \Drupal\Core\Entity\EntityInterface $group + * The group to get the membership for. + * @param array $states + * (optional) Array with the state to return. Defaults to active. + * + * @return int + * The number of memberships for the group. + */ + public function getGroupMembershipCount(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]); + /** * Returns the group membership for a given user and group. * From f757bb15dd6a4b67c423437ffc3470a752e36db9 Mon Sep 17 00:00:00 2001 From: Joachim Noreiko Date: Tue, 29 May 2018 15:01:25 +0100 Subject: [PATCH 065/111] Fixed access check to query for the count of group members, rather than count loaded membership entities. --- og.module | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/og.module b/og.module index 0ac1b7a19..28da5518f 100755 --- a/og.module +++ b/og.module @@ -207,7 +207,7 @@ function og_og_membership_access(OgMembershipInterface $entity, $operation, Acco } // Ensure that there's at least one member in the group. - if ($operation === 'delete' && count(Og::getGroupMemberships($group)) === 1) { + if ($operation === 'delete' && \Drupal::service('og.membership_manager')->getGroupMembershipCount($group) === 1) { return AccessResult::forbidden(); } From e4bc034224ee245499c099096e33fe1ac9bea0cf Mon Sep 17 00:00:00 2001 From: Joachim Noreiko Date: Tue, 29 May 2018 14:53:43 +0100 Subject: [PATCH 066/111] Added docs to UniqueOgMembershipConstraintValidator to explain why it's not typically triggered. --- .../Constraint/UniqueOgMembershipConstraintValidator.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php index c830cc67a..6df3344de 100644 --- a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php @@ -7,6 +7,13 @@ /** * Ensures that new members added to a group do not already exist. + * + * Note that in typical operation, this validation constraint will not come into + * play, as the membership entity's uid field is already validated by core's + * ValidReferenceConstraint, which hands over to the entity reference selection + * plugin. In our case, that is + * \Drupal\og\Plugin\EntityReferenceSelection\OgUserSelection, which already + * checks an existing member cannot be added to the group again. */ class UniqueOgMembershipConstraintValidator extends ConstraintValidator { From 361851c246e12f78d9a1bbacf2b762ecbb0a761b Mon Sep 17 00:00:00 2001 From: Joachim Noreiko Date: Tue, 29 May 2018 14:53:31 +0100 Subject: [PATCH 067/111] Fixed UniqueOgMembershipConstraintValidator loading all membership entities to check for a user's existing membership. --- .../UniqueOgMembershipConstraintValidator.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php index 6df3344de..9678ea03e 100644 --- a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php @@ -41,12 +41,17 @@ public function validate($value, Constraint $constraint) { } $new_member_uid = $value[0]['target_id']; - $membership_manager = \Drupal::service('og.membership_manager'); - foreach ($membership_manager->getGroupMemberships($entity->getGroup()) as $membership) { - if ((string) $membership->getOwner()->id() === (string) $new_member_uid) { - $this->context->addViolation($constraint->NotUniqueMembership, ['%user' => $membership->getOwner()->getDisplayName()]); - return; - } + + $query = \Drupal::service('entity_type.manager') + ->getStorage('og_membership') + ->getQuery() + ->condition('uid', $new_member_uid); + $membership_ids = $query->execute(); + + if ($membership_ids) { + $user = \Drupal::service('entity_type.manager')->getStorage('user')->load($new_member_uid); + $this->context->addViolation($constraint->NotUniqueMembership, ['%user' => $user->getDisplayName()]); + return; } } From 5932badbdeaff42862a8e777fb90a0f29a0ac96c Mon Sep 17 00:00:00 2001 From: Joachim Noreiko Date: Tue, 29 May 2018 15:01:56 +0100 Subject: [PATCH 068/111] Removed getGroupMemberships(): no longer used, and does not scale for large groups. --- src/MembershipManager.php | 39 ------------------------------ src/MembershipManagerInterface.php | 13 ---------- 2 files changed, 52 deletions(-) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index c7808d0b0..ff1baf17d 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -121,45 +121,6 @@ public function getMembership(EntityInterface $group, AccountInterface $user, ar return NULL; } - /** - * {@inheritdoc} - */ - public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]) { - // Get a string identifier of the states, so we can retrieve it from cache. - sort($states); - $states_identifier = implode('|', array_unique($states)); - - $identifier = [ - __METHOD__, - $group->id(), - $states_identifier, - ]; - $identifier = implode(':', $identifier); - - // Return cached result if it exists. - if (isset($this->cache[$identifier])) { - return $this->cache[$identifier]; - } - - $query = $this->entityTypeManager - ->getStorage('og_membership') - ->getQuery() - ->condition('entity_id', $group->id()); - - if ($states) { - $query->condition('state', $states, 'IN'); - } - - $results = $query->execute(); - - /** @var \Drupal\og\Entity\OgMembership[] $memberships */ - $this->cache[$identifier] = $this->entityTypeManager - ->getStorage('og_membership') - ->loadMultiple($results); - - return $this->cache[$identifier]; - } - /** * {@inheritdoc} */ diff --git a/src/MembershipManagerInterface.php b/src/MembershipManagerInterface.php index 583a2f588..873c2b8c9 100644 --- a/src/MembershipManagerInterface.php +++ b/src/MembershipManagerInterface.php @@ -70,19 +70,6 @@ public function getUserGroups(AccountInterface $user, array $states = [OgMembers */ public function getMemberships(AccountInterface $user, array $states = [OgMembershipInterface::STATE_ACTIVE]); - /** - * Returns the group memberships for a given group. - * - * @param \Drupal\Core\Entity\EntityInterface $group - * The group to get the membership for. - * @param array $states - * (optional) Array with the state to return. Defaults to active. - * - * @return \Drupal\og\OgMembershipInterface[] - * An array of OgMembership entities, keyed by ID. - */ - public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]); - /** * Returns the number of group memberships for a given group. * From 4b7cdae17b7857b307dd3da26691c096182b2d1c Mon Sep 17 00:00:00 2001 From: Dan Braghis Date: Fri, 8 Jun 2018 11:16:32 +0100 Subject: [PATCH 069/111] Fix OgUserSelection query --- src/Plugin/EntityReferenceSelection/OgUserSelection.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Plugin/EntityReferenceSelection/OgUserSelection.php b/src/Plugin/EntityReferenceSelection/OgUserSelection.php index 285352d33..90a42dfe1 100644 --- a/src/Plugin/EntityReferenceSelection/OgUserSelection.php +++ b/src/Plugin/EntityReferenceSelection/OgUserSelection.php @@ -153,11 +153,13 @@ public function entityQueryAlter(SelectInterface $query) { } // Left join to the OG membership base table. - $query->leftJoin('og_membership', 'ogm', "base_table.uid = ogm.uid"); + $query->leftJoin('og_membership', 'ogm', "base_table.uid = ogm.uid AND ogm.entity_type != :entity_type AND ogm.entity_id != :entity_id", [ + ':entity_type' => $group->getEntityTypeId(), + ':entity_id' => $group->id(), + ]); // Exclude any users who are in the current group. - $query->condition('ogm.entity_type', $group->getEntityTypeId(), '!='); - $query->condition('ogm.entity_id', $group->id(), '!='); + $query->condition('ogm.id', NULL, 'IS'); } /** From e136d8d201321e7004f02c7f13b0e8a19d0f1893 Mon Sep 17 00:00:00 2001 From: Dan Braghis Date: Fri, 8 Jun 2018 11:42:55 +0100 Subject: [PATCH 070/111] Fix query --- src/Plugin/EntityReferenceSelection/OgUserSelection.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Plugin/EntityReferenceSelection/OgUserSelection.php b/src/Plugin/EntityReferenceSelection/OgUserSelection.php index 90a42dfe1..e7030b64a 100644 --- a/src/Plugin/EntityReferenceSelection/OgUserSelection.php +++ b/src/Plugin/EntityReferenceSelection/OgUserSelection.php @@ -153,13 +153,13 @@ public function entityQueryAlter(SelectInterface $query) { } // Left join to the OG membership base table. - $query->leftJoin('og_membership', 'ogm', "base_table.uid = ogm.uid AND ogm.entity_type != :entity_type AND ogm.entity_id != :entity_id", [ + $query->leftJoin('og_membership', 'ogm', "base_table.uid = ogm.uid AND ogm.entity_type = :entity_type AND ogm.entity_id = :entity_id", [ ':entity_type' => $group->getEntityTypeId(), ':entity_id' => $group->id(), ]); // Exclude any users who are in the current group. - $query->condition('ogm.id', NULL, 'IS'); + $query->isNull('og.id'); } /** From 204b80271c8ed846b10790bf634dc6a5d9cddfcd Mon Sep 17 00:00:00 2001 From: Dan Braghis Date: Fri, 8 Jun 2018 11:45:51 +0100 Subject: [PATCH 071/111] fixup! Fix query --- src/Plugin/EntityReferenceSelection/OgUserSelection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugin/EntityReferenceSelection/OgUserSelection.php b/src/Plugin/EntityReferenceSelection/OgUserSelection.php index e7030b64a..1f14b5a22 100644 --- a/src/Plugin/EntityReferenceSelection/OgUserSelection.php +++ b/src/Plugin/EntityReferenceSelection/OgUserSelection.php @@ -159,7 +159,7 @@ public function entityQueryAlter(SelectInterface $query) { ]); // Exclude any users who are in the current group. - $query->isNull('og.id'); + $query->isNull('ogm.id'); } /** From c15a9fc061b42e5d3b7582252275bd8f64810dad Mon Sep 17 00:00:00 2001 From: Dan Braghis Date: Fri, 31 Aug 2018 09:54:18 +0100 Subject: [PATCH 072/111] Fix UniqueOgMembershipConstraintValidator not filtering on the group --- .../Constraint/UniqueOgMembershipConstraintValidator.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php index 9678ea03e..ed593ca2d 100644 --- a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php @@ -45,6 +45,8 @@ public function validate($value, Constraint $constraint) { $query = \Drupal::service('entity_type.manager') ->getStorage('og_membership') ->getQuery() + ->condition('entity_type', $entity->getGroupEntityType()) + ->condition('entity_id', $entity->getGroupId()) ->condition('uid', $new_member_uid); $membership_ids = $query->execute(); From 36f2f0e33216bd98970af957dde04ebac113368c Mon Sep 17 00:00:00 2001 From: Insasse Date: Fri, 16 Nov 2018 16:02:57 +0100 Subject: [PATCH 073/111] use new fieldtype --- src/Entity/OgMembership.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index 30fa58d4e..e8c4259c8 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -409,7 +409,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setLabel(t('Group entity ID')) ->setDescription(t('The entity ID of the group.')); - $fields['state'] = BaseFieldDefinition::create('list_string') + $fields['state'] = BaseFieldDefinition::create('og_list_string') ->setLabel(t('State')) ->setDescription(t('The user membership state: active, pending, or blocked.')) ->setDefaultValue(OgMembershipInterface::STATE_ACTIVE) From 01c4e696096e39ac0087e38f0f8ef11b5d8cefe1 Mon Sep 17 00:00:00 2001 From: Insasse Date: Fri, 16 Nov 2018 16:04:21 +0100 Subject: [PATCH 074/111] fix php doc --- src/Plugin/Field/FieldType/OgListString.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugin/Field/FieldType/OgListString.php b/src/Plugin/Field/FieldType/OgListString.php index 3b15cf6e0..fdbb3cd4d 100644 --- a/src/Plugin/Field/FieldType/OgListString.php +++ b/src/Plugin/Field/FieldType/OgListString.php @@ -5,7 +5,7 @@ use Drupal\options\Plugin\Field\FieldType\ListStringItem; /** - * Plugin implementation of the 'list_string' field type. + * Plugin implementation of the 'og_list_string' field type. * * @FieldType( * id = "og_list_string", From ddd003a5240ea2588df6be0e97d6918d9f9be20d Mon Sep 17 00:00:00 2001 From: Insasse Date: Fri, 16 Nov 2018 16:06:37 +0100 Subject: [PATCH 075/111] fix fatal on group create --- og.module | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/og.module b/og.module index 28da5518f..4a8fc5769 100755 --- a/og.module +++ b/og.module @@ -280,7 +280,7 @@ function og_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle, $fields = []; $fields['og_group'] = BaseFieldDefinition::create('og_group') - ->setLabel(t('OG Group')) + ->setLabel('OG Group') ->setComputed(TRUE) ->setTranslatable(FALSE) ->setDefaultValue(TRUE) From 0f86fd1c5f57b553eb6bb29f6c7e11ff599e9060 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 08:10:51 +0100 Subject: [PATCH 076/111] add options module to all kernel tests --- src/Entity/OgMembership.php | 2 +- src/Plugin/Field/FieldType/OgListString.php | 21 ------------------- tests/src/Kernel/Action/ActionTestBase.php | 2 +- .../DefaultRoleEventIntegrationTest.php | 2 +- .../CacheInvalidationOnGroupChangeTest.php | 1 + .../Field/AudienceFieldFormatterTest.php | 2 +- .../Kernel/GroupManagerSubscriptionTest.php | 1 + tests/src/Kernel/PermissionEventTest.php | 1 + .../SelectionHandlerSettingsSchemaTest.php | 1 + 9 files changed, 8 insertions(+), 25 deletions(-) delete mode 100644 src/Plugin/Field/FieldType/OgListString.php diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index e8c4259c8..30fa58d4e 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -409,7 +409,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setLabel(t('Group entity ID')) ->setDescription(t('The entity ID of the group.')); - $fields['state'] = BaseFieldDefinition::create('og_list_string') + $fields['state'] = BaseFieldDefinition::create('list_string') ->setLabel(t('State')) ->setDescription(t('The user membership state: active, pending, or blocked.')) ->setDefaultValue(OgMembershipInterface::STATE_ACTIVE) diff --git a/src/Plugin/Field/FieldType/OgListString.php b/src/Plugin/Field/FieldType/OgListString.php deleted file mode 100644 index fdbb3cd4d..000000000 --- a/src/Plugin/Field/FieldType/OgListString.php +++ /dev/null @@ -1,21 +0,0 @@ - label' pairs, i.e. 'US States': IL => Illinois, IA => Iowa, IN => Indiana."), - * category = @Translation("Text"), - * default_widget = "options_select", - * default_formatter = "list_default", - * ) - */ -class OgListString extends ListStringItem { - -} diff --git a/tests/src/Kernel/Action/ActionTestBase.php b/tests/src/Kernel/Action/ActionTestBase.php index cb6c1a309..2ecf08f9a 100644 --- a/tests/src/Kernel/Action/ActionTestBase.php +++ b/tests/src/Kernel/Action/ActionTestBase.php @@ -31,7 +31,7 @@ abstract class ActionTestBase extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = ['node', 'og', 'system', 'user']; + public static $modules = ['node', 'og', 'system', 'user', 'options']; /** * An array of test users. diff --git a/tests/src/Kernel/DefaultRoleEventIntegrationTest.php b/tests/src/Kernel/DefaultRoleEventIntegrationTest.php index 5f316e0e8..12afaf4e2 100644 --- a/tests/src/Kernel/DefaultRoleEventIntegrationTest.php +++ b/tests/src/Kernel/DefaultRoleEventIntegrationTest.php @@ -18,7 +18,7 @@ class DefaultRoleEventIntegrationTest extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = ['entity_test', 'og', 'system', 'user', 'field']; + public static $modules = ['entity_test', 'og', 'system', 'user', 'field', 'options']; /** * The Symfony event dispatcher. diff --git a/tests/src/Kernel/Entity/CacheInvalidationOnGroupChangeTest.php b/tests/src/Kernel/Entity/CacheInvalidationOnGroupChangeTest.php index 2546c5f97..efad1d31e 100644 --- a/tests/src/Kernel/Entity/CacheInvalidationOnGroupChangeTest.php +++ b/tests/src/Kernel/Entity/CacheInvalidationOnGroupChangeTest.php @@ -24,6 +24,7 @@ class CacheInvalidationOnGroupChangeTest extends KernelTestBase { 'og', 'system', 'user', + 'options' ]; /** diff --git a/tests/src/Kernel/Field/AudienceFieldFormatterTest.php b/tests/src/Kernel/Field/AudienceFieldFormatterTest.php index 1b95a78db..aae496c33 100644 --- a/tests/src/Kernel/Field/AudienceFieldFormatterTest.php +++ b/tests/src/Kernel/Field/AudienceFieldFormatterTest.php @@ -15,7 +15,7 @@ class AudienceFieldFormatterTest extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = ['field', 'og']; + public static $modules = ['field', 'og', 'options',]; /** * Testing og_field_formatter_info_alter(). diff --git a/tests/src/Kernel/GroupManagerSubscriptionTest.php b/tests/src/Kernel/GroupManagerSubscriptionTest.php index a6e185dfe..efdf4039d 100644 --- a/tests/src/Kernel/GroupManagerSubscriptionTest.php +++ b/tests/src/Kernel/GroupManagerSubscriptionTest.php @@ -26,6 +26,7 @@ class GroupManagerSubscriptionTest extends KernelTestBase { 'og_test', 'system', 'user', + 'options', ]; /** diff --git a/tests/src/Kernel/PermissionEventTest.php b/tests/src/Kernel/PermissionEventTest.php index c9a0ea94c..05089d1ec 100644 --- a/tests/src/Kernel/PermissionEventTest.php +++ b/tests/src/Kernel/PermissionEventTest.php @@ -28,6 +28,7 @@ class PermissionEventTest extends KernelTestBase { 'og', 'system', 'user', + 'options', ]; /** diff --git a/tests/src/Kernel/SelectionHandlerSettingsSchemaTest.php b/tests/src/Kernel/SelectionHandlerSettingsSchemaTest.php index c1effe04c..8d1e38da3 100644 --- a/tests/src/Kernel/SelectionHandlerSettingsSchemaTest.php +++ b/tests/src/Kernel/SelectionHandlerSettingsSchemaTest.php @@ -22,6 +22,7 @@ class SelectionHandlerSettingsSchemaTest extends KernelTestBase { 'og_ui', 'system', 'user', + 'options', ]; /** From 4f084d098c22c5aeb88103302e9608cb58c74e82 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 08:18:35 +0100 Subject: [PATCH 077/111] Remove t() from setLabel() --- og.install | 2 +- src/Entity/OgMembership.php | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/og.install b/og.install index 80ad218cf..777a283a8 100644 --- a/og.install +++ b/og.install @@ -23,7 +23,7 @@ function og_update_8001(&$sandbox) { if (!isset($sandbox['total'])) { $storage_definition = BaseFieldDefinition::create('string') - ->setLabel(t('Group bundle ID')) + ->setLabel('Group bundle ID') ->setDescription(t('The bundle ID of the group.')); \Drupal::entityDefinitionUpdateManager()->installFieldStorageDefinition('entity_bundle', 'og_membership', 'og', $storage_definition); diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index 30fa58d4e..f63127d44 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -363,23 +363,23 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = []; $fields['id'] = BaseFieldDefinition::create('integer') - ->setLabel(t('ID')) + ->setLabel('ID') ->setDescription(t("The group membership's unique ID.")) ->setReadOnly(TRUE) ->setSetting('unsigned', TRUE); $fields['uuid'] = BaseFieldDefinition::create('uuid') - ->setLabel(t('UUID')) + ->setLabel('UUID') ->setDescription(t('The membership UUID.')) ->setReadOnly(TRUE); $fields['type'] = BaseFieldDefinition::create('entity_reference') - ->setLabel(t('Type')) + ->setLabel('Type') ->setDescription(t('The bundle of the membership')) ->setSetting('target_type', 'og_membership_type'); $fields['uid'] = BaseFieldDefinition::create('entity_reference') - ->setLabel(t('Username')) + ->setLabel('Username') ->setDescription(t('The user ID of the member.')) ->setSetting('target_type', 'user') ->setSetting('handler', 'og:user') @@ -398,19 +398,19 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setRequired(TRUE); $fields['entity_type'] = BaseFieldDefinition::create('string') - ->setLabel(t('Group entity type')) + ->setLabel('Group entity type') ->setDescription(t('The entity type of the group.')); $fields['entity_bundle'] = BaseFieldDefinition::create('string') - ->setLabel(t('Group bundle ID')) + ->setLabel('Group bundle ID') ->setDescription(t('The bundle ID of the group.')); $fields['entity_id'] = BaseFieldDefinition::create('string') - ->setLabel(t('Group entity ID')) + ->setLabel('Group entity ID') ->setDescription(t('The entity ID of the group.')); $fields['state'] = BaseFieldDefinition::create('list_string') - ->setLabel(t('State')) + ->setLabel('State') ->setDescription(t('The user membership state: active, pending, or blocked.')) ->setDefaultValue(OgMembershipInterface::STATE_ACTIVE) ->setSettings([ @@ -429,7 +429,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setRequired(TRUE); $fields['roles'] = BaseFieldDefinition::create('entity_reference') - ->setLabel(t('Roles')) + ->setLabel('Roles') ->setDescription(t('The OG roles related to an OG membership entity.')) ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) ->setSetting('target_type', 'og_role') @@ -443,11 +443,11 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setDisplayConfigurable('form', TRUE); $fields['created'] = BaseFieldDefinition::create('created') - ->setLabel(t('Create')) + ->setLabel('Create') ->setDescription(t('The Unix timestamp when the membership was created.')); $fields['language'] = BaseFieldDefinition::create('language') - ->setLabel(t('Language')) + ->setLabel('Language') ->setDescription(t('The {languages}.language of this membership.')); return $fields; From dd2e1c20061cf9dfb058281a62f64407004ff44f Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 08:24:21 +0100 Subject: [PATCH 078/111] test --- og_ui/tests/src/Functional/BundleFormAlterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/og_ui/tests/src/Functional/BundleFormAlterTest.php b/og_ui/tests/src/Functional/BundleFormAlterTest.php index 8f326fcdf..bbd539b2a 100644 --- a/og_ui/tests/src/Functional/BundleFormAlterTest.php +++ b/og_ui/tests/src/Functional/BundleFormAlterTest.php @@ -18,7 +18,7 @@ class BundleFormAlterTest extends BrowserTestBase { /** * {@inheritdoc} */ - public static $modules = ['block_content', 'entity_test', 'node', 'og_ui']; + public static $modules = ['block_content', 'entity_test', 'node', 'og_ui', 'system', 'og', 'options']; /** * An administrator user. From 2ddb8415ab51f75c9dd69fa5ef804100b1d26cd1 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 08:51:04 +0100 Subject: [PATCH 079/111] Remove deprecated drupal_set_message replace it with OO MessengerInterface --- src/Controller/SubscriptionController.php | 2 +- src/Form/GroupSubscribeForm.php | 19 +++++++++++++-- src/Form/GroupUnsubscribeConfirmForm.php | 29 +++++++++++++++++++++++ src/Form/OgMembershipForm.php | 26 ++++++++++++++++---- src/Form/OgMembershipTypeForm.php | 26 ++++++++++---------- 5 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/Controller/SubscriptionController.php b/src/Controller/SubscriptionController.php index e32831ded..fca8dd4e2 100644 --- a/src/Controller/SubscriptionController.php +++ b/src/Controller/SubscriptionController.php @@ -7,6 +7,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Url; +use Drupal\og\Og; use Drupal\og\OgAccessInterface; use Drupal\og\OgMembershipInterface; use Drupal\og\OgMembershipTypeInterface; @@ -15,7 +16,6 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; -use Drupal\og\Og; /** * Controller for OG subscription routes. diff --git a/src/Form/GroupSubscribeForm.php b/src/Form/GroupSubscribeForm.php index 822ee96cc..0a0a366bb 100644 --- a/src/Form/GroupSubscribeForm.php +++ b/src/Form/GroupSubscribeForm.php @@ -11,6 +11,7 @@ use Drupal\og\OgAccessInterface; use Drupal\og\OgMembershipInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Messenger\MessengerInterface; /** * Provides a form for subscribing to a group. @@ -30,6 +31,13 @@ class GroupSubscribeForm extends ContentEntityForm { */ protected $ogAccess; + /** + * The messenger. + * + * @var \Drupal\Core\Messenger\MessengerInterface + */ + protected $messenger; + /** * Constructs a GroupSubscribeForm. * @@ -48,9 +56,15 @@ class GroupSubscribeForm extends ContentEntityForm { * * @see https://github.com/Gizra/og/issues/397 */ - public function __construct(OgAccessInterface $og_access, $entity_repository, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) { + public function __construct( + OgAccessInterface $og_access, $entity_repository, + EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, + TimeInterface $time = NULL, + MessengerInterface $messenger + ) { parent::__construct($entity_repository, $entity_type_bundle_info, $time); $this->ogAccess = $og_access; + $this->messenger = $messenger; } /** @@ -72,7 +86,8 @@ public static function create(ContainerInterface $container) { $container->get('og.access'), $container->get($entity_repository_service), $container->get('entity_type.bundle.info'), - $container->get('datetime.time') + $container->get('datetime.time'), + $container->get('messenger') ); } diff --git a/src/Form/GroupUnsubscribeConfirmForm.php b/src/Form/GroupUnsubscribeConfirmForm.php index 8dd459bb1..5c4116c64 100644 --- a/src/Form/GroupUnsubscribeConfirmForm.php +++ b/src/Form/GroupUnsubscribeConfirmForm.php @@ -5,12 +5,41 @@ use Drupal\Core\Entity\ContentEntityDeleteForm; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; +use Drupal\Core\Messenger\MessengerInterface; /** * Provides a confirmation form for unsubscribing form a group. */ class GroupUnsubscribeConfirmForm extends ContentEntityDeleteForm { + /** + * The messenger. + * + * @var \Drupal\Core\Messenger\MessengerInterface $messenger + */ + protected $messenger; + + /** + * Constructs the GroupUnsubscribeConfirmForm object. + * + * @param \Drupal\Core\Messenger\MessengerInterface $messenger + * The messenger. + */ + public function __construct(MessengerInterface $messenger) { + $this->messenger = $messenger; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('messenger') + ); + } + + + /** * {@inheritdoc} */ diff --git a/src/Form/OgMembershipForm.php b/src/Form/OgMembershipForm.php index 703a51a45..e2157cc44 100644 --- a/src/Form/OgMembershipForm.php +++ b/src/Form/OgMembershipForm.php @@ -10,6 +10,7 @@ use Drupal\og\OgAccessInterface; use Drupal\og\OgMembershipInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Messenger\MessengerInterface; /** * Form controller for the group content edit forms. @@ -25,6 +26,13 @@ class OgMembershipForm extends ContentEntityForm { */ protected $ogAccess; + /** + * The messenger. + * + * @var \Drupal\Core\Messenger\MessengerInterface + */ + protected $messenger; + /** * Constructs a MessageForm object. * @@ -36,10 +44,19 @@ class OgMembershipForm extends ContentEntityForm { * The time service. * @param \Drupal\og\OgAccessInterface $og_access * The OG access service. + * @param \Drupal\Core\Messenger\MessengerInterface $messenger + * The messenger. */ - public function __construct(EntityManagerInterface $entity_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, OgAccessInterface $og_access) { + public function __construct( + EntityManagerInterface $entity_manager, + EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, + TimeInterface $time = NULL, + OgAccessInterface $og_access, + MessengerInterface $messenger +) { parent::__construct($entity_manager, $entity_type_bundle_info, $time); $this->ogAccess = $og_access; + $this->messenger = $messenger; } /** @@ -50,7 +67,8 @@ public static function create(ContainerInterface $container) { $container->get('entity.manager'), $container->get('entity_type.bundle.info'), $container->get('datetime.time'), - $container->get('og.access') + $container->get('og.access'), + $container->get('messanger') ); } @@ -121,12 +139,12 @@ public function save(array $form, FormStateInterface $form_state) { if ($insert) { $this->logger('og')->notice('OG Membership: added the @membership_type membership for the use uid @uid to the group of the entity-type @group_type and ID @gid.', $context); - drupal_set_message($this->t('Added %user to %group.', $t_args)); + $this->messenger->addMessage($this->t('Added %user to %group.', $t_args)); return; } $this->logger('og')->notice('OG Membership: updated the @membership_type membership for the use uid @uid to the group of the entity-type @group_type and ID @gid.', $context); - drupal_set_message($this->t('Updated the membership for %user to %group.', $t_args)); + $this->messenger->addMessage($this->t('Updated the membership for %user to %group.', $t_args)); } } diff --git a/src/Form/OgMembershipTypeForm.php b/src/Form/OgMembershipTypeForm.php index 3a6369d08..a11fd9fe1 100644 --- a/src/Form/OgMembershipTypeForm.php +++ b/src/Form/OgMembershipTypeForm.php @@ -7,6 +7,7 @@ use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Messenger\MessengerInterface; /** * Form handler for OG membership type forms. @@ -20,23 +21,24 @@ class OgMembershipTypeForm extends BundleEntityFormBase { */ protected $entityManager; + /** + * The messenger. + * + * @var \Drupal\Core\Messenger\MessengerInterface + */ + protected $messenger; + /** * Constructs the OgMembershipTypeForm object. * * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager. + * @param \Drupal\Core\Messenger\MessengerInterface $messenger + * The messenger. */ - public function __construct(EntityManagerInterface $entity_manager) { + public function __construct(EntityManagerInterface $entity_manager, MessengerInterface $messenger) { $this->entityManager = $entity_manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('entity.manager') - ); + $this->messenger = $messenger; } /** @@ -111,10 +113,10 @@ public function save(array $form, FormStateInterface $form_state) { $t_args = ['%name' => $type->label()]; if ($status == SAVED_UPDATED) { - drupal_set_message($this->t('The membership type %name has been updated.', $t_args)); + $this->messenger->addMessage($this->t('The membership type %name has been updated.', $t_args)); } elseif ($status == SAVED_NEW) { - drupal_set_message($this->t('The membership type %name has been added.', $t_args)); + $this->messenger->addMessage($this->t('The membership type %name has been added.', $t_args)); $context = array_merge($t_args, ['link' => $type->link($this->t('View'), 'collection')]); $this->logger('og')->notice('Added membership type %name.', $context); } From dc15112bcd764be9d16c3d075ea77c6546fbf5bf Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 09:10:06 +0100 Subject: [PATCH 080/111] add cache_test --- og_ui/tests/src/Functional/BundleFormAlterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/og_ui/tests/src/Functional/BundleFormAlterTest.php b/og_ui/tests/src/Functional/BundleFormAlterTest.php index bbd539b2a..8eb189756 100644 --- a/og_ui/tests/src/Functional/BundleFormAlterTest.php +++ b/og_ui/tests/src/Functional/BundleFormAlterTest.php @@ -18,7 +18,7 @@ class BundleFormAlterTest extends BrowserTestBase { /** * {@inheritdoc} */ - public static $modules = ['block_content', 'entity_test', 'node', 'og_ui', 'system', 'og', 'options']; + public static $modules = ['block_content', 'entity_test', 'node', 'og_ui', 'system', 'og', 'options', 'cache_test']; /** * An administrator user. From 2862839340c04ff242bb86325ed762388ff8b14e Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 09:15:11 +0100 Subject: [PATCH 081/111] add messenger to test --- tests/src/Unit/SubscriptionControllerTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/src/Unit/SubscriptionControllerTest.php b/tests/src/Unit/SubscriptionControllerTest.php index 0d3efe2d0..c0e9245d6 100644 --- a/tests/src/Unit/SubscriptionControllerTest.php +++ b/tests/src/Unit/SubscriptionControllerTest.php @@ -14,6 +14,7 @@ use Drupal\og\OgMembershipInterface; use Drupal\Tests\UnitTestCase; use Drupal\user\EntityOwnerInterface; +use Drupal\Core\Messenger\MessengerInterface; /** * Tests the subscription controller. @@ -91,13 +92,14 @@ public function setUp() { $this->ogMembership = $this->prophesize(OgMembershipInterface::class); $this->url = $this->prophesize(Url::class); $this->user = $this->prophesize(AccountInterface::class); - + $this->messenger = $this->prophesize(MessengerInterface::class); // Set the container for the string translation service. $container = new ContainerBuilder(); $container->set('current_user', $this->user->reveal()); $container->set('entity.form_builder', $this->entityFormBuilder->reveal()); $container->set('og.membership_manager', $this->membershipManager->reveal()); $container->set('string_translation', $this->getStringTranslationStub()); + $container->set('messenger'), $this->messenger->reveal(); \Drupal::setContainer($container); } From 970b20f2f3acebe8f5131b23cec2386487042827 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 09:41:46 +0100 Subject: [PATCH 082/111] fix typo --- tests/src/Unit/SubscriptionControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Unit/SubscriptionControllerTest.php b/tests/src/Unit/SubscriptionControllerTest.php index c0e9245d6..81d71397c 100644 --- a/tests/src/Unit/SubscriptionControllerTest.php +++ b/tests/src/Unit/SubscriptionControllerTest.php @@ -99,7 +99,7 @@ public function setUp() { $container->set('entity.form_builder', $this->entityFormBuilder->reveal()); $container->set('og.membership_manager', $this->membershipManager->reveal()); $container->set('string_translation', $this->getStringTranslationStub()); - $container->set('messenger'), $this->messenger->reveal(); + $container->set('messenger', $this->messenger->reveal()); \Drupal::setContainer($container); } From 01610781cd68b87e5a73cbb9d3c5bdec6f751dc5 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 09:53:43 +0100 Subject: [PATCH 083/111] fix code style --- og_ui/tests/src/Functional/BundleFormAlterTest.php | 11 ++++++++++- src/Form/GroupSubscribeForm.php | 5 ++++- src/Form/GroupUnsubscribeConfirmForm.php | 4 +--- src/Form/OgMembershipTypeForm.php | 2 +- .../EntityReferenceSelection/OgUserSelection.php | 1 - .../UniqueOgMembershipConstraintValidator.php | 2 +- tests/src/Kernel/DefaultRoleEventIntegrationTest.php | 9 ++++++++- .../Entity/CacheInvalidationOnGroupChangeTest.php | 2 +- tests/src/Kernel/Field/AudienceFieldFormatterTest.php | 2 +- tests/src/Unit/SubscriptionControllerTest.php | 7 +++++++ 10 files changed, 34 insertions(+), 11 deletions(-) diff --git a/og_ui/tests/src/Functional/BundleFormAlterTest.php b/og_ui/tests/src/Functional/BundleFormAlterTest.php index 8eb189756..95bda4423 100644 --- a/og_ui/tests/src/Functional/BundleFormAlterTest.php +++ b/og_ui/tests/src/Functional/BundleFormAlterTest.php @@ -18,7 +18,16 @@ class BundleFormAlterTest extends BrowserTestBase { /** * {@inheritdoc} */ - public static $modules = ['block_content', 'entity_test', 'node', 'og_ui', 'system', 'og', 'options', 'cache_test']; + public static $modules = [ + 'block_content', + 'entity_test', + 'node', + 'og_ui', + 'system', + 'og', + 'options', + 'cache_test', + ]; /** * An administrator user. diff --git a/src/Form/GroupSubscribeForm.php b/src/Form/GroupSubscribeForm.php index 0a0a366bb..03c16e8bd 100644 --- a/src/Form/GroupSubscribeForm.php +++ b/src/Form/GroupSubscribeForm.php @@ -49,6 +49,8 @@ class GroupSubscribeForm extends ContentEntityForm { * The entity type bundle service. * @param \Drupal\Component\Datetime\TimeInterface $time * The time service. + * @param \Drupal\Core\Messenger\MessengerInterface $messenger + * The messenger. * * @todo Set the `EntityRepositoryInterface` type hint on the second argument * once Drupal 8.6.0 is released. It is currently omitted to preserve @@ -57,7 +59,8 @@ class GroupSubscribeForm extends ContentEntityForm { * @see https://github.com/Gizra/og/issues/397 */ public function __construct( - OgAccessInterface $og_access, $entity_repository, + OgAccessInterface $og_access, + EntityRepositoryInterface $entity_repository, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, MessengerInterface $messenger diff --git a/src/Form/GroupUnsubscribeConfirmForm.php b/src/Form/GroupUnsubscribeConfirmForm.php index 5c4116c64..2455d3e79 100644 --- a/src/Form/GroupUnsubscribeConfirmForm.php +++ b/src/Form/GroupUnsubscribeConfirmForm.php @@ -15,7 +15,7 @@ class GroupUnsubscribeConfirmForm extends ContentEntityDeleteForm { /** * The messenger. * - * @var \Drupal\Core\Messenger\MessengerInterface $messenger + * @var \Drupal\Core\Messenger\MessengerInterface */ protected $messenger; @@ -38,8 +38,6 @@ public static function create(ContainerInterface $container) { ); } - - /** * {@inheritdoc} */ diff --git a/src/Form/OgMembershipTypeForm.php b/src/Form/OgMembershipTypeForm.php index a11fd9fe1..72df86b0e 100644 --- a/src/Form/OgMembershipTypeForm.php +++ b/src/Form/OgMembershipTypeForm.php @@ -6,8 +6,8 @@ use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Messenger\MessengerInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Form handler for OG membership type forms. diff --git a/src/Plugin/EntityReferenceSelection/OgUserSelection.php b/src/Plugin/EntityReferenceSelection/OgUserSelection.php index 1f14b5a22..e66edd5d6 100644 --- a/src/Plugin/EntityReferenceSelection/OgUserSelection.php +++ b/src/Plugin/EntityReferenceSelection/OgUserSelection.php @@ -133,7 +133,6 @@ public function entityQueryAlter(SelectInterface $query) { // Exclude users who are already in the current group. // This has to be done on the SQL query rather than the entity query, // because a reverse relationship to the OG membership entity is needed. - // @todo implement an easier, more consistent way to get the group type. At // the moment, this works either for checkboxes or OG Autocomplete widget // types on entities that have a getGroup() method. It also does not work diff --git a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php index ed593ca2d..20579a41c 100644 --- a/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php +++ b/src/Plugin/Validation/Constraint/UniqueOgMembershipConstraintValidator.php @@ -51,7 +51,7 @@ public function validate($value, Constraint $constraint) { $membership_ids = $query->execute(); if ($membership_ids) { - $user = \Drupal::service('entity_type.manager')->getStorage('user')->load($new_member_uid); + $user = \Drupal::service('entity_type.manager')->getStorage('user')->load($new_member_uid); $this->context->addViolation($constraint->NotUniqueMembership, ['%user' => $user->getDisplayName()]); return; } diff --git a/tests/src/Kernel/DefaultRoleEventIntegrationTest.php b/tests/src/Kernel/DefaultRoleEventIntegrationTest.php index 12afaf4e2..545de2ebf 100644 --- a/tests/src/Kernel/DefaultRoleEventIntegrationTest.php +++ b/tests/src/Kernel/DefaultRoleEventIntegrationTest.php @@ -18,7 +18,14 @@ class DefaultRoleEventIntegrationTest extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = ['entity_test', 'og', 'system', 'user', 'field', 'options']; + public static $modules = [ + 'entity_test', + 'og', + 'system', + 'user', + 'field', + 'options', + ]; /** * The Symfony event dispatcher. diff --git a/tests/src/Kernel/Entity/CacheInvalidationOnGroupChangeTest.php b/tests/src/Kernel/Entity/CacheInvalidationOnGroupChangeTest.php index efad1d31e..307c4a733 100644 --- a/tests/src/Kernel/Entity/CacheInvalidationOnGroupChangeTest.php +++ b/tests/src/Kernel/Entity/CacheInvalidationOnGroupChangeTest.php @@ -24,7 +24,7 @@ class CacheInvalidationOnGroupChangeTest extends KernelTestBase { 'og', 'system', 'user', - 'options' + 'options', ]; /** diff --git a/tests/src/Kernel/Field/AudienceFieldFormatterTest.php b/tests/src/Kernel/Field/AudienceFieldFormatterTest.php index aae496c33..d485441e8 100644 --- a/tests/src/Kernel/Field/AudienceFieldFormatterTest.php +++ b/tests/src/Kernel/Field/AudienceFieldFormatterTest.php @@ -15,7 +15,7 @@ class AudienceFieldFormatterTest extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = ['field', 'og', 'options',]; + public static $modules = ['field', 'og', 'options']; /** * Testing og_field_formatter_info_alter(). diff --git a/tests/src/Unit/SubscriptionControllerTest.php b/tests/src/Unit/SubscriptionControllerTest.php index 81d71397c..40b9f6802 100644 --- a/tests/src/Unit/SubscriptionControllerTest.php +++ b/tests/src/Unit/SubscriptionControllerTest.php @@ -80,6 +80,13 @@ class SubscriptionControllerTest extends UnitTestCase { */ protected $user; + /** + * The messenger. + * + * @var \Drupal\Core\Messenger\MessengerInterface + */ + protected $messenger; + /** * {@inheritdoc} */ From 4be862d0fc672964361f6c96d21363063529c467 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 10:35:56 +0100 Subject: [PATCH 084/111] Add field module to BundleFormAlter --- og_ui/tests/src/Functional/BundleFormAlterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/og_ui/tests/src/Functional/BundleFormAlterTest.php b/og_ui/tests/src/Functional/BundleFormAlterTest.php index 95bda4423..1427f0cbf 100644 --- a/og_ui/tests/src/Functional/BundleFormAlterTest.php +++ b/og_ui/tests/src/Functional/BundleFormAlterTest.php @@ -26,7 +26,7 @@ class BundleFormAlterTest extends BrowserTestBase { 'system', 'og', 'options', - 'cache_test', + 'field', ]; /** From 686e5fafcb3b23d963674f806b6949e9ace06979 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 11:13:57 +0100 Subject: [PATCH 085/111] fix code style --- src/Form/OgMembershipForm.php | 2 +- src/Form/OgMembershipTypeForm.php | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/Form/OgMembershipForm.php b/src/Form/OgMembershipForm.php index e2157cc44..4473aa7ff 100644 --- a/src/Form/OgMembershipForm.php +++ b/src/Form/OgMembershipForm.php @@ -53,7 +53,7 @@ public function __construct( TimeInterface $time = NULL, OgAccessInterface $og_access, MessengerInterface $messenger -) { + ) { parent::__construct($entity_manager, $entity_type_bundle_info, $time); $this->ogAccess = $og_access; $this->messenger = $messenger; diff --git a/src/Form/OgMembershipTypeForm.php b/src/Form/OgMembershipTypeForm.php index 72df86b0e..540970ec6 100644 --- a/src/Form/OgMembershipTypeForm.php +++ b/src/Form/OgMembershipTypeForm.php @@ -3,7 +3,7 @@ namespace Drupal\og\Form; use Drupal\Core\Entity\BundleEntityFormBase; -use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Messenger\MessengerInterface; @@ -15,11 +15,11 @@ class OgMembershipTypeForm extends BundleEntityFormBase { /** - * The entity manager. + * The entity type manager. * - * @var \Drupal\Core\Entity\EntityManagerInterface + * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ - protected $entityManager; + protected $entityTypeManager; /** * The messenger. @@ -31,16 +31,26 @@ class OgMembershipTypeForm extends BundleEntityFormBase { /** * Constructs the OgMembershipTypeForm object. * - * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager - * The entity manager. + * @param \Drupal\Core\Entity\entityTypeManagerInterface $entity_manager + * The entity type manager. * @param \Drupal\Core\Messenger\MessengerInterface $messenger * The messenger. */ - public function __construct(EntityManagerInterface $entity_manager, MessengerInterface $messenger) { - $this->entityManager = $entity_manager; + public function __construct(entityTypeManagerInterface $entity_manager, MessengerInterface $messenger) { + $this->entityTypeManager = $entity_manager; $this->messenger = $messenger; } + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity_type.manager'), + $container->get('messenger') + ); + } + /** * {@inheritdoc} */ @@ -121,7 +131,7 @@ public function save(array $form, FormStateInterface $form_state) { $this->logger('og')->notice('Added membership type %name.', $context); } - $this->entityManager->clearCachedFieldDefinitions(); + $this->entityTypeManager->clearCachedFieldDefinitions(); $form_state->setRedirectUrl($type->urlInfo('collection')); } From c89c4ad783e27a175d502f978b7c20ad5ad9134f Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 11:30:40 +0100 Subject: [PATCH 086/111] Revert "Remove t() from setLabel()" This reverts commit 3e93d7a6b6be93be8fd51d77a86adce48d6f09dc. --- og.install | 2 +- src/Entity/OgMembership.php | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/og.install b/og.install index 777a283a8..80ad218cf 100644 --- a/og.install +++ b/og.install @@ -23,7 +23,7 @@ function og_update_8001(&$sandbox) { if (!isset($sandbox['total'])) { $storage_definition = BaseFieldDefinition::create('string') - ->setLabel('Group bundle ID') + ->setLabel(t('Group bundle ID')) ->setDescription(t('The bundle ID of the group.')); \Drupal::entityDefinitionUpdateManager()->installFieldStorageDefinition('entity_bundle', 'og_membership', 'og', $storage_definition); diff --git a/src/Entity/OgMembership.php b/src/Entity/OgMembership.php index f63127d44..30fa58d4e 100644 --- a/src/Entity/OgMembership.php +++ b/src/Entity/OgMembership.php @@ -363,23 +363,23 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = []; $fields['id'] = BaseFieldDefinition::create('integer') - ->setLabel('ID') + ->setLabel(t('ID')) ->setDescription(t("The group membership's unique ID.")) ->setReadOnly(TRUE) ->setSetting('unsigned', TRUE); $fields['uuid'] = BaseFieldDefinition::create('uuid') - ->setLabel('UUID') + ->setLabel(t('UUID')) ->setDescription(t('The membership UUID.')) ->setReadOnly(TRUE); $fields['type'] = BaseFieldDefinition::create('entity_reference') - ->setLabel('Type') + ->setLabel(t('Type')) ->setDescription(t('The bundle of the membership')) ->setSetting('target_type', 'og_membership_type'); $fields['uid'] = BaseFieldDefinition::create('entity_reference') - ->setLabel('Username') + ->setLabel(t('Username')) ->setDescription(t('The user ID of the member.')) ->setSetting('target_type', 'user') ->setSetting('handler', 'og:user') @@ -398,19 +398,19 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setRequired(TRUE); $fields['entity_type'] = BaseFieldDefinition::create('string') - ->setLabel('Group entity type') + ->setLabel(t('Group entity type')) ->setDescription(t('The entity type of the group.')); $fields['entity_bundle'] = BaseFieldDefinition::create('string') - ->setLabel('Group bundle ID') + ->setLabel(t('Group bundle ID')) ->setDescription(t('The bundle ID of the group.')); $fields['entity_id'] = BaseFieldDefinition::create('string') - ->setLabel('Group entity ID') + ->setLabel(t('Group entity ID')) ->setDescription(t('The entity ID of the group.')); $fields['state'] = BaseFieldDefinition::create('list_string') - ->setLabel('State') + ->setLabel(t('State')) ->setDescription(t('The user membership state: active, pending, or blocked.')) ->setDefaultValue(OgMembershipInterface::STATE_ACTIVE) ->setSettings([ @@ -429,7 +429,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setRequired(TRUE); $fields['roles'] = BaseFieldDefinition::create('entity_reference') - ->setLabel('Roles') + ->setLabel(t('Roles')) ->setDescription(t('The OG roles related to an OG membership entity.')) ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) ->setSetting('target_type', 'og_role') @@ -443,11 +443,11 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setDisplayConfigurable('form', TRUE); $fields['created'] = BaseFieldDefinition::create('created') - ->setLabel('Create') + ->setLabel(t('Create')) ->setDescription(t('The Unix timestamp when the membership was created.')); $fields['language'] = BaseFieldDefinition::create('language') - ->setLabel('Language') + ->setLabel(t('Language')) ->setDescription(t('The {languages}.language of this membership.')); return $fields; From f4df10be63b4159b6e5d3b9777cdaaa4703f4d0a Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 12:42:52 +0100 Subject: [PATCH 087/111] use entitymanager for backport compability --- og_ui/tests/src/Functional/BundleFormAlterTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/og_ui/tests/src/Functional/BundleFormAlterTest.php b/og_ui/tests/src/Functional/BundleFormAlterTest.php index 1427f0cbf..eb5a0c48d 100644 --- a/og_ui/tests/src/Functional/BundleFormAlterTest.php +++ b/og_ui/tests/src/Functional/BundleFormAlterTest.php @@ -39,9 +39,9 @@ class BundleFormAlterTest extends BrowserTestBase { /** * The entity type manager. * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface + * @var \Drupal\Core\Entity\EntityManagerInterface */ - protected $entityTypeManager; + protected $entityManager; /** * {@inheritdoc} @@ -49,7 +49,7 @@ class BundleFormAlterTest extends BrowserTestBase { public function setUp() { parent::setUp(); - $this->entityTypeManager = \Drupal::entityTypeManager(); + $this->entityManager = \Drupal::entityManager(); // Log in as an administrator that can manage blocks and content types. $this->adminUser = $this->drupalCreateUser([ @@ -121,7 +121,7 @@ public function testGroupContentAjax() { $form_state = new FormState(); // Set the form state as if the 'entity_test' option was chosen with AJAX. $form_state->setValue('og_target_type', 'entity_test'); - $entity = $this->entityTypeManager->getStorage('node_type')->create([]); + $entity = $this->entityManager->getStorage('node_type')->create([]); (new BundleFormAlter($entity))->formAlter($form, $form_state); // Check that the target bundles are set to the test entity bundle. From 7da362301fd2ebbec5b0c7c1b1786f988a57a1d9 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 19 Nov 2018 12:49:32 +0100 Subject: [PATCH 088/111] Revert "use entitymanager for backport compability" This reverts commit a430a742eb1bb837d1327bad530ea0fe484fa61d. --- og_ui/tests/src/Functional/BundleFormAlterTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/og_ui/tests/src/Functional/BundleFormAlterTest.php b/og_ui/tests/src/Functional/BundleFormAlterTest.php index eb5a0c48d..1427f0cbf 100644 --- a/og_ui/tests/src/Functional/BundleFormAlterTest.php +++ b/og_ui/tests/src/Functional/BundleFormAlterTest.php @@ -39,9 +39,9 @@ class BundleFormAlterTest extends BrowserTestBase { /** * The entity type manager. * - * @var \Drupal\Core\Entity\EntityManagerInterface + * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ - protected $entityManager; + protected $entityTypeManager; /** * {@inheritdoc} @@ -49,7 +49,7 @@ class BundleFormAlterTest extends BrowserTestBase { public function setUp() { parent::setUp(); - $this->entityManager = \Drupal::entityManager(); + $this->entityTypeManager = \Drupal::entityTypeManager(); // Log in as an administrator that can manage blocks and content types. $this->adminUser = $this->drupalCreateUser([ @@ -121,7 +121,7 @@ public function testGroupContentAjax() { $form_state = new FormState(); // Set the form state as if the 'entity_test' option was chosen with AJAX. $form_state->setValue('og_target_type', 'entity_test'); - $entity = $this->entityManager->getStorage('node_type')->create([]); + $entity = $this->entityTypeManager->getStorage('node_type')->create([]); (new BundleFormAlter($entity))->formAlter($form, $form_state); // Check that the target bundles are set to the test entity bundle. From 1d2f4bcccfdb93c1c7fac37ff346e2fec2deb533 Mon Sep 17 00:00:00 2001 From: Insasse Date: Wed, 21 Nov 2018 09:13:59 +0100 Subject: [PATCH 089/111] Fix typos --- src/Form/OgMembershipForm.php | 2 +- src/Plugin/Derivative/OgLocalTask.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Form/OgMembershipForm.php b/src/Form/OgMembershipForm.php index 4473aa7ff..73dcd959c 100644 --- a/src/Form/OgMembershipForm.php +++ b/src/Form/OgMembershipForm.php @@ -68,7 +68,7 @@ public static function create(ContainerInterface $container) { $container->get('entity_type.bundle.info'), $container->get('datetime.time'), $container->get('og.access'), - $container->get('messanger') + $container->get('messenger') ); } diff --git a/src/Plugin/Derivative/OgLocalTask.php b/src/Plugin/Derivative/OgLocalTask.php index c861065c4..dd1019f80 100644 --- a/src/Plugin/Derivative/OgLocalTask.php +++ b/src/Plugin/Derivative/OgLocalTask.php @@ -28,7 +28,7 @@ class OgLocalTask extends DeriverBase implements ContainerDeriverInterface { * * @var \Drupal\Core\Routing\RouteProvider */ - protected $routProvider; + protected $routeProvider; /** * Creates an OgLocalTask object. @@ -40,7 +40,7 @@ class OgLocalTask extends DeriverBase implements ContainerDeriverInterface { */ public function __construct(GroupTypeManagerInterface $group_type_manager, RouteProvider $route_provider) { $this->groupTypeManager = $group_type_manager; - $this->routProvider = $route_provider; + $this->routeProvider = $route_provider; } /** @@ -62,7 +62,7 @@ public function getDerivativeDefinitions($base_plugin_definition) { foreach (array_keys($this->groupTypeManager->getGroupMap()) as $entity_type_id) { $route_name = "entity.$entity_type_id.og_admin_routes"; - if (!$this->routProvider->getRoutesByNames([$route_name])) { + if (!$this->routeProvider->getRoutesByNames([$route_name])) { // Route not found. continue; } From c270e459af8c8c49618ad9634abaf6840e4d6af1 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 26 Nov 2018 13:49:56 +0100 Subject: [PATCH 090/111] Remove installSchema() --- tests/src/Kernel/Access/AccessByOgMembershipTest.php | 1 - tests/src/Kernel/Access/OgAccessHookTest.php | 1 - tests/src/Kernel/Access/OgEntityAccessTest.php | 1 - tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php | 2 +- tests/src/Kernel/Action/ActionTestBase.php | 1 - .../Action/ChangeMultipleOgMembershipRolesActionTestBase.php | 2 -- tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php | 1 - tests/src/Kernel/Entity/EntityCreateAccessTest.php | 1 - tests/src/Kernel/Entity/GetBundleByBundleTest.php | 1 - tests/src/Kernel/Entity/GetGroupContentTest.php | 1 - tests/src/Kernel/Entity/GetMembershipsTest.php | 2 -- tests/src/Kernel/Entity/GetUserGroupsTest.php | 1 - tests/src/Kernel/Entity/GroupMembershipManagerTest.php | 1 - tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php | 1 - tests/src/Kernel/Entity/OgMembershipTest.php | 1 - tests/src/Kernel/Entity/OgStandardReferenceItemTest.php | 1 - tests/src/Kernel/Entity/ReferenceStringIdTest.php | 1 - tests/src/Kernel/Entity/SelectionHandlerTest.php | 1 - tests/src/Kernel/Form/GroupSubscribeFormTest.php | 1 - tests/src/Kernel/GroupManagerSubscriptionTest.php | 1 - tests/src/Kernel/GroupTypeConditionTest.php | 1 - tests/src/Kernel/OgDeleteOrphansTest.php | 2 -- 22 files changed, 1 insertion(+), 25 deletions(-) diff --git a/tests/src/Kernel/Access/AccessByOgMembershipTest.php b/tests/src/Kernel/Access/AccessByOgMembershipTest.php index 0594d0a07..5218c8b6c 100644 --- a/tests/src/Kernel/Access/AccessByOgMembershipTest.php +++ b/tests/src/Kernel/Access/AccessByOgMembershipTest.php @@ -73,7 +73,6 @@ public function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); // Create a user role for a standard authenticated user. $role = Role::create([ diff --git a/tests/src/Kernel/Access/OgAccessHookTest.php b/tests/src/Kernel/Access/OgAccessHookTest.php index 799e05088..6f2d5bca0 100644 --- a/tests/src/Kernel/Access/OgAccessHookTest.php +++ b/tests/src/Kernel/Access/OgAccessHookTest.php @@ -84,7 +84,6 @@ public function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); // Create two roles: one for normal users, and one for administrators. foreach (['authenticated', 'administrator'] as $role_id) { diff --git a/tests/src/Kernel/Access/OgEntityAccessTest.php b/tests/src/Kernel/Access/OgEntityAccessTest.php index ddd86d6e7..b51d79ba9 100644 --- a/tests/src/Kernel/Access/OgEntityAccessTest.php +++ b/tests/src/Kernel/Access/OgEntityAccessTest.php @@ -144,7 +144,6 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('entity_test'); - $this->installSchema('system', 'sequences'); $this->groupBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php index b70fa6d53..63f6243bc 100644 --- a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php +++ b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php @@ -93,7 +93,6 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); $this->entityTypeManager = $this->container->get('entity_type.manager'); @@ -232,6 +231,7 @@ protected function setUp() { case 'comment': $values = [ + 'name' => $this->randomString(), 'subject' => 'subscribe', 'comment_type' => $bundle_id, 'entity_id' => $this->group->id(), diff --git a/tests/src/Kernel/Action/ActionTestBase.php b/tests/src/Kernel/Action/ActionTestBase.php index 2ecf08f9a..6efef33d1 100644 --- a/tests/src/Kernel/Action/ActionTestBase.php +++ b/tests/src/Kernel/Action/ActionTestBase.php @@ -84,7 +84,6 @@ public function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); - $this->installSchema('system', ['sequences']); $this->membershipManager = $this->container->get('og.membership_manager'); $this->groupTypeManager = $this->container->get('og.group_type_manager'); diff --git a/tests/src/Kernel/Action/ChangeMultipleOgMembershipRolesActionTestBase.php b/tests/src/Kernel/Action/ChangeMultipleOgMembershipRolesActionTestBase.php index 4c6f9d9aa..ec9be610f 100644 --- a/tests/src/Kernel/Action/ChangeMultipleOgMembershipRolesActionTestBase.php +++ b/tests/src/Kernel/Action/ChangeMultipleOgMembershipRolesActionTestBase.php @@ -27,8 +27,6 @@ class ChangeMultipleOgMembershipRolesActionTestBase extends ChangeOgMembershipAc public function setUp() { parent::setUp(); - $this->installSchema('system', ['key_value_expire']); - $this->tempStorageFactory = $this->container->get('tempstore.private'); // Set up the group administrator as the user that will be logged in during diff --git a/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php b/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php index de0471227..92e86abb3 100644 --- a/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php +++ b/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php @@ -38,7 +38,6 @@ public function setUp() { $this->installConfig(['og']); $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); - $this->installSchema('system', 'sequences'); NodeType::create([ 'name' => $this->randomString(), diff --git a/tests/src/Kernel/Entity/EntityCreateAccessTest.php b/tests/src/Kernel/Entity/EntityCreateAccessTest.php index e0d225fd5..5be5fc53b 100644 --- a/tests/src/Kernel/Entity/EntityCreateAccessTest.php +++ b/tests/src/Kernel/Entity/EntityCreateAccessTest.php @@ -60,7 +60,6 @@ public function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); // Create a "group" node type and turn it into a group type. $this->groupType = NodeType::create([ diff --git a/tests/src/Kernel/Entity/GetBundleByBundleTest.php b/tests/src/Kernel/Entity/GetBundleByBundleTest.php index d89e83614..8ea4997a1 100644 --- a/tests/src/Kernel/Entity/GetBundleByBundleTest.php +++ b/tests/src/Kernel/Entity/GetBundleByBundleTest.php @@ -61,7 +61,6 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); $this->groupTypeManager = $this->container->get('og.group_type_manager'); diff --git a/tests/src/Kernel/Entity/GetGroupContentTest.php b/tests/src/Kernel/Entity/GetGroupContentTest.php index b35cd0f58..37f3bc427 100644 --- a/tests/src/Kernel/Entity/GetGroupContentTest.php +++ b/tests/src/Kernel/Entity/GetGroupContentTest.php @@ -56,7 +56,6 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */ $entity_type_manager = $this->container->get('entity_type.manager'); diff --git a/tests/src/Kernel/Entity/GetMembershipsTest.php b/tests/src/Kernel/Entity/GetMembershipsTest.php index 58088897d..fdc58c32e 100644 --- a/tests/src/Kernel/Entity/GetMembershipsTest.php +++ b/tests/src/Kernel/Entity/GetMembershipsTest.php @@ -64,8 +64,6 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); - $this->installSchema('user', ['users_data']); $this->entityTypeManager = $this->container->get('entity_type.manager'); diff --git a/tests/src/Kernel/Entity/GetUserGroupsTest.php b/tests/src/Kernel/Entity/GetUserGroupsTest.php index 543c35791..4f516eb75 100644 --- a/tests/src/Kernel/Entity/GetUserGroupsTest.php +++ b/tests/src/Kernel/Entity/GetUserGroupsTest.php @@ -89,7 +89,6 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('entity_test'); - $this->installSchema('system', 'sequences'); $this->groupBundle = mb_strtolower($this->randomMachineName()); $this->groupContentBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php index ac5950ae8..2bcad15a1 100644 --- a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php +++ b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php @@ -88,7 +88,6 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); $this->entityTypeManager = $this->container->get('entity_type.manager'); $this->membershipManager = $this->container->get('og.membership_manager'); diff --git a/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php b/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php index 019c70cdd..881c4eecd 100644 --- a/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php +++ b/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php @@ -60,7 +60,6 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); - $this->installSchema('system', 'sequences'); // Create a "group" node type and turn it into a group type. $this->groupBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Entity/OgMembershipTest.php b/tests/src/Kernel/Entity/OgMembershipTest.php index e97725faf..f7d55f0f5 100644 --- a/tests/src/Kernel/Entity/OgMembershipTest.php +++ b/tests/src/Kernel/Entity/OgMembershipTest.php @@ -74,7 +74,6 @@ protected function setUp() { $this->installEntitySchema('entity_test'); $this->installEntitySchema('node'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); $this->entityTypeManager = $this->container->get('entity_type.manager'); $storage = $this->entityTypeManager->getStorage('user'); diff --git a/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php b/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php index 3ed486df0..3b4e3b512 100644 --- a/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php +++ b/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php @@ -42,7 +42,6 @@ protected function setUp() { $this->installEntitySchema('entity_test'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); // Create several bundles. for ($i = 0; $i <= 2; $i++) { diff --git a/tests/src/Kernel/Entity/ReferenceStringIdTest.php b/tests/src/Kernel/Entity/ReferenceStringIdTest.php index 3ea0c4b5e..e12facb66 100644 --- a/tests/src/Kernel/Entity/ReferenceStringIdTest.php +++ b/tests/src/Kernel/Entity/ReferenceStringIdTest.php @@ -58,7 +58,6 @@ protected function setUp() { $this->installEntitySchema('entity_test_string_id'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); // Create two bundles, one will serve as group, the other as group content. for ($i = 0; $i < 2; $i++) { diff --git a/tests/src/Kernel/Entity/SelectionHandlerTest.php b/tests/src/Kernel/Entity/SelectionHandlerTest.php index 3673be1d3..59214af49 100644 --- a/tests/src/Kernel/Entity/SelectionHandlerTest.php +++ b/tests/src/Kernel/Entity/SelectionHandlerTest.php @@ -83,7 +83,6 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); - $this->installSchema('system', 'sequences'); // Setting up variables. $this->groupBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Form/GroupSubscribeFormTest.php b/tests/src/Kernel/Form/GroupSubscribeFormTest.php index 5b85cde8e..6b3926657 100644 --- a/tests/src/Kernel/Form/GroupSubscribeFormTest.php +++ b/tests/src/Kernel/Form/GroupSubscribeFormTest.php @@ -70,7 +70,6 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); - $this->installSchema('system', 'sequences'); // Create 3 test bundles and declare them as groups. $bundle_names = []; diff --git a/tests/src/Kernel/GroupManagerSubscriptionTest.php b/tests/src/Kernel/GroupManagerSubscriptionTest.php index efdf4039d..a1e16e121 100644 --- a/tests/src/Kernel/GroupManagerSubscriptionTest.php +++ b/tests/src/Kernel/GroupManagerSubscriptionTest.php @@ -64,7 +64,6 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', ['sequences']); // Create a group type. NodeType::create([ diff --git a/tests/src/Kernel/GroupTypeConditionTest.php b/tests/src/Kernel/GroupTypeConditionTest.php index 7ee4361c6..f296e4fa2 100644 --- a/tests/src/Kernel/GroupTypeConditionTest.php +++ b/tests/src/Kernel/GroupTypeConditionTest.php @@ -62,7 +62,6 @@ protected function setUp() { $this->installEntitySchema('entity_test'); $this->installEntitySchema('node'); $this->installEntitySchema('user'); - $this->installSchema('system', ['sequences']); // Create three test groups of different types. for ($i = 0; $i < 2; $i++) { diff --git a/tests/src/Kernel/OgDeleteOrphansTest.php b/tests/src/Kernel/OgDeleteOrphansTest.php index e658644ae..3035c7e8e 100644 --- a/tests/src/Kernel/OgDeleteOrphansTest.php +++ b/tests/src/Kernel/OgDeleteOrphansTest.php @@ -61,8 +61,6 @@ public function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); - $this->installSchema('node', 'node_access'); - $this->installSchema('system', ['sequences']); /** @var \Drupal\og\OgDeleteOrphansPluginManager $plugin_manager */ $plugin_manager = \Drupal::service('plugin.manager.og.delete_orphans'); From 75e9a31b7ec0f4ec1bae80dc45750f181ef2fcd3 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 26 Nov 2018 14:01:22 +0100 Subject: [PATCH 091/111] Revert "Remove installSchema()" This reverts commit 66c2485b07d7755e48d8bcb98c419ca6647833c9. --- tests/src/Kernel/Access/AccessByOgMembershipTest.php | 1 + tests/src/Kernel/Access/OgAccessHookTest.php | 1 + tests/src/Kernel/Access/OgEntityAccessTest.php | 1 + tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php | 2 +- tests/src/Kernel/Action/ActionTestBase.php | 1 + .../Action/ChangeMultipleOgMembershipRolesActionTestBase.php | 2 ++ tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php | 1 + tests/src/Kernel/Entity/EntityCreateAccessTest.php | 1 + tests/src/Kernel/Entity/GetBundleByBundleTest.php | 1 + tests/src/Kernel/Entity/GetGroupContentTest.php | 1 + tests/src/Kernel/Entity/GetMembershipsTest.php | 2 ++ tests/src/Kernel/Entity/GetUserGroupsTest.php | 1 + tests/src/Kernel/Entity/GroupMembershipManagerTest.php | 1 + tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php | 1 + tests/src/Kernel/Entity/OgMembershipTest.php | 1 + tests/src/Kernel/Entity/OgStandardReferenceItemTest.php | 1 + tests/src/Kernel/Entity/ReferenceStringIdTest.php | 1 + tests/src/Kernel/Entity/SelectionHandlerTest.php | 1 + tests/src/Kernel/Form/GroupSubscribeFormTest.php | 1 + tests/src/Kernel/GroupManagerSubscriptionTest.php | 1 + tests/src/Kernel/GroupTypeConditionTest.php | 1 + tests/src/Kernel/OgDeleteOrphansTest.php | 2 ++ 22 files changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/src/Kernel/Access/AccessByOgMembershipTest.php b/tests/src/Kernel/Access/AccessByOgMembershipTest.php index 5218c8b6c..0594d0a07 100644 --- a/tests/src/Kernel/Access/AccessByOgMembershipTest.php +++ b/tests/src/Kernel/Access/AccessByOgMembershipTest.php @@ -73,6 +73,7 @@ public function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); // Create a user role for a standard authenticated user. $role = Role::create([ diff --git a/tests/src/Kernel/Access/OgAccessHookTest.php b/tests/src/Kernel/Access/OgAccessHookTest.php index 6f2d5bca0..799e05088 100644 --- a/tests/src/Kernel/Access/OgAccessHookTest.php +++ b/tests/src/Kernel/Access/OgAccessHookTest.php @@ -84,6 +84,7 @@ public function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); // Create two roles: one for normal users, and one for administrators. foreach (['authenticated', 'administrator'] as $role_id) { diff --git a/tests/src/Kernel/Access/OgEntityAccessTest.php b/tests/src/Kernel/Access/OgEntityAccessTest.php index b51d79ba9..ddd86d6e7 100644 --- a/tests/src/Kernel/Access/OgEntityAccessTest.php +++ b/tests/src/Kernel/Access/OgEntityAccessTest.php @@ -144,6 +144,7 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('entity_test'); + $this->installSchema('system', 'sequences'); $this->groupBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php index 63f6243bc..b70fa6d53 100644 --- a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php +++ b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php @@ -93,6 +93,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); $this->entityTypeManager = $this->container->get('entity_type.manager'); @@ -231,7 +232,6 @@ protected function setUp() { case 'comment': $values = [ - 'name' => $this->randomString(), 'subject' => 'subscribe', 'comment_type' => $bundle_id, 'entity_id' => $this->group->id(), diff --git a/tests/src/Kernel/Action/ActionTestBase.php b/tests/src/Kernel/Action/ActionTestBase.php index 6efef33d1..1190f71b7 100644 --- a/tests/src/Kernel/Action/ActionTestBase.php +++ b/tests/src/Kernel/Action/ActionTestBase.php @@ -84,6 +84,7 @@ public function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); + $this->installSchema('system', ['queue', 'sequences']); $this->membershipManager = $this->container->get('og.membership_manager'); $this->groupTypeManager = $this->container->get('og.group_type_manager'); diff --git a/tests/src/Kernel/Action/ChangeMultipleOgMembershipRolesActionTestBase.php b/tests/src/Kernel/Action/ChangeMultipleOgMembershipRolesActionTestBase.php index ec9be610f..4c6f9d9aa 100644 --- a/tests/src/Kernel/Action/ChangeMultipleOgMembershipRolesActionTestBase.php +++ b/tests/src/Kernel/Action/ChangeMultipleOgMembershipRolesActionTestBase.php @@ -27,6 +27,8 @@ class ChangeMultipleOgMembershipRolesActionTestBase extends ChangeOgMembershipAc public function setUp() { parent::setUp(); + $this->installSchema('system', ['key_value_expire']); + $this->tempStorageFactory = $this->container->get('tempstore.private'); // Set up the group administrator as the user that will be logged in during diff --git a/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php b/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php index 92e86abb3..de0471227 100644 --- a/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php +++ b/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php @@ -38,6 +38,7 @@ public function setUp() { $this->installConfig(['og']); $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); + $this->installSchema('system', 'sequences'); NodeType::create([ 'name' => $this->randomString(), diff --git a/tests/src/Kernel/Entity/EntityCreateAccessTest.php b/tests/src/Kernel/Entity/EntityCreateAccessTest.php index 5be5fc53b..e0d225fd5 100644 --- a/tests/src/Kernel/Entity/EntityCreateAccessTest.php +++ b/tests/src/Kernel/Entity/EntityCreateAccessTest.php @@ -60,6 +60,7 @@ public function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); // Create a "group" node type and turn it into a group type. $this->groupType = NodeType::create([ diff --git a/tests/src/Kernel/Entity/GetBundleByBundleTest.php b/tests/src/Kernel/Entity/GetBundleByBundleTest.php index 8ea4997a1..d89e83614 100644 --- a/tests/src/Kernel/Entity/GetBundleByBundleTest.php +++ b/tests/src/Kernel/Entity/GetBundleByBundleTest.php @@ -61,6 +61,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); $this->groupTypeManager = $this->container->get('og.group_type_manager'); diff --git a/tests/src/Kernel/Entity/GetGroupContentTest.php b/tests/src/Kernel/Entity/GetGroupContentTest.php index 37f3bc427..b35cd0f58 100644 --- a/tests/src/Kernel/Entity/GetGroupContentTest.php +++ b/tests/src/Kernel/Entity/GetGroupContentTest.php @@ -56,6 +56,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */ $entity_type_manager = $this->container->get('entity_type.manager'); diff --git a/tests/src/Kernel/Entity/GetMembershipsTest.php b/tests/src/Kernel/Entity/GetMembershipsTest.php index fdc58c32e..58088897d 100644 --- a/tests/src/Kernel/Entity/GetMembershipsTest.php +++ b/tests/src/Kernel/Entity/GetMembershipsTest.php @@ -64,6 +64,8 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); + $this->installSchema('user', ['users_data']); $this->entityTypeManager = $this->container->get('entity_type.manager'); diff --git a/tests/src/Kernel/Entity/GetUserGroupsTest.php b/tests/src/Kernel/Entity/GetUserGroupsTest.php index 4f516eb75..543c35791 100644 --- a/tests/src/Kernel/Entity/GetUserGroupsTest.php +++ b/tests/src/Kernel/Entity/GetUserGroupsTest.php @@ -89,6 +89,7 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('entity_test'); + $this->installSchema('system', 'sequences'); $this->groupBundle = mb_strtolower($this->randomMachineName()); $this->groupContentBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php index 2bcad15a1..ac5950ae8 100644 --- a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php +++ b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php @@ -88,6 +88,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); $this->entityTypeManager = $this->container->get('entity_type.manager'); $this->membershipManager = $this->container->get('og.membership_manager'); diff --git a/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php b/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php index 881c4eecd..019c70cdd 100644 --- a/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php +++ b/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php @@ -60,6 +60,7 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); + $this->installSchema('system', 'sequences'); // Create a "group" node type and turn it into a group type. $this->groupBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Entity/OgMembershipTest.php b/tests/src/Kernel/Entity/OgMembershipTest.php index f7d55f0f5..e97725faf 100644 --- a/tests/src/Kernel/Entity/OgMembershipTest.php +++ b/tests/src/Kernel/Entity/OgMembershipTest.php @@ -74,6 +74,7 @@ protected function setUp() { $this->installEntitySchema('entity_test'); $this->installEntitySchema('node'); $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); $this->entityTypeManager = $this->container->get('entity_type.manager'); $storage = $this->entityTypeManager->getStorage('user'); diff --git a/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php b/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php index 3b4e3b512..3ed486df0 100644 --- a/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php +++ b/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php @@ -42,6 +42,7 @@ protected function setUp() { $this->installEntitySchema('entity_test'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); // Create several bundles. for ($i = 0; $i <= 2; $i++) { diff --git a/tests/src/Kernel/Entity/ReferenceStringIdTest.php b/tests/src/Kernel/Entity/ReferenceStringIdTest.php index e12facb66..3ea0c4b5e 100644 --- a/tests/src/Kernel/Entity/ReferenceStringIdTest.php +++ b/tests/src/Kernel/Entity/ReferenceStringIdTest.php @@ -58,6 +58,7 @@ protected function setUp() { $this->installEntitySchema('entity_test_string_id'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); // Create two bundles, one will serve as group, the other as group content. for ($i = 0; $i < 2; $i++) { diff --git a/tests/src/Kernel/Entity/SelectionHandlerTest.php b/tests/src/Kernel/Entity/SelectionHandlerTest.php index 59214af49..3673be1d3 100644 --- a/tests/src/Kernel/Entity/SelectionHandlerTest.php +++ b/tests/src/Kernel/Entity/SelectionHandlerTest.php @@ -83,6 +83,7 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); + $this->installSchema('system', 'sequences'); // Setting up variables. $this->groupBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Form/GroupSubscribeFormTest.php b/tests/src/Kernel/Form/GroupSubscribeFormTest.php index 6b3926657..5b85cde8e 100644 --- a/tests/src/Kernel/Form/GroupSubscribeFormTest.php +++ b/tests/src/Kernel/Form/GroupSubscribeFormTest.php @@ -70,6 +70,7 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); + $this->installSchema('system', 'sequences'); // Create 3 test bundles and declare them as groups. $bundle_names = []; diff --git a/tests/src/Kernel/GroupManagerSubscriptionTest.php b/tests/src/Kernel/GroupManagerSubscriptionTest.php index a1e16e121..24949d904 100644 --- a/tests/src/Kernel/GroupManagerSubscriptionTest.php +++ b/tests/src/Kernel/GroupManagerSubscriptionTest.php @@ -64,6 +64,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); + $this->installSchema('system', ['queue', 'sequences']); // Create a group type. NodeType::create([ diff --git a/tests/src/Kernel/GroupTypeConditionTest.php b/tests/src/Kernel/GroupTypeConditionTest.php index f296e4fa2..8306f394a 100644 --- a/tests/src/Kernel/GroupTypeConditionTest.php +++ b/tests/src/Kernel/GroupTypeConditionTest.php @@ -62,6 +62,7 @@ protected function setUp() { $this->installEntitySchema('entity_test'); $this->installEntitySchema('node'); $this->installEntitySchema('user'); + $this->installSchema('system', ['queue', 'sequences']); // Create three test groups of different types. for ($i = 0; $i < 2; $i++) { diff --git a/tests/src/Kernel/OgDeleteOrphansTest.php b/tests/src/Kernel/OgDeleteOrphansTest.php index 3035c7e8e..0ba6342f6 100644 --- a/tests/src/Kernel/OgDeleteOrphansTest.php +++ b/tests/src/Kernel/OgDeleteOrphansTest.php @@ -61,6 +61,8 @@ public function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); + $this->installSchema('node', 'node_access'); + $this->installSchema('system', ['queue', 'sequences']); /** @var \Drupal\og\OgDeleteOrphansPluginManager $plugin_manager */ $plugin_manager = \Drupal::service('plugin.manager.og.delete_orphans'); From eff799a8e22b829cbe4026f56ccd6c27e0abcb77 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 26 Nov 2018 14:06:03 +0100 Subject: [PATCH 092/111] Fix deprecated installSchema --- tests/src/Kernel/Access/AccessByOgMembershipTest.php | 2 +- tests/src/Kernel/Access/OgAccessHookTest.php | 2 +- tests/src/Kernel/Access/OgEntityAccessTest.php | 2 +- tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php | 2 +- tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php | 2 +- tests/src/Kernel/Entity/EntityCreateAccessTest.php | 2 +- tests/src/Kernel/Entity/GetBundleByBundleTest.php | 2 +- tests/src/Kernel/Entity/GetGroupContentTest.php | 2 +- tests/src/Kernel/Entity/GetMembershipsTest.php | 2 +- tests/src/Kernel/Entity/GetUserGroupsTest.php | 2 +- tests/src/Kernel/Entity/GroupMembershipManagerTest.php | 2 +- tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php | 2 +- tests/src/Kernel/Entity/OgMembershipTest.php | 2 +- tests/src/Kernel/Entity/OgStandardReferenceItemTest.php | 2 +- tests/src/Kernel/Entity/ReferenceStringIdTest.php | 2 +- tests/src/Kernel/Entity/SelectionHandlerTest.php | 2 +- tests/src/Kernel/Form/GroupSubscribeFormTest.php | 2 +- tests/src/Kernel/OgDeleteOrphansTest.php | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/src/Kernel/Access/AccessByOgMembershipTest.php b/tests/src/Kernel/Access/AccessByOgMembershipTest.php index 0594d0a07..9949d611f 100644 --- a/tests/src/Kernel/Access/AccessByOgMembershipTest.php +++ b/tests/src/Kernel/Access/AccessByOgMembershipTest.php @@ -73,7 +73,7 @@ public function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); // Create a user role for a standard authenticated user. $role = Role::create([ diff --git a/tests/src/Kernel/Access/OgAccessHookTest.php b/tests/src/Kernel/Access/OgAccessHookTest.php index 799e05088..ad35f4cc4 100644 --- a/tests/src/Kernel/Access/OgAccessHookTest.php +++ b/tests/src/Kernel/Access/OgAccessHookTest.php @@ -84,7 +84,7 @@ public function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); // Create two roles: one for normal users, and one for administrators. foreach (['authenticated', 'administrator'] as $role_id) { diff --git a/tests/src/Kernel/Access/OgEntityAccessTest.php b/tests/src/Kernel/Access/OgEntityAccessTest.php index ddd86d6e7..5446bedec 100644 --- a/tests/src/Kernel/Access/OgEntityAccessTest.php +++ b/tests/src/Kernel/Access/OgEntityAccessTest.php @@ -144,7 +144,7 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('entity_test'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); $this->groupBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php index b70fa6d53..c3e7ec0e7 100644 --- a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php +++ b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php @@ -93,7 +93,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); $this->entityTypeManager = $this->container->get('entity_type.manager'); diff --git a/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php b/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php index de0471227..ba046c9c3 100644 --- a/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php +++ b/tests/src/Kernel/Console/DrupalConsoleAddFieldTest.php @@ -38,7 +38,7 @@ public function setUp() { $this->installConfig(['og']); $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); NodeType::create([ 'name' => $this->randomString(), diff --git a/tests/src/Kernel/Entity/EntityCreateAccessTest.php b/tests/src/Kernel/Entity/EntityCreateAccessTest.php index e0d225fd5..25bf9caf5 100644 --- a/tests/src/Kernel/Entity/EntityCreateAccessTest.php +++ b/tests/src/Kernel/Entity/EntityCreateAccessTest.php @@ -60,7 +60,7 @@ public function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); // Create a "group" node type and turn it into a group type. $this->groupType = NodeType::create([ diff --git a/tests/src/Kernel/Entity/GetBundleByBundleTest.php b/tests/src/Kernel/Entity/GetBundleByBundleTest.php index d89e83614..27a6b7cd2 100644 --- a/tests/src/Kernel/Entity/GetBundleByBundleTest.php +++ b/tests/src/Kernel/Entity/GetBundleByBundleTest.php @@ -61,7 +61,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); $this->groupTypeManager = $this->container->get('og.group_type_manager'); diff --git a/tests/src/Kernel/Entity/GetGroupContentTest.php b/tests/src/Kernel/Entity/GetGroupContentTest.php index b35cd0f58..e4f63652a 100644 --- a/tests/src/Kernel/Entity/GetGroupContentTest.php +++ b/tests/src/Kernel/Entity/GetGroupContentTest.php @@ -56,7 +56,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */ $entity_type_manager = $this->container->get('entity_type.manager'); diff --git a/tests/src/Kernel/Entity/GetMembershipsTest.php b/tests/src/Kernel/Entity/GetMembershipsTest.php index 58088897d..0c75604f1 100644 --- a/tests/src/Kernel/Entity/GetMembershipsTest.php +++ b/tests/src/Kernel/Entity/GetMembershipsTest.php @@ -64,7 +64,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); $this->installSchema('user', ['users_data']); $this->entityTypeManager = $this->container->get('entity_type.manager'); diff --git a/tests/src/Kernel/Entity/GetUserGroupsTest.php b/tests/src/Kernel/Entity/GetUserGroupsTest.php index 543c35791..5fcd8f544 100644 --- a/tests/src/Kernel/Entity/GetUserGroupsTest.php +++ b/tests/src/Kernel/Entity/GetUserGroupsTest.php @@ -89,7 +89,7 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('entity_test'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); $this->groupBundle = mb_strtolower($this->randomMachineName()); $this->groupContentBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php index ac5950ae8..b3453ea8f 100644 --- a/tests/src/Kernel/Entity/GroupMembershipManagerTest.php +++ b/tests/src/Kernel/Entity/GroupMembershipManagerTest.php @@ -88,7 +88,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); $this->entityTypeManager = $this->container->get('entity_type.manager'); $this->membershipManager = $this->container->get('og.membership_manager'); diff --git a/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php b/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php index 019c70cdd..66cd39034 100644 --- a/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php +++ b/tests/src/Kernel/Entity/OgMembershipRoleReferenceTest.php @@ -60,7 +60,7 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); // Create a "group" node type and turn it into a group type. $this->groupBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Entity/OgMembershipTest.php b/tests/src/Kernel/Entity/OgMembershipTest.php index e97725faf..c00bbf54c 100644 --- a/tests/src/Kernel/Entity/OgMembershipTest.php +++ b/tests/src/Kernel/Entity/OgMembershipTest.php @@ -74,7 +74,7 @@ protected function setUp() { $this->installEntitySchema('entity_test'); $this->installEntitySchema('node'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); $this->entityTypeManager = $this->container->get('entity_type.manager'); $storage = $this->entityTypeManager->getStorage('user'); diff --git a/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php b/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php index 3ed486df0..4c40a8272 100644 --- a/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php +++ b/tests/src/Kernel/Entity/OgStandardReferenceItemTest.php @@ -42,7 +42,7 @@ protected function setUp() { $this->installEntitySchema('entity_test'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); // Create several bundles. for ($i = 0; $i <= 2; $i++) { diff --git a/tests/src/Kernel/Entity/ReferenceStringIdTest.php b/tests/src/Kernel/Entity/ReferenceStringIdTest.php index 3ea0c4b5e..4c2a8df94 100644 --- a/tests/src/Kernel/Entity/ReferenceStringIdTest.php +++ b/tests/src/Kernel/Entity/ReferenceStringIdTest.php @@ -58,7 +58,7 @@ protected function setUp() { $this->installEntitySchema('entity_test_string_id'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); // Create two bundles, one will serve as group, the other as group content. for ($i = 0; $i < 2; $i++) { diff --git a/tests/src/Kernel/Entity/SelectionHandlerTest.php b/tests/src/Kernel/Entity/SelectionHandlerTest.php index 3673be1d3..1c2a081fe 100644 --- a/tests/src/Kernel/Entity/SelectionHandlerTest.php +++ b/tests/src/Kernel/Entity/SelectionHandlerTest.php @@ -83,7 +83,7 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); // Setting up variables. $this->groupBundle = mb_strtolower($this->randomMachineName()); diff --git a/tests/src/Kernel/Form/GroupSubscribeFormTest.php b/tests/src/Kernel/Form/GroupSubscribeFormTest.php index 5b85cde8e..174e4005f 100644 --- a/tests/src/Kernel/Form/GroupSubscribeFormTest.php +++ b/tests/src/Kernel/Form/GroupSubscribeFormTest.php @@ -70,7 +70,7 @@ protected function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); - $this->installSchema('system', 'sequences'); + $this->installSchema('system', ['sequences']); // Create 3 test bundles and declare them as groups. $bundle_names = []; diff --git a/tests/src/Kernel/OgDeleteOrphansTest.php b/tests/src/Kernel/OgDeleteOrphansTest.php index 0ba6342f6..dcffe86e8 100644 --- a/tests/src/Kernel/OgDeleteOrphansTest.php +++ b/tests/src/Kernel/OgDeleteOrphansTest.php @@ -61,7 +61,7 @@ public function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); - $this->installSchema('node', 'node_access'); + $this->installSchema('node', ['node_access']); $this->installSchema('system', ['queue', 'sequences']); /** @var \Drupal\og\OgDeleteOrphansPluginManager $plugin_manager */ From e39ee62ae4bb33c1725b1effac2810a90482048e Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 26 Nov 2018 14:38:51 +0100 Subject: [PATCH 093/111] Comment name cant be null --- tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php index c3e7ec0e7..fd5cb4659 100644 --- a/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php +++ b/tests/src/Kernel/Access/OgGroupContentOperationAccessTest.php @@ -232,6 +232,7 @@ protected function setUp() { case 'comment': $values = [ + 'field_name' => $this->randomString(), 'subject' => 'subscribe', 'comment_type' => $bundle_id, 'entity_id' => $this->group->id(), From 91c54f1d7bd3482cac52b2028d4f5deaefe6655d Mon Sep 17 00:00:00 2001 From: Insasse Date: Tue, 27 Nov 2018 10:34:08 +0100 Subject: [PATCH 094/111] Remove invalid schema --- tests/src/Kernel/Action/ActionTestBase.php | 2 +- tests/src/Kernel/GroupManagerSubscriptionTest.php | 2 +- tests/src/Kernel/GroupTypeConditionTest.php | 2 +- tests/src/Kernel/OgDeleteOrphansTest.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/src/Kernel/Action/ActionTestBase.php b/tests/src/Kernel/Action/ActionTestBase.php index 1190f71b7..2ecf08f9a 100644 --- a/tests/src/Kernel/Action/ActionTestBase.php +++ b/tests/src/Kernel/Action/ActionTestBase.php @@ -84,7 +84,7 @@ public function setUp() { $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); $this->installEntitySchema('node'); - $this->installSchema('system', ['queue', 'sequences']); + $this->installSchema('system', ['sequences']); $this->membershipManager = $this->container->get('og.membership_manager'); $this->groupTypeManager = $this->container->get('og.group_type_manager'); diff --git a/tests/src/Kernel/GroupManagerSubscriptionTest.php b/tests/src/Kernel/GroupManagerSubscriptionTest.php index 24949d904..efdf4039d 100644 --- a/tests/src/Kernel/GroupManagerSubscriptionTest.php +++ b/tests/src/Kernel/GroupManagerSubscriptionTest.php @@ -64,7 +64,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('og_membership'); $this->installEntitySchema('user'); - $this->installSchema('system', ['queue', 'sequences']); + $this->installSchema('system', ['sequences']); // Create a group type. NodeType::create([ diff --git a/tests/src/Kernel/GroupTypeConditionTest.php b/tests/src/Kernel/GroupTypeConditionTest.php index 8306f394a..7ee4361c6 100644 --- a/tests/src/Kernel/GroupTypeConditionTest.php +++ b/tests/src/Kernel/GroupTypeConditionTest.php @@ -62,7 +62,7 @@ protected function setUp() { $this->installEntitySchema('entity_test'); $this->installEntitySchema('node'); $this->installEntitySchema('user'); - $this->installSchema('system', ['queue', 'sequences']); + $this->installSchema('system', ['sequences']); // Create three test groups of different types. for ($i = 0; $i < 2; $i++) { diff --git a/tests/src/Kernel/OgDeleteOrphansTest.php b/tests/src/Kernel/OgDeleteOrphansTest.php index dcffe86e8..fd80646c2 100644 --- a/tests/src/Kernel/OgDeleteOrphansTest.php +++ b/tests/src/Kernel/OgDeleteOrphansTest.php @@ -62,7 +62,7 @@ public function setUp() { $this->installEntitySchema('user'); $this->installEntitySchema('node'); $this->installSchema('node', ['node_access']); - $this->installSchema('system', ['queue', 'sequences']); + $this->installSchema('system', ['sequences']); /** @var \Drupal\og\OgDeleteOrphansPluginManager $plugin_manager */ $plugin_manager = \Drupal::service('plugin.manager.og.delete_orphans'); From 73ad1885a79eafcfaf87081ac8d49a66705ad2bc Mon Sep 17 00:00:00 2001 From: Insasse Date: Tue, 27 Nov 2018 10:58:58 +0100 Subject: [PATCH 095/111] Add t() to setLabel in og.module:287 --- og.module | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/og.module b/og.module index 4a8fc5769..28da5518f 100755 --- a/og.module +++ b/og.module @@ -280,7 +280,7 @@ function og_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle, $fields = []; $fields['og_group'] = BaseFieldDefinition::create('og_group') - ->setLabel('OG Group') + ->setLabel(t('OG Group')) ->setComputed(TRUE) ->setTranslatable(FALSE) ->setDefaultValue(TRUE) From ffd6d92f6fd99ade54bca48322529615f7fdee57 Mon Sep 17 00:00:00 2001 From: Insasse Date: Thu, 29 Nov 2018 10:26:45 +0100 Subject: [PATCH 096/111] Add missing getGroupMemberships() function --- og.services.yml | 2 +- src/MembershipManager.php | 28 +++++++++++++++++++++++++++- src/MembershipManagerInterface.php | 14 ++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/og.services.yml b/og.services.yml index 4a2c9c3d3..b1d13e80c 100644 --- a/og.services.yml +++ b/og.services.yml @@ -50,7 +50,7 @@ services: arguments: ['@config.factory', '@entity_type.manager', '@entity_type.bundle.info', '@event_dispatcher', '@cache.data', '@og.permission_manager', '@og.role_manager', '@router.builder', '@og.group_audience_helper'] og.membership_manager: class: Drupal\og\MembershipManager - arguments: ['@entity_type.manager', '@og.group_audience_helper'] + arguments: ['@entity_type.manager', '@og.group_audience_helper', '@database'] og.permission_manager: class: Drupal\og\PermissionManager arguments: ['@event_dispatcher'] diff --git a/src/MembershipManager.php b/src/MembershipManager.php index ff1baf17d..3f1244028 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -36,6 +36,13 @@ class MembershipManager implements MembershipManagerInterface { */ protected $groupAudienceHelper; + /** + * The database service. + * + * @var \Drupal\Core\Database\Connection + */ + protected $database; + /** * Constructs a MembershipManager object. * @@ -43,10 +50,13 @@ class MembershipManager implements MembershipManagerInterface { * The entity type manager. * @param \Drupal\og\OgGroupAudienceHelperInterface $group_audience_helper * The OG group audience helper. + * @param \Drupal\Core\Database\Connection $database + * The database service */ - public function __construct(EntityTypeManagerInterface $entity_type_manager, OgGroupAudienceHelperInterface $group_audience_helper) { + public function __construct(EntityTypeManagerInterface $entity_type_manager, OgGroupAudienceHelperInterface $group_audience_helper, Connection $database) { $this->entityTypeManager = $entity_type_manager; $this->groupAudienceHelper = $group_audience_helper; + $this->database = $database; } /** @@ -435,4 +445,20 @@ protected function loadMemberships(array $ids) { ->loadMultiple($ids); } + /** + * {@inheritdoc} + */ + public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]) { + $query = $this->database->select('og_membership', 'ogm') + ->fields('ogm', ['uid']) + ->condition('entity_id', $group->id()); + + if ($states) { + $query->condition('state', $states, 'IN'); + } + $member_ids = $query->execute()->fetchAssoc(); + $members = $this->entityTypeManager->getStorage('user')->loadMultiple($member_ids); + return $members; + } + } diff --git a/src/MembershipManagerInterface.php b/src/MembershipManagerInterface.php index 873c2b8c9..e5f369896 100644 --- a/src/MembershipManagerInterface.php +++ b/src/MembershipManagerInterface.php @@ -291,4 +291,18 @@ public function isMemberBlocked(EntityInterface $group, AccountInterface $user); */ public function reset(); + /** + * Returns all users that are active members of the group. + * + * @param \Drupal\Core\Entity\EntityInterface $group + * The group entity. + * @param array $states + * The member states. + * + * @return array + * Group members + */ + public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]); + + } From a74e06349c112f57fdca2050b287dadbca5cc1b5 Mon Sep 17 00:00:00 2001 From: Insasse Date: Thu, 29 Nov 2018 11:09:44 +0100 Subject: [PATCH 097/111] Add use statement --- src/MembershipManager.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index 3f1244028..152a08c7e 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -2,6 +2,7 @@ namespace Drupal\og; +use Drupal\Core\Database\Connection; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; From 88eb203c95d022d05a34eccee9d3a8702de45e95 Mon Sep 17 00:00:00 2001 From: Insasse Date: Thu, 29 Nov 2018 15:27:05 +0100 Subject: [PATCH 098/111] Use Messeangertrait in GroupUnsubscribeForm --- src/Form/GroupUnsubscribeConfirmForm.php | 28 ++---------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/src/Form/GroupUnsubscribeConfirmForm.php b/src/Form/GroupUnsubscribeConfirmForm.php index 2455d3e79..10767431a 100644 --- a/src/Form/GroupUnsubscribeConfirmForm.php +++ b/src/Form/GroupUnsubscribeConfirmForm.php @@ -4,39 +4,15 @@ use Drupal\Core\Entity\ContentEntityDeleteForm; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Messenger\MessengerTrait; use Drupal\Core\Url; -use Drupal\Core\Messenger\MessengerInterface; /** * Provides a confirmation form for unsubscribing form a group. */ class GroupUnsubscribeConfirmForm extends ContentEntityDeleteForm { - /** - * The messenger. - * - * @var \Drupal\Core\Messenger\MessengerInterface - */ - protected $messenger; - - /** - * Constructs the GroupUnsubscribeConfirmForm object. - * - * @param \Drupal\Core\Messenger\MessengerInterface $messenger - * The messenger. - */ - public function __construct(MessengerInterface $messenger) { - $this->messenger = $messenger; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('messenger') - ); - } + use MessengerTrait; /** * {@inheritdoc} From 373d10a78b8ea7797312a6d41b39b3e347a94ff3 Mon Sep 17 00:00:00 2001 From: Insasse Date: Fri, 30 Nov 2018 08:26:24 +0100 Subject: [PATCH 099/111] FetchAllAssoc getGroupMemberships() --- src/MembershipManager.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index 152a08c7e..326aee79e 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -457,7 +457,8 @@ public function getGroupMemberships(EntityInterface $group, array $states = [OgM if ($states) { $query->condition('state', $states, 'IN'); } - $member_ids = $query->execute()->fetchAssoc(); + $result = $query->execute()->fetchAllAssoc('uid', 'PDO::FETCH_ASSOC'); + $member_ids = array_keys($result); $members = $this->entityTypeManager->getStorage('user')->loadMultiple($member_ids); return $members; } From 7c8c46e9d83958e62009444ccd12433bbcb5e1b3 Mon Sep 17 00:00:00 2001 From: Insasse Date: Fri, 30 Nov 2018 10:19:23 +0100 Subject: [PATCH 100/111] Fix CreateMembershipTest --- tests/src/Unit/CreateMembershipTest.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/src/Unit/CreateMembershipTest.php b/tests/src/Unit/CreateMembershipTest.php index 3a461c003..dd00b211c 100644 --- a/tests/src/Unit/CreateMembershipTest.php +++ b/tests/src/Unit/CreateMembershipTest.php @@ -13,6 +13,7 @@ use Drupal\Tests\UnitTestCase; use Drupal\user\UserInterface; use Prophecy\Argument; +use Drupal\Core\Database\Connection; /** * Tests create membership helper function. @@ -85,6 +86,13 @@ class CreateMembershipTest extends UnitTestCase { */ protected $membership; + /** + * The database service. + * + * @var \Drupal\Core\Database\Connection + */ + protected $database; + /** * {@inheritdoc} */ @@ -98,6 +106,7 @@ public function setUp() { $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class); $this->entityTypeRepository = $this->prophesize(EntityTypeRepositoryInterface::class); $this->groupAudienceHelper = $this->prophesize(OgGroupAudienceHelperInterface::class); + $this->database = $this->prophesize(Connection::class); $this->entityTypeManager->getStorage('og_membership') ->willReturn($this->entityStorage->reveal()); @@ -130,6 +139,7 @@ public function setUp() { $container = new ContainerBuilder(); $container->set('entity_type.manager', $this->entityTypeManager->reveal()); $container->set('entity_type.repository', $this->entityTypeRepository->reveal()); + $container->set('database', $this->database->reveal()); \Drupal::setContainer($container); } @@ -139,7 +149,7 @@ public function setUp() { * @covers ::createMembership */ public function testNewGroup() { - $membership_manager = new MembershipManager($this->entityTypeManager->reveal(), $this->groupAudienceHelper->reveal()); + $membership_manager = new MembershipManager($this->entityTypeManager->reveal(), $this->groupAudienceHelper->reveal(), $this->database->reveal()); $membership = $membership_manager->createMembership($this->group->reveal(), $this->user->reveal()); $this->assertInstanceOf(OgMembershipInterface::class, $membership); } From d6067bc59dac41b8c316cf1c986d51d135b85d82 Mon Sep 17 00:00:00 2001 From: Insasse Date: Fri, 30 Nov 2018 10:33:02 +0100 Subject: [PATCH 101/111] fix code style --- src/MembershipManager.php | 2 +- src/MembershipManagerInterface.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index 326aee79e..1d9887ff5 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -52,7 +52,7 @@ class MembershipManager implements MembershipManagerInterface { * @param \Drupal\og\OgGroupAudienceHelperInterface $group_audience_helper * The OG group audience helper. * @param \Drupal\Core\Database\Connection $database - * The database service + * The database service. */ public function __construct(EntityTypeManagerInterface $entity_type_manager, OgGroupAudienceHelperInterface $group_audience_helper, Connection $database) { $this->entityTypeManager = $entity_type_manager; diff --git a/src/MembershipManagerInterface.php b/src/MembershipManagerInterface.php index e5f369896..84e2cdddc 100644 --- a/src/MembershipManagerInterface.php +++ b/src/MembershipManagerInterface.php @@ -304,5 +304,4 @@ public function reset(); */ public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]); - } From 075675f66be564b8828cb6f8af5e85296d74bb97 Mon Sep 17 00:00:00 2001 From: Insasse Date: Tue, 4 Dec 2018 09:03:30 +0100 Subject: [PATCH 102/111] Provide better DX for getGroupMemberships function --- src/MembershipManager.php | 5 ++++- src/MembershipManagerInterface.php | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index 1d9887ff5..83bfaf6bc 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -449,7 +449,7 @@ protected function loadMemberships(array $ids) { /** * {@inheritdoc} */ - public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]) { + public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE], $range = NULL) { $query = $this->database->select('og_membership', 'ogm') ->fields('ogm', ['uid']) ->condition('entity_id', $group->id()); @@ -457,6 +457,9 @@ public function getGroupMemberships(EntityInterface $group, array $states = [OgM if ($states) { $query->condition('state', $states, 'IN'); } + if ($range) { + $query->range(0, $range); + } $result = $query->execute()->fetchAllAssoc('uid', 'PDO::FETCH_ASSOC'); $member_ids = array_keys($result); $members = $this->entityTypeManager->getStorage('user')->loadMultiple($member_ids); diff --git a/src/MembershipManagerInterface.php b/src/MembershipManagerInterface.php index 84e2cdddc..78d46d70e 100644 --- a/src/MembershipManagerInterface.php +++ b/src/MembershipManagerInterface.php @@ -298,10 +298,12 @@ public function reset(); * The group entity. * @param array $states * The member states. + * @param int $range + * The number of members to get. * * @return array * Group members */ - public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE]); + public function getGroupMemberships(EntityInterface $group, array $states = [OgMembershipInterface::STATE_ACTIVE], $range = NULL); } From 39ab6100bbc70c5f48f95b19a8b7d6a749905046 Mon Sep 17 00:00:00 2001 From: Insasse Date: Wed, 5 Dec 2018 10:11:07 +0100 Subject: [PATCH 103/111] #441 - recommended change by MPParsley --- src/Entity/OgMembershipType.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Entity/OgMembershipType.php b/src/Entity/OgMembershipType.php index ad106a40a..f58d5e8d8 100644 --- a/src/Entity/OgMembershipType.php +++ b/src/Entity/OgMembershipType.php @@ -2,6 +2,7 @@ namespace Drupal\og\Entity; +use Drupal; use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\field\Entity\FieldConfig; use Drupal\og\OgMembershipInterface; @@ -70,6 +71,11 @@ public function id() { public function save() { $status = parent::save(); + if (\Drupal::isConfigSyncing()) { + // Do not create config while config import is in progress. + return; + } + if ($status === SAVED_NEW) { FieldConfig::create([ 'field_name' => 'og_membership_request', From 8c946cda2b1e4e284ccad99262f5aa7c1af7a02f Mon Sep 17 00:00:00 2001 From: Insasse Date: Thu, 6 Dec 2018 10:01:31 +0100 Subject: [PATCH 104/111] Remove unused use statement --- src/Entity/OgMembershipType.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Entity/OgMembershipType.php b/src/Entity/OgMembershipType.php index f58d5e8d8..6ea8e2df6 100644 --- a/src/Entity/OgMembershipType.php +++ b/src/Entity/OgMembershipType.php @@ -2,7 +2,6 @@ namespace Drupal\og\Entity; -use Drupal; use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\field\Entity\FieldConfig; use Drupal\og\OgMembershipInterface; From cadd15daa2398c56d52c8b755f5c7075c9b58e81 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 10 Dec 2018 14:41:02 +0100 Subject: [PATCH 105/111] Fix undefined index --- src/MembershipManager.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/MembershipManager.php b/src/MembershipManager.php index 83bfaf6bc..a8743634e 100644 --- a/src/MembershipManager.php +++ b/src/MembershipManager.php @@ -267,7 +267,9 @@ public function getGroupIds(EntityInterface $entity, $group_type_id = NULL, $gro // Compile a list of group target IDs. $target_ids = array_map(function ($value) { - return $value['target_id']; + if (isset($value['target_id'])) { + return $value['target_id']; + } }, $entity->get($field->getName())->getValue()); if (empty($target_ids)) { From 115a45972f5fc0a568e9f178590d9c908f4fe944 Mon Sep 17 00:00:00 2001 From: Insasse Date: Thu, 3 Jan 2019 09:11:47 +0100 Subject: [PATCH 106/111] Remove redundant use statement --- tests/src/Unit/SubscriptionControllerTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/src/Unit/SubscriptionControllerTest.php b/tests/src/Unit/SubscriptionControllerTest.php index 40b9f6802..36f02cf13 100644 --- a/tests/src/Unit/SubscriptionControllerTest.php +++ b/tests/src/Unit/SubscriptionControllerTest.php @@ -14,7 +14,6 @@ use Drupal\og\OgMembershipInterface; use Drupal\Tests\UnitTestCase; use Drupal\user\EntityOwnerInterface; -use Drupal\Core\Messenger\MessengerInterface; /** * Tests the subscription controller. From 721a25f256bbfad2f7edd1b46e8bda464f4aa508 Mon Sep 17 00:00:00 2001 From: Insasse Date: Thu, 3 Jan 2019 09:14:16 +0100 Subject: [PATCH 107/111] Remove redundant messanger var --- tests/src/Unit/SubscriptionControllerTest.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/src/Unit/SubscriptionControllerTest.php b/tests/src/Unit/SubscriptionControllerTest.php index 36f02cf13..19b69d9e9 100644 --- a/tests/src/Unit/SubscriptionControllerTest.php +++ b/tests/src/Unit/SubscriptionControllerTest.php @@ -79,13 +79,6 @@ class SubscriptionControllerTest extends UnitTestCase { */ protected $user; - /** - * The messenger. - * - * @var \Drupal\Core\Messenger\MessengerInterface - */ - protected $messenger; - /** * {@inheritdoc} */ From 2615039aabb97682406550e3a7c7ee2131668601 Mon Sep 17 00:00:00 2001 From: Insasse Date: Mon, 4 Feb 2019 16:36:37 +0100 Subject: [PATCH 108/111] Fix GroupCheck Fatal on custom routes --- src/Access/GroupCheck.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Access/GroupCheck.php b/src/Access/GroupCheck.php index 002797b84..22f7195b8 100644 --- a/src/Access/GroupCheck.php +++ b/src/Access/GroupCheck.php @@ -83,6 +83,9 @@ public function access(AccountInterface $user, Route $route, RouteMatchInterface if (!$group = $route_match->getParameter($parameter_name)) { return AccessResult::forbidden(); } + if (is_numeric($group)) { + $group = $this->entityTypeManager->getStorage($parameter_name)->load($group); + } $entity_type_id = $group->getEntityTypeId(); } From 92cc901dfec5298e3853d9ea994d6f2f26796ebf Mon Sep 17 00:00:00 2001 From: Insasse Date: Tue, 5 Feb 2019 08:59:15 +0100 Subject: [PATCH 109/111] Fix fatal error --- src/Entity/OgMembershipType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entity/OgMembershipType.php b/src/Entity/OgMembershipType.php index 6ea8e2df6..d20101c58 100644 --- a/src/Entity/OgMembershipType.php +++ b/src/Entity/OgMembershipType.php @@ -95,7 +95,7 @@ public function save() { */ public function delete() { if ($this->id() === OgMembershipInterface::TYPE_DEFAULT) { - throw \Exception("The default OG membership type cannot be deleted."); + throw new \Exception("The default OG membership type cannot be deleted."); } parent::delete(); } From e3bff7a4c7a0c8c98717bd1c2516c1e25e649b16 Mon Sep 17 00:00:00 2001 From: Insasse Date: Tue, 12 Feb 2019 09:07:52 +0100 Subject: [PATCH 110/111] Fix Exception on config import --- src/Entity/OgMembershipType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entity/OgMembershipType.php b/src/Entity/OgMembershipType.php index d20101c58..295c80f2f 100644 --- a/src/Entity/OgMembershipType.php +++ b/src/Entity/OgMembershipType.php @@ -94,7 +94,7 @@ public function save() { * {@inheritdoc} */ public function delete() { - if ($this->id() === OgMembershipInterface::TYPE_DEFAULT) { + if ($this->id() === OgMembershipInterface::TYPE_DEFAULT && !\Drupal::isConfigSyncing()) { throw new \Exception("The default OG membership type cannot be deleted."); } parent::delete(); From 7ec37787b9b1510906bd5feb03758fbeacd999e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20Zu=CC=88rn?= Date: Wed, 4 Sep 2019 14:59:27 +0200 Subject: [PATCH 111/111] #49713 workaround cache problem in phpunittest --- src/GroupTypeManager.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/GroupTypeManager.php b/src/GroupTypeManager.php index 7ed4554ae..5fc6cec1b 100644 --- a/src/GroupTypeManager.php +++ b/src/GroupTypeManager.php @@ -251,6 +251,9 @@ public function getGroupBundleIdsByGroupContentBundle($group_content_entity_type */ public function getGroupContentBundleIdsByGroupBundle($group_entity_type_id, $group_bundle_id) { $group_relation_map = $this->getGroupRelationMap(); + if (!is_array($group_relation_map) && property_exists($group_relation_map,'data')) { + $group_relation_map = $group_relation_map->data; + } return isset($group_relation_map[$group_entity_type_id][$group_bundle_id]) ? $group_relation_map[$group_entity_type_id][$group_bundle_id] : []; }