Completed
Push — master ( 8e8eb9...d3ac58 )
by Bradley
04:13
created

Mapper::generateRenderOptions()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
c 0
b 0
f 0
cc 6
eloc 7
nc 4
nop 1
rs 8.8571
1
<?php namespace Cornford\Googlmapper;
2
3
use Cornford\Googlmapper\Contracts\MappingInterface;
4
use Cornford\Googlmapper\Exceptions\MapperArgumentException;
5
use Cornford\Googlmapper\Exceptions\MapperException;
6
use Cornford\Googlmapper\Exceptions\MapperSearchException;
7
use Cornford\Googlmapper\Exceptions\MapperSearchLimitException;
8
use Cornford\Googlmapper\Exceptions\MapperSearchResultException;
9
use Cornford\Googlmapper\Models\Location;
10
use Cornford\Googlmapper\Models\Map;
11
use Cornford\Googlmapper\Models\Streetview;
12
use Exception;
13
14
class Mapper extends MapperBase implements MappingInterface {
15
16
	const GOOGLE_RESPONSE_OK = 'OK';
17
	const GOOGLE_RESPONSE_ZERO_RESULTS = 'ZERO_RESULTS';
18
	const GOOGLE_RESPONSE_QUERY_LIMIT = 'OVER_QUERY_LIMIT';
19
	const GOOGLE_RESPONSE_DENIED = 'REQUEST_DENIED';
20
	const GOOGLE_RESPONSE_INVALID = 'INVALID_REQUEST';
21
	const GOOGLE_RESPONSE_UNKNOWN = 'UNKNOWN_ERROR';
22
23
	/**
24
	 * Renders and returns Google Map code.
25
	 *
26
	 * @param integer $item
27
	 *
28
	 * @return string
29
	 */
30
	public function render($item = -1)
31
	{
32
		if (!$this->isEnabled()) {
33
			return;
34
		}
35
36
		return $this->view->make('googlmapper::mapper')
0 ignored issues
show
Bug introduced by
The method withView() does not seem to exist on object<Illuminate\Contracts\View\View>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
37
			->withView($this->view)
38
			->withOptions($this->generateRenderOptions($item))
39
			->withItems($item > -1 ? [$item => $this->getItem($item)] : $this->getItems())
40
			->render();
41
	}
42
43
	/**
44
	 * Renders and returns Google Map javascript code.
45
	 *
46
	 * @return string
47
	 */
48
	public function renderJavascript()
49
	{
50
		if (!$this->isEnabled()) {
51
			return;
52
		}
53
54
		return $this->view->make('googlmapper::javascript')
0 ignored issues
show
Bug introduced by
The method withView() does not seem to exist on object<Illuminate\Contracts\View\View>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
55
			->withView($this->view)
56
			->withOptions($this->generateRenderOptions())
57
			->render();
58
	}
59
60
	/**
61
	 * Generates the render options for Google Map.
62
	 *
63
	 * @param integer $item
64
	 *
65
	 * @return string
66
	 */
67
	protected function generateRenderOptions($item = -1)
68
	{
69
		$options = $this->getOptions();
70
71
		foreach (($item > -1 ? [$this->getItem($item)] : $this->getItems()) as $model) {
72
			foreach ($model->getOptions() as $key => $option) {
73
				if (array_key_exists($key, $this->getOptions()) && $this->getOptions()[$key] !== $option) {
74
					$options[$key] = $option;
75
				}
76
			}
77
		}
78
79
		return $options;
80
	}
81
82
	/**
83
	 * Search for a location against Google Maps Api.
84
	 *
85
	 * @param string $location
86
	 *
87
	 * @return mixed
88
	 */
89
	protected function searchLocation($location)
90
	{
91
		$request = file_get_contents(
92
			sprintf(
93
				'https://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false&key=%s',
94
				urlencode($location),
95
				$this->getKey()
96
			)
97
		);
98
99
		return json_decode($request);
100
	}
101
102
	/**
103
	 * Locate a location and return a Location instance.
104
	 *
105
	 * @param string $location
106
	 *
107
	 * @throws MapperArgumentException
108
	 * @throws MapperSearchException
109
	 * @throws MapperSearchResultException
110
	 * @throws MapperSearchLimitException
111
	 * @throws MapperException
112
	 *
113
	 * @return Location
114
	 */
115
	public function location($location)
116
	{
117
		if (empty($location)) {
118
			throw new MapperArgumentException('Invalid location search term provided.');
119
		}
120
121
		try {
122
			$resultObject = $this->searchLocation($location);
123
		} catch (Exception $exception) {
124
			throw new MapperSearchException('Unable to perform location search, the error was: "' . $exception->getMessage() .  '".');
125
		}
126
127
		if (isset($resultObject->status) && $resultObject->status == self::GOOGLE_RESPONSE_QUERY_LIMIT) {
128
			throw new MapperSearchLimitException('Unable to perform location search, your API key is over your quota.');
129
		}
130
131
		if (isset($resultObject->status) &&
132
			in_array(
133
				$resultObject->status,
134
				[
135
					self::GOOGLE_RESPONSE_DENIED,
136
					self::GOOGLE_RESPONSE_INVALID,
137
					self::GOOGLE_RESPONSE_UNKNOWN
138
				]
139
			)
140
		) {
141
			throw new MapperSearchResultException('An error occurred performing the location search.');
142
		}
143
144
		if ((isset($resultObject->status) && $resultObject->status == self::GOOGLE_RESPONSE_ZERO_RESULTS) ||
145
			!isset($resultObject->results) ||
146
			(isset($resultObject->results) && count($resultObject->results) == 0)
147
		) {
148
			throw new MapperSearchResultException('No results found for the location search.');
149
		}
150
151
		if (!isset($resultObject->results[0]->formatted_address) ||
152
			!isset($resultObject->results[0]->address_components[0]->types[0]) ||
153
			!isset($resultObject->results[0]->geometry->location->lat) ||
154
			!isset($resultObject->results[0]->geometry->location->lng) ||
155
			!isset($resultObject->results[0]->place_id) ||
156
			isset($resultObject->status) && $resultObject->status != self::GOOGLE_RESPONSE_OK
157
		) {
158
			throw new MapperException('The location search return invalid result data.');
159
		}
160
161
		return new Location([
162
			'mapper'    => $this,
163
			'search'    => $location,
164
			'address'   => $resultObject->results[0]->formatted_address,
165
			'type'      => $resultObject->results[0]->address_components[0]->types[0],
166
			'latitude'  => $resultObject->results[0]->geometry->location->lat,
167
			'longitude' => $resultObject->results[0]->geometry->location->lng,
168
			'placeId'   => $resultObject->results[0]->place_id,
169
		]);
170
	}
171
172
	/**
173
	 * Add a new map.
174
	 *
175
	 * @param float $latitude
176
	 * @param float $longitude
177
	 * @param array $options
178
	 *
179
	 * @return self
180
	 */
181
	public function map($latitude, $longitude, array $options = [])
182
	{
183
		$parameters = array_replace_recursive(
184
			$this->getOptions(),
185
			[
186
				'latitude' => $latitude,
187
				'longitude' => $longitude,
188
				'map' => 'map_' . count($this->getItems())
189
			],
190
			$options
191
		);
192
193
		$item = new Map($parameters);
194
		$this->addItem($item);
195
196
		return $this;
197
	}
198
199
	/**
200
	 * Add a new street view map.
201
	 *
202
	 * @param float   $latitude
203
	 * @param float   $longitude
204
	 * @param integer $heading
205
	 * @param integer $pitch
206
	 * @param array   $options
207
	 *
208
	 * @return self
209
	 */
210
	public function streetview($latitude, $longitude, $heading, $pitch, array $options = [])
211
	{
212
		$parameters = array_replace_recursive(
213
			$this->getOptions(),
214
			[
215
				'latitude' => $latitude,
216
				'longitude' => $longitude,
217
				'heading' => $heading,
218
				'pitch' => $pitch,
219
				'map' => 'map_' . count($this->getItems())
220
			],
221
			$options
222
		);
223
224
		$item = new Streetview($parameters);
225
		$this->addItem($item);
226
227
		return $this;
228
	}
229
230
	/**
231
	 * Add a new map marker.
232
	 *
233
	 * @param float $latitude
234
	 * @param float $longitude
235
	 * @param array $options
236
	 *
237
	 * @throws MapperException
238
	 *
239
	 * @return self
240
	 */
241
	public function marker($latitude, $longitude, array $options = [])
242
	{
243
		$items = $this->getItems();
244
		$parameters = $this->getOptions();
245
		$options = array_replace_recursive(['user' => $parameters['user']], $parameters['markers'], $options);
246
247
		if (empty($items)) {
248
			throw new MapperException('No map found to add a marker to.');
249
		}
250
251
		$item = end($items);
252
		$item->marker($latitude, $longitude, $options);
253
254
		return $this;
255
	}
256
257
	/**
258
	 * Add a new map information window.
259
	 *
260
	 * @param float  $latitude
261
	 * @param float  $longitude
262
	 * @param string $content
263
	 * @param array  $options
264
	 *
265
	 * @throws MapperException
266
	 *
267
	 * @return self
268
	 */
269
	public function informationWindow($latitude, $longitude, $content, array $options = [])
270
	{
271
		$items = $this->getItems();
272
273
		if (empty($items)) {
274
			throw new MapperException('No map found to add a information window to.');
275
		}
276
277
		$parameters = $this->getOptions();
278
		$options = array_replace_recursive(['user' => $parameters['user']], ['markers' => $parameters['markers']], $options);
279
		$item = end($items);
280
		$item->marker($latitude, $longitude, array_replace_recursive($options, ['markers' => ['content' => $content]]));
281
282
		return $this;
283
	}
284
285
	/**
286
	 * Add a new map polyline.
287
	 *
288
	 * @param array $coordinates
289
	 * @param array $options
290
	 *
291
	 * @throws MapperException
292
	 *
293
	 * @return self
294
	 */
295
	public function polyline(array $coordinates = [], array $options = [])
296
	{
297
		$items = $this->getItems();
298
		$parameters = $this->getOptions();
299
300
		$defaults = [
301
			'coordinates' => $coordinates,
302
			'geodesic' => false,
303
			'strokeColor' => '#FF0000',
304
			'strokeOpacity' => 0.8,
305
			'strokeWeight' => 2,
306
			'editable' => false
307
		];
308
		$options = array_replace_recursive(['user' => $parameters['user']], $defaults, $options);
309
310
		if (empty($items)) {
311
			throw new MapperException('No map found to add a polyline to.');
312
		}
313
314
		$item = end($items);
315
		$item->shape('polyline', $coordinates, $options);
316
317
		return $this;
318
	}
319
320
	/**
321
	 * Add a new map polygon.
322
	 *
323
	 * @param array $coordinates
324
	 * @param array $options
325
	 *
326
	 * @throws MapperException
327
	 *
328
	 * @return self
329
	 */
330 View Code Duplication
	public function polygon(array $coordinates = [], array $options = [])
0 ignored issues
show
Duplication introduced by
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...
331
	{
332
		$items = $this->getItems();
333
		$parameters = $this->getOptions();
334
335
		$defaults = [
336
			'coordinates' => $coordinates,
337
			'strokeColor' => '#FF0000',
338
			'strokeOpacity' => 0.8,
339
			'strokeWeight' => 2,
340
			'fillColor' => '#FF0000',
341
			'fillOpacity' => 0.35,
342
			'editable' => false
343
		];
344
		$options = array_replace_recursive(['user' => $parameters['user']], $defaults, $options);
345
346
		if (empty($items)) {
347
			throw new MapperException('No map found to add a polygon to.');
348
		}
349
350
		$item = end($items);
351
		$item->shape('polygon', $coordinates, $options);
352
353
		return $this;
354
	}
355
356
	/**
357
	 * Add a new map rectangle.
358
	 *
359
	 * @param array $coordinates
360
	 * @param array $options
361
	 *
362
	 * @throws MapperException
363
	 *
364
	 * @return self
365
	 */
366 View Code Duplication
	public function rectangle(array $coordinates = [], array $options = [])
0 ignored issues
show
Duplication introduced by
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...
367
	{
368
		$items = $this->getItems();
369
		$parameters = $this->getOptions();
370
371
		$defaults = [
372
			'coordinates' => $coordinates,
373
			'strokeColor' => '#FF0000',
374
			'strokeOpacity' => 0.8,
375
			'strokeWeight' => 2,
376
			'fillColor' => '#FF0000',
377
			'fillOpacity' => 0.35,
378
			'editable' => false
379
		];
380
		$options = array_replace_recursive(['user' => $parameters['user']], $defaults, $options);
381
382
		if (empty($items)) {
383
			throw new MapperException('No map found to add a rectangle to.');
384
		}
385
386
		$item = end($items);
387
		$item->shape('rectangle', $coordinates, $options);
388
389
		return $this;
390
	}
391
392
	/**
393
	 * Add a new map circle.
394
	 *
395
	 * @param array $coordinates
396
	 * @param array $options
397
	 *
398
	 * @throws MapperException
399
	 *
400
	 * @return self
401
	 */
402 View Code Duplication
	public function circle(array $coordinates = [], array $options = [])
0 ignored issues
show
Duplication introduced by
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...
403
	{
404
		$items = $this->getItems();
405
		$parameters = $this->getOptions();
406
407
		$defaults = [
408
			'coordinates' => $coordinates,
409
			'strokeColor' => '#FF0000',
410
			'strokeOpacity' => 0.8,
411
			'strokeWeight' => 2,
412
			'fillColor' => '#FF0000',
413
			'fillOpacity' => 0.35,
414
			'radius' => 100000,
415
			'editable' => false
416
		];
417
		$options = array_replace_recursive(['user' => $parameters['user']], $defaults, $options);
418
419
		if (empty($items)) {
420
			throw new MapperException('No map found to add a circle to.');
421
		}
422
423
		$item = end($items);
424
		$item->shape('circle', $coordinates, $options);
425
426
		return $this;
427
	}
428
429
}
430