/** * {@inheritdoc} */ public function render(ResultRow $values) { $value = $this->getValue($values); if (empty($value)) { return ''; } $entity = $this->getEntity($values); $address = $entity->{$this->definition['field_name']}->first(); switch ($this->definition['property']) { case 'administrative_area': $parent_id = NULL; $needs_parent = FALSE; break; case 'locality': $parent_id = $address->administrative_area; $needs_parent = TRUE; break; case 'dependent_locality': $parent_id = $address->locality; $needs_parent = TRUE; break; } if (!$needs_parent || !empty($parent_id)) { $subdivisions = $this->subdivisionRepository->getList($address->country_code, $parent_id); if (isset($subdivisions[$value])) { $value = $subdivisions[$value]; } } return $this->sanitizeValue($value); }
/** * 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}(); } // Replace the subdivision values with the names of any predefined ones. foreach ($address_format->getUsedSubdivisionFields() as $field) { if (empty($values[$field])) { // This level is empty, so there can be no sublevels. break; } $subdivision = $this->subdivisionRepository->get($values[$field], $address->getLocale()); if (!$subdivision) { // This level has no predefined subdivisions, stop. break; } $values[$field] = $subdivision->getCode(); if (!$subdivision->hasChildren()) { // The current subdivision has no children, stop. break; } } return $values; }
/** * Builds the subdivision form elements. * * @param array $form * The form. * @param array $values * The form values. * @param \Drupal\address\Entity\AddressFormatInterface $address_format * The address format for the selected country. * * @return array * The form with the added subdivision elements. */ protected function buildSubdivisionElements(array $form, array $values, AddressFormatInterface $address_format) { $depth = $this->subdivisionRepository->getDepth($values['country_code']); if ($depth === 0) { // No predefined data found. return $form; } $labels = LabelHelper::getFieldLabels($address_format); $subdivision_fields = $address_format->getUsedSubdivisionFields(); $current_depth = 1; foreach ($subdivision_fields as $index => $field) { $property = FieldHelper::getPropertyName($field); $parent_property = $index ? FieldHelper::getPropertyName($subdivision_fields[$index - 1]) : NULL; if ($parent_property && empty($values[$parent_property])) { // No parent value selected. break; } $parent_id = $parent_property ? $values[$parent_property] : NULL; $subdivisions = $this->subdivisionRepository->getList($values['country_code'], $parent_id); if (empty($subdivisions)) { break; } $form[$property] = ['#type' => 'select', '#title' => $labels[$field], '#options' => $subdivisions, '#default_value' => $values[$property], '#empty_option' => $this->t('- All -')]; if ($current_depth < $depth) { $form[$property]['#ajax'] = ['callback' => [get_class($this), 'ajaxRefresh'], 'wrapper' => $form['#wrapper_id']]; } $current_depth++; } return $form; }
/** * 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; }
/** * Validates the provided subdivision values. * * @param array $values The field values, keyed by field constants. * @param AddressFormatInterface $addressFormat The address format. * @param Constraint $constraint The constraint. * * @return array An array of found valid subdivisions. */ protected function validateSubdivisions($values, AddressFormatInterface $addressFormat, $constraint) { $countryCode = $addressFormat->getCountryCode(); $subdivisionFields = $addressFormat->getUsedSubdivisionFields(); $foundIds = []; foreach ($subdivisionFields as $index => $field) { if (empty($values[$field]) || !in_array($field, $constraint->fields)) { // The field is empty or validation is disabled. break; } $parentField = $index ? $subdivisionFields[$index - 1] : null; $parentId = $parentField ? $values[$parentField] : null; $children = $this->subdivisionRepository->getList($countryCode, $parentId); if (!$children) { // No predefined subdivisions found. break; } $found = false; $value = $values[$field]; if (isset($children[$value])) { $found = true; $foundIds[] = $value; } if (!$found) { $this->addViolation($field, $constraint->invalidMessage, $value, $addressFormat); break; } } // Load the found subdivision ids. $subdivisions = []; foreach ($foundIds as $id) { $subdivisions[] = $this->subdivisionRepository->get($id); } return $subdivisions; }
/** * Gets a list of form fields for the provided address format. * * @param AddressFormatInterface $addressFormat * @param array $subdivisions An array of needed subdivisions. * * @return array An array in the $field => $formOptions format. */ protected function getFormFields(AddressFormatInterface $addressFormat, $subdivisions) { // @todo Add support for having multiple fields in the same line. $fields = []; $labels = $this->getFieldLabels($addressFormat); $requiredFields = $addressFormat->getRequiredFields(); $groupedFields = $addressFormat->getGroupedFields(); foreach ($groupedFields as $lineFields) { foreach ($lineFields as $field) { $fields[$field] = ['label' => $labels[$field], 'required' => in_array($field, $requiredFields)]; } } // Add choices for predefined subdivisions. foreach ($subdivisions as $field => $parentId) { // @todo Pass the form locale to get the translated values. $children = $this->subdivisionRepository->getList($addressFormat->getCountryCode(), $parentId); if ($children) { $fields[$field]['choices'] = $children; } } return $fields; }
/** * Processes the subdivision elements, adding predefined values where found. * * @param array $element * The existing form element array. * @param array $values * An array of address values, keyed by property name. * @param \Drupal\address\Entity\AddressFormatInterface $address_format * The address format. * * @return array * The processed form element array. */ protected function processSubdivisionElements(array $element, array $values, AddressFormatInterface $address_format) { $depth = $this->subdivisionRepository->getDepth($values['country_code']); if ($depth === 0) { // No predefined data found. return $element; } $subdivision_properties = []; foreach ($address_format->getUsedSubdivisionFields() as $field) { $subdivision_properties[] = FieldHelper::getPropertyName($field); } // Load and insert the subdivisions for each parent id. $currentDepth = 1; foreach ($subdivision_properties as $index => $property) { if (!isset($element[$property]) || !Element::isVisibleElement($element[$property])) { break; } $parent_property = $index ? $subdivision_properties[$index - 1] : NULL; if ($parent_property && empty($values[$parent_property])) { break; } $parent_id = $parent_property ? $values[$parent_property] : NULL; $subdivisions = $this->subdivisionRepository->getList($values['country_code'], $parent_id); if (empty($subdivisions)) { break; } $element[$property]['#type'] = 'select'; $element[$property]['#options'] = $subdivisions; $element[$property]['#empty_value'] = ''; unset($element[$property]['#size']); if ($currentDepth < $depth) { $element[$property]['#ajax'] = ['callback' => [get_class($this), 'ajaxRefresh'], 'wrapper' => $element['#wrapper_id']]; } $currentDepth++; } return $element; }