これまでのところ、私は次のことをしました:
hook_redirect_response_alter
を実装するためにRedirectモジュールのパッチを適用しました。次のhook_redirect_response_alter
を トークンのサポートと解析 に定義しました。
use Drupal\redirect\Entity\Redirect;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Component\Utility\UrlHelper;
/**
* Implements hook_redirect_response_alter().
*/
function MYMODULE_redirect_response_alter(RedirectResponse $response, Redirect $redirect) {
$uri = $redirect->getRedirect()['uri']; // "internal:/bar/[current-page:url:args:last]"
if (!empty($uri) && strpos($uri, '[') !== FALSE) {
$uri = \Drupal::token()->replace($uri); // "internal:/bar/"
$external = UrlHelper::isValid($uri, TRUE); // bool
$redirect->setRedirect($external ? $uri : explode('/', $uri, 2)[1]);
$response->setTargetUrl($redirect->getRedirectUrl()->setAbsolute()->toString()); // "http://localhost/bar/"
}
}
/admin/config/search/redirect
に次のリダイレクトを追加しました:
foo/*
/bar/[current-page:url:args:last]
上記に基づいて、foo/X
を入力するとbar/X
にリダイレクトされ、それに応じてfoo/Y
をbar/Y
にリダイレクトすることを期待しています。ただし、上記のトークンは空の文字列に置き換えられます。 [current-page:url:args:value:2]
などのトークンを使用する場合も同様ですが、トークンはまったく置き換えられません。トークンもエンティティタイプに基づいて生成されるので、[redirect:url:args:last]
を使用しても機能しないことを here も学んだので、Redirectモジュールはそれを認識していません。
パスから2番目の引数を抽出できる可能性がある/admin/help/token
で見つかったいくつかのトークンを試してみましたが、このタスクに適した、または期待どおりに機能していないことがわかりました。
例えば:
コメントで提案されているように、トークンのreplace()
メソッドに$redirect
コンテキストを適用すると、期待どおりに機能しませんでした。
したがって、次の行:
$uri = \Drupal::token()->replace($uri, ['redirect' => $redirect]);
トークンにredirect
接頭辞を入力しますが、現在のパスを誤って置き換えます。 [redirect:url:args:join:/]
は、すべてのページでadmin/config/search/redirect/edit/25
になります。
current-page
トークンのコンテキストを設定しようとしましたが、現在のパスが存在する必要がありますが、リダイレクト中に現在のパスがメニュールーティングテーブルに存在しないため、ロードできません( Url::createFromRequest()
と\Drupal::request()
を試しました。
何が欠けていますか?同じことを達成する簡単な方法はありますか?
トークンのreplace
メソッドのコンテキストを渡すことが期待どおりに機能しなかったため、カスタムモジュールに新しいトークンを定義して、Drupalパスの特定のコンポーネントを返します(次の ガイド )。
my_redirect.tokens.inc
<?php
/**
* @file
* An include file defining custom tokens.
*/
use Drupal\Core\Render\BubbleableMetadata;
/**
* Implements hook_token_info().
*/
function my_redirect_token_info() {
$type = [
'name' => t('Custom URL token for redirect'),
'description' => t('Tokens helpful for redirect pages.'),
];
$node['url-arg'] = [
'name' => t("URL Argument"),
'dynamic' => TRUE,
'description' => t('Returns a component of the current Drupal path.'),
];
return [
'types' => ['my_redirect' => $type],
'tokens' => ['my_redirect' => $node],
];
}
/**
* Implements hook_tokens().
*/
function my_redirect_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
$replacements = [];
if ($type == 'my_redirect') {
if ($argTokens = \Drupal::token()->findWithPrefix($tokens, 'url-arg')) {
foreach ($argTokens as $arg => $original) {
$current_path = \Drupal::service('path.current')->getPath();
if ($arg === "first") {
$value = explode('/', $current_path)[1];
}
elseif ($arg === "last") {
$value = end(explode('/', $current_path));
}
else {
$value = explode('/', $current_path)[$arg ?: 0];
}
$replacements[$original] = $value;
}
}
}
return $replacements;
}
したがって、すでに述べたパッチと上記のコードを適用した後、次のリダイレクトルールを使用できます。
foo/*
/bar/[my_redirect:url-arg:2]