3 namespace Drupal\filter;
5 use Drupal\Component\Utility\Crypt;
6 use Drupal\Component\Utility\Html;
7 use Drupal\Component\Utility\UrlHelper;
8 use Drupal\Core\Render\BubbleableMetadata;
11 * Used to return values from a text filter plugin's processing method.
13 * The typical use case for a text filter plugin's processing method is to just
14 * apply some filtering to the given text, but for more advanced use cases,
15 * it may be necessary to also:
16 * - Declare asset libraries to be loaded.
17 * - Declare cache tags that the filtered text depends upon, so when either of
18 * those cache tags is invalidated, the filtered text should also be
20 * - Declare cache context to vary by, e.g. 'language' to do language-specific
22 * - Declare a maximum age for the filtered text.
23 * - Apply uncacheable filtering, for example because it differs per user.
25 * In case a filter needs one or more of these advanced use cases, it can use
26 * the additional methods available.
28 * The typical use case:
30 * public function process($text, $langcode) {
33 * return new FilterProcessResult($text);
37 * The advanced use cases:
39 * public function process($text, $langcode) {
42 * $result = new FilterProcessResult($text);
44 * // Associate assets to be attached.
45 * $result->setAttachments(array(
51 * // Associate cache contexts to vary by.
52 * $result->setCacheContexts(['language']);
54 * // Associate cache tags to be invalidated by.
55 * $result->setCacheTags($node->getCacheTags());
57 * // Associate a maximum age.
58 * $result->setCacheMaxAge(300); // 5 minutes.
64 class FilterProcessResult extends BubbleableMetadata {
69 * @see \Drupal\filter\Plugin\FilterInterface::process()
73 protected $processedText;
76 * Constructs a FilterProcessResult object.
78 * @param string $processed_text
79 * The text as processed by a text filter.
81 public function __construct($processed_text = '') {
82 $this->processedText = $processed_text;
86 * Gets the processed text.
90 public function getProcessedText() {
91 return $this->processedText;
95 * Gets the processed text.
99 public function __toString() {
100 return $this->getProcessedText();
104 * Sets the processed text.
106 * @param string $processed_text
107 * The text as processed by a text filter.
111 public function setProcessedText($processed_text) {
112 $this->processedText = $processed_text;
117 * Creates a placeholder.
119 * This generates its own placeholder markup for one major reason: to not have
120 * FilterProcessResult depend on the Renderer service, because this is a value
121 * object. As a side-effect and added benefit, this makes it easier to
122 * distinguish placeholders for filtered text versus generic render system
125 * @param string $callback
126 * The #lazy_builder callback that will replace the placeholder with its
129 * The arguments for the #lazy_builder callback.
132 * The placeholder markup.
134 public function createPlaceholder($callback, array $args) {
135 // Generate placeholder markup.
136 // @see \Drupal\Core\Render\PlaceholderGenerator::createPlaceholder()
137 $arguments = UrlHelper::buildQuery($args);
138 $token = Crypt::hashBase64(serialize([$callback, $args]));
139 $placeholder_markup = '<drupal-filter-placeholder callback="' . Html::escape($callback) . '" arguments="' . Html::escape($arguments) . '" token="' . Html::escape($token) . '"></drupal-filter-placeholder>';
141 // Add the placeholder attachment.
142 $this->addAttachments([
144 $placeholder_markup => [
145 '#lazy_builder' => [$callback, $args],
150 // Return the placeholder markup, so that the filter wanting to use a
151 // placeholder can actually insert the placeholder markup where it needs the
152 // placeholder to be replaced.
153 return $placeholder_markup;