Problem/Motivation

\Drupal\Core\StreamWrapper\PrivateStream::basePath() returns NULL which cause deprecations on PHP 8.1 if a test expects it to be set.

Steps to reproduce

Run \Drupal\KernelTests\Core\File\MimeTypeTest on PHP 8.1

Proposed resolution

  • Set file_private_path in MimeTypeTest
  • Fix \Drupal\Core\StreamWrapper\PrivateStream::basePath()

Remaining tasks

User interface changes

None

API changes

None

Data model changes

None

Release notes snippet

N/a

Comments

alexpott created an issue. See original summary.

alexpott’s picture

Status: Active » Needs review
StatusFileSize
new583 bytes
alexpott’s picture

Hmmm... this is not going to work why this is causing a deprecation in PHP 8.1. Need to remove the change in #3220021: [meta] Ensure compatibility of Drupal 9 with PHP 8.1 (as it evolves).

alexpott’s picture

Oh i recorded this in the commit message...
ba0e1aad825 - Fix \Drupal\KernelTests\Core\File\MimeTypeTest (3 months ago) <Alex Pott>
:)

Status: Needs review » Needs work

The last submitted patch, 2: 3239761-2-will-fail.patch, failed testing. View results

alexpott’s picture

alexpott’s picture

Title: \Drupal\Core\StreamWrapper\PrivateStream::basePath() returns NULL if file_private_path not in settings causing deprecations in PHP 8.1 » Fix MimeTypeTest to prevent deprecations in PHP 8.1 and fix \Drupal\Core\StreamWrapper\PrivateStream::basePath() documentation
Issue summary: View changes
Status: Needs work » Needs review
Issue tags: +Documentation
StatusFileSize
new1.5 KB
new1.38 KB

Yep we can fix \Drupal\KernelTests\Core\File\MimeTypeTest instead. Which is good because we rely on \Drupal\Core\StreamWrapper\PrivateStream::basePath() returning NULL in a few places... for example in \Drupal\Core\File\HtaccessWriter::defaultProtectedDirs:

  public function defaultProtectedDirs() {
    $protected_dirs[] = new ProtectedDirectory('Public files directory', 'public://');
    if (PrivateStream::basePath()) {
      $protected_dirs[] = new ProtectedDirectory('Private files directory', 'private://', TRUE);
    }
    $protected_dirs[] = new ProtectedDirectory('Temporary files directory', 'temporary://');
    return $protected_dirs;
  }
andypost’s picture

I think it needs work because \Drupal\Core\StreamWrapper\LocalStream::getDirectoryPath() returns string but it's used in \Drupal\Core\StreamWrapper\PrivateStream::getDirectoryPath() so I think better fix (except mime test) is

return Settings::get('file_private_path', '');
andypost’s picture

All other places will work as expected getting empty string instead of NULL

andypost’s picture

StatusFileSize
new852 bytes
new1.33 KB

Kind of it

alexpott’s picture

StatusFileSize
new1.38 KB

@andypost please read the previous comments and discussion. The fix in #11 was the fix on #3220021: [meta] Ensure compatibility of Drupal 9 with PHP 8.1 (as it evolves) prior to discovering that the ONLY place this deprecation is triggered in core is while running the \Drupal\KernelTests\Core\File\MimeTypeTest. And that's because it incorrectly uses the private stream wrapper without the setting. Fixing like you have in #11 prevents anyone else from receiving the deprecation and then fixing it properly. Going back to #7 which has been proven to fix the deprecation on #3220021: [meta] Ensure compatibility of Drupal 9 with PHP 8.1 (as it evolves) with the recent commits.

andypost’s picture

Yes, I did read, the problem is that \Drupal\Core\StreamWrapper\PrivateStream::getDirectoryPath() needs to be fixed as we expect NULL now

andypost’s picture

StatusFileSize
new479 bytes

I mean

andypost’s picture

Maybe better to split test fix and improvement of interface, I bet we'll get more warnings if we add return type there

alexpott’s picture

@andypost let's open a follow-up. I think getDirectoryPath() should throw an exception if ::basePath() is NULL. The change here is the minimum to get around the exception without changing any return values... ::getDirectoryPath() already returns a NULL in this situation. That's what is happening in HEAD, it's not right and we can improve but it's not necessary to fix the deprecation.

alexpott’s picture

See \Drupal\Core\CoreServiceProvider::register() - we only register the wrapper if this setting is set...

    // Only register the private file stream wrapper if a file path has been set.
    if (Settings::get('file_private_path')) {
      $container->register('stream_wrapper.private', 'Drupal\Core\StreamWrapper\PrivateStream')
        ->addTag('stream_wrapper', ['scheme' => 'private']);
    }
andypost’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new1.67 KB
new1.76 KB

Hmmm actually #17 points to an even better fix. It turns out that in kernel tests the private stream wrapper is being registered by \Drupal\KernelTests\Core\File\FileTestBase::register() - so that test base should properly create a private files directory so that it works as expected.

alexpott’s picture

@andypost thanks for creating the follow-up. Just realised I hadn't asked the question as to what was registering the private stream wrapper - turns out it is \Drupal\KernelTests\Core\File\FileTestBase - so that's where we need to set the setting.

andypost’s picture

Great catch! It should fix 2 usages in contrib as well http://grep.xnddx.ru/search?text=%5CFileTestBase&filename= (link fixed)

andypost’s picture

Status: Needs review » Reviewed & tested by the community

I find this ready

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed 7cc466d and pushed to 9.3.x. Thanks!

  • catch committed 7cc466d on 9.3.x
    Issue #3239761 by alexpott, andypost: Fix MimeTypeTest to prevent...
daffie’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

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