Skip to content

Commit 7998ca1

Browse files
author
Jon Waldstein
committed
feature: add new param for including default codes
1 parent 978c0c3 commit 7998ca1

2 files changed

Lines changed: 243 additions & 4 deletions

File tree

src/Rules/Currency.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,15 @@ class Currency implements ValidationRule, ValidatesOnFrontEnd
1818
/**
1919
* @unreleased
2020
*/
21-
public function __construct(?array $currencyCodes = null)
21+
public function __construct(?array $currencyCodes = null, bool $includeDefaultCurrencyCodes = false)
2222
{
23-
$this->currencyCodes = $currencyCodes ?? self::currencyCodes();
23+
if (empty($currencyCodes)) {
24+
$this->currencyCodes = self::defaultCurrencyCodes();
25+
} elseif ($includeDefaultCurrencyCodes) {
26+
$this->currencyCodes = array_merge(self::defaultCurrencyCodes(), $currencyCodes);
27+
} else {
28+
$this->currencyCodes = $currencyCodes;
29+
}
2430
}
2531

2632
/**
@@ -40,7 +46,15 @@ public static function id(): string
4046
*/
4147
public static function fromString(string $options = null): ValidationRule
4248
{
43-
return new self();
49+
if (empty($options) || empty(trim($options))) {
50+
return new self();
51+
}
52+
53+
$parts = explode('|', $options, 2);
54+
$currencyCodes = explode(',', $parts[0]);
55+
$includeDefaults = isset($parts[1]) && strtolower(trim($parts[1])) === 'include_defaults';
56+
57+
return new static($currencyCodes, $includeDefaults);
4458
}
4559

4660
/**
@@ -83,7 +97,7 @@ public function __invoke($value, Closure $fail, string $key, array $values)
8397
*
8498
* @return string[]
8599
*/
86-
public static function currencyCodes(): array
100+
public static function defaultCurrencyCodes(): array
87101
{
88102
static $codes = null;
89103

tests/unit/Rules/CurrencyTest.php

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,231 @@ public function testCustomCurrencyCodesOverride()
4545
self::assertValidationRuleFailed($rule, 'EUR');
4646
}
4747

