Closed (fixed)
Project:
Drupal core
Version:
11.x-dev
Component:
file system
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
1 Jul 2021 at 23:00 UTC
Updated:
13 Feb 2024 at 23:09 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
kim.pepperAdd this to the meta
Comment #3
kim.pepperComment #4
kim.pepperInitial patch showing how the constraint validator API would look.
Comment #5
berdirDidn't look too closely yet, one related issue I'd like to point out is #2867336: File size validator should only respect the explicitly configured maximum file size.
That's a very awkward if you use s3 upload or any other mechanism that doesn't rely on manually uploading files on your server. If a file already exists then there is no reason to validate it against the upload max size IMHO.
I understand it's tricky to refactor things and change them at the same time, but I'd love to find a way to finally resolve that isuse.
Comment #6
gabesulliceIt's very exciting to see this materializing! Don't mind my review too much since it's mostly made up of nitpicks on what I understand is an initial patch to illustrate the concept.
@Berdir Yeah... I hear you, but I'd be very reluctant to do that. From my limited experience with the file system, its issues appear to be plagued by scope creep and a desire to fix everything every other thing before fixing any one thing. Let's race these issues against each other instead.
Are these supposed to be the same:
FileSizevsFileSizeLimit?Are there default file extension constraints we should have here?
Nit:
s/files-allowed/allowed-extensions/Are there unit tests in
file.modulefor extension validation that we can port to this constraint?Nit:
s/FILE/SIZE/Nit:
s/LIMIT/QUOTA/Comment #7
kim.pepperThanks for the review @gabesullice Still early days, but I wanted to get a sense of what the API would look like and what BC we'd need to handle.
I've added a bunch of deprecations so I expect there to be lots of fails here.
Re: #6:
Comment #9
kim.pepperHandle missing arguments in _file_convert_validators_to_constraints().
Comment #11
kim.pepperFixes \Drupal\Tests\file\Kernel\ValidateTest
Comment #12
kim.pepperMore file validator fixes.
Comment #14
kim.pepperFix E_USER_DEPRECATED
Comment #17
kim.pepperHaving 2nd thoughts about this issue. Initially I thought we could swap file_validate out for a new service based on symfony constraints, however file_validate is tightly bound to the form api, and there are hundreds of contrib modules using it. grep.xnddx.ru/search?text=file_validate
Going to postpone until the other issues are in.
Comment #21
kim.pepperI'm shifting away from Symfony Validators to a (hopefully) simpler approach in #3353583: Allow validators passed to file_validate to use callable syntax
Comment #22
kim.pepperRe-roll to see what's breaking.
Comment #24
kim.pepperFix test fails
Comment #25
kim.pepperI wonder if we should go further up the stack and replace
'#upload_validators'in the Form API with an array of\Symfony\Component\Validator\Constraintinstances? This probably means replacing how form validation works to be more inline with Symfony Validator component, and there seems to be some pushback on using it at all #3054535: Discuss whether to decouple from Symfony ValidatorComment #26
kim.pepperAlso not sure how the form API and existing validators tie into the whole Typed Data API and plugin validators like
\Drupal\file\Plugin\Validation\Constraint\FileValidationConstraintValidator.Comment #27
joachim commentedKeyed by what? And in what order?
Could this go on a service somewhere instead of being a function? We can mark it as @internal.
Typo: should be "let's".
I think we need some docs on this class to explain why we have a mishmash of procedural validators and Symfony constraints.
I assume it's because of BC? But shouldn't there also be an issue to deprecate the functional validators?
Comment #28
kim.pepperThanks @joachim. I'm still looking for the right approach for this.
Re: #25 Should we introduce Constraints to the Form API? Or should we just focus on upload validators and converting them over?
Re #26 If we do start to use Constraints, should we try and reuse the plugins that typed data api uses?
Comment #29
kim.pepperChatted with @larowlan about this at DrupalSouth and decided the best approach is utilise constraint validation plugins.
We can create plugins with the same IDs as the function names for BC, and deprecate the functions.
Comment #30
larowlanCapturing some conversation from DrupalSouth
\Drupal\Core\TypedData\TypedDataManager::getValidatorhas some prior art to create a validator\Drupal\Core\TypedData\TypedData::validatehas how to validate once you have the validatorComment #31
smustgrave commentedCan the issue summary also be updated to include agreed upon solution please
Thanks!
Comment #32
larowlanTo reflect current discussion
Comment #33
kim.pepperStarting on the new approach described above in #29 and #30.
Posting here for architectural review.
Comment #34
kim.pepperAdded an additional validation for FileExtension to test passing in arguments. We will need to use the existing '$value' option as we don't currently an associative array of options, just the function arguments.
I also updated the issue summary with the current approach and remaining tasks.
Comment #36
kim.pepperComment #37
kim.pepperStill a work in progress. Did more work building out constraints and added logic for deprecating existing hook functions.
Ran into
file_validate_image_resolution()which I think doesn't belong as a validator. I created #3363745: Deprecate file_validate_image_resolution() and replace with a service which I think is a blocker for this issue.Comment #38
smustgrave commentedIf CC error could be addressed.
Comment #39
kim.pepperRe: #37 I dug a bit deeper and trying to remove
file_validate_image_resolution()from the validators is going to be complex. I have added a\Drupal\file\Plugin\Validation\Constraint\FileImageDimensionsConstraint. Happy to hear opinions on how we can do this better.Remaining tasks:
Convert all the file validation functions to pluginsComment #41
kim.pepperFixes test fails and adds a test for
FileNameLengthConstraintValidator.Comment #42
kim.pepperAdds a test event subscriber.
Comment #43
kim.pepperDeprecates
file_validate()and replaces usages.Remaining tasks:
Convert all the file validation functions to pluginsDeprecatefile_validate()Replace usages in coreComment #45
kim.pepperReplaced more usages of
file_validate()andfile_validate_*functions.Comment #47
kim.pepperFixing test fails.
Comment #49
kim.pepperJSON API has an undeclared dependency on file module so a lot of these fails are because we have a new file service that will error out when the container is built, whereas before we were just calling the
file_validate()function and not checking if it was available.Added
'file'as a module dependency to a load of the JSON-API tests.The patch grows bigger, and the night grows darker...
Comment #51
kim.pepperFixes tests.
Remaining tasks:
Convert all the file validation functions to pluginsDeprecatefile_validate()Replace usages in coreDeprecate the legacy file validate hook functionsfile_validate_*functionsComment #53
kim.pepperTrying a different approach to fix test issue by checking
$file instanceof ConstraintViolationListInterfaceinstead of$file instanceof EntityConstraintViolationListInterface.Comment #54
kim.pepperFileSizeMaxtoFileSizeLimit.ile_validate_*tests to ensure we don't lose any test coverage.No more remaining tasks! Just reviews needed.
Comment #56
kim.pepperDon't use markup in test assertions.
Updated the CR to provide much more details and mapping old to new form API changes.
Comment #57
kim.pepperComment #58
smustgrave commentedSearched for file_validate_size() and all instances appear to be addressed.
Fyi expectDeprecation is deprecated itself but seems #3322785: [meta] Several expect*() methods have been deprecated in PHPUnit 9.6 there is still a plan being made.
Comment #59
larowlanThis is looking amazing. I've done half the review and will finish it off tomorrow, here's observations so far
🔥
Technically this is a BC break but we don't provide API for controllers and it looks like nothing is extending it in contrib https://git.drupalcode.org/search?group_id=2&scope=blobs&search=%22exten... so I think we're fine as long as this is mentioned in the CR
We will need to handle both formats here, as there will be existing render arrays with the theme hook in contrib/custom code with this in the old format.
We should trigger a deprecation error if they are
We will need to handle both formats here, as there will be existing forms in contrib/custom code with this in the old format.
We should trigger a deprecation error if they are
nice
we should be safe to narrow this to
:string🧐 think there's an extra space here
copy/paste?
I think if we flip this and return early it would simplify the code, e.g.
we can probably flip this too, and add the violation and return early, avoiding the else and another layer of nesting
we can return from each of these and avoid elseif
we can return here and avoid an else too
copy/paste
Should the 240 in this string be placeholdered? I think the maxLength would be configurable via the constraint constructor right?
should this be using mb_strlen to allow for utf-8 characters?
copy paste?
Note to other reviewers, this just uses the parent now
however, we can probably drop the use of the trait now
Part way through review, up to here
Comment #60
kim.pepperminDimensionsviolation further down.Comment #61
larowlanGot to the end, couple of questions about tests
do we need a legacy test for this and the equivalent BC layer in the managed file element ?
was going to ask 'should there be a getter for this' then realised its public, 👌
minor: can we improve this? 'Provides a class for file validation' perhaps?
I _think_ you can just call $file->getTypedData()
Should we add a test event listener using the new event that writes the 'validate' entry and keep these as they were? Would reduce the size of the patch and retain the existing coverage.
should we assert the message is as expected?
here too, I think we should be asserting the expected message to ensure the violation is what we expect rather than just the count
here too
if we extend the abstract base class from above I think we can remove all this setup
Removing the needs architectural review tag as I think this looks good.
The cleanup in the API resources makes it clear this is the right model, we were mixing constraints and errors in a weird mis-mash. Now its a single approach (or it will be once we can remove the BC layer).
Comment #62
kim.pepper\Drupal\Tests\file\Kernel\LegacyFileThemeTest::testTemplatePreprocessFileUploadHelp()::createFromEntity()underneath, but lets find out.file_validator_testmodule's event listener to set the test state that the FileUploadTest was previously checking, and re-added the check for 'validation' hook being fired (event though it's an event now). I had to rework the FileValidatorTest as we are no longer adding a violation in the event listener.Drupal\Tests\file\Kernel\Plugin\Validation\Constraint\FileConstraintValidatorTestBaseto\Drupal\Tests\file\Kernel\Validation\FileValidatorTestBaseComment #63
smustgrave commentedFrom what I can tell all of @larowlan's points have been addressed.
Comment #64
wim leers🤩
I think that many of these could use
\Symfony\Component\Validator\Constraints\FileValidatorinstead? 😅 That would mean less code to maintain on the Drupal side!Related: #3365498: Add Missing Symfony Validators to Drupal Constraint Validator.
Comment #65
wim leersComment #66
smustgrave commented@Wim Leers showed me this and explained a lot about how the Constraints can be leveraged. Think if we can leverage them we should!
Comment #67
kim.pepperHad a look through the Symfony constraints. As mentioned in Slack, we have a
\Drupal\file\FileInterfaceand\Drupal\Core\Image\ImageInterfacewe are validating, so the Symfony validators won't work.Comment #68
kim.pepperComment #69
smustgrave commentedThanks for checking that. Will remark then.
Comment #70
kim.pepperRe-roll of #62
Comment #71
larowlanIssue credits
Comment #72
larowlanJust one comment and one follow up request, feel free to self RTBC or push back if not appropriate.
there's a lot of duplicate code between these two, can we get a followup to move to a base-class or trait?
these two classes have identical setup methods - could/should we use a base class? We have one already in this patch, could some of this duplication go there?
Comment #73
kim.pepperComment #75
larowlanCommitted 79c7666 and pushed to 11.x. Thanks!
Published the changed record
Comment #77
damienmckennaFYI this introduced a subtle bug whereby if a validator passed through #upload_validators did not exist as a function it was assumed to be a constraint plugin, whereas some contrib modules used it as a namespaced variable that would ultimately be passed through to hook_file_validate(). This has caused problems with several contrib modules, including Webform (#3409599: Drupal\Component\Plugin\Exception\PluginNotFoundException: The "webform_file_validate_extensions" plugin does not exist).
Comment #78
kim.pepperA new bug reported for the BC layer: #3420802: [regression] file_save_upload does not properly handle extensions