Во время миграции нередко возникает необходимость перенести пользователей вместе с паролями. Конечно всегда можно сбросить их и пользователи всегда смогут создать их заново, но отчего бы не попробовать сохранить эти данные.

name: FooBar
description: FooBar functionality
package: FooBar
type: module
core: 8.x
version: 8.x-1.0

dependencies:
  - migrate
  - migrate_plus

Источником пользователей у нас выступает таблица users базы migrate. Для чего в settings.php необходимо добавить новое подключение.

settings.php

$databases['migrate']['default'] = array (
  'database' => 'database',
  'username' => 'username',
  'password' => 'password',
  'prefix' => '',
  'host' => '127.0.0.1',
  'port' => '3306',
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver' => 'mysql',
);

Теперь конфигурация плагина. Проще простого.

migrate_plus.migration.foobar_user.yml

id: foobar_user
label: Migrate user
source:
  plugin: foobar_user
  target: migrate
process:
  name: name
  mail: mail
  pass: pass
  status:
    plugin: default_value
    default_value: 1
destination:
  plugin: entity:user
migration_dependencies: {}

А вот для написания плагина понадобится чуть больше кода.

User.php

  public function fields() {
    return [
      'name',
      'pass',
      'mail',
      'uid'
    ];
  }

  public function getIds() {
    return ['uid' => ['type' => 'integer']];
  }

  public function prepareRow(Row $row) {
    $pass = $row->getSourceProperty('pass');
    $row->setSourceProperty('pass', 'F$' . $pass);
    return parent::prepareRow($row);
  }

  public function query() {
    return $this->select('users', 'u')
      ->fields('u', $this->fields());
  }

Ничего сложного, но для того, чтоб выделить мигрированный пароль, к нему добавляется префикс F$.

Включим наш модуль и запустим миграцию.

drush en foobar
drush mim foobar_user

Можно убедиться, что в базе данных были созданы новые пользователи и их пароли соответствуют старым с нашим префиксом. Однако залогинится со старым паролем нам неудасться, потому что система аутентификации Друпал ничего про это не знает. Чтобы это исправить, мы создадим свой сервис проверки пароля взамен существующего.

services.yml

services:
  password:
    class: Drupal\foobar\Password\FoobarHashedPassword
    arguments: [16]

FoobarHashedPassword.php

  protected function goodOldHash($password) {
    return md5($password);
  }

  public function check($password, $hash) {
    if (substr($hash, 0, 2) == 'F$') {
      return 'F$' . $this->goodOldHash($password) === $hash;
    }
    return parent::check($password, $hash);
  }
}

Файлы