social_group_flexible_group.module in Open Social 10.1.x
Same filename and directory in other branches
- 8.9 modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.module
- 8.6 modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.module
- 8.7 modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.module
- 8.8 modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.module
- 10.3.x modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.module
- 10.0.x modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.module
- 10.2.x modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.module
The Social Group Flexible Group module.
File
modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.moduleView source
<?php
/**
* @file
* The Social Group Flexible Group module.
*/
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\block\Entity\Block;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\group\Entity\Group;
use Drupal\group\Entity\GroupInterface;
use Drupal\social_group_flexible_group\FlexibleGroupContentVisibilityUpdate;
use Drupal\views\Plugin\views\query\QueryPluginBase;
use Drupal\views\Plugin\views\row\EntityRow;
use Drupal\views\ViewExecutable;
use Drupal\views\Views;
/**
* Provide a method to alter array of group types used in open social.
*
* @param array $social_group_types
* List of group types used in open social.
*
* @ingroup social_group_api
*/
function social_group_flexible_group_social_group_types_alter(array &$social_group_types) {
$social_group_types[] = 'flexible_group';
}
/**
* Implements hook_views_data_alter().
*/
function social_group_flexible_group_views_data_alter(array &$data) {
$data['node_access']['flexible_group_node_access'] = [
'title' => t('Filter nodes, with visibility group, placed in group you are not a member of.'),
'filter' => [
'title' => t('Filter nodes, with visibility group, placed in group you are not a member of.'),
'help' => t('Filter nodes, with visibility group, placed in group you are not a member of.'),
'id' => 'flexible_group_node_access',
],
];
}
/**
* Implements hook_form_FORM_ID_form_alter().
*/
function social_group_flexible_group_form_group_flexible_group_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Lets remove group type from flexible group.
// Editing is useless since the options are all in there.
if ($form['group_type']['#disabled']) {
// Remove all the options.
// @see social_group_form_alter().
unset($form['group_type']);
unset($form['#fieldgroups']['group_settings']->children['group_type']);
unset($form['#group_children']['group_type']);
}
$form['field_flexible_group_visibility']['#prefix'] = t('Altering the visibility options could result in changes in access for content within this group and the group itself.');
$form['actions']['submit']['#submit'][] = '_social_flexible_group_edit_submit';
}
/**
* Implements hook_form_alter().
*/
function social_group_flexible_group_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Exposed Filter block on the all-groups overview and search.
if ($form['#id'] === 'views-exposed-form-newest-groups-page-all-groups' || $form['#id'] === 'views-exposed-form-search-groups-page-no-value' || $form['#id'] === 'views-exposed-form-search-groups-page') {
// Update filter values so it matches the join methods in the popover.
if (!empty($form['field_group_allowed_join_method'])) {
if (array_key_exists('added', $form['field_group_allowed_join_method']['#options'])) {
$form['field_group_allowed_join_method']['#options']['added'] = t('Invite only');
}
if (array_key_exists('direct', $form['field_group_allowed_join_method']['#options'])) {
$form['field_group_allowed_join_method']['#options']['direct'] = t('Open to join');
}
if (array_key_exists('request', $form['field_group_allowed_join_method']['#options'])) {
$form['field_group_allowed_join_method']['#options']['request'] = t('Request to join');
}
}
// Add states so this is only available when flexible groups is checked.
// Could be hidden when only flexible groups is enabled, so check that.
// @todo remove this once everything is migrated to flexible groups.
if (!empty($form['field_group_allowed_join_method']) && !empty($form['type']['#options']) && $form['type']['#type'] !== 'hidden') {
$form['field_group_allowed_join_method']['#states'] = [
'visible' => [
':input[name="type"]' => [
'value' => 'flexible_group',
],
],
];
}
}
// For adding or editing a flexible group, we alter the visibility fields.
if ($form['#id'] === 'group-flexible-group-add-form' || $form['#id'] === 'group-flexible-group-edit-form') {
// Change the group visibility on flexible groups.
if (!empty($form['field_group_allowed_visibility'])) {
if (!empty($form['field_group_allowed_visibility']['widget']['#title'])) {
$form['field_group_allowed_visibility']['widget']['#title'] = t('Group content visibility options');
}
if (!empty($form['field_group_allowed_visibility']['widget']['#description'])) {
$form['field_group_allowed_visibility']['widget']['#description'] = t('Choose the visibility options allowed for the group content.');
}
// When referencing select lists and radio buttons in remote conditions,
// a 'value' condition must be used.
$form['field_group_allowed_visibility']['#states'] = [
'visible' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'public',
],
[
'value' => 'community',
],
[
'value' => 'members',
],
],
],
];
}
// Change the allowed join method on flexible groups.
if (!empty($form['field_group_allowed_join_method'])) {
// First we reorder the elmements, if invite only is part of it
// we always want to show this last.
if (!empty($form['field_group_allowed_join_method']['widget']['#options'])) {
if (array_key_exists('added', $form['field_group_allowed_join_method']['widget']['#options'])) {
$option = $form['field_group_allowed_join_method']['widget']['#options']['added'];
// Unset it.
unset($form['field_group_allowed_join_method']['widget']['#options']['added']);
// Add it at the end.
$form['field_group_allowed_join_method']['widget']['#options']['added'] = $option;
}
}
if (!empty($form['field_group_allowed_join_method']['widget']['#title'])) {
$form['field_group_allowed_join_method']['widget']['#title'] = t('Join methods');
}
if (!empty($form['field_group_allowed_join_method']['widget']['#description'])) {
$form['field_group_allowed_join_method']['widget']['#description'] = t('How can people join this group. Group managers can always add members directly, regardless of the chosen join method.');
}
// When referencing select lists and radio buttons in remote conditions,
// a 'value' condition must be used.
$form['field_group_allowed_join_method']['#states'] = [
'visible' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'public',
],
[
'value' => 'community',
],
[
'value' => 'members',
],
],
],
];
}
// Only when adding a flexible group, we need to predefine the
// content visibility and join method based on the group visibility.
if ($form['#id'] === 'group-flexible-group-add-form') {
// Reset default_values on the add form only.
// So we can use state management to check / select.
if (!empty($form['field_group_allowed_join_method']['widget']['#default_value'])) {
$form['field_group_allowed_join_method']['widget']['#default_value'] = [];
}
if (!empty($form['field_group_allowed_visibility']['widget']['#default_value'])) {
$form['field_group_allowed_visibility']['widget']['#default_value'] = [];
}
}
// On the edit form, if there is no value set for the group_visibility
// it means it was an already existing flexible group and we need to add a
// default value so people can save it.
if ($form['#id'] === 'group-flexible-group-edit-form' && empty($form['field_flexible_group_visibility']['widget']['#default_value'])) {
// The default is always community because we used to only have closed
// groups (which is visible for the community) or public if the
// content visibility has public as an option.
$form['field_flexible_group_visibility']['widget']['#default_value'] = 'community';
if (in_array('public', $form['field_group_allowed_visibility']['widget']['#default_value'])) {
$form['field_flexible_group_visibility']['widget']['#default_value'] = 'public';
}
}
// Disable type field if there are no terms added in 'Group type' vocab.
// Also, check for settings by SM for enabling this field.
$group_type_settings = \Drupal::config('social_group.settings')
->get('social_group_type_required');
if ($group_type_settings && isset($form['field_group_type']) && !empty(\Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->loadTree('group_type'))) {
$form['field_group_type']['widget']['#required'] = TRUE;
// Unset the group type label for none.
if (isset($form['field_group_type']['widget']['#options']['_none'])) {
unset($form['field_group_type']['widget']['#options']['_none']);
}
}
else {
$form['field_group_type']['#access'] = FALSE;
}
$form['#after_build'][] = 'social_group_flexible_group_flexible_group_add_after_build';
$form['#attached']['library'][] = 'social_group_flexible_group/admin';
}
}
/**
* After_build function for the flexible group add form to add default states.
*
* @param array $form
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*
* @return mixed
* The form array containing the default values & states.
*/
function social_group_flexible_group_flexible_group_add_after_build(array $form, FormStateInterface $form_state) {
$group_types = [
'flexible_group',
];
\Drupal::moduleHandler()
->alter('social_group_settings', $group_types);
foreach ($group_types as $group_type) {
$form_ids[] = 'group-' . str_replace('_', '-', $group_type) . '-add-form';
}
// Add states for content visibility based on group visibility.
// Only on the add page. On edit we want users to be able to consciously
// decide what allowed visibility to select.
if (in_array($form['#id'], $form_ids ?? []) && isset($form['field_flexible_group_visibility']['widget']['#options'], $form['field_group_allowed_visibility']['widget']['#options'])) {
// If group visibility is public. All content visibility is selected.
$form['field_group_allowed_visibility']['widget']['public']['#states'] = [
'checked' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'public',
],
],
],
'unchecked' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'community',
],
[
'value' => 'members',
],
],
],
];
// If group visibility is community. Communit & Group members are selected.
$form['field_group_allowed_visibility']['widget']['community']['#states'] = [
'checked' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'public',
],
[
'value' => 'community',
],
],
],
'unchecked' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'members',
],
],
],
];
// If group visibility is group. Only group members are selected.
$form['field_group_allowed_visibility']['widget']['group']['#states'] = [
'checked' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'public',
],
[
'value' => 'community',
],
[
'value' => 'members',
],
],
],
];
}
// Add states for join method based on group visibility.
// We do this for add and edit, we want to make sure if users make the
// decision to choose to only show a group to it's Members, the
// join method is selected to Invite only. Because there is no way
// for users to join or request to join in that case.
if (isset($form['field_flexible_group_visibility']['widget']['#options'], $form['field_group_allowed_join_method']['widget']['#options'])) {
// If group visibility is members. Select invite-only.
if (!empty($form['field_group_allowed_join_method']['widget']['added'])) {
$form['field_group_allowed_join_method']['widget']['added']['#states'] = [
'checked' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'members',
],
],
],
];
}
// If group visibility is members. Disable and uncheck open to join.
if (!empty($form['field_group_allowed_join_method']['widget']['direct'])) {
$form['field_group_allowed_join_method']['widget']['direct']['#states'] = [
'disabled' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'members',
],
],
],
'unchecked' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'members',
],
],
],
];
}
// If group visibility is members. Disable and uncheck open to join.
if (!empty($form['field_group_allowed_join_method']['widget']['request'])) {
$form['field_group_allowed_join_method']['widget']['request']['#states'] = [
'disabled' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'members',
],
],
],
'unchecked' => [
':input[name="field_flexible_group_visibility"]' => [
[
'value' => 'members',
],
],
],
];
}
}
return $form;
}
/**
* Implements hook_ENTITY_TYPE_access().
*/
function social_group_flexible_group_group_access(EntityInterface $entity, $operation, AccountInterface $account) {
$result = AccessResult::neutral();
// Write custom access checks based on the new group visibility field.
// If group visibility doesn't exist we can skip this.
/** @var \Drupal\group\Entity\GroupInterface $entity */
if ($operation !== 'view' || !$entity
->hasField('field_flexible_group_visibility')) {
return $result;
}
// If user has administer groups access we can skip this.
if ($account
->hasPermission('manage all groups')) {
return $result;
}
// If group visibility value doesn't exist we can skip.
if (empty($entity
->getFieldValue('field_flexible_group_visibility', 'value'))) {
return $result;
}
// If group visibility exists and public is selected, we can skip.
$group_visibility = $entity
->getFieldValue('field_flexible_group_visibility', 'value');
if ($group_visibility === 'public') {
return $result;
}
// If group visibility exists and community or members is selected, check
// if user is logged.
if ($group_visibility === 'community') {
return AccessResult::forbiddenIf($account
->isAnonymous())
->cachePerUser()
->addCacheableDependency($entity);
}
// If group visibility exists and members only is selected, we need to check
// if user is logged in and is a member of the group.
if ($group_visibility === 'members') {
$not_a_member = !$entity
->getMember($account) || $account
->isAnonymous();
return AccessResult::forbiddenIf($not_a_member)
->cachePerPermissions()
->cachePerUser()
->addCacheableDependency($entity)
->addCacheableDependency($account);
}
return $result;
}
/**
* Implements template_preprocess_form_element().
*/
function social_group_flexible_group_preprocess_form_element(&$variables) {
// Make sure our flexible group visibility field renders icons in the radio
// labels. We add a new property to the form element label render array.
// This is used in FormElementLabel.php to add data for templating.
if (!isset($variables['element']['#type'])) {
return;
}
if ($variables['element']['#type'] === 'radio' && !empty($variables['name']) && $variables['name'] === 'field_flexible_group_visibility') {
$variables['label']['#render_icon'] = TRUE;
$variables['attributes']['class'][] = 'inline-item';
}
if ($variables['element']['#type'] === 'checkbox' && !empty($variables['name']) && strpos($variables['name'], 'field_group_allowed_visibility') !== FALSE) {
$variables['label']['#render_icon'] = TRUE;
$variables['attributes']['class'][] = 'inline-item';
}
}
/**
* Implements template_preprocess_form_element().
*/
function social_group_flexible_group_preprocess_fieldset(&$variables) {
// Make sure our flexible group visibility field renders a tooltip, since
// this field is rendered as fieldset with legend and radios as children
// we need to do it in this preprocess.
$element = $variables['element'];
if (!empty($element['#field_name'])) {
if ($element['#field_name'] === 'field_flexible_group_visibility') {
$description = '';
foreach ($element['#options'] as $key => $label) {
$description .= social_group_group_visibility_description($key);
}
// Render a specific tooltip based on a field name and description.
// This is done in the fieldset, next to the <legend>.
$variables['popover'] = social_group_render_tooltip('field_flexible_group_visibility', t('Group Visibility'), $description);
}
if ($element['#field_name'] === 'field_group_allowed_visibility') {
$description = '';
foreach ($element['#options'] as $key => $label) {
$description .= social_group_allowed_visibility_description($key);
}
// Render a specific tooltip based on a field name and description.
// This is done in the fieldset, next to the <legend>.
$variables['popover'] = social_group_render_tooltip('field_group_allowed_visibility', t('Group content visibility'), $description);
}
if ($element['#field_name'] === 'field_group_allowed_join_method') {
$description = '';
foreach ($element['#options'] as $key => $label) {
$description .= social_group_allowed_join_method_description($key);
}
// Render a specific tooltip based on a field name and description.
// This is done in the fieldset, next to the <legend>.
$variables['popover'] = social_group_render_tooltip('field_group_allowed_join_method', t('Join methods'), $description);
}
}
}
/**
* Custom form submit handler for editing a flexible group.
*
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* Form state.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
function _social_flexible_group_edit_submit(array $form, FormStateInterface $form_state) {
// Check if the visibility changed.
$default_visibility = $form['field_group_allowed_visibility']['widget']['#default_value'];
$new_visibility = $form_state
->getValue('field_group_allowed_visibility');
$changed_visibility = [];
// If there was a visibility that we don't have anymore after editting
// all the content that was inside the group with this visibility
// will get the lowest visibility that is still checked.
foreach ($default_visibility as $key => $option) {
if (array_search($option, array_column($new_visibility, 'value')) === FALSE) {
$changed_visibility[] = $option;
}
}
// So there is now a visibility setting we don't support anymore
// after editing. Make sure we update all the content that has this
// to the next best optin.
if (!empty($changed_visibility)) {
$group = _social_group_get_current_group();
if ($group instanceof GroupInterface) {
// Update the default visibility of all the content.
FlexibleGroupContentVisibilityUpdate::batchUpdateGroupContentVisibility($group, $changed_visibility, $new_visibility);
// Make sure we clear cache tags accordingly.
$cache_tags = _social_group_cache_tags($group);
foreach ($cache_tags as $cache_tag) {
Cache::invalidateTags([
$cache_tag,
]);
}
}
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function social_group_flexible_group_form_social_group_add_alter(&$form, FormStateInterface $form_state, $form_id) {
// Rearrange all the options so flexible is last
// we will need the space for the configuration.
$type_options = $form['group_settings']['group_type']['#options'];
if (!empty($type_options['flexible_group'])) {
$flexible = $type_options['flexible_group'];
unset($form['group_settings']['group_type']['#options']['flexible_group']);
$form['group_settings']['group_type']['#options']['flexible_group'] = $flexible;
}
}
/**
* Check if a user can join the group directly.
*
* @param \Drupal\group\Entity\GroupInterface $group
* The group we are checking.
*
* @return bool
* TRUE when users can join.
*/
function social_group_flexible_group_can_join_directly(GroupInterface $group) {
$join_methods = $group
->get('field_group_allowed_join_method')
->getValue();
if (!in_array('direct', array_column($join_methods, 'value'), FALSE)) {
return FALSE;
}
return TRUE;
}
/**
* Check if a user can be added to a group.
*
* @param \Drupal\group\Entity\Group $group
* The group we are checking.
*
* @return bool
* TRUE when users can join.
*/
function social_group_flexible_group_can_be_added(Group $group) {
$join_methods = $group
->get('field_group_allowed_join_method')
->getValue();
if (!in_array('added', array_column($join_methods, 'value'), FALSE)) {
return FALSE;
}
return TRUE;
}
/**
* Check if public is enabled as visibility options.
*
* @param \Drupal\group\Entity\GroupInterface $group
* The group we are checking.
*
* @return bool
* TRUE when users can join.
*/
function social_group_flexible_group_public_enabled(GroupInterface $group) {
$visibility_options = $group
->get('field_group_allowed_visibility')
->getValue();
if (!in_array('public', array_column($visibility_options, 'value'), FALSE)) {
return FALSE;
}
return TRUE;
}
/**
* Check if community is enabled as visibility options.
*
* @param \Drupal\group\Entity\GroupInterface $group
* The group we are checking.
*
* @return bool
* TRUE when users can join.
*/
function social_group_flexible_group_community_enabled(GroupInterface $group) {
$visibility_options = $group
->get('field_group_allowed_visibility')
->getValue();
if (!in_array('community', array_column($visibility_options, 'value'), FALSE)) {
return FALSE;
}
return TRUE;
}
/**
* Check if members is enabled as visibility options.
*
* @param \Drupal\group\Entity\Group $group
* The group we are checking.
*
* @return bool
* TRUE when users can join.
*/
function social_group_flexible_group_members_enabled(Group $group) {
$visibility_options = $group
->get('field_group_allowed_visibility')
->getValue();
if (!in_array('group', array_column($visibility_options, 'value'), FALSE)) {
return FALSE;
}
return TRUE;
}
/**
* Implements hook_menu_local_actions_alter().
*/
function social_group_flexible_group_menu_local_actions_alter(&$local_actions) {
$group = _social_group_get_current_group();
$user = \Drupal::currentUser();
// Remove the social_group add member action on the
// membership overview if we can't add members directly.
// SM+ can still add members though.
if ($group instanceof GroupInterface && $group
->getGroupType()
->id() === 'flexible_group' && !social_group_flexible_group_can_be_added($group) && !$user
->hasPermission('manage all groups') && !$group
->hasPermission('administer members', $user)) {
unset($local_actions['social_group.add_member']);
}
}
/**
* Determine whether a user can see flexible groups as outsider.
*
* @param \Drupal\group\Entity\Group $group
* The group we are checking.
* @param \Drupal\Core\Session\AccountInterface $account
* The user to check for.
*
* @return bool
* Whether the user is allowed to view this flexible groups.
*/
function social_group_flexible_group_can_view_flexible_groups(Group $group, AccountInterface $account) : bool {
// Users who can manage all can manage everything.
if ($account
->hasPermission('manage all groups')) {
return TRUE;
}
// If User is a member it can see it.
if ($group
->getMember($account) !== FALSE) {
return TRUE;
}
// Outsiders can only see groups that have
// public / community enabled as visibility.
if ($account
->isAuthenticated() && !social_group_flexible_group_community_enabled($group) && !social_group_flexible_group_public_enabled($group)) {
return FALSE;
}
return TRUE;
}
/**
* Implements hook_views_query_alter().
*
* Hide flexible groups everywhere when the current user cant see it.
*/
function social_group_flexible_group_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
if (empty($view->rowPlugin) || !$view->rowPlugin instanceof EntityRow || $view->rowPlugin
->getEntityTypeId() !== 'group') {
return;
}
$account = \Drupal::currentUser();
if (!$account
->isAnonymous()) {
// Don't trigger page cache, this will cache it for AN
// but with LU data.
// Dynamic page cache handles this.
\Drupal::service('page_cache_kill_switch')
->trigger();
}
// Don't check, they can see it all.
if ($account
->hasPermission('manage all groups')) {
return;
}
// Let's build our join with the allowed visibility data.
$configuration = [
'type' => 'LEFT',
'table' => 'group__field_flexible_group_visibility',
'field' => 'entity_id',
'left_table' => 'groups_field_data',
'left_field' => 'id',
'operator' => '=',
];
$alias = 'groups_field_flexible_group_visibility';
/** @var \Drupal\views\Plugin\views\query\Sql $query */
$join = Views::pluginManager('join')
->createInstance('standard', $configuration);
$rel = $query
->addRelationship($alias, $join, 'groups_field_data');
$query
->addTable('group__field_flexible_group_visibility', $rel, $join, $alias);
/** @var \Drupal\views\Plugin\views\query\Sql $query */
$current_where = count($query->where);
// Make sure we add one new group with a where clause.
$new_where = $current_where + 1;
// We need to add our group by using a query tag.
// Otherwise views doesn't accept it.
$query
->addTag('flexible_group_by');
// Get all LU groups.
$my_groups = \Drupal::service('social_group.helper_service')
->getAllGroupsForUser($account
->id());
// Get all hidden groups.
$hidden_groups = \Drupal::entityTypeManager()
->getStorage('group')
->loadByProperties([
'field_flexible_group_visibility' => 'members',
]);
// Get all hidden groups that the current user is not a member of
// and remove them from showing in the view.
$ids = array_diff(array_keys($hidden_groups), $my_groups);
if ($ids) {
// Anonymous user should only see 'public' groups.
if ($account
->isAnonymous()) {
$community_groups = \Drupal::entityTypeManager()
->getStorage('group')
->loadByProperties([
'field_flexible_group_visibility' => 'community',
]);
$ids = array_merge($ids, array_keys($community_groups));
// Add context so for AN it will have a different cache.
$view->element['#cache']['contexts'][] = 'user.roles:anonymous';
}
$query
->addWhere($new_where, 'groups_field_data.id', $ids, 'NOT IN');
}
// Make sure this block gets refreshed for a user if the group membership
// changed for this user.
$view->element['#cache']['contexts'][] = 'user';
$view->element['#cache']['tags'][] = 'group_content_list:plugin:group_membership:entity:' . $account
->id();
}
/**
* Implements hook_query_TAG_alter().
*/
function social_group_flexible_group_query_flexible_group_by_alter(AlterableInterface $query) {
$query
->distinct();
}
/**
* Implements hook_block_access().
*/
function social_group_flexible_group_block_access(Block $block, $operation, AccountInterface $account) {
// This is a list of the blocks that this function cares about, if we're being
// called for a different block we exit early.
$block_id = $block
->getPluginId();
$managed_blocks = [
'views_exposed_filter_block:newest_groups-page_all_groups',
'views_block:groups-block_user_groups',
'views_block:upcoming_events-upcoming_events_group',
'views_block:latest_topics-group_topics_block',
'views_block:group_managers-block_list_managers',
];
// We don't care for other blocks.
if (!in_array($block_id, $managed_blocks, FALSE)) {
return AccessResult::neutral();
}
$group = _social_group_get_current_group();
// We don't care about other group types in here.
if ($group && $group
->getGroupType()
->id() === 'flexible_group') {
// Only when users cant join directly, add the managers block
// so they know who to contact.
if ($operation === 'view' && social_group_flexible_group_can_join_directly($group) && $block
->getPluginId() === 'views_block:group_managers-block_list_managers') {
return AccessResult::forbidden();
}
// All users with permissions can see the rest.
if ($account
->hasPermission('manage all groups')) {
return AccessResult::neutral();
}
if (!$group
->getMember($account) && !social_group_flexible_group_community_enabled($group) && !social_group_flexible_group_public_enabled($group)) {
// If it is flexible and the current user is not an member of this group,
// and content visibility is not public and also not community
// hide it.
$forbidden_blocks = [
'views_block:upcoming_events-upcoming_events_group',
'views_block:latest_topics-group_topics_block',
];
foreach ($forbidden_blocks as $forbidden_block) {
if ($operation === 'view' && $block
->getPluginId() === $forbidden_block) {
return AccessResult::forbidden();
}
}
}
}
return AccessResult::neutral();
}
/**
* Sets dynamic allowed values for the group type icon field.
*/
function social_group_flexible_group_type_allowed_values_function(FieldStorageConfig $definition, ContentEntityInterface $entity = NULL, $cacheable) {
$theme_path = drupal_get_path('theme', 'socialbase');
$icon_files = \Drupal::service('file_system')
->scanDirectory(DRUPAL_ROOT . '/' . $theme_path . '/components/06-libraries/icons/source', '/^icon-.*\\.svg$/', [
'recurse' => FALSE,
]);
$options = [];
foreach ($icon_files as $file) {
$options[$file->name] = $file->name;
}
return $options;
}
/**
* Sets the default value for the group type icon field.
*/
function social_group_flexible_group_type_default_value_function(ContentEntityInterface $entity, FieldDefinitionInterface $definition) {
return [
[
'value' => 'icon-event',
],
];
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function social_group_flexible_group_form_taxonomy_term_group_type_form_alter(&$form, FormStateInterface $form_state, $form_id) {
if (!isset($form['field_group_type_icon'])) {
return;
}
$form['#attached']['library'][] = 'social_group_flexible_group/admin';
$default_icon = $form['field_group_type_icon']['widget']['#default_value'][0];
$form['field_group_type_icon']['preview'] = [
'#type' => 'inline_template',
'#template' => '<div class="icon-svg-wrapper" data-href="#' . $default_icon . '"><svg class="selected-svg"><use xlink:href="#' . $default_icon . '"></use></svg>{{ svg_icons|raw }}</div>',
'#context' => [
'svg_icons' => file_get_contents(drupal_get_path('theme', 'socialbase') . '/assets/icons/icons.svg'),
],
];
$form['field_group_type_icon']['widget']['#ajax'] = [
'callback' => '_social_group_flexible_group_type_change_topic_icon_ajax',
'event' => 'change',
];
}
/**
* Ajax callback to change group type icon.
*/
function _social_group_flexible_group_type_change_topic_icon_ajax(array $form, FormStateInterface $form_state) {
$response = new AjaxResponse();
$icon = $form_state
->getValue('field_group_type_icon')[0]['value'];
$replaced = [
'#type' => 'inline_template',
'#template' => '<div class="icon-svg-wrapper" data-href="#' . $icon . '"><svg class="selected-svg"><use xlink:href="#' . $icon . '"></use></svg>{{ svg_icons|raw }}</div>',
'#context' => [
'svg_icons' => file_get_contents(drupal_get_path('theme', 'socialbase') . '/assets/icons/icons.svg'),
],
];
$response
->addCommand(new ReplaceCommand('.icon-svg-wrapper', $replaced));
return $response;
}