-
Notifications
You must be signed in to change notification settings - Fork 35
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
Issue #46 (Wrong result from local number) fix #47
Conversation
…ntry code - git ignores .DS_Store files
Hey, I will take a look this weekend. I agree it is a bit clumsy. |
} | ||
|
||
// rethrow previously got error | ||
throw countryCodeException!; |
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.
let's not use the !
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.
That is not possible because it leads to compilation issues. This can be avoided with the transformation CountryCodeParser.extractCountryCode
and _findDestinationMetadata
to return an optional, which causes to more remarkable code changes.
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.
It seems like you were talking about the country_code_parser interface that throws when the country code is not found. Which could instead return a String?
. That's a fair observation and I'm okay with that. At first glance this seems to be a small change but it'd be better if it was in a separate PR imo, just to make it easy to review.
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.
Agreed. What do you think is the best to do in this case?
return null; | ||
} | ||
|
||
static PhoneMetadata getMatchUsingPatterns( |
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 does not seem to be used anywhere anymore. Therefor this can be removed and the "Strict" can be removed from the new one.
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.
getMatchUsingPatternsStrict
was introduced to avoid duplicated code in getMatchUsingPatterns
. As I wrote, I tried to localize changes maximally, but I suggest redesigning interfaces to avoid exceptions and non-valid metadata matches.
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.
You misunderstood me. It seems like getMatchUsingPatterns
is not used anywhere in the code base except here. It can safely be removed. When getMatchUsingPatterns
is removed we will only have getMatchUsingPatternsStrict
which can be renamed to getMatchUsingPatterns
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.
but I suggest redesigning interfaces to avoid exceptions and non-valid metadata matches.
MetadataMatcher already returns a nullable. That discussion could be made for the country code parser though
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.
Done.
List<PhoneMetadata>? metadatas; | ||
|
||
try { | ||
countryCode = CountryCodeParser.extractCountryCode(phoneWithoutExitCode); |
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 believe there is something unsound here:
Currently the code in the parser assumes that if there was no exit code, then the next part is not a country code. (line 60)
// if there was no exit code then we assume we are dealing with a national number
if (containsExitCode) {
national = CountryCodeParser.removeCountryCode(
withoutExitCode,
destinationMetadata.countryCode,
);
}
But here this assumption is not taken into account.
However, some people want to be able to parse phone number starting with a country code without the exit code see: #39 . But I believe that's outside the scope of this PR
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.
Are there any tests that cover this case?
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.
Are there any tests that cover this case?
I suggest not handling this case in this PR.
There is a list of test in the issue that I believe would not pass currently without the leading '+'. That is:
var expected = '+64211234567';
expect(sanitizePhoneNumber('640211234567', countryCode: IsoCode.NZ), expected);
expect(sanitizePhoneNumber('64211234567', countryCode: IsoCode.NZ), expected);
This is outside the scope of this Pull request though.
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.
OK.
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 you explain to me why don't we do (as per my first comment)
// if there was an exit code then we can safely assume that the next part is a country code. If no country code is found then it is invalid.
if (phoneHadExitCode) {
countryCode = CountryCodeParser.extractCountryCode(phoneWithoutExitCode);
}
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.
Earlier, there was no difference in whether the phone had an exit code or not; the parser tried to interpret the first digits as country code. So, my changes were an attempt to preserve the current way to process input.
Thank you for your efforts!
Please clarify what I have to do. |
- MetadataMatcher.getMatchUsingPatternsStrict renamed to MetadataMatcher.getMatchUsingPatterns
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'm still trying to wrap my head around some of the changes. My main question point is line 113, the last comment I added.
What would really help is if you could give a few example phone numbers in the comments related to some of the big logic blocks you added in find metadata.
Phone parsing can be difficult (but fun).
if (countryCode != null) { | ||
metadatas = MetadataFinder.getMetadatasForCountryCode(countryCode); | ||
final national = CountryCodeParser.removeCountryCode(phoneWithoutExitCode, countryCode); | ||
final metadataMatch = MetadataMatcher.getMatchUsingPatterns(national, metadatas); |
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.
getMatchUsingPatternsStrict
checks that the metadata matches the phone number and and the phone number is valid. Why do we need to check that it is valid if there is a match ? It could be an incomplete phone number for example. Wouldn't that negatively affect that scenario ?
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.
For example, while trying to process local US numbers like (707) 555-1854
without an exit code, the country code was resolved as 70
, but the number is not valid for IsoCode.RU. I added the strict match option to determine if the number truly belongs to the found region.
lib/src/parsers/phone_parser.dart
Outdated
if (phoneHadExitCode) { | ||
// 1. | ||
// if phone number has the exit code, we should use it | ||
// despite caller's metadata and phone number validity |
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 comment is ambiguous. What is "it" in "we should use => it <=". And why "phone number validity", as metadatas you return already check validity ?
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.
That's a part of handling a partial input that starts with an exit code.
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 updated the comment
List<PhoneMetadata>? metadatas; | ||
|
||
try { | ||
countryCode = CountryCodeParser.extractCountryCode(phoneWithoutExitCode); |
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 you explain to me why don't we do (as per my first comment)
// if there was an exit code then we can safely assume that the next part is a country code. If no country code is found then it is invalid.
if (phoneHadExitCode) {
countryCode = CountryCodeParser.extractCountryCode(phoneWithoutExitCode);
}
Hello again, sorry for the back and forth, I somewhat misunderstood your issue at first. I believe the part of the code that should be fixed for your actual issue is not exactly the part that you fixed. Correct me if I'm wrong: This was your issue: expect(
PhoneNumber.parse('(707) 555-1854', callerCountry: IsoCode.US)
.international,
equals('+17075551854')); The actual culprit is this line https://github.com/cedvdb/phone_numbers_parser/blob/dev/lib/src/parsers/phone_parser.dart#L102 if (callerMetadata != null &&
callerNationalPrefix != null &&
phoneWithoutExitCode.startsWith(callerNationalPrefix)) { // will be false because it is **local** (same area in us)
return callerMetadata;
} where you'd want to enter this condition. You do not enter this because the phone number is in local form. Therefor the condition: Am I wrong that this would be the only change required to fix your issue ? |
Potentially, yes, but when I replace the block
with
in the initial version of the library, the tests fail on
However, the tests I added perform well. I think an exit code check should be mandatory in this method. |
I've been away the past few days. I'll have a look into this tomorrow to see what I can do. |
I see it was a complex solution. Many thanks for your efforts! |
@aazhevsky the solution itself was 3 lines (there is a function rename that should not be part of the PR), the refactor took a bit longer |
Hello,
These changes will fix the Wrong result obtained from local number #46 issue.
After applying the changes, the following local US phone numbers are parsed successfully:
All the interfaces are kept, as well as all tests passed. The major problem is that the code of the fix is a bit clumsy. At best,
CountryCodeParser.extractCountryCode
should return an optional, as PhoneParser._findDestinationMetadata itself.I consciously stopped on as it is, not to spread the changes over the whole project.