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

Commit

Permalink
Fix merge conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
MPParsley committed Sep 28, 2021
2 parents b0394ad + 6494ed3 commit f2dbe9c
Show file tree
Hide file tree
Showing 18 changed files with 1,201 additions and 495 deletions.
4 changes: 0 additions & 4 deletions config/schema/og.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +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'

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 @@ -159,6 +159,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);
}
}

if ($access->isAllowed()) {
return $access;
}
Expand Down Expand Up @@ -196,6 +210,11 @@ function og_og_membership_type_access(OgMembershipTypeInterface $entity, $operat
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;
}

if (!Og::isGroupContent($entity_type_id, $bundle)) {
// Not a group content.
return AccessResult::neutral();
Expand All @@ -221,23 +240,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]));
}

$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);

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 @@ -307,7 +344,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 @@ -322,7 +368,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 @@ -543,6 +543,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 @@ -394,8 +394,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 @@ -412,7 +410,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 @@ -422,18 +420,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
// 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) {
// Check user has "create" permission on this entity.
$permission = "create $bundle content";
if ($this->ogAccess->userAccess($group, $permission, $this->currentUser)->isAllowed()) {
$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;
}

}
6 changes: 3 additions & 3 deletions src/Plugin/Field/FieldType/OgStandardReferenceItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
*
* @FieldType(
* id = "og_standard_reference",
* label = @Translation("OG membership reference"),
* description = @Translation("An entity field containing an OG membership reference for a non-user entity."),
* label = @Translation("OG reference"),
* description = @Translation("An entity reference field containing an OG reference for a non-user entity."),
* category = @Translation("Reference"),
* no_ui = TRUE,
* default_widget = "og_complex",
* default_widget = "options_select",
* default_formatter = "entity_reference_label",
* list_class = "\Drupal\Core\Field\EntityReferenceFieldItemList",
* constraints = {"ValidOgMembershipReference" = {}}
Expand Down
Loading

0 comments on commit f2dbe9c

Please sign in to comment.