/** * @covers ::__construct * @covers ::getCountryCode * @covers ::getLocale * @covers ::getFormat * @covers ::getLocalFormat * @covers ::getUsedFields * @covers ::getUsedSubdivisionFields * @covers ::getRequiredFields * @covers ::getUppercaseFields * @covers ::getAdministrativeAreaType * @covers ::getLocalityType * @covers ::getDependentLocalityType * @covers ::getPostalCodeType * @covers ::getPostalCodePattern * @covers ::getPostalCodePrefix * @covers ::getSubdivisionDepth */ public function testValid() { $definition = ['country_code' => 'US', 'locale' => 'en', 'format' => "%givenName %familyName\n%organization\n%addressLine1\n%addressLine2\n%locality, %administrativeArea %postalCode", 'local_format' => '%postalCode\\n%addressLine1\\n%organization\\n%givenName %familyName', 'required_fields' => [AddressField::ADMINISTRATIVE_AREA, AddressField::LOCALITY, AddressField::POSTAL_CODE, AddressField::ADDRESS_LINE1], 'uppercase_fields' => [AddressField::ADMINISTRATIVE_AREA, AddressField::LOCALITY], 'administrative_area_type' => AdministrativeAreaType::STATE, 'locality_type' => LocalityType::CITY, 'dependent_locality_type' => DependentLocalityType::DISTRICT, 'postal_code_type' => PostalCodeType::ZIP, 'postal_code_pattern' => '(\\d{5})(?:[ \\-](\\d{4}))?', 'postal_code_prefix' => 'US', 'subdivision_depth' => 1]; $addressFormat = new AddressFormat($definition); $this->assertEquals($definition['country_code'], $addressFormat->getCountryCode()); $this->assertEquals($definition['locale'], $addressFormat->getLocale()); $this->assertEquals($definition['format'], $addressFormat->getFormat()); $this->assertEquals($definition['local_format'], $addressFormat->getLocalFormat()); $this->assertEquals($definition['required_fields'], $addressFormat->getRequiredFields()); $this->assertEquals($definition['uppercase_fields'], $addressFormat->getUppercaseFields()); $this->assertEquals($definition['administrative_area_type'], $addressFormat->getAdministrativeAreaType()); $this->assertEquals($definition['locality_type'], $addressFormat->getLocalityType()); // The format has no %dependentLocality, the type must be NULL. $this->assertNull($addressFormat->getDependentLocalityType()); $this->assertEquals($definition['postal_code_type'], $addressFormat->getPostalCodeType()); $this->assertEquals($definition['postal_code_pattern'], $addressFormat->getPostalCodePattern()); $this->assertEquals($definition['postal_code_prefix'], $addressFormat->getPostalCodePrefix()); $this->assertEquals($definition['subdivision_depth'], $addressFormat->getSubdivisionDepth()); $expectedUsedFields = [AddressField::ADMINISTRATIVE_AREA, AddressField::LOCALITY, AddressField::POSTAL_CODE, AddressField::ADDRESS_LINE1, AddressField::ADDRESS_LINE2, AddressField::ORGANIZATION, AddressField::GIVEN_NAME, AddressField::FAMILY_NAME]; $this->assertEquals($expectedUsedFields, $addressFormat->getUsedFields()); $expectedUsedSubdivisionFields = [AddressField::ADMINISTRATIVE_AREA, AddressField::LOCALITY]; $this->assertEquals($expectedUsedSubdivisionFields, $addressFormat->getUsedSubdivisionFields()); }
/** * Validates the provided postal code. * * @param string $postalCode The postal code. * @param array $subdivisions An array of found valid subdivisions. * @param AddressFormat $addressFormat The address format. * @param Constraint $constraint The constraint. */ protected function validatePostalCode($postalCode, array $subdivisions, AddressFormat $addressFormat, $constraint) { if (empty($postalCode) || !in_array(AddressField::POSTAL_CODE, $constraint->fields)) { // Nothing to validate. return; } // Resolve the available patterns. $fullPattern = $addressFormat->getPostalCodePattern(); $startPattern = null; foreach ($subdivisions as $subdivision) { $pattern = $subdivision->getPostalCodePattern(); if (empty($pattern)) { continue; } if ($subdivision->getPostalCodePatternType() == PatternType::FULL) { $fullPattern = $pattern; } else { $startPattern = $pattern; } } if ($fullPattern) { // The pattern must match the provided value completely. preg_match('/' . $fullPattern . '/i', $postalCode, $matches); if (!isset($matches[0]) || $matches[0] != $postalCode) { $this->addViolation(AddressField::POSTAL_CODE, $constraint->invalidMessage, $postalCode, $addressFormat); return; } } if ($startPattern) { // The pattern must match the start of the provided value. preg_match('/' . $startPattern . '/i', $postalCode, $matches); if (!isset($matches[0]) || strpos($postalCode, $matches[0]) !== 0) { $this->addViolation(AddressField::POSTAL_CODE, $constraint->invalidMessage, $postalCode, $addressFormat); return; } } }
/** * Gets the address values used to build the view. * * @param AddressInterface $address The address. * @param AddressFormat $addressFormat The address format. * * @return array The values, keyed by address field. */ protected function getValues(AddressInterface $address, AddressFormat $addressFormat) { $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. $originalValues = []; $subdivisionFields = $addressFormat->getUsedSubdivisionFields(); $parents = []; foreach ($subdivisionFields as $index => $field) { if (empty($values[$field])) { // This level is empty, so there can be no sublevels. break; } $parents[] = $index ? $originalValues[$subdivisionFields[$index - 1]] : $address->getCountryCode(); $subdivision = $this->subdivisionRepository->get($values[$field], $parents); if (!$subdivision) { break; } // Remember the original value so that it can be used for $parents. $originalValues[$field] = $values[$field]; // Replace the value with the expected code. $useLocalName = LocaleHelper::match($address->getLocale(), $subdivision->getLocale()); $values[$field] = $useLocalName ? $subdivision->getLocalCode() : $subdivision->getCode(); if (!$subdivision->hasChildren()) { // The current subdivision has no children, stop. break; } } return $values; }