Skip to content
This repository has been archived by the owner on Aug 18, 2024. It is now read-only.

160 remove complex widget #570

Merged
merged 215 commits into from
Sep 28, 2021
Merged
Show file tree
Hide file tree
Changes from 205 commits
Commits
Show all changes
215 commits
Select commit Hold shift + click to select a range
a658b0e
Start removing complex widget
amitaibu Sep 15, 2016
bce0c5e
Add core widgets
amitaibu Sep 15, 2016
bad2c09
Allow privileged user to create content
amitaibu Sep 15, 2016
c75b654
Check permissions
amitaibu Sep 15, 2016
d49ac2b
Start fixing tests
amitaibu Sep 15, 2016
1d061ee
Fix logic and tests
amitaibu Sep 15, 2016
d8591fb
Sniffer fixes
amitaibu Sep 15, 2016
97fb566
Fix return value in docs
amitaibu Sep 16, 2016
77eb562
Re-add Functional test
amitaibu Sep 19, 2016
9bb346e
Sniffer fixes
amitaibu Sep 19, 2016
ce13e41
Sniffer fixes
amitaibu Sep 19, 2016
d317614
Merge branch '8.x-1.x' into 160-remove-complex-widget
amitaibu Sep 20, 2016
0e10e5f
Setting up the base for the new test.
Sep 30, 2016
793715e
Commit more work.
Sep 30, 2016
3d4013f
First version of the tests.
Sep 30, 2016
9c4858b
Make code sniffer happy.
Sep 30, 2016
5346d09
Merge 8.x-1.x
amitaibu Oct 4, 2016
1551922
Remove un-needed method
amitaibu Oct 4, 2016
3f69920
Remove unused statement
amitaibu Oct 4, 2016
ca3bc5d
Start expanding the widget tests
amitaibu Oct 15, 2016
3e3c90d
Create node types
amitaibu Oct 15, 2016
78a427e
Comments cleanup
amitaibu Oct 15, 2016
11f4bd2
Remove traits
amitaibu Oct 15, 2016
8c94013
Try to find cause of bug
amitaibu Oct 15, 2016
e98354c
Remove unusued code
amitaibu Oct 15, 2016
1508540
Remove custom settings
amitaibu Oct 15, 2016
afd3f71
Remove unused use
amitaibu Oct 15, 2016
586e677
Add todo
amitaibu Oct 15, 2016
c5fdf87
Filter out the bundles that are not groups.
amitaibu Oct 15, 2016
328c913
Fix indentation
amitaibu Oct 15, 2016
68a9abd
Improve exception error
amitaibu Oct 15, 2016
a117c7b
Improve names
amitaibu Oct 15, 2016
0940d99
Remove unusued code
amitaibu Oct 15, 2016
521b508
Remove custom settings
amitaibu Oct 15, 2016
ef4af0d
Filter out the bundles that are not groups.
amitaibu Oct 15, 2016
d5d34d6
Fix indentation
amitaibu Oct 15, 2016
7334e9c
Sniffer fixes
amitaibu Oct 18, 2016
9ac5241
Convert test to Functional
amitaibu Oct 18, 2016
71e903a
Add comment
amitaibu Oct 18, 2016
00525d9
Debug failing tests
amitaibu Oct 18, 2016
a60a300
Revert debug
amitaibu Oct 18, 2016
cb75f16
Fix wrong node type name
amitaibu Oct 18, 2016
f7b0d29
Simplify and debug test
amitaibu Oct 18, 2016
43f8acd
Add status 200
amitaibu Oct 18, 2016
cf30f3a
gst
amitaibu Oct 18, 2016
94db0c1
Quicker debugs
amitaibu Oct 18, 2016
a2bdbab
Check 404 page
amitaibu Oct 18, 2016
e0c2655
Rebuild routes
amitaibu Oct 18, 2016
ba47934
Fields page
amitaibu Oct 18, 2016
4d65046
click link
amitaibu Oct 18, 2016
2104177
Back to drupalGet
amitaibu Oct 18, 2016
4f47cc0
Check access
amitaibu Oct 18, 2016
a988745
Enable field ui
amitaibu Oct 18, 2016
470e6ef
Allow debug
amitaibu Oct 18, 2016
5c939ec
Import URL
amitaibu Oct 18, 2016
0fcf95e
Debug user access
amitaibu Oct 18, 2016
81f1b28
Cleanup
amitaibu Oct 18, 2016
f33eb3d
Admin user
amitaibu Oct 18, 2016
7762e4f
Back to permissions
amitaibu Oct 18, 2016
3a1929b
Remove use
amitaibu Oct 19, 2016
8f241b2
Permissions
amitaibu Oct 19, 2016
1b18142
Core test
amitaibu Oct 19, 2016
1d5b92d
Run core
amitaibu Oct 19, 2016
ef4d2db
Debug core
amitaibu Oct 19, 2016
8dc9aa1
Remove core debug
amitaibu Oct 19, 2016
d817fc4
Start conveting test to Kernel
amitaibu Oct 19, 2016
d64af00
More work
amitaibu Oct 19, 2016
e2e82b9
Use entity test with bundle
amitaibu Oct 19, 2016
ee625d3
Merge field settings
amitaibu Oct 19, 2016
2fdf2bd
Fix test
amitaibu Oct 19, 2016
a21eb83
Sniffer fixes
amitaibu Oct 19, 2016
85849ae
Remove debug
amitaibu Oct 19, 2016
a1cc01e
Create Node type correctly
amitaibu Oct 19, 2016
7a18d5c
Add unpublished node
amitaibu Oct 19, 2016
780b54a
Fix OgSelectionWidgetTest
amitaibu Oct 19, 2016
352551d
Validate that the user have access to post a group content.
Nov 25, 2016
7fafaef
Adding skeleton for a test [skip ci]
Nov 26, 2016
093324c
Commit work [skip ci]
Nov 26, 2016
8aa95f5
Fix a typo and continue working on the test [skip ci]
Nov 27, 2016
24a1221
Set the role properly [skip ci]
Dec 3, 2016
6bdaa20
Use forbidden and not allowed.
Apr 6, 2017
b174e23
Checkin when forbidden.
Apr 8, 2017
4bb4819
Somehow fix the tests.
Apr 9, 2017
0741340
Getting the root entity.
Apr 11, 2017
ae94377
Merge branch '8.x-1.x' into 160-remove-complex-widget
Apr 11, 2017
12838fb
Merge branch '8.x-1.x' into 160-remove-complex-widget
Apr 11, 2017
8ab5433
Fix conflict
Apr 12, 2017
55b3fcf
Stbalize tests.
Apr 12, 2017
a2271be
Minor refactor.
Apr 12, 2017
7744bc3
Wrong operator.
Apr 12, 2017
9f96bc4
Trying to understand what’s the difference [skip ci]
Apr 13, 2017
7ecdedd
Find another solution.
Apr 13, 2017
86dee21
Adding basic constraint to add entities [skip ci]
Apr 20, 2017
f20e279
Commit logic for now.
Apr 20, 2017
3134064
Don’t add constant to all the entities, just check the field.
Apr 20, 2017
8abc283
Fix tests.
Apr 21, 2017
8c7cadb
Remove the testin file
Sep 26, 2017
564682f
Fix name.
Sep 27, 2017
a2d92a2
Fix cs
Sep 27, 2017
74e677d
Get the text.
Sep 27, 2017
2c5af11
Maybe now?
Sep 28, 2017
df17662
Catching and not version.
Sep 28, 2017
779efee
CS fix.
Sep 28, 2017
1450634
Handle another case for the fields.
Sep 28, 2017
961eb7d
Set the field as required in specific cases.
Sep 29, 2017
0e030db
More changes.
Sep 29, 2017
15debda
Adding the validation.
Sep 30, 2017
f43add7
The validation works as expected. Now, we need to write tests.
Sep 30, 2017
2257ece
More improvements.
Sep 30, 2017
35b019f
Adding the boilerplate for the new test.
Sep 30, 2017
12cc927
Done with the tests.
Sep 30, 2017
365da2f
Minor fixes.
Oct 4, 2017
f3894cd
Make CS happy.
Oct 4, 2017
16ff320
make cs happy.
Oct 4, 2017
b7e2d5e
Merge remote-tracking branch 'origin/8.x-1.x' into 160-remove-complex…
pfrenssen Jul 3, 2018
b7ac85b
Fix grammar in comments.
mariano-dagostino Jul 3, 2018
3493f91
Improve comment of access check logic
mariano-dagostino Jul 3, 2018
3439183
GroupTypeManager::getAllGroupBundles should respect GroupTypeManagerI…
mariano-dagostino Jul 3, 2018
fd83a5d
Merge branch '8.x-1.x' into 160-remove-complex-widget
RoySegall Jul 8, 2018
c304aea
Use single quotes
MPParsley May 12, 2019
0625119
Undo single quotes
MPParsley May 12, 2019
5fa4b7a
Improve readability foreach
MPParsley May 12, 2019
352ba22
Updated documentation for the entity reference field
MPParsley May 12, 2019
57dfc44
Use invalidMessage from constraint
MPParsley May 12, 2019
fab2fe6
Added dependency injection to ValidOgMembershipMultipleReferenceConst…
MPParsley May 12, 2019
3d3365a
Merge remote-tracking branch 'gizra/8.x-1.x' into 160-remove-complex-…
pfrenssen May 12, 2019
2faaad5
Fix tests
MPParsley May 12, 2019
214f5cd
Fixed unnecessarily gendered language in a comment
MPParsley May 12, 2019
9c94943
Cleanup call to MembershipManager::reset()
MPParsley May 12, 2019
84a85fc
Protected properties should start with a small cap
MPParsley May 12, 2019
c194f0e
Protected properties should start with a small cap.
MPParsley May 12, 2019
e5b3b60
Update src/Plugin/Validation/Constraint/ValidOgMembershipMultipleRefe…
MPParsley May 12, 2019
fde09bc
Revert commit
MPParsley May 12, 2019
86301b0
Deprecate Drupal\simpletest\ContentTypeCreationTrait
MPParsley May 12, 2019
5622d85
Deprecated Drupal\simpletest\NodeCreationTrait
MPParsley May 12, 2019
85d87ae
Fixed namespaces
MPParsley May 12, 2019
e9e2152
Removed deprecated call to Drupal::entityManager
MPParsley May 12, 2019
991ea33
Removed deprecated entity.query service
MPParsley May 12, 2019
d6ceee6
Removed calls to deprecated entityManager
MPParsley May 12, 2019
7e58f33
Use EntityTypeManagerInterface
MPParsley May 12, 2019
ffd5afe
Remove call to deprecated entity.manager
MPParsley May 12, 2019
412f880
Fixed EntityManager deprecations in OgSelection
MPParsley May 12, 2019
aa82d18
Fixed call to undefined function getBundleInfo() on EntityTypeManager
MPParsley May 12, 2019
34ffca4
Added getQuery
MPParsley May 12, 2019
bdc92db
Clear membership cache
MPParsley May 12, 2019
417d548
Restore cache reset
MPParsley May 12, 2019
0f87dbe
Test with cache delete.
MPParsley May 12, 2019
c980ace
Cleanup test
MPParsley May 12, 2019
38a25a7
Fixed indentation
MPParsley May 13, 2019
d0b227f
Added missing use statement
MPParsley May 13, 2019
6f6a733
Fix tests
MPParsley May 13, 2019
fd95fdb
Revert permission format
MPParsley May 20, 2019
0439c0e
Revert permission format
MPParsley May 20, 2019
eff1923
Revert permission format
MPParsley May 20, 2019
40f677f
Merge branch '8.x-1.x' into 160-remove-complex-widget
damienmckenna Jul 24, 2019
0e7bec1
Merge pull request #569 from damienmckenna/160-remove-complex-widget
MPParsley Sep 10, 2019
037c38f
Remove unused use statement
MPParsley Sep 10, 2019
7bda98a
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
damienmckenna Dec 9, 2019
cdde6cd
Merge pull request #595 from damienmckenna/feature/160-remove-complex…
pfrenssen Dec 10, 2019
bd428c6
Fix codesniffer errors
MPParsley Dec 10, 2019
5db820b
Removed redundant getGroupBundlesByEntityType() method.
damienmckenna Dec 10, 2019
97623d4
Typoo.
damienmckenna Dec 10, 2019
c6559a7
Merge pull request #596 from damienmckenna/feature/570-getGroupBundle…
MPParsley Dec 10, 2019
6630f00
Revert "Removed redundant getGroupBundlesByEntityType() method."
MPParsley Dec 12, 2019
7b8245a
Merge pull request #597 from Gizra/revert-596-feature/570-getGroupBun…
MPParsley Dec 12, 2019
0076fba
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Feb 6, 2020
8a35d7a
Fix merge conflict
MPParsley Feb 9, 2020
1ba32f8
Removed unused variables
MPParsley Feb 9, 2020
68cd03e
Update og.module
MPParsley Feb 9, 2020
fa93ef0
Test without admin field_mode
MPParsley Feb 9, 2020
58caa78
Test with deprecated Og::getSelectionHandler
MPParsley Feb 9, 2020
29cc980
fix merge conflict
MPParsley Feb 10, 2020
492825a
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Feb 17, 2020
9884218
Merge pull request #636 from Gizra/8.x-1.x
MPParsley Mar 25, 2020
6409300
undo remove whitespace
MPParsley Mar 26, 2020
72fb63d
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Jul 4, 2020
f8cbf12
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Jul 20, 2020
e3fd886
Fix deprecation
MPParsley Jul 20, 2020
7c591a4
Renamed permission
MPParsley Jul 20, 2020
79519fc
Remove deprecated method reset()
MPParsley Jul 20, 2020
6236767
Deprecate handler_settings
MPParsley Jul 20, 2020
e1ce4b0
Remove deprecated call to Og::getSelectionHandler
MPParsley Jul 20, 2020
61967f9
Fix undefined index target_bundles
MPParsley Jul 20, 2020
f270eb2
Remove deprecated call to Og::getSelectionHandler
MPParsley Jul 20, 2020
b4be10f
Revert Og::getSelectionHandler
MPParsley Jul 20, 2020
9cc2202
Apply suggestions from code review
MPParsley Jul 27, 2020
1ea6272
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Aug 3, 2020
e90010b
Split up OgAccess::userAccessEntity
MPParsley Aug 3, 2020
1e8d004
Fix order of parameters
MPParsley Aug 3, 2020
17f9b08
Fix syntax error
MPParsley Aug 3, 2020
f87e4e5
Added period.
MPParsley Aug 3, 2020
9b2aaae
Inject services
MPParsley Aug 3, 2020
79931c4
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Aug 4, 2020
e4f9334
Revert injection of OgAccess
MPParsley Aug 4, 2020
a0c1e6d
Revert injection of current user
MPParsley Aug 4, 2020
3926543
Remove hack for Drupal 8.4
MPParsley Aug 5, 2020
146c778
Revert dependency injections
MPParsley Aug 5, 2020
748e78d
Revert hack for ValidReferenceConstraintValidator
MPParsley Aug 5, 2020
0bd6cc1
Inject services.
Aug 5, 2020
e80f686
Fix tests
Aug 5, 2020
5a5995a
Test deprecation of Og:getSelectionHandler
MPParsley Aug 5, 2020
d32da0b
Use existing method getGroupBundleIdsByEntityType
MPParsley Aug 10, 2020
7c3ce1b
Revert getAllGroupBundles
MPParsley Aug 10, 2020
16aad07
Remove getGroupBundlesByEntityType
MPParsley Aug 10, 2020
fc73c8e
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Aug 10, 2020
75e3def
Revert deprecation
MPParsley Aug 10, 2020
5d95ec6
Revert deprecation
MPParsley Aug 10, 2020
528025d
Fix strict types
MPParsley Aug 10, 2020
2b43dec
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Aug 13, 2020
6951d09
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Jan 7, 2021
753e719
Merge branch '8.x-1.x'
MPParsley Jan 19, 2021
f1adcc7
Apply suggestions from code review
MPParsley Jan 19, 2021
1bb4998
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Apr 20, 2021
437bb31
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Apr 22, 2021
6494ed3
Merge branch '8.x-1.x' into feature/160-remove-complex-widget
MPParsley Jul 13, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions config/schema/og.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,6 @@ og.og_role.*:
type: string
label: 'Role type'

