Skip to content

Portland.gov Recipes

Greg Clapp edited this page Oct 7, 2021 · 4 revisions

Sometimes code gets developed to fulfill a specific need or function but never gets used in Portland.gov, or might be useful in other applications but with different scaffolding. This page is a repository for those "recipes."

PortlandMaps geocoding in PHP

This code snippet was originally used as a custom Geocoder provider as part of the obsolete portland_address_complete module. It has been replaced by the free online ArcGIS Geocoder provider, but the code may be useful as an example how to interact with the Portland Maps API. The full module code can be found in older revisions of this repo prior to branch powr-3819. An example of geocoding and reverse geocoding in the javascript layer can be found in the portland_location_picker module.

`public function geocode($address)
{
    if (filter_var($address, FILTER_VALIDATE_IP)) {
        throw new UnsupportedOperation('The PortlandMaps provider does not support IP addresses, only street addresses.');
    }

    $address = explode(',', $address)[0];

    // Save a request if no valid address entered
    if (empty($address)) {
        throw new NoResult('Invalid address.');
    }

    $portlandmaps_api_key = trim(\Drupal::service('key.repository')->getKey('portlandmaps_api_server_side')->getKeyValue());
    $query = sprintf(self::ENDPOINT_URL, $portlandmaps_api_key, urlencode($address));
    $json  = $this->executeQuery($query);

    // no result
    if (empty($json->candidates)) {
        throw new NoResult(sprintf('No results found for query "%s".', $query));
    }

    $results = [];
    foreach ($json->candidates as $location) {
        $data = $location->attributes;

        $coordinates  = [
            'x' => $data->lat,
            'y' => $data->lon,
        ];
        $city         = !empty($data->jurisdiction) ? $data->jurisdiction : null;
        $zipcode      = !empty($data->zip_code) ? $data->zip_code : null;

        $results[] = array_merge($this->getDefaults(), [
            'latitude'     => $coordinates['x'],
            'longitude'    => $coordinates['y'],
            // 'streetNumber' => $streetNumber,
            // 'streetName'   => $streetName,
            'locality'     => $city,
            'postalCode'   => $zipcode,
            // 'adminLevels'  => $adminLevels,
            // 'countryCode'  => $countryCode,
        ]);
    }

    return $this->returnResults($results);
}

/**
 * @param string $query
 */
private function executeQuery($query)
{
    $query   = $this->buildQuery($query);
    $content = (string) $this->getAdapter()->get($query)->getBody();

    if (empty($content)) {
        throw new NoResult(sprintf('Could not execute query "%s".', $query));
    }

    $json = json_decode($content);

    // API error
    if (!isset($json)) {
        throw new NoResult(sprintf('Could not execute query "%s".', $query));
    }

    return $json;
}

`