A part of moving legacy code out of file.inc, we should move file_scan_directory() to the file_system service.

CommentFileSizeAuthor
#86 3035312-86-interdiff.txt1.17 KBkim.pepper
#86 3035312-86.patch44.64 KBkim.pepper
#83 3035312-83.patch44.64 KBandypost
#83 interdiff.txt2.23 KBandypost
#80 3035312-80-interdiff.txt1.39 KBkim.pepper
#80 3035312-80.patch44.63 KBkim.pepper
#78 3035312-78-interdiff.txt1.19 KBkim.pepper
#78 3035312-78.patch44.59 KBkim.pepper
#77 interdiff-3035312-70-77.txt738 bytesyogeshmpawar
#77 3035312-77.patch44.87 KByogeshmpawar
#70 3035312-70-interdiff.txt426 byteskim.pepper
#70 3035312-70.patch45.29 KBkim.pepper
#67 3035312-67.patch45.18 KBkim.pepper
#64 3035312-64.patch45.44 KBpguillard
#62 3035312-62-interdiff.txt2.73 KBkim.pepper
#62 3035312-62.patch44.61 KBkim.pepper
#60 3035312-60.patch45.7 KBkim.pepper
#60 3035312-60-interdiff.txt1.02 KBkim.pepper
#58 3035312-58.patch45.59 KBkim.pepper
#58 3035312-58-interdiff.txt2.91 KBkim.pepper
#56 interdiff-3035312-53-54.txt1.26 KBmartin107
#56 3035312-54.patch45.62 KBmartin107
#53 3035312-53.patch45.63 KBkim.pepper
#53 3035312-53-interdiff.txt3.93 KBkim.pepper
#49 3035312-49.patch45.96 KBkim.pepper
#49 3035312-49-interdiff.txt5.93 KBkim.pepper
#47 3035312-47.patch45.26 KBkim.pepper
#47 3035312-47-interdiff.txt1.34 KBkim.pepper
#46 3035312-46.patch45.39 KBkim.pepper
#46 3035312-46-interdiff.txt503 byteskim.pepper
#45 3035312-45.patch45.39 KBkim.pepper
#45 3035312-45-interdiff.txt2.99 KBkim.pepper
#43 3035312-43.patch45.04 KBkim.pepper
#43 3035312-43-interdiff.txt14.42 KBkim.pepper
#38 3035312-38.patch38.64 KBkim.pepper
#38 3035312-38-interdiff.txt2.42 KBkim.pepper
#33 3035312-33.patch39.79 KBkim.pepper
#33 3035312-33-interdiff.txt856 byteskim.pepper
#26 interdiff-3035312-24-26.txt579 bytesnaveenvalecha
#26 3035312-26.patch39.54 KBnaveenvalecha
#24 3035312-24.patch39.43 KBkim.pepper
#24 3035312-24-interdiff.txt3.02 KBkim.pepper
#21 3035312-21.patch39.41 KBkim.pepper
#21 3035312-21-interdiff.txt4.87 KBkim.pepper
#16 3035312-16.patch38.93 KBkim.pepper
#16 3035312-16-interdiff.txt735 byteskim.pepper
#15 3035312-15.patch38.8 KBkim.pepper
#15 3035312-15-interdiff.txt1.46 KBkim.pepper
#14 3035312-14.patch38.02 KBkim.pepper
#14 3035312-14-interdiff.txt5.32 KBkim.pepper
#11 3035312-11.patch34 KBkim.pepper
#11 3035312-11-interdiff.txt2.95 KBkim.pepper
#6 3035312-6.patch33.89 KBkim.pepper

Comments

kim.pepper created an issue. See original summary.

claudiu.cristea’s picture

As it turned out in #1451320: Evaluate Symfony2's Finder Component to simplify file handling, file_scan_directory() is far more better in terms of performance. That we should preserve. But lacks DX. What if we create a component that is using file_scan_directory() implementation but on Finder interface so we’re compatible with the Symfony2 component and at some point, if they are solving their perfomance debt, we can easily drop our code but still keep the contract?

dww’s picture

+1 to trying #2.

kim.pepper’s picture

