Completed
Push — cleanup/small-fixes ( a08300 )
by Marcus
01:18
created

src/Formatter/Coordinate/DecimalMinutes.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
declare(strict_types=1);
3
4
namespace Location\Formatter\Coordinate;
5
6
use Location\Coordinate;
7
8
/**
9
 * Coordinate Formatter "DecimalMinutes"
10
 *
11
 * @author Marcus Jaschen <[email protected]>
12
 */
13
class DecimalMinutes implements FormatterInterface
14
{
15
    const UNITS_UTF8  = 'UTF-8';
16
    const UNITS_ASCII = 'ASCII';
17
18
    /**
19
     * @var string Separator string between latitude and longitude
20
     */
21
    protected $separator;
22
23
    /**
24
     * Use cardinal letters for N/S and W/E instead of minus sign
25
     *
26
     * @var bool
27
     */
28
    protected $useCardinalLetters;
29
30
    /**
31
     * @var string
32
     *
33
     * @psalm-suppress PropertyNotSetInConstructor
34
     */
35
    protected $unitType;
36
37
    /**
38
     * @var int
39
     */
40
    protected $digits = 3;
41
42
    /**
43
     * @var string
44
     */
45
    protected $decimalPoint = '.';
46
47
    /**
48
     * @var array
49
     */
50
    protected $units = [
51
        'UTF-8' => [
52
            'deg' => '°',
53
            'min' => '′',
54
        ],
55
        'ASCII' => [
56
            'deg' => '°',
57
            'min' => '\'',
58
        ],
59
    ];
60
61
    /**
62
     * @param string $separator
63
     */
64
    public function __construct(string $separator = ' ')
65
    {
66
        $this->separator          = $separator;
67
        $this->useCardinalLetters = false;
68
69
        $this->setUnits(static::UNITS_UTF8);
70
    }
71
72
    /**
73
     * Sets the separator between latitude and longitude values
74
     *
75
     * @param string $separator
76
     *
77
     * @return DecimalMinutes
78
     */
79
    public function setSeparator(string $separator): DecimalMinutes
80
    {
81
        $this->separator = $separator;
82
83
        return $this;
84
    }
85
86
    /**
87
     * @param bool $value
88
     *
89
     * @return DecimalMinutes
90
     */
91
    public function useCardinalLetters(bool $value): DecimalMinutes
92
    {
93
        $this->useCardinalLetters = $value;
94
95
        return $this;
96
    }
97
98
    /**
99
     * @param string $type
100
     *
101
     * @return DecimalMinutes
102
     * @throws \InvalidArgumentException
103
     */
104 View Code Duplication
    public function setUnits(string $type): DecimalMinutes
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
105
    {
106
        if (! array_key_exists($type, $this->units)) {
107
            throw new \InvalidArgumentException('Invalid unit type');
108
        }
109
110
        $this->unitType = $type;
111
112
        return $this;
113
    }
114
115
    /**
116
     * @param int $digits
117
     *
118
     * @return DecimalMinutes
119
     */
120
    public function setDigits(int $digits): DecimalMinutes
121
    {
122
        $this->digits = $digits;
123
124
        return $this;
125
    }
126
127
    /**
128
     * @param string $decimalPoint
129
     *
130
     * @return DecimalMinutes
131
     */
132
    public function setDecimalPoint(string $decimalPoint): DecimalMinutes
133
    {
134
        $this->decimalPoint = $decimalPoint;
135
136
        return $this;
137
    }
138
139
    /**
140
     * @param Coordinate $coordinate
141
     *
142
     * @return string
143
     */
144
    public function format(Coordinate $coordinate): string
145
    {
146
        $lat = $coordinate->getLat();
147
        $lng = $coordinate->getLng();
148
149
        $latValue   = abs($lat);
150
        $latDegrees = (int)$latValue;
151
152
        $latMinutesDecimal = $latValue - $latDegrees;
153
        $latMinutes        = 60 * $latMinutesDecimal;
154
155
        $lngValue   = abs($lng);
156
        $lngDegrees = (int)$lngValue;
157
158
        $lngMinutesDecimal = $lngValue - $lngDegrees;
159
        $lngMinutes        = 60 * $lngMinutesDecimal;
160
161
        return sprintf(
162
            '%s%02d%s %s%s%s%s%s%03d%s %s%s%s',
163
            $this->getLatPrefix($lat),
164
            abs($latDegrees),
165
            $this->units[$this->unitType]['deg'],
166
            number_format($latMinutes, $this->digits, $this->decimalPoint, $this->decimalPoint),
167
            $this->units[$this->unitType]['min'],
168
            $this->getLatSuffix($lat),
169
            $this->separator,
170
            $this->getLngPrefix($lng),
171
            abs($lngDegrees),
172
            $this->units[$this->unitType]['deg'],
173
            number_format($lngMinutes, $this->digits, $this->decimalPoint, $this->decimalPoint),
174
            $this->units[$this->unitType]['min'],
175
            $this->getLngSuffix($lng)
176
        );
177
    }
178
179
    /**
180
     * @param float $lat
181
     *
182
     * @return string
183
     */
184
    protected function getLatPrefix(float $lat): string
185
    {
186
        if ($this->useCardinalLetters || $lat >= 0) {
187
            return '';
188
        }
189
190
        return '-';
191
    }
192
193
    /**
194
     * @param float $lng
195
     *
196
     * @return string
197
     */
198
    protected function getLngPrefix(float $lng): string
199
    {
200
        if ($this->useCardinalLetters || $lng >= 0) {
201
            return '';
202
        }
203
204
        return '-';
205
    }
206
207
    /**
208
     * @param float $lat
209
     *
210
     * @return string
211
     */
212
    protected function getLatSuffix(float $lat): string
213
    {
214
        if (! $this->useCardinalLetters) {
215
            return '';
216
        }
217
218
        if ($lat >= 0) {
219
            return ' N';
220
        }
221
222
        return ' S';
223
    }
224
225
    /**
226
     * @param float $lng
227
     *
228
     * @return string
229
     */
230
    protected function getLngSuffix(float $lng): string
231
    {
232
        if (! $this->useCardinalLetters) {
233
            return '';
234
        }
235
236
        if ($lng >= 0) {
237
            return ' E';
238
        }
239
240
        return ' W';
241
    }
242
}
243