Completed
Pull Request — master (#1)
by ARCANEDEV
14:00
created

DistanceMatrixService::setMode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php namespace Arcanedev\GeoLocation\Google\DistanceMatrix;
2
3
use Arcanedev\GeoLocation\Contracts\Entities\Position;
4
use GuzzleHttp\ClientInterface;
5
use InvalidArgumentException;
6
7
/**
8
 * Class     DistanceMatrixService
9
 *
10
 * @package  Arcanedev\GeoLocation\Google\DistanceMatrix
11
 * @author   ARCANEDEV <[email protected]>
12
 *
13
 * @link     https://developers.google.com/maps/documentation/distance-matrix/intro
14
 */
15
class DistanceMatrixService
16
{
17
    /* -----------------------------------------------------------------
18
     |  Constants
19
     | -----------------------------------------------------------------
20
     */
21
22
    const BASE_URL = 'https://maps.googleapis.com/maps/api/distancematrix/json';
23
24
    /* -----------------------------------------------------------------
25
     |  Properties
26
     | -----------------------------------------------------------------
27
     */
28
29
    /** @var  \GuzzleHttp\ClientInterface */
30
    protected $client;
31
32
    /** @var string */
33
    protected $language = 'en';
34
35
    /** @var string */
36
    protected $mode = 'driving';
37
38
    /** @var string */
39
    protected $units = 'metric';
40
41
    /* -----------------------------------------------------------------
42
     |  Constructor
43
     | -----------------------------------------------------------------
44
     */
45
46
    /**
47
     * GoogleDistanceMatrix constructor.
48
     *
49
     * @param  \GuzzleHttp\ClientInterface  $client
50
     */
51
    public function __construct(ClientInterface $client)
52
    {
53
        $this->setHttpClient($client);
54
    }
55
56
    /* -----------------------------------------------------------------
57
     |  Getters & Setters
58
     | -----------------------------------------------------------------
59
     */
60
61
    /**
62
     * Set the HTTP Client.
63
     *
64
     * @param  \GuzzleHttp\ClientInterface  $client
65
     *
66
     * @return self
67
     */
68
    public function setHttpClient(ClientInterface $client)
69
    {
70
        $this->client = $client;
71
72
        return $this;
73
    }
74
75
    /**
76
     * Set the language.
77
     *
78
     * @param  string  $language
79
     *
80
     * @return self
81
     */
82
    public function setLanguage($language)
83
    {
84
        $this->language = $language;
85
86
        return $this;
87
    }
88
89
    /**
90
     * Set the mode of transport.
91
     *
92
     * @param  string  $mode
93
     *
94
     * @return self
95
     */
96
    public function setMode($mode)
97
    {
98
        $this->mode = $this->checkMode($mode);
99
100
        return $this;
101
    }
102
103
    /**
104
     * Set the unit system.
105
     *
106
     * @param  string  $units
107
     *
108
     * @return self
109
     */
110
    public function setUnits($units)
111
    {
112
        $this->units = $this->checkUnits($units);
113
114
        return $this;
115
    }
116
117
    /* -----------------------------------------------------------------
118
     |  Main Methods
119
     | -----------------------------------------------------------------
120
     */
121
122
    /**
123
     * Calculate the distance.
124
     *
125
     * @param  \Arcanedev\GeoLocation\Contracts\Entities\Position  $start
126
     * @param  \Arcanedev\GeoLocation\Contracts\Entities\Position  $end
127
     * @param  array                                               $options
128
     *
129
     * @return \Arcanedev\GeoLocation\Google\DistanceMatrix\DistanceMatrixResponse
130
     */
131
    public function calculate(Position $start, Position $end, array $options = [])
132
    {
133
        // https://developers.google.com/maps/documentation/distance-matrix/intro
134
135
        $url = static::BASE_URL.'?'.$this->prepareQuery($start, $end);
136
137
        $result = $this->client->request('GET', $url, $options);
138
139
        return new DistanceMatrixResponse(
140
            json_decode($result->getBody(), true)
141
        );
142
    }
143
144
    /**
145
     * Prepare the URL query.
146
     *
147
     * @param  \Arcanedev\GeoLocation\Contracts\Entities\Position  $start
148
     * @param  \Arcanedev\GeoLocation\Contracts\Entities\Position  $end
149
     *
150
     * @return string
151
     */
152
    private function prepareQuery(Position $start, Position $end)
153
    {
154
        $queryData = [
155
            'origins'      => $this->parsePosition($start),
156
            'destinations' => $this->parsePosition($end),
157
            'mode'         => $this->mode,
158
            'language'     => $this->language,
159
            'units'        => $this->units,
160
        ];
161
162
        return urldecode(http_build_query($queryData));
163
    }
164
165
    /**
166
     * Parse the position object.
167
     *
168
     * @param  \Arcanedev\GeoLocation\Contracts\Entities\Position  $position
169
     *
170
     * @return string
171
     */
172
    private function parsePosition(Position $position)
173
    {
174
        return $position->lat()->value().','.$position->long()->value();
175
    }
176
177
    /* -----------------------------------------------------------------
178
     |  Other Methods
179
     | -----------------------------------------------------------------
180
     */
181
182
    /**
183
     * Check the mode of transport.
184
     *
185
     * @param  string  $mode
186
     *
187
     * @return string
188
     */
189
    private function checkMode($mode)
190
    {
191
        $mode = strtolower($mode);
192
193
        if ( ! in_array($mode, ['driving', 'walking', 'bicycling', 'transit'])) {
194
            throw new InvalidArgumentException(
195
                "The given mode of transport [{$mode}] is invalid. Please check the supported travel modes: ".
196
                "https://developers.google.com/maps/documentation/distance-matrix/intro#travel_modes"
197
            );
198
        }
199
200
        return $mode;
201
    }
202
203
    /**
204
     * Check the unit system.
205
     *
206
     * @param  string  $units
207
     *
208
     * @return string
209
     */
210
    private function checkUnits($units)
211
    {
212
        $units = strtolower($units);
213
214
        if ( ! in_array($units, ['metric', 'imperial'])) {
215
            throw new InvalidArgumentException(
216
                "The given unit system [{$units}] is invalid. Please check the supported units: ".
217
                "https://developers.google.com/maps/documentation/distance-matrix/intro#unit_systems"
218
            );
219
        }
220
221
        return $units;
222
    }
223
}
224