Problem/Motivation
DrupalKernel
has a mixture of concrete and static methods which all need to use the Drupal file system.
Concrete methods already have $this->root
which they can use to discover the root directory for Drupal. However, $this->root
is set based on assumptions about where Drupal core sits in the file system.
Static methods still rely on DRUPAL_ROOT
which, itself, is set based on assumptions about Drupal's location in the file system.
These assumptions make it tricky to mock or test the kernel in many ways, and also is generally inelegant.
Proposed resolution
To solve these issues, we should inject the application root directory into the DrupalKernel
object on creation, and also inject the root into the various static methods.
Since much calling code does not know how to do this, we can make these injections optional, allowing the kernel object to make a reasonable guess about the root directory path.
This allows testing code to not have to deal with the DRUPAL_ROOT
constant. It also means that we can eventually untangle the need for legacy includes.
Remaining tasks
User interface changes
API changes
Data model changes
Comment | File | Size | Author |
---|---|---|---|
#24 | 2631362_24.patch | 9.34 KB | Mile23 |
#22 | interdiff.txt | 554 bytes | Mile23 |
#22 | 2631362_22.patch | 9.28 KB | Mile23 |
#16 | interdiff.txt | 3.6 KB | Mile23 |
#16 | 2631362_16.patch | 9.28 KB | Mile23 |
Comments
Comment #2
Mile23Le patch.
Comment #3
Mile23Comment #5
Mile23Ah, if only I could get the local testbot working....
Comment #7
Mile23Three's a charm?
Comment #8
tstoecklerYay, this is quite an awesome patch.
The "|null" can be dropped, it's not that NULL is an explicit value with a semantic meaning, it's just that the parameter is optional. Similarly the "or NULL" and the "Default to NULL" can be dropped.
All of this applies to multiple hunks in this patch
Seems the $allow_dumping parameter is added needlessly.
Comment #9
hussainwebGreat patch, @Mile23. I am changing the comments as per suggestions in #8.1. I am not too sure about the second point. I think there is value in keeping the parameters consistent in inheriting classes.
Comment #10
tstoecklerHmm... I missed the inheritance part. Still though, if we are not actually using the parameter I don't think we should declare it. Otherwise I think we should be passing it on to the parent.
Comment #11
hussainwebAnd I missed the parameter. I was sure I saw it being passed. Anyway, it seems it has to be FALSE and I have changed the default parameter to FALSE. I think the inherited docblock is now inaccurate. Any suggestions?
Comment #12
tstoecklerYes, that way it makes sense, IMO, thanks. Not sure about the docblock.
Comment #13
Mile23See the === ?
It means we need to document string|null, because the type of the parameter matters to the code.
I'm pretty sure the reason we override createFromRequest is so we can insert our new defaults for optional parameters. Otherwise we don't really need it. So yay, that stays. But....
On the other hand, the reason we pass FALSE to parent in the constructor is so we can explicitly always turn off dumping.
So we do need to keep the FALSE, but also add the $app_root parameter.
Comment #14
Mile23Reverted the
string|null
in docblocks, re-added FALSE toTestRunnerKernel::__construct()
.Also changed visibility of
guessApplicationRoot()
to be private, so that we don't end up with callers just calling it as an input to the factory, or worse using it to discover the app root.Comment #15
hussainweb@Mile23: I see the
===
, but isn't that used to set the value to a default guessed application root? In other words, NULL has no semantic meaning for the parameter, it is just used to keep it optional. This is what happens in rest of the Drupal code where it is not documented as NULL, jut optional.For the
$allow_dumping
, there is an advantage in using the variable instead of literalFALSE
. In normal usage, callers would skip this parameter and it would remain FALSE (which is default). However, what if a caller explicitly wanted to pass TRUE to the parent. I know that is not in the scope of this issue but we are effectively blocking it here and not even documenting why we are not using $allow_dumping. This could lead to confusion later.I'd suggest changing it back to the parameter OR documenting why we are using FALSE and create a follow-up.
Comment #16
Mile23Right. Exactly. :-) The thing is that it's there to force the kernel to never allow dumping. It's the version of the kernel that runs the tests, so it shouldn't dump its container; it should always rebuild it on the next test run, and it should remain isolated from the tests.
I don't necessarily agree with it, but that's how it's designed. http://cgit.drupalcode.org/drupal/tree/core/lib/Drupal/Core/Test/TestRun...
Changing it is out of scope here. File a follow-up if you'd like.
OK, so also reverted docblocks so that now we have
string
instead ofstring|null
.Comment #17
dawehnerThank you for keeping the changes as much in scope as possible!
I like getting the app root more sane, thanks a lot for that!
we never use private functions, let's just keep using protected here
In other places we used $this->root, what about keep doing that?
Comment #18
Mile23Is there a reason we never use private methods, other than we never use them?
The reason it's private is in #14.
In an ideal world that method wouldn't exist, because we'd require the injected app root rather than allowing it to be optional. Then no one would ever guess. But that would be a major refactoring and a bit of an API change. So having the guess be private discourages others from relying on the guess.
Comment #19
dawehnerWell, the thing is, that some people maybe want to change its behaviour. For such a flexible system as Drupal it is sometimes impossible to know.
Comment #20
Mile23If they want to change its behavior then they can submit a patch. I made it private so people wouldn't use it outside the kernel. See #14.
Comment #21
dawehnerMake it protected and deal with it. Its not that hard. You just waste your personal time ... people will block the commit etc.
Comment #22
Mile23So I shouldn't use
private
because an unknown person might thinkprivate
is bad, and wouldn't be convinced by #14, and leaving it alone will waste *my* time.Ok, phantom reviewer, this one's for you...
Here's a patch that says
protected
instead. If anyone other than the phantom reviews it, I'd really appreciate it if you could say something like, "Why is this methodprotected
? It looks like it should beprivate
, since that will encourage people to walk the path of dependency injection, an idiom we've adopted here in the Drupal project with the release of Drupal 8, and basically the raison d'etre of this patch."Thanks.
Comment #24
Mile23Rerolled for 8.2.x.
We really should just force the injection of DRUPAL_ROOT without giving an option not to.
Comment #25
dawehnerWell, this is not really an option in Drupal 8.x ...
In general I really like this patch. As a small followup we could even create try to replace the DRUPAL_ROOT constant with a call to the kernel.
Comment #27
catchNice patch.
Committed/pushed to 8.2.x, thanks!
Forgot to add commit credit before commit, but did it after.