Problem/Motivation

While working on #2620304-19: htaccess functions should be a service discovered

The FileStorage using deprecated functions drupal_chmod(), drupal_unlink, drupal_rmdir all of them are wrappers to file_system service.
The FileStorage created statically in core so no way to use container injection

Proposed resolution

Add private$fileSystem property to minimize calls to \Drupal::service() & getFileSystem() method to proxy to service because there's no way to inject without causing circular dependency in logger (see #10) and discussion in #22

Remaining tasks

accept, commit

User interface changes

API changes

Data model changes

Comments

andypost created an issue. See original summary.

andypost’s picture

Issue summary: View changes
Status: Active » Needs review
StatusFileSize
new1.9 KB

Kinda of that

andypost’s picture

Issue tags: +KharkivGSW18
borisson_’s picture

Status: Needs review » Reviewed & tested by the community

Looks great! Only those deprecated methods are used in that file, so that means this is RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

This is not injecting the service. If we want to do that then we need to do quite a bit more work to add it to the constructor of FileStorage and InstallStorage and ExtensionInstallStorage.

As these classes are used everywhere the default should be NULL but we should automatically deprecate this and mandate it in Drupal 9.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new4.13 KB
new4.38 KB

Patch adds constructor argument & clean-up code
All this storage classes are used to be created manually so not clear how to keep BC, that's why I did add \Drupal::service('file_system') as workaround

If this change needs to trigger error then it needs change record

andypost’s picture

StatusFileSize
new681 bytes
new4.38 KB

Proper patch

The last submitted patch, 6: 2940135-6.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 7: 2940135-7.patch, failed testing. View results

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new3.03 KB
new5.48 KB

Revert removal of constructor & added injection to ExtensionInstallStorage

Status: Needs review » Needs work

The last submitted patch, 10: 2940135-10.patch, failed testing. View results

andypost’s picture

Injection at install time creates circular dependency so looks #2 was right way

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

berdir’s picture

Status: Needs work » Needs review
StatusFileSize
new3.22 KB
new1.88 KB

Yes, injecting through the constructor is not an option. What if we just add a setter method so if someone really wants to do unit tests, he can, similar to string translation trait, messenger and so on. That said, not quite sure how you'd do unit tests of this anyway, because it clearly is very file/storage related, you can't mock the remaining low-level php functions and so on anyway.

There are almost 40 variants of new FileStorage() in core, so updating them all would be a ton of work, which is why I didn't deprecate not passing one in.

Interdiff is against #2.

andypost’s picture

Status: Needs review » Reviewed & tested by the community

Awesome idea, looks good to go

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 14: 2940135-14.patch, failed testing. View results

andypost’s picture

Status: Needs work » Reviewed & tested by the community

bot flux

voleger’s picture

voleger’s picture

+1 for rtbc

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
+++ b/core/core.services.yml
@@ -321,6 +321,8 @@ services:
     factory: Drupal\Core\Config\FileStorageFactory::getSync
+    calls:
+      - [setFileSystem, ['@file_system']]

How about making the factory container aware, using \Drupal\Core\DependencyInjection\ContainerInjectionInterface, and then injecting the service via constructor injection? Yes we'd then have to do more work with the other storages but we'd achieve the aims of having the file system service injected everywhere.

andypost’s picture

Assigned: Unassigned » andypost

@alexpott i gonna explore this way, the real problem here is that FileStorage and derivatives created directly (not using service - 32 times at least)

berdir’s picture

Status: Needs review » Needs work

I discussed this a bit with alexpott in slack:

berdir: there are 2 problems
alexpott: Only 2?
berdir: I'm grouping them together
berdir: a) FileStorage has 4 subclasses, 30+ versions of new FileStorage() all over the place and optional constructor arguments (the collection)
berdir: that's all solvable, but it is a *lot* of work
berdir: \Drupal\Core\Config\ConfigInstaller alone creates file storage objects in 5 places
berdir: which means we'd also need to inject it through those places, so inject into ConfigInstaller, so that it i can inject it further. And the optional constructor argument makes it all a bit awkward IMHO
alexpott: Yeah well I guess this makes me ponder why we’re borthering (edited)
berdir: and ExtensionInstallStorage has 5 optional arguments
berdir: b) is that we end up in a circular reference if we try to do that. See test fails in #10: Circular reference detected for service "config.factory", path: "language_request_subscriber -> language_manager -> config.factory -> config.typed -> config.storage.schema -> file_system -> logger.channel.file -> logger.factory -> logger.syslog".
alexpott: Nice
alexpott: We really should never be injecting loggers… they should be listening to events - but that’s a separate issue.
alexpott: Is there a burning reason why we don’t convert the calls to \Drupal::service() - yes it is ugly - but in reality this is what is happening anyway
berdir: yeah, in case of FileSystem, we also discussed if it shouldn't log bug only throw exceptions, leaving the logging to the parent.. which would allow more useful log messages than the ones we currently have _if_ those implementations would bother to do that, and I'm sure most wouldn't.. :wink:
berdir: I don't think there is a burning reason, FileStorage isn't very unit-testable anyway, as it has a lot of direct IO calls itself too
berdir: if you're OK with that then I'm too. I modeled this after things like StringTranslationTrait, which allows optional injection. but as I said, we're most likely not going to write unit tests for this thing any time soon
alexpott: I think we should admit the awfulness of \Drupal::service() and move on.
berdir: not even hidden behind a getFileSystem() method? there are 4 or 5 calls to its methods
alexpott: It could be - but it should be private so if we ever get to injection we can remove it without thinking too hard
berdir: sounds good

So..
* Change the method to private, remove setFileSystem(), just do return \Drupal::service()
* update the issue title/summary to reflect that we don't inject but just use the serice

andypost’s picture

Assigned: andypost » Unassigned
Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new1.57 KB
new2.51 KB

Fixed IS and addressed suggestion

andypost’s picture

StatusFileSize
new2.51 KB

reupload patch

andypost’s picture

alexpott’s picture

+++ b/core/lib/Drupal/Core/Config/FileStorage.php
@@ -33,6 +33,13 @@ class FileStorage implements StorageInterface {
+  /**
+   * The file system.
+   *
+   * @var \Drupal\Core\File\FileSystemInterface
+   */
+  private $fileSystem;

I'm not sure that the property is worth it.

andypost’s picture

StatusFileSize
new843 bytes
new2.16 KB

@alexpott ensureStorage() and chmod() could be called from write() subsequently but only once and that rare case so removed

berdir’s picture

Title: Inject file_system service to \Drupal\Core\Config\FileStorage » Use file_system service to \Drupal\Core\Config\FileStorage
Status: Needs review » Reviewed & tested by the community

Lets do this so we can finalize the deprecation of those functions.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

I pushed the deprecation patch first because it's doing something more important - this needs a reroll.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new2.21 KB

reroll

berdir’s picture

Status: Needs review » Reviewed & tested by the community

And back to RTBC.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 30: 2940135-30.patch, failed testing. View results

Mixologic’s picture

Status: Needs work » Reviewed & tested by the community

dispatcher/testbot issue. back to rtbc

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 2348afa46a to 8.8.x and 321bbf9658 to 8.7.x. Thanks!

  • alexpott committed 2348afa on 8.8.x
    Issue #2940135 by andypost, Berdir, alexpott: Use file_system service to...

  • alexpott committed 321bbf9 on 8.7.x
    Issue #2940135 by andypost, Berdir, alexpott: Use file_system service to...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.