field.widget.settings.og_complex:
type: field.widget.settings.entity_reference_autocomplete
label: 'OG Group Audience field widget'
mapping:
# This already exists in field.widget.settings.entity_reference_autocomplete
# in Drupal 8.8.x and is added here just to ensure backwards compatibility
# with Drupal 8.7.x.
# @todo Remove this entry in https://github.com/Gizra/og/issues/581
# @see https://github.com/Gizra/og/issues/581
match_limit:
type: integer
label: 'Maximum number of autocomplete suggestions.'

views.field.og_membership_bulk_form:
type: views_field_bulk_form
label: 'OG Membership bulk form'
Expand Down
70 changes: 65 additions & 5 deletions og.module
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,20 @@ function og_entity_access(EntityInterface $entity, $operation, AccountInterface
/** @var \Drupal\Core\Access\AccessResult $access */
$access = \Drupal::service('og.access')->userAccessEntityOperation($operation, $entity, $account);

$audience_fields = \Drupal::service('og.group_audience_helper')->getAllGroupAudienceFields($entity_type_id, $bundle_id);
if (count($audience_fields) === 1) {
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($entity_type_id, $bundle_id);
foreach ($field_definitions as $field_definition) {
/** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */
if (!in_array($field_definition->getName(), array_keys($audience_fields))) {
continue;
}

// Check if the field needs to be required.
$field_definition->setRequired($access);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MPParsley this one is related to https://github.com/Gizra/og/pull/570/files#r377001979

We try to make sure that if a node must be created inside an OG context, it cannot be created without choosing a group. Again not sure about the correctness of code - but rather on the reason.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this code is not working. This is calling FieldConfigInterface::setRequired() but never calling FieldConfigInterface::save() after making the change so this code is basically doing nothing.

We should not alter field definitions in hook_entity_access() in any case.

}
}

if ($access->isAllowed()) {
return $access;
}
Expand All @@ -178,6 +192,11 @@ function og_entity_access(EntityInterface $entity, $operation, AccountInterface
function og_entity_create_access(AccountInterface $account, array $context, $bundle) {
$entity_type_id = $context['entity_type_id'];

if (!empty($context['skip_og_permission'])) {
// We've already been here or we want to skip the access check.
return;
}
Comment on lines +195 to +198
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary? This seems brittle to me and a potential security problem. We should not allow to skip access checks unless there is a very good reason for it.

Copy link
Member

@amitaibu amitaibu Feb 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about the correctness of the code here - but I remember the reason though. When you create a node, it still doesn't belong to a group. It might belong, but if for example the audience field is optional, than that node could be a "global" one (i.e. does not belong to a group).

So we need to check if that node could be created outside of OG context. If it can, then we don't have the final say.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this is intended to avoid an endless loop, because this is calling itself again later on.

This approach feels very strange to me. The code below calls the access check, passing exactly the same parameters, from inside the access check? What information could this possibly be retrieving that we don't already have at this point.


if (!Og::isGroupContent($entity_type_id, $bundle)) {
// Not a group content.
return AccessResult::neutral();
Expand All @@ -203,23 +222,41 @@ function og_entity_create_access(AccountInterface $account, array $context, $bun
// @see \Drupal\og\Plugin\EntityReferenceSelection\OgSelection::buildEntityQuery()
$required = FALSE;

/** @var \Drupal\og\OgGroupAudienceHelperInterface $audience_helper */
$audience_helper = \Drupal::service('og.group_audience_helper');
$audience_fields = $audience_helper->getAllGroupAudienceFields($entity_type_id, $bundle);
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($entity_type_id, $bundle);
foreach ($field_definitions as $field_definition) {
/** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */
if (!\Drupal::service('og.group_audience_helper')->isGroupAudienceField($field_definition)) {
if (!in_array($field_definition->getName(), array_keys($audience_fields))) {
continue;
}

if (count($audience_fields) === 1) {
// Set the field to required only if we have a single audience field.
// If we have multiple fields then the require logic will perform at the
// entity constraint level.
$field_definition->setRequired(!\Drupal::entityTypeManager()
->getAccessControlHandler($entity_type_id)
->createAccess($bundle, $account, ['skip_og_permission' => TRUE]));
}
Comment on lines +235 to +242
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we again setting fields to be required inside an access hook? This doesn't belong here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should investigate a different solution, this is a hack. We should not alter any field definitions in hook_entity_access().

It looks like this field definition is used as temporary storage for what could be a simple $is_required flag.


$options = [
'target_type' => $field_definition->getFieldStorageDefinition()->getSetting('target_type'),
'handler' => $field_definition->getSetting('handler'),
'field_mode' => 'admin',
];
/** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManager $handler */
$handler = \Drupal::service('plugin.manager.entity_reference_selection');
$handler = $handler->getInstance($options);

// @todo Remove deprecated call to Og::getSelectionHandler.
// $handler = Og::getSelectionHandler($field_definition);
MPParsley marked this conversation as resolved.
Show resolved Hide resolved

if ($handler->getInstance($options)) {
return AccessResult::neutral();
if ($handler && $handler->countReferenceableEntities()) {
// At least one of the fields has referenceable groups. That mean that
// the user can create group content when referencing the group content in
// at least one of the fields.
return AccessResult::allowed();
}
// Allow users to create content outside of groups, if none of the
// audience fields is required.
Expand Down Expand Up @@ -289,7 +326,16 @@ function og_field_formatter_info_alter(array &$info) {
* Implements hook_field_widget_info_alter().
*/
function og_field_widget_info_alter(array &$info) {
$info['options_buttons']['field_types'][] = OgGroupAudienceHelperInterface::GROUP_REFERENCE;
$field_types = [
'entity_reference_autocomplete',
'entity_reference_autocomplete_tags',
'options_buttons',
'options_select',
];

foreach ($field_types as $field_type) {
$info[$field_type]['field_types'][] = OgGroupAudienceHelperInterface::GROUP_REFERENCE;
}
}

/**
Expand All @@ -304,7 +350,21 @@ function og_field_widget_info_alter(array &$info) {
function og_entity_type_alter(array &$entity_types) {
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
foreach ($entity_types as $entity_type_id => $entity_type) {

// Add link template to groups. We add it to all the entity types, and later
// on return the correct access, depending if the bundle is indeed a group
// and accessible. We do not filter here the entity type by groups, so
// whenever GroupTypeManager::addGroup is called, it's enough to mark route
// to be rebuilt via RouteBuilder::setRebuildNeeded.
$entity_type->setLinkTemplate('og-admin-routes', "/group/$entity_type_id/{{$entity_type_id}}/admin");

// We won't check if an entity might be group content because we need to
// check if that entity has any bundle that could be a group entity and this
// would cause a recursion. The constraint will check there if the entity is
// group content or not.
if ($entity_type->entityClassImplements(ContentEntityInterface::class)) {
$entity_type->addConstraint('ValidOgMembershipMultipleReference');
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/Entity/OgMembership.php
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,8 @@ public function preSave(EntityStorageInterface $storage) {
}
}

$uid = $this->get('uid')->target_id;

// Check for an existing membership.
$query = \Drupal::entityQuery('og_membership');
$query
Expand Down
23 changes: 14 additions & 9 deletions src/Og.php
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,6 @@ protected static function getFieldBaseDefinition($plugin_id) {
*
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The field definition.
* @param array $options
* Overriding the default options of the selection handler.
*
* @return \Drupal\og\Plugin\EntityReferenceSelection\OgSelection
* Returns the OG selection handler.
Expand All @@ -395,7 +393,7 @@ protected static function getFieldBaseDefinition($plugin_id) {
* @see https://github.com/Gizra/og/issues/580
* @codingStandardsIgnoreEnd
*/
public static function getSelectionHandler(FieldDefinitionInterface $field_definition, array $options = []) {
public static function getSelectionHandler(FieldDefinitionInterface $field_definition) {
// @codingStandardsIgnoreStart
@trigger_error('Og:getSelectionHandler() is deprecated in og:8.x-1.0-alpha4
and is removed from og:8.x-1.0-alpha5.
Expand All @@ -405,18 +403,25 @@ public static function getSelectionHandler(FieldDefinitionInterface $field_defin
// @codingStandardsIgnoreEnd
if (!\Drupal::service('og.group_audience_helper')->isGroupAudienceField($field_definition)) {
$field_name = $field_definition->getName();
throw new \Exception("The field $field_name is not an audience field.");
throw new \Exception("The field $field_name is not a group audience field.");
}

$default_options = [
$entity_type_id = $field_definition->getTargetEntityTypeId();
$definition = \Drupal::entityTypeManager()->getDefinition($entity_type_id);

$values = [];
if ($bundle_key = $definition->getKey('bundle')) {
$values[$bundle_key] = $field_definition->getTargetBundle();
}

$entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->create($values);

$options = [
'target_type' => $field_definition->getFieldStorageDefinition()->getSetting('target_type'),
'handler' => $field_definition->getSetting('handler'),
'field_mode' => 'default',
'entity' => $entity,
] + $field_definition->getSetting('handler_settings');

// Override with passed $options.
$options = NestedArray::mergeDeep($default_options, $options);

return \Drupal::service('plugin.manager.entity_reference_selection')->createInstance('og:default', $options);
}

Expand Down
150 changes: 128 additions & 22 deletions src/Plugin/EntityReferenceSelection/OgSelection.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,18 @@

namespace Drupal\og\Plugin\EntityReferenceSelection;

use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
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\og\OgAccessInterface;
use Drupal\og\Og;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Provide default OG selection handler.
Expand All @@ -26,6 +36,71 @@
*/
class OgSelection extends DefaultSelection {

/**
* The OG access service.
*
* @var \Drupal\og\OgAccessInterface
*/
protected $ogAccess;

/**
* The OG membership manager.
*
* @var \Drupal\og\MembershipManagerInterface
*/
protected $ogMembershipManager;

/**
* Constructs a new SelectionBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity manager service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
* The entity field manager.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
* The entity type bundle info service.
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
* The entity repository.
* @param \Drupal\og\OgAccessInterface $og_access
* The OG access service.
* @param \Drupal\og\MembershipManagerInterface $og_membership_manager
* The OG membership service.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user, EntityFieldManagerInterface $entity_field_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityRepositoryInterface $entity_repository, OgAccessInterface $og_access, MembershipManagerInterface $og_membership_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $module_handler, $current_user, $entity_field_manager, $entity_type_bundle_info, $entity_repository);
$this->ogAccess = $og_access;
$this->ogMembershipManager = $og_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_type.manager'),
$container->get('module_handler'),
$container->get('current_user'),
$container->get('entity_field.manager'),
$container->get('entity_type.bundle.info'),
$container->get('entity.repository'),
$container->get('og.access'),
$container->get('og.membership_manager')
);
}

/**
* Get the selection handler of the field.
*
Expand Down Expand Up @@ -62,7 +137,6 @@ public function getSelectionHandler() {
* it.
*/
protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {

// Getting the original entity selection handler. OG selection handler using
// the default selection handler of the entity, which the field reference
// to, and add another logic to the query object i.e. check if the entities
Expand All @@ -81,37 +155,45 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS')
$query->condition($bundle_key, $bundles, 'IN');
}

$user_groups = $this->getUserGroups();
if (!$user_groups) {
// Get the identifier key of the entity.
$identifier_key = $definition->getKey('id');

if ($this->currentUser->isAnonymous()) {
// @todo: Check if anonymous users should have access to any referenced
MPParsley marked this conversation as resolved.
Show resolved Hide resolved
// groups? What about groups that allow anonymous posts?
return $query->condition($identifier_key, -1);
}

if ($this->currentUser->hasPermission('administer organic groups')) {
// User can see all the groups.
return $query;
}

$identifier_key = $definition->getKey('id');
if (empty($this->configuration['entity'])) {
// @todo Find out why we have this scenario.
return $query;
}

/** @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = $this->configuration['entity'];
$bundle = $entity->bundle();

$ids = [];
if (!empty($this->getConfiguration()['field_mode']) && $this->getConfiguration()['field_mode'] === 'admin') {
// Don't include the groups, the user doesn't have create permission.
foreach ($user_groups as $group) {
foreach ($this->getUserGroups() as $group) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Check user has "create" permission on this entity.
$permission = "create $bundle content";
if ($this->ogAccess->userAccess($group, $permission, $this->currentUser)->isAllowed()) {
Comment on lines +183 to +185
Copy link
Collaborator Author

@MPParsley MPParsley Aug 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Check user has "create" permission on this entity.
$permission = "create $bundle content";
if ($this->ogAccess->userAccess($group, $permission, $this->currentUser)->isAllowed()) {
// Check if the current user can perform the "create" operation on this entity.
if ($this->ogAccess->userAccessGroupContentEntityOperation('create', $group, $entity, $this->currentUser)) {

$ids[] = $group->id();
}
}

if ($ids) {
$query->condition($identifier_key, $ids, 'NOT IN');
}
if ($ids) {
$query->condition($identifier_key, $ids, 'IN');
}
else {
// Determine which groups should be selectable.
foreach ($user_groups as $group) {
$ids[] = $group->id();
}
if ($ids) {
$query->condition($identifier_key, $ids, 'IN');
}
else {
// User doesn't have permission to select any group so falsify this
// query.
$query->condition($identifier_key, -1, '=');
}
// User doesn't have permission to select any group so falsify this
// query.
$query->condition($identifier_key, -1);
}

return $query;
Expand All @@ -130,4 +212,28 @@ protected function getUserGroups() {
return isset($other_groups[$this->configuration['target_type']]) ? $other_groups[$this->configuration['target_type']] : [];
}

/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);

// Filter out the bundles that are not groups.
$entity_type_id = $this->configuration['target_type'];
$entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
$bundles_info = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id);

if ($entity_type->hasKey('bundle')) {
$bundles = Og::groupTypeManager()->getGroupBundleIdsByEntityType($entity_type_id);
foreach ($bundles as $bundle) {
$bundle_options[$bundle] = $bundles_info[$bundle]['label'];
}

natsort($bundle_options);
$form['target_bundles']['#options'] = $bundle_options;
}

return $form;
}

}
Loading