Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
other
Priority:
Major
Category:
Bug report
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
3 Sep 2015 at 12:52 UTC
Updated:
4 Aug 2024 at 21:06 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
alexpottThis was borne out of work done on #2560715: Prefer toString to __toString in renderVar for ToStringInterface - it might be nice to unit test the TranslationWrapper implementation.
Comment #3
dawehnerIs there a reason to not use get_class() instead of gettype()?
Comment #4
stefan.r commented@dawehner no reason, might as well use that
Comment #5
stefan.r commentedlet's add a test
Comment #6
stefan.r commentedhmm that is wrong, should be Drupal\Tests\Core\StringTranslation
Comment #7
alexpottCan we make this a fatal and not do a return? Or does that cause problems?
No ()
Comment #8
stefan.r commentedDon't know... __toString() has to return a string, so maybe E_USER_ERROR + die()?
Comment #10
tim.plunkett7.1, I'm confused.
If we do not catch the exception, PHP will emit a E_RECOVERABLE_ERROR, per http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tos...
That's already fatal.
Why would we want to catch the exception and emit a new different fatal?
Comment #11
stefan.r commentedThe exception would never reach the error handler... If we make it a trigger_error() it will...
Fatal error: Method Drupal\Core\StringTranslation\TranslationWrapper::__toString() must not throw an exception in /Applications/MAMP/htdocs/drupal/core/lib/Drupal/Core/Entity/EntityType.php on line 0Comment #12
lauriiiI thought we could just return an empty string from the __toString() whenever it is unable to create the string itself.
Comment #13
tim.plunkettI agree with @lauriii. And we should codify that in the test.
Comment #14
stefan.r commented@alexpott what was your reasoning for wanting it to fatal?
It's certainly possible (ie. trigger_error() with a E_USER_ERROR and hardcoding a special case in the Drupal error handler (
$fatal = $recoverable || ($error_level == E_USER_ERROR && substr($caller['function'], -strlen('__toString()')) == '__toString()');), with a fallback to die() in the catch blcok in case we are using another error handler, but do we want this?Comment #15
tim.plunkettJust cleaning up the test a bit, prophecy makes it harder to mess up in case the wrong string is passed to translate().
Comment #16
dawehnerFuck PHPUnit, see https://github.com/sebastianbergmann/phpunit/issues/487
I'm curious whether we should return SafeMarkup::format() instead, which doesn't fail but still renders something sort of usable.
Let's document that here ... why we actually need it.
Comment #17
alexpottIs it not a fatal error when t() doesn't work when we expect it to... what is the point of soldiering on?
Comment #18
stefan.r commentedif we fallback to SafeMarkup::format() it would probably just display the untranslated strings if all that's broken is t() and if things are really bad we'd fail further down the line anyway... But I think a fatal may be fine as well, at least it would prevent bad things if someone did if ($input != t('Save the kittens')) { kill_the_kittens() }
Comment #19
chx commentedBecause PHP is dumb as a bag of rocks. When an exception gets thrown while in __toString PHP dies with "__toString() must not throw an exception" and it dies with a line 0 and no stack trace. What we want here is better error reporting and a stack trace to work with. A fatal is fine.
Comment #20
chx commentedAlso there's a subtle fix here to PHP suddenly becoming strictly typed with the value of __toString https://3v4l.org/YdXQX .
Basically, when we wrote the twig autoescape patch we shied away from returning a __toString armed object from t() and every safe string because of http://www.phpwtf.org/objects-tostring-are-not-strings these things. The landscape has changed as we are pushing for Twig to escape more. So now we go risky and have much more of these objects. This issue is mitigating some of that risk. Developers will still need to string cast if using a t()'d string as an array index or a needle in strpos but both should be reasonably rare.
Comment #21
dawehnerI'm not convinced that dieing is a good idea at all. Why is the error not enough?
Comment #22
stefan.r commentedWithout entering into whether it is better to fatal or continue on a failed t() call, if we want it to definitely be fatal we'd have to resort to hacks like this to trigger a fatal error with a custom message, as our error handler doesn't consider E_USER_ERRRORs to be fatal.
Tests in this patch will also fail because the die(). I think we'd have to move that to its own method and mock it, if we even want to keep it. We don't technically need it as I believe we use the Drupal error handler everywhere and we'd have fataled anyway before we ever reach the die().
Comment #24
alexpottImo we should fatal because that exactly what would happen if we called ->render() and it threw an exception.
Comment #25
chx commentedInterdiff is pointless since it's almost the same size as the patch. Oh well! Test amended, __toString moved into trait, I think we are good to go.
Comment #26
chx commentedComment #27
stefan.r commentedThanks @chx for fixing that, if we want to fatal (which we would have done anyway in render()) this looks great now.
We don't enforce UpperCamel for traits do we?
Comment #28
dawehnerThank you chx!
Yeah I think this is now the best solution we can get. PHP is a sad world, this is for sure.
Yeah let's camel case that quickly ... sorry
Comment #29
chx commentedSure.
Comment #30
dawehnerThank you!
Comment #31
stefan.r commentedNice work all :)
Two nits that can be fixed on commit:
ToStringTrait
and a newline too much here
Comment #32
chx commentednitfixes.
Comment #33
alexpottWe should document that this forces a method called "render" to be implemented by the class that uses this. @stefan.r had a good idea of adding an abstract
render()method.Comment #34
stefan.r commentedvoila
Comment #35
stefan.r commentedComment #36
dawehner+1
Comment #37
alexpottThis issue addresses a major bug and is allowed per https://www.drupal.org/core/beta-changes. Committed f52b068 and pushed to 8.0.x. Thanks!
Comment #40
andypostIn a light of PHP 8.4 this error reporting need changes #3465827: Stop passing E_USER_ERROR to trigger_error() on PHP 8.4