48+
/**
49+
* Test constructor with includeDefaultCurrencyCodes parameter.
50+
*
51+
* @since 1.1.0
52+
*/
53+
public function testConstructorWithIncludeDefaultCurrencyCodes()
54+
{
55+
// Test with custom codes and includeDefaultCurrencyCodes = true
56+
$customCodes = ['XYZ', 'ABC', 'DEF'];
57+
$rule = new Currency($customCodes, true);
58+
59+
// Custom codes should pass
60+
self::assertValidationRulePassed($rule, 'XYZ');
61+
self::assertValidationRulePassed($rule, 'ABC');
62+
self::assertValidationRulePassed($rule, 'def'); // case insensitive
63+
64+
// Standard codes should also pass when including defaults
65+
self::assertValidationRulePassed($rule, 'USD');
66+
self::assertValidationRulePassed($rule, 'EUR');
67+
self::assertValidationRulePassed($rule, 'JPY');
68+
69+
// Invalid codes should still fail
70+
self::assertValidationRuleFailed($rule, 'INVALID');
71+
self::assertValidationRuleFailed($rule, 'ZZZ');
72+
}
73+
74+
/**
75+
* Test constructor with includeDefaultCurrencyCodes = false (explicit).
76+
*
77+
* @since 1.1.0
78+
*/
79+
public function testConstructorWithIncludeDefaultCurrencyCodesFalse()
80+
{
81+
// Test with custom codes and includeDefaultCurrencyCodes = false (explicit)
82+
$customCodes = ['XYZ', 'ABC', 'DEF'];
83+
$rule = new Currency($customCodes, false);
84+
85+
// Custom codes should pass
86+
self::assertValidationRulePassed($rule, 'XYZ');
87+
self::assertValidationRulePassed($rule, 'ABC');
88+
self::assertValidationRulePassed($rule, 'def'); // case insensitive
89+
90+
// Standard codes should fail when not including defaults
91+
self::assertValidationRuleFailed($rule, 'USD');
92+
self::assertValidationRuleFailed($rule, 'EUR');
93+
self::assertValidationRuleFailed($rule, 'JPY');
94+
}
95+
96+
/**
97+
* Test constructor with empty custom codes and includeDefaultCurrencyCodes = true.
98+
*
99+
* @since 1.1.0
100+
*/
101+
public function testConstructorWithEmptyCustomCodesAndIncludeDefaults()
102+
{
103+
// Test with empty custom codes and includeDefaultCurrencyCodes = true
104+
$rule = new Currency([], true);
105+
106+
// Should behave like default constructor (only default codes)
107+
self::assertValidationRulePassed($rule, 'USD');
108+
self::assertValidationRulePassed($rule, 'EUR');
109+
self::assertValidationRuleFailed($rule, 'XYZ');
110+
}
111+
112+
/**
113+
* Test constructor with null custom codes and includeDefaultCurrencyCodes = true.
114+
*
115+
* @since 1.1.0
116+
*/
117+
public function testConstructorWithNullCustomCodesAndIncludeDefaults()
118+
{
119+
// Test with null custom codes and includeDefaultCurrencyCodes = true
120+
$rule = new Currency(null, true);
121+
122+
// Should behave like default constructor (only default codes)
123+
self::assertValidationRulePassed($rule, 'USD');
124+
self::assertValidationRulePassed($rule, 'EUR');
125+
self::assertValidationRuleFailed($rule, 'XYZ');
126+
}
127+
128+
/**
129+
* Test fromString method with basic functionality.
130+
*
131+
* @since 1.1.0
132+
*/
133+
public function testFromStringBasic()
134+
{
135+
// Test empty string returns default rule
136+
$rule = Currency::fromString('');
137+
self::assertValidationRulePassed($rule, 'USD');
138+
self::assertValidationRulePassed($rule, 'EUR');
139+
self::assertValidationRuleFailed($rule, 'XYZ');
140+
141+
// Test null returns default rule
142+
$rule = Currency::fromString(null);
143+
self::assertValidationRulePassed($rule, 'USD');
144+
self::assertValidationRulePassed($rule, 'EUR');
145+
self::assertValidationRuleFailed($rule, 'XYZ');
146+
147+
// Test whitespace only returns default rule
148+
$rule = Currency::fromString(' ');
149+
self::assertValidationRulePassed($rule, 'USD');
150+
self::assertValidationRulePassed($rule, 'EUR');
151+
self::assertValidationRuleFailed($rule, 'XYZ');
152+
}
153+
154+
/**
155+
* Test fromString method with custom currency codes only.
156+
*
157+
* @since 1.1.0
158+
*/
159+
public function testFromStringCustomCodesOnly()
160+
{
161+
// Test custom codes without include_defaults
162+
$rule = Currency::fromString('XYZ,ABC,DEF');
163+
164+
// Custom codes should pass
165+
self::assertValidationRulePassed($rule, 'XYZ');
166+
self::assertValidationRulePassed($rule, 'ABC');
167+
self::assertValidationRulePassed($rule, 'DEF');
168+
self::assertValidationRulePassed($rule, 'def'); // case insensitive
169+
170+
// Standard codes should fail
171+
self::assertValidationRuleFailed($rule, 'USD');
172+
self::assertValidationRuleFailed($rule, 'EUR');
173+
}
174+
175+
/**
176+
* Test fromString method with custom currency codes and include_defaults.
177+
*
178+
* @since 1.1.0
179+
*/
180+
public function testFromStringWithIncludeDefaults()
181+
{
182+
// Test custom codes with include_defaults
183+
$rule = Currency::fromString('XYZ,ABC,DEF|include_defaults');
184+
185+
// Custom codes should pass
186+
self::assertValidationRulePassed($rule, 'XYZ');
187+
self::assertValidationRulePassed($rule, 'ABC');
188+
self::assertValidationRulePassed($rule, 'DEF');
189+
self::assertValidationRulePassed($rule, 'def'); // case insensitive
190+
191+
// Standard codes should also pass
192+
self::assertValidationRulePassed($rule, 'USD');
193+
self::assertValidationRulePassed($rule, 'EUR');
194+
self::assertValidationRulePassed($rule, 'JPY');
195+
196+
// Invalid codes should still fail
197+
self::assertValidationRuleFailed($rule, 'INVALID');
198+
self::assertValidationRuleFailed($rule, 'ZZZ');
199+
}
200+
201+
/**
202+
* Test fromString method with various include_defaults formats.
203+
*
204+
* @since 1.1.0
205+
*/
206+
public function testFromStringIncludeDefaultsFormats()
207+
{
208+
// Test different case variations of include_defaults
209+
$variations = [
210+
'XYZ,ABC|include_defaults',
211+
'XYZ,ABC|INCLUDE_DEFAULTS',
212+
'XYZ,ABC|Include_Defaults',
213+
'XYZ,ABC| include_defaults ', // with spaces
214+
'XYZ,ABC| INCLUDE_DEFAULTS ', // with more spaces
215+
];
216+
217+
foreach ($variations as $variation) {
218+
$rule = Currency::fromString($variation);
219+
220+
// Should include both custom and default codes
221+
self::assertValidationRulePassed($rule, 'XYZ', "Failed for variation: $variation");
222+
self::assertValidationRulePassed($rule, 'USD', "Failed for variation: $variation");
223+
}
224+
}
225+
226+
/**
227+
* Test fromString method with invalid include_defaults format.
228+
*
229+
* @since 1.1.0
230+
*/
231+
public function testFromStringInvalidIncludeDefaultsFormat()
232+
{
233+
// Test invalid include_defaults format (should be treated as custom codes only)
234+
$rule = Currency::fromString('XYZ,ABC|invalid_flag');
235+
236+
// Custom codes should pass
237+
self::assertValidationRulePassed($rule, 'XYZ');
238+
self::assertValidationRulePassed($rule, 'ABC');
239+
240+
// Standard codes should fail (include_defaults not properly specified)
241+
self::assertValidationRuleFailed($rule, 'USD');
242+
self::assertValidationRuleFailed($rule, 'EUR');
243+
}
244+
245+
/**
246+
* Test fromString method edge cases.
247+
*
248+
* @since 1.1.0
249+
*/
250+
public function testFromStringEdgeCases()
251+
{
252+
// Test single currency code
253+
$rule = Currency::fromString('XYZ');
254+
self::assertValidationRulePassed($rule, 'XYZ');
255+
self::assertValidationRuleFailed($rule, 'USD');
256+
257+
// Test single currency code with include_defaults
258+
$rule = Currency::fromString('XYZ|include_defaults');
259+
self::assertValidationRulePassed($rule, 'XYZ');
260+
self::assertValidationRulePassed($rule, 'USD');
261+
262+
// Test empty custom codes with include_defaults
263+
$rule = Currency::fromString('|include_defaults');
264+
self::assertValidationRulePassed($rule, 'USD');
265+
self::assertValidationRuleFailed($rule, 'XYZ');
266+
267+
// Test only pipe with include_defaults
268+
$rule = Currency::fromString('|include_defaults');
269+
self::assertValidationRulePassed($rule, 'USD');
270+
self::assertValidationRuleFailed($rule, 'XYZ');
271+
}
272+
48273
/**
49274
* Test that obsolete currency codes no longer pass validation.
50275
*

0 commit comments

Comments
 (0)