DecimalMinutes   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 238
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 1
dl 0
loc 238
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A setDigits() 0 6 1
A setDecimalPoint() 0 6 1
A format() 0 34 1
A getLatPrefix() 0 8 3
A getLngPrefix() 0 8 3
A getLatSuffix() 0 12 3
A getLngSuffix() 0 12 3
A __construct() 0 7 1
A setSeparator() 0 6 1
A useCardinalLetters() 0 6 1
A setUnits() 0 10 2
A getUnitType() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Location\Formatter\Coordinate;
6
7
use InvalidArgumentException;
8
use Location\Coordinate;
9
10
/**
11
 * Coordinate Formatter "DecimalMinutes"
12
 *
13
 * @author Marcus Jaschen <[email protected]>
14
 */
15
class DecimalMinutes implements FormatterInterface
16
{
17
    public const UNITS_UTF8  = 'UTF-8';
18
    public const UNITS_ASCII = 'ASCII';
19
20
    /**
21
     * @var string Separator string between latitude and longitude
22
     */
23
    protected $separator;
24
25
    /**
26
     * Use cardinal letters for N/S and W/E instead of minus sign
27
     *
28
     * @var bool
29
     */
30
    protected $useCardinalLetters;
31
32
    /**
33
     * @var string
34
     *
35
     * @psalm-suppress PropertyNotSetInConstructor
36
     */
37
    protected $unitType;
38
39
    /**
40
     * @var int
41
     */
42
    protected $digits = 3;
43
44
    /**
45
     * @var string
46
     */
47
    protected $decimalPoint = '.';
48
49
    /**
50
     * @var array
51
     */
52
    protected $units = [
53
        'UTF-8' => [
54
            'deg' => '°',
55
            'min' => '′',
56
        ],
57
        'ASCII' => [
58
            'deg' => '°',
59
            'min' => '\'',
60
        ],
61
    ];
62
63
    /**
64
     * @param string $separator
65
     */
66
    public function __construct(string $separator = ' ')
67
    {
68
        $this->separator          = $separator;
69
        $this->useCardinalLetters = false;
70
71
        $this->setUnits(static::UNITS_UTF8);
72
    }
73
74
    /**
75
     * Sets the separator between latitude and longitude values
76
     *
77
     * @param string $separator
78
     *
79
     * @return DecimalMinutes
80
     */
81
    public function setSeparator(string $separator): DecimalMinutes
82
    {
83
        $this->separator = $separator;
84
85
        return $this;
86
    }
87
88
    /**
89
     * @param bool $value
90
     *
91
     * @return DecimalMinutes
92
     */
93
    public function useCardinalLetters(bool $value): DecimalMinutes
94
    {
95
        $this->useCardinalLetters = $value;
96
97
        return $this;
98
    }
99
100
    /**
101
     * @param string $type
102
     *
103
     * @return DecimalMinutes
104
     * @throws \InvalidArgumentException
105
     */
106
    public function setUnits(string $type): DecimalMinutes
107
    {
108
        if (! array_key_exists($type, $this->units)) {
109
            throw new InvalidArgumentException('Invalid unit type');
110
        }
111
112
        $this->unitType = $type;
113
114
        return $this;
115
    }
116
117
    /**
118
     * @return string
119
     */
120
    public function getUnitType(): string
121
    {
122
        return $this->unitType;
123
    }
124
125
    /**
126
     * @param int $digits
127
     *
128
     * @return DecimalMinutes
129
     */
130
    public function setDigits(int $digits): DecimalMinutes
131
    {
132
        $this->digits = $digits;
133
134
        return $this;
135
    }
136
137
    /**
138
     * @param string $decimalPoint
139
     *
140
     * @return DecimalMinutes
141
     */
142
    public function setDecimalPoint(string $decimalPoint): DecimalMinutes
143
    {
144
        $this->decimalPoint = $decimalPoint;
145
146
        return $this;
147
    }
148
149
    /**
150
     * @param Coordinate $coordinate
151
     *
152
     * @return string
153
     */
154
    public function format(Coordinate $coordinate): string
155
    {
156
        $lat = $coordinate->getLat();
157
        $lng = $coordinate->getLng();
158
159
        $latValue   = abs($lat);
160
        $latDegrees = (int)$latValue;
161
162
        $latMinutesDecimal = $latValue - $latDegrees;
163
        $latMinutes        = 60 * $latMinutesDecimal;
164
165
        $lngValue   = abs($lng);
166
        $lngDegrees = (int)$lngValue;
167
168
        $lngMinutesDecimal = $lngValue - $lngDegrees;
169
        $lngMinutes        = 60 * $lngMinutesDecimal;
170
171
        return sprintf(
172
            '%s%02d%s %s%s%s%s%s%03d%s %s%s%s',
173
            $this->getLatPrefix($lat),
174
            abs($latDegrees),
175
            $this->units[$this->unitType]['deg'],
176
            number_format($latMinutes, $this->digits, $this->decimalPoint, $this->decimalPoint),
177
            $this->units[$this->unitType]['min'],
178
            $this->getLatSuffix($lat),
179
            $this->separator,
180
            $this->getLngPrefix($lng),
181
            abs($lngDegrees),
182
            $this->units[$this->unitType]['deg'],
183
            number_format($lngMinutes, $this->digits, $this->decimalPoint, $this->decimalPoint),
184
            $this->units[$this->unitType]['min'],
185
            $this->getLngSuffix($lng)
186
        );
187
    }
188
189
    /**
190
     * @param float $lat
191
     *
192
     * @return string
193
     */
194
    protected function getLatPrefix(float $lat): string
195
    {
196
        if ($this->useCardinalLetters || $lat >= 0) {
197
            return '';
198
        }
199
200
        return '-';
201
    }
202
203
    /**
204
     * @param float $lng
205
     *
206
     * @return string
207
     */
208
    protected function getLngPrefix(float $lng): string
209
    {
210
        if ($this->useCardinalLetters || $lng >= 0) {
211
            return '';
212
        }
213
214
        return '-';
215
    }
216
217
    /**
218
     * @param float $lat
219
     *
220
     * @return string
221
     */
222
    protected function getLatSuffix(float $lat): string
223
    {
224
        if (! $this->useCardinalLetters) {
225
            return '';
226
        }
227
228
        if ($lat >= 0) {
229
            return ' N';
230
        }
231
232
        return ' S';
233
    }
234
235
    /**
236
     * @param float $lng
237
     *
238
     * @return string
239
     */
240
    protected function getLngSuffix(float $lng): string
241
    {
242
        if (! $this->useCardinalLetters) {
243
            return '';
244
        }
245
246
        if ($lng >= 0) {
247
            return ' E';
248
        }
249
250
        return ' W';
251
    }
252
}
253