Problem/Motivation
If a module logs an error and one of the context are not convertible into a string, dblog the page crashes with an exception. To recover from this issue I have first truncated the dblog table and than cleared all caches as the truncate was not enough.
Proposed resolution
LogMessageParser::parseMessagePlaceholders(), which is called by the dblog and syslog loggers, should exclude any non-stringable placeholders, as the PSR-3 logging standard states that "the array can contain anything. Implementors MUST ensure they treat context data with as much lenience as possible. A given value in the context MUST NOT throw an exception nor raise any php error, warning or notice."
Proposed in #21 raise an exception when trying to write a log with placeholders that cannot converted into strings. Also, if possible, try to indicate where this error was produced as part of the raised exception. #52
Remaining tasks
None
User interface changes
None
API changes
None
| Comment | File | Size | Author |
|---|
Issue fork drupal-2481349
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 2481349-prevent-the-use
changes, plain diff MR !5352
Comments
Comment #1
dawehnerThat sucks indeed.
Can you give any hint what it was? Is that maybe too much memory?
Comment #2
dawehnerThat sucks indeed.
Can you give any hint what it was? Is that maybe too much memory?
Comment #3
berdirYes, how does it crash? Exception? php error?
Comment #4
hass commentedIt was a pretty Drupal exception. Not a php error.
Comment #5
dawehnerI tried the following:
One thing I could imagine is that somehow you managed to get an object into $message, then maybe the (string) cast in isSafe() could fail, just one random idea.
@hass
Could you imagine that you had a really long message inside dblog?
Comment #6
hass commentedIt was an object or json. It was for sure not a very long message.
Comment #7
hass commentedI was able to reproduce this.
Add this to line 143 in http://cgit.drupalcode.org/recaptcha/tree/recaptcha.module?h=8.x-2.x#n143
and if the captcha has been send to Google open
admin/reports/dblogand you get this:Followed by a php error that is logged in database (with the HTML tags - bug2):
Deleted the
reCAPTCHA web servicerow from watchdog tabe and the dblog works again.I know I should use
print_r, but such a "crash" should not happen:Comment #8
hass commentedComment #9
webchickIf this happens, it'll render the dblog page in pretty rough shape, but does not render the entire system unusable, so downgrading to major.
Comment #10
todd zebert commentedI'm working on a patch for this at #DrupalConLA mentored sprint.
Comment #11
todd zebert commentedDave and I have a patch, and he has a Drupal Unit Test that's almost done.
Comment #12
dawehner@Todd Zebert
Great work, I hope you can upload a patch soon. One thing you should learn, things don't have to be perfect in the first place. Better iterate quickly.
Comment #13
todd zebert commentedWell, we had something very close end of the sprint Fri, but I haven't heard from Dave (not Mike, my mistake) "vasi" since then. I've pinged him on twitter.
Comment #14
vasi commentedHere's a patch that attempts to fix the problem, along with some tests.
Comment #15
vasi commentedThere's a bunch of choices that had to be made here:
- What happens when someone tries to log an object? Possibilities include: It succeeds, it fails, or it succeeds but shows a warning. We decided to allow it to succeed. Since many dblogs are already warning conditions, it might get confusing to print warnings-upon-warnings.
- What does the dblog UI do with an object? Possibilities include: Go down flaming, show some sort of placeholder (eg: "
- At what level do we fix this issue? It could be in the DbLogController or in SafeMarkup. Although fixing it in SafeMarkup would solve this issue everywhere, it's not clear that we want this to never yield an error--maybe in other cases that's desirable. Also, many, many other parts of Drupal use SafeMarkup, and it's hard to decide whether the same behaviour is appropriate for all of them. So for now, we're fixing it in DbLogController.
I'd appreciate guidance about whether we made the right choices or not!", show a string representation of the object, maybe others. For now we're going with a string representation, as yielded by print_r. It's probably the closest we can get to what the user intended to show.
Comment #16
vasi commentedComment #17
todd zebert commentedTo test, apply just the test code:
git apply -v --include=core/modules/dblog/src/Tests/DbLogControllerFormatTest.php safemarkup_issafe-2481349-14.patchTo run the test (your sudo -u, and --url will vary):
sudo -u _www php ./core/scripts/run-tests.sh --url http://toddlocal.drupal8.com --browser --verbose --file core/modules/dblog/src/Tests/DbLogControllerFormatTest.phpAs expect,
testFormatMessageObject()fails. Here's the complete simpletest report:I verified my existing object in dblog still created the existing error at /admin/reports/dblog .
Apply just the patched code:
git apply -v --include=core/modules/dblog/src/Controller/DbLogController.php safemarkup_issafe-2481349-14.patchRerun the test:
sudo -u _www php ./core/scripts/run-tests.sh --url http://toddlocal.drupal8.com --browser --verbose --file core/modules/dblog/src/Tests/DbLogControllerFormatTest.phpAll nine tests passes, excerpt:
I verified my existing object in dblog DOES NOT created the existing error at /admin/reports/dblog .
Comment #18
catchWe should throw an exception when the incorrect argument is passed in the first place rather than trying to account for the incorrect API usage.
Comment #19
todd zebert commentedIn our first discussion of this with our mentor @heddn we figured "saving" the data - that is, the data sent to the log - was worthwhile, vs just throwing an exception. Additionally, if we throw an exception, we can't even include the data causing the error because that that would cause another exception, unless of course we did the equivalent of a __toString; but then it seems silly to capture the data in an error in the log and not just capture the data in the log to begin with.
public function DbLog::log doesn't put constraints on the type of items in $context, nor does public function LoggerInterface::log. As it is, the log takes the data fine. It's just the making the output safe for render that breaks.
Comment #20
todd zebert commentedComment #21
heddnre #19: Go ahead and throw an exception when the incorrect type of object is passed. Instead of trying to make things work.
Comment #23
vasi commentedReplacing with the throwing-an-exception-on-misuse approach.
Tests fail because of what looks like a bug in LogMessageParser. It's still looking for old-style '!placeholder', and doesn't understand ':placeholder'. Ooops!
Comment #24
vasi commentedComment #27
dagmarThis is fixed here: #2617330: LogMessageParser::parseMessagePlaceholders() needs to switch bang placeholder to colon placeholder but according @dawehner it needs tests.
So I merged both patches into this a single one, if tests pass I think we could close two issues with a single patch.
Comment #32
fgmPossibly related issue is #2760031: Log messages won't appear translated if they have special characters in them, of which #2617330: LogMessageParser::parseMessagePlaceholders() needs to switch bang placeholder to colon placeholder was marked as a duplicate.
Comment #33
ziomizar commentedI'm working on triaging this issue at Drupalcon Vienna2016, following the instructions in #2474049: [meta] Major issue triage. @fgm is helping as our mentor.
Comment #34
ziomizar commentedThe test fail also on 8.5.x-dev.
Patch need reroll.
Comment #35
ziomizar commentedComment #36
jofitzRe-rolled patch from #27.
Comment #38
ziomizar commentedI saw a strange behaviuour in the tests.
I changed the foreach loop into the test to use DataProvider to pass the logging method.
Seems more stable now.
Comment #39
hass commentedComment #40
jofitzMerged @ziomizar's changes into the patch.
Comment #41
dagmarAccording to the PHPunit docs, this should be an array of arrays.
This should be mocked too. Mocking this class we could move this unit test outside the scope of dblog.
Comment #42
jofitzCorrected the test failures.
Corrected the coding standards errors.
Corrected the data provider.
@dagmar Can you explain more about the need to mock DBLog, please? I don't understand the reason for doing so and, if my implementation is correct, it would require a lot of work.
Comment #43
fgmAIUI, the idea of mocking DBLog is that it no longer needs the dblog module to be enabled to run the tests, and no longer needs to be a even a KernelTest but can be just a UnitTest.
Comment #44
dagmarIn my opinion, this exception should be triggered at
LogMessageParserlevel.If you have dblog disabled, and some contrib module runs this line of code:
\Drupal::logger('php')->warning('closure %c', ['%c' => function () { } ]);Then syslog will log this:
Recoverable fatal error: Object of class Closure could not be converted to string in Drupal\syslog\Logger\SysLog->log() (line 71 of /var/www/drupal/core/modules/syslog/src/Logger/SysLog.phpwhich is basically the same thing you saw when try to see the log using dblog.If we move this exception to the
LogMessageParserthen, you can mock the use ofDblog, or just use a different logger to try this functionality.Comment #45
dagmarSomething like this.
Comment #47
dagmarWe should check only for placeholders not all the items in the context array.
Comment #49
dagmarComment #50
dagmarI think this title reflects better the idea behind this patch.
Comment #51
dagmarUpdated issue summary to reflect the proposed solution. This patch only needs some code review.
Comment #52
fgmRaising an exception during logging seems like a big red flag for me. How are you supposed to log it ? It looks like it has the potential for infinite recursion in some scenarios (can't imagine which ones right now, but in earlier watchdog code, we had specific logic to avoid such recursions, and this doesn't seem to be included here.
Comment #53
dagmarTwo core maintainers proposed in #18 and #21 proposed to trow an exception.
Maybe we need some test coverage that ensure that some log is created when the log placeholders are not convertible into strings. What do you think @fgm?
Comment #54
fgmThe problem with #18 and #21, IMHO, is that they fail to appreciate the specificity of logging as a way to track problems vs other situations.
This is partly covered by #19, which could provide a middle ground: how about generating a (synthetic) log record as an error/critical about incorrect API usage about to throw, passing minimaly safe data (probably just a limited call stack slice without arguments to pinpoint the source code line causing the problem), and only then throw an exception. That way tracability, which is what logging is all about, is preserved for future analysis, while interactive usage provides the immediate feedback.
Comment #56
nithinkolekar commentedlearning,understanding drupal8 to covert d7 module and I needed to dblog some object to debug and get info stored in that object.
\Drupal::logger('mymodule')->info(print_r($account, TRUE)); // raised exception Fatal error: Allowed memory size of 134217728 bytes exhaustedIs that mean \Drupal::logger supports only selected objects(in my case $form_state_values worked)?
https://www.drupal.org/node/2270941 has some code having $message without clarifying whether we can use print_r with objects.
Comment #57
berdirThat has nothing to with logging, that's your code. print_r() and similar functions just can't handle content entities. the same error would happen if you just have print_r() without anything else.
One option is to use $account->toArray(), then you have a simple array structure of the values of that account. Or you can use kint() from the devel.module. Or use a real debugger.
see https://wizzlern.nl/drupal/drupal-8-entity-cheat-sheet on how to work with content entities.
Comment #58
fgmMaybe we should make the logger API aware of APIs like ComplexDataInterface, which seems to be the lowest level interface including such a method to enable representing content without specific processing on the caller side ?
Comment #59
dagmarI see what you mean @fgm. What about this?
Comment #60
dagmarMake tests easier to read providing to sets of @dataProviders.
Comment #61
dagmarComment #62
fgm@dagmar : looks like a sane workaround to me. It would be good to have an UX opinion, though, I guess.
Comment #63
dagmarIf someone can review the message shown to developers (see issue summary) and decide if needs some modification would be great.
Comment #64
dagmarIt turns out that this issue also fix #2703877: Logger tries to replace {users_field_data} with current user object and #2980802: Object of class Drupal\\Core\\Session\\AccountProxy could not be converted to string so I included a test to check this exception for those cases too.
Comment #68
didebruPatch #64 does not fix
Serialization of 'Closure' is not allowed in serialize() (line 14 of core/lib/Drupal/Component/Serialization/PhpSerialize.php).As mentioned in https://www.drupal.org/project/drupal/issues/1872690
Comment #69
didebruI get this error if
$this->keyValueExpirableFactory->get('form')->setWithExpire($form_build_id, $form, $expire);is called.
Comment #70
dagmarHi @Insasse thanks for your comment.
I think your issue is different than this one. His is trying to avoid crash viewing the log report. Please read the issue summary. Yours is mentioning a different subsystem, the
keyvalue.databaseI may be wrong anyway, so could you provide the backtrack of your error?Comment #71
didebruHey @Dagmar,
The Full error message:
$form_state->setCached(FALSE); fixed it for me.
Comment #72
dagmar@Insasse I don't see dblog module involved in the process. It seems a new issue. Feel free to create a new one, probably under the
base systemcomponent. Thanks!Comment #79
smustgrave commentedRerolled for 9.5 but not able to figure out why the tests are breaking.
Comment #80
smustgrave commentedFixed build errors.
Comment #83
mfbMy 2¢ is that the PSR-3 log standard should be followed as much as possible:
So ideally, parseMessagePlaceholders() - which is called by the two built-in implementors, dblog and syslog - wouldn't throw. If a placeholder can't be stringified then it could simply be removed from the message placeholders, under the logic that it's not a valid message placeholder, it's just part of the context.
An alternative solution, which requires a bit more code, would be to helpfully generate a string that describes the unstringable object, callable, resource, array, or whatever it is, e.g.
'Object ' . get_class($value),'Array of length ' . count($value), etc.Comment #84
littlepixiez commentedI have just rerolled the patch to work with Drupal core 9.5.2 - would be good to have some more community testing on it.
Comment #85
dagmarThe idea of throwing an exception is 8 year old... But I agree with @mfb that we should follow the PSR-3 log standard as much as possible.
IMO we should:
Comment #86
neclimdulSo there's dealing with logging with the original patch was doing. Didn't really have time to review while in the middle of dealing with this blocking debugging a broken site. Attached is a quick fix I made that deals with variables not being strings similar to the way we already deal with unserialization failures in the UI.
This was useful but doesn't help other systems using logging so the deeper fix seems needed too. Conflict was with #2617330: LogMessageParser::parseMessagePlaceholders() needs to switch bang placeholder to colon placeholder. Untested re-roll for that also attached.
Comment #87
neclimdulAt the least this needs to be converted to a FQDN(add the first \).
Comment #89
mfbHere's an attempt to follow the PSR-3 standard re: context data (see #83) by having LogMessageParser::parseMessagePlaceholders() ignore any non-stringable objects, arrays, etc. Dblog and syslog modules call this method to get the message placeholders, so hopefully with this change there should be less danger of invalid placeholders causing an exception to be thrown.
I didn't add extra logging, but if necessary we could have the LogMessageParser service log a notice in this scenario.
Comment #90
_utsavsharma commentedtried to fix failures in #89.
Comment #91
dagmarLooks good, and fixes a problem that otherwise it quite complicated to recover from (see the original issue description). However as is this patch will not apply to PHP 7.4 as Stringable is only PHP 8 available.
Comment #92
mfbUpdated issue summary to match logic in the most recent patches
Comment #93
quietone commentedThanks, it is always good to see an old issue get to RTBC!
I'm triaging RTBC issues. I re-read the IS and the comments. I didn't find any unanswered questions.
@mfb, thanks for updating the proposed resolution. That is very helpful.
However, the screenshot in the Issue Summary is for a previous version of the patch, with a different approach. It would help if that was removed.
I then read the patch, not a full review, and noticed these.
This is now fairly long and would benefit from a comment.
This has the actual result first and it should be the expected.
Because of the point about adding a comment I am tempted to move this to NW. However, even though it is a longish 'if' is it not complex. Therefor, I am leaving this a RTBC and I'll ping in #contribute to see if someone wants to complete the three items I mentioned. Be aware, that another committer may still choose to send this back for more work.
Comment #94
quietone commentedI just remembered I reviewed a patch today with a comment line too long. And here it is.
This should be fixed. I can do that now.
Comment #96
mfbAddressed #93
Comment #97
quietone commented@mfb, thanks for making those minor changes.
The failing test in #94 is unrelated. It was in
.
Because the change I made was adding correct wrapping and I have reviewed that changes in #96, I am restoring the RTBC.
Comment #98
smustgrave commentedRestoring status per #97
Comment #100
dagmarRandom test failure.
Comment #102
dagmarRandom test failure.
Comment #103
xjmThanks everyone for finally identifying the root cause of this and referencing the PSR for best practices for a fix. I definitely agree that an exception or other error should not be thrown; the solution would be worse than the problem.
It seems kinda like the valid placeholder formats should be provided by the
FormattableMarkupAPI and not hardcoded here. I realize the existing code has this problem as well, but maybe that's part of what led to this issue in the first place? It seems to me that we also don't allow these invalid data formats inFormattableMarkup, and there are plenty of situations where we don't want the rendering of a string to break the page.Ultimately, the code that acts on these placeholder values is
FormattableMarkup::placeholderEscape():which calls:
...which throws a warning if passed a non-string on PHP 7, or a fatal on PHP 8 which typehints the argument.
So, anything other than a string or MarkupInterface is invalid input, and it seems like
FormattableMarkupshould be handling that itself, possibly with a "safe" mode that silently replaces the placeholder with emptystring rather than fataling with a TypeError.Since this is a site-breaking bug, I'd be okay with scoping a better architecture to a followup, especially since half the problem is the existing code (and to some extent the existing switch statement "fun" of
FormattableMarkupitself), so long as we file the followup and document it in the comments in this hunk.Our documentation standards specify that small words like "that" should not be omitted from inline documentation, so the comments on the data provider should probably be:
Also, I would use the phrase "can be converted" rather than "convertible" because the latter will make people think of cars and might be confusing to second-language speakers.
All that said -- we've moved in the direction of using descriptive data provider array keys rather than inline comments in the provider, for easier debugging and clear test output. We retain inline comments for sitautions where the code is hard to read and a short phrase is not sufficient. So, the keys could be things like:
FormattableMarkup placeholder valueNo placeholders but other context valuesPlain array placeholder valueThese two cases have the same comment. It would be better for them to be distinct, maybe something like:
and:
This is especially important if we convert the data provider to having meaningful test case keys.
Nit: Missing Oxford comma after "number".
Since this is no longer displaying a message, I don't think it needs a usability review. (My guess is a usability review would have told us displaying messages about bad data in an obscure log message was bad UX.)
Thanks everyone!
Comment #104
mfbOk, I went ahead and converted the data provider to have test case keys. These all seem simple enough (to me) that just the descriptive key is good enough without a comment.
As far as followup work on what's a valid placeholder, the current status quo is that Drupal is not strict: Any \Stringable object can be used as a placeholder, not just MarkupInterface objects. A real-world example would be a \Stringable Customer class; if you use an object of this class as a placeholder in a log message, then the object will be stored in the database (as serialized PHP) and such \Stringable objects, as well as integers and floats, will be happily cast to string when later rendering the log message.
If Html.php had
declare(strict_types=1);at the top of the file, then this would not work. In this case, a \Stringable object, float or integer passed to Html::escape() would throw a TypeError when the non-string value is passed to htmlspecialchars(), which expects only a string, strictly speaking.As someone who maintains two contrib logger modules, I don't really see a problem with the status quo - why not allow \Stringable objects to be used in various places, including logging. But certainly Drupal could decide to be more strict going forward, and either cast \Stringable-but-not-MarkupInterface objects to string, or ignore them entirely.
Comment #105
xjmThanks @mfb; those fixes are perfect.
You are right about
\Stringable-- basically replaceFormattableMarkupwith\Stringablethroughout my comment when I reference it as a data type. So the followup scope would be to move this logic toFormattableMarkup(or whatever appropriate level of that API):Might be two issues actually:
FormattableMarkup::placeholderFormat()to provide a list of valid key prefixes, which the logger could then use.Comment #106
mfbCreated a followup #3387437: Unify logic for determining valid placeholder keys and values
Comment #107
xjmThe test-only patch is definitely not failing in the way I expect. I thought it was a fluke but requeued it and got the same result. 🤔 I don't get it.
Comment #108
mfb@xjm idk but seems to work now 🤷
Comment #109
smustgrave commentedBelieve the previous failures for
PHP Fatal error: Uncaught TypeError: Drupal\Core\Database\Transaction\TransactionManagerBase::removeStackItem(): Argument #1 ($id) must be of type string, int given, called in /var/www/html/core/lib/Drupal/Core/Database/Transaction/TransactionManagerBase.php on line 228 and defined in /var/www/html/core/lib/Drupal/Core/Database/Transaction/TransactionManagerBase.php:145Were related to a break in HEAD last week, that was reverted.
Comment #110
xjmThis looks great now. Thanks also @mfb for the followup. One outstanding point of feedback (I thought of this during my first review, but somehow failed to post a comment about it):
I'm surprised that null would be an allowed value. Is the following really valid code?
What's the expected output? I suppose it's the most minimal change to the current functionality, but if we do decide to include the
is_null()case as an allowed case, then we should have a test case for it.(I have similar thoughts for Booleans, although those at least have a semi-meaningful output as
0or1. They should probably get test cases too.)Comment #111
mfb@xjm using NULL here is still allowed at the moment, but is deprecated. The silenced deprecation notice was added in #3255637: Deprecate NULL values in Html::escape(), ::decodeEntities(), and FormattableMarkup::placeholderFormat() to make it easier to upgrade to PHP 8. Therefore, I had to allow NULL in addition to scalar values for the time being. I wasn't sure it was worth adding a test, given that NULL was already deprecated, but we certainly could.
As far as TRUE and FALSE, those are /not/ deprecated yet. Probably a good idea to deprecate them, but that's out of scope of this issue. TRUE is cast to '1' and FALSE to empty string (like NULL), not '0'. Sure we could add a test case for those too, why not..
Comment #112
mfbAddresses #110; also fixed the description of the last test case in previous patch, which wasn't quite right.
Comment #113
smustgrave commentedAppears feedback has been addressed.
Comment #114
xjmThanks @mfb; that makes total sense and the CR reference is helpful. It also explains why these do not raise deprecation errors yet.
Super-nit: "Boolean" is derived from a name and should be capitalized. (I can also fix this on commit.)
Shall we add a followup to decide whether Booleans should also be deprecated?
Comment #115
xjmDreditor ate a long comment, argh.
Something I didn't notice in previous reviews (sorry!) is that it's against our coding standards to have conditions wrapped to multiple lines. It's better to define a couple local variables, e.g.
$valid_prefixfor the second condition, and$valid_data_typeor something for the third. Then the condition becomes:Comment #116
xjmWhile you are making the above changes, we recommend that you convert this patch to a merge request. Merge requests are preferred over patches. Be sure to hide the old patch files as well. (Converting an issue to a merge request without other improvements is not recommended and will not receive credit.)
Comment #117
xjmThe casing thing is ultra-trivial but the change to the condition would need actual review, so NWed. If it were an MR I could have just used the suggestion feature to save us all time. :) We're recommending MRs now generally as patches are being phased out for core now.
Comment #118
mfb@xjm My opinion is that a followup is out of scope of this issue. This issue is just about preventing the use of placeholders that cannot be coerced into strings because PHP throws a TypeError today, here and now, not about deciding what can or cannot be coerced into a string in the future (i.e. adding new deprecated warnings and TypeError situations).
I don't see a clear "need" for a followup from this issue because Drupal is basically following how PHP does things out of the box - certain things, like Stringable objects, numbers and even booleans are coerced to a string; coercing NULL to empty string triggers a deprecated warning; if you don't want any of this coercing to happen, you declare(strict_types=1) in your file and do your own casting.
Comment #119
xjmConfused -- the exact point of followups is that they are out of scope on the issue. 🙂 It came up in discussion on this issue but was not in scope; therefore, to preserve the unresolved discussion once the issue is marked fixed, we file a followup.
Comment #120
mfb@xjm I filed the one followup issue we found so far: #3387437: Unify logic for determining valid placeholder keys and values, and I haven't seen any other unresolved issues that need a followup issue (yet).
Comment #122
mfb@xjm In the MR I tried breaking that logic out to helper methods for hopefully improved readability, what do you think? (This does mean a couple extra function calls, so not perfect from a micro-optimization standpoint.)
p.s. more fun weird stuff you can unfortunately do with Booleans: TRUE / 4; strtr(TRUE, TRUE, FALSE); htmlspecialchars(TRUE) / FALSE; ok I lied about the last one, this throws a division by zero error :p
Comment #123
smustgrave commentedBelieve the changes of breaking out looks fine. Agree easier to read. If reused a bunch maybe worth a trait?
Comment #124
mfbWe have the followup where helper methods/trait/etc. can be discussed further #3387437: Unify logic for determining valid placeholder keys and values
Comment #125
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #126
mfbRebased
Comment #127
smustgrave commentedRebase seems good
Comment #128
quietone commentedI'm triaging RTBC issues. It is always a pleasure to review an older issue! I read the IS and the comments. I didn't find any unanswered questions or other work to do.
In #114, xjm asks if "we add a followup to decide whether Booleans should also be deprecated?" I am not sure that has been answered. There is already one followup but that issue does not cover this point, unless I am misunderstanding.
The introduction of two methods for the valid/invalid logic is different than the suggestion in #115 to use local variables. I don't think the logic is complex that new helper method are required. What about something like the following?
I did not review the MR.
I updated credit.
I am setting to needs work for the two items above. Once that is sorted this should be ready.
Thanks.
Comment #129
mfb@quietone I'm not a fan of using local variables in that manner, because it does not break out of the conditional logic early if the key is not valid. For example, if the key is 'exception', we don't need to look at the object it stores; we can simply move on to the next key. How about two levels of conditional logic, to allow breaking out early while avoiding wrapping? See current iteration of the merge request.
re: "Shall we add a followup to decide whether Booleans should also be deprecated?" my answer was no, we don't need to. Drupal did not deprecate NULL placeholders until PHP deprecated NULL to string coercion. And PHP has not yet deprecated Boolean to string coercion, although there have been some RFCs that discussed it. When I said "Probably a good idea to deprecate them" I was referring to that slow process of PHP deprecating it, followed by Drupal deprecating it, and then eventually throwing an error. If/when we reach that point, the code in this class would need to be changed to ignore Boolean context data.
Comment #130
smustgrave commentedReviewed the commit for the two levels of logic checking and think that's a good middle ground.
Also appears the question about a follow up appears to have been answered in #129.
Comment #131
longwaveGood to finally get this one fixed. Backported to 10.2.x as a low risk bug fix.
Committed and pushed 367e57e7bc to 11.x and a335588be2 to 10.2.x. Thanks!