Currently there are a few of issues we'd need to address:

  1. file_scan_directory() has a dependency on Settings::get('file_scan_ignore_directories', [])
  2. It does some logging \Drupal::logger('file')->error('@dir can not be opened', ['@dir' => $dir]);
  3. The Symfony Finder component returns an Iterator
  4. file_scan_directory() uses recursion, which might complicate things.
kim.pepper’s picture

Given the above #4, I think we should move this to the file_system service instead.

kim.pepper’s picture

Title: Move file_scan_directory() to Finder component » Move file_scan_directory() to file_system service
Status: Active » Needs review
StatusFileSize
new33.89 KB

Here's a patch that moves it to the file_system service.

Status: Needs review » Needs work

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

andypost’s picture

As 8.8 branch is open - not sure what we should have in deprecation message

+++ b/core/lib/Drupal/Core/Asset/CssCollectionOptimizer.php
@@ -196,7 +196,7 @@ public function deleteAll() {
         $this->fileSystem->delete($uri);
...
-    file_scan_directory('public://css', '/.*/', ['callback' => $delete_stale]);
+    \Drupal::service('file_system')->scanDirectory('public://css', '/.*/', ['callback' => $delete_stale]);

+++ b/core/lib/Drupal/Core/Asset/JsCollectionOptimizer.php
@@ -198,7 +198,7 @@ public function deleteAll() {
         $this->fileSystem->delete($uri);
...
-    file_scan_directory('public://js', '/.*/', ['callback' => $delete_stale]);
+    \Drupal::service('file_system')->scanDirectory('public://js', '/.*/', ['callback' => $delete_stale]);

both services has fileSystem already injected

kim.pepper’s picture

@andypost Happy to leave it on 8.7.0 until 11 March?

Also, any suggestions on how to handle FileTranslation? Looks like it's designed as a value object, but depends on a service? Do we inject FileSystem everywhere we see new FileTranslation()? or just convert FileTranslation to a service itself?

andypost’s picture

Looks it should be 8.7 for a while!

+++ b/core/lib/Drupal/Core/File/FileSystem.php
@@ -634,4 +634,82 @@ public function createFilename($basename, $directory) {
+      $dir = file_stream_wrapper_uri_normalize($dir);

I bet we should use the service methods instead, maybe convert it same time?

kim.pepper’s picture

Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new2.95 KB
new34 KB

Thanks @andypost. As discussed in slack, I went with the private function getFileSystem() approach.

Re: #10 there's a separate issue for that. Not clear to me whether this is related or not?

andypost’s picture

Related issues: +#3034072: Move file uri/scheme functions from file.inc and FileSystem to StreamWrapperManager

Related to 10, the problem here is that service should not use function from include which using the service and calls already deprecated stuff

Status: Needs review » Needs work

The last submitted patch, 11: 3035312-11.patch, failed testing. View results

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new5.32 KB
new38.02 KB

Discussed with @andypost in slack, I'd prefer the streamwrapper changes be done in #3034072: Move file uri/scheme functions from file.inc and FileSystem to StreamWrapperManager rather than here.

Fixes a few missing conversions.

kim.pepper’s picture

StatusFileSize
new1.46 KB
new38.8 KB

Agreed with @andypost to wrap calls to file_stream_wrapper_uri_normalize() in a private method.

kim.pepper’s picture

StatusFileSize
new735 bytes
new38.93 KB

Adds links to https://www.drupal.org/node/3034072 in comments.

jibran’s picture

Other then a minor question patch looks great. Thanks for working on it.

+++ b/core/lib/Drupal/Core/StringTranslation/Translator/FileTranslation.php
@@ -117,4 +128,17 @@ public static function filesToArray($langcode, array $files) {
+  private function getFileSystem() {
+    if (!isset($this->fileSystem)) {
+      $this->fileSystem = \Drupal::service('file_system');
+    }
+    return $this->fileSystem;

Why are we doing this here and not in constructor?

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

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

kim.pepper’s picture

@jibran as per #8 and #9 FileTranslation is a value object, not a service, but depends on the file_system service. We are using a lazy loader approach here.

mile23’s picture

Status: Needs review » Needs work
  1. +++ b/core/includes/file.inc
    @@ -968,80 +967,15 @@ function file_unmanaged_save_data($data, $destination = NULL, $replace = FILE_EX
    + * @deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0.
    

    It's 8.8.x now. :-)

  2. +++ b/core/lib/Drupal/Core/File/FileSystem.php
    @@ -634,4 +634,99 @@ public function createFilename($basename, $directory) {
    +   * @todo Remove when https://www.drupal.org/node/3034072 is in.
    

    #3034072: Move file uri/scheme functions from file.inc and FileSystem to StreamWrapperManager still waiting...

  3. +++ b/core/lib/Drupal/Core/StringTranslation/Translator/FileTranslation.php
    @@ -117,4 +128,17 @@ public static function filesToArray($langcode, array $files) {
    +      $this->fileSystem = \Drupal::service('file_system');
    
    +++ b/core/tests/Drupal/KernelTests/Core/File/ScanDirectoryTest.php
    @@ -3,7 +3,7 @@
    + * Tests \Drupal\Core\File\FileSystemInterface::scanDirectory().
    

    Use @coversDefaultClass and/or @covers. Also, it doesn't test the interface.

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new4.87 KB
new39.41 KB

Thanks for the review.

  1. Fixed
  2. Waiting...
  3. Fixed. I wasn't keen on introducing any out of scope changes, but since this test purely tests scanDirectory() I think we are ok here.
mile23’s picture

Status: Needs review » Reviewed & tested by the community

Diggit.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 21: 3035312-21.patch, failed testing. View results

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new3.02 KB
new39.43 KB

Fix incorrect syntax on the covers annotations.

Status: Needs review » Needs work

The last submitted patch, 24: 3035312-24.patch, failed testing. View results

naveenvalecha’s picture

Status: Needs work » Needs review
StatusFileSize
new39.54 KB
new579 bytes

Fixing the test

kim.pepper’s picture

Status: Needs review » Reviewed & tested by the community

As @Mile23 RTBC'd back in #23 I think we're safe to re-RTBC now.

dww’s picture

Mostly looks great, thanks. Don't want to NW over this, but:

+++ b/core/lib/Drupal/Core/StringTranslation/Translator/FileTranslation.php
@@ -22,15 +23,25 @@ class FileTranslation extends StaticTranslation {
-  public function __construct($directory) {
+  public function __construct($directory, FileSystemInterface $file_system = NULL) {
     parent::__construct();
     $this->directory = $directory;
+    $this->fileSystem = $file_system;
   }

@@ -117,4 +128,17 @@ public static function filesToArray($langcode, array $files) {
+    if (!isset($this->fileSystem)) {
+      $this->fileSystem = \Drupal::service('file_system');
+    }

Generally don't we trigger a deprecation warning if the new arg isn't passed and we have to fall back to a default of NULL triggering \Drupal::service()?

I usually see that directly in the constructor, instead of needing the whole private getFileSystem() method.

cilefen’s picture

I don’t know what we gain in general by writing “deprecated in Drupal 8.7.0“ with a specific version (8.7.0). It will be deprecated whenever the deprecation is released, right?

Don’t change this patch because of this! But if anyone agrees with me we should open an issue to discuss.

berdir’s picture

The version number is crucial for contrib, because when you get deprecation messages, you need to know if you can actually act on them. For example, right now, it is too early to change code so it works only on 8.7, but in 6 month, you can add a version dependency on that and update your calls.

Also, it's a coding standard, see #3024461: Adopt consistent deprecation format for core and contrib deprecation messages.

kim.pepper’s picture

Re: #28

I usually see that directly in the constructor, instead of needing the whole private getFileSystem() method.

The reason for the getFileSystem() is to lazily load the file system service. If we do it in the constructor, Symfony dependency injection detects a circular dependency and errors out.

dww’s picture

@kim.pepper re: #31: Ok, makes sense. Thanks for the explanation. However, it seems we still want a deprecation warning, no?

kim.pepper’s picture

StatusFileSize
new856 bytes
new39.79 KB

Re: #32 Adds a @trigger_error to the getFileSystem() method.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 33: 3035312-33.patch, failed testing. View results

andypost’s picture

dww’s picture

Re #33: Thanks and ouch: 1,567 fails... yikes. ;) I haven't tried to look into why this is failing so much. But, seems like a good thing we added the warning, since it's showing us that the patch isn't complete and something getting called frequently hasn't been updated as needed.

berdir’s picture

  1. +++ b/core/lib/Drupal/Core/File/FileSystem.php
    @@ -636,4 +636,99 @@ public function createFilename($basename, $directory) {
    +   * @see https://www.drupal.org/node/3034072
    +   */
    +  private function normalizeUri($uri) {
    +    return file_stream_wrapper_uri_normalize($uri);
    +  }
    

    Why do we need this? Can't we just call the function until it becomes deprecated?

  2. +++ b/core/lib/Drupal/Core/StringTranslation/Translator/FileTranslation.php
    @@ -117,4 +128,18 @@ public static function filesToArray($langcode, array $files) {
    +   */
    +  private function getFileSystem() {
    +    if (!isset($this->fileSystem)) {
    +      @trigger_error('Calling FileTranslation::__construct() without the $file_system argument is deprecated in drupal:8.8.0. The $file_system argument will be required in drupal:9.0.0. See https://www.drupal.org/node/3038437', E_USER_DEPRECATED);
    +      $this->fileSystem = \Drupal::service('file_system');
    +    }
    +    return $this->fileSystem;
    +  }
    

    I don't understand the pattern here. We are we kinda injecting it but then still have a private method and deprecate it in there?

    It has an existing constructor, so why don't we just put the deprecation message in there? Or we say we don't require it, but then we shouldn't deprecate it.

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new2.42 KB
new38.64 KB
  1. Fixed
  2. I was addressing feedback in #32 without really thinking about it. FileTranslation is a special case where it is a value object that gets instantiated for a specific directory, but also calls a service internally. So I think adding a deprecation is wrong in this case, and we should just lazy-load the service as we are doing in #28. I think an optional constructor gives a hint as to the dependency, without specifically requiring it. Open to other options.
claudiu.cristea’s picture

Status: Needs review » Needs work
Issue tags: +@deprecated, +Needs change record updates
  1. +++ b/core/lib/Drupal/Core/File/FileSystemInterface.php
    @@ -462,4 +462,43 @@ public function createFilename($basename, $directory);
    +   * @param int $depth
    +   *   The current depth of recursion. This parameter is only used internally
    +   *   and should not be passed in.
    ...
    +  public function scanDirectory($dir, $mask, array $options = [], $depth = 0);
    

    The interface is a public contract. Parameters that are revealing an implementation detail ($depth) should not be on the public contract. We should remove it and rework the implementation, probably by wrapping a protected helper method: doScanDirectory().

  2. +++ b/core/lib/Drupal/Core/File/FileSystem.php
    @@ -636,4 +636,82 @@ public function createFilename($basename, $directory) {
    +        $this->logger->error('@dir can not be opened', ['@dir' => $dir]);
    

    Log or throw an exception? Have no idea if we can touch this but exception sounds better for me. Then we provide the BC in file_scan_directory() by catching the exception and logging. I think this would needs sub-system maintainer advice.

  3. +++ b/core/lib/Drupal/Core/StringTranslation/Translator/FileTranslation.php
    @@ -22,15 +23,25 @@ class FileTranslation extends StaticTranslation {
    +  public function __construct($directory, FileSystemInterface $file_system = NULL) {
    ...
    +    $this->fileSystem = $file_system;
    
    @@ -117,4 +128,17 @@ public static function filesToArray($langcode, array $files) {
    +  /**
    +   * Returns file system service.
    +   *
    +   * @return \Drupal\Core\File\FileSystemInterface
    +   *   The file system service.
    +   */
    +  private function getFileSystem() {
    +    if (!isset($this->fileSystem)) {
    +      $this->fileSystem = \Drupal::service('file_system');
    +    }
    +    return $this->fileSystem;
    +  }
    

    In see the BC is supported in signature but we have also to raise the red flag, i.e @trigger_error(). #37.2 was correct. We should drop the method and add the deprecation in the constructor, as usual.

  4. The deprecated function is still mentioned in a docblock, in default.settings.php
  5. The CR branch needs to be updated to 8.8.x.
claudiu.cristea’s picture

More...

+++ b/core/lib/Drupal/Core/File/FileSystem.php
@@ -636,4 +636,82 @@ public function createFilename($basename, $directory) {
+    if (is_dir($dir)) {

So... this is also weird and for sure it's a bug. If the directory doesn't exist or $dir points to a file, rather than a directory, the method will still return an empty array ([]), same as in the case when is scanning an existing, empty directory. This is misleading. I think we have to throw an exception. Some could argue that this is off-topic and should be moved to a followup. But as this is a new service method, I think we should fix it here.

dww’s picture

Re: #39.3 and #37.2: I raised this is in #28. See @kim.pepper's answer in #31:

The reason for the getFileSystem() is to lazily load the file system service. If we do it in the constructor, Symfony dependency injection detects a circular dependency and errors out.

Not sure I totally buy it, but that's the story.

berdir’s picture

> FileTranslation is a special case where it is a value object that gets instantiated for a specific directory, but also calls a service internally.

I don't think it's really a value object, it *is* service, but it's only dynamically registered in install_begin_request() for example. I think it would be possible to inject the file_system there. But I'm also open to try that in a follow-up issue.

kim.pepper’s picture

Status: Needs work » Needs review
Issue tags: -Needs change record updates
StatusFileSize
new14.42 KB
new45.04 KB

Thanks for all your reviews!

Re: #39

  1. Great idea. Fixed.
  2. This would break current functionality. As we are using recursion, it's possible to scan a directory tree, and hit a sub-directory you don't have permission to scan, log an error, but continue with other directories, and return the files that were able to be scanned.
  3. also #41 and #42 OK. I concede defeat on this one. I've added the constructor @trigger error and replaced usages.
  4. Fixed
  5. Fixed

Re: #40

I added a check for is_dir and created and throw a new NotRegularDirectoryException now. I've updated file_scan_directory() to catch this and return an empty array for BC.

kim.pepper’s picture

Status: Needs review » Needs work

Seems that the check for is_dir() is being relied on in a load of places throughout core. We can either:

  1. Put an is_dir() check where ever we call scanDirectory()
  2. Wrap scanDirectory() in a try/catch and ignore the exception

Any preference?

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new2.99 KB
new45.39 KB

I added a couple of is_dir() checks to see how broken things are.

kim.pepper’s picture

StatusFileSize
new503 bytes
new45.39 KB

Typo.

kim.pepper’s picture

StatusFileSize
new1.34 KB
new45.26 KB

OK. Still getting lots of fails. See if this helps.

Status: Needs review » Needs work

The last submitted patch, 47: 3035312-47.patch, failed testing. View results

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new5.93 KB
new45.96 KB

Fix test fails in #47

martin107’s picture

Status: Needs review » Needs work

After a visual scan of the patch ... this looks like a good improvement.

a) The drive behind the issue is sound.
b) The implementation is good.

I have only a minor thing

The Drupal standard as encoded in phpcs now places a tight restraint on the text format of deprecation text.

drupal:8.7.0 (without capitalization ) is the main change needed. Here is a single example of the warnings generated by the patch.

507 | ERROR | [ ] The deprecation text '@deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0. Use
| | \Drupal\Core\File\FileSystemInterface::getDestinationFilename() instead.' does not match the standard
| | format: @deprecated in %in-version% and will be removed from %removal-version%. %extra-info%.

berdir’s picture

drupal:version is IMHO fine, I think the problem with the message is before => from.

claudiu.cristea’s picture

  1. +++ b/core/lib/Drupal/Core/File/FileSystem.php
    @@ -636,4 +637,120 @@ public function createFilename($basename, $directory) {
    +    // Merge in defaults.
    +    $options += [
    +      'callback' => 0,
    +      'recurse' => TRUE,
    +      'key' => 'uri',
    +      'min_depth' => 0,
    +    ];
    ...
    +    $options['key'] = in_array($options['key'], ['uri', 'filename', 'name']) ? $options['key'] : 'uri';
    

    It doesn't make sense to merge defaults and normalize $options['key'] on each recursion. We can move them in the main public method so that they run only once.

  2. +++ b/core/lib/Drupal/Core/File/FileSystem.php
    @@ -636,4 +637,120 @@ public function createFilename($basename, $directory) {
    +    if ($depth == 0) {
    +      $dir = file_stream_wrapper_uri_normalize($dir);
    +      $dir_has_slash = (substr($dir, -1) === '/');
    +    }
    

    This also can be moved in the public method to run only once. I'm also confused about the logic related to $dir_has_slash. Why do we need that? Wouldn't it be more simple to remove the trailing slash once (also in the main method) and drop the if(), few lines below: if ($depth == 0 && $dir_has_slash) {...? Or I'm missing something.

  3. +++ b/core/lib/Drupal/Core/File/FileSystem.php
    @@ -636,4 +637,120 @@ public function createFilename($basename, $directory) {
    +    // Allow directories specified in settings.php to be ignored. You can use
    +    // this to not check for files in common special-purpose directories. For
    +    // example, node_modules and bower_components. Ignoring irrelevant
    +    // directories is a performance boost.
    +    if (!isset($options['nomask'])) {
    +      $ignore_directories = Settings::get('file_scan_ignore_directories', []);
    +      array_walk($ignore_directories, function (&$value) {
    +        $value = preg_quote($value, '/');
    +      });
    +      $default_nomask = '/^' . implode('|', $ignore_directories) . '$/';
    +    }
    

    This also looks like a part that should run only once. It seems that on every recursion the result of $default_nomaks is the same. It doesn't depend on the recursion depth. We can move it in the main method and pass it to the protected method, or add it as a new entry in $options, as 'default_nomaks'.

  4. +++ b/core/lib/Drupal/Core/File/FileSystem.php
    @@ -636,4 +637,120 @@ public function createFilename($basename, $directory) {
    +    // Avoid warnings when opendir does not have the permissions to open a
    +    // directory.
    +    if (!is_dir($dir)) {
    +      throw new NotRegularDirectoryException("$dir is not a directory.");
    +    }
    

    This check is also needed only for the top directory because the subsequent directories are checked again with is_dir()few lines below: if ($options['recurse'] && is_dir($uri)) {. That means every sub-dir is checked twice. We can move it in the main method.

  5. +++ b/core/lib/Drupal/Core/File/FileSystem.php
    @@ -636,4 +637,120 @@ public function createFilename($basename, $directory) {
    +          if ($depth == 0 && $dir_has_slash) {
    +            $uri = "$dir$filename";
    +          }
    

    If the trim of trailing slash works (see above), we can drop this.

kim.pepper’s picture

StatusFileSize
new3.93 KB
new45.63 KB

Thanks @claudiu.cristea for a great review as always.

  1. Fixed
  2. Fixed. I just used rtrim() I assume this will be ok.
  3. Fixed. I just used $options['nomask'] as it only gets set if there is no value passed in.
  4. Fixed. I also moved the next line $options['key'] = in_array($options['key'], ['uri', 'filename', 'name']) ? $options['key'] : 'uri'; to the parent method.
  5. Fixed

Re: #50 @martin107 the deprecation messages on file_destination() and file_unmanaged_prepare() aren't in this patch??

kim.pepper’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 53: 3035312-53.patch, failed testing. View results

martin107’s picture

Status: Needs work » Needs review
StatusFileSize
new45.62 KB
new1.26 KB

Re: #50 @martin107 the deprecation messages on file_destination() and file_unmanaged_prepare() aren't in this patch??

@kim.pepper - Sorry I did not mean to give you grief.

As I visually scanned the patch, my brain flagged the imperfections that phpcs would spot and then I blindly reported the stuff incorrectly.

by way of getting right with the universe .. here is the change.

   987 | ERROR   | [ ] The deprecation text '@deprecated in Drupal 8.8.0 and will be removed before Drupal 9.0.0. Use
       |         |     \Drupal\Core\File\FileSystemInterface::scanDirectory() instead.' does not match the standard format:
       |         |     @deprecated in %in-version% and will be removed from %removal-version%. %extra-info%.
   993 | WARNING | [ ] The deprecation version 'Drupal 8.8.0 and will be removed before Drupal 9.0.0' does not match the
       |         |     standard: drupal:n.n.n or project:n.x-n.n
   993 | WARNING | [ ] The 'See' url 'https://www.drupal.org/node/3038437.' should not end with a period. 

Status: Needs review » Needs work

The last submitted patch, 56: 3035312-54.patch, failed testing. View results

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new2.91 KB
new45.59 KB

Sorry I did not mean to give you grief

No grief taken. :-) I was just a bit confused that's all. I usually run phpcs across changed files before posting patches, and I guess this wasn't picked up.

Re #52.2 Looks like rtrim is too aggressive. I've removed it altogether to see what breaks.

Status: Needs review » Needs work

The last submitted patch, 58: 3035312-58.patch, failed testing. View results

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new1.02 KB
new45.7 KB

We still need to check if the path ends with a slash when creating the URI.

jibran’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Core/File/FileSystem.php
    @@ -636,4 +637,110 @@ public function createFilename($basename, $directory) {
    +      throw new NotRegularDirectoryException("$dir is not a directory.");
    
    +++ b/core/lib/Drupal/Core/File/FileSystemInterface.php
    @@ -462,4 +462,43 @@ public function createFilename($basename, $directory);
    +   * @throws \Drupal\Core\File\Exception\FileException
    +   *   Implementation may throw FileException or its subtype on failure.
    

    These are not the same. I don't know we can document parent exception like that.

  2. +++ b/core/lib/Drupal/Core/File/FileSystem.php
    @@ -636,4 +637,110 @@ public function createFilename($basename, $directory) {
    +   * @throws \Drupal\Core\File\Exception\FileException
    +   *   Implementation may throw FileException or its subtype on failure.
    

    This not thrown anywhere in this function. Am I missing something?

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new44.61 KB
new2.73 KB

Fixes for #61 to specify the exact exception.

Also removed duplicate docblock comments in doScanDirectory() to refer to scanDirectory().

Status: Needs review » Needs work

The last submitted patch, 62: 3035312-62.patch, failed testing. View results

pguillard’s picture

Status: Needs work » Needs review
Issue tags: +@DevDaysTransylvania
StatusFileSize
new45.44 KB

Here is a a rerolled-patch

pguillard’s picture

Issue tags: -@DevDaysTransylvania +DevDaysTransylvania

Status: Needs review » Needs work

The last submitted patch, 64: 3035312-64.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new45.18 KB

I couldn't work out what changed in #64 so I re-rolled #62 again.

kim.pepper’s picture

Looks like we needed to convert a usage of file_stream_wrapper_uri_normalize().

Status: Needs review » Needs work

The last submitted patch, 67: 3035312-67.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new45.29 KB
new426 bytes

Fixed a missing import in install.inc

darrenwh’s picture

Hiding old patches

darrenwh’s picture

darrenwh’s picture

Status: Needs review » Needs work
+++ b/core/includes/install.inc
@@ -166,9 +166,11 @@ function drupal_get_database_types() {
diff --git a/core/includes/theme.inc b/core/includes/theme.inc

+++ b/core/lib/Drupal/Core/Asset/CssCollectionOptimizer.php
--- a/core/lib/Drupal/Core/Asset/JsCollectionOptimizer.php
+++ b/core/lib/Drupal/Core/Asset/JsCollectionOptimizer.php

+++ b/core/lib/Drupal/Core/Asset/JsCollectionOptimizer.php
@@ -198,7 +198,9 @@ public function deleteAll() {
+      $this->fileSystem->scanDirectory('public://js', '/.*/', ['callback' => $delete_stale]);

This method call (scanDirectory) throws an exception, should it be caught here and in all other cases where it's called?

kim.pepper’s picture

Why should it catch the exception in all places it is used?

kim.pepper’s picture

Status: Needs work » Needs review

In drupal_get_database_types() we are scanning core/lib/Drupal/Core/Database/Driver which we know exists, and checking if the directory exists for drivers/lib/Drupal/Driver/Database, so it's not needed.

In CssCollectionOptimizer and JsCollectionOptimizer we are checking if the directory exists before scanning. So again, it's not needed.

Putting back to Needs Review for other reviewers.

yogeshmpawar’s picture

Assigned: Unassigned » yogeshmpawar
yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
StatusFileSize
new44.87 KB
new738 bytes

Resolved one coding standard issue & added an interdiff as well.

kim.pepper’s picture

StatusFileSize
new44.59 KB
new1.19 KB

Fixes missing import, and removes git merge cruft.

berdir’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/image/tests/src/Functional/ImageAdminStylesTest.php
    @@ -44,7 +44,11 @@ public function createSampleImage(ImageStyleInterface $style) {
    +    $count = 0;
    +    if (is_dir('public://styles/' . $style->id())) {
    +      $count = count(\Drupal::service('file_system')->scanDirectory('public://styles/' . $style->id(), '/.*/'));
    +    }
    

    I'm not *completely* convinced that requiring a valid directory is a good thing, results in a ton of extra checks.

  2. +++ b/core/modules/system/tests/src/Kernel/Installer/InstallTranslationFilePatternTest.php
    @@ -1,16 +1,18 @@
    +
    +  protected static $modules = ['system'];
     
    

    this needs a docblock.

  3. +++ b/core/scripts/run-tests.sh
    --- a/core/tests/Drupal/KernelTests/Core/File/FileSystemDeprecationTest.php
    +++ b/core/tests/Drupal/KernelTests/Core/File/FileSystemDeprecationTest.php
    
    +++ b/core/tests/Drupal/KernelTests/Core/File/FileSystemDeprecationTest.php
    @@ -252,4 +252,11 @@ public function providerTestUriScheme() {
    +  public function testDepreactedScanDirectory() {
    +    $this->assertNotNull(file_scan_directory('temporary://', '/^NONEXISTINGFILENAME/'));
    +  }
    

    Depreacated :)

kim.pepper’s picture

Status: Needs work » Needs review
Issue tags: +Needs framework manager review
StatusFileSize
new44.63 KB
new1.39 KB
  1. Yeah, not sure either. Would be good to get an opinion of a framework manager.
  2. Fixed
  3. Fixed
berdir’s picture

Status: Needs review » Reviewed & tested by the community

1. Yes, lets see if we can get feedback on that, RTBC otherwise IMHO, splitting the method into a public API and the internal one for the recursion looks much cleaner.

kim.pepper’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll
andypost’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new2.23 KB
new44.64 KB

Reroll and fix message according current core sniffers

kim.pepper’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC

catch’s picture

Status: Reviewed & tested by the community » Needs work

One minor point, otherwise looks good:

+++ b/core/lib/Drupal/Core/File/FileSystem.php
@@ -625,4 +626,97 @@ public function createFilename($basename, $directory) {
+    // directories is a performance boost.
+    if (!isset($options['nomask'])) {
+      $ignore_directories = $this->settings->get('file_scan_ignore_directories', []);
+      array_walk($ignore_directories, function (&$value) {
+        $value = preg_quote($value, '/');
+      });
+      $options['nomask'] = '/^' . implode('|', $ignore_directories) . '$/';
+    }
+    if (!is_dir($dir)) {
+      throw new NotRegularDirectoryException("$dir is not a directory.");
+    }

The is_dir() check seems like it should come before the nomask, otherwise we're building up $options['nomask'] for no reason.

kim.pepper’s picture

Status: Needs work » Needs review
StatusFileSize
new44.64 KB
new1.17 KB

Fixes #85

darrenwh’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/File/FileSystem.php
@@ -625,4 +626,97 @@ public function createFilename($basename, $directory) {
+      throw new NotRegularDirectoryException("$dir is not a directory.");

Should this be a InvalidArgumentException?

https://www.php.net/manual/en/class.invalidargumentexception.php

kim.pepper’s picture

Re: #87 no, we have a more specific exception we can throw.

kim.pepper’s picture

Status: Needs work » Reviewed & tested by the community

Going to change this back to RTBC to get feedback from @catch

  • catch committed dd90789 on 8.8.x
    Issue #3035312 by kim.pepper, andypost, martin107, yogeshmpawar,...
catch’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs framework manager review

Committed dd90789 and pushed to 8.8.x. Thanks!

Status: Fixed » Closed (fixed)

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