View source
<?php
namespace Drupal\social_group\Plugin\Field\FieldWidget;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Extension\ModuleHandler;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsSelectWidget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\group\Entity\Group;
use Drupal\group\Plugin\GroupContentEnablerManager;
use Drupal\user\Entity\User;
use Symfony\Component\DependencyInjection\ContainerInterface;
class SocialGroupSelectorWidget extends OptionsSelectWidget implements ContainerFactoryPluginInterface {
protected $configFactory;
protected $moduleHander;
protected $currentUser;
protected $pluginManager;
protected $entityTypeManager;
protected $userManager;
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, ConfigFactoryInterface $configFactory, AccountProxyInterface $currentUser, ModuleHandler $moduleHandler, GroupContentEnablerManager $pluginManager, EntityTypeManagerInterface $entity_type_manager) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->configFactory = $configFactory;
$this->moduleHander = $moduleHandler;
$this->currentUser = $currentUser;
$this->pluginManager = $pluginManager;
$this->entityTypeManager = $entity_type_manager;
$this->userManager = $entity_type_manager
->getStorage('user');
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container
->get('config.factory'), $container
->get('current_user'), $container
->get('module_handler'), $container
->get('plugin.manager.group_content_enabler'), $container
->get('entity_type.manager'));
}
protected function getOptions(FieldableEntityInterface $entity) {
if (!isset($this->options)) {
if ($entity
->getEntityTypeId() !== 'node') {
return parent::getOptions($entity);
}
$entity_type = $entity
->bundle();
$account = $this->userManager
->load($this->currentUser
->id());
if (!$account
->hasPermission('administer nodes') && !$account
->hasPermission('manage all groups')) {
$account = $entity
->getOwner();
}
$options = $this->fieldDefinition
->getFieldStorageDefinition()
->getOptionsProvider($this->column, $entity)
->getSettableOptions($account);
foreach ($options as $key => $optgroup) {
if (is_array($optgroup)) {
foreach ($optgroup as $gid => $title) {
if ($group = Group::load($gid)) {
$plugin_ids = $this->pluginManager
->getInstalledIds($group
->getGroupType());
if (!in_array('group_node:' . $entity_type, $plugin_ids)) {
unset($options[$key]);
}
}
break;
}
}
}
if (!$account
->hasPermission('manage all groups')) {
$options = $this
->removeGroupsWithoutCreateAccess($options, $account, $entity);
}
if ($empty_label = $this
->getEmptyLabel()) {
$options = [
'_none' => $empty_label,
] + $options;
}
$module_handler = $this->moduleHander;
$context = [
'fieldDefinition' => $this->fieldDefinition,
'entity' => $entity,
];
$module_handler
->alter('options_list', $options, $context);
array_walk_recursive($options, [
$this,
'sanitizeLabel',
]);
$this->options = $options;
}
return $this->options;
}
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$element = parent::formElement($items, $delta, $element, $form, $form_state);
$element['#suffix'] = '<div id="group-selection-result"></div>';
$element['#ajax'] = [
'callback' => __CLASS__ . '::validateGroupSelection',
'effect' => 'fade',
'event' => 'change',
];
$default_visibility = $this->configFactory
->get('entity_access_by_field.settings')
->get('default_visibility');
$form['default_visibility'] = [
'#type' => 'value',
'#value' => $default_visibility,
];
$change_group_node = $this->configFactory
->get('social_group.settings')
->get('allow_group_selection_in_node');
$entity = $form_state
->getFormObject()
->getEntity();
if (!$entity
->id()) {
$current_group = _social_group_get_current_group();
if (!empty($current_group) && empty($element['#default_value'])) {
$element['#default_value'] = [
$current_group
->id(),
];
}
}
else {
if (!$change_group_node && !$this->currentUser
->hasPermission('manage all groups')) {
$element['#disabled'] = TRUE;
$element['#description'] = t('Moving content after creation function has been disabled. In order to move this content, please contact a site manager.');
}
}
return $element;
}
public static function validateGroupSelection(array $form, FormStateInterface $form_state) {
$ajax_response = new AjaxResponse();
$entity = $form_state
->getFormObject()
->getEntity();
$selected_visibility = $form_state
->getValue('field_content_visibility');
if (!empty($selected_visibility)) {
$selected_visibility = $selected_visibility['0']['value'];
}
if ($selected_groups = $form_state
->getValue('groups')) {
foreach ($selected_groups as $selected_group_key => $selected_group) {
$gid = $selected_group['target_id'];
$group = Group::load($gid);
$group_type_id = $group
->getGroupType()
->id();
$allowed_visibility_options = social_group_get_allowed_visibility_options_per_group_type($group_type_id, NULL, $entity, $group);
break;
}
}
else {
$default_visibility = $form_state
->getValue('default_visibility');
$allowed_visibility_options = social_group_get_allowed_visibility_options_per_group_type(NULL, NULL, $entity);
$ajax_response
->addCommand(new InvokeCommand('#edit-field-content-visibility-' . $default_visibility, 'prop', [
'checked',
'checked',
]));
}
foreach ($allowed_visibility_options as $visibility => $allowed) {
$ajax_response
->addCommand(new InvokeCommand('#edit-field-content-visibility-' . $visibility, 'addClass', [
'js--animate-enabled-form-control',
]));
if ($allowed === TRUE) {
$ajax_response
->addCommand(new InvokeCommand('#edit-field-content-visibility-' . $visibility, 'removeAttr', [
'disabled',
]));
if (empty($default_visibility) || $visibility === $default_visibility) {
$ajax_response
->addCommand(new InvokeCommand('#edit-field-content-visibility-' . $visibility, 'prop', [
'checked',
'checked',
]));
}
}
else {
if ($selected_visibility && $selected_visibility === $visibility) {
$ajax_response
->addCommand(new InvokeCommand('#edit-field-content-visibility-' . $visibility, 'removeAttr', [
'checked',
]));
}
$ajax_response
->addCommand(new InvokeCommand('#edit-field-content-visibility-' . $visibility, 'prop', [
'disabled',
'disabled',
]));
}
$ajax_response
->addCommand(new InvokeCommand('#edit-field-content-visibility-' . $visibility, 'change'));
}
$text = t('Changing the group may have impact on the <strong>visibility settings</strong> and may cause <strong>author/co-authors</strong> to lose access.');
drupal_set_message($text, 'info');
$alert = [
'#type' => 'status_messages',
];
$ajax_response
->addCommand(new HtmlCommand('#group-selection-result', $alert));
return $ajax_response;
}
private function removeGroupsWithoutCreateAccess(array $options, User $account, EntityInterface $entity) {
foreach ($options as $option_category_key => $groups_in_category) {
if (is_array($groups_in_category)) {
foreach ($groups_in_category as $gid => $group_title) {
if (!$this
->checkGroupContentCreateAccess($gid, $account, $entity)) {
unset($options[$option_category_key][$gid]);
}
}
if (empty($options[$option_category_key])) {
unset($options[$option_category_key]);
}
}
else {
if (!$this
->checkGroupContentCreateAccess($option_category_key, $account, $entity)) {
unset($options[$option_category_key]);
}
}
}
return $options;
}
private function checkGroupContentCreateAccess($gid, User $account, EntityInterface $entity) {
$group = Group::load($gid);
if ($group
->hasPermission('create group_' . $entity
->getEntityTypeId() . ':' . $entity
->bundle() . ' entity', $account)) {
if ($group
->getGroupType()
->id() === 'public_group') {
$config = $this->configFactory
->get('entity_access_by_field.settings');
if ($config
->get('disable_public_visibility') === 1 && !$account
->hasPermission('override disabled public visibility')) {
return FALSE;
}
}
return TRUE;
}
return FALSE;
}
}