You are here

social_landing_page.module in Open Social 10.2.x

The Social landing page module.

File

modules/social_features/social_landing_page/social_landing_page.module
View source
<?php

/**
 * @file
 * The Social landing page module.
 */
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Template\Attribute;
use Drupal\file\Entity\File;
use Drupal\image\Entity\ImageStyle;
use Drupal\node\NodeInterface;
use Drupal\node\Entity\Node;
use Drupal\paragraphs\Entity\Paragraph;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;

/**
 * Implements hook_form_alter().
 */
function social_landing_page_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if (in_array($form_id, [
    'node_landing_page_edit_form',
    'node_landing_page_form',
  ])) {
    $form['#attached']['library'][] = 'social_landing_page/admin';
  }
}

/**
 * Implements hook_form_form_ID_alter().
 *
 * Remove Landing Page option from Search Content filter.
 */
function social_landing_page_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form['#id'] === 'views-exposed-form-search-content-page') {
    if (isset($form['type']['#options']['landing_page'])) {
      unset($form['type']['#options']['landing_page']);
    }
  }
}

/**
 * Implements hook_field_widget_WIDGET_TYPE_form_alter().
 *
 * When rendering the block form inside paragraphs, the #states will not
 * work due to different name parameter, since it's nested inside the paragraph
 * field. We need to alter the form, so that the #states will match the new
 * html markup provided by paragraph. We only do this for
 * 'Override title' field.
 */
function social_landing_page_field_widget_block_field_default_form_alter(&$element, &$form_state, $context) {

  // Make sure we are inside a paragraph.
  $form = $context['form'];
  $entity_type = $form['#entity_type'];
  if ($entity_type != 'paragraph') {
    return;
  }

  // Make sure we only do this in field_landing_page_section.
  $parents = $form['#parents'];
  if (!in_array('field_landing_page_section', $parents)) {
    return;
  }

  // Get block settings and label fields.
  $block_settings = $element['settings'];
  $views_label_checkbox = isset($block_settings['views_label_checkbox']) ? $block_settings['views_label_checkbox'] : FALSE;
  $views_label_fieldset = isset($block_settings['views_label_fieldset']) ? $block_settings['views_label_fieldset'] : FALSE;
  $views_label = isset($block_settings['views_label']) ? $block_settings['views_label'] : FALSE;
  if (!$views_label_checkbox || !$views_label_fieldset || !$views_label) {
    return;
  }

  // Grab the id.
  $id = $block_settings['#attributes']['id'];
  $items = explode('-', $id);

  // Generate the new state name.
  // We use block id, to get all the parent names
  // and then add the checkbox element to it.
  $state_name = $items[0];
  unset($items[0]);
  $items[] = 'views_label_checkbox';
  foreach ($items as $name) {
    $state_name .= '[' . $name . ']';
  }

  // Fields on which to alter the state.
  $fields = [
    'views_label_fieldset',
    'views_label',
  ];
  $state = ':input[name="' . $state_name . '"]';
  foreach ($fields as $field) {

    // Remove old values and replace them with the new ones.
    unset($element['settings'][$field]['#states']['visible']);
    $element['settings'][$field]['#states']['visible'][0] = [
      $state => [
        'checked' => TRUE,
      ],
    ];
  }
}

/**
 * Implements hook_theme().
 */
function social_landing_page_theme() {

  // Page.
  $theme_templates['page__node__landing_page'] = [
    'base hook' => 'page',
  ];

  // Node.
  $theme_templates['node__landing_page'] = [
    'base hook' => 'node',
  ];
  $theme_templates['node__landing_page__featured'] = [
    'base hook' => 'node',
  ];

  // Paragraphs.
  $theme_templates['paragraph__block__default'] = [
    'base hook' => 'paragraph',
  ];
  $theme_templates['paragraph__button__default'] = [
    'base hook' => 'paragraph',
  ];
  $theme_templates['paragraph__hero__default'] = [
    'base hook' => 'paragraph',
  ];
  $theme_templates['paragraph__hero_small__default'] = [
    'base hook' => 'paragraph',
  ];
  $theme_templates['paragraph__introduction__default'] = [
    'base hook' => 'paragraph',
  ];
  $theme_templates['paragraph__section__default'] = [
    'base hook' => 'paragraph',
  ];
  $theme_templates['paragraph__accordion__default'] = [
    'base hook' => 'paragraph',
  ];
  $theme_templates['paragraph__accordion_item__default'] = [
    'base hook' => 'paragraph',
  ];

  // Fields.
  $theme_templates['field__paragraph__section'] = [
    'base hook' => 'field',
  ];

  // Fields for hero buttons.
  $theme_templates['field__paragraph__field_hero_buttons'] = [
    'base hook' => 'field',
  ];
  $theme_templates['field__paragraph__field_hero_small_buttons'] = [
    'base hook' => 'field',
  ];

  // Views.
  $theme_templates['views_view__community_activities'] = [
    'base hook' => 'views_view',
  ];
  return $theme_templates;
}

/**
 * Implements hook_preprocess_page().
 */
function social_landing_page_preprocess_page(&$variables) {

  // Here we remove class for landing page.
  if (isset($variables['node']) && $variables['node'] instanceof NodeInterface && $variables['node']
    ->bundle() === 'landing_page') {
    if (\Drupal::routeMatch()
      ->getRouteName() === 'entity.node.edit_form') {
      $variables['attributes'] = new Attribute();
      $variables['attributes']
        ->addClass('container');
    }
    if (\Drupal::routeMatch()
      ->getRouteName() === 'entity.node.content_translation_overview') {
      $variables['container_wrapper'] = TRUE;
    }
  }
}

/**
 * Prepares variables for the paragraph.
 */
