web-dev-qa-db-ja.com

Drupal 8)でプログラムで現在のパスを変更および書き換える方法

これが私が達成しようとしていることです:

私は2言語(en、fr)の多言語サイトを持っていますが、4つのiso_codes(us、gb、fr、be)も持っています。

Drupalは、たとえば/ usや/ gbが/ enのエイリアスであることを理解するために必要です(これらはまったく同じコンテンツを共有します)。

プログラムまたはモジュールでそれを達成する方法があるかどうか知っていますか?

私は現在、 setPath on the go: RouteCollection とKernelEvents :: Requestの2つのイベントサブスクライバーを調べていますが、今のところ結果はありません。

どんな助けでも大歓迎です。

1
pbonnefoi

PathProcessorサービスを使用して、やりたいことを実現できました。

Here is my services.yml
  mymodule.path_processor:
    class: Drupal\mymodule\PathProcessor\PathProcessor
    arguments: ['@language_manager', '@config.factory', '@path.alias_manager']
    tags:
      - { name: path_processor_inbound, priority: 200 }

そして、私のPathProcessor.phpクラスの私のコード:

/**
 * Processes the inbound path using path alias lookups.
 */
class PathProcessorCustom implements InboundPathProcessorInterface, OutboundPathProcessorInterface {

    protected $language_manager;
    protected $configFactory;
    protected $aliasManager;

    public function __construct(LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory, AliasManagerInterface $alias_manager) {
        $this->languageManager = $language_manager;
        $this->configFactory = $config_factory;
        $this->aliasManager = $alias_manager;
    }

    public function processInbound($path, Request $request) {
        if (!strpos($path, '/admin/')) {
            $path = $this->removeISOCode($path);
        }

        return $path;
    }

    public function processOutbound($path, &$options = array(), Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
        if (!strpos($path, '/admin/')) {
            $path = $this->insertISOCode($path);
        }

        return $path;
    }

    protected function removeISOCode($path) {
        $langcode = $this->languageManager->getDefaultLanguage()->getId();
        $isocodes = $this->getISOCodeMapping();
        $path_items = explode('/', $path);
        if (isset($path_items[1]) && strlen($path_items[1]) == 2 && in_array($path_items[1], $isocodes[$langcode])) {
            $config_negotiation_url = $this->configFactory->get('language.negotiation')->get('url');
            if (!in_array($path_items[1], $config_negotiation_url['prefixes'])) {
                array_splice($path_items, 1, 1);
                if (count($path_items) == 1) {
                    $config_system_site = $this->configFactory->get('system.site')->get('page');
                    $path = $config_system_site['front'];
                }
                else {
                    $path = implode('/', $path_items);
                    $path = $this->aliasManager->getPathByAlias($path, 'en');
                }
            }
        }

        return $path;
    }

    protected function insertISOCode($path) {
        $path_items = explode('/', $path);
        if (isset($path_items[1]) && strlen($path_items[1]) == 2 && $path_items[1] == 'gb') {
            $config_negotiation_url = $this->configFactory->get('language.negotiation')->get('url');
            if(!in_array($path_items[1], $config_negotiation_url['prefixes'])) {
                $path_items[1] = $language;
            }
        }

        $path = implode('/', $path_items);

        return $path;
    }

    protected function getISOCodeMapping() {
        return [
            'en' => ['gb', 'us'],
            'fr' => ['fr', 'be']
        ];
    }

}

私が行うことは、URLを分解し、不要だとわかっているものを削除し、URLを実際のコンテンツURLにマップすることです。それ以外の場合は、デフォルトの404にリダイレクトします。

2
pbonnefoi