Problem/Motivation

SafeStringInterface is badly named for two reasons:

  1. The output is not necessarily safe
  2. The output is more than just a string - it is a string formatted for output in the HTML context

Proposed resolution

Rename SafeStringInterface to MarkupInterface and move it to Drupal\Component\Render and do quite a few other changes to make this consistent:

  • Drupal\Component\Utility\FormattableString to Drupal\Component\Render\FormattableMarkup
  • Drupal\Core\StringTranslation\TranslatableString to Drupal\Core\StringTranslation\TranslatableMarkup
  • Drupal\Component\Utility\PlainTextOutput to Drupal\Component\Render\PlainTextOutput
  • Drupal\Component\Utility\SafeStringTrait to Drupal\Component\Render\MarkupTrait
  • Drupal\Core\Render\SafeString to Drupal\Core\Render\Markup
  • Drupal\Core\Field\FieldFilteredString to Drupal\Core\Field\FieldFilteredMarkup
  • Drupal\filter\Render\FilteredString to Drupal\filter\Render\FilteredMarkup
  • Drupal\views\Render\ViewsRenderPipelineSafeString to Drupal\views\Render\ViewsRenderPipelineMarkup

The basic reason why this change makes sense is that it clarifies that the purpose of the entire render system is to produce markup. Another reason is that aligns the names with Twig_Markup a class that Twig provides something similar.

Is the disruption worth it? @alexpott thinks so - the more clarity this system has the better.

Remaining tasks

Commit

User interface changes

No

API changes

Yes, some recently introduced classes will be renamed, as well as some classes that had existed for longer but are confusingly/harmfully named.
MarkupInterface is not @internal anymore

Issue fork drupal-2576533

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

alexpott created an issue. See original summary.

alexpott’s picture

Title: SafeStringInnterface et al are badly named » SafeStringInterface et al are badly named
alexpott’s picture

Issue summary: View changes
dawehner’s picture

SafeStringInterface is certainly now a bad name, given how it evolved over time. We need to make sure that MarkupInterface also matches the idea of EscapedString.
So do we consider the EscapedString the final markup representation of a string?

Is the disruption worth it? I think so - the more clarity this system has the better.

We can easily provide a BC layer here, so if needed, there is no disruption. On the other hand, quite some of those classes have been added since the last beta.

alexpott’s picture

@dawehner also I think if we leave a BC layer then we've got the problem of confusion.

alexpott’s picture

Thinking a bit more - the BC layer is the SafeMarkup::format() / SafeMarkup::checkPlain() / TranslationManager::translate() / TranslationManager::formatPlural() / t() / format_plural() / TranslationWrapper.

stefan.r’s picture

+1 to renaming this, SafeString is not a very descriptive name. Could we deprecate + trigger_error() rather than remove completely?

Given the input of t()/TranslatableString is markup as well, I don't see what's tricky about TranslatableString - it's exactly the same as FormattableString except it's translatable so its name should stay consistent. So probably either TranslatableString/FormattableString or TranslatableMarkup/FormattableMarkup? The only worry with the latter is that the docs specifically state to use no (or minimal) markup in the input string.

(Note we leave this in core and marked @internal because absolutely nothing should use this as it is a just mark this as not to be escaped by Twig object and unfit for use outside of the Renderer).

Can we prohibit access to this more strongly than just marking @internal? Ie fail if called from outside of core?

alexpott’s picture

Assigned: Unassigned » alexpott

Working on this.

alexpott’s picture

Status: Active » Needs review
StatusFileSize
new218.27 KB

Renames and moves all-teh-things. Including TranslatableString.

@stefan.r this patch contains 0 logic changes - doing something more to prevent people using SafeString/Markup would be a logic change and is therefore out-of-scope. Also I feel we are moving on to very dangerous territory if we are always trying to implement things that stop developers from doing things - it is feel to document that it should not be used and each module should create its own object if it needs to do this sort of thing but have a runtime check about were code is used feels very heavy handed.

Status: Needs review » Needs work

The last submitted patch, 9: 2576533-9.patch, failed testing.

The last submitted patch, 9: 2576533-9.patch, failed testing.