function social_landing_page_preprocess_paragraph(&$variables) {

  /** @var \Drupal\paragraphs\Entity\Paragraph $entity */
  $entity = $variables['elements']['#paragraph'];
  $bundle = $entity
    ->bundle();
  switch ($bundle) {
    case 'hero':

      // Add the hero styled image.
      $image_style = 'social_landing_hero';
      $image_field = "field_{$bundle}_image";
      if ($entity
        ->hasField($image_field) && !empty($entity->{$image_field}->entity)) {
        $variables['hero_styled_image_url'] = ImageStyle::load($image_style)
          ->buildUrl($entity->{$image_field}->entity
          ->getFileUri());
      }
      break;
    case 'hero_small':

      // Add the hero styled image.
      $image_style = 'social_landing_hero_small';
      $image_field = "field_{$bundle}_image";
      if ($entity
        ->hasField($image_field) && !empty($entity->{$image_field}->entity)) {
        $variables['hero_small_styled_image_url'] = ImageStyle::load($image_style)
          ->buildUrl($entity->{$image_field}->entity
          ->getFileUri());
      }
      break;
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function social_landing_page_preprocess_node(&$variables) {

  /** @var \Drupal\node\Entity\Node $node */
  $node = $variables['node'];
  if ($node
    ->getType() === 'landing_page') {

    // If featured we need to do some magic.
    if ($variables['view_mode'] === 'featured') {
      $hero_image = _social_landing_page_get_hero_image($node);
      if (!empty($hero_image)) {
        $variables['content']['field_landing_page_image'] = [
          '#type' => 'markup',
          '#markup' => $hero_image,
        ];
      }
    }

    // Get current user.
    $account = \Drupal::currentUser();

    // Add node edit url for management.
    if ($node instanceof NodeInterface && $node
      ->access('update', $account)) {
      $variables['node_edit_url'] = $node
        ->toUrl('edit-form')
        ->toString();
    }

    // A landing page has a different way of determining this.
    $variables['no_image'] = FALSE;
    $image = _social_landing_page_get_hero_image($node);
    if (empty($image)) {
      $variables['no_image'] = TRUE;
    }
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function social_landing_page_preprocess_field(&$variables) {
  if ($variables['field_name'] === 'field_button_link_an' || $variables['field_name'] === 'field_button_link_lu') {
    $entity = $variables['element']['#object'];
    $button_style = $entity->field_button_style->value;
    foreach ($variables['items'] as $key => $value) {
      if (isset($variables['items'][$key]['content'])) {
        $variables['items'][$key]['content']['#options']['attributes'] = [
          'class' => 'btn btn-lg ' . $button_style,
        ];
      }
    }
  }
}

/**
 * Fetches the first available hero section image from a landing page.
 *
 * @param \Drupal\node\Entity\Node $node
 *   The landing page.
 *
 * @return array
 *   Render array of the image with a link.
 *
 * @throws \Drupal\Core\Entity\EntityMalformedException
 */
function _social_landing_page_get_hero_image(Node $node) {

  // Must be a valid node.
  if (!$node instanceof Node || $node
    ->getType() !== 'landing_page') {
    return [];
  }

  // Loop over the landing page sections of the landing page.
  foreach ($node
    ->get('field_landing_page_section') as $section) {

    // Get the referenced paragraph.
    $referenced = $section
      ->getValue();
    $paragraph_id = $referenced['target_id'];

    // First paragraph is always of type section.
    $paragraph_section = Paragraph::load($paragraph_id);

    // Get the related paragraph (the one with the actual content)
    $section_id = $paragraph_section
      ->get('field_section_paragraph')->target_id;
    $paragraph_content = Paragraph::load($section_id);

    // Must be of type hero.
    if ($paragraph_content && $paragraph_content
      ->getType() === 'hero') {
      $fid = $paragraph_content
        ->get('field_hero_image')->target_id;
      $file = File::load($fid);

      // Check if it's an existing file.
      if ($file instanceof File) {

        // Build an image render array.
        $image = [
          '#theme' => 'image_style',
          '#style_name' => 'social_featured',
          '#uri' => $file
            ->getFileUri(),
        ];

        // Build a link render array.
        $build = [
          '#title' => render($image),
          '#type' => 'link',
          '#url' => $node
            ->toUrl('canonical'),
        ];
      }

      // We immediately return the 1st found hero.
      return render($build);
    }
  }
  return [];
}

/**
 * Implements hook_social_user_account_header_create_links().
 *
 * Adds the "Create Landing Page" link to the content creation menu.
 */
function social_landing_page_social_user_account_header_create_links($context) {
  return [
    'add_landing_page' => [
      '#type' => 'link',
      '#attributes' => [
        'title' => new TranslatableMarkup('Create New Landing Page'),
      ],
      '#title' => new TranslatableMarkup('New Landing Page'),
      '#weight' => 400,
    ] + Url::fromRoute('node.add', [
      'node_type' => 'landing_page',
    ])
      ->toRenderArray(),
  ];
}

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function social_landing_page_theme_suggestions_page_alter(array &$suggestions, array $variables) {

  // Get Request Object.
  $request = \Drupal::request();

  // If there is HTTP Exception..
  if ($exception = $request->attributes
    ->get('exception')) {

    // Get the status code.
    $status_code = $exception
      ->getStatusCode();
    if ($status_code == 404) {
      $suggestions[] = 'page__node__landing_page';
    }
  }
}

/**
 * Implements hook_social_core_compatible_content_forms_alter().
 */
function social_landing_page_social_core_compatible_content_forms_alter(&$compatible_content_type_forms) {
  $compatible_content_type_forms[] = 'node_landing_page_form';
  $compatible_content_type_forms[] = 'node_landing_page_edit_form';
}