railpage/railpagecore

View on GitHub
lib/Locations/Country.php

Summary

Maintainability
F
4 days
Test Coverage
<?php
    /**
     * Lineside locations by country
     * @since   Version 3.8.7
     * @package Railpage
     * @author  Michael Greenhill
     */

    namespace Railpage\Locations;

    use stdClass;
    use Exception;
    use DateTime;
    use Railpage\Place;
    use Railpage\Debug;
    use Railpage\Url;
    use Railpage\ISO\ISO_3166;
    use Zend_Db_Expr;


    /**
     * Country
     * @since Version 3.8.7
     */
    
    class Country extends Locations {
        
        /**
         * Registry/Redis/Memcached cache identifier
         * @since Version 3.10.0
         * @const string CACHE_KEY
         */
        
        const CACHE_KEY = "railpage.country=%s";

        /**
         * Country name
         * @var string $name
         */

        public $name;

        /**
         * Country short code
         * @var string $code
         */

        public $code;

        /**
         * URL for this country
         * @var string $url
         */

        public $url;

        /**
         * Centre point
         * @var object $centre
         */

        public $centre;

        /**
         * Bounding box
         * @var object $boundingBox
         */

        public $boundingBox;

        /**
         * Timezone
         * @var string $timezone
         */

        public $timezone;

        /**
         * Constructor
         *
         * @param string $code
         */

        public function __construct($code) {

            parent::__construct();

            $this->code = $code;
            $this->url = new Url("/locations/" . strtolower($this->code));

            $countries = ISO_3166::get_countries();

            if (strlen($this->code) == 2) {
                $this->name = $countries[$code]['name'];
            } else {
                foreach ($countries as $cc => $data) {
                    if (strtolower($data['name']) == strtolower($this->code)) {
                        $this->code = $cc;
                        $this->url = new Url("/locations/" . strtolower($this->code));
                        $this->name = $data['name'];
                    }
                }
            }


            Debug::RecordInstance();
            $timer = Debug::GetTimer();

            if (!$this->loadFromCache() || empty( $this->name )) {
                $woe = Place::getWOEData(strtoupper($code));

                if (isset( $woe['places']['place'][0]['name'] )) {
                    $woe = $woe['places']['place'][0];

                    $data = [
                        "point"        => new Zend_Db_Expr(sprintf("GeomFromText('POINT(%s %s)')", $woe['centroid']['latitude'], $woe['centroid']['longitude'])),
                        "bb_southwest" => new Zend_Db_Expr(sprintf("GeomFromText('POINT(%s %s)')", $woe['boundingBox']['southWest']['latitude'], $woe['boundingBox']['southWest']['longitude'])),
                        "bb_northeast" => new Zend_Db_Expr(sprintf("GeomFromText('POINT(%s %s)')", $woe['boundingBox']['northEast']['latitude'], $woe['boundingBox']['northEast']['longitude'])),
                        "country_code" => $woe['country attrs']['code'],
                        "country_name" => $woe['name'],
                        "timezone"     => isset( $woe['timezone'] ) ? $woe['timezone'] : ""
                    ];

                    $this->db->insert("geoplace", $data);

                    $this->name = $woe['name'];

                    $this->centre = new stdClass;
                    $this->centre->lat = $woe['centroid']['latitude'];
                    $this->centre->lon = $woe['centroid']['longitude'];

                    $this->boundingBox = new stdClass;
                    $this->boundingBox->northEast = new stdClass;
                    $this->boundingBox->northEast->lat = $woe['boundingBox']['northEast']['latitude'];
                    $this->boundingBox->northEast->lon = $woe['boundingBox']['northEast']['longitude'];

                    $this->boundingBox->southWest = new stdClass;
                    $this->boundingBox->southWest->lat = $woe['boundingBox']['southWest']['latitude'];
                    $this->boundingBox->southWest->lon = $woe['boundingBox']['southWest']['longitude'];
                }

            }


            /**
             * Fetch the WOE (Where On Earth) data from Yahoo
             */


            Debug::LogEvent(__METHOD__, $timer);
        }

        /**
         * Populate this country from cached data
         * @since Version 3.10.0
         * @return boolean
         */

        private function loadFromCache() {

            $mckey = sprintf("railpage:locations.country=%s", strtoupper($this->code));
            
            #printArray($mckey);die;

            if (!$row = $this->Memcached->fetch($mckey) && !$row = $this->Redis->fetch($mckey)) {

                $query = "SELECT *, X(point) AS centroid_lat, Y(point) AS centroid_lon,
                    X(bb_southwest) AS bb_southwest_lat, Y(bb_southwest) AS bb_southwest_lon,
                    X(bb_northeast) AS bb_northeast_lat, Y(bb_northeast) AS bb_northeast_lon
                 FROM geoplace 
                 WHERE country_code = ? 
                    AND region_code IS NULL 
                    AND neighbourhood IS NULL
                    LIMIT 0, 1";

                $row = $this->db->fetchRow($query, strtoupper($this->code));

                if (is_array($row)) {
                    $this->Memcached->save($mckey, $row, strtotime("+1 year"));
                    $this->Redis->save($mckey, $row, strtotime("+1 year"));
                }

            }

            if (!isset( $row ) || !is_array($row) || count($row) === 0) {
                return false;
            }

            #$this->name = $row['country_name'];
            $this->timezone = $row['timezone'];

            $this->centre = new stdClass;
            $this->centre->lat = $row['centroid_lat'];
            $this->centre->lon = $row['centroid_lat'];

            $this->boundingBox = new stdClass;
            $this->boundingBox->northEast = new stdClass;
            $this->boundingBox->northEast->lat = $row['bb_northeast_lat'];
            $this->boundingBox->northEast->lon = $row['bb_northeast_lon'];

            $this->boundingBox->southWest = new stdClass;
            $this->boundingBox->southWest->lat = $row['bb_southwest_lat'];
            $this->boundingBox->southWest->lon = $row['bb_southwest_lat'];

            return true;

        }

        /**
         * Get regions within this country
         * @return array
         *
         * @param string|bool $country Kept in for backwards compatibility with parent::getRegions()
         */

        public function getRegions($country = false) {
            $query = "SELECT COUNT(l.id) AS count, l.region_slug AS slug,
                g.region_name AS name, g.region_code, g.timezone
                FROM location AS l 
                    LEFT JOIN geoplace AS g ON l.geoplace = g.id 
                WHERE l.country = ? 
                GROUP BY l.region 
                ORDER BY l.region ASC";

            $regions = array();

            foreach ($this->db->fetchAll($query, $this->code) as $row) {
                if (empty( $row['slug'] )) {
                    $data = array(
                        "region_slug" => $this->makeRegionSlug($row['name'])
                    );

                    $where = array(
                        "region = ?"  => $row['name'],
                        "country = ?" => $this->code
                    );

                    $this->db->update("location", $data, $where);

                    $row['slug'] = $this->makeRegionSlug($row['name']);
                }

                $row['url'] = $this->url . "/" . $row['slug'];
                $shortname = $row['region_code'];

                /**
                 * Get WOE data for this region
                 */

                /*
                #$woe = getWOEData($row['name'] . "," . $this->code);
                $woe = Place::getWOEData($row['name'] . "," . $this->code);


                if (isset($woe['places']['place'][0]['name'])) {
                    $row['name'] = $woe['places']['place'][0]['name'];
                }

                if (!empty($this->timezone)) {
                    $row['timezone'] = $this->timezone;
                }

                if (isset($woe['places']['place'][0]['timezone'])) {
                    $row['timezone'] = $woe['places']['place'][0]['timezone'];
                }
                */

                $row['glyph'] = strtolower(sprintf("map-%s", $this->code));

                /**
                 * Assign a map glyph
                 */

                switch (strtolower($this->code)) {

                    case "au" :
                        $row['glyph'] = strtolower(sprintf("map-%s-%s", $this->code, str_replace(array( "ACT", "NSW", "QLD", "TAS", "VIC" ), array( "AC", "NW", "QL", "TS", "VC" ), strtoupper($shortname))));
                        break;

                    case "gb" :
                        $row['glyph'] = "map-uk";
                        break;

                    case "us" :
                        $find = array(
                            "alaska",
                            "alabama",
                            "arizona",
                            "arkansas",
                            "california",
                            "colorado",
                            "Connecticut",
                            "delaware",
                            "district of columbia",
                            "florida",
                            "georgia",
                            "hawaii",
                            "idaho",
                            "illinois",
                            "indiana",
                            "iowa",
                            "kansas",
                            "kentucky",
                            "louisiana",
                            "maine",
                            "maryland",
                            "massachusetts",
                            "michigan",
                            "minnesota",
                            "mississippi",
                            "missouri",
                            "montana",
                            "nebraska",
                            "nevada",
                            "new hampshire",
                            "new jersey",
                            "new mexico",
                            "new york",
                            "north carolina",
                            "north dakota",
                            "ohio",
                            "oklahoma",
                            "oregon",
                            "pennsylvania",
                            "rhode island",
                            "south carolina",
                            "south dakota",
                            "tennessee",
                            "texas",
                            "utah",
                            "vermont",
                            "virginia",
                            "washington",
                            "west virginia",
                            "wisconsin",
                            "wyoming"
                        );

                        $replace = array(
                            "ak", "al", "az", "ar", "ca", "co", "ct", "de", "dc", "fl", "ga", "hi", "id", "il", "in", "ia", "ks", "ky",
                            "la", "me", "md", "ma", "mi", "mn", "ms", "mo", "mt", "ne", "nv", "nh", "nj", "nm", "ny", "nc", "nd", "oh",
                            "ok", "or", "pa", "ri", "sc", "sd", "tn", "tx", "ut", "vt", "va", "wa", "wv", "wi", "wy"
                        );

                        $row['glyph'] = strtolower(sprintf("map-%s-%s", $this->code, str_ireplace($find, $replace, $shortname)));
                        break;
                }

                $regions[] = $row;
            }

            return $regions;
        }

        /**
         * Get locations within this country
         * @return array
         *
         * @param string|bool $region  Kept for backwards compatibility with parent::getLocations()
         * @param string|bool $country Kept for backwards compatibility with parent::getLocations()
         */

        public function getLocations($region = false, $country = false) {
            $query = "SELECT * FROM location WHERE country = ? ORDER BY name";

            $locations = array();

            foreach ($this->db->fetchAll($query, array( $this->code )) as $row) {
                $row['url'] = $this->makeRegionPermalink($this->code, $row['region']) . "/" . $row['slug'];
                $locations[] = $row;
            }

            return $locations;
        }

        /**
         * Get this object as a string
         * @since Version 3.9.1
         * @return string
         */

        public function __toString() {

            return $this->name;

        }
    }