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

src/Formatter/Coordinate/DMS.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 "DMS"
10
 *
11
 * @author Marcus Jaschen <[email protected]>
12
 */
13
class DMS 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 array
39
     */
40
    protected $units = [
41
        'UTF-8' => [
42
            'deg' => '°',
43
            'min' => '′',
44
            'sec' => '″',
45
        ],
46
        'ASCII' => [
47
            'deg' => '°',
48
            'min' => '\'',
49
            'sec' => '"',
50
        ],
51
    ];
52
53
    /**
54
     * @param string $separator
55
     *
56
     * @throws \InvalidArgumentException
57
     */
58
    public function __construct(string $separator = ' ')
59
    {
60
        $this->separator          = $separator;
61
        $this->useCardinalLetters = false;
62
        $this->setUnits(static::UNITS_UTF8);
63
    }
64
65
    /**
66
     * Sets the separator between latitude and longitude values
67
     *
68
     * @param string $separator
69
     *
70
     * @return DMS
71
     */
72
    public function setSeparator(string $separator): DMS
73
    {
74
        $this->separator = $separator;
75
76
        return $this;
77
    }
78
79
    /**
80
     * @param bool $value
81
     *
82
     * @return DMS
83
     */
84
    public function useCardinalLetters(bool $value): DMS
85
    {
86
        $this->useCardinalLetters = $value;
87
88
        return $this;
89
    }
90
91
    /**
92
     * @param string $type
93
     *
94
     * @return DMS
95
     * @throws \InvalidArgumentException
96
     */
97 View Code Duplication
    public function setUnits(string $type): DMS
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...
98
    {
99
        if (! array_key_exists($type, $this->units)) {
100
            throw new \InvalidArgumentException('Invalid unit type');
101
        }
102
103
        $this->unitType = $type;
104
105
        return $this;
106
    }
107
108
    /**
109
     * @param Coordinate $coordinate
110
     *
111
     * @return string
112
     */
113
    public function format(Coordinate $coordinate): string
114
    {
115
        $lat = $coordinate->getLat();
116
        $lng = $coordinate->getLng();
117
118
        $latValue   = abs($lat);
119
        $latDegrees = (int)$latValue;
120
121
        $latMinutesDecimal = $latValue - $latDegrees;
122
        $latMinutes        = (int)(60 * $latMinutesDecimal);
123
124
        $latSeconds = 60 * (60 * $latMinutesDecimal - $latMinutes);
125
126
        $lngValue   = abs($lng);
127
        $lngDegrees = (int)$lngValue;
128
129
        $lngMinutesDecimal = $lngValue - $lngDegrees;
130
        $lngMinutes        = (int)(60 * $lngMinutesDecimal);
131
132
        $lngSeconds = 60 * (60 * $lngMinutesDecimal - $lngMinutes);
133
134
        return sprintf(
135
            '%s%02d%s %02d%s %02d%s%s%s%s%03d%s %02d%s %02d%s%s',
136
            $this->getLatPrefix($lat),
137
            abs($latDegrees),
138
            $this->units[$this->unitType]['deg'],
139
            $latMinutes,
140
            $this->units[$this->unitType]['min'],
141
            round($latSeconds, 0),
142
            $this->units[$this->unitType]['sec'],
143
            $this->getLatSuffix($lat),
144
            $this->separator,
145
            $this->getLngPrefix($lng),
146
            abs($lngDegrees),
147
            $this->units[$this->unitType]['deg'],
148
            $lngMinutes,
149
            $this->units[$this->unitType]['min'],
150
            round($lngSeconds, 0),
151
            $this->units[$this->unitType]['sec'],
152
            $this->getLngSuffix($lng)
153
        );
154
    }
155
156
    /**
157
     * @param float $lat
158
     *
159
     * @return string
160
     */
161
    protected function getLatPrefix(float $lat): string
162
    {
163
        if ($this->useCardinalLetters || $lat >= 0) {
164
            return '';
165
        }
166
167
        return '-';
168
    }
169
170
    /**
171
     * @param float $lng
172
     *
173
     * @return string
174
     */
175
    protected function getLngPrefix(float $lng): string
176
    {
177
        if ($this->useCardinalLetters || $lng >= 0) {
178
            return '';
179
        }
180
181
        return '-';
182
    }
183
184
    /**
185
     * @param float $lat
186
     *
187
     * @return string
188
     */
189
    protected function getLatSuffix(float $lat): string
190
    {
191
        if (! $this->useCardinalLetters) {
192
            return '';
193
        }
194
195
        if ($lat >= 0) {
196
            return ' N';
197
        }
198
199
        return ' S';
200
    }
201
202
    /**
203
     * @param float $lng
204
     *
205
     * @return string
206
     */
207
    protected function getLngSuffix(float $lng): string
208
    {
209
        if (! $this->useCardinalLetters) {
210
            return '';
211
        }
212
213
        if ($lng >= 0) {
214
            return ' E';
215
        }
216
217
        return ' W';
218
    }
219
}
220