alexpott’s picture

I think if we do this (and I think we should) we should do it before #2575615: Introduce HtmlEscapedText and remove SafeMarkup::setMultiple() and SafeMarkup::getAll() and remove the static safeStrings list and #2570431: Document that certain (non-"href") attribute values in t() and SafeMarkup::format() are not supported and may be insecure because this patch changes slightly the direction that those patches will take.

For #2575615: Introduce HtmlEscapedText and remove SafeMarkup::setMultiple() and SafeMarkup::getAll() and remove the static safeStrings list, EscapedStringInterface/EscapedString becomes EscapedMarkupInterface/EscapedMarkup.

For #2570431: Document that certain (non-"href") attribute values in t() and SafeMarkup::format() are not supported and may be insecure, I think the documentation is made way simpler by the new class names making it more obvious what we consider to be markup and what is not.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new503 bytes
new218.32 KB

Binary files suck.

alexpott’s picture

+++ b/core/lib/Drupal/Core/Render/Element/HtmlTag.php
@@ -85,7 +85,7 @@ public static function preRenderHtmlTag($element) {
-    $element['#markup'] = SafeString::create($markup);
+    $element['#markup'] = Markup::create($markup);

<3

dawehner’s picture

  1. +++ b/core/includes/common.inc
    @@ -284,21 +284,21 @@ function format_size($size, $langcode = NULL) {
           case 'KB':
    -        return new TranslatableString('@size KB', $args, $options);
    +        return new TranslatableMarkup('@size KB', $args, $options);
           case 'MB':
    -        return new TranslatableString('@size MB', $args, $options);
    +        return new TranslatableMarkup('@size MB', $args, $options);
           case 'GB':
    

    TranslatableMarkup feels weird

  2. +++ b/core/includes/errors.inc
    @@ -74,7 +74,7 @@ function _drupal_error_handler_real($error_level, $message, $filename, $line, $c
    -      '@message' => SafeString::create(Xss::filterAdmin($message)),
    +      '@message' => Markup::create(Xss::filterAdmin($message)),
    

    At some point we could even have XssFilteredMarkup

wim leers’s picture

Priority: Normal » Major
Issue tags: +DX (Developer Experience)

+1000 for the concept. This HUGELY improves understandability, and thus DX.

Status: Needs review » Needs work

The last submitted patch, 13: 2576533.13.patch, failed testing.

The last submitted patch, 13: 2576533.13.patch, failed testing.

stefan.r’s picture

it is feel to document that it should not be used and each module should create its own object if it needs to do this sort of thing but have a runtime check about were code is used feels very heavy handed.

I agree it's a slippery slope, but what's also dangerous is contrib doing Markup::create() on unsafe markup - so it may be worth checking that internal actually means internal here as I feel this needs stronger dissuasion than just an @internal annotation and there's no such thing as a @dangerous annotation. If not a runtime check (and knowing it's out of scope here), I'd also be happy with an assert() or that codesniffer check on contrib releases we discussed, with a warning on unsafe projects.

TranslatableMarkup feels weird

I thought the same thing but then embraced the weirdness... it actually clarifies that the input and output are markup - it's markup that can be translated to other languages.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new1.18 KB
new218.73 KB

Fixing test fails.

@stefan.r I still think that trying to lockdown Drupal\Core\Render\Markup is out-of-scope for this issue - if you want to try you can always open a new issue - that said I don't see a performant and good way to do this and also it just goes against the grain of open source. It is enough that it is marked final.

catch’s picture

Postponed #2569485: Add AttributeSafeStringInterface and UriAttributeSafeStringInterface, that should end up duplicate if this happens. fwiw I like this issue very much, the ambiguity of 'SafeString' is partly why the full scope of our problems wasn't realised until quite late, and this makes its purpose much more concrete.

wim leers’s picture

  1. +++ b/core/lib/Drupal/Component/Render/PlaceholderTrait.php
    @@ -2,10 +2,14 @@
    - * Contains \Drupal\Component\Utility\PlaceholderTrait.
    + * Contains \Drupal\Component\Render\PlaceholderTrait.
    
    +++ b/core/lib/Drupal/Core/Annotation/ContextDefinition.php
    @@ -8,7 +8,7 @@
     namespace Drupal\Core\Annotation;
    

    This is confusing WRT \Drupal\Core\Render\PlaceholderGeneratorInterface + \Drupal\Core\Render\PlaceholderGenerator.

    They are vastly different kinds of placeholders, yet are in the same namespace, which suggests they're kinda the same thing.

    … except they're not in the same namespace: these live in Component, the ones I mentioned live in Core. Still, this is the most concerning part about this patch.

  2. +++ b/core/lib/Drupal/Core/Render/Renderer.php
    @@ -187,7 +187,7 @@ protected function renderPlaceholder($placeholder, array $elements) {
    -    $elements['#markup'] = SafeString::create(str_replace($placeholder, $markup, $elements['#markup']));
    +    $elements['#markup'] = Markup::create(str_replace($placeholder, $markup, $elements['#markup']));
    
    @@ -292,7 +292,7 @@ protected function doRender(&$elements, $is_root_call = FALSE) {
    -          $elements['#markup'] = SafeString::create($elements['#markup']);
    +          $elements['#markup'] = Markup::create($elements['#markup']);
    

    This makes so much sense that I basically don't have words for it. Except that it hurts. It hurts to see the old version and how painfully much better this is.

dawehner’s picture

… except they're not in the same namespace: these live in Component, the ones I mentioned live in Core. Still, this is the most concerning part about this patch.

What about use MarkupPlaceholder and RenderPlaceholder?

stefan.r’s picture

This is confusing WRT \Drupal\Core\Render\PlaceholderGeneratorInterface + \Drupal\Core\Render\PlaceholderGenerator.

They are vastly different kinds of placeholders, yet are in the same namespace, which suggests they're kinda the same thing.

… except they're not in the same namespace: these live in Component, the ones I mentioned live in Core. Still, this is the most concerning part about this patch.

Maybe this can just be documented in the PHPdocs, these "placeholders" are so vastly different that I think it's fine.

Otherwise PlaceholderTrait could also just be renamed or moved to Component/Utility...

stefan.r’s picture

What about use MarkupPlaceholder and RenderPlaceholder?

That could also work

alexpott’s picture

I think the PlaceholderTrait needs to be alongside MarkupInterface because it is concerned with how to do replacements in markup with an eye on safeness and the context of where the placeholders are used.

alexpott’s picture

We could also just punt on the PlaceholderTrait name - since it is highly unlikely to have usages outside of FormattableMarkup, TranslatableMarkup and PluralTranslatableMarkup.

pwolanin’s picture

Overall direction here looks reasonable and I think is important to clarify what's happening.

Changing PlaceholderTrait seems much less important than the others, so I'd just leave it.

stefan.r’s picture

Agreed, just documenting they're different things should be fine

wim leers’s picture

Isn't PlaceholderTrait actually TranslationPlaceholderTrait? It's specifically for @something, :something and %something. All of which are translation syntax thingies. It just happens to be that translations can also contain markup. But first and foremost it seems to be about translations.

stefan.r’s picture

Hmm that's correct but it may add to the confusion as these placeholders are used in both TranslatableString (t()) and FormattableString (SafeMarkup::format()) - the first is for translations, the second isn't but otherwise acts the same.

yesct’s picture

webchick’s picture

Issue tags: +rc deadline, +beta target

If we're going to do this, it needs to be done in the next ~5 days. Probably ideal to get it in before beta16 (tomorrow) if possible.

dawehner’s picture

Agreed, just documenting they're different things should be fine

Seems to be a good solution for now. SafeStringInterface will be used that often that we better figure out a good name for that. The placeholder issue is comparable small against that.

alexpott’s picture

Thinking about PlaceholderTrait and it's documentation - how about we just open a followup to do improvement this wrt to its differences to render placeholder generation?

alexpott’s picture

Opened #2577785: Remove PlaceholderTrait to fix PlaceholderTrait documentation.

alexpott’s picture

I'll review and update all the change records if this issue lands.

xjm’s picture

For #2575615: Introduce EscapedString and remove SafeMarkup::setMultiple() and SafeMarkup::getAll() and remove the static safeStrings list, EscapedStringInterface/EscapedString becomes EscapedMarkupInterface/EscapedMarkup.

I realize this one isn't part of this issue, but "escaped markup interface" seems oxymoronical to me. If it's escaped, it's no longer markup. Asking here since it seems related to the reasoning about naming for this patch (all of which looks fine to me FWIW).

I've thought about it a bit and I agree with not retaining two of everything for 8.0.0 -- the goal is to make the API less confusing, but leaving in all those deprecated wrappers would be more confusing.

I was at first concerned about dropping all these sudden changes on everyone a week before RC with no warning whatsoever. However, actually, most of the things listed here have just been added in the past two weeks I think, aside from SafeStringInterface and its implementations, which were always marked internal anyway. Is that a correct assessment? Did I miss anything?

xjm’s picture

Also, answers to #38 would be good beta eval material for the IS. :)

effulgentsia’s picture

I haven't read the full patch or the issue comments yet, so this is just a drive-by question. Apologies if it was already discussed and answered:

In the issue summary:

SafeStringInterface is badly named for two reasons:

1) The output is not necessarily safe

In the patch:

+++ b/core/lib/Drupal/Component/Utility/SafeMarkup.php
@@ -65,7 +67,7 @@ class SafeMarkup {
   public static function isSafe($string, $strategy = 'html') {
     // Do the instanceof checks first to save unnecessarily casting the object
     // to a string.
-    return $string instanceOf SafeStringInterface || isset(static::$safeStrings[(string) $string][$strategy]) ||
+    return $string instanceOf MarkupInterface || isset(static::$safeStrings[(string) $string][$strategy]) ||
       isset(static::$safeStrings[(string) $string]['all']);
   }

I'm not quite clear how to interpret this. Is MarkupInterface a better name partially because it doesn't claim to be "safe"? But then why is isSafe() only checking MarkupInterface and not something more strictly named (e.g., a SafeMarkupInterface that extends MarkupInterface)?

xjm’s picture

It's not clear from the summary whether PlaceholderTrait is or isn't part of this patch. It looks like it is in the current patch.

That name seems less unambiguous not as obviously a good choice for me. I'd suggest something FormattableStringPlaceholderTrait... since all translatable strings are also formatted strings? But I'd suggest spinning it off into its own issue to get the other ones in maybe. #2577785: Remove PlaceholderTrait seems to only be about docs and I don't think documentation solves the confusion (which is what caused us all these SafeFoo problems in the first place, of course).

xjm’s picture

isSafe() I think we are only retaining for BC reasons, thence the inconsistency in naming. But I do see how there could be confusion between the differing intents of AnyMarkupYouLikeInterface and SufficientlySanitizedMarkupInterface. MarkupThatYourSiteWillPrintJustLikeThisInterface. MarkupThatMustNotContainOtherwiseUnsanitizedUserInputInterface. Or in other words, I do see/share the concern about the name MarkupInterface not warning people away or clarifying what the implications of implementing the interface are, whereas with SafeStringInterface, it was less clear for consumers, but more clear for people actually constructing one, that there was some expectation about what should go in there in the first place.

I guess this partly depends if we are keeping the @internal on the MarkupInterface. @alexpott said something about needing to remove it (the patch does not, which is good as that would be scope creep). But to me that increases the risk as well.

xjm’s picture

Another concern, I might expect MarkupInterface to be the object equivalent of #markup in render arrays. But it's not, at all.

stefan.r queued 20: 2576533.20.patch for re-testing.

stefan.r’s picture

I think the current patch is mostly fine as is. The concerns can mostly be documented (and MarkupInterface is still @internal) so if we mention clearly in the code that the placeholders in PlaceholderTrait and PlaceholderGenerator are different things, we only have a problem if people use PlaceholderTrait without reading the docs.

But realistically it will only be used in FormattableString and TranslatableString anyway, which brings me to...

I'd suggest something FormattableStringPlaceholderTrait... since all translatable strings are also formatted strings?

Technically not yet... But if we codify that, that may work? Could we maybe get rid of PlaceholderTrait, move its code into FormattableString, and make TranslatableString extend FormattableString?

Oh and despite how silly it sounds I actually quite like SufficientlySanitizedMarkupInterface...

Status: Needs review » Needs work

The last submitted patch, 20: 2576533.20.patch, failed testing.

effulgentsia’s picture

To elaborate on #40, my first thought when seeing MarkupInterface was yay, in a follow-up we'll be able to make Vocabulary::getDescription() return an object that implements that as a way of informing callers that what's returned is HTML and not plain-text. But, with the current patch treating MarkupInterface as a signal that the markup is also safe, we couldn't do that.

Additionally, as #38 points out, EscapedMarkup would not be accurate, since the result is not markup, it's only HTML-encoded text.

Therefore, here's some possible suggestions to think about, all open to modifying or shooting down:

  • Instead of MarkupInterface, have a HtmlStringInterface.
  • Add a separate SafeHtmlStringInterface or add isSafe() to HtmlStringInterface.
  • Rename #2575615: Introduce HtmlEscapedText and remove SafeMarkup::setMultiple() and SafeMarkup::getAll() and remove the static safeStrings list to HtmlEscapedText.
  • Either keep FilteredMarkup, TranslatableMarkup, etc. or rename them to FilteredHtml, TranslatableHtml, etc.
  • Maybe have a concrete generic class that implements HtmlStringInterface, but do not have a concrete generic class that implements SafeHtmlStringInterface (as SafeString does in HEAD and Markup does in the current patch). Instead, create a RenderedMarkup or RenderedHtml class for the Renderer to use for its output.
stefan.r’s picture

Re #47 - I agree that having a separate object signaling that something is an HTML fragment could be nice, but not sure about some of the other remarks:

  1. For Vocabulary::getDescription we could still make it an object with another interface to signal it contains HTML markup that doesn't implement MarkupInterface (or whatever we call the interface that signals safeness)
  2. We can either be correct or be brief - if we want to be brief I still think Markup is fine and we can document where we're not 100% correct. It might mean there's a bit of a learning curve but is that really such a problem?
  3. If we want to be 100% correct, EscapedMarkup may technically not be "markup", but it is not plain-text either. In isolation, its contents are technically not "markup", but they will almost always be contained within markup - and again these are all things that can be documented.

    So I think EscapedMarkup is fine, as the result is escaped HTML markup, i.e. HTML markup where the '"&<> are turned into HTML entities. Technically the result would be "HTML text containing HTML-escaped HTML markup".

  4. As to the suggested HtmlEscapedText, it still implies plain-text, which is a confusion from D7 we want to avoid, so maybe HtmlEscapedHtmlText?
  5. For the "safe" HTML string I do think we should come up with a better name than SanitizedAnything/SafeAnything and ::isSafe() as it's not necessarily safe (or fully sanitized), and here misnaming things actually poses a security risk - when rendered to string a SafeString object can still contain unsanitized HTML and it's only "safe" for use within HTML fragments and not within other contexts such as JSON, HTML attributes or CSS/Javascript embedded into HTML.
  6. HTMLStringInterface is not really more correct than MarkupInterface either, as it only refers to HTML text or a series of HTML nodes, and excludes other contexts within an HTML document (such as anything between the "<" and ">" of an HTML tag)
dawehner’s picture

This is maybe a different angle from what has been discussed so far.
For me HTML, given its name, consists of markup. Whether its actual tags or whether escaped strings, its all markup. So what represents a MarkupInterface for me is an object which will be printed to the resulting HTML just as it is, without any additional massaging on the outside (internal details don't matter). An EscapedMarkup will be a string which will be printed in an escaped way to the final HTML markup, a Markup object will just print out its value to the final HTML.

Sometimes we just assume that people are stupid and by that cause so much confusion that at the end there is more harm caused.

alexpott’s picture

Re EscapedMarkup I think we're missing the point that the markup representation of something like I like the <br> tag is I like the &lt;br&gt; tag. I think think EscapedHTML and EscapedHTMLInterface are okay too but then we're going to need to think about how we tell Twig not to escape things. This patch changes SafeStringInterface to be MarkupInterface but given then push back on EscapedMarkup I doubt that people will be happy if EscapedHTMLInterface extends MarkupInterface - although for me this makes since the __toString() does return the representation of the string necessary to display it in markup. All of this is only relevant for #2575615: Introduce HtmlEscapedText and remove SafeMarkup::setMultiple() and SafeMarkup::getAll() and remove the static safeStrings list

Re the safeness of MarkupInterface - the point is that this interface tells Twig not to auto-escape because it contains markup - the safeness or not of doing this is up to the implementation. This is one of the long running problems with using the words safe... SafeMarkup::isSafe() is alos badly named because what it really means is that this is markup and don't escape it.

Wrt. to PlaceholderTrait there will not be any usages in contrib or custom yet so I think it is okay to rename - so #2577785: Remove PlaceholderTrait has been repurposed to discuss and fix this.

Re the suggestions in #47 - I'm not opposed to changing Markup to HTML - but afaik HTML is just a specific case of markup. One thing this is nice about HTML is how it ties together with Drupal\Component\Utility\HTML. If we're all happy to go with HtmlInterface over MarkupInterface, then I'm happy to make that change... which would look like this...

  • SafeStringInterface =>HtmlInterface
  • FormattableString => FormattableHtml
  • SafeStringTrait => HtmlTrait
  • SafeString => Html
  • FieldFilteredString => FieldFilteredHtml
  • FilteredString => FilteredHtml
  • ViewsRenderPipelineSafeString => ViewsRenderPipelineHtml
  • TranslatableString => TranslatableHtml
  • PluralTranslatableString => PluralTranslatableHtml

However there are downsides - we lose the connection with Twig_Markup and we lose the connection with #markup - some see this connection as confusing but I don't think it is. In the current patch the Renderer whole point is to complete the #markup. Once you call render on an array when it is done the #markup element will contain a Markup object.

Overall I strongly favour going with MarkupInterface and then discussing the correct name for the escaped thing in #2575615: Introduce HtmlEscapedText and remove SafeMarkup::setMultiple() and SafeMarkup::getAll() and remove the static safeStrings list

catch’s picture

#50 has good reasons to stick to Markup.

I'm not sure the name is perfect, but it's 1000 times better than SafeString.

stefan.r’s picture

+1 for Markup

wim leers’s picture

Status: Needs work » Reviewed & tested by the community

Given the very convincing explanation in #50 and the fact that my sole other concern (PlaceholderTrait being confusing, see #22.1) is being addressed in #257775 and will remove that trait, I think this is actually ready now :)

We've had a good, valuable, and IMHO important discussion here, and we are concluding that what the patch already does, is the sensible thing to do.

Hence: RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Postponed
Issue tags: +Needs issue summary update

Obviously I agree entirely with #53 I think we should get #2577785: Remove PlaceholderTrait in first as it conflicts with this and makes the discussions simpler. Plus this issue needs a good issue summary update.

xjm’s picture

Status: Postponed » Needs work

Whee!

stefan.r’s picture

Assigned: alexpott » stefan.r

I can give the reroll a try in ~15min... unless @alexpott was already working on this?

alexpott’s picture

Assigned: stefan.r » Unassigned
Status: Needs work » Needs review
StatusFileSize
new231.28 KB

Here's a reroll on top of all the recent changes. I've also removed the @internal from MarkupInterface because it just is not true. I've attempted to explain how it used in core and how it does not guarentee safe-ness but certain implementations can be used safely.

Status: Needs review » Needs work

The last submitted patch, 57: 2576533-57.patch, failed testing.

stefan.r’s picture

Reviewed the interdiff with patch I had in my own testing issue and didn't see anything odd - just replacements about recent changes and more SafeString -> Markup conversions. SafeStringNormalizer hasn't been renamed here but that may be followup material.

The interdiff is not really more informative than the patch itself so let's just try to get this green for now...

The SafeStringInterface -> MarkupInterface.php conversion was not done as git mv though, it would be nice if we didn't lose the version info for git blame and for reviewability

stefan.r’s picture

Status: Needs work » Needs review
StatusFileSize
new917 bytes
new230.93 KB

Reuploading #57 without the bit about the drupal-8.language-enabled.php binary file just to see what the testbot thinks

As to the git mv, that didn't work for me either, I guess git decides it is a new file when it's too different despite logging a rename?

Status: Needs review » Needs work

The last submitted patch, 60: 2576533-57.patch, failed testing.

catch’s picture

Maybe -rename-threshold would help?

wim leers’s picture

Try git diff -M10%.

wim leers’s picture

I found only a single nitpick. Once this is green, this is ready IMHO.

  1. +++ b/core/lib/Drupal/Component/Render/MarkupInterface.php
    @@ -0,0 +1,45 @@
    +/**
    + * Marks an object's __toString() method as returning markup.
    + *
    + * Objects that implement this interface will not be automatically XSS filtered
    + * by the render system or automatically escaped by the theme engine.
    

    Super clear! :)

  2. +++ b/core/lib/Drupal/Component/Render/MarkupInterface.php
    @@ -0,0 +1,45 @@
    + * pipeline in order to render JSON and to fast render fields. By contrast,
    

    "to fast render fields" sounds wrong.

  3. +++ b/core/lib/Drupal/Core/Render/Renderer.php
    @@ -292,7 +292,7 @@ protected function doRender(&$elements, $is_root_call = FALSE) {
    -          $elements['#markup'] = SafeString::create($elements['#markup']);
    +          $elements['#markup'] = Markup::create($elements['#markup']);
    

    <3

  4. +++ b/core/lib/Drupal/Core/Render/RendererInterface.php
    @@ -27,7 +27,7 @@
    -   * @return \Drupal\Component\Utility\SafeStringInterface
    +   * @return \Drupal\Component\Render\MarkupInterface
        *   The rendered HTML.
    

    <3

  5. +++ b/core/lib/Drupal/Core/Template/TwigExtension.php
    @@ -404,7 +404,7 @@ public function escapeFilter(\Twig_Environment $env, $arg, $strategy = 'html', $
    -    if ($autoescape && ($arg instanceOf \Twig_Markup || $arg instanceOf SafeStringInterface)) {
    +    if ($autoescape && ($arg instanceOf \Twig_Markup || $arg instanceOf MarkupInterface)) {
    

    <3

  6. +++ b/core/modules/filter/filter.module
    @@ -286,7 +286,7 @@ function filter_fallback_format() {
    - * @return \Drupal\Component\Utility\SafeStringInterface
    + * @return \Drupal\Component\Render\MarkupInterface
      *   The filtered text.
    

    <3

  7. +++ b/core/themes/engines/twig/twig.engine
    @@ -46,7 +46,7 @@ function twig_init(Extension $theme) {
    - * @return string|\Drupal\Component\Utility\SafeStringInterface
    + * @return string|\Drupal\Component\Render\MarkupInterface
      *   The output generated by the template, plus any debug information.
    

    <3

stefan.r’s picture

Status: Needs work » Needs review
StatusFileSize
new2.47 KB
new233.64 KB

Agree about #64.2 but that was also already on the previous docs (which is hard to see precisely because git doesn't consider it a rename :), so maybe let's not fix that here

catch’s picture

+++ b/core/modules/filter/filter.module
@@ -286,7 +286,7 @@ function filter_fallback_format() {
- * @return \Drupal\Component\Utility\SafeStringInterface
+ * @return \Drupal\Component\Render\MarkupInterface
  *   The filtered text.

Would be even better if this said 'The formatted text'.

xjm’s picture

Note: @alexpott didn't mention in #57 but I helped write some of those docs. :P

Carry on. :)

wim leers’s picture

#66: Let's rename filter.module to text_format.module in D9? :P

effulgentsia’s picture

Checking the credit box for @xjm per #67. Possibly other participants on this issue need to get that box checked too, but I'll leave that for whoever commits this.

alexpott’s picture

Ticking some more credit boxes. Sorry @xjm - my bad. I've discussed this with @effulgentsia and @catch in IRC and the whole idea came from swimming with @dawehner :)

alexpott’s picture

So drupal-8.language-enabled.php was changed originally by this patch because it contains references to the TranslatableString class - however as this is part of an update path test based on the beta in drupal-8.bare.standard.php.gz it should be aligned with beta 12. So actually we should not have changed it from TranslationWrapper to TranslatableString so leaving it out of this patch is fine.

dawehner’s picture

+++ b/core/lib/Drupal/Component/Render/MarkupInterface.php
@@ -0,0 +1,45 @@
+ * @see \Drupal\Core\Template\TwigExtension::escapeFilter()
...
+ * @see \Drupal\Core\StringTranslation\TranslatableMarkup
+ * @see \Drupal\views\Render\ViewsRenderPipelineMarkup

Why does that not fail the component test?
I'd strongly recommend that the component test removes its strictness for comments, but people didn't liked that when I tried to change that

alexpott’s picture

@dawehner because we decided to exclude @see :)

  protected function assertNoCoreUsage($class_path) {
    $contents = file_get_contents($class_path);
    preg_match_all('/^.*Drupal\\\Core.*$/m', $contents, $matches);
    $matches = array_filter($matches[0], function($line) {
      // Filter references to @see as they don't really matter.
      return strpos($line, '@see') === FALSE;
    });
    $this->assertEmpty($matches, "Checking for illegal reference to 'Drupal\\Core' namespace in $class_path");
  }
effulgentsia’s picture

@dawehner: I think the test already excludes "@see" lines.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Alright, I think we will the change record updates later.

stefan.r’s picture

Title: SafeStringInterface et al are badly named » Rename SafeStringInterface to MarkupInterface and move related classes
Issue summary: View changes
Issue tags: -Needs issue summary update

Gave this another look and very happy with how this looks, much clearer.

As to the change record updates, @alexpott said in #37 he'd do those once this issue was in.

wim leers’s picture

RTBC++

alexpott’s picture

StatusFileSize
new236.62 KB
new6.46 KB

@effulgentsia noticed we'd missing FilteredString plus PHPStorm was still marking MarkupInterface as internal so fixed that.

Furthermore I fixed some references to FieldFilteredString

effulgentsia’s picture

#78 looks great to me. I'll commit it once DrupalCI says it passes tests. Unless someone knocks it back before then.

The last submitted patch, 57: 2576533-57.patch, failed testing.

  • effulgentsia committed 708ce0a on 8.0.x
    Issue #2576533 by alexpott, stefan.r, Wim Leers, dawehner, xjm,...
effulgentsia’s picture

Title: Rename SafeStringInterface to MarkupInterface and move related classes » [needs CR updates] Rename SafeStringInterface to MarkupInterface and move related classes
Status: Reviewed & tested by the community » Needs work

Pushed to 8.0.x! "Needs work" for the CR updates.

I used git apply --index of the #78 patch in an attempt to preserve history. When I do a git log --follow, I see the retained history for most of the files, but not for MarkupInterface and FilteredMarkup, despite the #78 patch showing those as renames. I'm not clear on whether that history is lost forever, or still available with some magic option passed to git log. http://stackoverflow.com/questions/14832963/how-can-i-control-the-rename... claims the latter, but I don't know if that's accurate.

effulgentsia’s picture

@alexpott informed me that git log -M10% --follow core/lib/Drupal/Component/Render/MarkupInterface.php shows history. Yay!

The last submitted patch, 60: 2576533-57.patch, failed testing.

alexpott’s picture

Title: [needs CR updates] Rename SafeStringInterface to MarkupInterface and move related classes » Rename SafeStringInterface to MarkupInterface and move related classes
Status: Needs work » Fixed
Issue tags: -Needs change record updates

I've updated all of the mentions of the classes renamed in this patch in out change records. I've related this issue to the most pertinent.

The last submitted patch, 65: 2576533-65.patch, failed testing.

Status: Fixed » Needs work

The last submitted patch, 78: 2576533-2-76.patch, failed testing.

alexpott’s picture

Status: Needs work » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

prudloff made their first commit to this issue’s fork.

xjm changed the visibility of the branch 2576533-rename-safestringinterface-to to hidden.