social_core.module in Open Social 10.0.x
Same filename and directory in other branches
- 8.9 modules/social_features/social_core/social_core.module
- 8 modules/social_features/social_core/social_core.module
- 8.2 modules/social_features/social_core/social_core.module
- 8.3 modules/social_features/social_core/social_core.module
- 8.4 modules/social_features/social_core/social_core.module
- 8.5 modules/social_features/social_core/social_core.module
- 8.6 modules/social_features/social_core/social_core.module
- 8.7 modules/social_features/social_core/social_core.module
- 8.8 modules/social_features/social_core/social_core.module
- 10.3.x modules/social_features/social_core/social_core.module
- 10.1.x modules/social_features/social_core/social_core.module
- 10.2.x modules/social_features/social_core/social_core.module
The Social core module.
File
modules/social_features/social_core/social_core.moduleView source
<?php
/**
* @file
* The Social core module.
*/
use Drupal\block\Entity\Block;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\file\Entity\File;
use Drupal\filter\FilterFormatInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Url;
use Drupal\filter\Entity\FilterFormat;
use Drupal\group\Entity\Group;
use Drupal\image\Entity\ImageStyle;
use Drupal\node\NodeInterface;
use Drupal\path\Plugin\Field\FieldWidget\PathWidget;
use Drupal\user\Entity\User;
use Drupal\user\UserInterface;
/**
* Implements hook_page_attachments().
*/
function social_core_page_attachments(array &$attachments) {
// Unconditionally attach library to the page.
$attachments['#attached']['library'][] = 'social_core/accessibility';
}
/**
* Implements hook_theme().
*/
function social_core_theme() {
return [
// @deprecated: use node--hero.html.twig instead.
'page_hero_data' => [
'variables' => [
'title' => NULL,
'hero_node' => NULL,
'node' => NULL,
'node_type' => NULL,
'section_class' => NULL,
'event_enrollment' => NULL,
'hero_styled_image_url' => NULL,
],
],
];
}
/**
* Implements hook_modules_installed().
*/
function social_core_modules_installed($modules) {
// If either social_group_flexible_group or social_landing_page gets enabled
// and the other is already enabled, we should import the the configuration
// for the optional view mode by enabling social_flexible_group_featured.
if (in_array('social_group_flexible_group', $modules, TRUE) && \Drupal::moduleHandler()
->moduleExists('social_landing_page') || in_array('social_landing_page', $modules, TRUE) && \Drupal::moduleHandler()
->moduleExists('social_group_flexible_group')) {
\Drupal::service('module_installer')
->install([
'social_flexible_group_featured',
]);
}
// If either social_book or social_landing_page gets enabled and
// the other is already enabled, we should import the the configuration
// for the optional view mode by enabling social_book_featured.
if (in_array('social_book', $modules, TRUE) && \Drupal::moduleHandler()
->moduleExists('social_landing_page') || in_array('social_landing_page', $modules, TRUE) && \Drupal::moduleHandler()
->moduleExists('social_book')) {
\Drupal::service('module_installer')
->install([
'social_book_featured',
]);
}
}
/**
* Implements hook_entity_form_display_alter().
*/
function social_core_entity_form_display_alter(EntityFormDisplayInterface $form_display, array $context) {
$field_groups = $form_display
->getThirdPartySettings('field_group');
if (!isset($field_groups['group_settings'])) {
return;
}
$fields = [];
// List of all fields which are split by section.
foreach ($field_groups as $field_group) {
$fields = array_merge($fields, $field_group['children']);
}
// List of all fields which aren't split by section.
$fields = array_diff(array_keys($form_display
->getComponents()), $fields);
if ($fields) {
$field_groups['group_settings']['children'] = array_merge($field_groups['group_settings']['children'], $fields);
$form_display
->setThirdPartySetting('field_group', 'group_settings', $field_groups['group_settings'])
->save();
}
}
/**
* Implements hook_preprocess_HOOK().
*/
function social_core_preprocess_node(&$variables) {
/** @var \Drupal\node\NodeInterface $node */
$node = $variables['node'];
// Add common variable for teaser images.
$image_field = "field_{$node->getType()}_image";
// If machine name too long or using another image field.
if (!$node
->hasField($image_field)) {
$node_fields = $node
->getFields();
$image_fields = array_filter($node_fields, '_social_core_find_image_field');
// Get the first image field of all the fields.
if ($image_fields) {
$image_field = reset($image_fields)
->getName();
}
else {
$image_field = NULL;
}
}
if (!empty($variables['content'][$image_field]['#theme'])) {
$variables['node_image'] = $variables['content'][$image_field];
$variables['no_image'] = FALSE;
}
else {
$variables['no_image'] = TRUE;
}
if ($variables['view_mode'] === 'hero') {
// Add node edit url for management.
// Get the current route name to check if the user is on the
// edit or delete page.
$route = \Drupal::routeMatch()
->getRouteName();
if (!in_array($route, [
'entity.node.edit_form',
'entity.node.delete_form',
])) {
$account = \Drupal::currentUser();
if ($node
->access('update', $account)) {
$variables['node_edit_url'] = $node
->toUrl('edit-form')
->toString();
// Ensure the cache varies correctly depending upon access of the user.
$variables['#cache']['contexts'][] = 'user.node_grants';
}
}
// Add the hero styled image.
if ($node
->hasField($image_field) && !empty($node->{$image_field}->entity)) {
$variables['hero_styled_image_url'] = ImageStyle::load('social_xx_large')
->buildUrl($node->{$image_field}->entity
->getFileUri());
}
}
}
/**
* Implements hook_social_user_account_header_account_links().
*
* Adds the "My invitations" link to the user menu.
*/
function social_core_social_user_account_header_account_links(array $context) {
// We require a user for this link.
if (empty($context['user']) || !$context['user'] instanceof AccountInterface) {
return [];
}
/** @var \Drupal\social_core\InviteService $core_invites */
$core_invites = \Drupal::service('social_core.invite');
// Only when there are actual Invite plugins enabled.
if (!empty($core_invites
->getInviteData('name'))) {
$title = new TranslatableMarkup('Invites');
// If we have invites show the number.
if (!empty($core_invites
->getInviteData('amount'))) {
$title = [
'#type' => 'inline_template',
'#template' => '<span>{% trans %}Invites{% endtrans %}</span> <span{{ attributes }}>{{ icon }}</span>',
'#context' => [
'attributes' => new Attribute([
'class' => 'margin-left-xs badge badge-accent badge--pill',
]),
'icon' => (string) $core_invites
->getInviteData('amount'),
],
];
}
return [
'divider_no_mobile' => [
'#wrapper_attributes' => [
'class' => [
'divider',
'hidden-for-phone-only',
],
'role' => 'separator',
],
'#weight' => 325,
],
'my_invites' => [
'#type' => 'link',
'#attributes' => [
'title' => new TranslatableMarkup('Invites'),
],
'#title' => $title,
'#weight' => 350,
] + Url::fromRoute('social_core.my_invites')
->toRenderArray(),
];
}
}
/**
* Implements hook_social_user_account_header_items().
*
* Adds an indicator to the user account menu.
*/
function social_core_social_user_account_header_items_alter(array &$menu_links, array $context) {
// We require a logged in user for this indicator.
if (empty($context['user']) || !$context['user']
->isAuthenticated()) {
return;
}
// If the account_box link was removed we have nothing to do.
if (!isset($menu_links['account_box'])) {
return;
}
// Get the total amount of notifications for the user.
/** @var \Drupal\social_core\InviteService $core_invites */
$core_invites = \Drupal::service('social_core.invite');
// Only when there are actual Invites.
if ($core_invites
->getInviteData('amount') > 0) {
$menu_links['account_box']['#wrapper_attributes']['class'][] = 'has-alert has-alert--desktop';
}
}
/**
* Tries to determine if a field is an image field based on a field name.
*
* @param \Drupal\Core\Field\FieldItemList $field
* A field object.
*
* @return \Drupal\Core\Field\FieldItemList|null
* Will return the FieldItemList or null if its not an image field.
*/
function _social_core_find_image_field(FieldItemList $field) {
if (strpos($field
->getName(), 'image') !== FALSE) {
return $field;
}
return NULL;
}
/**
* Implements hook_form_FORM_ID_alter().
*
* For Site information Site details form.
*/
function social_core_form_system_site_information_settings_alter(&$form, FormStateInterface $form_state, $form_id) {
// Hide site slogan field and make it disabled as well whenever the user
// is able to fill out the textfield.
if (!empty($form['site_information']['site_slogan'])) {
$form['site_information']['site_slogan']['#type'] = 'hidden';
$form['site_information']['site_slogan']['#disabled'] = TRUE;
}
}
/**
* Implements hook_node_links_alter().
*/
function social_core_node_links_alter(array &$links, NodeInterface $entity, array &$context) {
// Remove the comment links.
unset($links['comment__field_topic_comments'], $links['comment__field_event_comments']);
if (isset($context['view_mode']) && in_array($context['view_mode'], [
'activity',
'activity_comment',
])) {
// Add a readmore link.
$node_title_stripped = strip_tags($entity
->label());
$links['node']['#links']['node-readmore'] = [
'title' => t('Read more<span class="visually-hidden"> about @title</span>', [
'@title' => $node_title_stripped,
]),
'url' => $entity
->toUrl(),
'attributes' => [
'rel' => 'tag',
'title' => $node_title_stripped,
],
];
}
}
/**
* Prepares variables for comment field templates.
*
* Default template: field--comment.html.twig.
*
* @param array $variables
* An associative array containing:
* - element: An associative array containing render arrays for the list of
* comments, and the comment form. Array keys: comments, comment_form.
*/
function social_core_preprocess_field(array &$variables) {
$element = $variables['element'];
if ($element['#formatter'] == 'comment_node') {
// Create separate variables for the more_link.
$variables['more_link'] = $element[0]['more_link'];
}
}
/**
* Implements hook_preprocess_block().
*/
function social_core_preprocess_block(&$variables) {
/** @var \Drupal\user\Entity\User $account */
$account = \Drupal::routeMatch()
->getParameter('user');
/** @var \Drupal\group\Entity\Group $group */
$group = \Drupal::routeMatch()
->getParameter('group');
if (is_numeric($account)) {
$account = User::load($account);
}
if (is_numeric($group)) {
$group = Group::load($group);
}
if (!empty($variables['elements']['content']['#view'])) {
$view = $variables['elements']['content']['#view'];
if (!empty($view
->getDisplay())) {
$link = $view
->getDisplay();
if (!empty($link
->useMoreText())) {
$more_link = $link
->useMoreText();
}
}
}
// Add variables to sidebar blocks.
switch ($variables['elements']['#derivative_plugin_id']) {
case 'upcoming_events-block_my_upcoming_events':
$variables['view_all_path'] = Url::fromRoute('view.events.events_overview', [
'user' => \Drupal::currentUser()
->id(),
]);
$variables['button_text'] = $more_link;
$link
->setOption('use_more', FALSE);
break;
case 'upcoming_events-block_community_events':
$variables['subtitle'] = t('in the community');
$variables['view_all_path'] = Url::fromRoute('view.upcoming_events.page_community_events');
if (isset($variables['label']['#markup'])) {
$label = $variables['label']['#markup'];
}
else {
$label = t('events');
}
$variables['button_text'] = t('All @label', [
'@label' => $label,
]);
break;
case 'latest_topics-block_latest_topics':
$variables['subtitle'] = t('in the community');
$variables['view_all_path'] = Url::fromRoute('view.latest_topics.page_latest_topics');
$variables['button_text'] = $more_link;
$link
->setOption('use_more', FALSE);
break;
case 'newest_groups-block_newest_groups':
$variables['subtitle'] = t('in the community');
$variables['view_all_path'] = Url::fromRoute('view.newest_groups.page_all_groups');
$variables['button_text'] = $more_link;
$link
->setOption('use_more', FALSE);
break;
case 'newest_users-block_newest_users':
$variables['subtitle'] = t('in the community');
$variables['view_all_path'] = Url::fromRoute('view.newest_users.page_newest_users');
$variables['button_text'] = $more_link;
$link
->setOption('use_more', FALSE);
break;
case 'events-block_events_on_profile':
if ($account instanceof UserInterface) {
$variables['subtitle'] = t('for this user');
$variables['view_all_path'] = Url::fromRoute('view.events.events_overview', [
'user' => $account
->id(),
]);
$variables['button_text'] = t('All @label', [
'@label' => $variables['label']['#markup'],
]);
}
break;
case 'topics-block_user_topics':
if ($account instanceof UserInterface) {
$variables['subtitle'] = t('for this user');
$variables['view_all_path'] = Url::fromRoute('view.topics.page_profile', [
'user' => $account
->id(),
]);
$variables['button_text'] = $more_link;
$link
->setOption('use_more', FALSE);
}
break;
case 'groups-block_user_groups':
if ($account instanceof UserInterface) {
$variables['subtitle'] = t('for this user');
$variables['view_all_path'] = Url::fromRoute('view.groups.page_user_groups', [
'user' => $account
->id(),
]);
$variables['button_text'] = $more_link;
$link
->setOption('use_more', FALSE);
}
break;
case 'group_members-block_newest_members':
$variables['subtitle'] = t('in the group');
$variables['view_all_path'] = Url::fromRoute('view.group_members.page_group_members', [
'group' => $group
->id(),
]);
$variables['button_text'] = $more_link;
$link
->setOption('use_more', FALSE);
break;
case 'upcoming_events-upcoming_events_group':
$variables['subtitle'] = t('in the group');
$variables['view_all_path'] = Url::fromRoute('view.group_events.page_group_events', [
'group' => $group
->id(),
]);
$variables['button_text'] = t('All @label', [
'@label' => $variables['label']['#markup'],
]);
break;
case 'latest_topics-group_topics_block':
$variables['subtitle'] = t('in the group');
$variables['view_all_path'] = Url::fromRoute('view.group_topics.page_group_topics', [
'group' => $group
->id(),
]);
$variables['button_text'] = $more_link;
$link
->setOption('use_more', FALSE);
break;
}
}
/**
* Implements hook_menu_local_tasks_alter().
*/
function social_core_menu_local_tasks_alter(&$data, $route_name) {
if (\Drupal::currentUser()
->isAnonymous()) {
// Anonymous user so we unset the user tabs on login register etc.
if (isset($data['tabs'][0]['user.register'])) {
unset($data['tabs'][0]['user.register']);
}
if (isset($data['tabs'][0]['user.pass'])) {
unset($data['tabs'][0]['user.pass']);
}
if (isset($data['tabs'][0]['user.login'])) {
unset($data['tabs'][0]['user.login']);
}
}
// Remove node Edit tab. Edit will always go through Floating Edit Button.
if (isset($data['tabs'][0]['entity.node.edit_form'])) {
unset($data['tabs'][0]['entity.node.edit_form']);
}
// Change the default 'View' tab title.
if (isset($data['tabs'][0]['entity.node.canonical']['#link'])) {
$data['tabs'][0]['entity.node.canonical']['#link']['title'] = t('Details');
}
// Remove Delete tab. Delete will always go through Edit.
if (isset($data['tabs'][0]['entity.node.delete_form'])) {
unset($data['tabs'][0]['entity.node.delete_form']);
}
}
/**
* Implements hook_form_taxonomy_vocabulary_form_alter().
*/
function social_core_form_taxonomy_vocabulary_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Fetch current user.
$account = \Drupal::currentUser();
// Check if the current use is the admin.
if (!in_array('administrator', $account
->getRoles())) {
// Remove the option to delete.
unset($form['actions']['delete']);
}
}
/**
* Implements hook_form_taxonomy_vocabulary_confirm_delete_alter().
*/
function social_core_form_taxonomy_vocabulary_confirm_delete_alter(&$form, FormStateInterface $form_state, $form_id) {
// Fetch current user.
$account = \Drupal::currentUser();
// Check if the current use is the admin.
if (!in_array('administrator', $account
->getRoles())) {
// Remove the option to delete.
unset($form['actions']['submit']);
$form['description']['#markup'] = t('You have insufficient permissions to delete this vocabulary');
}
}
/**
* Implements hook_preprocess().
*/
function social_core_preprocess_breadcrumb(&$variables) {
// Get the user.
$user = \Drupal::currentUser();
// Add cache tag for the user.
$variables['#cache']['tags'][] = 'user:breadcrumb:' . $user
->id();
}
/**
* Implements hook_element_info_alter().
*/
function social_core_element_info_alter(array &$info) {
if (isset($info['text_format']['#process'])) {
$info['text_format']['#process'][] = 'social_core_filter_process_format';
}
if (isset($info['entity_autocomplete'])) {
$info['entity_autocomplete']['#value_callback'] = [
'\\Drupal\\social_core\\Entity\\Element\\EntityAutocomplete',
'valueCallback',
];
}
}
/**
* Remove ability of selecting format if full_html is available.
*
* @todo Instead of defining the list of fields it would be better to add a
* separate Setting to all text_format fields, allowing to select whether to
* show format selector or not.
*/
function social_core_filter_process_format($element) {
// Only fields listed here will have text format settings disabled.
$full_html_field_ids = [
'edit-body-0',
'edit-field-profile-self-introduction-0',
'edit-field-group-description-0',
];
$element_id = $element['#id'];
// Check if there is generated sub-id and cleanup it.
if (($sub_id = strpos($element_id, '--')) !== FALSE) {
$element_id = substr($element_id, 0, $sub_id);
}
// Default filter format for text area fields.
$social_filter_format = 'full_html';
// Allow module to override default filter format because some content type
// could require specific one.
Drupal::moduleHandler()
->alter('social_filter_format_default', $social_filter_format);
/** @var \Drupal\filter\Entity\FilterFormat $social_filter_format */
$social_filter_format = FilterFormat::load($social_filter_format);
// Check if filter format was loaded, to prevent fatal errors if wrong value
// was provided in the hook_social_filter_format_default_alter().
if (!$social_filter_format instanceof FilterFormatInterface) {
return $element;
}
$permission_name = $social_filter_format
->getPermissionName();
$account = Drupal::currentUser();
if ($element['#type'] === 'text_format' && $element['#format'] === $social_filter_format
->id() && !$account
->hasPermission($permission_name)) {
$element['#format'] = 'basic_html';
$element['value']['#format'] = 'basic_html';
$element['format']['format']['#default_value'] = 'basic_html';
$element['format']['format']['#value'] = 'basic_html';
$element['value']['#disabled'] = FALSE;
$element['format']['format']['#access'] = FALSE;
$element['format']['#access'] = TRUE;
$key = array_search('filter_form_access_denied', $element['value']['#pre_render']);
if (isset($element['value']['#pre_render'][$key])) {
unset($element['value']['#pre_render'][$key]);
}
}
elseif ($element['#type'] === 'text_format' && $account
->hasPermission($permission_name) && in_array($element_id, $full_html_field_ids)) {
$element['#format'] = $social_filter_format;
$element['format']['format']['#access'] = FALSE;
$element['format']['format']['#value'] = $social_filter_format
->id();
$element['format']['help']['#access'] = FALSE;
$element['format']['format']['#options'] = [
$social_filter_format
->id() => $social_filter_format
->label(),
];
}
return $element;
}
/**
* Hide blocks on extendable visibility path.
*
* Implements hook_block_access().
*/
function social_core_block_access(Block $block, $operation, AccountInterface $account) {
$blocks =& drupal_static(__FUNCTION__);
$blocks = [];
// First check if we have it cached before we run the modulehandler alter.
/** @var \Drupal\Core\Cache\CacheBackendInterface $cache */
$cache = \Drupal::service('cache.default');
if ($cache
->get('social_core.block_visibility_cache') === FALSE) {
// Allow other modules to change the block visibility.
$blocks = \Drupal::moduleHandler()
->invokeAll('social_core_block_visibility_path');
// Set the cache expire to 1 week.
$date = new DateTime(date('Y-m-d'));
$date
->modify('+7 day');
$cache
->set('social_core.block_visibility_cache', $blocks, $date
->getTimestamp(), [
'social_core.block_visibility_cache',
]);
}
else {
$blocks = $cache
->get('social_core.block_visibility_cache')->data;
}
// Alter the access based on the blocks array.
if ($operation === 'view' && isset($blocks[$block
->getPluginId()])) {
// Get the current path.
$current_path = \Drupal::service('path.current')
->getPath();
// Go through the request paths and see if they match.
foreach ($blocks[$block
->getPluginId()] as $page) {
if (\Drupal::service('path.matcher')
->matchPath($current_path, $page) === TRUE) {
return AccessResult::forbidden();
}
}
}
// No opinion.
return AccessResult::neutral();
}
/**
* Implements hook_field_widget_form_alter().
*/
function social_core_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {
$field_definition = $context['items']
->getFieldDefinition();
if ($field_definition
->getType() == 'path') {
$url = Url::fromRoute('<front>', [], [
'absolute' => TRUE,
]);
// Protocols we can strip.
$protocols = [
'https://www.',
'http://www.',
'https://',
'http://',
'www.',
];
// The URL.
$truncate_url = $url
->toString();
// Loop over the protocols and try to replace them in the string.
foreach ($protocols as $protocol) {
$truncate_url = str_replace($protocol, '', $truncate_url);
}
// Put the protocoless, truncated URL in the addon.
$element['alias']['#field_prefix'] = '<div class="input-group input-group-expanded"><span class="input-group-addon">' . $truncate_url . '</span>';
$element['alias']['#field_suffix'] = '</div>';
// Unset description and title.
unset($element['alias']['#description']);
unset($element['alias']['#title']);
// URLs are stored with a leading slash but our display includes that slash
// in the prefix so we remove it here.
if (isset($element['alias']['#default_value'])) {
$element['alias']['#default_value'] = ltrim($element['alias']['#default_value'], '/');
}
$element['#element_validate'] = [
'social_core_path_validate',
];
}
}
/**
* Form element validation handler for URL alias form element.
*
* Ensures that a path alias entered by a user is always a relative internal URL
* that starts with a leading slash. If the user did not enter a leading slash
* then we add it for them.
*
* @param array $element
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
function social_core_path_validate(array &$element, FormStateInterface $form_state) {
$alias = trim($element['alias']['#value'], " \\/");
$parsed_url = parse_url($alias);
if (isset($parsed_url['host']) || isset($parsed_url['scheme']) || !isset($parsed_url['path'])) {
$form_state
->setError($element, t('The URL alias must be a relative URL.'));
}
elseif (trim($element['alias']['#value']) !== "/") {
// $alias is already trimmed of leading/trailing slashes.
// We use rtrim here to ensure we don't set the value to an empty slash
// during form submission.
// The following line only changes the value of the rendered form element.
// If we have a non-empty alias PathWidget::validateFormElement will
// update the actual stored value to include the leading slash.
$element['alias']['#value'] = rtrim('/' . $alias, '/');
PathWidget::validateFormElement($element, $form_state);
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function social_core_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Array of node types, which have the new group_settings fieldset,
// these nodes can use the new content style, and have $form['advanced']
// removed.
// if we remove it for nodes which don't have that fieldset, fields will be
// rendered outside of a card.
$compatible_content_type_forms = [
'node_event_form',
'node_event_edit_form',
'node_topic_form',
'node_topic_edit_form',
'node_page_form',
'node_page_edit_form',
];
// Create new alter hook which allows extensions to add nodes
// to this list once they have added the group_settings.
\Drupal::moduleHandler()
->alter('social_core_compatible_content_forms', $compatible_content_type_forms);
// Let's remove the form elements not needed by Open Social.
// We understand this is quite BC breaking, url_redirects / revision info
// we don't use as Open Social, you might use. So by
// changing the theme setting in social blue, you can go back to the
// old settings and use Field UI to change the other fields.
$use_social_content_forms = theme_get_setting('content_entity_form_style');
if ($use_social_content_forms === 'open_social' && in_array($form_id, $compatible_content_type_forms)) {
// We want to move all the fields from $form['advanced'] to our new
// field sets which are created as part of #3186003.
if (!empty($form['advanced'])) {
unset($form['advanced']);
// Unset optional fields.
if (isset($form['revision'])) {
unset($form['revision']);
}
if (isset($form['revision_log'])) {
unset($form['revision_log']);
}
if (isset($form['revision_information'])) {
unset($form['revision_information']);
}
if (isset($form['url_redirects'])) {
unset($form['url_redirects']);
}
if (isset($form['meta'])) {
unset($form['meta']);
}
// Add descriptive text to URL Alias field.
if (isset($form['path']['widget'][0]['alias'])) {
$form['path']['widget'][0]['alias']['#description'] = t('The URL alias allows you to customise the link to this page.');
}
// Hide the automatic URL alias.
if (isset($form['path']['widget'][0]['pathauto'])) {
$form['path']['widget'][0]['pathauto']['#type'] = 'hidden';
// Path uses the above checkbox to decide whether or not to save
// the automatically generated alias, or use a custom one.
// since we hide the element, and the default is checked,
// the path will never be overridden if someone updates it.
// So we need to check this in our custom submit handler.
// It should perform before path auto runs.
array_unshift($form['actions']['submit']['#submit'], '_social_core_path_widget_submit');
}
// Move the fields from advanced to group_settings.
if (!empty($form['#fieldgroups']['group_settings'])) {
// Move the book outline fields to the group settings.
// #502430 we need to remove this ourselves, users with permission
// can see the book outline even when not configured as part
// of the book settings.
if (!empty($form['book']) && $form_state
->getFormObject() !== NULL && \Drupal::moduleHandler()
->moduleExists('book')) {
// Grab the Entity to see if books are enabled for this one.
$entity = $form_state
->getFormObject()
->getEntity();
if (!empty($entity
->getType()) && is_string($entity
->getType())) {
// Move it to our new fieldset on book pages either on its own
// or in the group_settings.
$form['book']['#type'] = 'fieldset';
$form['book']['#attributes']['class'][] = 'card';
$form['book']['#weight'] = isset($form['#fieldgroups']['group_visibility']->weight) ? $form['#fieldgroups']['group_visibility']->weight + 1 : '3';
$enabled = book_type_is_allowed($entity
->getType());
// If it's not enabled we can just safely unset it.
if (!$enabled) {
unset($form['book']);
}
}
}
// Move the node Menu settings to group_settings.
if (!empty($form['menu'])) {
$form['menu']['#group'] = 'group_settings';
$form['menu']['#weight'] = -20;
$form['menu']['#title'] = t('Menu link');
if (!empty($form['menu']['link']['title'])) {
$form['menu']['link']['title']['#title'] = t('Title');
$form['menu']['link']['title']['#description'] = t('This title will be displayed in the menu.');
}
if (!empty($form['menu']['link']['description'])) {
$form['menu']['link']['title']['#description'] = t('This description will be displayed when hovering over the menu link.');
}
}
// Move the Published status to group settings with a new wrapper.
if (!empty($form['status'])) {
// Add an details element to status.
$form['status_label'] = [
'#type' => 'details',
'#title' => t('Publish status'),
'#description' => '',
'#open' => TRUE,
'#weight' => 110,
'#group' => 'group_settings',
];
$form['status']['#group'] = 'status_label';
$form['status_label']['status'] = $form['status'];
unset($form['status']);
}
// Node author information for administrators.
$form['author_info'] = [
'#type' => 'details',
'#title' => t('Author Information'),
'#description' => '',
'#open' => TRUE,
'#weight' => 100,
'#group' => 'group_settings',
];
// Move author uid to the new author info fieldset,
// and remove descriptive text.
if (isset($form['uid'])) {
$form['uid']['#group'] = 'author_info';
$form['uid']['widget']['#description'] = '';
if (!empty($form['uid']['widget'][0]['target_id'])) {
$form['uid']['widget'][0]['target_id']['#description'] = '';
}
$form['author_info']['uid'] = $form['uid'];
unset($form['uid']);
}
// Move created to the new author info fieldset,
// and remove descriptive text.
if (isset($form['created'])) {
$form['created']['#group'] = 'author_info';
$form['created']['widget']['#description'] = '';
$form['created']['widget'][0]['#description'] = '';
$form['created']['widget'][0]['value']['#description'] = '';
$form['author_info']['created'] = $form['created'];
unset($form['created']);
}
$has_option_fields = FALSE;
foreach ([
'promote',
'sticky',
] as $field) {
if (isset($form[$field])) {
$form['options'][$field] = $form[$field];
unset($form[$field]);
$has_option_fields = TRUE;
}
}
// When the "Promoted to front page" field or the "Sticky at top of
// lists" field is enabled then move their wrapper (the "Promotion
// options" sub-section) to the "Settings" section.
// @see \Drupal\node\NodeForm::form().
if ($has_option_fields) {
$form['options']['#group'] = 'group_settings';
// Place the "Promotion options" sub-section after the "Publish
// status" sub-section.
$form['options']['#weight'] = 120;
// Display sub-section as expanded.
$form['options']['#optional'] = FALSE;
}
}
// According to FileWidget.php we cant use a widget form alter.
if (!empty($form['field_files']) && !empty($form['field_files']['widget']['#file_upload_title'])) {
$form['field_files']['widget']['#file_upload_title'] = t('Attachments');
}
}
// Change the button text from Save to Create topic / event etc.
// Adds a cancel button.
// Removes the preview button.
if (!empty($form['actions']['submit']) && !empty($form['actions']['submit']['#value']) && $form_state
->getFormObject() !== NULL && method_exists($form_state
->getFormObject(), 'getOperation')) {
// Change the button text from Save to Create topic / event etc.
// Only on node add pages.
if ($form_state
->getFormObject()
->getOperation() !== 'edit') {
/** @var \Drupal\Node\NodeInterface $entity */
$entity = $form_state
->getFormObject()
->getEntity();
if (!empty(node_get_type_label($entity)) && is_string(node_get_type_label($entity))) {
$form['actions']['submit']['#value'] = t('Create @entity', [
'@entity' => strtolower(node_get_type_label($entity)),
]);
}
}
// Adds cancel button.
if (!isset($form['actions']['cancel'])) {
$form['actions']['cancel'] = [
'#type' => 'submit',
'#value' => t('Cancel'),
'#submit' => [
'_social_core_node_cancel',
],
'#limit_validation_errors' => [],
'#attributes' => [
'class' => [
'button btn-default btn waves-effect waves-btn',
],
],
];
}
// Remove the preview button.
if (isset($form['actions']['preview'])) {
unset($form['actions']['preview']);
}
}
}
}
/**
* Custom form submit handler for handling an path alias update.
*
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* Form state.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
function _social_core_path_widget_submit(array $form, FormStateInterface $form_state) {
// Path uses the pathauto checkbox to decide whether or not to save
// the automatically generated alias, or use a custom one.
// since we hide the element, and the default is checked,
// the path will never be overridden if someone updates it.
// So we need to check this in our custom submit handler.
$default_path = isset($form['path']['widget'][0]['alias']['#default_value']) ? $form['path']['widget'][0]['alias']['#default_value'] : '';
$input = $form_state
->getUserInput();
$updated_path = isset($input['path'][0]['alias']) ? $input['path'][0]['alias'] : '';
// If we don't have a match, make sure we override the checkbox as well.
if ($updated_path !== $default_path) {
// Override the User input, act as if this was changed.
$input['path'][0]['pathauto'] = "0";
$form_state
->setUserInput($input);
// Override the value.
$form_state
->setValue([
'path',
'0',
'pathauto',
], "0");
// If the updated path is empty, make it automatic again.
if (empty($updated_path)) {
$input['path'][0]['pathauto'] = "1";
$form_state
->setUserInput($input);
$form_state
->setValue([
'path',
'0',
'pathauto',
], "1");
}
}
}
/**
* Redirects to the previous page, or home when pressing cancel form.
*
* @param array $form
* Join and leave form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* Form state interface.
*/
function _social_core_node_cancel(array &$form, FormStateInterface $form_state) {
// By default the front page will be used,
// especially for adding a node.
$form_state
->setRedirect('<front>');
// If we have an existing node, we rather go to the node itself.
if (!empty($form_state
->getFormObject()
->getEntity())) {
$entity = $form_state
->getFormObject()
->getEntity();
if ($entity instanceof NodeInterface && $entity
->id() !== NULL) {
$form_state
->setRedirect('entity.node.canonical', [
'node' => $entity
->id(),
[],
]);
}
}
}
/**
* Implements hook_theme_registry_alter().
*/
function social_core_theme_registry_alter(&$theme_registry) {
$theme_registry['menu__toolbar']['variables']['menu_name'] = NULL;
}
/**
* Function to set default email logo if not set already for OS.
*/
function _social_core_set_default_email_logo_for_socialblue() {
// Only when socialblue is default we continue.
if (\Drupal::configFactory()
->get('system.theme')
->get('default') === 'socialblue') {
$logo = theme_get_setting('logo.url', 'socialblue');
$basetheme_url = drupal_get_path('theme', 'socialblue');
// Only if the theme setting for the logo, is still the socialblue
// default logo, we can update our default logo.
// If someone changed it to their own branding, let's not update it
// because that would create regression.
// that will be /profile/contrib/social/themes/socialblue/logo.svg.
if (!empty($basetheme_url) && $logo === DIRECTORY_SEPARATOR . $basetheme_url . DIRECTORY_SEPARATOR . 'logo.svg') {
// Add default image.
$config_factory = \Drupal::configFactory();
// Lets get the email logo settings.
$socialblue_settings = $config_factory
->getEditable('socialblue.settings');
$default_image = $socialblue_settings
->get('email_logo');
// Only if there is no default image, or if its the same as the
// socialblue logo we can continue.
if (empty($default_image) || $default_image === $basetheme_url . DIRECTORY_SEPARATOR . 'logo.svg') {
$file_system = \Drupal::service('file_system');
$uri = $file_system
->copy($basetheme_url . DIRECTORY_SEPARATOR . 'logo_email.png', 'public://logo_email.png', FileSystemInterface::EXISTS_REPLACE);
$media = File::create([
'uri' => $uri,
]);
$media
->setPermanent();
$media
->save();
$default_image[0] = $media
->id();
// We just save the file id.
$socialblue_settings
->set('email_logo', $default_image)
->save();
}
}
}
}
/**
* Implements hook_preprocess_HOOK() for status_messages.
*/
function social_core_preprocess_status_messages(&$variables) {
// We want to remove stratus messages coming form image_widget_crop module.
// These notifications are technical in nature and add no value for the user.
// @see: \Drupal\image_widget_crop\ImageWidgetCropManager::saveCrop().
if (isset($variables['message_list']['status'])) {
// Get all the status messages.
$status_messages = $variables['message_list']['status'];
// Loop through them to find the relevant messages we are looking for.
foreach ($status_messages as $delta => $message) {
// Unset them finally.
if (strpos((string) $message, 'The crop') !== FALSE) {
unset($variables['message_list']['status'][$delta]);
}
}
}
}