Allow extending Money with custom currency provider #95
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Superseeds #94
This is an attempt to solve #30 and #61
First, we need to accept that the
Money
andCurrency
objects cannot be final. In reality, they take on different shapes and forms. The currentBrick\Money\Money
implementation is built around ISO 4217 currencies, but users are trying to adapt it for other purposes, like cryptocurrencies or historical currencies. The reason is simple: the underlying Brick\Money manipulation engine is extremely versatile and would work just as well with those alternative currency types. This is a valid and logical use case.Secondly, with the main methods for object creation being static, proper dependency injection to configure a global default behavior becomes impossible.
The quickest solution without a major refactor would be to introduce inheritance as an extension point. This allows users to provide custom currency providers tailored to their use cases. The library itself could leverage this to introduce new types of currencies, such as the historic ISO 4217 currencies discussed here: #93 (comment).
It uses inheritance as a point of extension to define the
CurrencyProvider
used and adapt the code base to rely on aCurrency
interface instead of the previousCurrency
(which was actuallyIsoCurrency
).The static logic for creating
Money
remains closely tied toIsoCurrencyProvider
to prevent a more extensive breaking change.This approach balances the need for those interested in distinguishing between
Money
andIsoMoney
, while allowing other users to continue usingMoney
as they have since the library's inception, without needing to address this distinction in their context.You can now do:
It has the following breaking changes:
Currency
has been renamed toIsoCurrency
to better reflect its role in representing ISO 4217 currenciesCurrency
is now an interface, withIsoCurrency
serving as its concrete implementation.Currency#getCurrencyCode()
is nowCurrency#getCode()
for clarityUnknownCurrencyException
has been renamed toUnknownIsoCurrencyException
to align with its specific use forIsoCurrency
typesISOCurrencyProvider
has been renamed toIsoCurrencyProvider
to adhere to the upcoming PSR rules for capitalization of abbreviationsPreviously, allowing
string|int
as currency necessitated objects to identify the corresponding IsoCurrency, creating a tight coupling with a specific IsoCurrencyProvider implementation and a mix of unwanted responsibility for the object. To move towards a more currency-agnostic architecture, it is now advised to resolve the currency beforehand.$currency
inCurrency#is()
has been refined to accept onlyCurrency
, removing support forstring|int
$currency
inCurrencyConverter#convert()
has been refined to accept onlyCurrency
, removing support forstring|int
$currency
inCurrencyConverter#convertToRational()
has been refined to accept onlyCurrency
, removing support forstring|int