-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validate XML mapping against XSD file #6728
Conversation
*/ | ||
public static function fromLibXmlErrors(array $errors) : self | ||
{ | ||
return new self(array_reduce(array_map(function (\LibXMLError $error) : string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First time ever playing with array_reduce
, this is fun! But I should probably use implode
instead, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that looks like it could perfectly be implemented with implode(PHP_EOL, array_map(...);
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will change
e71713a
to
1d91644
Compare
Regarding the exception issue, I found that the xml driver extends a class from another package (doctrine/common). One of the parent methods throws an exception from that package if the result from Would you consider throwing an exception from this package a BC-break or not? Also, if we forget about this PR for a moment, wouldn't it be better to do this? Asking because <?php
try {
// method call from another package
} catch (ExceptionFromAnotherPackage $e) {
throw new ExceptionFromThisPackage('message', 0, $e);
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be a nice addition to 3.0 and have it enabled by default.
Note that this introduces a dependency on ext-dom.
@@ -861,6 +862,21 @@ protected function loadMappingFile($file) | |||
return $result; | |||
} | |||
|
|||
private function assertValid(string $file): void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about call it validateMapping
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be less misleading since I don't use actual assertions here
{ | ||
$backedUpErrorSetting = libxml_use_internal_errors(true); | ||
$document = new \DOMDocument(); | ||
$document->load($file); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will cause duplicated IO, better pass already fetched XML string to this function and use DOMDocument::loadXML()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah but it gives worse error messages
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #6728 (comment)
if (!$document->schemaValidate(__DIR__ . '/../../../../../doctrine-mapping.xsd')) { | ||
$errors = libxml_get_errors(); | ||
libxml_clear_errors(); | ||
libxml_use_internal_errors(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two directives could be put into a more DRY finally
block, and use $backedUpErrorSetting
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I lost my train of thought it seems
$backedUpErrorSetting = libxml_use_internal_errors(true); | ||
$document = new \DOMDocument(); | ||
$document->load($file); | ||
if (!$document->schemaValidate(__DIR__ . '/../../../../../doctrine-mapping.xsd')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space around !
is needed.
In 3.0: No. Please add some tests to illustrate how the error propagation from libxml looks like. |
Right now it's not optional so... congrats, no failures! |
Uuuuh what am I saying, there is one failure that was not intended (I think):
BTW, here is the error message when loading a string instead of a file:
|
6dd616c
to
e3985e3
Compare
Made that explicit |
e3985e3
to
0a1bca7
Compare
composer.json
Outdated
@@ -15,6 +15,7 @@ | |||
"minimum-stability": "dev", | |||
"require": { | |||
"php": "^7.1", | |||
"ext-dom": "*", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a question: Isn't this extension optional? The usage of XML in Doctrine is optional too for a user, isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, it's an optional dependency. However, making it an explicit dependency is the defensive way here: we prevent the code from blowing up in the users face with a fatal error if they use XML mappings.
Remember that other bundles (e.g. the FOSUserBundle) specify XML mappings which are automatically imported, so the user won't know that he's using XML mappings and thus should add the ext-dom
dependency.
One more thought: moving this to suggest
would require all bundles that specify XML mappings to add a require
entry for ext-dom
, which would be a BC break towards the bundles. IMO it's safer to add it as an explicit dependency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Talking about "Bundles" sounds more like Symfony instead of Doctrine. This repository is independent from frameworks. Should in this case the require
be added in DoctrineBundle? What are "all bundles"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SenseException replace "bundles" with "anything that provides XML mappings". Suggesting ext-dom
instead of requiring it will break third party software if they already use XML mappings. That's a BC break that would move this feature back to 3.0. The way it is now it's possible to add this to the 2.x line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alcaeus I rebased on 3.x yesterday 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, didn't see that, my bad. IMO it's better to have the explicit dependency anyways. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have mixed feelings about this. One one hand, it's true that user would need explicit ext-dom dependency. On the other one, we should check at runtime for DOM presence, it just feels wrong to force people with annotations install DOM. (Well, we can say the same about doctrine/annotations, but that's slightly different story).
Since this PR is now 3.0 only, it should be fine fine to do either way, but question is which one is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other one, we should check at runtime for DOM presence, it just feels wrong to force people with annotations install DOM.
https://webmozart.io/blog/2014/10/24/defining-php-annotations-in-xml/
9f5fd37
to
e7d61c2
Compare
Needs a rebase. |
0a1bca7
to
36f01cd
Compare
This means that a class implementing a doctrine/common interface or extending a class from that package can throw a specialized exception that will still be caught by code in the parent package. Blocks doctrine#6728
#7199 should solve this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An unrelated follow up could be to get rid of SimpleXML in the driver and use only ext-dom
@lcobucci regarding the OCP, I read the link you gave and it says (rightly IMO) that the OCP is something that should be taken into account when designing a class. I think a sensible way to violate the OCP as little as possible could be to do the following: interface XMLValidator
{
public function __invoke(string $file);
}
class DomXMLValidator implements XMLValidator
{
// … implementation goes here
}
class XMLDriver
{
// inject validator in constructor and call it
} But given the size of the added piece of code, and given how unlikely I think it is people would want to inject their own implementation of the XMLValidator, I'm not sure it's worth it. Do you still have concerns about runtime deprecations, now that we have switched to https://github.com/doctrine/deprecations/ ? That lib wasn't discussed at all in doctrine/doctrine-website#200 |
The great thing about "principles" that version of me from 4 years ago hadn't learned well is that they aren't absolute rules 😆. I (now) know that understanding the context and allowing some flexibility is important - even though I tend to stick to them as much as possible. If I was making this feature, I'd still aim to add a new component instead of modifying the existing one to conditionally change its behaviour based on a boolean flag. I believe that adding a new ( With that said, I understand your arguments and agree that a completely different design would make things much better buuuuut 🤣
Doctrine has fully embraced that deprecations library so I believe that's a moot point now 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some minor improvements on the SA side of things =)
69b16b9
to
116a632
Compare
Co-Authored-By: Axel Venet <avenet@wamiz.com> Co-authored-by: Luís Cobucci <lcobucci@gmail.com>
116a632
to
ab3a255
Compare
User Deprecated: Using XML mapping driver with XSD validation disabled is deprecated and will not be supported in Doctrine ORM 3.0. (XmlDriver.php:60 called by SimplifiedXmlDriver.php:23, doctrine/orm#6728, package doctrine/orm)
TODO