Problem/Motivation
Part of #3221796: [META] Modernise file upload logic we identified that we are duplicating the code to find the file upload location in the following places:
\Drupal\file\Plugin\Field\FieldType\FileItem::getUploadLocation()\Drupal\file\Plugin\rest\resource\FileUploadResource::getUploadLocation()\Drupal\jsonapi\Controller\TemporaryJsonapiFileFieldUploader::getUploadLocation()
We can't really create a base class and use inheritance for this, as they use different methods of uploading files (ie. UploadedFile vs input stream).
Steps to reproduce
Proposed resolution
Add a trait that gets the upload destination from the field definition, and deprecate the duplication.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #24 | 3389688-nr-bot.txt | 90 bytes | needs-review-queue-bot |
| #19 | 3389688-nr-bot.txt | 4.26 KB | needs-review-queue-bot |
Issue fork drupal-3389688
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 11.x
compare
- 3389688-provide-a-trait
changes, plain diff MR !4876
Comments
Comment #3
kim.pepperLooks like it's going to be problematic replacing the code in method
\Drupal\file\Plugin\Field\FieldType\FileItem::doGetUploadLocation()with a trait because it is static.Comment #4
smustgrave commentedFor the new trait could we get a CR
Comment #5
kim.pepperFixed merge conflicts and added a change record.
Comment #6
shweta__sharma commented@kim.pepper Need to rebase the branch.
Thanks!
Comment #7
smustgrave commentedFor the rebase.
Comment #8
kim.pepperMerged with 11.x
Comment #9
prashant.cThe trait seem to be functioning well for the file fields. I was considering whether it might be sensible to maintain consistency in the function names within the trait as well. For instance, changing
getFileUploadLocationtogetUploadLocation(). Just a suggestion.Comment #10
smustgrave commentedThanks for fixing that @kim.pepper!
Comment #11
quietone commentedI'm triaging RTBC issues. I read the IS, the comments, the change record and the MR. I do like a bit of tidying up!
The question raised in #9 has not been answered. Why the name change? And how will this effect any contrib usages of
getUploadLocation?The change record also needs to be updated, it is referring to changes that have not been made. Also, the first sentence is difficult to read, and English is my first language. Also, instead of mentioning a usage in a contrib project it would be more helpful to explain what must be done in contrib to update modules for this change, such as a before and after example.
Setting to needs work for the above.
Comment #12
kim.peppergetUploadLocation()as per the suggestion in #9Comment #13
kim.pepperI really wanted to replace
\Drupal\file\Plugin\Field\FieldType\FileItem::getUploadLocation()with the trait but not sure how to work around deprecating a static method with a class method.Comment #14
smustgrave commentedthoughts on handling that replacement in a follow up?
Comment #15
kim.pepperCreated follow-up #3411813: [PP-1] Replace FileItem::getUploadLocation() with FileUploadLocationTrait
Comment #16
smustgrave commentedOh cool. Then in that case rest seems fine to me.
Comment #17
smustgrave commentedComment #18
kim.pepperI thought I would have a go at replacing
FileItem::doGetUploadLocation()with the trait method.Unfortunately,
generateSampleValue()calls it and is a static method, so we have to call the trait method statically too. I added a@phpstan-ignore-next-linebut I'm not sure what the alternative is?Comment #19
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #20
kim.pepperUpdated IS
Comment #21
smustgrave commentedReviewed the deprecation and link to CR appears correct https://www.drupal.org/node/3406099
Reviewing actual CR and all the details are there.
Believe this is good.
Comment #22
quietone commentedThis is my second visit here for triage. I didn't find any unanswered questions or other work to do.
Leaving at RTBC;
Comment #23
alexpottI wonder if we don't have to add the service. Can we use the same approach as \Drupal\media_library\Form\FileUploadForm::createMediaFromValue and create a FileItem to do this.
Otherwise if we're going to go with the current approach I think we should be accepting a field definition object instead of settings and validating that it is a fiie item that we're generating a location for. Otherwise it's all a bit mushing random arrays together.
Comment #24
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #25
kim.pepper#23 @alexpott I'd prefer to use a service, as we depend on
'token'and that has about 5 other dependencies.I've changed
\Drupal\file\Upload\UploadDestinationResolver::getUploadDestination()from acceptingarray $settingstoFieldDefinitionInterfaceand I think that works better.Comment #26
alexpottI've looked at both this and \Drupal\file\Validation\FileValidatorSettingsTrait::getFileUploadValidators() and I think that they both should be / have been part of the file field API. If we put them on \Drupal\file\Plugin\Field\FieldType\FileFieldItemList then we'd be able to call this methods from the field definition we already have.
I don't think our API should be decided by the fact that our field system struggles with container injection (only because it was updated before the container was truly available in the D8 cycle). Both getFileUploadValidators() and getUploadDestination() are extremely intimate to the internals of the file field type.
Comment #27
kim.pepper#26 hmm, not sure exactly how that would work 🤔
I'm a bit lost on how FieldDefinitionInterface and FieldItemList are related.
Comment #28
kim.pepper@alexpott re: #26 I added the method to
\Drupal\file\Plugin\Field\FieldType\FileFieldItemList::getUploadLocation()but not sure how to access that from a$field_definition.Comment #29
kim.pepper@alexpott thanks for the review, but we still need to work out how to do this. See #28
Comment #30
alexpottYeah having this on the field item list doesn't work out :( I can't see how to get back to the list item either...
$field_definition->getClass()returns\Drupal\file\Plugin\Field\FieldType\FileFieldItemListbut $field_defintion is actually a FieldItemDataDefinition.How about not deprecating the stuff on the FileItem and use that - as suggested in #23.
Comment #31
kim.pepperI took the approach suggested in #30 of creating a file item from the field definition. I put it in a trait so it could get used by both REST and JSON API.
@alexpott Do we still want to postpone the deprecation to 12.x? It seems much less disruptive now.
Comment #32
kim.pepperUpdated title and IS
Comment #33
alexpottGiven they are both controllers I think 11.x is fine
Comment #34
smustgrave commentedAppears feedback has been addressed.
CR still appears fine, not sure if it was updated or mention removed in 12 before.
Comment #35
alexpottCommitted and pushed 7a12710863 to 11.x and e9c7c01bc8 to 10.3.x. Thanks!
Comment #40
mattew commentedI've encountered a significant issue with the implementation of this change that affects the deprecation mechanism and backward compatibility.
The problem is that the current implementation uses a trait alias in FileUploadResource:
This creates several problems:
1. Deprecation warnings are bypassed: When a class extends FileUploadResource and overrides `getUploadLocation()`, the overridden method is never called because the core code now calls `getUploadDestination()` instead. This means the deprecation warning in the original `getUploadLocation()` method is never triggered.
2. Silent breakage: Existing code that extends FileUploadResource and overrides `getUploadLocation()` silently stops working without any indication to developers that their code needs updating.
3. Counter-intuitive override mechanism: Currently, if developers want to override the upload location logic, they must create a `getUploadDestination()` method instead of overriding `getUploadLocation()`, which is very counter-intuitive.
4. Misleading documentation: The deprecation message says "Use \Drupal\file\Upload\FileUploadLocationTrait::getUploadLocation() instead" but in practice, developers need to implement `getUploadDestination()`.
I've created a separate issue to address this: https://www.drupal.org/project/drupal/issues/3540037
This implementation effectively breaks the standard PHP inheritance model for the deprecation period, which could cause significant confusion and silent failures in contrib/custom modules that extend FileUploadResource.