web-dev-qa-db-ja.com

移行:更新の移行後にurl_aliasのエントリが重複する

Wprdpressからdrupal 8(pathauto module enabled)への用語とノードの移行があります。移行テンプレートのURLエイリアスを次のように設定します:

process:
  path/alias: source_path
  path/pathauto:
    plugin: default_value
    default_value: 0

そのようにパスを設定すると、drush mi termを使用してコンテンツをインポートするときにうまく機能します。しかし、用語をdrush mi term --updateで更新すると、新しい(同じ)パスがurl_aliasテーブルに挿入されます。たとえば、tid 1の用語は1回インポートされ、2回更新されます。url_aliasテーブルには次のエイリアスがあります。

select * from url_alias where source = '/taxonomy/term/1';
+------+------------------+---------------+----------+
| pid  | source           | alias         | langcode |
+------+------------------+---------------+----------+
| 1514 | /taxonomy/term/1 | /term-1-alias | de       |
| 2731 | /taxonomy/term/1 | /term-1-alias | de       |
| 3632 | /taxonomy/term/1 | /term-1-alias | de       |
+------+------------------+---------------+----------+

ところで、pathautoモジュールを有効にしていますが、アンインストールしても同じ動作になります。

2
LarS

コアパスモジュールのバグのようです: https://www.drupal.org/node/2350135

2
Mike Ryan

この問題を回避するために、次の回避策を講じました。

$ value /ノードの組み合わせに対してurl_aliasレコードがすでに挿入されているかどうかをチェックするカスタムプロセスプラグインを作成します。そうであればNULLを返し、そうでなければ$ valueを返します。

<?php
/**
 * @file
 * Contains \Drupal\your_migrate_module\Plugin\migrate\process\EmptyIfUrlAliasExists.
 *
 */

namespace Drupal\your_migrate_module\Plugin\migrate\process;

use Drupal\Core\Database\Database;
use Drupal\migrate\Annotation\MigrateProcessPlugin;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;

/**
 * This process plugin can be used for path/alias fields as long as the following issues are not resolved. It is a workaround for:
 *
 * https://www.drupal.org/node/2350135#comment-9476629
 * https://drupal.stackexchange.com/questions/238393/migrate-duplicate-entries-in-url-alias-after-update-migrations)
 *
 * @MigrateProcessPlugin(
 *   id = "empty_if_url_alias_exists",
 * )
 */
class EmptyIfUrlAliasExists extends ProcessPluginBase
{
    /**
     * {@inheritdoc}
     */
    public function transform(
        $value,
        MigrateExecutableInterface $migrate_executable,
        Row $row,
        $destination_property
    ) {
        // Retrieves a \Drupal\Core\Database\Connection which is a PDO instance
        $db = Database::getConnection();

        $sth = $db->select('url_alias', 'u')
            ->fields('u', ['pid']);
        $and = $sth->andConditionGroup()
            ->condition('u.source', '/node/' . $row->getIdMap()['destid1'])
            ->condition('u.alias', $value);
        $sth->condition($and);
        $data = $sth->execute();

        $results = $data->fetch(\PDO::FETCH_NUM);

        //when no url_alias record found, return the url, so it can be added.
        if ($results === false || count($results) === 0) {
            return $value;
        }
        //when an url_alias record is already present, return null, so the migration does not add it again
        return null;
    }
}

次に、ノード移行ymlのプロセス部分で、以下を使用します。

process:
  'path/pathauto': 
     plugin: default_value
     default_value: 0 # Disable pathauto.
  'path/alias':
    -
      plugin: empty_if_url_alias_exists
      source: public_url
    -
      plugin: skip_on_empty
      method: process
1
mvbaalen