メソッドに引数として渡された翻訳可能な文字列のフォーマット済みテキストとしてJSONをプリティプリントしますか?

Aug 21 2020

長さの前文:

サービスクラスで、特定の権限を持つユーザーの画面上のデバッグ情報を表示したいと思います。

my_custom_module.permissions.yml

'view debug info':
  title: 'View debug info'
  description: 'Allow user to view DataPartner API debugging messages.'
  restrict access: true

src/Api/DataPartner.php

<?php

namespace Drupal\my_custom_module\Api;

/**
 * @file
 * Contains \Drupal\my_custom_module\Api\DataPartner.
 */

use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;

/**
 * Provides API integration methods.
 */
class DataPartner {

  use StringTranslationTrait;

  /**
   * Private function to determine whether displaying debug info is permitted.
   *
   * @return bool
   *   TRUE if debugging is permitted for current user in current environment.
   */
  private function hasDebugPermission() {
    return MY_CUSTOM_MODULE_DEBUG_FLAG && $this->account->hasPermission('view debug info');
  }

それにはもう少しあります。

*.services.ymlServiceクラス内およびServiceクラス内の依存性注入のものを省略しました。これは、ユーザーアカウントのアクセス許可の確認、画面へのDrupalメッセージの書き込みなどを処理するメソッドを提供するために使用しています。(私が注入しているサービスを示し、StringTranslationTrait私の質問に関連する場合は、その依存関係を注入するのではなく、Serviceクラスでを使用していることを示すのに十分なだけ含めました。)

またMY_CUSTOM_MODULE_DEBUG_FLAG、実稼働環境でデバッグを無効にし、ConfigFormのチェックボックスに基づいてデバッグを切り替える定数を定義しましたが、実際の質問には影響しません。

とにかく、これで次のようなAPIデバッグメッセージを表示できます。

if ($this->hasDebugPermission()) {
  $this->messenger->addMessage($this->t('Step 2: $response = <br><pre>@value</pre>', [ '@value' => print_r(json_encode($this->response_decode, JSON_PRETTY_PRINT), TRUE),
  ]));
}

これは、それに関しては問題ありませんが、より良いカプセル化が必要でした。私はこれを試しました:

  /**
   * Private function to display debug info if permitted.
   *
   * @param string $message * Translatable message string to be displayed, if permitted. * @param array $variables
   *   Values for substitution in translatable string.
   */
  private function displayDebugInfo(string $message, array $variables = []) {
    if ($this->account->hasPermission('view debug info')) { $this->messenger->addMessage($this->t($message, $variables));
    }
  }

ただし、これは次の理由でDrupalコーディング標準に違反します。

警告| t()可能な場合は、文字列リテラルのみを渡す必要があります

これについての興味深い議論がここにあります。

リンクされた問題キューには、メソッドに引数として渡す前に文字列を翻訳用にマークできると記載されているので、次のことを試しました。

  /**
   * Private function to display debug info if permitted.
   *
   * @param string $message
   *   Translatable message string to be displayed, if permitted.
   */
  private function displayDebugInfo(string $message, array $variables = []) {
    if ($this->account->hasPermission('view debug info')) { $this->messenger->addMessage($message));
    }
  }

その場合、次のようなAPIデバッグメッセージを表示する必要があります。

this->displayDebugInfo($this->t('Step 2: $response = <br><pre>@value</pre>', [ '@value' => print_r(json_encode($this->response_decode, JSON_PRETTY_PRINT), TRUE),
]));

この長い前文は私に私の質問をもたらします。

実際の質問:

この方法で翻訳可能な文字列をメソッドに渡すと、HTMLマークアップが画面に出力されるため、きれいに印刷されたJSONが事前にフォーマットされたテキストとして表示される代わりに、ユーザーには見苦しいテキストとマークアップのレンガが表示されます。

ブラウザの開発ツールのDOMインスペクタでマークアップを調べると、のようなエスケープされたHTMLエンティティではなく、通常のマークアップのように見えます&lt;pre&gt;

  • マークアップがブラウザによって解釈されないのはなぜですか?(セキュリティ上の理由があると思います。)
  • ケーキ(事前にフォーマットされたきれいに印刷されたJSONを$this->messenger->addMessage())に入れて、それも(オブジェクト指向のカプセル化を改善して)食べたい場合、欲しいものを手に入れる方法はありますか?

回答

2 imclean Aug 28 2020 at 03:40

最も簡単な方法は、Markupクラスを直接使用することです。これはcoder / phpcsを喜ばせるはずです。Coreもこれを行います。

<?php

namespace Drupal\my_custom_module\Api;

use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\StringTranslation\StringTranslationTrait;

/**
 * Provides API integration methods.
 */
class DataPartner {

  use StringTranslationTrait;

  /**
   * Private function to determine whether displaying debug info is permitted.
   *
   * @return bool
   *   TRUE if debugging is permitted for current user in current environment.
   */
  private function hasDebugPermission() {
    return MY_CUSTOM_MODULE_DEBUG_FLAG && $this->account->hasPermission('view debug info'); } /** * Private function to display debug info if permitted. * * @param string $message
   *   Translatable message string to be displayed, if permitted.
   */
  private function displayDebugInfo(string $message, array $variables = []) {
    if ($this->account->hasPermission('view debug info')) { $this->messenger->addMessage(Markup::create($message)));
    }
  }

}

@file 名前空間付きクラスには必要ありません。