Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
Lets remove usage of "blacklist" and "whitelist" in \Drupal\Core\Template classes and their tests.
They are:
- An historic bad labelling of people
- Provide no context: "what is listed in them"?
Proposed resolution
- Rename protected member variables that have "whitelisted" in their name with "allowed".
- Deprecate settings that have "whitelisted" in their name and replace with "allowed".
- Fix all comments accordingly
Remaining tasks
Decide if we need BC.Yes. See Settings BC work from #3163226: Add the ability to deprecate a Settings name- Decide if we need to touch core/lib/Drupal/Core/Template/Attribute.php too. Only 'black-cat' and 'white-cat' and friends. Seems we could leave those.
Fix everything:core/lib/Drupal/Core/Template/Loader/StringLoader.php- Comment only. See #3core/lib/Drupal/Core/Template/TwigSandboxPolicy.php- Full of "whitelist":
protected $whitelisted_methods; protected $whitelisted_prefixes; protected $whitelisted_classes;
Land #3163226: Add the ability to deprecate a Settings name so we can properly deprecate the settings.Decide if/how much testing of the real settings deprecations we actually need (see #31): Decision in #38Reviews.RTBC.- Decide which is the best approach:
- #44: Magic provider that tests all real deprecated settings automatically.
- #43: Manually defined provider for each real deprecated setting, shared test method.
- #50: Separate test methods for each set of deprecated settings, with @expectedDeprecation annotations. No @dataProvider. Has to be replicated for each new deprecated setting.
- Commit appropriate patch.
User interface changes
None
API changes
None, only renaming some protected members.
Data model changes
Nope.
Release notes snippet
TBD. Probably not.
Comment | File | Size | Author |
---|---|---|---|
#53 | interdiff-50-53.txt | 690 bytes | jungle |
#53 | 3151094-53.patch | 7.84 KB | jungle |
Comments
Comment #2
alexpottComment #3
dwwGets us started with core/lib/Drupal/Core/Template/Loader/StringLoader.php
NW for core/lib/Drupal/Core/Template/TwigSandboxPolicy.php
Comment #4
dwwMoving this to a separate task:
Comment #5
ravi.shankar CreditAttribution: ravi.shankar at OpenSense Labs commentedHere I have tried to address comment #3.
Comment #6
dwwRe: #5: Thanks, but you didn't touch any of the variables with "whitelist" in their names. :( That's the point of this issue.
Here's a patch that actually completes work for the scope of this issue.
One concern:
I don't see that setting documented anywhere, so I don't see where to change the example for this.
More concerning, perhaps for BC we need to read and honor the old value, too? And trigger a deprecation warning or something?
At least we'll need a CR that this setting (and these protected variables) have changed.
Comment #7
dwwDraft CR: https://www.drupal.org/node/3162897
Comment #9
dww#3037436: [random test failure] Make QuickEditIntegrationTest more robust and fail proof strikes again. Re-queuing.
Comment #10
alexpottI think we need to continue to support the old setting but deprecate it. So we can safely remove it in Drupal 10.
Comment #11
alexpottAlso looking in contrib I'm not sure what http://codcontrib.hank.vps-private.net/node/30453440 is about
Comment #12
dwwRe: #10 - yup, I thought so at #6.
Like so?
Comment #13
dwwWhoops, I missed. There are 3 such settings. :( New patch coming soon.
Meanwhile, other googling:
https://www.drupal.org/project/twig_domquery mentions the legacy setting in its project description. I guess we can open an issue in there to ask them to move to the new setting once this lands?
Comment #14
dwwLet's try this. ;)
Hope it's self-documenting from the code, but the approach in all 3 cases is we check for the new setting first. Only if it's empty to do we check for the old setting. If that's defined, we
@trigger_error()
but use it. If that's also empty, we provide the hard-coded defaults.Comment #15
dwwUpdated the CR to document the settings changes.
Also, what's the policy for editing prior CRs in cases like this?
Theme system restricts which object methods can be accessed from templates
Thanks,
-Derek
Comment #16
dwwWhoops, sorry
Comment #17
dwwRe: #11 -- yeah, not clear WTF is going on there, either. ;) Maybe we should open an issue in https://www.drupal.org/project/issues/twig_extender about it?
Comment #18
jungleTo keep consistency, the last one should be:
(Including the comment)
+1 to the logic.
Not found, maybe we can ask it in the #documentation channel.
NW for the point 1, otherwise it's RTBC to me.
Thanks!
Comment #19
jungleIn addition to #18.1, missing
else
Comment #20
dwwThanks for the review!
However, please look at the full code for core/lib/Drupal/Core/Template/TwigSandboxPolicy.php:
We don't want to
array_flip()
, or we'll break this. I *almost* added a comment to that effect in #14, but thought it might be considered scope creep. ;)Comment #21
dwwWhoops, x-post! #19 is definitely a bug. ;)
1 moment....
Comment #22
dwwComment #23
jungle#20 is right, ignore #18.1 please.
whitelists -> only loads, whitelisting -> only loading, good.
whitelisted methods -> allowed methods, good
whitelisted prefixes -> allowed prefixes, good
whitelisted classes -> allowed classes, good
Comment #24
alexpottSo looking at the deprecation code it reminds me that I think we should generalise the approach to renaming settings we used for config_sync_directory in Drupal 8. I.e. we should have a map of deprecated settings to new settings with the deprecation information too. We should open a blocking issue to do that because atm we have no test coverage of the BC layer added here. Whereas if we relied on a generic (and tested) Settings deprecation process it'd more reliable and we'd have less hunks of complex code here.
Comment #25
dwwAgreed, that'd be better.
#3151093: Replace use of whitelist/blacklist in \Drupal\Core\Security\RequestSanitizer and its test has
\Drupal\Core\Site\Settings::handleDeprecations()
.Is that how you want that to work?
Do you want to split that part out to a separate issue?
Or just land that as-is and we'll build on it here?
Thanks!
-Derek
Comment #26
alexpottPostponing on #3163226: Add the ability to deprecate a Settings name
Comment #27
dwwProof of concept for #3163226-13: Add the ability to deprecate a Settings name
Here's #22 cleaned up / simplified, plus #3163226-13.
Comment #28
jungleBTW, missing
$this->allowed_prefixes = $allowed_prefixes;
Comment #29
dwwGood catch, thanks! 2 new patches:
3151094-29.with-3163226-21.patch
will hopefully run / pass tests now. ;) It's fixed version of #27 plus the latest from #3163226-21: Add the ability to deprecate a Settings name3151094-29.after-3163226.do-not-test.patch
is just the changes for this issue once #3163226 is committed. "do-not-test" since it won't apply until that lands.Comment #30
dwwNew patches based on changes at #3163226: Add the ability to deprecate a Settings name
Settings::$deprecatedSettings
is now keyed by legacy name.Here's a do-not-test that will only apply after #3163226-37 is committed and a version with #3163226-37 included and drupalci.yml change to only run the new test.
Also cleaning up the summary + remaining tasks now that this is nearly complete.
Thanks,
-Derek
Comment #31
dwwOpen questions:
Settings::get()
, and ensuring that we always get the correct value returned and that the deprecation message is generated in the 5 expected cases, do we even need to be testing the real deprecations at all?Testing the real deprecations seems a bit like busy-work to me. If we trust the new API, can't we just use it without re-testing it for every usage? It's more churn when we deprecate, and more stuff to cleanup at the next major.
Thoughts?
Thanks!
-Derek
Comment #32
dwwAs in, can we just do this, instead?
Comment #33
jungleRe #31, Good question! How about the following, just to test that it works, no data provider -- triggered expected deprecation message(s).
Comment #34
jungleEven more, remove assertions, only care deprecation message(s)
Comment #35
dwwYay, blocker is in! This can proceed. Queued #32 for a test run.
Comment #36
jungle@dww, could you add the test suggested in #33 and #34 if you agree?
Missing test for the newly added deprecated settings, I am afraid I could not RTBC this.
Comment #37
dwwI'm waiting for a core committer to answer #31.1. As I wrote there, I believe if we trust the tests for the
Settings::$deprecatedSettings
array / API (as we should), then adding "real" deprecation tests for every deprecated setting seems like pointless churn to me. Once we have tests for a given form element, we don't re-test that form element every time we use it. I don't see why we need anything more than #32.Tagging for framework manager review.
Of course if they want more, we can add them. Not sure if #34/ #35 is enough, or we should have a dataProvider, or what. If they want real deprecation tests, we need clarity on their preferred approach, and an answer to #31.2: do we need to test all 6 possible cases for each setting? If not, which subset is enough? Etc.
Thanks,
-Derek
Comment #38
alexpottYes we don't test for every detail but we do often test for the presence and effect of the form field. I think we need a single test showing the deprecation is triggered as expected.
Comment #39
dwwRe: #38: Groovy, thanks for clarifying!
Re: #33:
;)
With an eye towards #3151093: Replace use of whitelist/blacklist in \Drupal\Core\Security\RequestSanitizer and its test I'm going with a
@dataProvider
approach.Do we want each setting in its own case, or can we group them to test all deprecated twig_sandbox_* settings in 1 case like I'm doing here?
Thanks,
-Derek
Comment #41
dwwWhoops, comment spacing isn't quite right. ;)
This should be better.
Comment #42
dwwBefore:
After:
(these 3 are pre-existing).
Comment #43
dwwIf we move each setting into a separate case from the dataProvider, we can simplify some of these even further and shrink the patch.
Also fixing a typo in a @param comment s/stinrg/string/
Comment #44
dwwAnd if we want to get really clever, we can auto-populate
providerTestRealDeprecatedSettings()
viaSettings::$deprecatedSettings
itself. ;) Then we never have to touch this file and we know that all deprecated settings will be tested.Probably this will be considered too much magic and we'll have to stick with #43, but I'm uploading for comparison / consideration, just in case. ;)
Comment #45
jungleIf i change
$this->addExpectedDeprecationMessage($expected_deprecation);
to$this->expectDeprecationMessage($expected_deprecation);
, it won't pass. wondering what's the difference between them. If you know, would you mind to share? Thanks!Comment #46
dwwI confess to not fully understanding. I can say that
addExpectedDeprecationMessage()
is fromDrupal\Tests\Traits\ExpectDeprecationTrait
. Although, yikes, apparently that's on its way out, too: #3157434: Deprecate \Drupal\Tests\Traits\ExpectDeprecationTrait in favour of \Symfony\Bridge\PhpUnit\ExpectDeprecationTrait ;)However,
expectDeprecationMessage()
is native to PHPUnit itself.My (limited) understanding is that the Symfony PHPUnit bridge catches all deprecation warnings thrown and has its own handling of them so we can ignore a huge # of deprecations that we can't do anything about until we stop supporting older versions of PHP, PHPUnit, Symfony, etc, etc. Therefore, we need to use that plumbing to inspect deprecations, since if we ask PHPUnit itself to expect something, it'll never be seen. Or something. ;)
I'm sure @alexpott can completely school us on the details. ;)
Comment #47
jungleThanks @dww, I do not fully get #46, but after fixing/rerolling the patch for the issue you shared, I think we can try the following changes:
expectDeprecation()
(or similar) is more accurate/suitable thanaddExpectedDeprecationMessage()
, IMO.Comment #48
dwwThanks for reviewing. However, #47 is out of scope here. This test was already using
Drupal\Tests\Traits\ExpectDeprecationTrait
before I started touching it at #3163226: Add the ability to deprecate a Settings name. I don't see any existing references toSymfony\Bridge\PhpUnit\ExpectDeprecationTrait
anywhere in the 9.1.x branch (yet). Converting from our custom version of this trait to theSymfony\Bridge
version should happen at #3157434: Deprecate \Drupal\Tests\Traits\ExpectDeprecationTrait in favour of \Symfony\Bridge\PhpUnit\ExpectDeprecationTrait, not here. If that lands first, it should make those changes itself to this test as it exists in the 9.1.x branch. If/when that happens, then we can re-roll this to useexpectDeprecation()
on the new instances. But until then, we should definitely leave this as-is.Cheers,
-Derek
Comment #49
jungleThanks @dww.
Then #44 is RTBC to me, one test covers all real deprecated settings magically. Deprecated settings added later on do not need to add tests anymore. However, #33 + #34 is an alternative to me still, so uploading a patch based on it, for committer's reference.
Comment #50
jungleSorry the above should be removed from #49
Comment #51
dwwIMHO #44 is the best option, and will be zero work for subsequent issues. Re-uploading that, since I think we both agree that's RTBC, whereas #34 / #35 / #50 is an alternative / 2nd choice if committers prefer. Honestly, I'd consider #50 the third choice. If #44 is too much magic, I'd rather go with #43 than #50.
So I'm re-uploading #44 to be the last patch in the issue for both testbot and committer review.
I also put all of this into the summary as the final remaining task.
Thanks,
-Derek
Comment #52
alexpottI looked at #51 and was thinking I wish it was more declarative. But then looking at #43 that seems a bit off. I think the correct patch is #50. It's testing that if you have the setting in your setting.php you get the expected deprecation.
Should have the @runInSeparateProcess annotation. In fact we should file a follow-up to move this annotation to the class because there are so many statics involved with the Settings.
Comment #53
jungleThanks @alexpott. Added @runInSeparateProcess
Comment #54
jungleFollow up filed
Comments are welcome over there.
Comment #55
alexpottCommitted a2856d1 and pushed to 9.1.x. Thanks!
Comment #57
dwwRe: #52: Thanks for making a decision. You wanted more declarative than #51 / #44 -- spell it out, use less magic. ;) Fair enough. More work for each deprecated setting, but we've only got 4 of them at this point. Unlike other kinds of deprecations, there are unlikely to be a huge # of these.
I'm slightly bummed we'll have to repeat all of this in each test:
Which is why I was advocating for #43 with a @dataProvider as the alternative. That still has the same desired effect:
That's what all 3 approaches do. ;)
Anyway, if you're happy with copy/pasta on this, we can move on. Just trying to better understand your thinking / preferences to calibrate my own for future work.
Re: #54: Thanks for opening that! Now that I know PHPUnit has this plumbing, I was thinking the same for this whole test class. Commented there with a patch. ;)