Skip to content

Commit

Permalink
feat: 956 - added product owner fields (openfoodfacts#961)
Browse files Browse the repository at this point in the history
* feat: 956 - added product owner fields

New file:
* `owner_field.dart`: Helper class to compute the Product.ownerFields tags.

Impacted files:
* `api_get_product_test.dart`: added a test for owner fields
* `openfoodfacts.dart`: added new class `OwnerField`
* `product.dart`: added field `ownerFields` and method `getOwnerFieldTimestamp`
* `product.g.dart`: generated
* `product_fields.dart`: refactored around localized product fields

* Unrelated unit test minor fix
  • Loading branch information
monsieurtanuki authored Aug 12, 2024
1 parent 9296ce6 commit bd3202b
Show file tree
Hide file tree
Showing 6 changed files with 364 additions and 45 deletions.
1 change: 1 addition & 0 deletions lib/openfoodfacts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export 'src/model/old_product_result.dart';
export 'src/model/ordered_nutrient.dart';
export 'src/model/ordered_nutrients.dart';
export 'src/model/origins_of_ingredients.dart';
export 'src/model/owner_field.dart';
export 'src/model/packaging.dart';
export 'src/model/parameter/allergens_parameter.dart';
export 'src/model/parameter/barcode_parameter.dart';
Expand Down
25 changes: 25 additions & 0 deletions lib/src/model/owner_field.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import '../utils/language_helper.dart';
import '../utils/product_fields.dart';
import 'nutrient.dart';
import 'off_tagged.dart';

/// Helper class to compute the Product.ownerFields tags.
class OwnerField implements OffTagged {
const OwnerField.raw(this.offTag);

OwnerField.nutrient(final Nutrient nutrient) : this.raw(nutrient.offTag);

factory OwnerField.productField(
final ProductField productField,
final OpenFoodFactsLanguage language,
) {
final ProductField? inLanguages = productField.inLanguages;
if (inLanguages == null) {
return OwnerField.raw(productField.offTag);
}
return OwnerField.raw('${inLanguages.offTag}${language.offTag}');
}

@override
final String offTag;
}
30 changes: 27 additions & 3 deletions lib/src/model/product.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'ingredients_analysis_tags.dart';
import 'knowledge_panels.dart';
import 'nutrient_levels.dart';
import 'nutriments.dart';
import 'owner_field.dart';
import 'product_image.dart';
import 'product_packaging.dart';
import '../interface/json_object.dart';
Expand Down Expand Up @@ -562,10 +563,19 @@ class Product extends JsonObject {
)
bool? obsolete;

/// Timestamps of owner_fields, in seconds.
///
/// Typically used to say "Was that field set by the owner?".
/// Read-only.
/// See also [getOwnerFieldTimestamp].
@JsonKey(name: 'owner_fields', includeIfNull: false)
Map<String, int>? ownerFields;

/// Expiration date / best before. Just a string, no format control.
@JsonKey(name: 'expiration_date', includeIfNull: false)
String? expirationDate;

// TODO(monsieurtanuki): remove all the "this" constructor fields, except maybe "barcode"
Product(
{this.barcode,
this.productName,
Expand Down Expand Up @@ -766,7 +776,7 @@ class Product extends JsonObject {
result.imagesFreshnessInLanguages![language] = values;
return;
default:
if (fieldsInLanguages.contains(productField)) {
if (productField.isInLanguages) {
throw Exception('Unhandled in-languages case for $productField');
}
}
Expand Down Expand Up @@ -800,7 +810,10 @@ class Product extends JsonObject {
// We store those values in a more structured maps like
// [productNameInLanguages].

ProductField? productField = extractProductField(key, fieldsAllLanguages);
ProductField? productField = extractProductField(
key,
ProductField.getAllLanguagesList(),
);
if (productField != null) {
final Map<OpenFoodFactsLanguage, String>? localized =
_getLocalizedStrings(json[key]);
Expand All @@ -813,7 +826,10 @@ class Product extends JsonObject {
continue;
}

productField = extractProductField(key, fieldsInLanguages);
productField = extractProductField(
key,
ProductField.getInLanguagesList(),
);
if (productField != null) {
final OpenFoodFactsLanguage language =
_langFrom(key, productField.offTag);
Expand Down Expand Up @@ -1073,4 +1089,12 @@ class Product extends JsonObject {
// quantity: put non breaking spaces between numbers and units
return '$productNameBrand$separator${quantity!.replaceAll(' ', '\u{00A0}')}';
}

/// Returns the timestamp (in seconds) of the owner field.
///
/// Typically used to check if the field value was set by the product owner
/// (if the timestamp is not null), which means that the user cannot set a
/// value.
int? getOwnerFieldTimestamp(final OwnerField ownerField) =>
ownerFields?[ownerField.offTag];
}
4 changes: 4 additions & 0 deletions lib/src/model/product.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit bd3202b

Please sign in to comment.