murmurations-1.0.0-alpha1/murmurations.module

murmurations.module
<?php

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\murmurations\Plugin\Murmurations\PluginMultipleBase;
use Drupal\murmurations\MurmurationsPluginInterface;
use Drupal\murmurations\MurmurationsPluginMultipleInterface;

/**
 * @todo remind user after installation to set the index url
 */

/**
 * Implements hook_ENTITY_TYPE_insert().
 */
function murmurations_entity_insert(EntityInterface $entity) {
  $plugin_manager = \Drupal::service('plugin.manager.murmurations');
  if ($plugin = $plugin_manager->getByEntityType($entity->getEntityTypeId())) {
    /** @var $plugin Drupal\murmurations\MurmurationsPluginMultipleInterface */
    if ($plugin->setEntity($entity)->publishable()) {
      $publish_path = $plugin->getPublishPath();
      if (!\Drupal::service('murmurations.index')->reindex($publish_path)) {
        \Drupal::messenger()->AddStatus('Item will be indexed later.');
        \Drupal::queue('murmurations_update_index')->createItem($publish_path);
      }
    }
  }
}

/**
 * Implements hook_ENTITY_TYPE_update().
 */
function murmurations_entity_update(EntityInterface $entity) {
  $plugin_manager = \Drupal::service('plugin.manager.murmurations');
  if ($plugin = $plugin_manager->getByEntityType($entity->getEntityTypeId())) {
    /** @var $plugin Drupal\murmurations\MurmurationsPluginMultipleInterface */
    if ($plugin->setEntity($entity)->publishable()) {
      $publish_path = $plugin->getPublishPath();
      if (!\Drupal::service('murmurations.index')->reindex($publish_path)) {
        \Drupal::queue('murmurations_update_index')->createItem($publish_path);
      }
    }
  }
}

/**
 * Implements hook_ENTITY_TYPE_delete().
 * Murmurations index will forget the item anyway when the profile_url returns a 404.
 */
function murmurations_entity_predelete(EntityInterface $entity) {
  $plugin_manager = \Drupal::service('plugin.manager.murmurations');
  if ($plugin = $plugin_manager->getByEntityType($entity->getEntityTypeId())) {
    // @todo check if the entity is indexed.
    $plugin->setEntity($entity);
    if ($plugin instanceOf PluginMultipleBase and !$plugin->publishable()) {
      return;
    }
    try {
      \Drupal::service('murmurations.index')->deindex($plugin->getPublishPath());
    }
    catch (\Exception $e) {

    }
  }
}

/**
 * Add reindex jobs to the drupal queue.
 *
 * @param array $rel_paths
 *
 * @todo How to process some of these queue items immediately?
 */
function murmurations_queue_items(array $rel_paths) {
  $queue = \Drupal::queue('murmurations_update_index');
  foreach ($rel_paths as $rel_path) {
    $queue->createItem($rel_path);
  }
}

/**
 * Helper to move a point randomly
 *
 * @param array $point
 *   An array with keys 'lat' and 'lon'
 * @param integer $scale
 *   1/1000s of a degree range of variation.
 */
function displace_point(array $point, $scale) : array {
  if ($point['lat']) {
    foreach ([$point['lat'], $point['lon']] as &$val) {
      $offset = rand(2, 7)* 0.001*$scale;
      if (rand(0, 1)) {
        $offset = -$offset;
      }
      $val += $offset;
    }
  }
  return $point;
}

/**
 * not sure about this.
 */
function murmurations_theme() {
  return [
    'murm_search_result_text' => [
      'pattern' => 'murm_search_result_text__',
      'variables' => [
        'title' => '',
        'body' => '',
        'url' => '',
        'tags' => '', // Might be better as an array
        'distance' => 0
      ]
    ],
    'murm_search_result_map' => [
      'pattern' => 'murm_search_result_map__',
      'variables' => [
        'title' => '',
        'body' => '',
        'url' => '',
        'tags' => '',
      ]
    ]
  ];
}

/**
 * Implements hook_entity_access().
 * Ensure all entities exposed by murmurations are visible to anonymous users.
 */
function murmurations_entity_access(\Drupal\Core\Entity\EntityInterface $entity, $operation) {
  $result = AccessResult::neutral();
  if ($operation == 'view' and $entity instanceOf Drupal\Core\Entity\ContentEntityInterface) {
    if ($plugin = \Drupal::service('plugin.manager.murmurations')->getByEntityType($entity->getEntityTypeId())) {
      if (in_array($entity->id(), $plugin->getEntityIds())) {
        $result = AccessResult::allowed()->addCacheableDependency($entity);
      }
    }
  }
  return $result;
}

/**
 * Identify a geofield on the entity and return it as lat and lon.
 *
 * @param ContentEntityInterface $entity
 * @return array
 *   with keys lat, lon
 */
function murmurations_geolocate_entity_with_fallback(ContentEntityInterface $entity) : array {
  if ($coords = murmurations_entity_field_type_value($entity, 'geofield')) {
    return array_intersect_key($coords, array_flip(['lat', 'lon']));
  }
  return \Drupal::config('murmurations.settings')->get('fallback_point');
}

