Skip to content

Commit 3c95fc0

Browse files
author
Clément Le Provost
committed
Add support for a list of languages in the ignorePlurals query parameter
This change is similar to what was done for the `removeStopWords` parameter. WARNING: This change is not backward-compatible; there is nothing much we can do about it if we want to support the new values.
1 parent 1b5167b commit 3c95fc0

File tree

3 files changed

+101
-20
lines changed

3 files changed

+101
-20
lines changed

Source/Query.swift

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,49 @@ public class Query : NSObject, NSCopying {
309309
set { self["allowTyposOnNumericTokens"] = Query.buildBool(newValue) }
310310
}
311311

312-
/// If set to true, simple plural forms won’t be considered as typos (for example car/cars will be considered as
313-
/// equal).
314-
public var ignorePlurals: Bool? {
315-
get { return Query.parseBool(self["ignorePlurals"]) }
316-
set { self["ignorePlurals"] = Query.buildBool(newValue) }
312+
/// Applicable values for the `ignorePlurals` parameter.
313+
public enum IgnorePlurals: Equatable {
314+
/// Enable/disable plurals on all supported languages.
315+
case all(Bool)
316+
/// Enable plurals on a specific set of languages, identified by their ISO code.
317+
case selected([String])
318+
319+
// NOTE: Associated values disable automatic conformance to `Equatable`, so we have to implement it ourselves.
320+
static public func ==(lhs: IgnorePlurals, rhs: IgnorePlurals) -> Bool {
321+
switch (lhs, rhs) {
322+
case (let .all(lhsValue), let .all(rhsValue)): return lhsValue == rhsValue
323+
case (let .selected(lhsValue), let .selected(rhsValue)): return lhsValue == rhsValue
324+
default: return false
325+
}
326+
}
327+
}
328+
329+
/// Consider singular and plurals forms alike to be a match without typo. For example, "car" and "cars", or "foot"
330+
/// and "feet", will be considered equivalent. This parameter can be:
331+
///
332+
/// You may enable this option for all languages at once (`.all`) or for a specific subset (`.selected`).
333+
///
334+
public var ignorePlurals: IgnorePlurals? {
335+
get {
336+
let stringValue = self["ignorePlurals"]
337+
if let boolValue = Query.parseBool(stringValue) {
338+
return .all(boolValue)
339+
} else if let arrayValue = Query.parseStringArray(stringValue) {
340+
return .selected(arrayValue)
341+
} else {
342+
return nil
343+
}
344+
}
345+
set {
346+
if let newValue = newValue {
347+
switch newValue {
348+
case let .all(boolValue): self["ignorePlurals"] = Query.buildBool(boolValue)
349+
case let .selected(arrayValue): self["ignorePlurals"] = Query.buildStringArray(arrayValue)
350+
}
351+
} else {
352+
self["ignorePlurals"] = nil
353+
}
354+
}
317355
}
318356

319357
/// List of attributes you want to use for textual search (must be a subset of the `searchableAttributes` index setting).
@@ -1066,9 +1104,28 @@ public class Query : NSObject, NSCopying {
10661104
}
10671105

10681106
@objc(ignorePlurals)
1069-
public var z_objc_ignorePlurals: NSNumber? {
1070-
get { return Query.toNumber(self.ignorePlurals) }
1071-
set { self.ignorePlurals = newValue?.boolValue }
1107+
public var z_objc_ignorePlurals: Any? {
1108+
get {
1109+
if let value = ignorePlurals {
1110+
switch value {
1111+
case let .all(boolValue): return NSNumber(value: boolValue)
1112+
case let .selected(arrayValue): return arrayValue
1113+
}
1114+
} else {
1115+
return nil
1116+
}
1117+
}
1118+
set {
1119+
if let boolValue = newValue as? Bool {
1120+
ignorePlurals = .all(boolValue)
1121+
} else if let numberValue = newValue as? NSNumber {
1122+
ignorePlurals = .all(numberValue.boolValue)
1123+
} else if let arrayValue = newValue as? [String] {
1124+
ignorePlurals = .selected(arrayValue)
1125+
} else {
1126+
ignorePlurals = nil
1127+
}
1128+
}
10721129
}
10731130

10741131
@objc(advancedSyntax)

Tests/ObjectiveCBridging.m

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -348,11 +348,19 @@ - (void)test_ignorePlurals {
348348
Query* query1 = [Query new];
349349
XCTAssertNil(query1.ignorePlurals);
350350

351-
NSNumber* value = [NSNumber numberWithBool:YES];
352-
query1.ignorePlurals = value;
353-
XCTAssertEqualObjects(query1[@"ignorePlurals"], @"true");
354-
Query* query2 = [Query parse:[query1 build]];
355-
XCTAssertEqualObjects(query2.ignorePlurals, value);
351+
NSArray* VALUES = @[ [NSNumber numberWithBool:YES], [NSNumber numberWithBool:NO], @[ @"de", @"en", @"fr"] ];
352+
NSArray* RAW_VALUES = @[ @"true", @"false", @"de,en,fr" ];
353+
for (int i = 0; i < VALUES.count; ++i) {
354+
query1.ignorePlurals = VALUES[i];
355+
XCTAssertEqualObjects(query1[@"ignorePlurals"], RAW_VALUES[i]);
356+
Query* query2 = [Query parse:[query1 build]];
357+
XCTAssertEqualObjects(query2.ignorePlurals, VALUES[i]);
358+
}
359+
360+
// WARNING: There is no validation of ISO codes, so any string is interpreted as a single language.
361+
query1[@"ignorePlurals"] = @"invalid";
362+
XCTAssertNotNil(query1.ignorePlurals);
363+
XCTAssertEqual(1, ((NSArray*)query1.ignorePlurals).count);
356364
}
357365

358366
- (void)test_advancedSyntax {

Tests/QueryTests.swift

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,17 +150,33 @@ class QueryTests: XCTestCase {
150150
func test_ignorePlurals() {
151151
let query1 = Query()
152152
XCTAssertNil(query1.ignorePlurals)
153-
query1.ignorePlurals = true
154-
XCTAssertEqual(query1.ignorePlurals, true)
153+
154+
query1.ignorePlurals = .all(true)
155+
XCTAssertEqual(query1.ignorePlurals, .all(true))
155156
XCTAssertEqual(query1["ignorePlurals"], "true")
156-
let query2 = Query.parse(query1.build())
157-
XCTAssertEqual(query2.ignorePlurals, true)
157+
var query2 = Query.parse(query1.build())
158+
XCTAssertEqual(query2.ignorePlurals, .all(true))
158159

159-
query1.ignorePlurals = false
160-
XCTAssertEqual(query1.ignorePlurals, false)
160+
query1.ignorePlurals = .all(false)
161+
XCTAssertEqual(query1.ignorePlurals, .all(false))
161162
XCTAssertEqual(query1["ignorePlurals"], "false")
162163
let query3 = Query.parse(query1.build())
163-
XCTAssertEqual(query3.ignorePlurals, false)
164+
XCTAssertEqual(query3.ignorePlurals, .all(false))
165+
166+
let VALUE = ["de", "en", "fr"]
167+
query1.ignorePlurals = .selected(VALUE)
168+
XCTAssertEqual(query1.ignorePlurals, .selected(VALUE))
169+
XCTAssertEqual(query1["ignorePlurals"], "de,en,fr")
170+
query2 = Query.parse(query1.build())
171+
XCTAssertEqual(query2.ignorePlurals, .selected(VALUE))
172+
173+
// WARNING: There's no validation of ISO codes, so any string is interpreted as a single code.
174+
query1["ignorePlurals"] = "invalid"
175+
XCTAssertNotNil(query1.ignorePlurals)
176+
switch query1.ignorePlurals! {
177+
case let .selected(values): XCTAssertEqual(1, values.count)
178+
default: XCTFail()
179+
}
164180
}
165181

166182
func test_distinct() {

0 commit comments

Comments
 (0)