Updated: Comment #44
Problem/Motivation
Right now:
- Modules cannot provide different stream wrappers for different image styles of the same original. Derivatives are always inheriting the original stream wrapper.
- There's no point where modules can define a custom path for creation and retrieving derivatives. As an effect we have to stick to the actual derivative location hardcoded strategy making impossible to keep derivatives elsewhere in the filesystem or even outside Drupal, on a remote system (
flickr://
????). - Modules cannot grant different permissions on different image styles of the same original. Same as for stream wrappers, many use cases may want different permissions for different styles.
Use case: A website that sells big digital posters want to keep the original big images in the private://
stream wrapper only for users who bought that image but also wants to provide low resolution, small, watermarked derivative in the public://
stream. A medium style should also be provided for all registered users in private://
. To summarize:
Image style | URI | Permissions |
---|---|---|
[original] | private://system/files/image.jpg |
owner only |
medium | private://system/files/styles/medium/private/image.jpg |
authenticated user |
small | public://styles/small/public/image.jpg |
whole Internet |
Proposed resolution
Let contrib modules extend \Drupal\image\Plugin\Core\Entity\ImageStyle
and provide flexibility on image derivative creation and retrieving by:
- Defining
image_style_deliver()
,image_style_create_derivative()
,image_style_flush()
,image_style_url()
,image_style_path()
(and others) as methods of interface\Drupal\image\ImageStyleInterface
. - Moving their functionality in corresponding
\Drupal\image\Plugin\Core\Entity\ImageStyle
method implementations by providing the actual behavior.
Proposed conversions (not definitive):
Procedural | \Drupal\image\ImageStyleInterface | \Drupal\image\Plugin\Core\Entity\ImageStyle |
---|---|---|
image_style_deliver() |
->deliver() |
|
image_style_flush() |
->flush() |
|
N/A | ->flushImage() |
|
image_style_url() |
->url() |
|
image_style_path() |
->path() |
|
image_style_create_derivative() |
->createDerivative() |
|
image_style_transform_dimensions() |
->transformDimensions() |
|
image_style_path_token() |
N/A | ->getPathToken() |
Remaining tasks
Add a patch soon.- Change notice.
Change the legacy D7 menu routes for private and public image derivatives into Symfony dynamic route for. Fixed in #1987712: Convert file_download() to a new style controller.public://
and YAML definition forprivate://
- Followup: #2029649: Move entity_load('image_style', ...) in preprocess, #1898420: image.module - Convert theme_ functions to Twig.
- Followup: Add tests for
->deliver()
method.
User interface changes
No changes in UI.
API changes
- Modules will have now the opportunity to intercept the derivative creation and place each derivative in custom locations, under custom streams by extending
\Drupal\image\Plugin\Core\Entity\ImageStyle
or directly implementing\Drupal\image\ImageStyleInterface
interface. - By implementing their own
->deliver()
method, modules will be able to control permissions on derivatives and give different permissions on different styles.
Related Issues
- #1744136: Consistent and flexible derivative access check
- #987846: Switching file storage to anything other than public/private breaks image styles
- #1987712: Convert file_download() to a new style controller
- #2029649: Move entity_load('image_style', ...) in preprocess
- #1898420: image.module - Convert theme_ functions to Twig
- #1821854: Convert image effects into plugins
- #2033669: Image file objects should be classed
- #1788542: Use EntityFormController and EntityListController for image styles
- #1358896: Flexible scheme and URI for image derivatives
- #1821166: Support image style derivatives using a different file scheme than the original image
- #1372736: Improve image styles handling for external FileStreamWrappers
- #1903190: Allow image style derivatives of private images to be stored on the public file system
Original report by [username]
N/A
Comment | File | Size | Author |
---|---|---|---|
#53 | image-2027423-53.patch | 60.07 KB | claudiu.cristea |
#53 | interdiff.txt | 2.91 KB | claudiu.cristea |
#50 | image-2027423-50.patch | 58.67 KB | tim.plunkett |
#50 | interdiff.txt | 2.18 KB | tim.plunkett |
#50 | interdiff-from-RTBC.txt | 12.51 KB | tim.plunkett |
Comments
Comment #0.0
claudiu.cristeaUpdated issue summary.
Comment #0.1
claudiu.cristeaUpdated issue summary.
Comment #0.2
claudiu.cristeaUpdated issue summary.
Comment #0.3
claudiu.cristeaUpdated issue summary.
Comment #0.4
claudiu.cristeaUpdated issue summary.
Comment #1
claudiu.cristeaAdded #1821854: Convert image effects into plugins as related issue.
Comment #1.0
claudiu.cristeaUpdated issue summary.
Comment #2
claudiu.cristeaHere's first patch.
Comment #3
claudiu.cristeaRemoved line end whitespaces.
Comment #4
claudiu.cristeaRelated #1788542: Use EntityFormController and EntityListController for image styles.
Comment #4.0
claudiu.cristeaUpdated issue summary.
Comment #4.1
claudiu.cristeaUpdated issue summary.
Comment #4.2
claudiu.cristeaAdded related item.
Comment #4.3
claudiu.cristeaUpdated issue summary.
Comment #4.4
claudiu.cristeaUpdated issue summary.
Comment #4.5
claudiu.cristeaUpdated issue summary.
Comment #4.6
claudiu.cristeaUpdated issue summary.
Comment #4.7
claudiu.cristeaUpdated issue summary.
Comment #5
claudiu.cristeaAdded related issues to issue summary:
Comment #6
claudiu.cristeaThis is duplicated by:
Comment #7
dman CreditAttribution: dman commentedNice initiative. I've fielded support requests for this for a few years.
I'll see if I can find time to trial it. Takes a bit to set up the manual test case ...
Comment #8
claudiu.cristeaThanks @dman! Note that this is only a step to open the image style system to modules. Any alteration of image styles scheme, path or permissions should be handled by future contrib modules.
Comment #9
dman CreditAttribution: dman commentedIt was in my queue at #1863720: Image styles needs selectable file system path that led to the very-well-stated feature request #1903190: Allow image style derivatives of private images to be stored on the public file system that deserves a name-check here - potatosauce did a fine job of helping us improve the system. ... since we are dropping related links into this thread :-)
Comment #9.0
dman CreditAttribution: dman commentedUpdated issue summary.
Comment #9.1
claudiu.cristeaUpdated issue summary.
Comment #9.2
claudiu.cristeaUpdated issue summary.
Comment #10
claudiu.cristeaThanks @dman for the link. I added #1903190: Allow image style derivatives of private images to be stored on the public file system to related issues but also mark it as duplicate while here there's already a testable patch and we have aggregated all related issues to get the "whole picture".
Comment #10.0
claudiu.cristeaAdded #987846.
Comment #11
andypostLet's mark this @deprecated with link to new implementation
awesomeness++ this requires controller and follow up issue # for unittests
getUri() and getUrl() or maybe buildURI() and buildURL()
file|image -> flashMedia()
Also I think better to merge this into one method
flush($uri = NULL) seems better
this is a file uri or url?
same time $destination is URI
This needs explanation, implementation of this method have to provide at least:
- width
- height
path() makes no sense, also why not use file-object itself?
createDerivate() operating on urls? so what about access checking comment!
disagree on that, getUrl() proper name that does not have collision with entity method
$node->get($field_name)->value probably now
Yay!
this entity_load() scares me :) let's make follow-up to move this to preprocess
Comment #12
potatosauce CreditAttribution: potatosauce commentedGreat!
I'm now following this thread too. I was building an image gallery site in late 2012, and I just couldn't get things going on certain way, what is obviously getting here more attention.
If it helps anything, you should read the descriptions (and comments) in 1863720 and 1903190 so you can pretty much see why there is a problem. There is also bit more wider perspective in this problem in comments, although I believe the solution can't hug all the world :-) Anyways, just to give some idea, how things could work, if they could.
Really glad this thing is getting forward!
Comment #13
andypostThis is really great clean-up so any takers?
Comment #14
claudiu.cristeaYes. I'm taking the issue.
If fact it's not deprecated in this patch. I still use it as a wrapper because I didn't knew how to implement the menu route for paths like these (grrr!!!) so that menu route points directly to the class method:
Once the dynamic route get implemented this will be removed.
Comment #15
claudiu.cristeaSorry. Removed by mistake the tag
Comment #16
claudiu.cristeaNot very familiar with controllers. Can you explain?
Unit tests. We need to define what should be testable here. There are already some existing tests for Image Styles.
Comment #16.0
claudiu.cristeaUpdated issue summary.
Comment #16.1
andypostUpdated issue summary.
Comment #17
andypostShould be converted #1987712: Convert file_download() to a new style controller
PS added to summary
Comment #18
claudiu.cristeaSo,
->deliver()
will go in the style controller. How about other methods (flush, buildUri, etc)?Anyway, it seems that we need to wait for #1987712: Convert file_download() to a new style controller.
Comment #18.0
claudiu.cristeaUpdated issue summary.
Comment #19
claudiu.cristeaAdded followup: #2029649: Move entity_load('image_style', ...) in preprocess.
Comment #19.0
claudiu.cristeaIssue summary updated. Added related #2029649: Move entity_load('image_style', ...) in preprocess.
Comment #20
andypost@claudiu.cristea I dont think we need to wait, no time left... This tasks could be done in-parallel
Comment #21
claudiu.cristeaI'm working on it. A new patch is on the way. It's still not clear to me how to address some issues. See #18.
Comment #22
andypostSuppose deliver() should be proxied to #1987712: Convert file_download() to a new style controller
Other methods just needs rename
Comment #23
claudiu.cristeaFixed most of them...
Comment #24
claudiu.cristeaInterdiff
Comment #25
andypostI think only injection of needed services need some work. Other nitpicks are less critical
this needs link to the issue
suppose save() should call flush() internally
trailing white-space
this needs injection of $request & $moduleHandler services
And $lock service
do we really need $config injection here?
And clean URLs should be deprecated
this needs injection too
Comment #26
claudiu.cristeaThis mean passing $request and $moduleHandler to ImageStyle constructor? I really cannot understand this while
ImageStyle::deliver()
will be only a wrapper for callingImageStyle::deliver()
. In fact I really don't understand the reason of having this method while it's used only by the menu route (that is pointing to the controller.By "injection" you mean real injection or just using
Drupal::lock()
?Don't understand, sorry.
Comment #27
andypostActually the issue depends on conversion #1987712: Convert file_download() to a new style controller
Fix deprecated functions. Once we move code around it needs to be cleaned up!
Filed #2030207: Do not load all field instances when replacing image style
PS: Injection of services is possible for plugins https://drupal.org/node/2012118 but is not needed because deliver() should live in separate controller.
Delivery depends on conversion #1987712: Convert file_download() to a new style controller
Which have right implementation.
This is API change should be done before July 1 and issue summary needs to point about it
Comment #29
claudiu.cristeaLet's try again. There were some wrong arguments passed to
\Drupal::moduleHandler()->invokeAll()
. Moved also->flush()
in->postSave()
. That needs review.Comment #31
claudiu.cristeaSorry for the latest. Let's see if this turns green.
Comment #32
andypostAwesome! Now we need to get delivery in and write tests for #2030207: Do not load all field instances when replacing image style
Comment #33
claudiu.cristeaCan we get more reviews on this, please?
@andypost, what else should we write in the issue summary in order to be "July 1 Ready"?
Comment #34
fietserwinSome minor quickies, documentation related. I will continue my review later today and then review the core of this patch (ImageStyle.php and image.module).
comment says 'style'entry is an array, but it now is an object (though it already was, not due to this patch).
- incorrect English
- 2 typos, BTW: an exception is not returned but thrown, so I should make it "The image to be delivered.".
I propose to change this to:
- Returns the URI of this image when using this style.
- The URI to the image derivative for this style.
- i'm a bit lost. What is the difference between URI and URL? "Server path (or file system path)" versus "extenal path"
- Why is $clean_urls mixed? I guess it should be bool(ean).
- @see refers to the actual base class method, shouldn't it refer to the interface method?
- lines are to long.
- does it really save a cached version? I guess it saves the image for caching.
- can you explicitly document what happens if the image derivative already exists?
- Effects are not really applied but queried/asked about how the dimensions would be affected if it would be applied. Moreover this is an implementation detail, the style should return the resulting dimensions, how it computes these is not relevant here.
Comment #35
fietserwinQuite a big method. Are there any functional differences with the one in issue 1987712? This because I did not really review this method, that is better done (has already been done) in issue 1987712, assuming that they are functionally equivalent.
Comment line to long.
Comment line to long.
Comment lines to long.
$original_uri seems to be a misleading name (derivative_uri?).
Is this the fail silent design pattern :) ?
Furthermore:
- I also reviewed the changes (most are deletes) in image.module. They are all OK. Also the removals of the flushes, they are now part of the postSave and postDelete methods().
- I did not review the tests.
- I can confirm that none of the removed functions is still called anywhere.
API changes:
- a number of image_style_...() functions are removed (_create_derivative, transform_dimensions, _flush, _url, _path_token, _path). not sure if those are internal or real API functions.
- the parameter of hook_image_style_flush is now an object. image.api.php is not completely correct in this, the parameter type is correct, but the text still mentions array (as does api.drupal.org).
So the part I reviewed is functionally RTBC, though documentation, naming and coding standards (comment lines to long) need some attention.
Comment #36
claudiu.cristeaThanks @fietserwin for this valuable review. Giving some input only on some points.
URI: public://images/image.jpg, URL: http://example.com/sites/default/files/images/image.jpg
This has been introduced in https://drupal.org/SA-CORE-2013-002. It's a security issue. I wouldn't touch that.
This shouldn't be documented in the interface being an implementation issue. Maybe some implementations will always have existing derivatives (imagine keeping derivatives on Flickr).
Agree but this will be removed in favour of #1987712: Convert file_download() to a new style controller. I won't spend time with this. Rather make there a full review.
I don't have a good answer it seems that the response object have the clean urls flag set. IMO passing the
$clean_urls
argument should be removed. @andypost?Here's a new patch with fixes.
Comment #37
andypost\Drupal\image\ImageStyleInterface
trailing whitespace
Comment #38
claudiu.cristeaThese are Ok while they are testing specifically the Drupal shipped implementation of
ImageStyleInterface
which isImageStyle
. The test doesn't apply to other implementations.Comment #39
claudiu.cristeaHere are fixes to docs.
Comment #40
fietserwinI was just referring to the documentation, there it should be documented as bool, not a mixed (especially as we explicitly check on FALSE.
IMO, the interface defines the (base) contract and thus should specify preconditions that can be assumed and postconditions that should be met. Thus it should specify that as a precondition the directory does not have to exist or that the derivative can already exist and (as a postcondition) does not absolutely have to be recreated in that case.
I prefer to have some documentation if exceptions are caught and ignored because that is an anti-pattern. In this case i can imagine that we don't care if that service cannot be found, it is not absolutely needed for our task.
Thanks for changing the other remarks.
Comment #41
andypostThere's no consensus on #1987712: Convert file_download() to a new style controller
So let's get this in first
Comment #42
YesCT CreditAttribution: YesCT commentedThis issue was RTBC and passing tests on July 1, the beginning of API freeze.
Comment #43
tim.plunkettSee also:
#2033669: Image file objects should be classed
#1821854: Convert image effects into plugins
Comment #43.0
tim.plunkettUpdated issue summary.
Comment #44
claudiu.cristeaAdded #2033669: Image file objects should be classed to issue summary.
Comment #44.0
claudiu.cristeaAdded #2033669 to summary.
Comment #45
tim.plunkettI've rerolled my other two issues on top of this one since it is already RTBC.
Let's get this in!
Comment #46
tim.plunkettThat big RDF issue added an extra call to image_style_url(). Fixed, leaving RTBC.
Comment #48
tim.plunkettDoh, bad copy/paste and random failure.
While I was in there, I cleaned up a couple instances of bad docs.
Comment #50
tim.plunkettPHPStorm reported it as an unused variable, but
$request = $this->prepareRequestForGenerator($clean_url);
was needed. I've deleted the assignment so no one else makes the same mistake.Also, I've attached an interdiff from the last RTBC in #39.
Comment #51
andypostLooks great!
Comment #52
tim.plunkettNote for reviewers, this call to flush is removed since saving the style as a whole triggers flushing now.
Comment #53
claudiu.cristeaHere's a polished
->deliver()
method and a phpdoc addition.Comment #54
alexpottCommitted 27f8cd4 and pushed to 8.x. Thanks!
Lets get #1987712: Convert file_download() to a new style controller this done ASAP... to me the amount application level services that are being accessed in the new deliver method on the ImageStyle config entity is ugly.
Fixed code style in commit...
Comment #54.0
alexpottUpdated issue summary.
Comment #55
fietserwinRegarding the interdiff of #53:
I don't like it that $valid is changed into an integer here. &= is NOT the same as = ... && ... , and &&= does not exist. So the original notation was correct: we want a boolean, so use operators that return a boolean, that's way more readable.
Comment #56
claudiu.cristeaPHP correctly evaluates
$valid
even is integer. It shouldn't be a strict evaluation here. But anyway the discussion here is senseless while this piece of code will be removed soon by #1987712: Convert file_download() to a new style controller.Comment #57
tim.plunkettChange notices are critical.
Comment #58
claudiu.cristeaIt's almost ready but I need pieces from other issues that were just committed.
Comment #59
claudiu.cristeaHere's a draft:
The image style system is flexible now. Contrib or custom modules are able to extend it or even replace it with their own implementation. A new interface (
ImageStyleInterface
) for image style configuration classes has been defined. Drupal 8 is shipped withImageStyle
as default class implementation ofImageStyleInterface
. Legacy image style configurations from Drupal 7 were converted into configuration entities (configurables), instances ofImageStyle
.The
image_style_deliver()
was converted into a new download controllerImageStyleDownloadController
being responsible with image derivatives delivery. By extending or overwritting this class you can implement custom permissions on image styles.Old, procedural, functions were replaced by methods from
ImageStyleInterface
interface. Here's a conversion table:image_style_path()
->buildUri()
image_style_url()
->buildUrl()
image_style_flush()
->flush()
image_style_create_derivative()
->createDerivative()
image_style_transform_dimensions()
->transformDimensions()
>image_style_path_token()
->getPathToken()
image_style_deliver()
Note: Bolded methods are implementing
ImageStyleInterface
.Find a derivative URI and URL
D7
D8
Create a derivative image programmatically
D7
D8
Comment #60
claudiu.cristeaPosted here: https://drupal.org/node/2050669
Comment #61
andypostAwesome!
Comment #62.0
(not verified) CreditAttribution: commentedUpdating related issues.
Comment #63
SocialNicheGuru CreditAttribution: SocialNicheGuru commentedWill this patch be ported to D7?
Comment #64
Dave ReidIs there an example of how two different stream wrappers (provided by two different contrib modules) would be able to accomplish this from their own module code, and separate from each other?
Comment #65
claudiu.cristeaThis issue is not about stream wrappers. The quoted text refers to the ability of a module to completely change the location of derivatives. And yes, only one module can do this, compared to D7 where no module can interact in the derivative creation.
EDIT: And not only the location but also the mechanism of derivative building (not only altering the path)
Comment #66
Dave ReidOk, then I'm definitely feeling better about re-opening #1358896: Flexible scheme and URI for image derivatives because the actual need is for the individual stream wrappers to be able to control where image style URIs get generated for their own paths, without having to worry about which module wins.
Comment #67
claudiu.cristeaHm... I don't think that a stream wrapper should know about where derivatives will be placed. It's not stream wrapper's business. But yes, a simple mechanism that allows path alteration it's more than welcomed. And maybe also fro D8?