usebb2drupal-8.x-1.0-rc1/src/UseBBUrlTranslator.php

src/UseBBUrlTranslator.php
<?php

namespace Drupal\usebb2drupal;

use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
use Drupal\Core\Entity\Query\QueryFactory;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Database\Query\AlterableInterface;

/**
 * UseBB URL translator service class.
 */
class UseBBUrlTranslator implements UseBBUrlTranslatorInterface {
  protected $info;
  protected $migrationManager;
  protected $database;
  protected $queryFactory;
  protected $entityTypeManager;

  /**
   * {@inheritdoc}
   */
  public function __construct(UseBBInfoInterface $info, MigrationPluginManagerInterface $migration_manager, Connection $database, QueryFactory $query_factory, EntityTypeManagerInterface $entity_type_manager) {
    $this->info = $info;
    $this->migrationManager = $migration_manager;
    $this->database = $database;
    $this->queryFactory = $query_factory;
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function execute($migration_id, array &$context) {
    switch ($migration_id) {
      case 'usebb_forum':
        $entity_type = 'taxonomy_term';
        $field_name = 'description.value';
        break;

      case 'usebb_topic':
        $entity_type = 'node';
        $field_name = 'body.value';
        break;

      case 'usebb_post':
        $entity_type = 'comment';
        $field_name = 'comment_body.value';
        break;

      case 'usebb_user':
        $entity_type = 'user';
        $field_name = 'signature.value';
        break;

      default:
        return;
    }
    if (empty($context['sandbox'])) {
      $context['sandbox']['entity_ids'] = $this->getQuery($migration_id, $entity_type, $field_name)->execute();
      $context['sandbox']['progress'] = 0;
      $context['sandbox']['max'] = count($context['sandbox']['entity_ids']);
    }
    if (empty($context['sandbox']['entity_ids'])) {
      $context['finished'] = 1;
      return;
    }
    $storage = $this->entityTypeManager->getStorage($entity_type);
    $processed = 0;
    foreach ($storage->loadMultiple($context['sandbox']['entity_ids']) as $entity_id => $entity) {
      $this->updateEntity($entity, $field_name);
      $processed++;
      $context['sandbox']['progress']++;
      unset($context['sandbox']['entity_ids'][$entity_id]);
      if ($processed === 15) {
        $context['message'] = t('Translating internal links in @type @progress of @max.', [
          '@type' => str_replace(['usebb_', '_'], ['', ' '], $migration_id),
          '@progress' => $context['sandbox']['progress'],
          '@max' => $context['sandbox']['max'],
        ]);
        break;
      }
    }
    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
  }

  /**
   * Create a query against the database for contents with untranslated links.
   *
   * @param string $migration_id
   *   Migration ID.
   * @param string $entity_type
   *   Entity type.
   * @param string $field_name
   *   Field to query for URLs.
   *
   * @return Drupal\Core\Entity\Query\QueryInterface
   *   Query.
   */
  protected function getQuery($migration_id, $entity_type, $field_name) {
    $query = $this->queryFactory->get($entity_type);
    $group = $query->orConditionGroup();
    foreach ($this->info->getPublicUrls() as $url) {
      $group->condition($field_name, '%' . $this->database->escapeLike('<a href="' . $url) . '%', 'LIKE');
    }
    return $query->condition($group)
      ->addTag('usebb2drupal_url_translator')
      ->addMetaData('usebb2drupal_migration', $migration_id);
  }

  /**
   * {@inheritdoc}
   */
  public function alterQuery(AlterableInterface $query) {
    $migration = $this->getMigrationInstance($query->getMetaData('usebb2drupal_migration'));
    $id_map_table = $migration->getIdMap()->mapTableName();
    $destid = 1;
    $join_condition = [];
    foreach (array_keys($migration->getDestinationPlugin()->getIds()) as $destination_id) {
      $field = $query->getFields()[$destination_id];
      $join_condition[] = $field['table'] . '.' . $field['field'] . ' = migrate_map.destid' . $destid++;
    }
    $query->join($id_map_table, 'migrate_map', implode(' AND ', $join_condition));
  }

  /**
   * Update URLs in an entity.
   *
   * @param Drupal\Core\Entity\EntityInterface $entity
   *   Entity to update.
   * @param string $field_name
   *   Field name containing URLs.
   */
  protected function updateEntity(EntityInterface $entity, $field_name) {
    $entity->usebb_changed = clone $entity->changed;
    if (strpos($field_name, '.') !== FALSE) {
      list($field_name, $property) = explode('.', $field_name, 2);
      $value = $this->translateUrls($entity->$field_name->$property);
      $entity->$field_name->$property = $value;
    }
    else {
      $value = $this->translateUrls($entity->$field_name);
      $entity->$field_name = $value;
    }
    $entity->save();
  }

  /**
   * Translate URLs in a string.
   *
   * @param string $string
   *   String to translate URLs in.
   *
   * @return string
   *   String with updates URLs.
   */
  protected function translateUrls($string) {
    foreach ($this->info->getPublicUrls() as $url) {
      $url = preg_quote($url, '#');
      $string = preg_replace_callback('#<a href="(' . $url . '([^"]*))">(\1</a>)?#', function ($matches) {
        if ($new_path = $this->translatePath($matches[2])) {
          $new_url = base_path() . $new_path;
          return !empty($matches[3])
            ? '<a href="' . $new_url . '">' . $new_path . '</a>'
            : '<a href="' . $new_url . '">';
        }
        return $matches[0];
      }, $string);
    }
    return $string;
  }

  /**
   * Translate UseBB path to Drupal.
   *
   * @param string $path
   *   UseBB path to translate.
   *
   * @return string|null
   *   Drupal migrated path or NULL when not found.
   */
  protected function translatePath($path) {
    // Category.
    if ((preg_match('#^/index\-([0-9]+)\.html?#', $path, $matches) || preg_match('#^/index\.php\?cat=([0-9]+)#', $path, $matches))
        && ($id = $this->getMigratedId('category', $matches[1]))) {
      return 'forum/' . $id;
    }
    // Forum.
    if ((preg_match('#^/forum\-([0-9]+)(\-[0-9]+)?\.html?#', $path, $matches) || preg_match('#^/forum\.php\?id=([0-9]+)(&page=[0-9]+)?#', $path, $matches))
        && ($id = $this->getMigratedId('forum', $matches[1]))) {
      return 'forum/' . $id;
    }
    // Topic.
    if ((preg_match('#^/topic\-([0-9]+)(\-[0-9]+)?\.html?#', $path, $matches) || preg_match('#^/topic\.php\?id=([0-9]+)(&page=[0-9]+)?#', $path, $matches))
        && ($id = $this->getMigratedId('topic', $matches[1]))) {
      return 'node/' . $id;
    }
    // Post.
    if (preg_match('#^/topic\-post([0-9]+)\.html?#', $path, $matches) || preg_match('#^/topic\.php\?post=([0-9]+)#', $path, $matches)) {
      // Post that was migrated to a comment.
      if ($id = $this->getMigratedId('post', $matches[1])) {
        return 'comment/' . $id . '#comment-' . $id;
      }
      // First post included in a topic row and not migrated to a comment.
      if (($topic_id = $this->info->getTopicFromPost($matches[1])) && ($id = $this->getMigratedId('topic', $topic_id))) {
        return 'node/' . $id;
      }
    }
    // Profile.
    if ((preg_match('#^/profile\-([0-9]+)\.html?#', $path, $matches) || preg_match('#^/profile\.php\?id=([0-9]+)#', $path, $matches))
        && ($id = $this->getMigratedId('user', $matches[1]))) {
      return 'user/' . $id;
    }
    // Forum index.
    if (empty($path) || $path === '/' || preg_match('#^/index\.(html|php)#', $path)) {
      return 'forum';
    }
    return NULL;
  }

  /**
   * Get the migrated (destination) ID for a migration row.
   *
   * @param string $migration_id
   *   Migration ID without `usebb_`.
   * @param int $source_id
   *   Source ID.
   *
   * @return int|null
   *   Migrated (destination) ID or NULL when not found.
   */
  protected function getMigratedId($migration_id, $source_id) {
    $ids = $this->getMigrationInstance('usebb_' . $migration_id)->getIdMap()
      ->lookupDestinationId([(int) $source_id]);
    if (empty($ids)) {
      return NULL;
    }
    return (int) reset($ids);
  }

  /**
   * Load a migration plugin instance.
   *
   * @param string $migration_id
   *   Migration ID.
   *
   * @return \Drupal\migrate\Plugin\MigrationInterface
   *   Migration plugin instance.
   */
  protected function getMigrationInstance($migration_id) {
    static $instances = [];
    if (!isset($instances[$migration_id])) {
      $instances[$migration_id] = $this->migrationManager->createInstance($migration_id);
    }
    return $instances[$migration_id];
  }

}

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

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