Commit 7090c976 authored by bojanz's avatar bojanz

Issue #2525762 by dbolinovski, slasher13, rocketeerbkw: Create a Plain formatter

parent d5ffb572
......@@ -32,3 +32,25 @@ function address_form_field_config_edit_form_alter(&$form, FormStateInterface $f
$form['default_value']['#access'] = FALSE;
}
}
/**
* Implements hook_theme().
*/
function address_theme() {
return [
'address_plain' => [
'variables' => [
'recipient' => '',
'organization' => '',
'address_line1' => '',
'address_line2' => '',
'postal_code' => '',
'sorting_code' => '',
'dependent_locality' => [],
'locality' => [],
'administrative_area' => [],
'country' => [],
],
]
];
}
......@@ -23,7 +23,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*
* @FieldFormatter(
* id = "address_default",
* label = @Translation("Address"),
* label = @Translation("Default"),
* field_types = {
* "address",
* },
......
<?php
namespace Drupal\address\Plugin\Field\FieldFormatter;
use CommerceGuys\Addressing\Enum\AddressField;
use CommerceGuys\Addressing\Repository\AddressFormatRepositoryInterface;
use CommerceGuys\Addressing\Repository\CountryRepositoryInterface;
use CommerceGuys\Addressing\Repository\SubdivisionRepositoryInterface;
use Drupal\address\AddressInterface;
use Drupal\address\Entity\AddressFormatInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\Element;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Plugin implementation of the 'address_plain' formatter.
*
* @FieldFormatter(
* id = "address_plain",
* label = @Translation("Plain"),
* field_types = {
* "address",
* },
* )
*/
class AddressPlainFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
/**
* The address format repository.
*
* @var \CommerceGuys\Addressing\Repository\AddressFormatRepositoryInterface
*/
protected $addressFormatRepository;
/**
* The country repository.
*
* @var \CommerceGuys\Addressing\Repository\CountryRepositoryInterface
*/
protected $countryRepository;
/**
* The subdivision repository.
*
* @var \CommerceGuys\Addressing\Repository\SubdivisionRepositoryInterface
*/
protected $subdivisionRepository;
/**
* Constructs an AddressPlainFormatter object.
*
* @param string $plugin_id
* The plugin_id for the formatter.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The definition of the field to which the formatter is associated.
* @param array $settings
* The formatter settings.
* @param string $label
* The formatter label display setting.
* @param string $view_mode
* The view mode.
* @param array $third_party_settings
* Any third party settings.
* @param \CommerceGuys\Addressing\Repository\AddressFormatRepositoryInterface $address_format_repository
* The address format repository.
* @param \CommerceGuys\Addressing\Repository\CountryRepositoryInterface $country_repository
* The country repository.
* @param \CommerceGuys\Addressing\Repository\SubdivisionRepositoryInterface $subdivision_repository
* The subdivision repository.
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AddressFormatRepositoryInterface $address_format_repository, CountryRepositoryInterface $country_repository, SubdivisionRepositoryInterface $subdivision_repository) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
$this->addressFormatRepository = $address_format_repository;
$this->countryRepository = $country_repository;
$this->subdivisionRepository = $subdivision_repository;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $pluginId, $pluginDefinition) {
// @see \Drupal\Core\Field\FormatterPluginManager::createInstance().
return new static(
$pluginId,
$pluginDefinition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['label'],
$configuration['view_mode'],
$configuration['third_party_settings'],
$container->get('address.address_format_repository'),
$container->get('address.country_repository'),
$container->get('address.subdivision_repository')
);
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
foreach ($items as $delta => $item) {
$elements[$delta] = $this->viewElement($item, $langcode);
}
return $elements;
}
/**
* Builds a renderable array for a single address item.
*
* @param \Drupal\address\AddressInterface $address
* The address.
* @param string $langcode
* The language that should be used to render the field.
*
* @return array
* A renderable array.
*/
protected function viewElement(AddressInterface $address, $langcode) {
$country_code = $address->getCountryCode();
$countries = $this->countryRepository->getList();
$address_format = $this->addressFormatRepository->get($country_code, $address->getLocale());
$values = $this->getValues($address, $address_format);
$element = [
'#theme' => 'address_plain',
'#recipient' => $values['recipient'],
'#organization' => $values['organization'],
'#address_line1' => $values['addressLine1'],
'#address_line2' => $values['addressLine2'],
'#postal_code' => $values['postalCode'],
'#sorting_code' => $values['sortingCode'],
'#administrative_area' => $values['administrativeArea'],
'#locality' => $values['locality'],
'#dependent_locality' => $values['dependentLocality'],
'#country' => [
'code' => $country_code,
'name' => $countries[$country_code],
],
'#cache' => [
'contexts' => [
'languages:' . LanguageInterface::TYPE_INTERFACE,
],
],
];
return $element;
}
/**
* Gets the address values used for rendering.
*
* @param \Drupal\address\AddressInterface $address
* The address.
* @param \Drupal\address\Entity\AddressFormatInterface $address_format
* The address format.
*
* @return array
* The values, keyed by address field.
*/
protected function getValues(AddressInterface $address, AddressFormatInterface $address_format) {
$values = [];
foreach (AddressField::getAll() as $field) {
$getter = 'get' . ucfirst($field);
$values[$field] = $address->$getter();
}
foreach ($address_format->getUsedSubdivisionFields() as $field) {
$value = $values[$field];
// The template needs access to both the subdivision code and name.
$values[$field] = [
'code' => '',
'name' => $value,
];
if (empty($value)) {
// This level is empty, so there can be no sublevels.
break;
}
$subdivision = $this->subdivisionRepository->get($value, $address->getLocale());
if (!$subdivision) {
// This level has no predefined subdivisions, stop.
break;
}
// Replace the subdivision values with the predefined ones.
$values[$field] = [
'code' => $subdivision->getCode(),
'name' => $subdivision->getName(),
];
if (!$subdivision->hasChildren()) {
// The current subdivision has no children, stop.
break;
}
}
return $values;
}
}
<?php
namespace Drupal\address\Tests\Formatter;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\simpletest\KernelTestBase;
/**
* Tests the plain formatter.
*
* @group address
*/
class PlainFormatterTest extends KernelTestBase {
/**
* @var array
*/
public static $modules = [
'system',
'field',
'language',
'text',
'entity_test',
'user',
'address'
];
/**
* @var string
*/
protected $entityType;
/**
* @var string
*/
protected $bundle;
/**
* @var string
*/
protected $fieldName;
/**
* @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface
*/
protected $display;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['system']);
$this->installConfig(['field']);
$this->installConfig(['text']);
$this->installConfig(['address']);
$this->installEntitySchema('entity_test');
ConfigurableLanguage::createFromLangcode('zh-hant')->save();
// The address module is never installed, so the importer doesn't run
// automatically. Instead, we manually import the address formats we need.
$country_codes = ['AD', 'SV', 'TW', 'US', 'ZZ'];
$importer = \Drupal::service('address.address_format_importer');
$importer->importEntities($country_codes);
$importer->importTranslations(['zh-hant']);
$this->entityType = 'entity_test';
$this->bundle = $this->entityType;
$this->fieldName = Unicode::strtolower($this->randomMachineName());
$field_storage = FieldStorageConfig::create([
'field_name' => $this->fieldName,
'entity_type' => $this->entityType,
'type' => 'address',
]);
$field_storage->save();
$field = FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => $this->bundle,
'label' => $this->randomMachineName(),
]);
$field->save();
$this->display = entity_get_display($this->entityType, $this->bundle, 'default');
$this->display->setComponent($this->fieldName, [
'type' => 'address_plain',
'settings' => [],
]);
$this->display->save();
}
/**
* Tests the rendered output.
*/
public function testRender() {
$entity = EntityTest::create([]);
$entity->{$this->fieldName} = [
'country_code' => 'AD',
'locality' => 'AD-07',
'postal_code' => 'AD500',
'address_line1' => 'C. Prat de la Creu, 62-64',
];
$this->renderEntityFields($entity, $this->display);
// Confirm the expected elements, including the predefined locality
// (properly escaped), country name.
$expected_elements = [
'C. Prat de la Creu, 62-64',
'AD500',
'Parròquia d&#039;Andorra la Vella',
'Andorra',
];
foreach ($expected_elements as $expected_element) {
$this->assertRaw($expected_element);
}
// Confirm that an unrecognized locality is shown unmodified.
$entity->{$this->fieldName}->locality = 'FAKE_LOCALITY';
$this->renderEntityFields($entity, $this->display);
$this->assertRaw('FAKE_LOCALITY');
}
/**
* Renders fields of a given entity with a given display.
*
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity object with attached fields to render.
* @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
* The display to render the fields in.
*
* @return string
* The rendered entity fields.
*/
protected function renderEntityFields(FieldableEntityInterface $entity, EntityViewDisplayInterface $display) {
$content = $display->build($entity);
$content = $this->render($content);
return $content;
}
}
{#
/**
* @file
* Default template for the 'plain' address formatter.
*
* Available variables:
* - recipient: Recipient.
* - organization: Organization.
* - address_line1: First address line.
* - address_line2: Second address line.
* - postal_code: Postal code.
* - sorting_code: Sorting code.
* - dependent_locality: The dependent locality.
* - dependent_locality.code: Dependent locality code.
* - dependent_locality.name: Dependent locality name.
* - locality: The locality subdivision.
* - locality.code: Locality code.
* - locality.name: Locality name.
* - administrative_area: The administrative area subdivision.
* - administrative_area.code: Administrative area code.
* - administrative_area.name: Administrative area name.
* - country: The country.
* - country.code: Country code.
* - country.name: Country name.
*
* if a subdivision (dependent_locality, locality, administrative_area) was
* entered, the array will always have a name. If it's a predefined subdivision,
* it will also have a code (e.g. 'CA' for California), which is preferred.
*
* @ingroup themeable
*/
#}
<p class="address" translate="no">
{% if recipient %}
{{ recipient }} <br>
{% endif %}
{% if organization %}
{{ organization }} <br>
{% endif %}
{% if address_line1 %}
{{ address_line1 }} <br>
{% endif %}
{% if address_line2 %}
{{ address_line2 }} <br>
{% endif %}
{% if dependent_locality.name %}
{{ dependent_locality.code ?: dependent_locality.name }} <br>
{% endif %}
{% if locality.name or postal_code or administrative_area.name %}
{{ locality.code ?: locality.name }} {{ postal_code }} {{ administrative_area.code ?: administrative_area.name }} <br>
{% endif %}
{{ country.name }}
</p>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment