Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#150 untested - do not merge #151

Open
wants to merge 4 commits into
base: 8.x-1.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion og.module
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ function og_entity_create_access(AccountInterface $account, array $context, $bun
// We can't check if user has create permissions, as there is no group
// context. However, we can check if there are any groups the user will be
// able to select, and if not, we don't allow access.
// @see \Drupal\og\Plugin\EntityReferenceSelection\OgSelection::buildEntityQuery()
// @see \Drupal\og\Plugin\EntityReferenceSelection\OgDefaultSelection::buildEntityQuery()
$required = FALSE;

$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($entity_type_id, $bundle);
Expand Down
28 changes: 24 additions & 4 deletions src/Og.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@

namespace Drupal\og;

use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\og\Plugin\EntityReferenceSelection\OgSelection;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\views\Plugin\EntityReferenceSelection\ViewsSelection;

/**
* A static helper class for OG.
Expand Down Expand Up @@ -444,7 +445,7 @@ protected static function getFieldBaseDefinition($plugin_id) {
* @param array $options
* Overriding the default options of the selection handler.
*
* @return OgSelection
* @return \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface
* @throws \Exception
*/
public static function getSelectionHandler(FieldDefinitionInterface $field_definition, array $options = []) {
Expand All @@ -464,7 +465,26 @@ public static function getSelectionHandler(FieldDefinitionInterface $field_defin
// Deep merge the handler settings.
$options['handler_settings'] = NestedArray::mergeDeep($field_definition->getSetting('handler_settings'), $options['handler_settings']);

return \Drupal::service('plugin.manager.entity_reference_selection')->createInstance('og:default', $options);
// Find our which class we should use.
/* @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface $selection_plugin_manager */
$selection_plugin_manager = \Drupal::service('plugin.manager.entity_reference_selection');
$original_handler = $selection_plugin_manager->getInstance($options);

// See if we have a suitable class for this.
// @todo: Find a better way to do this?
if ($original_handler instanceof DefaultSelection) {
$plugin_id = 'og:default';
}
elseif ($original_handler instanceof ViewsSelection) {
$plugin_id = 'og:views';
}
else {
// @todo: Create our own exception for this?
throw new PluginException(sprintf("OG proxy plugin for plugin ID '%s' was not found.", $original_handler->getPluginId()));
}

// Create and return our proxy selection handler.
return $selection_plugin_manager->createInstance($plugin_id, $options);
}

}
53 changes: 53 additions & 0 deletions src/OgSelectionTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/**
* @file
* Contains \Drupal\og\OgSelectionTrait.
*/

namespace Drupal\og;

use Drupal\user\Entity\User;

/**
* Trait for common methods for OG Selection handlers.
*/
trait OgSelectionTrait {

/**
* The original selection handler for the field.
*
* @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface
*/
protected $selectionHandler;

/**
* Get the selection handler of the field.
*
* @return \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface
*/
public function getSelectionHandler() {
if (!isset($this->selectionHandler)) {
$options = [
'target_type' => $this->configuration['target_type'],
'handler_settings' => $this->configuration['handler_settings'],
];
if (isset($this->configuration['handler_settings']['original_handler'])) {
$options['handler'] = $this->configuration['handler_settings']['original_handler'];
}
$this->selectionHandler = \Drupal::service('plugin.manager.entity_reference_selection')->getInstance($options);
}
return $this->selectionHandler;
}

/**
* Get hold of the groups this user is part of.
*
* @return \Drupal\Core\Entity\ContentEntityInterface[]
*/
protected function getUserGroups() {
$other_groups = Og::getEntityGroups(User::load($this->currentUser->id()));
return isset($other_groups[$this->configuration['target_type']]) ? $other_groups[$this->configuration['target_type']] : [];
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

/**
* @file
* Contains \Drupal\og\Plugin\EntityReferenceSelection\OgSelection.
* Contains \Drupal\og\Plugin\EntityReferenceSelection\OgDefaultSelection.
*/

namespace Drupal\og\Plugin\EntityReferenceSelection;

use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
use Drupal\user\Entity\User;
use Drupal\og\OgSelectionTrait;
use Drupal\og\Og;

/**
* Provide default OG selection handler.
* Provide a proxy OG selection handler for
* \Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection.
*
* Note that the id is correctly defined as "og:default" and not the other way
* around, as seen in most other default selection handler (e.g. "default:node")
Expand All @@ -29,23 +29,9 @@
* weight = 1
* )
*/
class OgSelection extends DefaultSelection {
class OgDefaultSelection extends DefaultSelection {

/**
* Get the selection handler of the field.
*
* @return DefaultSelection
*/
public function getSelectionHandler() {
$options = [
'target_type' => $this->configuration['target_type'],
// 'handler' key intentionally absent as we want the selection manager to
// choose the best option.
// @see \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManager::getInstance()
'handler_settings' => $this->configuration['handler_settings'],
];
return \Drupal::service('plugin.manager.entity_reference_selection')->getInstance($options);
}
use OgSelectionTrait;

/**
* Overrides the basic entity query object. Return only group in the matching
Expand All @@ -67,7 +53,7 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS')
// 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
// bundle defined as group.

$query = $this->getSelectionHandler()->buildEntityQuery($match, $match_operator);
$target_type = $this->configuration['target_type'];
$entityDefinition = \Drupal::entityTypeManager()->getDefinition($target_type);
Expand All @@ -85,21 +71,18 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS')
$identifier_key = $entityDefinition->getKey('id');

$ids = [];
foreach ($user_groups as $delta => $group) {
$ids[] = $group->id();
}

if ($this->configuration['handler_settings']['field_mode'] == 'admin') {
// Don't include the groups, the user doesn't have create permission.
foreach ($user_groups as $delta => $group) {
$ids[] = $group->id();
}

if ($ids) {
$query->condition($identifier_key, $ids, 'NOT IN');
}
}
else {
// Determine which groups should be selectable.
foreach ($user_groups as $group) {
$ids[] = $group->id();
}
if ($ids) {
$query->condition($identifier_key, $ids, 'IN');
}
Expand All @@ -113,13 +96,4 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS')
return $query;
}

/**
*
* @return ContentEntityInterface[]
*/
protected function getUserGroups() {
$other_groups = Og::getEntityGroups(User::load($this->currentUser->id()));
return isset($other_groups[$this->configuration['target_type']]) ? $other_groups[$this->configuration['target_type']] : [];
}

}
79 changes: 79 additions & 0 deletions src/Plugin/EntityReferenceSelection/OgViewsSelection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

/**
* @file
* Contains \Drupal\og\Plugin\EntityReferenceSelection\OgDefaultSelection.
*/

namespace Drupal\og\Plugin\EntityReferenceSelection;

use Drupal\views\Plugin\EntityReferenceSelection\ViewsSelection;
use Drupal\og\OgSelectionTrait;

/**
* Provide a proxy OG selection handler for
* \Drupal\views\Plugin\EntityReferenceSelection\ViewsSelection.
*
* Note that the id is correctly defined as "og:views" and not the other way
* around, as seen in most other default selection handler (e.g. "default:node")
* as OG's selection handler is a wrapper around those entity specific views
* ones. That is, the same selection handler will be returned no matter what is
* the target type of the reference field. Internally, it will call the original
* selection handler, and use it for building the queries.
*
* @EntityReferenceSelection(
* id = "og:views",
* label = @Translation("OG selection"),
* group = "og",
* weight = 1
* )
*/
class OgViewsSelection extends ViewsSelection {

use OgSelectionTrait;

/**
* {@inheritdoc}
*/
protected function initializeView($match = NULL, $match_operator = 'CONTAINS', $limit = 0, $ids = NULL) {
$return = $this->getSelectionHandler()->initializeView($match, $match_operator, $limit, $ids);
$this->view = $this->getSelectionHandler()->view;
if ($return) {
$display = $this->view->getDisplay();

// @todo: Find a way to ensure only group entities are returned.

$user_groups = $this->getUserGroups();
$group_ids = [];
foreach ($user_groups as $delta => $group) {
$group_ids[] = $group->id();
}

if ($user_groups) {
if ($this->configuration['handler_settings']['field_mode'] == 'admin') {
// @todo: Ideally find a way to exclude certain IDs at a query level.
}
else {
// Determine which groups should be selectable.
if ($group_ids) {
$entity_reference_options = $display->getOption('entity_reference_options');
if (isset($entity_reference_options['ids'])) {
$entity_reference_options['ids'] = array_intersect($entity_reference_options['ids'], $group_ids);
}
else {
$entity_reference_options['ids'] = $group_ids;
}
$display->setOption('entity_reference_options', $entity_reference_options);
}
else {
// User doesn't have permission to select any group simply return
// FALSE.
return FALSE;
}
}
}
}
return $return;
}

}
9 changes: 7 additions & 2 deletions src/Plugin/Field/FieldWidget/OgComplex.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,13 @@ class OgComplex extends EntityReferenceAutocompleteWidget {
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$parent = parent::formElement($items, $delta, $element, $form, $form_state);
// todo: fix the definition in th UI level.
$parent['target_id']['#selection_handler'] = 'og:default';
$options = array(
'target_type' => $parent['target_id']['#target_type'],
'handler' => $parent['target_id']['#selection_handler'],
'handler_settings' => $parent['target_id']['#selection_settings'],
);
$parent['target_id']['#selection_settings']['original_handler'] = $parent['target_id']['#selection_handler'];
$parent['target_id']['#selection_handler'] = Og::getSelectionHandler($this->fieldDefinition, $options)->getPluginId();
$parent['target_id']['#selection_settings']['field_mode'] = 'default';

return $parent;
Expand Down
2 changes: 1 addition & 1 deletion tests/src/Kernel/Entity/SelectionHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class SelectionHandlerTest extends KernelTestBase {
/**
* The selection handler.
*
* @var \Drupal\og\Plugin\EntityReferenceSelection\OgSelection.
* @var \Drupal\og\Plugin\EntityReferenceSelection\OgDefaultSelection.
*/
protected $selectionHandler;

Expand Down