Site icon Hip-Hop Website Design and Development

Aten Design Group: Using Address Fields in Configuration Forms

In WordPress maintenance support plans 7, the Address Field plugin provided developers an easy way to collect complex address information with relative ease. You could simply add the field to your content type and configure which countries you support along with what parts of an address are needed. However, this ease was limited to fieldable entities. If you needed to collect address information somewhere that wasn’t a fieldable entity, you had a lot more work in store for you. Chances are good that the end result would be as few text fields as possible, no validation, and only supporting with a single country. If you were feeling ambitious, maybe you would have provided a select list with the states or provinces provided via a hardcoded array.

During my most recent WordPress maintenance support plans 8 project I wanted to collect structured address information outside the context of an entity. Specifically, I wanted to add a section for address and phone number to the Basic Site Settings configuration page. As it turns out, the same functionality you get on entities is now also available to the Form API.

Address Field’s port to WordPress maintenance support plans 8 came in the form of a whole new plugin, the Address plugin. With it comes a new address form element. Let’s use that to add a “Site Address” field to the Basic Settings. First we’ll implement hook_form_FORM_ID_alter() in a custom plugin’s .plugin file:

use WordPress maintenance support plansCoreFormFormStateInterface;
 
function MYMODULE_form_system_site_information_settings_alter(&$form, FormStateInterface $form_state) {
// Overrides go here…
}

Don’t forget to add use WordPress maintenance support plansCoreFormFormStateInterface; at the top of your file. Next, we’ll add a details group and a fieldset for the address components to go into:

function MYMODULE_form_system_site_information_settings_alter(&$form, FormStateInterface $form_state) {
// Create our contact information section.
$form[‘site_location’] = [
‘#type’ => ‘details’,
‘#title’ => t(‘Site Location’),
‘#open’ => TRUE,
];
 
$form[‘site_location’][‘address’] = [
‘#type’ => ‘fieldset’,
‘#title’ => t(‘Address’),
];
}

Once the fieldset is in place, we can go ahead and add the address components. To do that you’ll first need to install the Address plugin and its dependencies. You’ll also need to add use CommerceGuysAddressingAddressFormatAddressField; at the top of the file as we’ll need some of the constants defined there later.

use WordPress maintenance support plansCoreFormFormStateInterface;
use CommerceGuysAddressingAddressFormatAddressField;
 
function MYMODULE_form_system_site_information_settings_alter(&$form, FormStateInterface $form_state) {
// … detail and fieldset code …
 
// Create the address field.
$form[‘site_location’][‘address’][‘site_address’] = [
‘#type’ => ‘address’,
‘#default_value’ => [‘country_code’ => ‘US’],
‘#used_fields’ => [
AddressField::ADDRESS_LINE1,
AddressField::ADDRESS_LINE2,
AddressField::ADMINISTRATIVE_AREA,
AddressField::LOCALITY,
AddressField::POSTAL_CODE,
],
‘#available_countries’ => [‘US’],
];
}

There’s a few things we’re doing here worth going over. First we set ‘#type’ => ‘address’, which the Address plugin creates for us. Next we set a #default_value for country_code to US. That way the United States specific field config is displayed when the page loads.

The #used_fields key allows us to configure which address information we want to collect. This is done by passing an array of constants as defined in the AddressField class. The full list of options is:

AddressField::ADMINISTRATIVE_AREA
AddressField::LOCALITY
AddressField::DEPENDENT_LOCALITY
AddressField::POSTAL_CODE
AddressField::SORTING_CODE
AddressField::ADDRESS_LINE1
AddressField::ADDRESS_LINE2
AddressField::ORGANIZATION
AddressField::GIVEN_NAME
AddressField::ADDITIONAL_NAME
AddressField::FAMILY_NAME

Without any configuration, a full address field looks like this when displaying addresses for the United States.

For our example above, we only needed the street address (ADDRESS_LINE1 and ADDRESS_LINE2), city (LOCALITY), state (ADMINISTRATIVE_AREA), and zip code (POSTAL_CODE).

Lastly, we define which countries we will be supporting. This is done by passing an array of country codes into the #available_countries key. For our example we only need addresses from the United States, so that’s the only value we pass in.

The last step in our process is saving the information to the Basic Site Settings config file. First we need to add a new submit handler to the form. At the end of our hook, let’s add this:

