Problem/Motivation
If the source image is passed as a stream wrapper, ImageStyle::buildUri() creates the destination on the same stream wrapper. This is fine for public:// and private:// and even for any writable custom stream wrapper. But when it comes to build a derivative from a read-only stream wrapper, Drupal cannot write there because it's simply... READONLY. The attached test proves this bug.
This is somehow related to #987846: Switching file storage to anything other than public/private breaks image styles but is not the same in the sense that D8 allows creation of derivatives from sources passed as stream wrappers but will fail to create the files on read-only wrappers.
Proposed resolution
When the source image is passed as a read-only stream wrapper, set the derivative scheme to \Drupal::config('system.file')->get('default_scheme'). Potentially back-port to D7.
Remaining tasks
None.
User interface changes
None.
API changes
None.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #12 | interdiff.txt | 5.49 KB | claudiu.cristea |
| #12 | 2770761-12.patch | 8.09 KB | claudiu.cristea |
| image_style_streamwrappers-test-only.patch | 5.2 KB | claudiu.cristea |
Comments
Comment #2
claudiu.cristeaTitle, IS, etc.
Comment #4
claudiu.cristeaAnd the patch.
Comment #5
claudiu.cristeaComment #6
claudiu.cristeaComment #7
mondrakeGood catch, @claudiu.cristea
can we keep this test wrapper writeable, please? I'm using this wrapper in contrib tests to write too and this would break them. How about a separate
DummyRemoteReadOnlyStreamWrapper.I think the todo needs to go above in the method's docblock.
Other than that looks good.
Comment #9
claudiu.cristeaThank you, @mondrake,
Sure.
Comment #10
claudiu.cristeaComment #11
mondrakeI know it's a test only wrapper, but still shouldn't we implement also
::getNameand::getDescription?I would suggest: "The scheme of derivative image files only needs to be computed for source files not stored in the default scheme."
I think we want "URI" uppercase in docs.
wouldn't it be better to have in the dataProvider
the file name is not really involved in the calculation. This way we can avoid recalculating the target scheme in test code and just check what prod code returns.
Side note, going back to #7 for a moment, I noticed that
DummyRemoteStreamWrapperextends PublicStream. This means thatDummyRemoteStreamWrapperinheritsStreamWrapperInterface::LOCAL_NORMALtype which is probably wrong as it has the local flag set on. I think we should have NORMAL or WRITE_VISIBLE there. But that's for a separate issue?Comment #12
claudiu.cristea@mondrake, thank you for review. Good points!
I fixed all from #11.
I noticed that too. First I was tempted to create a test wrapper by not extending PublicStream, so directly from StreamWrapperInterface. That would have been the 100% correct approach. But, believe me, that is horror because you'll need to implement dozens of methods. Yes, this will be subject for other issues. I think all wrappers need a base class that implements StreamWrapperInterface and most of the methods.
Comment #13
claudiu.cristeaComment #14
mondrakeLooks good to me, thanks
Comment #15
claudiu.cristea@mondrake, thank you. Here's one related and more juicy #2774449: Edge case image derivative URIs collision :)
Comment #16
xjmBased on the title and the patch, I think this fix is probably best targeted against a minor version.
Comment #17
alexpottThis makes this change only eligible for 8.2.x. I think this could be backported without this method and just using
\Drupal::service('stream_wrapper_manager');if we feel it is worth it. It probably is not.Comment #18
alexpottCommitted f18da3e and pushed to 8.2.x. Thanks!
The new backport policy says that a new Drupal 7 issue should be created. One it exists please mark this one as fixed.
Fixed on commit. Unused use.
Comment #23
mondrakeOpened #2791283: Derivatives should not be created on read-only stream wrappers [D7 backport], closing this one.