Problem/Motivation

First step of #2506427: [meta] !placeholder causes strings to be escaped and makes the sanitization API harder to understand.

Proposed resolution

  • Replace !placeholder with @placeholder, in t() and format_string() usage only, excluding those used in URLs or non-html formats.
  • Do not change core/modules/system/src/Tests/Common/XssUnitTest.php as it is the unit test for the functionality; that will be addressed in a different issue.
  • Also, do not change core/modules/views_ui/src/Tests/DisplayTest.php; that will be addressed in a different issue.
  • Also, do not change core/modules/locale/src/Tests/LocaleJavascriptTranslationTest.php; that will be addressed in a different issue.
  • Also, do not change core/modules/contact/src/Tests/ContactPersonalTest.php; that will be addressed in #2557113: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list.

Bash command to use for t():

egrep -r '\Wt\(.*\!([a-zA-Z])+' * | grep -v 'href="!' | grep Test.php | grep -v "vendor" | grep -v ".js" | grep -v .css | grep -v "~" 

The calls to format_string() are not to be replaced in this issues, only the !placeholder inside.
Note: This results ContactPageTest, which though deals with mails, so its excluded from this particular issue.

Remaining tasks

File issues for & complete:

  • Replace !placeholder with @placeholder from t() in XSSUnitTest (comment #156)
  • Replace !placeholder with @placeholder from t() in LocaleJavascriptTranslationTest (comment #157)
  • Replace !placeholder with @placeholder from t() in Views DisplayTest (comment #160)

Cross verify existing patch against bash command above and any other regexes to catch any cases not found here

User interface changes

Ideally, fewer completely unexpected double-escaping bugs.

API changes

None.

CommentFileSizeAuthor
#225 2506445-225.patch50.3 KBalexpott
#225 224-225-interdiff.txt825 bytesalexpott
#224 2506445-223.patch50.48 KBalexpott
#222 2506445_222.patch51.77 KBchx
#222 diffdiff.txt1.2 KBchx
#218 2506445-218.patch51.86 KBalexpott
#206 2506445.206.patch51.77 KBalexpott
#206 204-206-interdiff.txt3.92 KBalexpott
#204 2506445.204.patch52.71 KBalexpott
#204 199-204-interdiff.txt1.98 KBalexpott
#199 2506445.199.patch53.84 KBalexpott
#199 196-199-interdiff.txt8.78 KBalexpott
#196 placeholder-2506445.196.patch45.59 KBlarowlan
#196 interdiff.txt5.77 KBlarowlan
#190 interdiff-2506445-171-189.txt12.65 KBSutharsan
#190 replace_placeholder-2506445-189.patch51.06 KBSutharsan
#181 interdiff.txt593 byteseffulgentsia
#181 replace_placeholder-2506445-181.patch47.96 KBeffulgentsia
#179 interdiff.txt717 byteseffulgentsia
#179 replace_placeholder-2506445-179.patch48.72 KBeffulgentsia
#171 replace_placeholder-2506445-171.patch48.67 KBSutharsan
#171 interdiff-2506445-164-171.txt1.75 KBSutharsan
#164 replace_placeholder-2506445-164.patch50.25 KBjustAChris
#164 2506445-interdiff-161-164.txt944 bytesjustAChris
#161 replace_placeholder-2506445-161.patch51.17 KBjustAChris
#161 2506445-interdiff-149-161.txt5.53 KBjustAChris
#149 interdiff-2506445-146-149.txt2.62 KBSutharsan
#149 replace_placeholder-2506445-149.patch55.78 KBSutharsan
#147 replace_placeholder-2506445-146.patch58.01 KBSutharsan
#143 replace_placeholder-2506445-141.patch419.57 KBSutharsan
#140 replace_placeholder-2506445-140.patch419.83 KBSutharsan
#135 interdiff-2506445-128-135.txt2.19 KBSutharsan
#135 replace_placeholder-2506445-135.patch32.63 KBSutharsan
#128 replace_placeholder-2506445-128.patch31.34 KBsubhojit777
#126 interdiff.txt1010 bytessubhojit777
#126 replace_placeholder-2506445-126.patch31.32 KBsubhojit777
#122 non-href-slice-n-dice.txt36.45 KBjustAChris
#122 non-href-lookbehind.txt31.76 KBjustAChris
#121 2506445-interdiff.txt4.9 KBrpayanm
#121 2506445-121.patch31.6 KBrpayanm
#117 2506445-117.patch36.95 KBrpayanm
#111 1__d8_html__bash_.png38.54 KBjoelpittet
#101 replace_remaining-2506445-101.patch504.11 KBnlisgo
#101 interdiff-2506445-100-101.txt1001 bytesnlisgo
#100 replace_remaining-2506445-100.patch504.13 KBnlisgo
#96 replace_remaining-2506445-96-with-test.patch505.52 KBjoelpittet
#96 interdiff.txt702 bytesjoelpittet
#96 replace_remaining-2506445-96-reroll.patch505.19 KBjoelpittet
#92 ordered.ods42.81 KBjoelpittet
#89 files_stats-2506445-85.txt12.36 KBjustAChris
#87 files_modified-2506445-85.txt9.9 KBjustAChris
#85 2506445-UnexpecterError.jpg122.92 KBjustAChris
#85 replace-most-2506445-85.patch511.89 KBjustAChris
#80 interdiff-2506445-77-80.txt479 bytesAnonymous (not verified)
#80 replace-most-2506445-80.patch538.39 KBAnonymous (not verified)
#77 interdiff-2506445-73-77.txt14.47 KBAnonymous (not verified)
#77 replace-most-2506445-77.patch538.43 KBAnonymous (not verified)
#73 replace-most-2506445-73.patch538.51 KBAnonymous (not verified)
#71 replace-most-2506445-71.patch538.53 KBAnonymous (not verified)
#66 replace-most-2506445-65.patch538.5 KBAnonymous (not verified)
#61 replace_most-2506445-61.patch539.44 KBnlisgo
#61 interdiff-2506445-54-61.txt1.15 KBnlisgo
#60 interdiff-2506445-54-60.txt3.43 KBAnonymous (not verified)
#60 replace-most-2506445-60.patch535.74 KBAnonymous (not verified)
#57 interdiff-2506445-51-54.txt930 bytesAnonymous (not verified)
#54 replace-most-2506445-54.patch539.17 KBAnonymous (not verified)
#51 replace-most-2506445-51.patch538.46 KBAnonymous (not verified)
#49 replace-most-2506445-49.patch538.23 KBAnonymous (not verified)
#46 replace-most-2506445-45.patch545.74 KBAnonymous (not verified)
#44 replace_most-2506445-44.patch553.21 KBjoelpittet
#44 interdiff.txt5.97 KBjoelpittet
#42 replace_most-2506445-42.patch553.21 KBjoelpittet
#40 replace_most-2506445-40.patch537.43 KBjoelpittet
#40 interdiff.txt1.38 KBjoelpittet
#37 replace_many-2506445-37.patch544.69 KBjoelpittet
#33 replace_many-2506445-33.patch544.92 KBjoelpittet
#33 interdiff.txt16.13 KBjoelpittet
#31 replace_many-2506445-31.patch534.17 KBjoelpittet
#31 interdiff.txt1.45 KBjoelpittet
#28 replace_many-2506445-28.patch540.32 KBjoelpittet
#26 replace_many-2506445-26.patch394.33 KBjoelpittet
#22 replace_many-2506445-22.patch396.02 KBsubhojit777
#22 interdiff-2506445-21-22.txt676 bytessubhojit777
#21 replace_many-2506445-21.patch396.68 KBsubhojit777
#21 interdiff-2506445-17-21.txt2.98 KBsubhojit777
#17 replace_many-2506445-17.patch393.63 KBsubhojit777
#13 interdiff.txt4.87 KBjoelpittet
#13 replace_many-2506445-13.patch395.86 KBjoelpittet
#3 interdiff.txt2.78 KBjoelpittet
#3 replace_many-2506445-3.patch401.1 KBjoelpittet
#2 replace_many-2506445-1.patch413.81 KBjoelpittet
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

xjm’s picture

Was getting some false matches so I tightened my regex to just t() to start:
emacs `egrep -rl '\Wt\(.*\!([a-zA-Z])+' * | grep -v "vendor" | grep -v ".js" | grep -v .css | grep -v "~"`

joelpittet’s picture

FileSize
413.81 KB

Here's all of them, let's see how many break and how many mistakes I made;)

joelpittet’s picture

Status: Active » Needs review
FileSize
401.1 KB
2.78 KB

Overshot and undershot a few. And testbot engage!

Status: Needs review » Needs work

The last submitted patch, 3: replace_many-2506445-3.patch, failed testing.

xjm’s picture

So I started to roll this patch. One downside of this approach is that it will add many early checkPlain() calls (or following #2506035: Do not add placeholders from SafeMarkup::format() to the safe list still htmlspecialchars() calls) for things like URLs. So we do more early escaping in order to not have double-escaping.

However, while deferring more escaping is something we should solve at some point (and a concern I raised in the original SafeMarkup issue), it's not going to happen in 8.0.x, and the instances being changed in this patch are really a drop in the bucket. I do think we should have #2506035: Do not add placeholders from SafeMarkup::format() to the safe list to mitigate it though.

Edit: Augh. I had the issue assigned to myself, meaning I was working on this. I was deliberately separating it into a few scoped sub-issues for easier review.

joelpittet’s picture

194 fails in one test class: Drupal\Tests\editor\Unit\EditorXssFilter\StandardTest
That should be easy to knock down, if we find out why they are failing.

joelpittet’s picture

Sorry to jump the boat @xjm. Well now you have a big picture to run with I guess.

xjm’s picture

Assigned: xjm » Unassigned

Unassigning, no point in me posting a subset of this patch. :)

xjm’s picture

Wim Leers’s picture

The reason for the many failures here:

-    return !parent::needsRemoval($html_tags, $elem);
+    return @parent::needsRemoval($html_tags, $elem);

That's wrong :)

xjm’s picture

@Wim Leers: lol. I think that regex needs to be fixed. ;)

joelpittet’s picture

Oh I probably broke a bunch like that;) I went for fast instead of accurate:P

