[ 'read_id' ], 'public' => [] ]; /** * Search for an address based on an address string. This will make an API * call to SmartyStreets using that address string (after first checking * the cache to see if we've done it before), then it will either create the * address row for this user or return the existing one if it already * exists. * * For example: * * 1. 123 Sesame St. (query smarty, insert row) * 2. 123 Sesame Street (query smarty, return existing row) * 3. 123 Sesame Street (query smarty (cached), return existing row) * * @param string $address Address components (line_1, locality, * administrative_area, postal_code) * @param string $country ISO 3 country code * * @return array The address row. */ public function search($address, $country) { /** * If any of these fields are missing, set normalized to an empty array * and skip the SmartyStreets lookup. Also, line_1 must have a number and * text. */ foreach(['line_1', 'locality', 'administrative_area', 'postal_code'] as $key) { if( isset($address[$key]) === false || trim($address[$key]) === '' || $address[$key] === null ) { $normalized = []; break; } } if( isset($address['line_1']) === true && preg_match('/\d+ [0-9]*[a-z]+/i', trim(preg_replace('/[^a-z0-9 ]/i', ' ', $address['line_1']))) !== 1 ) { $normalized = []; } // If normalized wasn't overrridden, check with SmartyStreets. if(isset($normalized) === false) { $address_string = $address['line_1'] . ', ' . $address['locality'] . ', ' . $address['administrative_area'] . ', ' . $address['postal_code']; $normalized = $this->api( 'smarty_streets', 'smarty_streets_api', [ 'street' => $address_string, 'country' => $country ] ); } $key = $this->generate_key($normalized); $existing_address = $this->get([ 'key' => $key ]); if($existing_address === null) { return $this->create([ 'key' => $key, 'normalized' => $normalized ]); } else { return $existing_address; } } /** * Generate a key from the normalized address to see whether or not it's * been stored before. Note that SmartyStreets does not recommend using the * DPBC as a unique identifier. I am here, but the key is not intended to be * a unique identifier for an address. It's meant to be a representation of * the full details of an address. If the ZIP code changes for someone's * house, I need to store that as a new address or the actual address will * be incorrect. * * @link https://smartystreets.com/docs/addresses-have-unique-identifier * * @param string $normalized Normalized address as returned from * SmartyStreets * * @return string */ private function generate_key($normalized) { if(isset($normalized['delivery_point_barcode']) === true) { return sha1($normalized['delivery_point_barcode']); } else { $string = ''; if(isset($normalized['address1']) === true) { $string .= $normalized['address1']; } if(isset($normalized['address2']) === true) { $string .= $normalized['address2']; } if(isset($normalized['address3']) === true) { $string .= $normalized['address3']; } return sha1($string); } } }