The module currently has several uses of \Drupal in classes which could be replaced via proper use of dependency injection.
We should aim to fix these problems before creating the 2.0-beta releases, as at that point we should no longer do any BC-breaking changes.
drupalcsp --sniffs=DrupalPractice.Objects.GlobalDrupal .
FILE: /Users/jcnventura/drupal/8/modules/simplenews/src/Form/SubscriberExportForm.php
---------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE
---------------------------------------------------------------------------------------------
45 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
---------------------------------------------------------------------------------------------
FILE: /Users/jcnventura/drupal/8/modules/simplenews/src/Form/SubscriptionSettingsForm.php
---------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE
---------------------------------------------------------------------------------------------
51 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
---------------------------------------------------------------------------------------------
FILE: /Users/jcnventura/drupal/8/modules/simplenews/src/Form/NewsletterForm.php
----------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 5 WARNINGS AFFECTING 5 LINES
----------------------------------------------------------------------------------------------
59 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
173 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
216 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
220 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
224 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
----------------------------------------------------------------------------------------------
FILE: /Users/jcnventura/drupal/8/modules/simplenews/src/Form/SubscriptionsFormBase.php
----------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 5 WARNINGS AFFECTING 5 LINES
----------------------------------------------------------------------------------------------
173 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
217 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
272 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
290 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
310 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
----------------------------------------------------------------------------------------------
FILE: /Users/jcnventura/drupal/8/modules/simplenews/src/Form/MailSettingsForm.php
---------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 3 WARNINGS AFFECTING 3 LINES
---------------------------------------------------------------------------------------------
63 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
64 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
65 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
---------------------------------------------------------------------------------------------
FILE: /Users/jcnventura/drupal/8/modules/simplenews/src/Plugin/Block/SimplenewsSubscriptionBlock.php
----------------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 2 WARNINGS AFFECTING 2 LINES
----------------------------------------------------------------------------------------------------
156 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
170 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
----------------------------------------------------------------------------------------------------
FILE: /Users/jcnventura/drupal/8/modules/simplenews/src/Controller/ConfirmationController.php
----------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 9 WARNINGS AFFECTING 9 LINES
----------------------------------------------------------------------------------------------
35 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
64 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
71 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
78 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
142 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
168 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
177 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
182 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
190 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
----------------------------------------------------------------------------------------------
| Comment | File | Size | Author |
|---|---|---|---|
| #6 | drupal_class_should_be_avoided_in_classes_2.patch | 23.12 KB | gg24 |
Issue fork simplenews-3087462
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:
Comments
Comment #2
gg24 commentedHi,
I am working on it.
Comment #3
gg24 commentedHi,
I have created a patch. Please review.
Thanks!
Comment #4
gg24 commentedHi,
Rerolled the patch and fix few issues. Please review the patch.
Thanks!
Comment #5
gg24 commentedHi,
Rerolled the patch and fix few issues and warnings for tests failing. Please review the patch.
Thanks!
Comment #6
gg24 commentedHi,
Rerolled the patch and fix few issues and warnings for tests failing. Please review the patch.
Thanks!
Comment #7
adamps commentedThanks @gg24 that looks like good progress. These changes are not BC so if we are going to commit this it needs to be in before 2.x beta. If we can get a good patch in the next 2 weeks that would be great.
Here are some comments.
In many cases you can find code in Drupal Core that you can copy exactly. Here is some code I grabbed randomly from
AjaxResponseAttachmentsProcessorbased on a grep.This shows three problems present in many places in your code:
1. Must use the interface not the class of the default implementation. Otherwise when someone injects a different class the code will fail. For example
ModuleHandlerInterfaceinstead ofModuleHandler.2. For a comment containing the name of a service, please use spaces to make words: "The module handler".
3. For a @param comment use the full class name including a leading slash.
One other block copy error:
4. Name mismatch in
SubscriptionsFormBase.php:Comment #8
prabha1997 commentedI am working on this issue
Comment #9
adamps commentedThanks @prabha1997.
Unfortunately as we have now had a public beta release for 2.x I can't commit a patch to 2.x. This will have to wait until 3.x, and there isn't a branch for that yet. Please can you hold off for now?
Comment #10
marcos_lima commentedHi @AdamPS! Does this issue still need to be addressed? If so, I would gladly work on it.
Comment #11
adamps commentedThank you for the offer. Now is a good time - if you are quick😃.
We can make the changes in 3.x, provided that it has not yet had a beta release. I plan to make a beta soon, ideally within a week.
Comment #12
marcos_lima commentedAll right! Assigning it to myself then.
Comment #14
marcos_lima commentedI rerolled patch #6, then opened an Issue Fork and made the changes proposed in #7. I made a MR so it becomes easier to see the differences between versions and commit the changes in the end.
According to PHPCS, there still are \Drupal calls in
ConfirmationController.php,SubscriberExportForm.phpandSubscriptionsFormBase.php. I will try to address these tomorrow and commit to the MR.Comment #15
adamps commentedGreat thanks. Even if we miss out a few cases it would still be good progress and worth committing.
Comment #16
marcos_lima commentedThanks for the feedback @AdamPS! I made a commit adding Dependency Injection in
ConfirmationController.phpand in the \Drupal call inSubscriberExportForm.php. Some things I would like to point:1. In
SubscriberExportForm.phpI had some trouble because the entity.query service is deprecated (see entity.query service deprecated in favor of EntityStorageInterface::getQuery() and Deprecate entity.query service and replace with using the entity storage's getQuery() method) and I found that the QueryFactory usually used in its injection was already removed from Drupal 9 (see class QueryFactory).So I changed it in favor of the getStorage() method, as the deprecation notice suggests, which resulted in changing the line:
$query = \Drupal::entityQuery('simplenews_subscriber')To:
$query = $this->entityManager->getStorage('simplenews_subscriber')->getQuery()And the service
entity.querytoentity_type.manager, so I could effectively get the entity query with a injected service.If this is a unwanted change I can reverse it.
2. PHPCS warns about another dependency injection issue in
SubscriberExportForm.php, but it is not from a \Drupal direct call, but from a direct $_GET use:There are several occurrences on this file. Should I address this in this issue too or in a separate issue to keep the scope of this one on \Drupal calls?
3. Corrected a mistake in the String Translation dependency injection in
MailSettingsForm.php.There are still \Drupal calls left in
SubscriptionsFormBase.php, I will address these on Monday.Comment #17
tr commentedA large number of the changes in the MR are wrong.
ControllerBase already has the form builder and config factory services injected - you just need to use those, DON'T inject them again.
Likewise, ConfigFormBase already has the string translation service injected.
NewsletterForm too - at least two of the services you're injecting are already injected in the base EntityForm class.
Between these, that's well over half the patch that's not needed. I didn't review the rest in detail.
Comment #18
adamps commented@marcos_lima Thanks for your progress so far. TR is very thorough on details like this so I would trust him, but he can be a little blunt😃. Please don't be discouraged. It's definitely worth checking if a service is already injected as that's an easy fix.
You don't need to fix every problem. Even if you only fix 50%, it's still good progress. However all the code in your patch would need to be 100% right before we can commit it. So if you are not sure, you can leave something out.
1. It makes sense to me. Although the variable for entity_type.manager would normally be called $entityTypeManager.
2. It's up to you. You would likely need to inject the 'request_stack'. If you search for -
>getCurrentRequest()you can find lots of examples.Comment #19
adamps commentedActually, let's not rush this issue. True, 3.x will soon be beta, and we can't fix it in 3.x after that. However soon 4.x will open, and we can fix it there.
Comment #20
jcnventuraWell, if some of the services are already injected, we can certainly fix those anyway. Also the string translation is probably already there as well. I can also try to take a look at what is actually needed in this patch and simplify it in a way that we can commit it to 3.x, and leave any necessary API changes to 4.x. One simple way to do that in constructors is to have any new service be an optional parameter that is initialized to \Drupal::service('foo) if not provided. And we can already mark the parameter no longer being optional in 4.x..
Comment #21
tr commentedLet me note that injecting services like this is considered by core to be a backwards-compatible change - it's not an API change, so there is no need to defer the patch until the next major issue. It can be added at any point in the development cycle.
For the $_GET super global, I would handle that in a separate issue, since that's not really just a dependency injection issue, it's more of a porting to Drupal 8 issue since the last time $_GET was supposed to be used was Drupal 7.
I would prefer to get the patch fixed up and committed rather than postponed. I will be glad to review and make changes if necessary. I would have just re-rolled the above myself except I was away from my computer for the last several days, and also with the number of changes needed it would have been easier to just write a new patch rather than fix up the MR.
Comment #22
marcos_lima commented@AdamPS Sure, no problem, thanks for the heads up. Some of the injections @TR pointed out I inherited from the patch re-roll I did (such as the NewsletterForm.php ones), but anyway I should have spotted that, so my mistake too, and others I introduced myself. Besides the bluntness at least I learned new things. As per your comment #18.1, true, I changed the variable name to $entityTypeManager, thanks.
Just made a commit. This new commit changed:
And I think that’s the status of all the modified files. Feel free to correct me about those points.
The monitoring module related test continues to fail and I think that’s related to the issue Create a composer.json file.
Maybe the MR is a little cleaner now and I hope that now whoever wants to work on it can continue from there instead of having to make another one from scratch.
Comment #23
adamps commentedGreat thanks @marcos_lima that looks good to me. It would be great to have another review from @TR.
Yes that's true, I have seen that done in core. However it's more work, and so I'd rather avoid it. I would propose either to commit to 3.x now, or create 4.x soon and commit to that.
Comment #24
jcnventuraI find it strange what @TR said in #21 that adding services like this is considered BC-compatible. It clearly is not if someone is extending one of the classes while adding their own constructor which will likely be incompatible with the new one.
In this case the classes we're talking about are 4 forms, 1 block and the confirmation controller. I think that at this point, and with the beta being only 4 days old no one is extending those classes yet. And if they do, it is probably the controller. Of these 6 classes, the patch is adding new constructors to all but the block class. I think the combined risk of someone extending them while at the same time adding a new constructor is so low that I do not see the need to suddenly jump to 4.x. I think a simple warning on the 3.0-beta2 release notes that constructors were added/extended in these classes should be enough. And on that note, once the tests pass I'm OK with RTBCing this.
Comment #25
berdirCore is quite strict on the BC part, you can do it in the same way to be certain, by making the arguments optional and fall back to \Drupal::service() in the constructor, up to us and mostly Adam to decide how much he cares about that. Agreed that it is unlikely to be subclasses like that.
Also, injecting classes that exist on ControllerBase isn't wrong, just not that commonly done. The respective methods are specifically designed to support explicit injection, it is _not_ injected by default, just does a fallback t the service container. See \Drupal\Core\Controller\ControllerBase::entityTypeManager() for example. Also, ControllerBase has a lot more of those than FormBase so many of these really are required.
Comment #26
adamps commentedThanks. I agree with the reasoning in #24 so let's commit it to 3.x.
Comment #27
adamps commentedStrange I can't see any "retest" link for the MR, only for the patches.
Comment #28
marcos_lima commentedIndeed @AdamPS. I think it's a bug that happens sometimes, for me it wasn't showing too. Then I refreshed the page with ctrl+F5 to clear cache and it worked. I ran a retest, let's see.
Comment #29
adamps commentedGreat thanks. I tried to merge and it said "merging failed". Any idea why?
Comment #31
adamps commentedOK it worked after I hard-refreshed the page. Thanks everyone.
Comment #32
adamps commented