joelpittet’s picture

Status: Needs work » Needs review
FileSize
395.86 KB
4.87 KB

There may be more that I missed but this cleans up a few including the one in #10 thanks @Wim Leers.

--color-words was helpful, thanks xjm for showing me that a while back

Status: Needs review » Needs work

The last submitted patch, 13: replace_many-2506445-13.patch, failed testing.

subhojit777’s picture

Assigned: Unassigned » subhojit777
subhojit777’s picture

Issue tags: +Needs reroll
subhojit777’s picture

Issue tags: -Needs reroll
FileSize
393.63 KB

Now working on failing tests.

joelpittet’s picture

Status: Needs work » Needs review

The last submitted patch, 2: replace_many-2506445-1.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 17: replace_many-2506445-17.patch, failed testing.

subhojit777’s picture

Assigned: subhojit777 » Unassigned
Status: Needs work » Needs review
FileSize
2.98 KB
396.68 KB

I am having problem in debugging these tests Drupal\migrate_drupal\Tests\MigrateTableDumpTest and Drupal\system\Tests\Common\AddFeedTest, any help regarding this would be great. Rest of the things are fixed.

subhojit777’s picture

subhojit777’s picture

Removed verbose messages.

The last submitted patch, 21: replace_many-2506445-21.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 22: replace_many-2506445-22.patch, failed testing.

joelpittet’s picture

Status: Needs work » Needs review
FileSize
394.33 KB

Reroll of #22 thank you for knocking it down to 4 fails @subhojit777!

Going to see if I can get them down to 0 today.

Status: Needs review » Needs work

The last submitted patch, 26: replace_many-2506445-26.patch, failed testing.

joelpittet’s picture

Status: Needs work » Needs review
FileSize
540.32 KB

Seems I missed a bunch of things... mostly in hook_help()... this patch has grown. I reverted my slight name changes from percent back to pct and @error_message back to @e.

Status: Needs review » Needs work

The last submitted patch, 28: replace_many-2506445-28.patch, failed testing.

joelpittet’s picture

Well that's nice that it's the same # of fails after almost doubling the patch size...

joelpittet’s picture

Status: Needs work » Needs review
FileSize
1.45 KB
534.17 KB

My interdiff may suck on the migrate fixes, but the other two are in it;)

Crossing fingers.

Status: Needs review » Needs work

The last submitted patch, 31: replace_many-2506445-31.patch, failed testing.

joelpittet’s picture

Status: Needs work » Needs review
FileSize
16.13 KB
544.92 KB

Hmm instead of reverting the migrate stuff I should have went the other direction. Missed a few more things in there.
That revert fixed one but broke the other worse:P

Did a few *.js ones as well.

One problem is the feed icon. I can't do it because we remove SafeMarkup from the Attribute classes and just escape it now. So the problem is that t('@title') will escape once, then the result is sent to the Attribute where it's escaped a second time. I'm surprised we didn't run into more of those cases. @xjm Can or should we work around this some other way?

Status: Needs review » Needs work

The last submitted patch, 33: replace_many-2506445-33.patch, failed testing.

joelpittet’s picture

joelpittet’s picture

joelpittet’s picture

Re-roll and touchups to see where this is at (litmus test)

joelpittet’s picture

Title: Replace many !placeholder with @placeholder » Replace most !placeholder with @placeholder
Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 37: replace_many-2506445-37.patch, failed testing.

joelpittet’s picture

Status: Needs work » Needs review
FileSize
1.38 KB
537.43 KB

I should probably do this on an ignore test issue...

Status: Needs review » Needs work

The last submitted patch, 40: replace_most-2506445-40.patch, failed testing.

joelpittet’s picture

Status: Needs work » Needs review
FileSize
553.21 KB

