YetiForceCompany/YetiForceCRM

View on GitHub
app/Map/Address/GoogleGeocode.php

Summary

Maintainability
B
6 hrs
Test Coverage
F
0%
<?php

/**
 * Address finder Google file.
 *
 * @see https://maps.googleapis.com Documentation  of Google Geocoding API
 *
 * @package App
 *
 * @copyright YetiForce S.A.
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
 * @author    Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com>
 * @author    Radosław Skrzypczak <r.skrzypczak@yetiforce.com>
 */

namespace App\Map\Address;

/**
 * Address finder Google class.
 */
class GoogleGeocode extends Base
{
    /** {@inheritdoc} */
    public $docUrl = 'https://code.google.com/apis/console/?noredirect';

    /** {@inheritdoc} */
    public $customFields = [
        'key' => [
            'validator' => [['name' => 'AlphaNumeric']],
            'uitype' => 1,
            'label' => 'LBL_KEY',
            'purifyType' => \App\Purifier::ALNUM,
            'maximumlength' => '200',
            'typeofdata' => 'V~M',
            'tooltip' => 'LBL_KEY_PLACEHOLDER',
        ],
    ];
    /**
     * API Address to retrieve data.
     *
     * @var string
     */
    protected static $url = 'https://maps.googleapis.com/maps/api/geocode/json?';

    /** {@inheritdoc} */
    public function find($value)
    {
        if (empty($value) || !\App\RequestUtil::isNetConnection()) {
            return [];
        }
        $key = $this->config['key'];
        $lang = \App\Language::getShortLanguageName();
        $url = static::$url . "key={$key}&address=$value";
        try {
            \App\Log::beginProfile("GET|GoogleGeocode::find|{$url}", __NAMESPACE__);
            $response = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->get($url);
            \App\Log::endProfile("GET|GoogleGeocode::find|{$url}", __NAMESPACE__);
            if (200 !== $response->getStatusCode()) {
                \App\Log::warning('Error: ' . $url . ' | ' . $response->getStatusCode() . ' ' . $response->getReasonPhrase(), __CLASS__);
                return false;
            }
            $body = \App\Json::decode($response->getBody()->getContents());
        } catch (\Throwable $exc) {
            \App\Log::warning('Error: ' . $url . ' | ' . $exc->getMessage(), __CLASS__);
            return false;
        }
        $rows = [];
        if (empty($body['error_message']) && isset($body['status'])) {
            foreach ($body['results'] as $row) {
                $address = $this->parse($row['address_components']);
                $rows[] = [
                    'label' => $row['formatted_address'],
                    'address' => $address,
                    'coordinates' => [
                        'lat' => $row['geometry']['location']['lat'],
                        'lon' => $row['geometry']['location']['lng']
                    ],
                    'countryCode' => strtolower($address['addresslevel1'][1] ?? ''),
                ];
            }
        } elseif (isset($body['error_message'])) {
            \App\Log::warning("{$body['status']}: {$body['error_message']}", __NAMESPACE__);
            throw new \App\Exceptions\AppException("ERR_COMMUNICATION_ERROR|{$body['status']}: {$body['error_message']}");
        }
        return $rows;
    }

    /**
     * Parse response.
     *
     * @param array $rows
     *
     * @return string[]
     */
    private function parse($rows)
    {
        $address = [];
        foreach ($rows as $row) {
            switch ($row['types'][0]) {
                case 'street_number':
                    if (false !== strpos($row['long_name'], '/')) {
                        [$address['buildingnumber'], $address['localnumber']] = explode('/', $row['long_name'], 2);
                    } else {
                        $address['buildingnumber'] = $row['long_name'];
                    }
                    break;
                case 'route':
                    $address['addresslevel8'] = $row['long_name'];
                    break;
                case 'postal_code':
                    if (empty($row['types'][1])) {
                        $address['addresslevel7'] = $row['long_name'];
                    }
                    break;
                case 'neighborhood':
                    $address['addresslevel6'] = $row['long_name'];
                    break;
                case 'sublocality':
                    $address['addresslevel6'] = $row['long_name'];
                    break;
                case 'locality':
                    $address['addresslevel5'] = $row['long_name'];
                    break;
                case 'administrative_area_level_3':
                    $address['addresslevel4'] = $row['long_name'];
                    break;
                case 'administrative_area_level_2':
                    $address['addresslevel3'] = $row['long_name'];
                    break;
                case 'administrative_area_level_1':
                    $address['addresslevel2'] = $row['long_name'];
                    break;
                case 'country':
                    $address['addresslevel1'] = $row['long_name'];
                    break;
                default:
                    break;
            }
        }
        return $address;
    }
}