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
Currently drupal_set_message()
is called inside OO code, which makes it hard to unit test. There are examples in core where this method is being stubbed out, but it is complicated. This dissuades module developers from unit testing their code.
Proposed resolution
Provide a new service to inject into OO code. Keep drupal_set_message()
for backwards compatibility, but deprecate it.
Remaining tasks
Do it.
User interface changes
None.
API changes
No changes. New API.
Original Description
Convert drupal_set_message()
and drupal_get_message()
to a service, so it can be injected and unit tested, and the implementation can be swapped.
Beta phase evaluation
Issue category | Task, because we want to able to allow proper testability of our code. |
---|---|
Issue priority | Normal, because the impact is not that high |
Disruption | No disruption, because the BC layer is kept |
Comment | File | Size | Author |
---|
Comments
Comment #1
XanoThe tests will need to be finished. I am having some trouble with that, as PHPUnit prints output before the session can be started in the test itself.
Comment #2
Xano#1 accidentally contained the wrong patch.
Comment #3
Crell CreditAttribution: Crell commentedCan we call these flash messages, since that's what Symfony's session system calls them (and what we want to use internally eventually)?
This method isn't setting the message, it's adding another message to a list. Thus, addMessage().
This function needs to go away anyway; don't add another use of it.
Comma unnecessary.
Comment #4
XanoGreat, thanks for the review! Do you have any suggestions on how to unit test this?
Comment #5
Crell CreditAttribution: Crell commentedSince it's using $_SESSION, I'm not sure if you can. :-( Not until we switch over to the Symfony session system.
Comment #6
XanoFlash messages are part of Symfony's session component. However, drupal_set_message() uses the session, but is not part of the session system. Renaming this code may therefore send the wrong message.
Comment #7
XanoComment #9
Xano7: drupal_2278383_7.patch queued for re-testing.
Comment #11
twistor CreditAttribution: twistor commentedNeeded a re-roll, thought I'd poke at the unit tests.
Comment #13
twistor CreditAttribution: twistor commentedTurns out Drush is calling drupal_get_messages() too early. I don't have time to follow up at this point.
Here's a POC.
Comment #15
twistor CreditAttribution: twistor commentedThis should fix the warnings.
Comment #16
Crell CreditAttribution: Crell commentedShouldn't all of drupal_get_messages() turn into a method call to the service? Otherwise this function is still necessary for useful behavior, which we do not want.
Can we do a sample conversion here while we're at it? For instance, this seems like a useful utility method for FormBase and ControllerBase; $this->addMessage() (or something). We don't need to convert all usages of dsm() here but having minimal integration sets the stage for the non-BC-breaking follow-up work.
Comment #17
larowlanThere should be a trait too. In at least two contrib module in working on I have a wrapper method to dsm in a trait.
Comment #18
twistor CreditAttribution: twistor commented#16, The functionality of drupal_get_messages() has been broken up into distinct methods. The code there is just for compatibility. That logic isn't needed anymore once drupal_get_message() is dead.
Guess I'll bang on this some more.
Comment #19
twistor CreditAttribution: twistor commentedTrait added and SpecialAttributesRouteSubscriber converted to use it.
Comment #20
Crell CreditAttribution: Crell commentedThe docblock should provide some direction for when to use it (and when not to). I am partial to the language introduced in #2282161: Split off link/url generation trait for obvious reasons. ;-) Of course, that makes listeners likely not a place that should use the trait; Controllers and Forms are the main users.
Aside from those points this looks good.
Comment #21
XanoI am not a session guru, but should this superglobal not be set automatically once the session has been started?
drupal_set_message() used to do too many things at once, partly because there was no central location to store the messages. This issue does not only convert messages to a service, but also improves the code by using classes' ability to store state in themselves and by splitting functionality up into different classes for better DX.
Comment #22
Xano@twistor: I am generally not in favor of adding traits that aid in setting dependencies on classes, as it does not motivate people to use dependency injection at all. Why did you add one, and why did you use it for SpecialAttributesRouteSubscriber? There is absolutely no reason that class shouldn't use constructor injection.
Comment #23
kim.pepperRe-roll of #19
I've added comments similar to what is in LinkGeneratorTrait as per @crell's comment in #20.
I also think this answers @Xano's issue in #22. Allowing the trait to work without DI is a huge advantage. We're using DI where ever possible in core, and advising contrib to use it with the comments.
RE: #21 Shouldn't we be injecting RequestStack and grabbing ->session() from that instead of using $_SESSION??
Comment #24
Crell CreditAttribution: Crell commentedWe're not yet converted over to the Symfony session handling AFAIK, so we can't use RequestStack / session(). :-(
I'm not sold on the trait, except insofar as it's something that could be argued belongs in ControllerBase and I would like to remove much of ControllerBase in favor of traits. :-) So, given that, should we add the trait to ControllerBase but NOT to a subscriber? (I agree that the subscriber shouldn't use the trait, as it's registered through the container at this point so it fails the test the trait says to use.)
Comment #25
dawehnerLet's not forgo some documentation here.
Do we have an idea about an @group?
Yeah, we can drop that shit now!
We have to specify @covers in order to let code coverage see that.
See above
I totally think this is okay to do here!
Comment #26
kim.pepperRe-rolled for #1825952: Turn on twig autoescape by default and fixes for #25
Comment #28
kim.pepperHmmm. Patch doesn't look right.
This is a straight re-roll of #23 without fixes in in #25.
Comment #30
XanoI am still against using the trait as it is of limited usefulness and does not help with setting up proper dependency injection. Not just services, but also classes that have some sort of container-based factory method shouldn't use this trait. Which use cases would then be left?
StringTranslationTrait
is an exception, because the particulart()
method is necessary for translation extraction.Comment #32
XanoComment #33
Crell CreditAttribution: Crell commentedCan we drop the trait for now and punt that to a spinoff issue to debate separately? The rest here we all seem to be OK with and we should get it in ASAP.
(FTR, I am not a big fan of the trait either as it should, really, only ever be used in controllers and forms. Other code shouldn't be using it, period. But I'm not going to die on that hill in this case. Other trait proposals I might...)
Comment #34
kim.pepperTrait be gone! (whoosh)
I also fixed an issue merging in the autoescape patch.
Comment #36
kim.pepperFixes test failures.
I'm not 100% sure of how the
SafeMarkup::isSafe($message)
part works, so need someone to review that.Comment #37
XanoI assigned the issue to myself in #32 and was just about to upload a new patch. I'm not angry about this, but please pay attention to the assigned issue property in order to prevent duplicate efforts.
Comment #38
Fabianx CreditAttribution: Fabianx commentedIn that case the marking safe and all that is happening below here in drupal_get_messages needs to be ported over to that.
The isSafe call is okay though.
Comment #39
kim.pepperSorry Xano :-( All yours.
Comment #40
XanoI added a few missing code coverage annotations.
Shouldn't this workaround be in Drush instead? We generally don't cater for specific contrib cases in core.
What does this solve? $_SESSION should exist once the session has been started. If the session hasn't been started at this point in the code, something went wrong.
This breaks the documentation of the interface, as the outputa of getMessages() and getMessagesByType() are no longer arrays of strings. It also seems silly we have to fix a Twig issue here, but I have no practical experience with auto-escape, so I may be wrong.
No worries. I just wanted to prevent accidental duplicate efforts.
Comment #41
Fabianx CreditAttribution: Fabianx commentedThis should do the same as drupal_get_messages() and process the 'safe' flag, then return a list of strings.
Explanation:
> It also seems silly we have to fix a Twig issue here, but I have no practical experience with auto-escape, so I may be wrong.
You need to ensure safe strings are persisted across page requests. This is Drupals new autoescape security model.
How you do that is up to your implementation, the current implementation uses arrays(), which is the reason why $_SESSION must not be returned directly from getMessages or getMessagesByType(), but the processing from drupal_get_messages() needs to be ported over.
That means:
Before storing in $_SESSION -> Detect which strings are safe and store somewhere, use SafeMarkup::isSafe()
After retrieving from $_SESSION -> Detect which strings have been safe in the previous request and mark them again as safe using SafeMarkup::set().
Does that make things clearer?
Comment #42
Fabianx CreditAttribution: Fabianx commentedComment #43
Xano@kim.pepper: Could you answer questions 1 and 2 from #40? I'm not sure about those two things.
Comment #44
kim.pepper@Xano: no, I'm not sure either. They were introduced with the auto-escape patch.
Comment #45
XanoComment #47
Fabianx CreditAttribution: Fabianx commentedThis looks great now! Thanks so much!
Comment #48
tim.plunkettNo earthly idea what this is. It is never used...
Comment #49
XanoComment #50
XanoComment #52
kim.pepperManual install is working for me, however, drush install fails when calling
drupal_get_message()
.Comment #53
XanoDrush can easily be patched to check for the service's existence. However, apparently we still have code in core that calls
drupal_set_message()
ordrupal_get_message()
when the service does not exist yet. I wonder if we should debug this, or just add back the hack from the previous patch until all code has been converted to use the service rather than the functions. I'm leaning towards the latter.Comment #54
kim.pepperI've created a separate issue #2347287: Provide a trait for setting messages for creating a trait that wraps drupal_set_message. We can swap it with this service once it is in.
Comment #55
XanoI added @twistor's original check for the messenger's exstistence back in, but without mentioning Drush directly.
Comment #57
XanoComment #59
XanoComment #61
XanoI added a second messenger class that stores messages in one of its properties, so it can only be used for setting messages that will be retrieved within the same request.
Comment #63
XanoComment #65
XanoComment #66
kim.pepperAwesome work getting this green, Xano!
Is this used anywhere? Or is it meant to be a swap in replacement for the sessionmessenger?
Nitpick: Double space
Comment #67
Fabianx CreditAttribution: Fabianx commentedThis comment does not look right in this context.
The static manager is nice, but it would be even nicer if the normal messenger would extend the static messenger class as commonly done elsewhere.
Currently too much code is duplicated.
I also verified the autoescape implementation and its perfectly implemented (as I was originally pinged on that).
Thanks so much!
Comment #68
Crell CreditAttribution: Crell commentedI don't know if it's not usable yet with the ongoing session work, but as a reminder Symfony has a session-based message system called flash messages that was enhanced specifically for Drupal, 2 years ago. We still haven't gotten around to leveraging it. :-) Can we yet?
Comment #69
znerol CreditAttribution: znerol commented@Crell: #2229145: Register symfony session components in the DIC and inject the session service into the request object introduces the necessary infrastructure but that is blocked by #2230121: Remove exit() from FormBuilder.
Comment #70
XanoIt is used in the installer. See the last interdiff.
Yeah. The thing is that almost every method needs to work with a different storage variable: either
$_SESSION
or$this->messages
.I was told off for wanting to introduce a new Symfony component in Austin, so I'm not sure we can do that here. We will definitely need our own interface that extends the Symfony one, though, as theirs does not allow preventing repeated messages.
Comment #71
Crell CreditAttribution: Crell commentedFlash messages are part of HttpFoundation. We already have the code. We're just not using it. Repeat prevention sounds like something to add upstream if possible.
Comment #72
Fabianx CreditAttribution: Fabianx commentedLets fix the nitpicks and this should be RTBC in my book. IMHO we can do the conversion to swap out the implementation with Symfony flash messages later - the service is simple enough and this interface nice.
Comment #73
XanoI don't like
FlashBagInterface
, because the methods are not very self-descriptive and the code documentation is very bare. On top of that, it misses the repeat flag.Could you reply to my replies to your nitpicks? :-P
Comment #74
Fabianx CreditAttribution: Fabianx commentedThe only two nitpicks left are:
* The page caching kill switch.
is describing a method having nothing to do with that - might not be explicit from the context.
Double Space from #66.
I meant to say that the code duplication was not worth the effort for the base class (that was not a nitpick, so I thought I was clear - why I was not ...)
So only two typos, and should be good to go.
Sorry for the confusion.
Comment #75
XanoRe-roll.
Comment #76
XanoIt's not a method, but a property, and the service ID is
page_cache_kill_switch
.Comment #77
Fabianx CreditAttribution: Fabianx commentedHere it says
'The page caching kill switch.'
which is wrong and what I meant.
Comment #78
XanoThanks for clarifying that! I fixed the property description and changed the three-space indentation to two spaces.
Comment #79
Fabianx CreditAttribution: Fabianx commentedBack to RTBC then, thanks so much
Comment #80
alexpottWe should deprecate till Drupal 9.0 now and not 8.0.
I don't think we should commit this with the workaround. This is basically hiding dependency problems. We should convert all the code this fails because of this problem in the this patch.
We can remove SafeMarkup from bootstrap.inc now.
Spelling mistake.
Comment #81
dawehnerHere is a review ...
If we need this, there might be good reasons, so can we document when we need this? Maybe early installer?
In general I think drupal_set_message() is something you tend to use REALLY often, right? Most form submit methods have some for example. Did you considered to introduce \Drupal::messenger() or \Drupal::message()?
Can we have some general description like: Allows to add messenges visible by the user to the site?
Given that SafeMarkup problem, did we thought about also providing support for render arrays and so directly use
'#type' => 'inline_template'
?Its kind of odd from an architecture point of view that each implementation has to take care of that. Maybe you could at least have a common base class to simplify stuff like processMessages etc?
One thing I don't see yet, but is certainly REALLY important is a test for checking that SafeMarkup/escaping is done properly
We can drop those
Its kinda odd, that you have to do that on your own. If you read about https://phpunit.de/manual/current/en/appendixes.annotations.html#appendi... and https://phpunit.de/manual/current/en/fixtures.html#fixtures.global-state it is a pitty that $_SESSION is explicit not listed here.
You could split this test up in multiple test methods using https://phpunit.de/manual/4.3/en/appendixes.annotations.html#appendixes....
Comment #82
effulgentsia CreditAttribution: effulgentsia commentedSee #2073817-9: [META] Remove drupal_set_message()
Comment #83
tibbsa CreditAttribution: tibbsa commented#1251960: harmonize severity/type in watchdog and drupal_set_message has been around for some time and suggested changes to the '$type' parameter that might be worth considering. If we're going to deprecate drupal_set_message() altogether in due course, it is probably worth considering whether any other API changes are worthwhile to do at the same time.
Comment #84
dawehnerI think its wrong to not do it now, if folks are interested to work on it.
a) We want to make the life easy for people, if this means providing a service, then we should do that. It has obvious advantages like unit-testabilty,
b) Why should drupal_set_message() be excluded but #2426805: Modernize drupal_get_destination() got in?
c) The session work moved forward in the meantime, so we could solve things maybe better now.
Comment #85
Crell CreditAttribution: Crell commentedI agree with dawehner. Improved testability via decoupling is a benefit for everyone working on core, because it means more and more code becomes easy and fast to test. It only takes a single drupal_set_message() call to make a proper unit test with PHPUnit impossible/prohibitively hard.
We obviously can't remove the existing function at this point in the cycle, but no one is proposing that. Just that it, like so many other functions, front for a sustainable version that can carry us through the full 8.x lifespan.
While we could do much of this work in 8.1, 8.0 is what most books and documentation will get written for. Getting certain things *right* before they're captured for all time in tree carcasses is important to ensure the community learns good practices from the beginning rather than needing to relearn them again 6 months later, because most won't. It's also another point for non-Drupal PHP devs to look at Drupal and go "oh, it's still lame, never mind"; we want to avoid that.
Comment #86
Fabianx CreditAttribution: Fabianx commentedComment #87
XanoI understand and agree with the decision that we need a period of only fixing bugs before we publish a new Drupal version, but that period does not need to be 6+ months. This also does not add new features and things like testability should have a very high priority, as they support improved code quality.
Next to that, deciding that these internal refactorings should be postponed long before the aforementioned bug-fix-only period has started is a huge demotivation to people who are willing to spend their time on improving the code base *and* to people who are interested in adopting Drupal.
TLDR; I vote for re-opening this issue.
Comment #88
kim.pepperYou had me at 're-open'.
Updated issue summary, and added beta stage evaluation (very similar to the one in #2426805: Modernize drupal_get_destination() !)
Comment #89
kim.pepperComment #90
kim.pepperUpdated issue title, as we are no longer proposing to replace
drupal_set_message()
.Comment #91
kim.pepperWould like to get some feedback from committers as to why #2426805: Modernize drupal_get_destination() passed the beta stage evaluation and how that relates to this issue.
Comment #92
XanoIf I follow the beta changes flow chart, I come to the conclusion that this could possibly be allowed because it reduces fragility, as we will no longer need to declare drupal_set_message() in every unit test, something that has broken test runs in the past.
Comment #93
jibranI think it's a good idea and we can do it without BC break as well by keeping wrapper function.
Comment #94
kim.pepperIs anyone brave enough to change this back to 'active'?
Comment #95
dawehnerI don't have any problem with doing that.
Comment #96
Fabianx CreditAttribution: Fabianx commentedComment #97
alexpottSo for me the reason #2426805: Modernize drupal_get_destination() was permitted is that it directly relates to the routing system that we've been modernizing through the release and its testability. The message system has not been modernized and is a bigger problem space on its own than
drupal_get_destination()
. Currently there are 48 calls todrupal_get_destination
- there are 417 tod_s_m()
. The call I made ondrupal_get_destination()
was that the disruption (because there is disruption and risk even with a bc layer) was worth it. I'm not sure I could or would make the same argument here.Comment #98
xjmThanks @alexpott and @dawehner.
Following the beta evaluation linked in the summary:
It does not matter whether or not it is disruptive -- following the flowchart, a normal task with no prioritized changes is postponed. Therefore, this issue should remain postponed to 8.1.x. If anyone can make a case for why any of the points in the list above are not true, please do so in the summary and we can discuss it further, but I think it'd be better to focus resources elsewhere. Thanks!
Comment #99
alexpottThe only test that has a fake implementation of drupal_set_message() is AggregatorPluginSettingsBaseTest. I think we should just convert that to a KernelTestBase test and move on.
Comment #100
dawehnerI'll try to make another point, DX consistency.
I had a look through common.inc and bootstrap.inc and had a look which don't have yet a more modern variant yet.
drupal_set_message()
is from my point of view one of the view remaining methods which are really often used (proven by alex in #2278383-97: Create an injectible service for drupal_set_message().There is drupal_get_path() / drupal_get_filename() but they are really not often needed, now that many things are classes.
Comment #101
PolHello all,
FYI, I took this patch and added it to the 8.x-1.x branch of Service Container.
Link of the pull request: https://github.com/LionsAd/service_container/pull/58
Comment #102
Fabianx CreditAttribution: Fabianx as a volunteer commentedRe - #101:
Due to the not-sure-this-will-the-final-implementation-in-Drupal-8.1 we instead used our LegacyMessenger from Drupal 7 and just used the MessengerInterface.
Comment #103
hass CreditAttribution: hass commentedComment #104
Mile23Agreed we should make dsm into a service, but the test problems are somewhat fixed in this WIP: #2301873: Use ExtensionDiscovery to register test namespaces for running PHPUnit Patch in #8.
Comment #106
andypostComment #107
kim.pepperComment #108
dawehnerLet's reroll it, fix a couple of things and try to get the call rolling again.
Comment #110
dawehnerLet's see whether this helps
Comment #112
xjmComment #113
dawehner1137, 1138, let's see, maybe the next patch will be 1139.
Comment #115
dawehnerLess failures
Comment #116
jibranCan we use session parameter bag here?
Comment #117
dawehnerThank you for your review @jibran
Well I considered this issue as not changing the internal behaviour at all, but rather providing just the service. We can afterwards try to change the internals.
Comment #118
dawehner@jibran
To clarify my answer a bit more ... this patch is a patch that optimizes for reviewability. It changes one thing, rather than two at the same time. There is no reason we cannot do the other step, but we already gain a lot by just going the first step.
Comment #119
jibranThanks for the explanation @dawehner.
Let's add some explanation here for the documentation
Just wondering, do we really need kill switch for static messenger?
Comment #120
Fabianx CreditAttribution: Fabianx as a volunteer commented+1 to #117 and first providing the interface, then changing the implementation!
Comment #121
dawehnerThank you @jibran, let's document a bit more.
Well, the page output still varies so we should not cache.
Comment #122
jibranThank you for improving the docs.
This doesn't seem right. What are we trying to say here?
s/message to/messages for
Right! but isn't the page uncached already?
Comment #123
Xanos/send/sent
@jibran already pointed out this does not make sense in English (the sentence was likely edited a couple of times, it happens), but I also think we should describe the type of messages in more detail. This interface is responsible for handling runtime messages to individual users, as opposed to log messages or private messages, for instance.
I propose prefixing the constants with
TYPE_
or something similar, for readability, so we can easily reference them in documentation, and they will not collide with possible future constants.$message
isstring|\Drupal\Core\StringTranslation\TranslatableMarkup
If we prefix the constants like suggested earlier, we can simplify this comment by replacing individual constant names with
self::TYPE_*
.I have come to dislike fluent interfaces since I first worked on this issue, since it's hard to mock and decorate, and does not provide too many DX improvements for production code. Can we change these methods to not return anything at all?
We could update the constant names to
self::TYPE_*
here too.The class does not know it's the default implementation, and shouldn't say it is. That's all up to the service container.
Do we support
MarkupInterface
orTranslatableMarkup
?string|\Drupal\Core\StringTranslation\TranslatableMarkup
Can we somehow replace the kill switch by exposing cacheability data?
Comment #124
chx CreditAttribution: chx as a volunteer commentedI found it strange that $_SESSION is still in the latest patch.
Comment #125
jibranRE:#123.6 I think it is more of a personal preference but returning
$this
has its own benefit and I kind a like it so let's not bikeshed on it here in this issue. I think we are already discussing it in #2134513: [policy, no patch] Trait strategy.Comment #126
Fabianx CreditAttribution: Fabianx as a volunteer commented#124: We are doing baby steps here. Once the interface is stable the implementation can be enhanced / changed / debated and bike shedded internally.
Comment #127
XanoThere are some factual concerns, but I agree that personal preference and experience influence how serious those concerns are to people. I don't mean to bikeshed anything, but since this is about a new public API, it's part of the discussion here.
Personally I have not been able to think of reasons for introducing a fluent interface here. It's not some kind of builder we are adding, so repeated calls to the same instance will be rare, if they ever happen at all.
I quickly checked #2134513: [policy, no patch] Trait strategy and I did not see anything relevant. Could you perhaps point us to the correct comment?
Comment #128
dawehner#126, #124
I hope we can agree on this. Here is a follow up: #2760167: Add \Drupal\Core\Messenger\Messenger
Improved this.
Its just for the installer so it really doesn't matter, but IMHO its more "correct" to just do it. It also gives a good examples in case someone comes up with an alternative implementation.
I changed the text again to include a concrete example, which IMHO, should make it clearer.
Surem why not!
Do we do that anywhere else in core?
MarkupInterface
is designed to be hidden from the user.IMHO as we have just 3 examples we should list them.
I see your point, especiall on interfaces which are not meant to be called more than once. On the other hand this would break quite the consistency we have now in many places all over core. What about opening up a dedicated discussion for future API designs?
If you read the code above its actually a Markup object at this point in time.
No we cannot. Page cache is designed to not use cacheability metadata, as this would be something outside of the HTTP layer.
Comment #129
dawehnerHere is the patch as well.
Comment #130
Wim LeersThat's a little bit over-simplifying. In this case, the cacheability metadata we need to bubble is
max-age=0
. Not cache tags/contexts. So in this case, we could actually make that work. But until we have #2352009: [pp-3] Bubbling of elements' max-age to the page's headers and the page cache, we can't. That was deemed to big a change before D8.0.0, so we didn't get that.The real problem here is that the thing calling
drupal_set_message()
is not guaranteed to also be directly rendering something into the response that can setmax-age=0
.Ideally, you wouldn't use a kill switch, but a
\Drupal\Core\PageCache\ResponsePolicyInterface
. And since the message is associated with a response, ideally you'd have#attached['messages']
, just like you have#attached['library']
,#attached['http_header']
, et cetera. Then the response policy could do something like:However, since this issue continues to use
$_SESSION
, perhaps that's something for #2760167: Add \Drupal\Core\Messenger\Messenger.Comment #131
Fabianx CreditAttribution: Fabianx as a volunteer commented#130: However we both know that the kill-switch in drupal_set_message() can be pretty useless - if the request is forwarded to another URL e.g..
However given the complexity of the space, this should definitely be a separate follow-up issue.
Comment #132
dawehnerRight this discussion is quite out of scope of this issue. :)
Comment #133
XanoThe reason I raised this, is because I figured the newly introduced public API (the interface) might depend on whether or not we support cacheability data. If it does indeed depend on it, it's in scope and MUST be fixed in this patch, because we cannot break BC once this new service has been released into the wild as part of a stable Drupal release. If adding cacheability metadata is not and will not be relevant, then let's just keep going the way we were and get this thing in :)On second thought: @Wim Leers is obviously right in #130 where he said that messages have a max-age of 0, since they can never be cached at all. Based on that we do not have to provide any caching functionality in the newly introduced public interface.
Comment #134
Xano@dawehner: Thanks for the new patch, and @Wim Leers thanks for reviewing this from a cacheability point of view!
I'm not sure if we do, but since we don't technically just work with strings, we should document it. Let's put it another way: if we'd use a
string
type hint, the type check would fail on translatable markup.I don't really mind, except that this is hard to update in the future. Nowhere near a blocker, though.
Comment #135
dawehnerWell, we use string in let's say 1mio other places.
I don't really mind, except that this is hard to update in the future. Nowhere near a blocker, though.
I hope we don't add another type rather soon than later :)Comment #136
dawehnerBack to needs review ... I hope that's fair, as I have given a point.
Comment #137
dawehnerNow that I commented I realized, that drupal_set_message() did the same, so let's do the same here as well :P
Comment #138
XanoThanks for clarifying the types!
Is
[][]
a thing? I can't find it in our documentation standards, but I'd be happy to use it!Comment #139
XanoCorrecting what looks like accidentally incorrect commit credit settings.
Comment #140
dawehnerComment #141
dawehnerI've seen it in other places, and well it kinda just makes sense. type[] is an array of type. So when type=type2[], then type[] is an array of array of type2.
Comment #142
Gábor HojtsyComment #143
Fabianx CreditAttribution: Fabianx as a volunteer and at Tag1 Consulting commentedComment #144
Xano@dawehner: Agreed. Let's go for it.
I went through the patch again and this looks good to go to me. Thanks, everybody!
Comment #145
xjmIt's exciting to see this issue RTBC!
Tagging for a framework manager's review given the architectural importance of this.
Edit: @Xano, as of last I checked, only committers could actually save issue credits. A new feature could have been deployed, but in case it didn't seem to work I wanted to explain why.
Comment #146
catchThis just eats the message, whereas the previous code would put it into $_SESSION always. Are we actually hitting this condition and if so what's getting lost?
Comment #147
catchComment #148
catchThat workaround was brought up in #40, #80 and #81 as well - let's remove it from the patch.
Comment #149
joelpittetRemoved from the patch re #148 Let's see what happens
Comment #150
andypostGreen! Looks that workaround for some contrib that trying access message in early bootstrap with incomlete container
Comment #151
alexpottDiscussed with @catch. Neither of us have any framework concerns with this patch. Using $_SESSION is mandatory for BC unfortunately but it's a simple refactor for Drupal 9.
Committed ee22272 and pushed to 8.2.x. Thanks!
Comment #153
claudiu.cristeaAfter I saw this fixed I jumped to read the CR :) Or is not needed because we are only deprecating
drupal_set_message()
?Comment #154
Fabianx CreditAttribution: Fabianx as a volunteer and at Tag1 Consulting commented#153 A change record should be good indeed.
Comment #155
dawehnerI'' write one
Comment #156
dawehnerCan someone have a look at it https://www.drupal.org/node/2774931 and publish it if it looks okayish?
Comment #158
alexpottSo without this code drush can not install Drupal 8. It would have been better if the comment had given the example because this is probably why this was here.
Comment #159
alexpottIf we do have this workaround in core then we should try to set up a test for it.
Comment #160
twistor CreditAttribution: twistor as a volunteer commentedI think I implemented that hack, and if I remember, it was for Drush.
Can't we just fix Drush?
Comment #161
alexpott@twistor well yes but then that needs deploying etc... and this won't make it into 8.2.x. I think the workaround is okay - it just needs better docs and maybe a test. You could use an isolated PHPUnit test to do this for example.
Comment #162
alexpottOr a kernel test where you remove the container from \Drupal
Comment #163
dawehnerSure, let's open a follow up #2775211: [PP-1] Test and document why drupal_set_message() has a workaround for a missing container
Comment #164
catchdrupal_get_message() is also used to clear messages in $_SESSION, so if we have the workaround at all, it should retain bc by handling that case, not just return [];
Comment #167
dawehnerCan someone actually explain why this was rolled back?
#2278383-158: Create an injectible service for drupal_set_message() seems not like a real explanation for that.
Comment #169
Mile23Comment #170
catch@dawehner I'm not @alexpott but assuming there's an exception when you try to install with the patch applied via drush - that seems like enough reason to roll back? Either we'd need to add back in the workaround, or get drush fixed upstream (but even then individual installs will still be out of date).
Comment #171
dawehnerThank you for answering my question!
Okay, so adding this layer is enough here?
Comment #172
catchYeah I think it's https://www.drupal.org/node/2278383#comment-11429167 reverting the interdiff but then adding a longer comment about why it's there.
Also it's not a bc layer at the moment, it's just eating failure - it should probably clear the messages if $clear = TRUE?
Comment #173
jibranSo we just need to address #172.
Comment #174
Fabianx CreditAttribution: Fabianx as a volunteer and at Tag1 Consulting commentedI would still suggest (if getting this in poses to be difficult) a 2/3-step process to get this in:
- Rename drupal_set_message to _drupal_set_message - instead of removing, mark as @internal and possibly @deprecated
- Have drupal_set_message call \Drupal::service('messenger') (etc. - like in this patch)
- Create a LegacyMessenger class that calls the _ functions
(e.g. possibly similar to http://cgit.drupalcode.org/service_container/tree/src/Messenger/LegacyMe... though also just calling the functions is fine with me.)
Then in a 2nd follow-up issue do the actual conversion and deal with BC, etc.
The advantage of splitting design / interface and implementation is that we can have the new interfaces and services, but don't have to worry about BC and breaking code until later.
--
Just a suggestion to get the important part (the service and the interface) finally in.
Comment #175
dawehnerI really like this approach. This allows us to not focus on the failure for now. Great suggestion @Fabianx!
Comment #176
PolMe like it too.
Comment #177
Anonymous (not verified) CreditAttribution: Anonymous commentedYou would be better off separating the responsibilities of the messenger service both handing notifications, and notifying page_cache_kill_switch service, by dispatching an event instead. You could then have an observer that is responsible for triggering the page_cache_kill_switch when the messenger service is triggered.
Also I think the API could do with being modernised a bit, and removing the need for constants. I would take some tips from PSR's LoggerInterface (https://github.com/php-fig/log/blob/master/Psr/Log/LoggerInterface.php) and have something along the lines of:
That way you can be sure that the concrete implementation handles each expected type of message properly. As the BC layer I would then suggest that the implementation of drupal_set_message() be changed to:
Comment #178
dawehnerThe comment in #177 is why we should things one step at a time and then discuss that later.
Comment #179
Fabianx CreditAttribution: Fabianx as a volunteer and at Tag1 Consulting commented+1 to #177: Lets create a nice interface first :).
Comment #180
dawehnerTo be honest the interface as of now as part of the patch seems to be reasonable for me.
Comment #184
jibranComment #185
jofitz CreditAttribution: jofitz at ComputerMinds commentedRe-rolled.
Comment #186
jibranThis addresses #158 and we are back to RTBC because we don't have any other feedback. I marked #2775211: [PP-1] Test and document why drupal_set_message() has a workaround for a missing container and #2760167: Add \Drupal\Core\Messenger\Messenger as postpone on this.
Comment #188
jibranPHPCS fix.
Comment #190
jibranHopefully, this will fix the fails.
Comment #191
dawehnerSome changes:
What do you think?
Comment #193
dawehnerThis fixes a couple of the installation issues ...
Comment #195
dawehnerLet's remove the unit test for the class, which no longer exists.
Comment #196
Wim LeersFor now, a superficial review, with first impressions.
Totally off-topic: I can't see this and not think of Facebook Messenger or MSN Messenger :P
Hm I'm not sure what this means exactly…
This seems wrong:
* /**
.It's a queue! This is important to state in the docblock, I think: that messages are presented to the user in the order they were added to the queue. And therefore the message order depends on the code execution order. No sorting.
Note: Symfony uses
all()
for this. Maybe we should too?Comment #197
dawehnerThis is a good point.
I tried to rename a good amount of methods now:
Comment #199
dawehnerLet's fix it :)
Comment #200
kim.pepperThanks @dawehner!
A couple of minor tweaks:
This wording can be improved. What about: "This function might be called early on in the installer, so we check whether the service exists."
8.4?
Comment #201
pritish.kumar CreditAttribution: pritish.kumar at OpenSense Labs commentedMade the changes as specified in #200.
Comment #203
jibranThe patch looks good to me. We should update change notice and add all new methods to it.
Comment #204
Mile23Poor dsm(). Always one day too late to be refactored. Can we please move this to 8.4.x in some way, or is it too much of an API change?
Say '@deprecated in Drupal 8.4.x, will be removed before Drupal 9.0.0.'
Unless we're really going to wait for 8.5.x on this.
Also needs a follow-up to @trigger_error() on this.
Should drupal_get_messages() also be deprecated?
Comment #205
kim.pepperUpdated change notice.
Comment #206
kim.pepperThat ship has sailed.
Updated the deprecation message.
Comment #207
jibranLooks good now. Thanks, @kim.pepper.
Comment #208
kim.pepperA few minor nitpicks which can be fix on commit.
Reference to 8.4
Another reference to 8.4
Needs a grammar fix.
Comment #209
larowlanThis is quite a convoluted ternary. Can we add brackets around it, or break it onto it's own line please?
Any reason why these are stand alone and not just part of the LegacyMessenger class?
If we can't be certain that the messenger service exists (this legacy class is used in early bootstrap etc) - can we be sure the page cache kill switch exists? If so then is it being added by the Installer service provider? If so any reason why we can't do the same?
Comment #210
larowlanSee http://cgit.drupalcode.org/drupal/tree/core/lib/Drupal/Core/Installer/In... for InstallerServiceProvider
Comment #211
larowlanIn regards to my questions 2 and 3, saw earlier comments from @FabianX and the follow-ups.
However, I'm not totally convinced on the stand alone functions, I think that inlining them into the class as protected methods would avoid needing to have them marked as deprecated/internal.
Happy to punt the service container workaround and use of SESSION to the follow up.
Comment #212
dawehnerFair, I tried to fix it.
I think a good middleground are private functions on the object, aka. functions which can be completely changed in the future.
Comment #214
jofitz CreditAttribution: jofitz at ComputerMinds commentedMoved ternary onto it's own line.
Removed redundant newline.
Comment #215
dawehnerThank you @Jo Fitzgerald!
Comment #216
jibran#209.1 and #209.2 are addressed just two minor issuse.
It'd be nice to add some docs here.
s/8.5/8.5.x
Comment #217
dawehnerThank you @jibran
Comment #219
jofitz CreditAttribution: jofitz at ComputerMinds commented@dawehner It looks like you based your patch off #212 rather than #214 - you have re-introduced your error around the ternary in bootstrap.php.
Comment #220
dawehnerOh you are totally right. Thank you!
Comment #221
jibranThanks, @dawehner and @Jo Fitzgerald. This is ready.
Comment #222
larowlanIf we're not safe to universally call
\Drupal::service('messener')
are there instances where unconditionally calling for the page cache kill switch are problematic too?I think this is supposed to link to the change record?
See https://www.drupal.org/core/deprecation
nit: trailing whitespace, can be fixed on commit
Comment #223
kim.pepperComment #224
kim.pepperDiscussed with @larowlan in chat whether or not we still need to check if the messenger service exists in the early install phase, and decided to post a patch here that removes it to see if tests pass. It was 3 years ago this was a problem, after all.
(interdiff is against #220)
Comment #225
larowlanOne minor nit for 224 (if it should pass)
+ * (optional) The page cache kill switch.
its not optional anymore
can be fixed on commit
Comment #226
kim.pepperIf tests are green, we need to do a site install with a recent version of drush.
Comment #227
kim.pepperManually did a site install using drush 9.0.0-beta4 and did not see an error. \m/
Comment #228
jibran#226 was my only concern after the changes we made in #224. I think patch is ready. We don't need to test it with 8.4.x beacuse we are not going to backport it so RTBC.
Comment #229
larowlanSorry, this needs a @see to the change record too.
Do we need to be adding
trigger_error
here too?Or is that only after everything is converted? I will try and find clarification.
Comment #230
larowlanDiscussed with @catch and we agreed on the following plan
- remove the deprecation of drupal_set_message/drupal_get_message and the LegacyMessenger.
- mark MessengerInterface internal (for now)
- keep LegacyMessenger as internal
Then in #2760167: Add \Drupal\Core\Messenger\Messenger when we have a genuine alternative, add the deprecations back, and remove internal from MessengerInterface
No need for trigger_error here either, that will come in the follow-up when we do have a non deprecated alternative
Comment #231
dawehnerI see, so we keep things as internal as possible till we figure out some way to deal with it properly.
@kim.pepper If you have time, please give it a try.
Comment #232
kim.pepperSounds good.
Comment #233
jibran#230 is a good plan. Thanks for the changes @kim.pepper
Comment #235
larowlanCredited @catch for time yesterday debating/devising the BC/deprecation approach that we settled on.
fixed on commit
Committed as 48a8e53 and pushed to 8.5.x.
Unpostponed the followup #2760167: Add \Drupal\Core\Messenger\Messenger and updated the issue summary over there.
Would be good to see some movement over there so we can deprecate drupal_set_message and remove the LegacyMessenger in time for 8.5.0-alpha1.
Comment #236
larowlanMoved the change record to the follow-up as its going to be when we do the actual deprecation.
Comment #238
Rob C CreditAttribution: Rob C commentedHi all,
#2952634: LegacyMessenger::deleteByType does not delete anything
So i think this issue might be related. Could some of you reply in this issue to get it fixed asap?
Thanks!
Comment #239
andypostFiled small follow-up #2985709: Remove outdated @todo in StatusMessages
Comment #240
jonathan1055 CreditAttribution: jonathan1055 as a volunteer commentedAdded change record url https://www.drupal.org/node/2774931 to I.S. as it was only mentioned once, in comment #156 and is useful to have it at the top for easier access.
Comment #241
markhalliwellJust added this issue to the change record itself; this allows the change record to show up in the sidebar automatically.