Graudusk/callurl

View on GitHub
src/CallUrlModel/GeoModelTrait.php

Summary

Maintainability
B
4 hrs
Test Coverage
<?php
/**
 * Showing off a standard class with methods and properties.
 */
namespace Erjh17\CallUrlModel;

/**
 * A trait implementing GeoModelTrait.
 */
trait GeoModelTrait
{
    // use \Erjh17\CallUrl;
    /**
     * @var int        $ip  The ip address.
     * @var string     $message  The message.
     * @var boolean    $valid  If the ip address is valid.
     * @var string     $host  The ip adress' host.
     */

    private $continent_name;
    private $country_name;
    private $city;
    private $zip;
    private $latitude;
    private $ipUrl;
    private $longitude;
    private $openCageUrl;
    private $opencagekey;
    public $dataList = [
        "continent_name",
        "country_name",
        "city",
        "zip",
        "latitude",
        "longitude",
        "lat",
        "lon",
        "display_name"
    ];

    abstract public function isValidIp();
    abstract public function validateIp();
    abstract public function getInfo();
    abstract public function fillInfo($result, $keys);

    /**
     * Sets ipstackurl property.
     *
     * @param string $url ipstack url.
     */
    public function setIpstackUrl($url)
    {
        $this->ipUrl = $url;
    }

    /**
     * Sets opencageurl property.
     *
     * @param string $url opencage url.
     */
    public function setOpencageUrl($url)
    {
        $this->openCageUrl = $url;
    }

    /**
     * Sets opencagekey property.
     *
     * @param string $key opencage key.
     */
    public function setOpencageKey($key)
    {
        $this->opencagekey = $key;
    }

    /**
     * Returns specific fetched key properties.
     *
     * @return array Geographic data
     */
    public function getGeoInfo()
    {
        return array_merge(
            array(
                'continent_name' => $this->continent_name,
                'country_name' => $this->country_name,
                'city' => $this->city,
                'zip' => $this->zip,
                'latitude' => str_replace(",", ".", $this->latitude),
                'longitude' => str_replace(",", ".", $this->longitude),
                'mapUrl' => "https://www.openstreetmap.org/#map=12/$this->latitude/$this->longitude&layers=H"
            ),
            $this->getZoomLevel()
        );
    }

    /**
     * Calculates zoom level and radius for the map and returns it.
     *
     * @return array Array containing zoom level and marker radius.
     */
    public function getZoomLevel()
    {
        $retArray = array();
        if (!$this->isValidIp()) {
            $retArray = array("zoomLevel" => "12", "radius" => "600");
        } elseif ($this->city !== null) {
            $retArray = array("zoomLevel" => "12", "radius" => "600");
        } else {
            $retArray = array("zoomLevel" => "3", "radius" => "400000");
        }
        return $retArray;
    }

    /**
     * Returns geographic info together with IP-info
     *
     * @return array Ip-info + geographic info
     */
    public function getAllInfo()
    {
        return array_merge($this->getInfo(), $this->getGeoInfo());
    }

    /**
     * Validates provided coordinate with regexp.
     *
     * @param string $subject Coordinate.
     *
     * @return integer
     */
    public function isCoord($subject)
    {
        $pattern = "/\d+\.\d+[\,\ ]+\d+\.\d+/";
        return preg_match($pattern, $subject);
    }

    /**
     * Fetches geographic information from callUrl module using ip address.
     *
     * @return array Data array with geographic info.
     */
    public function getGeoFromIp()
    {
        $cUrl = $this->di->get("callurl");
        $query = ["access_key" => $this->ipstackkey];
        $url = $this->ipUrl . $this->ipAddress;
        return $cUrl->fetch($url, $query);
    }

    /**
     * Fetches and returns Geographic info from multiple sources.
     *
     * @return array Geographic data.
     */
    public function fetchGeoInfo()
    {
        $cUrl = $this->di->get("callurl");
        $this->validateIp();
        if (!$this->isValidIp() && $this->isCoord($this->ipAddress)) {
            $this->setCoord();
        } elseif ($this->isValidIp()) {
            $apiResult = $this->getGeoFromIp();

            if (!empty($apiResult)) {
                $this->fillInfo($apiResult, $this->dataList);
            } else {
                $this->setErrorMessage("Ingen positionsdata kunde hämtas utifrån platsnamnet.");
            }
        } else {
            $query = [
                "key" => $this->opencagekey,
                "q" => $this->ipAddress,
                "pretty" => "1",
                "language" => "sv"
            ];
            $url = $this->openCageUrl;
            $geocode = $cUrl->fetch($url, $query);

            if (isset($geocode["results"][0])) {
                $this->latitude = $geocode["results"][0]["geometry"]["lat"];
                $this->longitude = $geocode["results"][0]["geometry"]["lng"];
                $nodeType = $geocode["results"][0]["components"]["_type"];
                if (isset($geocode["results"][0]["components"][$nodeType])) {
                    $this->city = $geocode["results"][0]["components"][$nodeType];
                }
                if (isset($geocode["results"][0]["components"]["country"])) {
                    $this->country_name = $geocode["results"][0]["components"]["country"];
                }
                if (isset($geocode["results"][0]["components"]["postcode"])) {
                    $this->zip = $geocode["results"][0]["components"]["postcode"];
                }
            } else {
                $this->setErrorMessage("Ingen positionsdata kunde hämtas utifrån platsnamnet.");
            }
        }
        $this->validateCoord();
        return $this->getAllInfo();
    }


    /**
     * Sets the error message provided.
     *
     * @param string $msg Error message
     */
    public function setErrorMessage($msg)
    {
        $this->errorMsg .= $msg . "\n";
    }

    /**
     * Checks wether the coordinate is within the map bounds
     *
     * @return boolean
     */
    public function validateCoord()
    {
        $lat = str_replace(".", ",", $this->latitude);
        $lon = str_replace(".", ",", $this->longitude);
        if (!$lat && !$lon) {
            $this->setErrorMessage("Kunde inte hämta position utifrån den angivna platsen.");
        }
        if ($lat < -85.05112878 || $lat > 85.05112878) {
            $this->setErrorMessage("Y-koordinaten är utanför maxgränsen.");
        }
        if ($lon < -180 || $lon > 180) {
            $this->setErrorMessage("X-koordinaten är utanför maxgränsen.");
        }
    }

    /**
     * Turns the provided string into a map coordinate.
     *
     * @return void
     */
    public function setCoord()
    {
        if ($this->ipAddress) {
            $latLon = explode(",", $this->ipAddress);
            $this->latitude = $latLon[0];
            $this->longitude = $latLon[1];
        }
    }
}