Skip to content

Commit

Permalink
comply with libphonenumber's mainCountryForCode attribute when format…
Browse files Browse the repository at this point in the history
…ting numbers (#75)

* comply with libphonenumber's mainCountryForCode attribute when formatting numbers

see:
https://github.com/google/libphonenumber/blob/55716be400990f6542112323134cc1abc58abc2e/making-metadata-changes.md?plain=1#L34

Fixes: #74

* add a canadian phone number test
  • Loading branch information
fpbouchard authored Sep 27, 2024
1 parent fe47ebe commit 5074801
Show file tree
Hide file tree
Showing 8 changed files with 6,336 additions and 5,757 deletions.
11,990 changes: 6,244 additions & 5,746 deletions lib/src/metadata/generated/metadata_formats_by_iso_code.dart

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions lib/src/metadata/metadata_finder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,24 @@ abstract class MetadataFinder {
}

static PhoneMetadataFormats findMetadataFormatsForIsoCode(IsoCode isoCode) {
final metadata = metadataFormatsByIsoCode[isoCode];
var metadata = metadataFormatsByIsoCode[isoCode];
if (metadata is PhoneMetadataFormatReferenceDefinition) {
metadata = metadataFormatsByIsoCode[metadata.referenceIsoCode];
}
if (metadata == null) {
throw PhoneNumberException(
code: Code.invalidIsoCode,
description: 'isoCode "$isoCode" not found',
);
}
return metadata;
if (metadata is! PhoneMetadataFormatListDefinition) {
throw PhoneNumberException(
code: Code.invalidIsoCode,
description:
'isoCode "$isoCode" reference not a format list: $metadata',
);
}
return metadata.formats;
}

/// expects normalized countryCode
Expand Down
29 changes: 29 additions & 0 deletions lib/src/metadata/models/phone_metadata_formats.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
import 'dart:convert';

import '../../iso_codes/iso_code.dart';

typedef PhoneMetadataFormats = List<PhoneMetadataFormat>;

abstract class PhoneMetadataFormatDefinition {}

class PhoneMetadataFormatReferenceDefinition
implements PhoneMetadataFormatDefinition {
final IsoCode referenceIsoCode;

const PhoneMetadataFormatReferenceDefinition({
required this.referenceIsoCode,
});
}

class PhoneMetadataFormatListDefinition
implements PhoneMetadataFormatDefinition {
final PhoneMetadataFormats formats;

const PhoneMetadataFormatListDefinition({
required this.formats,
});

factory PhoneMetadataFormatListDefinition.fromMap(Map<String, dynamic> map) {
return PhoneMetadataFormatListDefinition(
formats: List<PhoneMetadataFormat>.from(
map['formats']?.map((x) => PhoneMetadataFormat.fromMap(x))),
);
}
}

class PhoneMetadataFormat {
final String pattern;
final String? nationalPrefixFormattingRule;
Expand Down
25 changes: 19 additions & 6 deletions resources/data_sources/read_metadata.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,28 @@ Future<Map<IsoCode, PhoneMetadataLengths>> getMetadataLengths() async {
PhoneMetadataLengths.fromMap(value['lengths'])));
}

Future<Map<IsoCode, PhoneMetadataFormats>> getMetadataFormats() async {
Future<Map<IsoCode, PhoneMetadataFormatDefinition>> getMetadataFormats() async {
final info = await readMetadataJson();
final referencesByCountryCode = <String, IsoCode>{};
info.forEach((key, value) {
if (value['isMainCountryForDialCode']) {
referencesByCountryCode[value['countryCode']] =
IsoCode.values.byName(key.toUpperCase());
}
});
return info.map((key, value) {
PhoneMetadataFormats converted;
converted = (value['formats'] as List)
.map((v) => PhoneMetadataFormat.fromMap(v))
.toList();
PhoneMetadataFormatDefinition formatDefinition;
String countryCode = value['countryCode'];
bool isMainCountryForDialCode = value['isMainCountryForDialCode'];
if (!isMainCountryForDialCode &&
referencesByCountryCode.containsKey(countryCode)) {
formatDefinition = PhoneMetadataFormatReferenceDefinition(
referenceIsoCode: referencesByCountryCode[countryCode]!);
} else {
formatDefinition = PhoneMetadataFormatListDefinition.fromMap(value);
}

return MapEntry(IsoCode.values.byName(key.toUpperCase()), converted);
return MapEntry(IsoCode.values.byName(key.toUpperCase()), formatDefinition);
});
}

Expand Down
7 changes: 4 additions & 3 deletions resources/generate_files.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,14 @@ Future writeLenghtsMapFile(Map<IsoCode, PhoneMetadataLengths> metadata) async {
await file.writeAsString(content);
}

Future writeFormatsMapFile(Map<IsoCode, PhoneMetadataFormats> metadata) async {
Future writeFormatsMapFile(
Map<IsoCode, PhoneMetadataFormatDefinition> metadata) async {
var content = '$isoCodeImport'
'import "../models/phone_metadata_formats.dart";'
'const metadataFormatsByIsoCode = <IsoCode, PhoneMetadataFormats>{%%};';
'const metadataFormatsByIsoCode = <IsoCode, PhoneMetadataFormatDefinition>{%%};';
var body = '';
metadata.forEach((key, value) {
body += '$key: [${(value).map((f) => encodeFormats(f)).join(',')}],';
body += '$key: ${encodeFormatDefinition(value)},';
});
content = content.replaceFirst('%%', body);
final file = await File('$baseFolder/metadata_formats_by_iso_code.dart')
Expand Down
13 changes: 13 additions & 0 deletions resources/utils/phone_metadata_encoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@ String encodeLengths(PhoneMetadataLengths lengths) {
)''';
}

String encodeFormatDefinition(PhoneMetadataFormatDefinition definition) {
if (definition is PhoneMetadataFormatReferenceDefinition) {
return '''PhoneMetadataFormatReferenceDefinition(
referenceIsoCode: ${definition.referenceIsoCode},
)''';
} else if (definition is PhoneMetadataFormatListDefinition) {
return '''PhoneMetadataFormatListDefinition(
formats: [${definition.formats.map(encodeFormats).join(', ')}],
)''';
}
throw ArgumentError('Unknown definition type: $definition');
}

String encodeFormats(PhoneMetadataFormat formats) {
return '''PhoneMetadataFormat(
pattern: ${_enc(formats.pattern)},
Expand Down
6 changes: 6 additions & 0 deletions test/internal/_metadata_finder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ void main() {
}
});

test('should get formats metadata for iso code going through references',
() {
expect(MetadataFinder.findMetadataFormatsForIsoCode(IsoCode.CA),
equals(MetadataFinder.findMetadataFormatsForIsoCode(IsoCode.US)));
});

test('should get metadata for country calling code', () {
expect(MetadataFinder.findMetadataForCountryCode('33', '123456')?.isoCode,
equals(IsoCode.FR));
Expand Down
9 changes: 9 additions & 0 deletions test/phone_number_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,15 @@ void main() {
expect(format(testNumber), equals('6 89 55 55 5'));
testNumber = '689555555';
});

test('should format through a format reference', () {
String format(String phoneNumber) =>
PhoneNumber.parse(phoneNumber, destinationCountry: IsoCode.CA)
.formatNsn(isoCode: IsoCode.CA);

var testNumber = '4185551212';
expect(format(testNumber), equals('(418) 555-1212'));
});
});

group('range', () {
Expand Down

0 comments on commit 5074801

Please sign in to comment.