One way that helps me find these is a case sensitive regex project search for:
['"]!(?!IE)[a-zA-Z]

And exclude the following folders/files: -vendor/*,-*.css,-*.json

Then when I find one I just search the project for instances of that same one and any remaining ! that may be left over in that file. I think it catches about 99% of the cases.

There a few false positives there including people using that ! to as their regex delimiter, but excludes the !IE false positive that is quite frequent.

Status: Needs review » Needs work

The last submitted patch, 42: replace_most-2506445-42.patch, failed testing.

joelpittet’s picture

Status: Needs review » Needs work

The last submitted patch, 44: replace_most-2506445-44.patch, failed testing.

Anonymous’s picture

We should not change the D6 database dump that is used in tests. If it produces more errors... then we need to fix them in migrate as things get imported!

This patch is the same as #44 but with migrate_drupal/src/Tests/Table/d6/Variable.php reverted.

Anonymous’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 46: replace-most-2506445-45.patch, failed testing.

Anonymous’s picture

Status: Needs work » Needs review
FileSize
538.23 KB

Regarding my comment in #46, it turns out that the tests are not actually safe markup calls, but rather, old D6-style tokens. As such, I have rerolled with that test excluded. Revised patch attached.

New issue has been created to deal with the tokens: #2551631: D6 user_mail tokens do not get converted.

Status: Needs review » Needs work

The last submitted patch, 49: replace-most-2506445-49.patch, failed testing.

Anonymous’s picture

Status: Needs work » Needs review
FileSize
538.46 KB

Reroll to bring this up-to-date with head.

YesCT’s picture

the fail
Drupal\Tests\migrate\Unit\MigrateExecutableTest

Parameter 0 for invocation Drupal\migrate\MigrateMessageInterface::display('Migration failed with source ...{<(', 'error') does not match expected value. Other MigrateExecutableTest.php 61 Drupal\Tests\migrate\Unit\MigrateExecutableTest->testImportWithFailingRewind()

@Ryan Weal said was failing sometimes, and

  public function testImportWithFailingRewind() {
    $exception_message = $this->getRandomGenerator()->string();

is randomly generating a message which sometimes has some stuff that gets escaped.

So, I think we should not randomly generate the message.
Either
a) set a message string that doesn't need escaping
or
b) set a message that does need escaping
or..
c) both

and then make the tests test what we expect will happen.

Status: Needs review » Needs work

The last submitted patch, 51: replace-most-2506445-51.patch, failed testing.

Anonymous’s picture

Status: Needs work » Needs review
FileSize
539.17 KB

Hopefully this applies and brings us down to only one fail.

Status: Needs review » Needs work

The last submitted patch, 54: replace-most-2506445-54.patch, failed testing.

Anonymous’s picture

I've taken this as far as I can get with it.

It seems like ConfigImporter::logError is not marking as safe. So when we run the test we are getting this:

$logs[0] (populated by ConfigImporter::logError) :
'Unexpected error during import with operation create for config_test.dynamic.primary: 'config_test' entity with ID 'secondary' already exists.'

expected :
'Unexpected error during import with operation create for config_test.dynamic.primary: \'config_test\' entity with ID \'secondary\' already exists.'

Anonymous’s picture

FileSize
930 bytes

Here is something resembling an interdiff (used git show on my working branch) for my change between comments #51 and #54 which fixes one of the errors.

nlisgo’s picture

I seem to be getting the following for $logs[0]:

string(162) "Unexpected error during import with operation create for config_test.dynamic.primary: &#039;config_test&#039; entity with ID &#039;secondary&#039; already exists."

And the expected is:

string(142) "Unexpected error during import with operation create for config_test.dynamic.primary: 'config_test' entity with ID 'secondary' already exists."
Anonymous’s picture

Git blame reveals that this was done on purpose in #2514044: Do not use SafeMarkup::format in exceptions.

So maybe we should just revert that failing change?

Anonymous’s picture

Status: Needs work » Needs review
FileSize
535.74 KB
3.43 KB

Taking ConfigImporter out of the equation for now, we will create a new issue to address use of !placeholder there.

nlisgo’s picture

Could this be the solution?

nlisgo’s picture

  1. +++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
    @@ -762,7 +763,7 @@ protected function processConfiguration($collection, $op, $name) {
         catch (\Exception $e) {
    -      $this->logError($this->t('Unexpected error during import with operation @op for @name: !message', array('@op' => $op, '@name' => $name, '!message' => $e->getMessage())));
    +      $this->logError($this->t('Unexpected error during import with operation @op for @name: @message', array('@op' => $op, '@name' => $name, '@message' => SafeMarkup::format($e->getMessage()))));
    

    The SafeMarkup::format around the $e->getMessage is consistent with what we do in Drupal\config\Tests\ConfigImporterTest::testSecondaryWriteSecondaryFirst

  2. +++ b/core/modules/config/src/Tests/ConfigImporterTest.php
    @@ -296,7 +296,7 @@ function testSecondaryWriteSecondaryFirst() {
         $message = SafeMarkup::format("'config_test' entity with ID '@name' already exists", array('@name' => 'secondary'));
    -    $this->assertEqual($logs[0], SafeMarkup::format('Unexpected error during import with operation @op for @name: !message.', array('@op' => 'create', '@name' => $name_primary, '!message' => $message)));
    +    $this->assertEqual($logs[0], SafeMarkup::format('Unexpected error during import with operation @op for @name: @message.', array('@op' => 'create', '@name' => $name_primary, '@message' => $message)));
       }
    

    The $message is the return of SafeMarkup::format()

Anonymous’s picture

Re: #61... hope so!

If not... we can deal with ConfigImporter in #2551743: Replace !placeholder references in Config with @placeholder.

The last submitted patch, 60: replace-most-2506445-60.patch, failed testing.

YesCT’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll
Anonymous’s picture

Rerolled. However, the test (\Drupal\user\Tests\UserBlocksTest) no longer passes locally, running that same test on 8.0.x branch also fails locally.

Anonymous’s picture

Status: Needs work » Needs review
Anonymous’s picture

Issue tags: -Needs reroll
nlisgo’s picture

\Drupal\user\Tests\UserBlocksTest passes for me locally and it appears to have passed on the testbot.

geertvd’s picture

Status: Needs review » Needs work
  1. +++ b/core/includes/install.core.inc
    @@ -2027,7 +2027,13 @@ function install_check_translations($langcode, $server_pattern) {
    +      'description' => t('The installer requires to contact the translation server to download a translation file. Check your internet connection and verify that your website can reach the translation server at <a href="@
    +@
    +@server_url">@
    +@
    +@server_url</a>.', array('@
    +@
    +@server_url' => $server_url)),
    

    We are doing this a couple of times, any reason why?

  2. +++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
    @@ -762,7 +763,7 @@ protected function processConfiguration($collection, $op, $name) {
    +      $this->logError($this->t('Unexpected error during import with operation @op for @name: @message', array('@op' => $op, '@name' => $name, '@message' => SafeMarkup::format($e->getMessage()))));
    

    We shouldn't be using SafeMarkup::format() without arguments, it's basically the same as calling SafeMarkup::set() #2547851: SafeMarkup::format() should require arguments without them it is just SafeMarkup::set() in disguise

Anonymous’s picture

Revised per #70.2 after consulting some of the other sprinters.

Anonymous’s picture

Status: Needs work » Needs review
Anonymous’s picture

Removed the unsightly formatting referenced in #70.1 above.

geertvd’s picture

Status: Needs review » Needs work
+++ b/core/modules/locale/locale.module
@@ -149,28 +149,36 @@ function locale_help($route_name, RouteMatchInterface $route_match) {
+      $output .= '<dd>' . t('Translation files with translated interface text are imported automatically when languages are added on the <a href="@languages">Languages</a> page, or when modules or themes are enabled. On the <a href="@locale-settings">Settings</a> page, the <em>Translation source</em> can be restricted to local files only, or to include the <a href="@
+@
+@server">Drupal translation server</a>. Although modules and themes may not be fully translated in all languages, new translations become available frequently. You can specify whether and how often to check for translation file updates and whether to overwrite existing translations on the <a href="@locale-settings">Settings</a> page. You can also manually import a translation file on the <a title="User interface translation import" href="@import">Import</a> page.', array('@import' => \Drupal::url('locale.translate_import'), '@locale-settings' => \Drupal::url('locale.settings'), '@languages' => \Drupal::url('entity.configurable_language.collection'), '@
+@
+@server' => 'https://localize.drupal.org')) . '</dd>';
...
+      $output .= '<dd>' . t('You can check how much of the interface on your site is translated into which language on the <a href="@languages">Languages</a> page. On the <a href="@translation-updates">Available translation updates</a> page, you can check whether interface translation updates are available on the <a href="@
+@
+@server">Drupal translation server</a>.', array('@languages' => \Drupal::url('entity.configurable_language.collection'), '@translation-updates' => \Drupal::url('locale.translate_status'), '@
+@
+@server' => 'https://localize.drupal.org')) . '<dd>';

+++ b/core/modules/node/node.module
@@ -82,19 +82,23 @@ function node_help($route_name, RouteMatchInterface $route_match) {
+      $output .= '<dd>' . t('The Node module makes a number of permissions available for each content type, which can be set by role on the <a href="@
+@
+@permissions">permissions page</a>.', array('@
+@
+@permissions' => \Drupal::url('user.admin_permissions', array(), array('fragment' => 'module-node')))) . '</dd>';

+++ b/core/modules/path/path.module
@@ -20,13 +20,17 @@ function path_help($route_name, RouteMatchInterface $route_match) {
+      $output .= '<dd>' . t('If you create or edit a taxonomy term you can add an alias (for example <em>music/jazz</em>) in the field "URL alias". When creating or editing content you can add an alias (for example <em>about-us/team</em>) under the section "URL path settings" in the field "URL alias". Aliases for any other path can be added through the page <a href="@aliases">URL aliases</a>. To add aliases a user needs the permission <a href="@
+@
+@permissions">Create and edit URL aliases</a>.', array('@aliases' => \Drupal::url('path.admin_overview'), '@
+@
+@permissions' => \Drupal::url('user.admin_permissions', array(), array('fragment' => 'module-path')))) . '</dd>';

+++ b/core/modules/statistics/statistics.module
@@ -19,13 +19,17 @@ function statistics_help($route_name, RouteMatchInterface $route_match) {
+      $output .= '<dd>' . t('The Statistics module includes a counter for each page that increases whenever the page is viewed. To use the counter, enable <em>Count content views</em> on the <a href="@statistics-settings">Statistics page</a>, and set the necessary <a href="@
+@
+@permissions">permissions</a> (<em>View content hits</em>) so that the counter is visible to the users.', array('@statistics-settings' => \Drupal::url('statistics.settings'), '@
+@
+@permissions' => \Drupal::url('user.admin_permissions', array(), array('fragment' => 'module-statistics')))) . '</dd>';

+++ b/core/modules/taxonomy/taxonomy.module
@@ -41,20 +41,24 @@ function taxonomy_help($route_name, RouteMatchInterface $route_match) {
+      $output .= '<p>' . t('The Taxonomy module allows users who have permission to create and edit content to categorize (tag) content of that type. Users who have the <em>Administer vocabularies and terms</em> <a href="@
+@
+@permissions" title="Taxonomy module permissions">permission</a> can add <em>vocabularies</em> that contain a set of related <em>terms</em>. The terms in a vocabulary can either be pre-set by an administrator or built gradually as content is added and edited. Terms may be organized hierarchically if desired.', array('@
+@
+@permissions' => \Drupal::url('user.admin_permissions', array(), array('fragment' => 'module-taxonomy')))) . '</p>';
+      $output .= '<p>' . t('For more information, see the <a href="@taxonomy">online documentation for the Taxonomy module</a>.', array('@taxonomy' => 'https://www.drupal.org/documentation/modules/taxonomy/')) . '</p>';

+++ b/core/modules/user/user.module
@@ -75,10 +75,14 @@ function user_help($route_name, RouteMatchInterface $route_match) {
+      return '<p>' . t('A role defines a group of users that have certain privileges. These privileges are defined on the <a href="@
+@
+@permissions">Permissions page</a>. Here, you can define the names and the display sort order of the roles on your site. It is recommended to order roles from least permissive (for example, Anonymous user) to most permissive (for example, Administrator user). Users who are not logged in have the Anonymous user role. Users who are logged in have the Authenticated user role, plus any other roles granted to their user account.', array('@
+@
+@permissions' => \Drupal::url('user.admin_permissions'))) . '</p>';

Missed some, also interdiffs are really needed when making changes on this size of a patch.

geertvd’s picture

+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
@@ -762,7 +764,7 @@ protected function processConfiguration($collection, $op, $name) {
+      $this->logError($this->t('Unexpected error during import with operation @op for @name: @message', array('@op' => $op, '@name' => $name, '@message' => SafeString::create($e->getMessage()))));

I'm not sure if this is the best alternative to SafeMarkup::format either, don't know what the better alternative is though.
I looked this up and this actually had an @ before but was changed in #2514044: Do not use SafeMarkup::format in exceptions

Anonymous’s picture

Re: #75 as noted above I took the advice of Joel Pittet who is here sprinting with us, as he knows more about it than I do.

Anonymous’s picture

Status: Needs work » Needs review
FileSize
538.43 KB
14.47 KB
geertvd’s picture

Besides my open question in #75 the patch looks good, would be great of someone else can confirm that it's ok to use SafeString::create() here.

joelpittet’s picture

@geertvd regarding #75 using SafeString::create() instead of SafeMarkup, allows us to mark the string as safe without poluting the large list of safeStrings that it holds on it. So we are slowly but surely moving away from SafeMarkup and towards SafeString as it is closer to what we aimed to do in the original autoescape issue and what Twig_Markup does.

That being said... I think we need to just be careful just the same as SafeMarkup::set() can be abused if used improperly... If we don't mark the string as safe and we use '@' it will escape everything in that variable, I'm curious what's in that variable that would cause escaping to produce negative results?

  1. +++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
    @@ -7,6 +7,8 @@
    +use Drupal\Component\Utility\SafeMarkup;
    

    This is an un-used use statement.

  2. +++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
    @@ -762,7 +764,7 @@ protected function processConfiguration($collection, $op, $name) {
    -      $this->logError($this->t('Unexpected error during import with operation @op for @name: !message', array('@op' => $op, '@name' => $name, '!message' => $e->getMessage())));
    +      $this->logError($this->t('Unexpected error during import with operation @op for @name: @message', array('@op' => $op, '@name' => $name, '@message' => SafeString::create($e->getMessage()))));
    

    I could be wrong but this is because the message has backtraces in it's message or some other HTML?

Anonymous’s picture

Remove unused SafeMarkup from #79.1.

geertvd’s picture

+++ b/core/modules/config/src/Tests/ConfigImporterTest.php
@@ -296,7 +296,7 @@ function testSecondaryWriteSecondaryFirst() {
     $message = SafeMarkup::format("'config_test' entity with ID '@name' already exists", array('@name' => 'secondary'));

The problematic variable is this one.
Doesn't SafeMarkup::format() mark a string as safe? So I really don't understand why the @placeholder is not inserting it unescaped.
Could be saying something silly here, that SafeMarkup stuff can get confusing.

Anonymous’s picture

I don't have a solution either, per my comment in #56.

Anonymous’s picture

I'm told that this is going to take many hours and further revisions to get to RTBC, and as the sprint I'm at is ending in 2h, I am going to move on to other tasks. Good luck here folks.

Status: Needs review » Needs work

The last submitted patch, 80: replace-most-2506445-80.patch, failed testing.

justAChris’s picture

Status: Needs work » Needs review
FileSize
511.89 KB
122.92 KB

Reroll of patch on #80.

Further investigation into ConfigImporter & ConfigImporterTest to hopefully help answer questions in #79 & #81

The error in $e->getMessage() is an exception thrown here:

EntityStorageBase:: doPreSave()

protected function doPreSave(EntityInterface $entity) {
    $id = $entity->id();

    // Track the original ID.
    if ($entity->getOriginalId() !== NULL) {
      $id = $entity->getOriginalId();
    }

    // Track if this entity exists already.
    $id_exists = $this->has($id, $entity);

    // A new entity should not already exist.
    if ($id_exists && $entity->isNew()) {
      throw new EntityStorageException("'{$this->entityTypeId}' entity with ID '$id' already exists.");

It looks like the only characters to get escaped are the quotes unless the ID or entityTypeId have special characters. Not sure if this means we are comfortable with marking this safe? I guess if you can mess with the configuration import (files), you could do other security damage?

Looking at the output to the user, manual testing of this error produce the same visual output with the different escape / print methods. A screen grab is attached of that output. The source is different (the escaped single quote):

In ConfigImporter::processConfiguration()
Bang ( '!message' => $e->getMessage() )

<div role="alert">
  <h2 class="visually-hidden">Error message</h2>
    Unexpected error during import with operation create for config_test.dynamic.primary: &#039;config_test&#039; entity with ID &#039;secondary&#039; already exists.
</div>

SafeString @ ( '@message' => SafeString::create($e->getMessage()) )

<div role="alert">
  <h2 class="visually-hidden">Error message</h2>
    Unexpected error during import with operation update for config_test.dynamic.primary: 'config_test' entity with ID 'secondary' already exists.
</div>

@ only ( '@message' => $e->getMessage() )

<div role="alert">
  <h2 class="visually-hidden">Error message</h2>
    Unexpected error during import with operation update for config_test.dynamic.primary: &#039;config_test&#039; entity with ID &#039;secondary&#039; already exists.
</div>

Regarding ConfigImporterTest::testSecondaryWriteSecondaryFirst(), we don't need to mark these safe, as long as the assertions match the logged value. To avoid using SafeMarkup::format, we could do something like:

+use Drupal\Component\Utility\Html;

@@ -295,8 +296,8 @@ function testSecondaryWriteSecondaryFirst() {
 
     $logs = $this->configImporter->getErrors();
     $this->assertEqual(count($logs), 1);
-    $message = SafeMarkup::format("'config_test' entity with ID '@name' already exists", array('@name' => 'secondary'));
-    $this->assertEqual($logs[0], SafeMarkup::format('Unexpected error during import with operation @op for @name: @message.', array('@op' => 'create', '@name' => $name_primary, '@message' => $message)));
+    $message = Html::escape("'config_test' entity with ID 'secondary' already exists");
+    $this->assertEqual($logs[0], "Unexpected error during import with operation create for " . $name_primary . ": " . $message . ".");
   }

We can drop the Html::escape() if the single quotes aren't escaped in the error.

I'm sure there are more efficient methods to reproduce the error manually, but here's how I did it:

  1. Grab Exported config from failing test. I’ve placed a copy of this: https://github.com/justAChris/DrupalConfigFail
  2. Add config_test, config_import_test modules from config test directory /core/modules/config/tests/ and Enable
  3. Export databse config to staging folder (drush config-export)
  4. Add failing test files from step 1 to staging folde
  5. Synchronize configuration at /admin/config/development/configuration, observe
xjm’s picture

Related issue: #2558791: "!"-prefixed tokens should Xss::filterAdmin() but not affect safeness

I'd really like to break this patch into smaller pieces. It is unmanageable and unreviewable as-is.

justAChris’s picture

I'd imagine it is uncommittable as well even if it did get to that stage. Not sure if it's helpful but attached a list of all the files touched by the latest reroll (#85).
205 Files, not sure the method to break this down, by module & core subsystem?

joelpittet’s picture

Category: Task » Plan

That is helpful @justAChris: Some things relate to their tests but for the most part they can be hunked together.
Could you do the same thing but also show the diff --stats so we know the how many changes are in the files?

Let's find the largest set of changes in a module or subsystem and group a couple of those to hack hunks of this patch down quick. Then we can deal with the one-off and smaller bits likely in this issue as hopefully a <100K patch.

justAChris’s picture

FileSize
12.36 KB

Stats for latest reroll attached.

Not sure if @xjm intended to move this planning to #2506427: [meta] !placeholder causes strings to be escaped and makes the sanitization API harder to understand since that was marked as meta.

justAChris’s picture

Status: Needs review » Active

At the very least this is back to Active now, if not closed (duplicate).

joelpittet’s picture

Category: Plan » Task

Whoops meta meta

joelpittet’s picture

FileSize
42.81 KB

OK perfect, while doing this I realized a bunch were in hook_help text, maybe even the majority. Just a side note...

Here's the list in 85 ordered by changes.

joelpittet’s picture

@justAChris If we close this we just need to make sure people who worked on it get credited in the spin-off issue(s).

Here's a proposal for splitting this into chunks:

  1. Contact: core/modules/contact/*
  2. Views: core/modules/views/*
  3. Comment: core/modules/comment/*
  4. Migrate: core/modules/migrate/*
  5. Skipping System module because it's a bit of a grab bag and Form stuff.
  6. Views UI: core/modules/views_ui/*
  7. Language: core/modules/language/*
  8. Locale: core/modules/locale/*
  9. Update: core/modules/update/*
  10. User: core/modules/user/*
  11. SimpleTest: core/modules/simpletest/*
  12. Search: core/modules/search/*
  13. Help: core/modules/help/*
  14. Skipping SysLog Stuff but may affect Migrate
  15. Node: core/modules/node/*
  16. Config Translation: core/modules/config_translation/*
  17. Block & Block Content: core/modules/block*
  18. Aggregator: core/modules/aggregator/*

Cherry picking a bit but how does that sound?

justAChris’s picture

First child issue added (for contact module): #2559435: Replace !placeholder with @placeholder in Contact module

justAChris’s picture

Title: Replace most !placeholder with @placeholder » Replace remaining !placeholder with @placeholder

Items 1-18 on #93 have been opened (with exception of 5 & 14) as child issues of #2506427: [meta] !placeholder causes strings to be escaped and makes the sanitization API harder to understand and marked related to this.

Per conversation w/ @joelpittet on irc, this issue should cover anything not covered by new issues, re-titled as such. This issue may be postponed until we determine the scope of "remaining".

For future reference, @joelpittet won the issue opening race :p

joelpittet’s picture

Here's a re-roll and just to help with those split offs I've added a test for all help pages!

Maybe it would be worth doing the tests in one shot with this test in play that way people aren't doing the hook_help() test which are probably the bulk of this patch.

joelpittet’s picture

I opened it up, it may mean a bit of re-rolling on some of the other issues but I think it will be worth it because it's 300k from this patch and and automated test to cover them all in two assert lines.

#2560783: Replace !placeholder with :placeholder for URLs in hook_help() implementations

alexpott’s picture

Status: Needs review » Needs work
+++ b/core/includes/file.inc
@@ -371,8 +371,8 @@ function file_save_htaccess($directory, $private = TRUE, $force_overwrite = FALS
+    $variables = array('%directory' => $directory, '@htaccess' => '<br />' . nl2br(Html::escape($htaccess_lines)));
+    \Drupal::logger('security')->error("Security warning: Couldn't write .htaccess file. Please create a .htaccess file in your %directory directory which contains the following lines: <code>@htaccess

", $variables);

This is double escape in a nut-shell. See #2564321: file_save_htaccess() generates error logs which are escaped incorrectly for a proper fix.

nlisgo’s picture

Assigned: Unassigned » nlisgo

I will review the issue referenced in #98 and prepare a patch to address the double escape.

nlisgo’s picture

Reroll necessary since the following issue was fixed: #2560733: Remove a few problematic t() calls from tests

I will address the feedback in #98 next.

nlisgo’s picture

Status: Needs work » Needs review
FileSize
1001 bytes
504.11 KB

This addresses the feedback in #98.

If #2564321: file_save_htaccess() generates error logs which are escaped incorrectly gets committed before this issue we will be removing the changes to core/includes/file.inc entirely as the code change is identical.

nlisgo’s picture

Assigned: nlisgo » Unassigned
geertvd’s picture

Since we are doing that fix in #2564321: file_save_htaccess() generates error logs which are escaped incorrectly we shouldn't do the fix here also, IMO it should just remove that from the patch right away.

nlisgo’s picture

@geertvd that had occurred to me but if we did that we would need to postpone this issue until that one was committed?

My opinion is that I feel comfortable including it in both as it is not the significant portion of either patch. And it removes the dependency chain for each issue.

Happy to fall in though but I understood from the comment in #98 by @alexpott that including the same fix was being requested.

Leaving as needs review unless anyone feels very strongly about it.

alexpott’s picture

Status: Needs review » Postponed
Related issues: +#2558791: "!"-prefixed tokens should Xss::filterAdmin() but not affect safeness

We're also discussing the ! in #2558791: "!"-prefixed tokens should Xss::filterAdmin() but not affect safeness. Given the discussions there I think we should postpone this.

alexpott’s picture

Can Ryan Weal, nlisgo, subhojit777, and justAChris comment on #2564353: Remove !placeholder usage from SafeMarkup::format() so they can get credit.

alexpott’s picture

Status: Postponed » Needs work

I think we could rescope this issue to fix all of the !placeholder by doing the following regex on the code base [\s>.\(]t\('[^']*(?<!href=")![a-zA-Z].

This issue should not convert:

  • !placeholder where the placeholder is a url
  • !placeholder where output of t() is being used for non-HTML such as an email

There will be around 170 or so things to fix.

xjm’s picture

Just a note for future reference -- "Per module" is rarely the best way to scope the children of the meta issue. We should focus the scope on the specific kinds of conceptual problems we're solving. For example, "Remove ! usage in test assertion messages". (More suggestions in this draft on issue scoping).

Also, in general, it's better to get the first child issue in first before spending time creating lots of others, and then to create the others from a list in the meta only as they are needed.

xjm’s picture

Title: Replace remaining !placeholder with @placeholder » Replace !placeholder with @placeholder in t() for non-URLs

Retitling for #107.

xjm’s picture

I can't get the regex in #107 to work in bash.

joelpittet’s picture

Issue summary: View changes
FileSize
38.54 KB

@xjm try this if you use ag.
ag '[\s>.\(]t\('[^']*(?<!href=")![a-zA-Z]'
Single quotes being of utmost importance.

EDIT: Well that didn't work actually, bash sucks and I forgot to escape things...

xjm’s picture

This should work in bash, on mac, to look for the ones I was previously matching in #1 and then just exclude hrefs that have a ! placeholder:

egrep -r '\Wt\(.*\!([a-zA-Z])+' * | grep -v "vendor" | grep -v ".js" | grep -v .css | grep -v "~" | grep -v 'href="!'
xjm’s picture

Issue summary: View changes

Adding a working bash command to the summary.

xjm’s picture

Status: Needs work » Active

Also, setting to active to indicate that we should start with a fresh patch.

170 usages is still kind of a lot. I'd suggest splitting it up more than this (but conceptually, not per module). A good first set of changes would be assertion messages in tests, maybe.

xjm’s picture

Also, see #2564353: Remove !placeholder usage from SafeMarkup::format() -- a lot of the comments on that issue will be relevant for these as well.

rpayanm’s picture

Assigned: Unassigned » rpayanm

Let me try!

rpayanm’s picture

Assigned: rpayanm » Unassigned
Status: Active » Needs review
FileSize
36.95 KB

There are still changes... I am continue tomorrow.

@xjm the bash command, I think that have false positives, here a example:

core/lib/Drupal/Core/Datetime/Element/Datelist.php: $form_state->setError($element, t('The %field date is invalid.', array('%field' => !empty($element['#title']) ? $element['#title'] : '')));

Status: Needs review » Needs work

The last submitted patch, 117: 2506445-117.patch, failed testing.

The last submitted patch, 117: 2506445-117.patch, failed testing.

alexpott’s picture

This will need a reroll now that #2564353: Remove !placeholder usage from SafeMarkup::format() has landed and that will fix the config tests.

+++ b/core/lib/Drupal/Core/Mail/MailManagerInterface.php
@@ -67,8 +67,8 @@
-   *         $message['subject'] = t('Notification from !site', $variables, $options);
-   *         $message['body'][] = t("Dear !username\n\nThere is new content available on the site.", $variables, $options);
+   *         $message['subject'] = t('Notification from @site', $variables, $options);
+   *         $message['body'][] = t("Dear @username\n\nThere is new content available on the site.", $variables, $options);

+++ b/core/modules/contact/contact.module
@@ -140,14 +140,14 @@ function contact_mail($key, &$message, $params) {
-      $message['subject'] .= t('[!form] !subject', $variables, $options);
-      $message['body'][] = t("!sender-name (!sender-url) sent a message using the contact form at !form-url.", $variables, $options);
+      $message['subject'] .= t('[@form] @subject', $variables, $options);
+      $message['body'][] = t("@sender-name (@sender-url) sent a message using the contact form at @form-url.", $variables, $options);
...
-      $message['subject'] .= t('[!form] !subject', $variables, $options);
+      $message['subject'] .= t('[@form] @subject', $variables, $options);

@@ -157,10 +157,10 @@ function contact_mail($key, &$message, $params) {
-      $message['subject'] .= t('[!site-name] !subject', $variables, $options);
-      $message['body'][] = t('Hello !recipient-name,', $variables, $options);
-      $message['body'][] = t("!sender-name (!sender-url) has sent you a message via your contact form at !site-name.", $variables, $options);
-      $message['body'][] = t("If you don't want to receive such emails, you can change your settings at !recipient-edit-url.", $variables, $options);
+      $message['subject'] .= t('[@site-name] @subject', $variables, $options);
+      $message['body'][] = t('Hello @recipient-name,', $variables, $options);
+      $message['body'][] = t("@sender-name (!sender-url) has sent you a message via your contact form at @site-name.", $variables, $options);
+      $message['body'][] = t("If you don't want to receive such emails, you can change your settings at @recipient-edit-url.", $variables, $options);

+++ b/core/modules/contact/src/MailHandler.php
@@ -91,7 +91,7 @@ public function sendMailMessages(MessageInterface $message, AccountInterface $se
-      $sender_cloned->name = $this->t('!name (not verified)', array('!name' => $message->getSenderName()));
+      $sender_cloned->name = $this->t('@name (not verified)', array('@name' => $message->getSenderName()));

+++ b/core/modules/contact/src/Tests/ContactPersonalTest.php
@@ -83,7 +83,7 @@ function testSendPersonalContactMessage() {
-    $this->assertEqual($mail['subject'], t('[!site-name] !subject', $variables), 'Subject is in sent message.');
+    $this->assertEqual($mail['subject'], t('[@site-name] @subject', $variables), 'Subject is in sent message.');

Not correct - these are non html usage. And should not be changed in this issue.

rpayanm’s picture

Status: Needs work » Needs review
FileSize
31.6 KB
4.9 KB

Reroll and @alexpott's suggestions.

justAChris’s picture

Posting a the results of the two regular expressions used thus far to find !placeholder in non href strings for comparison. Just cross verifying that they mainly produce the same results (with a few exceptions) to make sure we attempt to find all instances, which is the goal regardless of what regex is used.

non-href-slice-n-dice.txt using the grep currently listed in the issue summary.
non-href-lookbehind.txt is using the regex found in #107

Status: Needs review » Needs work

The last submitted patch, 121: 2506445-121.patch, failed testing.

The last submitted patch, 121: 2506445-121.patch, failed testing.

justAChris’s picture

Per #114 and irc conversation with @xjm and @joelpittet, the subset of this patch that are contained in test assertions has been split off: #2566503: [meta] Replace remaining !placeholder for Non-URL HTML outputs only.

This new issue should be actionable now as its resolution appears to be independent of the result of planning in the parent meta issue.

subhojit777’s picture

Status: Needs work » Needs review
FileSize
31.32 KB
1010 bytes

Managed to fix one failing test.

Status: Needs review » Needs work

The last submitted patch, 126: replace_placeholder-2506445-126.patch, failed testing.

subhojit777’s picture

Status: Needs work » Needs review
FileSize
31.34 KB

Straight reroll.

The last submitted patch, 126: replace_placeholder-2506445-126.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 128: replace_placeholder-2506445-128.patch, failed testing.

The last submitted patch, 128: replace_placeholder-2506445-128.patch, failed testing.

justAChris’s picture

Issue summary: View changes

Updating Bash command in issue summary to indicate that the replacement/removal in Tests should be handled in a different issue, currently #2566503: [meta] Replace remaining !placeholder for Non-URL HTML outputs only.

Sutharsan’s picture

I am aware that the replacements in tests will be handled in a different issue, but still investigate the errors. They need to be fixed any way. This is the first one:

+++ b/core/modules/node/src/Tests/NodeEditFormTest.php
@@ -78,7 +78,7 @@ public function testNodeEdit() {
     // Check that the title and body fields are displayed with the correct values.
     $active = '<span class="visually-hidden">' . t('(active tab)') . '</span>';
-    $link_text = t('!local-task-title!active', array('!local-task-title' => t('Edit'), '!active' => $active));
+    $link_text = t('@local-task-title@active', array('@local-task-title' => t('Edit'), '@active' => $active));
     $this->assertText(strip_tags($link_text), 0, 'Edit tab found and marked active.');
     $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');

This test fails because @placehoders are escaped the $link_text will now for example contain &lt; instead of <

Sutharsan’s picture

Assigned: Unassigned » Sutharsan
+++ b/core/includes/install.inc
@@ -558,7 +558,7 @@ function drupal_verify_profile($install_state) {
diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php

diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php
index c02d4fe..13b8795 100644

index c02d4fe..13b8795 100644
--- a/core/lib/Drupal/Core/Config/ConfigImporter.php

--- a/core/lib/Drupal/Core/Config/ConfigImporter.php
+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php

+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
@@ -762,7 +762,7 @@ protected function processConfiguration($collection, $op, $name) {

@@ -762,7 +762,7 @@ protected function processConfiguration($collection, $op, $name) {
       }
     }
     catch (\Exception $e) {
-      $this->logError($this->t('Unexpected error during import with operation @op for @name: !message', array('@op' => $op, '@name' => $name, '!message' => $e->getMessage())));
+      $this->logError($this->t('Unexpected error during import with operation @op for @name: @message', array('@op' => $op, '@name' => $name, '@message' => $e->getMessage())));
       // Error for that operation was logged, mark it as processed so that

Working on a new patch ...

The ConfigImporterTest test fails because @message contains quotes that get encoded due to the @placeholder

Sutharsan’s picture

Assigned: Sutharsan » Unassigned
Status: Needs work » Needs review
FileSize
32.63 KB
2.19 KB
subhojit777’s picture

@Sutharsan thanks for working on this. Would you like to write a patch for this issue #2509218: Ensure that SafeString objects can be used in non-HTML contexts as well. There are some tests failing there which are same as you just fixed here.

Sutharsan’s picture

@sughojit777 I Currently focus on those issues that are likely to be marked critical as per #2506427-51: [meta] !placeholder causes strings to be escaped and makes the sanitization API harder to understand.

webchick’s picture

Question. If this is scriptable, would it help if we instituted a small "commit freeze," rolled the mega-patch once, and committed it all in one go? If so, I'd be available later on today to do this.

Sutharsan’s picture

would it help if we instituted a small "commit freeze" ...

Nah, chasing head is fun ;) I'm currently checking the existing 'Replace !placeholder' patches. 1/3rd needs a reroll and most of the patches are only 6 - 10 days old. A freeze would help, but lets not rush. Get a combined and bot tested patch first, do some basic testing and then find a good moment to commit. Rerolling these patches is not super complicated and rerolling a single patch is already a lot better than 18 of them.

Sutharsan’s picture

This is the combined patch of the following issues:

  • 2506445 This issue
  • 2551743 Config, Credits to joelpittet, lauriii, Sutharsan
  • 2559435 Contact module, Credits to geertvd, izus, Sutharsan
  • 2559441 Views module, Credits to geertvd, joelpittet, Sutharsan
  • 2559445 Aggregator module, Credits to geertvd
  • 2559447 Block & Block Content modules, Credits to joelpittet, geertvd
  • 2559449 Config Translation module, Credits to geertvd, joelpittet
  • 2559451 Node module, Credits to geertvd, joelpittet, Sutharsan
  • 2559453 Help module, Credits to joelpittet
  • 2559455 Search module, Credits to joelpittet, izus
  • 2559459 User module, Credits to HOG, andypost, borisson_
  • 2559461 Comment module, Credits to izus, joelpittet, Sutharsan
  • 2559467 Migrate and migrate_drupal modules, Credits to joelpittet
  • 2559469 Update module, Credits to izus, joelpittet, Sharique
  • 2559471 views_ui module, Credits to joelpittet
  • 2559475 Language module Credits to Sutharsan, joelpittet
  • 2559479 Locale module, Credits to joelpittet, Sutharsan
  • 2560783 hook_help(), Credits to joelpittet, lauriii, Sutharsan

Status: Needs review » Needs work

The last submitted patch, 140: replace_placeholder-2506445-140.patch, failed testing.

The last submitted patch, 140: replace_placeholder-2506445-140.patch, failed testing.

Sutharsan’s picture

Status: Needs work » Needs review
FileSize
419.57 KB

Pls ignore patch in #140, it doesn't apply.

xjm’s picture

Title: Replace !placeholder with @placeholder in t() for non-URLs » Replace !placeholder with @placeholder in t() for non-URLs in tests
Issue summary: View changes
Status: Needs review » Needs work

Just to reiterate, this patch must not include places where the placeholder is used for URLs, because that needs to be explored separately. See #2565895: Add a new :placeholder to SafeMarkup::format() for URLs that handles bad protocols.

This patch should also not include placeholders that are being used for a non-HTML context e.g. email messages, because those need to be handled separately as well. See #2509218: Ensure that SafeString objects can be used in non-HTML contexts.

So the regex in the summary is a start, but we still need to look at each usage rather than just scripting the conversions. This is why I suggest starting with tests only. Lower risk and more manageable. Retitling to indicate that and updating the regex to target that.

Once that's in, we can tackle the non-test ones.

xjm’s picture

Status: Needs work » Active

Actually setting active again, to indicate again we need to start afresh, not update the existing patch or combine other patches. :)

xjm’s picture

Issue summary: View changes

Er. Fixing the grep command.

Sutharsan’s picture

Status: Active » Needs review
FileSize
58.01 KB

Ok, new patch.
This replaces the !placeholders in *Test.php files according to the regex in the issue summary.

webchick’s picture

@Sutharsan: Out of curiosity, what command did you pipe that into to do the actual find/replacing? This way you could go to bed sometime soon and someone from North America / Australia could take over if they were so inclined. :D

Sutharsan’s picture

@webchick, yes going to bed is my next priority.
I used the patch from #143 as starting point and only used the Test.php file from it (the regex script filters on presence of 'Text.php' in the file name). Next I used the regex to find the remaining !placeholders and find/replace the with an editor (not typing, too much risk of typo). As last step (this new patch) check for 'href=' or 'src=' in the patch and revert those changes. And search for usage in mail context (#144). That was my recipe.

This patch reverts changes for URL usage. No mail (or other non-html) usage identified.

The last submitted patch, 147: replace_placeholder-2506445-146.patch, failed testing.

The last submitted patch, 147: replace_placeholder-2506445-146.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 149: replace_placeholder-2506445-149.patch, failed testing.

xjm’s picture

Note that the next step after this one is passing will be #2566503: [meta] Replace remaining !placeholder for Non-URL HTML outputs only.

The last submitted patch, 149: replace_placeholder-2506445-149.patch, failed testing.

xjm’s picture

Thanks @Sutharsan.

+++ b/core/modules/block/src/Tests/BlockXssTest.php
@@ -80,7 +80,7 @@ protected function doViewTest() {
-    $this->assertRaw('alert("view");');
+    $this->assertRaw('alert(&quot;view&quot;);');

This change should not be made. It's changing the behavior of the test and not in scope. This looks like cruft from the old patch.

I'm not sure why it's better to reroll the stale patch than create a new one, but I guess someone can use the grep command with the patch applied, and at least with this patch size it's reviewable. Thanks!

xjm’s picture

Issue summary: View changes
+++ b/core/modules/system/src/Tests/Common/XssUnitTest.php
@@ -40,7 +40,7 @@ function testT() {
-    $text = t('Verbatim text: !value', array('!value' => '<script>'));
+    $text = t('Verbatim text: @value', array('@value' => '<script>'));

Ah, and this one is the unit test for !placeholder. We should remove this hunk from this patch, and instead handle this in the later issue that deprecates or removes !placeholder entirely.

xjm’s picture

+++ b/core/modules/link/src/Tests/LinkFieldTest.php
--- a/core/modules/locale/src/Tests/LocaleJavascriptTranslationTest.php
+++ b/core/modules/locale/src/Tests/LocaleJavascriptTranslationTest.php

+++ b/core/modules/locale/src/Tests/LocaleJavascriptTranslationTest.php
@@ -58,7 +58,7 @@ public function testFileParsing() {
       "Double Quote \\\"Escaped\\\" t" => '',
       'Double Quote Concat strings t' => '',
 
-      'Context !key Args t' => 'Context string',
+      'Context @key Args t' => 'Context string',
 
       'Context Unquoted t' => 'Context string unquoted',
       'Context Single Quoted t' => 'Context string single quoted',
@@ -73,7 +73,7 @@ public function testFileParsing() {

@@ -73,7 +73,7 @@ public function testFileParsing() {
       "Double Quote plural{$etx}Double Quote @count plural" => '',
       "Double Quote \\\"Escaped\\\" plural{$etx}Double Quote \\\"Escaped\\\" @count plural" => '',
 
-      "Context !key Args plural{$etx}Context !key Args @count plural" => 'Context string',
+      "Context @key Args plural{$etx}Context @key Args @count plural" => 'Context string',
 
       "Context Unquoted plural{$etx}Context Unquoted @count plural" => 'Context string unquoted',

I think these changes are also testing the behavior of the !placeholder functionality (or the discovery of strings with it) for the JavaScript equivalent of t(). I suggest we create a followup for this test and exclude it from the patch here.

xjm’s picture

+++ b/core/modules/help/src/Tests/HelpTest.php
@@ -113,6 +113,11 @@ protected function verifyHelp($response = 200) {
         foreach ($admin_tasks as $task) {
           $this->assertLink($task['title']);
         }
+        // Ensure there are no double escaped '&' or '<' characters.
+        $this->assertNoEscaped('&amp;');
+        $this->assertNoEscaped('&lt;');
+        // Ensure there are no escaped '<' characters.
+        $this->assertNoEscaped('<');
       }

Also, these assertions don't seem to be in scope either; maybe a separate issue?

xjm’s picture

@webchick, re: #148, the grep command is documented in the issue summary. It's not as simple as just scripting it, unfrotunately, because of all the side effects.

xjm’s picture

+++ b/core/modules/views/src/Tests/Handler/FieldWebTest.php
--- a/core/modules/views_ui/src/Tests/DisplayTest.php
+++ b/core/modules/views_ui/src/Tests/DisplayTest.php

+++ b/core/modules/views_ui/src/Tests/DisplayTest.php
@@ -225,16 +225,16 @@ public function testActionLinks() {
     $display_title_path = 'admin/structure/views/nojs/display/test_display/block_1/display_title';
     $this->drupalPostForm($display_title_path, array('display_title' => $display_title), t('Apply'));
 
-    $placeholder = array('!display_title' => $display_title);
+    $placeholder = array('@display_title' => $display_title);
     // Ensure that the dropdown buttons are displayed correctly.
-    $this->assertFieldByXpath('//input[@type="submit"]', t('Duplicate !display_title', $placeholder));
-    $this->assertFieldByXpath('//input[@type="submit"]', t('Delete !display_title', $placeholder));
-    $this->assertFieldByXpath('//input[@type="submit"]', t('Disable !display_title', $placeholder));
-    $this->assertNoFieldByXpath('//input[@type="submit"]', t('Enable !display_title', $placeholder));
+    $this->assertFieldByXpath('//input[@type="submit"]', t('Duplicate @display_title', $placeholder));
+    $this->assertFieldByXpath('//input[@type="submit"]', t('Delete @display_title', $placeholder));
+    $this->assertFieldByXpath('//input[@type="submit"]', t('Disable @display_title', $placeholder));
+    $this->assertNoFieldByXpath('//input[@type="submit"]', t('Enable @display_title', $placeholder));
 
     // Disable the display so we can test the rendering of the "Enable" button.
-    $this->drupalPostForm(NULL, NULL, t('Disable !display_title', $placeholder));
-    $this->assertFieldByXpath('//input[@type="submit"]', t('Enable !display_title', $placeholder));
-    $this->assertNoFieldByXpath('//input[@type="submit"]', t('Disable !display_title', $placeholder));
+    $this->drupalPostForm(NULL, NULL, t('Disable @display_title', $placeholder));
+    $this->assertFieldByXpath('//input[@type="submit"]', t('Enable @display_title', $placeholder));
+    $this->assertNoFieldByXpath('//input[@type="submit"]', t('Disable @display_title', $placeholder));

And, finally, the reason these are failing is that the display name is <test>. We should remove the t() calls entirely and just assert the raw expected output. This might be worth spinning off into its own issue too because it is a bit tricky and will be different from the other changes.

justAChris’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
5.53 KB
51.17 KB

Removed lines highlighted in comments #155 - #160.

Updated Issue Summary to indicate issues that should be filed to resolve this edge cases. I haven't yet filed them myself.
Regarding #158, those tests already exist in the hook_help() issue: #2560783: Replace !placeholder with :placeholder for URLs in hook_help() implementations. We should keep that issue open, but at postponed since it may come in handy if we change the placeholder in URLs

Also, haven't cross referenced against the bash script or any other regex to ensure that we've captured the entire scope.

Status: Needs review » Needs work

The last submitted patch, 161: replace_placeholder-2506445-161.patch, failed testing.

The last submitted patch, 161: replace_placeholder-2506445-161.patch, failed testing.

justAChris’s picture

Status: Needs work » Needs review
FileSize
944 bytes
50.25 KB

Revert core/modules/locale/src/Tests/LocaleJavascriptTranslationTest.php correctly this time.

Status: Needs review » Needs work

The last submitted patch, 164: replace_placeholder-2506445-164.patch, failed testing.

webchick’s picture

Status: Needs work » Needs review

Drupal\views\Tests\Plugin\DisplayFeedTest? Sounds like that may be spurious. Trying a re-rest, since DrupalCI liked it well enough.

The last submitted patch, 100: replace_remaining-2506445-100.patch, failed testing.

The last submitted patch, 100: replace_remaining-2506445-100.patch, failed testing.

joelpittet’s picture

Status: Needs review » Needs work
+++ b/core/modules/contact/src/Tests/ContactPersonalTest.php
@@ -79,12 +79,12 @@ function testSendPersonalContactMessage() {
-      '!site-name' => $this->config('system.site')->get('name'),
-      '!subject' => $message['subject[0][value]'],
-      '!recipient-name' => $this->contactUser->getUsername(),
+      '@site-name' => $this->config('system.site')->get('name'),
+      '@subject' => $message['subject[0][value]'],
+      '@recipient-name' => $this->contactUser->getUsername(),
...
-    $this->assertEqual($mail['subject'], t('[!site-name] !subject', $variables), 'Subject is in sent message.');
-    $this->assertTrue(strpos($mail['body'], 'Hello ' . $variables['!recipient-name']) !== FALSE, 'Recipient name is in sent message.');
+    $this->assertEqual($mail['subject'], t('[@site-name] @subject', $variables), 'Subject is in sent message.');
+    $this->assertTrue(strpos($mail['body'], 'Hello ' . $variables['@recipient-name']) !== FALSE, 'Recipient name is in sent message.');

These are for email tokens and I think they shouldn't be converted. I could be wrong but that is what I recall from one of the other issue and discussions with @effulgentsia

Sutharsan’s picture

Status: Needs work » Needs review
FileSize
1.75 KB
48.67 KB

These are for email tokens and I think they shouldn't be converted.

You are correct. No output escaping in email context, or other non-html output such as a webservice response. Their front-end (e.g. mail client) is responsible for that.

Sutharsan’s picture

Sutharsan’s picture

Issue summary: View changes
Novitsh’s picture

As far as #171 goes, looks OK to me.

justAChris’s picture

Status: Needs review » Needs work

About 20 of the replacements in the latest patch are in format_string() which looks to be outside the scope of this issue

+++ b/core/modules/aggregator/src/Tests/UpdateFeedItemTest.php
@@ -37,10 +37,10 @@ public function testUpdateFeedItem() {
-    $this->assertResponse(array(200), format_string('URL !url is accessible', array('!url' => $edit['url[0][value]'])));
+    $this->assertResponse(array(200), format_string('URL @url is accessible', array('@url' => $edit['url[0][value]'])));

And also, potentially wrong given 9.0.0 deprecation

On the positive side, running the bash grep in the issue summary against the patched codebase only returns items we have specifically excluded above:

core/modules/contact/src/Tests/ContactPersonalTest.php:    $this->assertEqual($mail['subject'], t('[!site-name] !subject', $variables), 'Subject is in sent message.');
core/modules/system/src/Tests/Common/XssUnitTest.php:    $text = t('Verbatim text: !value', array('!value' => '<script>'));
core/modules/views_ui/src/Tests/DisplayTest.php:    $this->assertFieldByXpath('//input[@type="submit"]', t('Duplicate !display_title', $placeholder));
core/modules/views_ui/src/Tests/DisplayTest.php:    $this->assertFieldByXpath('//input[@type="submit"]', t('Delete !display_title', $placeholder));
core/modules/views_ui/src/Tests/DisplayTest.php:    $this->assertFieldByXpath('//input[@type="submit"]', t('Disable !display_title', $placeholder));
core/modules/views_ui/src/Tests/DisplayTest.php:    $this->assertNoFieldByXpath('//input[@type="submit"]', t('Enable !display_title', $placeholder));
core/modules/views_ui/src/Tests/DisplayTest.php:    $this->drupalPostForm(NULL, NULL, t('Disable !display_title', $placeholder));
core/modules/views_ui/src/Tests/DisplayTest.php:    $this->assertFieldByXpath('//input[@type="submit"]', t('Enable !display_title', $placeholder));
core/modules/views_ui/src/Tests/DisplayTest.php:    $this->assertNoFieldByXpath('//input[@type="submit"]', t('Disable !display_title', $placeholder));
justAChris’s picture

  1. +++ b/core/modules/config_translation/tests/src/Unit/ConfigEntityMapperTest.php
    @@ -70,7 +70,7 @@ protected function setUp() {
    -      'title' => '!label language',
    +      'title' => '@label language',
    

    Not in t()

  2. +++ b/core/modules/config_translation/tests/src/Unit/ConfigFieldMapperTest.php
    @@ -50,7 +50,7 @@ protected function setUp() {
    -      'title' => '!label field',
    +      'title' => '@label field',
    

    Also not in t()

  3. +++ b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php
    @@ -59,7 +59,7 @@ protected function setUp() {
    -    $exception_message = $this->getRandomGenerator()->string();
    +    $exception_message = $this->getRandomGenerator()->name();
    

    Is this supporting some other Test assertion? seems wrong in this scope. EDITED: Maybe needed, see #52. Maybe run these tests locally without this update and see if it still fails?

  4. +++ b/core/modules/node/src/Tests/NodeEditFormTest.php
    @@ -77,8 +78,8 @@ public function testNodeEdit() {
    -    $active = '<span class="visually-hidden">' . t('(active tab)') . '</span>';
    -    $link_text = t('!local-task-title!active', array('!local-task-title' => t('Edit'), '!active' => $active));
    +    $active = SafeMarkup::format('<span class="visually-hidden">@active_tab</span>', array('@active_tab' => t('(active tab)')));
    +    $link_text = t('@local-task-title@active', array('@local-task-title' => t('Edit'), '@active' => $active));
    

    Should we even be touching the first line here? no placeholder. Or does it affect the second line? Is this really the best way to do this in that case? EDITED: Explanation in #133, but does this still apply since we reduced the scope to tests only?

effulgentsia’s picture

About 20 of the replacements in the latest patch are in format_string() which looks to be outside the scope of this issue

I'm ok with those being included in this patch. Is there a reason not to? The issue summary currently says "in t() usage only". Should we change the issue summary to also include SafeMarkup::format() usage or do we have/want a separate issue for that and then remove those from this patch?

And also, potentially wrong given 9.0.0 deprecation

If we include them in the patch, I'd be ok with either them being changed to SafeMarkup::format() while we're at it (since we're changing that line anyway), or letting that conversion be a separate issue.

Re #176.1/2: They are in t(), just indirectly, via ConfigEntityMapper::getTitle(). However, because of that, we also need to change the prefix used in that method, so let's remove that from here and do it in #2566503: [meta] Replace remaining !placeholder for Non-URL HTML outputs only.

Re #176.4: I don't get the question. This is in a test.

effulgentsia’s picture

Re #176.3: I opened #2567793: Random test failures in MigrateExecutableTest when random string returns unescaped html entities. Can anyone help to quickly resolve that issue? Not sure if it's a hard blocker or soft blocker for this one.

effulgentsia’s picture

Status: Needs work » Needs review
FileSize
48.72 KB
717 bytes

Interesting. On its own, #2567793: Random test failures in MigrateExecutableTest when random string returns unescaped html entities passes. Therefore, trying this to see if something in this patch is making it fail.

Sutharsan’s picture

These two test modules are overlooked by the regex:
FormTestVerticalTabsForm.php:
t('Field !num', array('!num' => $i)),
'#title' => t('Field !num', array('!num' => $i)),

node_test.module:
t('Value of testElement RSS element for node !nid.', ...
t('Extra data that should appear only in the RSS feed for node !nid.' ...
t('Extra data that should appear everywhere except the RSS feed ... !nid ...

effulgentsia’s picture

Since #179 passes, whatever was causing the problem in #52 no longer appears to be in this patch, so removing #176.3 from this patch as an out of scope change.

This patch does not yet address the rest of the feedback from #176, #177, and #180. Leaving that for someone else to work on.

justAChris’s picture

Regarding #176.4, I understand now that the update to the first line is needed to get the test to pass after converting ! to @. It doesn't seem the most efficient way to do this though. We're wrapping a t() inside a SafeMarkup::format()and then wrap it again inside another t(). All inside of a test assertion (which also does a strip_tags())

+++ b/core/modules/node/src/Tests/NodeEditFormTest.php
@@ -77,8 +78,8 @@ public function testNodeEdit() {
     // Check that the title and body fields are displayed with the correct values.
-    $active = '<span class="visually-hidden">' . t('(active tab)') . '</span>';
-    $link_text = t('!local-task-title!active', array('!local-task-title' => t('Edit'), '!active' => $active));
+    $active = SafeMarkup::format('<span class="visually-hidden">@active_tab</span>', array('@active_tab' => t('(active tab)')));
+    $link_text = t('@local-task-title@active', array('@local-task-title' => t('Edit'), '@active' => $active));
     $this->assertText(strip_tags($link_text), 0, 'Edit tab found and marked active.');
     $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
     $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
xjm’s picture

Hm, the format_string() usages probably should have been included in #2564353: Remove !placeholder usage from SafeMarkup::format(). There are possibly non-test instances of those too so we should create another followup for format_string(). That said, since they appear to all be on assertion messages (as opposed to text being asserted) and it's the same conceptual change, there's virtually no risk so I'm okay with including them here.

However, we should not continue to scope-creep by changing them to SafeMarkup::format(). This is a soft blocker (and possibly eventually a hard blocker) for a critical.

xjm’s picture

+++ b/core/modules/node/src/Tests/NodeRevisionsUiTest.php
+++ b/core/modules/node/src/Tests/NodeRevisionsUiTest.php
@@ -119,17 +119,17 @@ public function testNodeRevisionDoubleEscapeFix() {

@@ -119,17 +119,17 @@ public function testNodeRevisionDoubleEscapeFix() {
     // Assert the old revision message.
     $date = format_date($nodes[0]->revision_timestamp->value, 'short');
     $url = new Url('entity.node.revision', ['node' => $nodes[0]->id(), 'node_revision' => $nodes[0]->getRevisionId()]);
-    $old_revision_message = t('!date by !username', [
-      '!date' => \Drupal::l($date, $url),
-      '!username' => $editor,
+    $old_revision_message = t('@date by @username', [
+      '@date' => \Drupal::l($date, $url),
+      '@username' => $editor,
     ]);
     $this->assertRaw($old_revision_message);
 
     // Assert the current revision message.
     $date = format_date($nodes[1]->revision_timestamp->value, 'short');
-    $current_revision_message = t('!date by !username', [
-      '!date' => $nodes[1]->link($date),
-      '!username' => $editor,
+    $current_revision_message = t('@date by @username', [
+      '@date' => $nodes[1]->link($date),
+      '@username' => $editor,
     ]);
     $current_revision_message .= '<p class="revision-log">' . $revision_log . '</p>';
     $this->assertRaw($current_revision_message);

This test also needs a followup. It's supposed to be a test for a double-escaping fix, but it does an assertRaw() on the result of t() rather than asserting the actual raw expected output. This means that if our changes to t() end up reintroducing double-escaping, this test will just test that it's double-escaped. :P

xjm’s picture

+++ b/core/modules/node/src/Tests/NodeEditFormTest.php
@@ -77,8 +78,8 @@ public function testNodeEdit() {
     // Check that the title and body fields are displayed with the correct values.
-    $active = '<span class="visually-hidden">' . t('(active tab)') . '</span>';
-    $link_text = t('!local-task-title!active', array('!local-task-title' => t('Edit'), '!active' => $active));
+    $active = SafeMarkup::format('<span class="visually-hidden">@active_tab</span>', array('@active_tab' => t('(active tab)')));
+    $link_text = t('@local-task-title@active', array('@local-task-title' => t('Edit'), '@active' => $active));
     $this->assertText(strip_tags($link_text), 0, 'Edit tab found and marked active.');
     $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
     $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');

Oh, I also agree with @justAChris that this is kinda a WTF. It'd be better to remove both the format() and the t(), and just do a plain simple assertText(). Let's split this one off into its own issue too.

dawehner’s picture

  1. +++ b/core/modules/config_translation/tests/src/Unit/ConfigEntityMapperTest.php
    @@ -70,7 +70,7 @@ protected function setUp() {
           'base_route_name' => 'entity.configurable_language.edit_form',
    -      'title' => '!label language',
    +      'title' => '@label language',
           'names' => array(),
    
    +++ b/core/modules/config_translation/tests/src/Unit/ConfigFieldMapperTest.php
    @@ -50,7 +50,7 @@ protected function setUp() {
           'base_route_name' => 'entity.field_config.node_field_edit_form',
    -      'title' => '!label field',
    +      'title' => '@label field',
    

    Mh, how does that even pass, when \Drupal\config_translation\ConfigEntityMapper::getTitle is not changed?

  2. +++ b/core/modules/node/src/Tests/NodeRevisionsUiTest.php
    @@ -119,17 +119,17 @@ public function testNodeRevisionDoubleEscapeFix() {
    +    $old_revision_message = t('@date by @username', [
    +      '@date' => \Drupal::l($date, $url),
    +      '@username' => $editor,
    ...
    +    $current_revision_message = t('@date by @username', [
    +      '@date' => $nodes[1]->link($date),
    +      '@username' => $editor,
    

    Just a doc for myself: This works because LinkGenerator uses SafeMarkup::format()

Sutharsan’s picture

working on a new patch...

joelpittet’s picture

joelpittet’s picture

Sutharsan’s picture

Comments addressed:

dawehner’s picture

+++ b/core/modules/aggregator/src/Tests/UpdateFeedItemTest.php
@@ -37,10 +38,10 @@ public function testUpdateFeedItem() {
-    $this->assertResponse(array(200), format_string('URL !url is accessible', array('!url' => $edit['url[0][value]'])));
+    $this->assertResponse(array(200), SafeMarkup::format('URL @url is accessible', array('@url' => $edit['url[0][value]'])));

Just a quick note: This makes it a bit harder to review the patch ...

joelpittet’s picture

xjm’s picture

+++ b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php
@@ -81,7 +81,7 @@ public function testImportWithFailingRewind() {
-  public function testImportWithValidRow() {
+  public function __testImportWithValidRow() {

Oops. ;) Let's revert those.

xjm’s picture

And yeah, like I said, we should not convert format_string() to SafeMarkup::format() in this patch. See #183.

larowlan’s picture

Assigned: Unassigned » larowlan

fixing 193/4

larowlan’s picture

Assigned: larowlan » Unassigned
FileSize
5.77 KB
45.59 KB

Fixes 193/194

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Yeah, no you can actually use --word-diff

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

There's stuff missing... patch on its way.

alexpott’s picture

Status: Needs work » Needs review
FileSize
8.78 KB
53.84 KB

New patch.

alexpott’s picture

Some notes on the patch in #199

  1. +++ b/core/modules/aggregator/src/Tests/UpdateFeedItemTest.php
    @@ -37,10 +37,10 @@ public function testUpdateFeedItem() {
    -    $this->assertResponse(array(200), format_string('URL !url is accessible', array('!url' => $edit['url[0][value]'])));
    +    $this->assertResponse(200);
    

    This just can be massively simplified since the url you are on is displayed by the drupalGet above.

  2. +++ b/core/modules/node/src/Tests/NodeEditFormTest.php
    @@ -77,9 +77,7 @@ public function testNodeEdit() {
    -    $active = '<span class="visually-hidden">' . t('(active tab)') . '</span>';
    -    $link_text = t('!local-task-title!active', array('!local-task-title' => t('Edit'), '!active' => $active));
    -    $this->assertText(strip_tags($link_text), 0, 'Edit tab found and marked active.');
    +    $this->assertRaw('Edit<span class="visually-hidden">(active tab)</span>');
    

    Everything is wrong with HEAD here even the assertText is wrong... the message is 0 :)

dawehner’s picture

+++ b/core/modules/aggregator/src/Tests/UpdateFeedItemTest.php
@@ -37,10 +37,10 @@ public function testUpdateFeedItem() {
     $this->drupalGet($edit['url[0][value]']);
-    $this->assertResponse(array(200), format_string('URL !url is accessible', array('!url' => $edit['url[0][value]'])));
+    $this->assertResponse(200);
 

For sure, no question, that message is pointless, but still it makes the patch harder to review.

Status: Needs review » Needs work

The last submitted patch, 199: 2506445.199.patch, failed testing.

The last submitted patch, 199: 2506445.199.patch, failed testing.

alexpott’s picture

Status: Needs work » Needs review
FileSize
1.98 KB
52.71 KB
dawehner’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community

Went through every instance, we are done now.

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
3.92 KB
51.77 KB

Found another :( Also reverting the changes to DisplayTest and UpdateFeedItemTest and filing followups since they might cause scope discussions and the followups won't conflict so happy days.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Down to --word-diff changes again.

alexpott’s picture

Issue summary: View changes

Created the followups:

Also added ContactPersonalTest as that uses !placeholder but it is email testing and therefore needs to be handled differently as part of #2557113: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 206: 2506445.206.patch, failed testing.

alexpott’s picture

#206 failed because of GET http://ec2-54-186-69-54.us-west-2.compute.amazonaws.com/checkout/update.php/start?id=2&op=do_nojs returned 0 (0 bytes). ie. PIFR mess.

Status: Needs work » Needs review

alexpott queued 206: 2506445.206.patch for re-testing.

alexpott’s picture

Status: Needs review » Reviewed & tested by the community

As per #207

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 206: 2506445.206.patch, failed testing.

Status: Needs work » Needs review

dawehner queued 206: 2506445.206.patch for re-testing.

alexpott’s picture

Status: Needs review » Reviewed & tested by the community

COme on pifr...

justAChris’s picture

Title: Replace !placeholder with @placeholder in t() for non-URLs in tests » Replace !placeholder with @placeholder in t() and format_string() for non-URLs in tests
Issue summary: View changes

Updating issue summary to reflect that fact that we included occurrences of !placeholder in format_string() in the scope of this issue.

xjm’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll

No longer applies, alas. I think maybe one of the changes from another patch got mixed in here too?

alexpott’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
51.86 KB
First, rewinding head to replay your work on top of it...
Applying: Init commit
Applying: Some omissions
Using index info to reconstruct a base tree...
M	core/modules/aggregator/src/Tests/UpdateFeedItemTest.php
Falling back to patching base and 3-way merge...
Auto-merging core/modules/aggregator/src/Tests/UpdateFeedItemTest.php
Applying: Fix tests
Applying: Revert unnecessary change if you want to review with color words
alexpott’s picture

So nope nothing got mixed up - the changes we just a line of context to near to each other... ho hum.

xjm’s picture

Issue tags: -Needs reroll

Thanks @alexpott.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 218: 2506445-218.patch, failed testing.

chx’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
1.2 KB
51.77 KB

Reroll, dont credit me.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 222: 2506445_222.patch, failed testing.

alexpott’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
50.48 KB

We also had a conflict in NodeRevisionsUiTest. Fixing. Cause #2567857: Remove !placeholder in NodeRevisionUiTest and make it actually test the expected output just landed.

alexpott’s picture

Fixing unnecessary rollback of #2568015: Replace !placeholder in UpdateFeedItemTest - happened in #218.

alexpott--

joelpittet’s picture

RTBC++
alexpott++ (karma balance for noticing)

The last submitted patch, 218: 2506445-218.patch, failed testing.

The last submitted patch, 222: 2506445_222.patch, failed testing.

The last submitted patch, 224: 2506445-223.patch, failed testing.

  • xjm committed 497ebcd on 8.0.x
    Issue #2506445 by joelpittet, Ryan Weal, Sutharsan, alexpott,...
xjm’s picture

Status: Reviewed & tested by the community » Fixed
+++ b/core/modules/system/src/Tests/Form/FormTest.php
@@ -361,7 +361,6 @@ function testCheckboxProcessing() {
-    $error = '!name field is required.';

I confirmed this variable is never used within that test method.

@Sutharsan thanks for documenting all the issue credits from the previous child issues. lauriii, izus, andypost, borisson_, and Sharique have not commented on this issue, so I have added them manually to the end of the commit message.

Committed and pushed to 8.0.x. Thanks everyone for your epic patience as we figured out how to scope this issue, and see you in #2567855: Replace !placeholder with @placeholder in format_string() for non-URLs and #2566503: [meta] Replace remaining !placeholder for Non-URL HTML outputs only!

Status: Fixed » Needs work

The last submitted patch, 225: 2506445-225.patch, failed testing.

alexpott’s picture

Status: Needs work » Fixed

Silly pifr... this is done.

Status: Fixed » Closed (fixed)

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