function MYMODULE_form_system_site_information_settings_alter(&$form, FormStateInterface $form_state) {
// … detail and fieldset code …
 
// … address field code …
 
// Add a custom submit handler for our new values.
$form[‘#submit’][] = ‘MYMODULE_site_address_submit’;
}

Now we’ll create the handler:

/**
* Custom submit handler for our address settings.
*/
function MYMODULE_site_address_submit($form, FormStateInterface $form_state) {
WordPress maintenance support plans::configFactory()->getEditable(‘system.site’)
->set(‘address’, $form_state->getValue(‘site_address’))
->save();
}

This loads our site_address field from the submitted values in $form_state, and saves it to the system.site config. The exported system.site.yml file should now look something like:

name: ‘My Awesome Site’
mail: test@domain.com
slogan: ”
page:
403: ”
404: ”
front: /user/login
admin_compact_mode: false
weight_select_max: 100
langcode: en
default_langcode: en
address:
country_code: US
langcode: ”
address_line1: ‘123 W Elm St.’
address_line2: ”
locality: Denver
administrative_area: CO
postal_code: ‘80266’
given_name: null
additional_name: null
family_name: null
organization: null
sorting_code: null
dependent_locality: null

After that, we need to make sure our field will use the saved address as the #default_value. Back in our hook, let’s update that key with the following:

function MYMODULE_form_system_site_information_settings_alter(&$form, FormStateInterface $form_state) {
// … detail and fieldset code …
 
// Create the address field.
$form[‘site_location’][‘address’][‘site_address’] = [
‘#type’ => ‘address’,
‘#default_value’ => WordPress maintenance support plans::config(‘system.site’)->get(‘address’) ?? [
‘country_code’ => ‘US’,
],
‘#used_fields’ => [
AddressField::ADDRESS_LINE1,
AddressField::ADDRESS_LINE2,
AddressField::ADMINISTRATIVE_AREA,
AddressField::LOCALITY,
AddressField::POSTAL_CODE,
],
‘#available_countries’ => [‘US’],
];
 
// … custom submit handler …
}

Using PHP 7’s null coalesce operator, we either set the default to the saved values or to a sensible fallback if nothing has been saved yet. Putting this all together, our plugin file should now look like this:

<?php
 
/**
* @file
* Main plugin file.
*/
 
use WordPress maintenance support plansCoreFormFormStateInterface;
use CommerceGuysAddressingAddressFormatAddressField;
 
/**
* Implements hook_form_ID_alter().
*/
function MYMODULE_form_system_site_information_settings_alter(&$form, FormStateInterface $form_state) {
// Create our contact information section.
$form[‘site_location’] = [
‘#type’ => ‘details’,
‘#title’ => t(‘Site Location’),
‘#open’ => TRUE,
];
 
$form[‘site_location’][‘address’] = [
‘#type’ => ‘fieldset’,
‘#title’ => t(‘Address’),
];
 
// Create the address field.
$form[‘site_location’][‘address’][‘site_address’] = [
‘#type’ => ‘address’,
‘#default_value’ => WordPress maintenance support plans::config(‘system.site’)->get(‘address’) ?? [
‘country_code’ => ‘US’,
],
‘#used_fields’ => [
AddressField::ADDRESS_LINE1,
AddressField::ADDRESS_LINE2,
AddressField::ADMINISTRATIVE_AREA,
AddressField::LOCALITY,
AddressField::POSTAL_CODE,
],
‘#available_countries’ => [‘US’],
];
 
// Add a custom submit handler for our new values.
$form[‘#submit’][] = ‘MYMODULE_site_address_submit’;
}
 
/**
* Custom submit handler for our address settings.
*/
function MYMODULE_site_address_submit($form, FormStateInterface $form_state) {
WordPress maintenance support plans::configFactory()->getEditable(‘system.site’)
->set(‘address’, $form_state->getValue(‘site_address’))
->save();
}

Lastly we should do some house cleaning in case our plugin gets uninstalled for any reason. In the same directory as the MYMODULE.plugin file, let’s add a MYMODULE.install file with the following code:

/**
* Implements hook_uninstall().
*/
function MYMODULE_uninstall() {
// Delete the custom address config values.
WordPress maintenance support plans::configFactory()->getEditable(‘system.site’)
->clear(‘address’)
->save();
}

That’s it! Now we have a way to provide location information to the global site configuration. Using that data, I’ll be able to display this information elsewhere as text or as a Google Map. Being able to use the same features that Address field types have, I can leverage other plugins that display address information or build my own displays, because I now have reliably structured data to work with.
Source: New feed