JSON abbastanza stampato come testo preformattato in una stringa traducibile passata come argomento al metodo?

Aug 21 2020

LUNGHEZZA PREAMBOLO:

In una classe Service, vorrei visualizzare le informazioni di debug sullo schermo per gli utenti con un'autorizzazione specifica.

In my_custom_module.permissions.yml:

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

In 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');
  }

C'è qualcosa in più.

Ho tralasciato le cose di inserimento delle dipendenze nella *.services.ymle nella classe Service, che sto usando per fornire metodi per gestire il controllo dei permessi dell'account utente, la scrittura di messaggi Drupal sullo schermo e altre cose. (Ho incluso quanto basta per mostrare quali servizi sto iniettando e per mostrare che sto usando StringTranslationTraitnella classe Service piuttosto che iniettare quella dipendenza, nel caso in cui sia rilevante per la mia domanda.)

Ho anche definito la costante MY_CUSTOM_MODULE_DEBUG_FLAGper disabilitare il debug nell'ambiente di produzione e attivarlo in base a una casella di controllo in un ConfigForm, ma ciò non avrà alcun effetto sulla mia domanda attuale.

Ad ogni modo, ora posso visualizzare i messaggi di debug dell'API in questo modo:

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),
  ]));
}

Questo va bene, per quanto riguarda, ma volevo un migliore incapsulamento. Ho provato questo:

  /**
   * 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));
    }
  }

Tuttavia, questo viola gli standard di codifica Drupal perché:

ATTENZIONE | t()Ove possibile, devono essere passati solo i valori letterali stringa

C'è una discussione interessante su questo qui .

La coda dei problemi collegati menziona che puoi contrassegnare la stringa per la traduzione prima di passarla come argomento al tuo metodo, quindi ho provato che:

  /**
   * 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));
    }
  }

Se lo faccio, devo visualizzare i messaggi di debug dell'API in questo modo:

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

Questo lungo preambolo mi porta alla mia domanda.

DOMANDA REALE:

Il passaggio della stringa traducibile al metodo in questo modo fa sì che il markup HTML venga stampato sullo schermo, in modo che invece di vedere un JSON ben stampato come testo preformattato, l'utente vede un mattone di brutto testo e markup.

Quando esamino il markup nell'ispettore DOM degli strumenti di sviluppo del browser, sembra un markup normale, non entità HTML con escape come &lt;pre&gt;.

  • Perché il markup non viene interpretato dal browser? (Presumo che ci sia un motivo di sicurezza.)
  • Se voglio avere la mia torta (JSON preformattato piuttosto stampato in $this->messenger->addMessage()) e mangiarla anche io (con un migliore incapsulamento orientato agli oggetti), c'è un modo per me di ottenere quello che voglio?

Risposte

2 imclean Aug 28 2020 at 03:40

Il metodo più semplice consiste nell'usare direttamente la classe Markup. Questo dovrebbe per favore coder / phpcs. Core fa anche questo .

<?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 non è richiesto per le classi con spazio dei nomi.