You are here

social_search.module in Open Social 8.9

The Social search module.

File

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

/**
 * @file
 * The Social search module.
 */
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\group\Entity\GroupType;
use Drupal\profile\Entity\Profile;
use Drupal\search_api\Entity\Index;
use Drupal\search_api\Plugin\search_api\datasource\ContentEntity;
use Drupal\user\Entity\User;

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Enhance the Views exposed filter blocks forms.
 */
function social_search_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $filter_forms = [
    'views-exposed-form-search-content-page',
    'views-exposed-form-search-groups-page',
    'views-exposed-form-search-users-page',
  ];
  if (in_array($form['#id'], $filter_forms, TRUE)) {

    // Always enable the reset button.
    $form['actions']['reset']['#access'] = TRUE;
    $form['#attached']['library'][] = 'social_search/search_filters';
    switch ($form['#id']) {
      case 'views-exposed-form-search-users-page':
        social_search_alter_users_exposed_filter_block($form, $form_state, $form_id);
        break;
      case 'views-exposed-form-search-groups-page':
        social_search_alter_groups_exposed_filter_block($form, $form_state, $form_id);
        break;
      case 'views-exposed-form-search-content-page':
        social_search_alter_content_exposed_filter_block($form, $form_state, $form_id);
        break;
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Makes changes for the filter block on the user search page.
 */
function social_search_alter_users_exposed_filter_block(&$form, FormStateInterface $form_state, $form_id) {
  foreach ($form as &$element) {
    if (is_array($element) && isset($element['#type']) && $element['#type'] === 'entity_autocomplete') {
      $element['#selection_settings']['hide_id'] = TRUE;
    }
  }
  if (!empty($form['created']) && !empty($form['created_op'])) {
    $form['settings']['created_op'] = $form['created_op'];
    $form['settings']['created'] = $form['created'];
    unset($form['created_op'], $form['created']);
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Makes changes for the filter block on the groups search page.
 */
function social_search_alter_groups_exposed_filter_block(&$form, FormStateInterface $form_state, $form_id) {
  $options = [
    '' => t('- Any -'),
  ];
  $group_types = GroupType::loadMultiple();

  /** @var \Drupal\group\Entity\GroupType $group_type */
  foreach ($group_types as $group_type) {
    $options[$group_type
      ->id()] = $group_type
      ->label();
  }
  $form['type'] = [
    '#type' => 'select',
    '#options' => $options,
  ];
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Makes changes for the filter block on the content search page.
 */
function social_search_alter_content_exposed_filter_block(&$form, FormStateInterface $form_state, $form_id) {
  if (!empty($form['type'])) {
    $form['type']['#weight'] = '-100';
  }
  if (!empty($form['field_event_date']) && !empty($form['field_event_date_op'])) {
    if (!empty($form['settings'])) {
      $form['settings']['#states'] = [
        'visible' => [
          ':input[name=type]' => [
            'value' => 'event',
          ],
        ],
      ];
      $form['settings']['#weight'] = '-99';
      $form['settings']['#attributes']['class'] = [
        'indent_filter',
      ];
    }
    $form['settings']['field_event_date_op'] = $form['field_event_date_op'];
    $form['settings']['field_event_date'] = $form['field_event_date'];
    unset($form['field_event_date'], $form['field_event_date_op']);
  }
  if (!empty($form['location_details'])) {
    $form['location_details']['#weight'] = '-98';
    $form['location_details']['#attributes']['class'] = [
      'indent_filter',
    ];
  }

  // When combined sorting and filtering is used we make some changes to
  // accommodate theming.
  if (isset($form['sort_bef_combine'])) {

    // Ensure the sort option shows up at the top.
    $form['sort_bef_combine']['#weight'] = -9999;

    // From a UX perspective it doesn't make sense to show the least relevant
    // results first so we remove this sorting option.
    if (isset($form['sort_bef_combine']['#options']['search_api_relevance ASC'])) {
      unset($form['sort_bef_combine']['#options']['search_api_relevance ASC']);
    }

    // We attach custom CSS so that we can properly translate the filter title.
    // This selector should match the value in sort_filter.css of this module.
    // Use a useless variable to trick phpcs from giving us invalid warnings.
    $translated_filter = t('Filter');
    $form['social_search_translated_filter_string'] = [
      '#type' => 'html_tag',
      '#tag' => 'style',
      '#attributes' => [
        'type' => 'text/css',
      ],
      '#value' => "#block-filter .form-item-sort-bef-combine:after { content: '{$translated_filter}'; }",
    ];
  }
}

/**
 * Implements hook_block_view_BASE_BLOCK_ID_alter().
 *
 * Enhance the Views exposed filter blocks.
 */
function social_search_block_view_views_exposed_filter_block_alter(array &$build, BlockPluginInterface $block) {
  $filter_blocks = [
    'search_content-page',
    'search_groups-page',
    'search_users-page',
  ];
  if (in_array($build['#derivative_plugin_id'], $filter_blocks)) {

    // Disable cache for exposed filter block to get correct current path,
    // which is used in $form['#action'].
    $build['#cache'] = [
      'max-age' => 0,
    ];
  }
}

/**
 * Implements hook_views_data_alter().
 */
function social_search_views_data_alter(array &$data) {

  // Custom Event Date filters see SocialDate.php.
  $data['node']['social_date_filter'] = [
    'title' => t('Date Filter by Open Social'),
    'filter' => [
      'title' => t('Date Filter by Open Social'),
      'help' => t('Filters for date used in Open Social'),
      'id' => 'social_date_filter',
      'field' => 'field_event_date_value',
    ],
  ];
  $data['node']['social_created_filter'] = [
    'title' => t('Created Date Filter by Open Social'),
    'filter' => [
      'title' => t('Date Filter by Open Social'),
      'help' => t('Filters for date used in Open Social'),
      'id' => 'social_date_filter',
      'field' => 'created',
    ],
  ];
}

/**
 * Implements hook_search_api_views_handler_mapping_alter().
 */
function social_search_search_api_views_handler_mapping_alter(array &$mapping) {

  // Override the Search API views filter connected to date with
  // SocialDate.php (Extends current one limits options).
  $mapping['date']['filter']['id'] = 'social_date_filter';
}

/**
 * Implements hook_block_view_BASE_BLOCK_ID_alter().
 *
 * Make the label/title translatable.
 */
function social_block_view_search_hero_block_alter(array &$build, BlockPluginInterface $block) {
  $build['#configuration']['label'] = t('Search');
}

/**
 * Implements hook_ENTITY_TYPE_update().
 *
 * Update the profile index when user is updated or delete entry when blocked.
 */
function social_search_user_update(EntityInterface $entity) {

  /** @var \Drupal\user\Entity\User $entity */
  _social_search_retrigger_profile($entity);
}

/**
 * Retriggers the profile in the search when a user has ben changed.
 *
 * @param \Drupal\user\Entity\User $user
 *   The user whose profile we want to retrigger.
 */
function _social_search_retrigger_profile(User $user) {

  // These indices need to be updated.
  $indexes = [
    'social_all',
    'social_users',
  ];
  try {

    /** @var \Drupal\profile\ProfileStorage $profile_storage */
    $profile_storage = \Drupal::entityTypeManager()
      ->getStorage('profile');
  } catch (InvalidPluginDefinitionException $e) {
    return;
  } catch (PluginNotFoundException $e) {
    return;
  }

  /** @var \Drupal\profile\Entity\Profile $profile */
  $profile = $profile_storage
    ->loadByUser($user, 'profile');

  // Must be a profile, otherwise we can leave.
  if (!$profile instanceof Profile) {
    return;
  }

  // Loop over the indexes that need to be updated.
  foreach ($indexes as $index_id) {
    $index = Index::load($index_id);
    if ($index instanceof Index) {

      // Init.
      $profile_ids = [];

      /** @var \Drupal\user\Entity\User $original_user */
      $original_user = $user->original;
      foreach ($profile
        ->getTranslationLanguages() as $langcode => $language) {
        $profile_ids[] = $profile
          ->id() . ':' . $langcode;
      }
      $datasource_id = 'entity:profile';
      if ($user
        ->isBlocked() && $original_user
        ->isActive()) {
        $index
          ->trackItemsDeleted($datasource_id, $profile_ids);
      }
      elseif ($user
        ->isActive() && $original_user
        ->isBlocked()) {
        $filtered_item_ids = ContentEntity::filterValidItemIds($index, $datasource_id, $profile_ids);
        $index
          ->trackItemsInserted($datasource_id, $filtered_item_ids);
      }
      else {
        $index
          ->trackItemsUpdated($datasource_id, $profile_ids);
      }
    }
  }
}

/**
 * Re-saves search indices.
 *
 * This triggers the save for all search indexes which triggers updates of
 * fields and processors.
 *
 * @param array $index_ids
 *   An array of index IDs to re-save or NULL to re-save all indices.
 *
 * @throws \Drupal\Core\Entity\EntityStorageException
 */
function social_search_resave_search_indexes(array $index_ids = NULL) {

  // We load all indexes, we assume there will never be hundreds of search
  // indexes which would create its own problems for a site.
  $indexes = Index::loadMultiple($index_ids);

  /** @var \Drupal\search_api\IndexInterface $index */
  foreach ($indexes as $index) {

    // No need to disable and enable the index here, this worked around a
    // validation of the Search Settings form that prevented the save from being
    // triggered. However, this validation is not present in the entity save
    // logic. So a simple call to `save()` will trigger the reprocessing of
    // fields and processors.
    $index
      ->save();
  }
}