Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
38.60% covered (danger)
38.60%
22 / 57
70.00% covered (warning)
70.00%
7 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
Globe
38.60% covered (danger)
38.60%
22 / 57
70.00% covered (warning)
70.00%
7 / 10
75.27
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 getData
8.33% covered (danger)
8.33%
3 / 36
0.00% covered (danger)
0.00%
0 / 1
5.08
 getName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRadius
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMinLongitude
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMaxLongitude
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEastSign
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isKnown
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 equalsTo
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 coordinatesAreValid
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
5.12
1<?php
2
3namespace GeoData;
4
5/**
6 * Immutable representation of a celestial body
7 */
8class Globe {
9    /** @var string */
10    private $name;
11
12    /** @var float|null */
13    private $radius;
14
15    /** @var float */
16    private $minLon = -360;
17
18    /** @var float */
19    private $maxLon = 360;
20
21    /** @var int either -1 or +1 */
22    private $east = 1;
23
24    /** @var bool */
25    private $known = false;
26
27    /**
28     * @param string $name Internal globe name
29     */
30    public function __construct( $name ) {
31        global $wgGlobes;
32
33        $this->name = $name;
34
35        $data = $wgGlobes[$name] ?? self::getData()[$name] ?? null;
36        if ( $data !== null ) {
37            $this->radius = $data['radius'] ?? null;
38            $this->minLon = $data['lon'][0] ?? 0;
39            $this->maxLon = $data['lon'][1];
40            $this->east = $data['east'] ?? 1;
41            $this->known = true;
42        }
43    }
44
45    /**
46     * @return array[]
47     */
48    private static function getData() {
49        static $data = [];
50        if ( $data ) {
51            return $data;
52        }
53
54        $earth   = [ 'lon' => [ -180, 180 ], 'east' => +1 ];
55        $east360 = [ 'lon' => [ 0, 360 ], 'east' => +1 ];
56        $west360 = [ 'lon' => [ 0, 360 ], 'east' => -1 ];
57
58        /**
59         * Format:
60         * 'lon' => array of [minimum value, maximum value]
61         * 'east' => sign 1 degree East would have
62         * 'radius' => mean radius in meters (optional)
63         * Coordinate systems mostly taken from http://planetarynames.wr.usgs.gov/TargetCoordinates
64         * Radii taken from Wikipedia. Globes that are too irregular in shape don't have radius set.
65         */
66        $data = [
67            'earth'     => $earth + [ 'radius' => Math::EARTH_RADIUS ],
68            'mercury'   => $west360 + [ 'radius' => 2439700.0 ],
69            'venus'     => $east360 + [ 'radius' => 6051800.0 ],
70            'moon'      => $earth + [ 'radius' => 1737100.0 ],
71            // Assuming MDIM 2.1
72            'mars'      => $east360 + [ 'radius' => 3389500.0 ],
73            'phobos'    => $west360,
74            'deimos'    => $west360,
75            // 'ceres' => ???,
76            // 'vesta' => ???,
77            'ganymede'  => $west360 + [ 'radius' => 2634100.0 ],
78            'callisto'  => $west360 + [ 'radius' => 2410300.0 ],
79            'io'        => $west360 + [ 'radius' => 1821600.0 ],
80            'europa'    => $west360 + [ 'radius' => 1560800.0 ],
81            'mimas'     => $west360 + [ 'radius' => 198200.0 ],
82            'enceladus' => $west360 + [ 'radius' => 252100.0 ],
83            'tethys'    => $west360 + [ 'radius' => 531100.0 ],
84            'dione'     => $west360 + [ 'radius' => 561400.0 ],
85            'rhea'      => $west360 + [ 'radius' => 763800.0 ],
86            'titan'     => $west360 + [ 'radius' => 2575500.0 ],
87            'hyperion'  => $west360,
88            'iapetus'   => $west360 + [ 'radius' => 734500.0 ],
89            'phoebe'    => $west360,
90            'miranda'   => $east360 + [ 'radius' => 235800.0 ],
91            'ariel'     => $east360 + [ 'radius' => 578900.0 ],
92            'umbriel'   => $east360 + [ 'radius' => 584700.0 ],
93            'titania'   => $east360 + [ 'radius' => 788400.0 ],
94            'oberon'    => $east360 + [ 'radius' => 761400.0 ],
95            'triton'    => $east360 + [ 'radius' => 1353400.0 ],
96            // ???
97            'pluto'     => $east360 + [ 'radius' => 1187000.0 ],
98        ];
99
100        return $data;
101    }
102
103    /**
104     * Globe internal name
105     * @return string
106     */
107    public function getName() {
108        return $this->name;
109    }
110
111    /**
112     * Returns globe radius or null if it's not known
113     * @return float|null
114     */
115    public function getRadius() {
116        return $this->radius;
117    }
118
119    /**
120     * Returns minimum longitude
121     * @return float
122     */
123    public function getMinLongitude() {
124        return $this->minLon;
125    }
126
127    /**
128     * Returns maximum longitude
129     * @return float
130     */
131    public function getMaxLongitude() {
132        return $this->maxLon;
133    }
134
135    /**
136     * Returns the sign of East
137     * @return int
138     */
139    public function getEastSign() {
140        return $this->east;
141    }
142
143    /**
144     * Returns whether this globe is registered (and hence, we know its properties)
145     * @return bool
146     */
147    public function isKnown() {
148        return $this->known;
149    }
150
151    /**
152     * Compares this globe to another
153     * @param Globe $other
154     * @return bool
155     */
156    public function equalsTo( Globe $other ) {
157        return $this->name === $other->name;
158    }
159
160    /**
161     * Checks whether given coordinates are valid
162     * @param int|float|string $lat
163     * @param int|float|string $lon
164     * @return bool
165     */
166    public function coordinatesAreValid( $lat, $lon ) {
167        if ( !is_numeric( $lat ) || !is_numeric( $lon ) ) {
168            return false;
169        }
170        $lat = (float)$lat;
171        $lon = (float)$lon;
172
173        return $lon >= $this->minLon && $lon <= $this->maxLon
174            && abs( $lat ) <= 90;
175    }
176}