/**
 * Get the first value on a field of the given type on the given entity.
 *
 * @param \Drupal\user\EntityOwnerInterface $entity
 * @param string $field_type
 * @return array
 */
function murmurations_entity_field_type_value(ContentEntityInterface $entity, $field_type) : array {
  if ($field_name = murmurations_get_fieldname_of_entitytype($entity, $field_type)) {
    $field_items = $entity->{$field_name};
    if (!$field_items->isEmpty()) {
      return $field_items[0]->getValue(); // using arrayAccess on FieldItemList
    }
  }
  if ($entity instanceof \Drupal\user\EntityOwnerInterface) {
    return murmurations_entity_field_type_value($entity->getOwner(), $field_type);
  }
  \Drupal::logger('murmurations')->error(
    "No @type field on @entity_type @bundle",
    ['@type' => $field_type, '@entity_type' => $entity->getEntityTypeId(), '@bundle' => $entity->bundle()]
  );
  return [];
}

/**
 * Get a field name of the given type on the given entity
 * @param ContentEntityInterface $entity
 * @param string $type_name
 * @return string
 */
function murmurations_get_fieldname_of_entitytype(ContentEntityInterface $entity, $type_name) : string {
  $fields = \Drupal::service('entity_field.manager')
    ->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle());
  foreach ($fields as $field_name => $field_info) {
    if ($field_info->getType() == $type_name) {
      return $field_name;
    }
  }
  return '';
}

/**
 * Immediately remove all items from the index.
 * @throws \Exception
 */
function murmurations_deindex_all() {
  // Can't we just load all plugins?
  $murm_plugins = \Drupal::service('plugin.manager.murmurations');
  foreach ($murm_plugins->getDefinitions() as $plugin_id => $def) {
    $plugin = $murm_plugins->createInstance($plugin_id);
    $batch_def = [
      'title' => 'deindexing everything on the currency murms index',
      'operations' => \Drupal::Service('murmurations.index')->deindexPlugin($plugin)
    ];
    batch_set($batch_def);
//    catch (\Exception $e){
//      Drupal::messenger()->warning(
//        t('There was a problem immediately removing @plugin items from the index: @message'),
//        ['@plugin' => $plugin_id, '@message' => $e->getMessage()]
//      );
//      throw $e;
//    }
  }
}



/**
 * @param MurmurationsPluginInterface $plugin
 *
 * @return array[]
 *   Batch operations
 */
function murmurations_deindex_plugin_operations(MurmurationsPluginInterface $plugin) : array {
  $operations = [];
  if ($plugin instanceof MurmurationsPluginMultipleInterface) {
    foreach (array_chunk($plugin->getEntityIds(), 5) as $ids) {
      foreach ($ids as $id) {
        $profile_path = preg_replace('/\{[a-z]+\}/', $id, $plugin->getPluginDefinition()['profile_path']);
        $profile_paths[] = $profile_path;

      }
      $operations[] = ['murmurations_deindex_chunk', [$profile_paths]];
    }
  }
  else {
    $profile_path = $plugin->getPluginDefinition()['profile_path'];
    $operations[] = ['murmurations_deindex_chunk', [[$profile_path]]];
  }
  return $operations;
}

/**
 * @param MurmurationsPluginInterface $plugin
 *
 * @return array[]
 *   Batch operations
 */
function murmurations_reindex_plugin_operations(MurmurationsPluginInterface $plugin) {
  $operations = [];
  if ($plugin instanceof MurmurationsPluginMultipleInterface) {
    foreach (array_chunk($plugin->getEntityIds(), 5) as $ids) { // 5x5sec timeout < 30 secs php timeout.
      foreach ($ids as $id) {
        $profile_path = preg_replace('/\{[a-z]+\}/', $id, $plugin->getPluginDefinition()['profile_path']);
        $profile_paths[] = $profile_path;

      }
      $operations[] = ['murmurations_reindex_chunk', [$profile_paths, TRUE]];
    }
  }
  else {
    $profile_paths = [$plugin->getPluginDefinition()['profile_path']];
    $operations[] = ['murmurations_reindex_chunk', [$profile_paths, TRUE]];
  }
  return $operations;
}

/**
 * Batch callback.
 * @param array $profile_rel_urls
 */
function murmurations_deindex_chunk(array $profile_rel_urls) {
  $service = \Drupal::service('murmurations.index');
  foreach ($profile_rel_urls as $url) {
    $service->deindex($url);
  }
}

/**
 * Batch callback.
 * @param array $profile_rel_urls
 */
function murmurations_reindex_chunk(array $profile_rel_urls, bool $drop_on_fail = FALSE) {
  $service = \Drupal::service('murmurations.index');
  foreach ($profile_rel_urls as $url) {
    try {
      $service->reindex($url);
    }
    catch(\Exception $e) {
      if (!$drop_on_fail) {
        \Drupal::messenger('There was a problem reindexing. The system will retry later.');
        murmurations_queue_items($profile_rel_urls);
        return;
      }
    }
  }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc