compose-8.x-1.x-dev/compose.module
compose.module
<?php
/**
* @file
* Contains Drupal\compose\compose.module.
*/
use Drupal\Core\Cache\Cache;
use Drupal\Core\Render\Element;
use Drupal\Core\Url;
/**
* Implements hook_theme().
*/
function compose_theme() {
$theme = [];
$theme['compose_tabs'] = [
'render element' => 'content',
'template' => 'compose-tabs',
];
$theme['compose_entity_widget'] = [
'render element' => 'entities',
'template' => 'compose-entity-widget',
];
$theme['compose_preview_placeholder'] = [
'render element' => 'content',
'template' => 'compose-preview-placeholder',
];
return $theme;
}
/**
* Implements hook_entity_type_build().
*/
function compose_entity_type_build(array &$entity_types) {
/** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
foreach ($entity_types as &$entity_type) {
if (!$entity_type->hasHandlerClass('compose_widget')) {
$entity_type->setHandlerClass('compose_widget', '\Drupal\compose\EntityComposeWidget');
}
}
}
/**
* Implements hook_preprocess_compose_entity_widget().
*/
function compose_preprocess_compose_entity_widget(&$variables) {
$field_name = $variables['entities']['#field_name'];
$variables['attributes']['data-compose-entity-widget'] = '';
$variables['attributes']['class'][] = 'compose-entity-widget';
// If the cache contexts is not set, set it to an empty array.
if (!isset($variables['entities']['#cache']['context'])) {
$variables['entities']['#cache']['contexts'] = [];
}
foreach (Element::children($variables['entities']) as $delta) {
$entity_id = $variables['entities'][$delta]['#entity']->id();
$entity_type = $variables['entities'][$delta]['#entity']->getEntityTypeId();
// Make the top-level render element a container for a wrapper div.
$variables['entities'][$delta]['#type'] = 'container';
$variables['entities'][$delta]['#attributes']['class'][] = 'compose-entity-item';
$variables['entities'][$delta]['#attributes']['data-compose-entity-item'] = '';
// We need to impose our own ordering on these render elements.
$variables['entities'][$delta]['#sorted'] = FALSE;
// Create a container that will contain the entity label and actions.
$variables['entities'][$delta]['entity_meta'] = [
'#type' => 'container',
'#attributes' => [
'class' => 'compose-preview-meta',
],
'#weight' => -1,
];
// Create an h2 with the entity label within the entity_meta container.
$variables['entities'][$delta]['entity_meta']['entity_label'] = [
'#type' => 'html_tag',
'#tag' => 'h2',
'#value' => $variables['entities'][$delta]['#label'],
];
// Add the entity actions to the entity_meta container.
$variables['entities'][$delta]['entity_meta']['actions'] = $variables['entities'][$delta]['actions'];
// Unset the this since we are adding it to the entity_meta container.
unset($variables['entities'][$delta]['actions']);
// Build the container and data attributes to contain the rendered entity.
$variables['entities'][$delta]['entity'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#attributes' => [
'data-compose-delta' => $delta,
'data-compose-field-name' => $field_name,
'data-compose-entity-id' => $entity_id,
'data-compose-entity-type' => $entity_type,
'class' => ['compose-entity-preview'],
],
"#prefix" => '<div class="compose-preview-wrapper">',
'#suffix' => '</div>',
'#weight' => 0,
'placeholder' => [
'#theme' => 'compose_preview_placeholder',
],
];
// Give the delta the highest weight so it will appear below its siblings.
$variables['entities'][$delta]['delta']['#weight'] = 1;
// And give it a wrapper.
$variables['entities'][$delta]['delta']['#prefix'] = '<div class="compose-delta-wrapper">';
$variables['entities'][$delta]['delta']['#suffix'] = '</div>';
// Pass the cache tags and contexts to the actual element being rendered.
$variables['entities']['#cache']['tags'] = Cache::mergeTags($variables['entities']['#cache']['tags'], $variables['entities'][$delta]['#entity']->getCacheTags());
$variables['entities']['#cache']['contexts'] = Cache::mergeContexts($variables['entities']['#cache']['contexts'], $variables['entities'][$delta]['#entity']->getCacheContexts());
}
}
/**
* Implements hook_theme_registry_alter().
*/
function compose_theme_registry_alter(&$registry) {
$registry['node_edit_form']['path'] = drupal_get_path('module', 'compose') . '/templates';
$registry['node_edit_form']['template'] = 'node-edit-compose-form';
}
/**
* Implements hook_form_node_form_alter().
*/
function compose_form_node_form_alter(&$form, &$form_state, $form_id) {
if (isset($form['#entity_type']) && $form['#entity_type'] != 'node' && isset($form['field_layouts']['field_layout']['#options']['Compose'])) {
unset($form['field_layouts']['field_layout']['#options']['Compose']);
}
if (isset($form['_field_layout']) && $form['_field_layout']['#theme'] == 'compose_tabs') {
$form['#compose'] = TRUE;
$form['#attributes']['data-compose'] = 'compose-form';
if (\Drupal::service('theme.manager')->getActiveTheme()->getName() == 'seven') {
$form['#attached']['library'][] = 'compose/compose-seven';
}
// Move advanced field container to settings region.
$form['advanced']['#type'] = 'details';
$form['advanced']['#group'] = 'settings';
// Respect weight of settings fields within their groups.
// Update group weight based on highest field weight within the group.
$compose_groups = [
'content',
'fields',
'settings',
'revisions',
];
$ignore_fields = [
'actions',
'form_build_id',
'form_token',
'form_id',
'menu',
'revision_information',
'revision',
];
$field_settings = [];
foreach ($form as $field_name => $value) {
if (substr($field_name, 0, 1) !== '#' && substr($field_name, 0, 1) !== '_' && !in_array($field_name, $ignore_fields)) {
// Check for data in nested widget first.
if (isset($form[$field_name]['widget'][0]['#group'])) {
$group = $form[$field_name]['widget'][0]['#group'];
}
// Set group if it exists.
elseif (isset($form[$field_name]['#group'])) {
$group = $form[$field_name]['#group'];
}
// Force group to settings if it doesn't exist on the field.
elseif (!isset($form[$field_name]['#group'])) {
$group = 'settings';
$form[$field_name]['#group'] = $group;
// Nest the revision log in the revision information group.
if ($field_name = 'revision_log') {
$form[$field_name]['#group'] = 'revision_information';
$form[$field_name]['#weight'] = -99;
}
}
// If everything checks out, set the weight of the field.
if (isset($form[$field_name]['#weight']) && isset($group) && !in_array($group, $compose_groups)) {
$field_settings[$group][$field_name] = [
'weight' => $form[$field_name]['#weight'],
];
// Set weight on widget if it exists.
if (isset($form[$field_name]['widget'][0]['#weight'])) {
$form[$field_name]['widget'][0]['#weight'] = $form[$field_name]['#weight'];
}
}
}
}
// Set $form field data from our $field_settings array.
$sub_groups = [
'author',
'scheduler_settings',
'revision_information',
];
foreach ($field_settings as $group => $field_info) {
$form[$group]['#weight'] = max(array_column($field_info, 'weight'));
// Break out fields in advanced group to settings region directly.
if ($group == 'advanced') {
foreach ($field_info as $field_name => $weight) {
// Move fields with widgets from advanced group to settings region.
// Now users can set weights for everything above the advanced group.
if (isset($form[$field_name]['widget']['0']['#group']) && $form[$field_name]['widget']['0']['#group'] == 'advanced') {
$form[$field_name]['widget']['0']['#group'] = 'settings';
}
}
}
// Manually move sub-groups out of advanced group.
if (in_array($group, $sub_groups)) {
$form[$group]['#group'] = 'settings';
// Move revision info to the top of the settings region.
if ($group == 'revision_information') {
$form['revision_information']['#weight'] = -99;
}
}
}
// Move status and moderation state to a new container field.
$form['compose_tasks'] = [
'#type' => 'container',
];
foreach (['status', 'moderation_state'] as $field) {
$form['compose_tasks'][$field] = &$form[$field];
unset($form[$field]['#group']);
unset($form[$field]);
}
// Add revisions and cancel links to render array.
$storage = $form_state->getStorage();
if (isset($storage['form_display'])) {
$ogm = $storage['form_display']->getOriginalMode();
if ($ogm == 'edit' || $ogm == 'new') {
$entity = $form_state->getFormObject()->getEntity();
$revisions_url = Url::fromRoute(
'entity.node.version_history',
['node' => $entity->id()],
['absolute' => TRUE]
);
// Add cancel button to form actions.
$form['actions']['cancel'] = [
'#type' => 'link',
'#title' => t('Cancel'),
'#url' => $entity->toUrl(),
'#button_type' => 'default',
'#attributes' => [
'class' => [
'button',
'button-default',
],
],
'#weight' => '30',
'#access' => TRUE,
];
$form['compose_tasks']['revisions'] = [
'#type' => 'link',
'#title' => t('Revisions'),
'#url' => $revisions_url,
'#button_type' => 'default',
'#attributes' => [
'target' => '_blank',
'class' => [
'button',
'button-default',
'container-inline',
],
],
'#weight' => '30',
'#access' => TRUE,
];
}
}
}
}
/**
* Implements hook_form_entity_form_display_edit_form_alter().
*/
function compose_form_entity_form_display_edit_form_alter(&$form, &$form_state, $form_id) {
// Hide revisions region header.
if (isset($form['fields']['#regions']['revisions'])) {
unset($form['fields']['#regions']['revisions']);
}
// Hide revisions region option from select for fields.
foreach ($form['#fields'] as $field) {
if (isset($form['fields'][$field]['region']['#options']['revisions'])) {
unset($form['fields'][$field]['region']['#options']['revisions']);
}
}
// Manually hide revisions region option
// from url_redirects since it's not included in #fields.
if (isset($form['fields']['url_redirects']['region']['#options']['revisions'])) {
unset($form['fields']['url_redirects']['region']['#options']['revisions']);
}
// Hide revisions region option from select for field groups.
if (isset($form['#fieldgroups'])) {
foreach ($form['#fieldgroups'] as $field) {
if (isset($form['fields'][$field]['region']['#options']['revisions'])) {
unset($form['fields'][$field]['region']['#options']['revisions']);
}
}
}
}
/**
* Implements hook_module_implements_alter().
*/
function compose_module_implements_alter(&$implementations, $hook) {
if ($hook == 'form_alter' && isset($implementations['compose'])) {
// Must make sure compose form alter runs after field_layout.
$group = $implementations['compose'];
unset($implementations['compose']);
$implementations['compose'] = $group;
}
}
