-
Notifications
You must be signed in to change notification settings - Fork 642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/address subdivisions event #13361
Conversation
Just testing this feature out in advance of the 4.5 release, got the 'County' included by adding It looks like the address format repository for the GB countryCode, returns New to the Craft 4 addressing logic, and understand that I can tweak via the Also not sure if I have misunderstood, but grabbing the format and then requesting the used fields, skips any craft events, is that by design or should they be called: // When called via the service the craft events are called:
Craft::$app->getAddresses()->getUsedFields('GB');
// If accessing them the format then they are not?
$format = Craft::$app->getAddresses()->getAddressFormatRepository()->get('GB');
$format->getUsedFields();
$format->getRequiredFields();
$format->getPostalCodePattern(); |
Hi @samhibberd ,
You should also register the
When you call It's also worth noting that in 4.5 you'll be able to create your own formatter thanks to this PR: #13242 |
Hi @i-just, thanks for the detail, all makes sense! So always going to be best running through the Craft service when building out our front end forms.
Already got this up and running, really useful! 4.5 getting close? Thanks! |
Not a problem 🙂 4.5 is not too far away, but we don't have a firm date. |
Hey @i-just, not sure if i'm again missing some obvious stuff here, but struggling to get my head around this PR, the main issue we have is that we are migrating over 130k+ addresses of which most are UK addresses and have a County (assuming maps to an administrativeArea) and an Address Line 3 (which is now a custom field). This PR allows us to identify the Is it a case that we need to completely rewrite custom formatter logic to just build output an address string in the same format that craft requires) but by using our own logic and values that are set on the $address for uk addresses only. public function format(AddressInterface $address, array $options = []): string
{
if($address->getCountryCode() == 'GB')
{
return $address->addressLine1 . $address->administrativeArea;
}
return parent::format($address, $options);
} It feels like we absolutely need this PR, as County is always asked for in the UK, but the complexities to get it setup are a creating a bit of a barrier, over here anyway. Also not sure if these are bugs or further configurations, but when editing in the cp:
Screen.Recording.2023-07-26.at.16.06.25.mov |
Thanks @i-just, I think perhaps a little bit more reading up required, felt like it was getting rather complex to cover what i thought should be pretty simple.
Sorry, my code wasn't clear, I was just providing a basic example of how I might format the address directly not using the logic / methods from the default formatter. I did a bit more reading up and ended up being able to use the <?php
namespace modules\findarace\formatters;
use craft\helpers\Html;
use CommerceGuys\Addressing\AddressInterface;
use CommerceGuys\Addressing\AddressFormat\AddressFormat;
use CommerceGuys\Addressing\Locale;
class AddressFormatter extends \CommerceGuys\Addressing\Formatter\DefaultFormatter
{
protected $defaultOptions = [
'locale' => 'en',
'html' => true,
'html_tag' => 'p',
'html_attributes' => [],
];
public function format(AddressInterface $address, array $options = []): string
{
$this->validateOptions($options);
$options = array_replace($this->defaultOptions, $options);
$countryCode = $address->getCountryCode();
$addressFormat = $this->addressFormatRepository->get($countryCode);
// Add the country to the bottom or the top of the format string,
// depending on whether the format is minor-to-major or major-to-minor.
if (Locale::matchCandidates($addressFormat->getLocale(), $address->getLocale())) {
$formatString = '%country' . "\n" . $addressFormat->getLocalFormat();
} else {
$formatString = $addressFormat->getFormat() . "\n" . '%country';
}
// Include addressLine3 for al addresses
$formatString = str_replace("%locality\n", "%locality\n%administrativeArea\n", $formatString);
// Include administrativeArea for GB addresses only
if($countryCode == 'GB') {
$formatString = str_replace("%addressLine2\n", "%addressLine2\n%addressLine3\n", $formatString);
}
$view = $this->buildView($address, $addressFormat, $options);
$view = $this->renderView($view);
// Insert the rendered elements into the format string.
$replacements = [];
foreach ($view as $key => $element) {
$replacements['%' . $key] = $element;
}
$output = strtr($formatString, $replacements);
$output = $this->cleanupOutput($output);
if (!empty($options['html'])) {
$output = nl2br($output, false);
// Add the HTML wrapper element.
$output = Html::tag($options['html_tag'], $output, $options['html_attributes']);
}
return $output;
}
protected function getValues(AddressInterface $address, AddressFormat $addressFormat): array
{
$values = parent::getValues($address, $addressFormat);
$values['addressLine3'] = $address->addressLine3 ?: null;
if($address->getCountryCode() == 'GB') {
$values['administrativeArea'] = $address->administrativeArea ?: null;
}
return $values;
}
protected function buildView(AddressInterface $address, AddressFormat $addressFormat, array $options): array
{
$view = parent::buildView($address, $addressFormat, $options);
$view['addressLine3'] = [
'html' => $options['html'],
'html_tag' => 'span',
'html_attributes' => ['class' => 'address-line3'],
'value' => $address->addressLine3 ?: null,
];
if($address->getCountryCode() == 'GB') {
$view['administrativeArea'] = [
'html' => $options['html'],
'html_tag' => 'span',
'html_attributes' => ['class' => 'administrative-area'],
'value' => $address->administrativeArea ?: null,
];
}
return $view;
}
}
|
Hi @samhibberd, a quick update to clarify that the Here's how the locality/administrativeArea funtionality works on Screen.Recording.2023-07-27.at.11.33.03.mov |
Description
This PR adds:
commerceguys/addressing
subdivision data,Calls to
Craft::$app->getAddresses()->getSubdivisionRepository()->getList()
are now going throughcommerceguys/addressing
, and our method. Afterwards aEVENT_DEFINE_ADDRESS_SUBDIVISIONS
event is triggered to allow developers to manipulate the data even further.Taking
GB
as an example, the counties data is now shipped with Craft, however it's still up to the developer if they want to show theAdministativeArea
field in the Control Panel. If yes, you still need to use theEVENT_DEFINE_USED_FIELDS
event, and you can change the label of the field viaEVENT_DEFINE_FIELD_LABEL
.To manipulate the subdivisions data, you can now use the
EVENT_DEFINE_ADDRESS_SUBDIVISIONS
, like so:The data added via the new
addresses/SubdivisionRepository
and via theEVENT_DEFINE_ADDRESS_SUBDIVISIONS
is then used consistently throughout the Control Panel.e.g. when adding Address for a User
when using Administrative Area Address Condition (e.g. in a Shipping Zone in Commerce):
Related issues
#13101
#11788
#13345