diff --git a/CHANGELOG-WIP.md b/CHANGELOG-WIP.md
index e39a4ba7a24..3d39f002aea 100644
--- a/CHANGELOG-WIP.md
+++ b/CHANGELOG-WIP.md
@@ -12,6 +12,7 @@
- Entries can now have multiple authors. ([#12380](https://github.com/craftcms/cms/pull/12380))
- The “Save as a new entry” action is now available to all users with the “Create entries” permission, and will create a new unpublished draft rather than a fully-saved entry. ([#9577](https://github.com/craftcms/cms/issues/9577), [#10244](https://github.com/craftcms/cms/discussions/10244))
- Entry conditions can now have a “Matrix field” rule. ([#13794](https://github.com/craftcms/cms/discussions/13794))
+- Money field condition rules now use money inputs. ([#14148](https://github.com/craftcms/cms/pull/14148))
- Selected elements within relational fields now include a context menu with “View in a new tab”, “Edit”, and “Remove” options.
- Selected elements within relational fields now include a dedicated drag handle.
- Selected assets within Assets fields no longer open the file preview modal when their thumbnail is clicked on. The “Preview file” quick action, or the Shift + Spacebar keyboard shortcut, can be used instead.
@@ -211,8 +212,14 @@
- Added `craft\fields\Matrix::getSupportedSitesForElement()`.
- Added `craft\fields\Matrix::setEntryTypes()`.
- Added `craft\fields\Matrix::supportedSiteIds()`.
+- Added `craft\fields\Money::currencyLabel()`.
+- Added `craft\fields\Money::currencyLabel()`.
+- Added `craft\fields\Money::subunits()`.
+- Added `craft\fields\Money::subunits()`.
- Added `craft\fields\conditions\FieldConditionRuleTrait::fieldInstances()`.
- Added `craft\fields\conditions\FieldConditionRuleTrait::setLayoutElementUid()`.
+- Added `craft\fields\conditions\MoneyFieldConditionRule`.
+- Added `craft\fields\conditions\MoneyFieldConditionRule`.
- Added `craft\helpers\App::isWindows()`.
- Added `craft\helpers\App::silence()`.
- Added `craft\helpers\ArrayHelper::lastValue()`.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1f648f64aee..12273e1361b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,11 @@
## Unreleased
+- Money field condition rules now use money inputs. ([#14148](https://github.com/craftcms/cms/pull/14148))
- Improved the accessibility of element indexes. ([#14120](https://github.com/craftcms/cms/pull/14120))
+- Added `craft\fields\Money::currencyLabel()`.
+- Added `craft\fields\Money::subunits()`.
+- Added `craft\fields\conditions\MoneyFieldConditionRule`.
- `craft\base\BaseFsInterface::renameFile()` and `copyFile()` now have a `$config` argument. ([#14147](https://github.com/craftcms/cms/pull/14147))
- Fixed a bug where `craft\helpers\Db::prepareValueForDb()` wasn’t converting objects to arrays for JSON columns.
- Fixed a bug where Checkboxes, Multi-select, Dropdown, and Radio Buttons fields weren’t displaying `0` option labels within element indexes. ([#14127](https://github.com/craftcms/cms/issues/14127))
diff --git a/src/fields/Money.php b/src/fields/Money.php
index ca36ac63207..ab257b34b8f 100644
--- a/src/fields/Money.php
+++ b/src/fields/Money.php
@@ -12,7 +12,7 @@
use craft\base\Field;
use craft\base\InlineEditableFieldInterface;
use craft\base\SortableFieldInterface;
-use craft\fields\conditions\NumberFieldConditionRule;
+use craft\fields\conditions\MoneyFieldConditionRule;
use craft\gql\types\Money as MoneyType;
use craft\helpers\Cp;
use craft\helpers\Db;
@@ -144,7 +144,7 @@ public function getSettingsHtml(): ?string
return Craft::$app->getView()->renderTemplate('_components/fieldtypes/Money/settings.twig', [
'field' => $this,
'currencies' => $this->_isoCurrencies,
- 'subUnits' => $this->_isoCurrencies->subunitFor(new Currency($this->currency)),
+ 'subUnits' => $this->subunits(),
]);
}
@@ -257,30 +257,23 @@ protected function inputHtml(mixed $value, ?ElementInterface $element, bool $inl
$decimals = null;
if ($value instanceof MoneyLibrary) {
- $decimals = $this->_isoCurrencies->subunitFor($value->getCurrency());
+ $decimals = $this->subunits($value->getCurrency());
$value = MoneyHelper::toNumber($value);
}
- if ($decimals === null) {
- $decimals = $this->_isoCurrencies->subunitFor(new Currency($this->currency));
- }
+ $decimals = $decimals ?? $this->subunits();
$defaultValue = null;
if (isset($this->defaultValue)) {
$defaultValue = MoneyHelper::toNumber(new MoneyLibrary($this->defaultValue, new Currency($this->currency)));
}
- $currencyLabel = Craft::t('app', '({currencyCode}) {currencySymbol}', [
- 'currencyCode' => $this->currency,
- 'currencySymbol' => Craft::$app->getFormattingLocale()->getCurrencySymbol($this->currency),
- ]);
-
return Cp::moneyInputHtml([
'id' => $this->getInputId(),
'name' => $this->handle,
'size' => $this->size,
'currency' => $this->currency,
- 'currencyLabel' => $currencyLabel,
+ 'currencyLabel' => $this->currencyLabel(),
'showCurrency' => $this->showCurrency,
'decimals' => $decimals,
'defaultValue' => $defaultValue,
@@ -290,6 +283,29 @@ protected function inputHtml(mixed $value, ?ElementInterface $element, bool $inl
]);
}
+ /**
+ * @return string
+ * @since 5.0.0
+ */
+ public function currencyLabel(): string
+ {
+ return Craft::t('app', '({currencyCode}) {currencySymbol}', [
+ 'currencyCode' => $this->currency,
+ 'currencySymbol' => Craft::$app->getFormattingLocale()->getCurrencySymbol($this->currency),
+ ]);
+ }
+
+ /**
+ * @param Currency|null $currency
+ * @return int
+ * @since 5.0.0
+ */
+ public function subunits(?Currency $currency = null): int
+ {
+ $currency = $currency ?? new Currency($this->currency);
+ return $this->_isoCurrencies->subunitFor($currency);
+ }
+
/**
* @inheritdoc
*/
@@ -305,7 +321,7 @@ public function getElementValidationRules(): array
*/
public function getElementConditionRuleType(): array|string|null
{
- return NumberFieldConditionRule::class;
+ return MoneyFieldConditionRule::class;
}
/**
diff --git a/src/fields/conditions/MoneyFieldConditionRule.php b/src/fields/conditions/MoneyFieldConditionRule.php
new file mode 100644
index 00000000000..976afc5f3c8
--- /dev/null
+++ b/src/fields/conditions/MoneyFieldConditionRule.php
@@ -0,0 +1,136 @@
+
+ * @since 5.0.0
+ */
+class MoneyFieldConditionRule extends BaseNumberConditionRule implements FieldConditionRuleInterface
+{
+ use FieldConditionRuleTrait;
+
+ /**
+ * @inheritdoc
+ */
+ public function setAttributes($values, $safeOnly = true): void
+ {
+ // Hold setting of the value attribute until we have all the info we need
+ if (isset($values['value']) && is_array($values['value'])) {
+ /** @var array $value */
+ $value = ArrayHelper::remove($values, 'value');
+ }
+
+ if (isset($values['maxValue']) && is_array($values['maxValue'])) {
+ /** @var array $maxValue */
+ $maxValue = ArrayHelper::remove($values, 'maxValue');
+ }
+
+ parent::setAttributes($values, $safeOnly);
+
+ /** @var Money $field */
+ $field = $this->field();
+
+ if (isset($value) && isset($this->_fieldUid)) {
+ if (!isset($value['currency'])) {
+ $value['currency'] = $field->currency;
+ }
+ $this->value = MoneyHelper::toDecimal(MoneyHelper::toMoney($value));
+ }
+
+ if (isset($maxValue) && isset($this->_fieldUid)) {
+ if (!isset($maxValue['currency'])) {
+ $maxValue['currency'] = $field->currency;
+ }
+ $this->maxValue = MoneyHelper::toDecimal(MoneyHelper::toMoney($maxValue));
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function inputHtml(): string
+ {
+ // don't show the value input if the condition checks for empty/notempty
+ if ($this->operator === self::OPERATOR_EMPTY || $this->operator === self::OPERATOR_NOT_EMPTY) {
+ return '';
+ }
+
+ if ($this->operator === self::OPERATOR_BETWEEN) {
+ return Html::tag('div',
+ Html::hiddenLabel(Craft::t('app', 'Min Value'), 'min') .
+ // Min value (value) input
+ Cp::moneyInputHtml($this->inputOptions()) .
+ Html::tag('span', Craft::t('app', 'and')) .
+ Html::hiddenLabel(Craft::t('app', 'Max Value'), 'max') .
+ // Max value input
+ Cp::moneyInputHtml(array_merge(
+ $this->inputOptions(),
+ ['id' => 'maxValue', 'name' => 'maxValue', 'value' => $this->maxValue]
+ )) .
+ Html::tag('span', Craft::t('app', 'The values are matched inclusively.'), ['class' => 'info']),
+ ['class' => 'flex flex-center']
+ );
+ }
+
+ return Cp::moneyInputHtml($this->inputOptions());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function inputOptions(): array
+ {
+ /** @var Money $field */
+ $field = $this->field();
+ $defaultValue = null;
+ if ($field->defaultValue !== null) {
+ $defaultValue = MoneyHelper::toNumber(new MoneyLibrary($field->defaultValue, new Currency($field->currency)));
+ }
+
+ return [
+ 'type' => 'text',
+ 'id' => 'value',
+ 'name' => 'value',
+ 'value' => $this->value,
+ 'autocomplete' => false,
+ 'currency' => $field->currency,
+ 'currencyLabel' => $field->currencyLabel(),
+ 'showCurrency' => $field->showCurrency,
+ 'decimals' => $field->subunits(),
+ 'defaultValue' => $defaultValue,
+ 'describedBy' => $field->describedBy,
+ 'field' => $field,
+ 'showClear' => false,
+ ];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function elementQueryParam(): ?string
+ {
+ return $this->paramValue();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function matchFieldValue($value): bool
+ {
+ /** @var int|float|null $value */
+ return $this->matchValue($value);
+ }
+}