Completed
Push — update/google-maps-api ( 3bde02 )
by
unknown
10:48
created

Jetpack_Contact_Info_Widget::widget()   D

Complexity

Conditions 13
Paths 168

Size

Total Lines 77
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 31
nc 168
nop 2
dl 0
loc 77
rs 4.8488
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
if ( ! class_exists( 'Jetpack_Contact_Info_Widget' ) ) {
4
5
	//register Contact_Info_Widget widget
6
	function jetpack_contact_info_widget_init() {
7
		register_widget( 'Jetpack_Contact_Info_Widget' );
8
	}
9
10
	add_action( 'widgets_init', 'jetpack_contact_info_widget_init' );
11
12
	/**
13
	 * Makes a custom Widget for displaying Restaurant Location/Map, Hours, and Contact Info available.
14
	 *
15
	 * @package WordPress
16
	 */
17
	class Jetpack_Contact_Info_Widget extends WP_Widget {
18
19
		/**
20
		 * Constructor
21
		 */
22 View Code Duplication
		function __construct() {
23
			$widget_ops = array(
24
				'classname' => 'widget_contact_info',
25
				'description' => __( 'Display a map with your location, hours, and contact information.', 'jetpack' ),
26
				'customize_selective_refresh' => true,
27
			);
28
			parent::__construct(
29
				'widget_contact_info',
30
				/** This filter is documented in modules/widgets/facebook-likebox.php */
31
				apply_filters( 'jetpack_widget_name', __( 'Contact Info & Map', 'jetpack' ) ),
32
				$widget_ops
33
			);
34
			$this->alt_option_name = 'widget_contact_info';
35
36
			if ( is_customize_preview() ) {
37
				add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
38
			}
39
		}
40
41
		/**
42
		 * Enqueue scripts and styles.
43
		 */
44
		public function enqueue_scripts() {
45
			wp_enqueue_style( 'contact-info-map-css', plugins_url( 'contact-info/contact-info-map.css', __FILE__ ), null, 20160623 );
46
		}
47
48
49
		/**
50
		 * Return an associative array of default values
51
		 *
52
		 * These values are used in new widgets.
53
		 *
54
		 * @return array Array of default values for the Widget's options
55
		 */
56
		public function defaults() {
57
			return array(
58
				'title'   => __( 'Hours & Info', 'jetpack' ),
59
				'address' => __( "3999 Mission Boulevard,\nSan Diego CA 92109", 'jetpack' ),
60
				'phone'   => _x( '1-202-555-1212', 'Example of a phone number', 'jetpack' ),
61
				'hours'   => __( "Lunch: 11am - 2pm \nDinner: M-Th 5pm - 11pm, Fri-Sat:5pm - 1am", 'jetpack' ),
62
				'email'   => null,
63
				'showmap' => 0,
64
				'apikey'  => null,
65
				'lat'     => null,
66
				'lon'     => null,
67
				'apikey_error' => null,
68
			);
69
		}
70
71
		/**
72
		 * Outputs the HTML for this widget.
73
		 *
74
		 * @param array $args     An array of standard parameters for widgets in this theme
75
		 * @param array $instance An array of settings for this widget instance
76
		 *
77
		 * @return void Echoes it's output
78
		 **/
79
		function widget( $args, $instance ) {
80
			$instance = wp_parse_args( $instance, $this->defaults() );
81
82
			echo $args['before_widget'];
83
84
			if ( '' != $instance['title'] ) {
85
				echo $args['before_title'] . $instance['title'] . $args['after_title'];
86
			}
87
88
			/**
89
			 * Fires at the beginning of the Contact Info widget, after the title.
90
			 *
91
			 * @module widgets
92
			 *
93
			 * @since 3.9.2
94
			 */
95
			do_action( 'jetpack_contact_info_widget_start' );
96
97
			echo '<div itemscope itemtype="http://schema.org/LocalBusiness">';
98
99
			if ( '' != $instance['address'] ) {
100
101
				$showmap = $instance['showmap'];
102
103
				if ( $showmap && empty( $instance['apikey'] ) && wp_get_current_user() ) {
104
					if ( current_user_can( 'edit_theme_options' ) ) {
105
						echo '<div style="color:red;">' . esc_html__( 'Please add a valid Google MAPS API. (This message is only shown to Administators)', 'jetpack' ) . '</div>';
106
					}
107
				}
108
109
				if ( $showmap && $this->has_good_map( $instance ) ) {
110
111
					echo $this->build_map( $instance['address'], $this->get_google_api_key( $instance ) );
112
				}
113
114
115
				$map_link = $this->build_map_link( $instance['address'] );
116
117
				echo '<div class="confit-address" itemscope itemtype="http://schema.org/PostalAddress" itemprop="address"><a href="' . esc_url( $map_link ) . '" target="_blank">' . str_replace( "\n", "<br/>", esc_html( $instance['address'] ) ) . "</a></div>";
118
			}
119
120
			if ( '' != $instance['phone'] ) {
121
				if ( wp_is_mobile() ) {
122
					echo '<div class="confit-phone"><span itemprop="telephone"><a href="' . esc_url( 'tel:' . $instance['phone'] ) . '">' . esc_html( $instance['phone'] ) . "</a></span></div>";
123
				}
124
				else {
125
					echo '<div class="confit-phone"><span itemprop="telephone">' . esc_html( $instance['phone'] ) . '</span></div>';
126
				}
127
			}
128
129
			if ( is_email( trim( $instance['email'] ) ) ) {
130
				printf(
131
					'<div class="confit-email"><a href="mailto:%1$s">%1$s</a></div>',
132
					esc_html( $instance['email'] )
133
				);
134
			}
135
136
			if ( '' != $instance['hours'] ) {
137
				echo '<div class="confit-hours" itemprop="openingHours">' . str_replace( "\n", "<br/>", esc_html( $instance['hours'] ) ) . "</div>";
138
			}
139
140
			echo '</div>';
141
142
			/**
143
			 * Fires at the end of Contact Info widget.
144
			 *
145
			 * @module widgets
146
			 *
147
			 * @since 3.9.2
148
			 */
149
			do_action( 'jetpack_contact_info_widget_end' );
150
151
			echo $args['after_widget'];
152
153
			/** This action is documented in modules/widgets/gravatar-profile.php */
154
			do_action( 'jetpack_stats_extra', 'widget_view', 'contact_info' );
155
		}
156
157
158
		/**
159
		 * Deals with the settings when they are saved by the admin. Here is
160
		 * where any validation should be dealt with.
161
		 *
162
		 * @param array $new_instance New configuration values
163
		 * @param array $old_instance Old configuration values
164
		 *
165
		 * @return array
166
		 */
167
			function update( $new_instance, $old_instance ) {
168
				$instance            = array();
169
				$instance['title']   = wp_kses( $new_instance['title'], array() );
170
				$instance['address'] = wp_kses( $new_instance['address'], array() );
171
				$instance['phone']   = wp_kses( $new_instance['phone'], array() );
172
				$instance['email']   = wp_kses( $new_instance['email'], array() );
173
				$instance['hours']   = wp_kses( $new_instance['hours'], array() );
174
				$instance['apikey']  = wp_kses( isset( $new_instance['apikey'] ) ? $new_instance['apikey'] : $old_instance['apikey'], array() );
175
				$instance['lat']     = isset( $old_instance['lat'] ) ? floatval( $old_instance['lat'] ) : 0;
176
				$instance['lon']     = isset( $old_instance['lon'] ) ? floatval( $old_instance['lon'] ) : 0;
177
178
				if ( $this->recalcualte_log_and_lat( $new_instance, $old_instance ) ) {
179
						// Get the lat/lon of the user specified address.
180
					$address = $this->urlencode_address( $instance['address'] );
181
					$path    = "https://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=" . $address;
182
183
					if ( ! empty( $key ) ) {
0 ignored issues
show
Bug introduced by
The variable $key seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
184
						$path = add_query_arg( 'key', $this->get_google_api_key( $instance ), $path );
185
					}
186
					$json    = wp_remote_retrieve_body( wp_remote_get( esc_url( $path, null, null ) ) );
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 4 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
187
					if ( ! $json ) {
188
						// The read failed :(
189
						esc_html_e( "There was a problem getting the data to display this address on a map.  Please refresh your browser and try again.", 'jetpack' );
190
						die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method update() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
191
					}
192
193
					$json_obj = json_decode( $json );
194
195
					if ( isset( $json_obj->error_message ) ) {
196
						$instance['lat'] = "0";
197
						$instance['lon'] = "0";
198
						$instance['showmap'] = ( ! isset( $new_instance['showmap'] ) ) ? 0 : intval( $new_instance['showmap'] );
199
						$instance['apikey_error'] = $json_obj->status;
200
						return $instance;
201
					}
202
203
204
					if ( "ZERO_RESULTS" == $json_obj->status ) {
205
						// The address supplied does not have a matching lat / lon.
206
						// No map is available.
207
						$instance['lat'] = "0";
208
						$instance['lon'] = "0";
209
					} else {
210
						$loc = isset( $json_obj->results[0]->geometry->location )
211
						? $json_obj->results[0]->geometry->location :
212
						(object) array( 'lat' => 0, 'lng' => 0 );
213
214
						$lat = floatval( $loc->lat );
215
						$lon = floatval( $loc->lng );
216
217
						$instance['lat'] = "$lat";
218
						$instance['lon'] = "$lon";
219
					}
220
				}
221
				$instance['showmap'] = ( ! isset( $new_instance['showmap'] ) ) ? 0 : intval( $new_instance['showmap'] );
222
223
				return $instance;
224
		}
225
226
		function recalcualte_log_and_lat( $new_instance, $old_instance ) {
227
			if ( ! $new_instance['showmap'] ) {
228
				return false;
229
			}
230
231
			if ( empty( $new_instance['address'] ) ) {
232
				return false;
233
			}
234
235
			if ( empty( $new_instance['apikey'] ) ) {
236
				return false;
237
			}
238
239
			// New api keys
240
			if ( $new_instance['apikey'] !== $old_instance['apikey'] ) {
241
				return true;
242
			}
243
244
			// new Address
245
			if ( $this->urlencode_address( $old_instance['address'] ) !== $this->urlencode_address( $new_instance['address'] ) ) {
246
				return true;
247
			}
248
249
			// these values are set to nothing.
250
			if ( empty( $old_instance['lat'] ) || empty( $old_instance['lon'] ) ) {
251
				return true;
252
			}
253
254
			return false;
255
		}
256
257
258
		function get_google_api_key( $instance ) {
259
			/**
260
			 * Set a Google Maps API Key.
261
			 *
262
			 * @since 4.1.0
263
			 *
264
			 * @param string $api_key Google Maps API Key
265
			 */
266
			return apply_filters( 'jetpack_google_maps_api_key', $instance['apikey'] );
267
		}
268
269
270
271
		/**
272
		 * Displays the form for this widget on the Widgets page of the WP Admin area.
273
		 *
274
		 * @param array $instance Instance configuration.
275
		 *
276
		 * @return void
277
		 */
278
		function form( $instance ) {
279
280
			$instance = wp_parse_args( $instance, $this->defaults() );
281
			wp_enqueue_script(
282
				'contact-info-admin',
283
				Jetpack::get_file_url_for_environment(
284
					'_inc/build/widgets/contact-info/contact-info-admin.min.js',
285
					'modules/widgets/contact-info/contact-info-admin.js'
286
				),
287
				array( 'jquery' ),
288
				20160727
289
			);
290
291
			?>
292
			<p>
293
				<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Title:', 'jetpack' ); ?></label>
294
				<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>" />
295
			</p>
296
297
			<p>
298
				<label for="<?php echo esc_attr( $this->get_field_id( 'address' ) ); ?>"><?php esc_html_e( 'Address:', 'jetpack' ); ?></label>
299
				<textarea class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'address' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'address' ) ); ?>"><?php echo esc_textarea( $instance['address'] ); ?></textarea>
300
301
					<input class="jp-contact-info-showmap" id="<?php echo esc_attr( $this->get_field_id( 'showmap' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showmap' ) ); ?>" value="1" type="checkbox" <?php checked( $instance['showmap'], 1 ); ?> />
302
					<label for="<?php echo esc_attr( $this->get_field_id( 'showmap' ) ); ?>"><?php esc_html_e( 'Show map', 'jetpack' ); ?></label>
303
					<?php
304
				if( ! $this->has_good_map( $instance ) ) {
305
					?>
306
					<span class="error-message"><?php _e( 'Sorry. We can not plot this address. A map will not be displayed. Is the address formatted correctly?', 'jetpack' ); ?></span>
307
					<input id="<?php echo esc_attr( $this->get_field_id( 'showmap' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showmap' ) ); ?>" value="<?php echo( intval( $instance['showmap'] ) ); ?>" type="hidden" />
308
					<?php
309
				}
310
				?>
311
			</p>
312
313
			<p class="jp-contact-info-apikey" style="<?php echo $instance['showmap'] ? '' : 'display: none;'; ?>">
314
				<label for="<?php echo esc_attr( $this->get_field_id( 'apikey' ) ); ?>">
315
					<?php _e( 'Google Maps API Key', 'jetpack' ); ?>
316
					<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'apikey' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'apikey' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['apikey'] ); ?>" />
317
					<br />
318
319
					<?php if ( $instance[ 'apikey_error' ] ) { ?>
320
					<span class="error-message"><?php echo $this->get_api_key_error( $instance['apikey_error'] ); ?></span>
321
					<br />
322
					<?php } ?>
323
					<small><?php printf( wp_kses( __( 'Google now requires an API key to use their maps on your site. <a href="%s">See our documentation</a> for instructions on acquiring a key.', 'jetpack' ), array( 'a' => array( 'href' => true ) ) ), 'https://jetpack.com/support/extra-sidebar-widgets/contact-info-widget/' ); ?></small>
324
				</label>
325
			</p>
326
327
			<p>
328
				<label for="<?php echo esc_attr( $this->get_field_id( 'phone' ) ); ?>"><?php esc_html_e( 'Phone:', 'jetpack' ); ?></label>
329
				<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'phone' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'phone' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['phone'] ); ?>" />
330
			</p>
331
332
			<p>
333
				<label for="<?php echo esc_attr( $this->get_field_id( 'email' ) ); ?>"><?php esc_html_e( 'Email Address:', 'jetpack' ); ?></label>
334
				<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'email' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'email' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['email'] ); ?>" />
335
			</p>
336
337
			<p>
338
				<label for="<?php echo esc_attr( $this->get_field_id( 'hours' ) ); ?>"><?php esc_html_e( 'Hours:', 'jetpack' ); ?></label>
339
				<textarea class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'hours' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'hours' ) ); ?>"><?php echo esc_textarea( $instance['hours'] ); ?></textarea>
340
			</p>
341
342
			<?php
343
		}
344
345
		function get_api_key_error( $status ) {
346
			switch ( $status ) {
347
				case 'OVER_QUERY_LIMIT':
348
					default:
349
					return esc_html__( 'You have exceeded your daily request quota for this API. Please enter a valid API KEY', 'jetpack' );
350
			}
351
		}
352
353
354
		/**
355
		 * Generate a Google Maps link for the supplied address.
356
		 *
357
		 * @param string $address Address to link to.
358
		 *
359
		 * @return string
360
		 */
361
		function build_map_link( $address ) {
362
			// Google map urls have lots of available params but zoom (z) and query (q) are enough.
363
			return "https://maps.google.com/maps?z=16&q=" . $this->urlencode_address( $address );
364
		}
365
366
367
		/**
368
		 * Builds map display HTML code from the supplied latitude and longitude.
369
		 *
370
		 * @param float $lat Map Latitude
0 ignored issues
show
Bug introduced by
There is no parameter named $lat. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
371
		 * @param float $lon Map Longitude
0 ignored issues
show
Bug introduced by
There is no parameter named $lon. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
372
		 *
373
		 * @return string HTML of the map
374
		 */
375
		function build_map( $address, $api_key = null ) {
376
			$this->enqueue_scripts();
377
			$src = add_query_arg( 'q', urlencode( $address ), 'https://www.google.com/maps/embed/v1/place' );
378
			if ( ! empty( $api_key ) ) {
379
				$src = add_query_arg( 'key', $api_key, $src );
380
			}
381
382
			return '<iframe width="600" height="216" frameborder="0" src="' . esc_url( $src ) . '" class="contact-map"></iframe>';
383
		}
384
385
		/**
386
		 * Encode an URL
387
		 *
388
		 * @param string $address The URL to encode
389
		 *
390
		 * @return string The encoded URL
391
		 */
392
		function urlencode_address( $address ) {
393
394
			$address = strtolower( $address );
395
			$address = preg_replace( "/\s+/", " ", trim( $address ) ); // Get rid of any unwanted whitespace
396
			$address = str_ireplace( " ", "+", $address ); // Use + not %20
397
			urlencode( $address );
398
399
			return $address;
400
		}
401
402
		/**
403
		 * Check if the instance has a valid Map location.
404
		 *
405
		 * @param array $instance Widget instance configuration.
406
		 *
407
		 * @return bool Whether or not there is a valid map.
408
		 */
409
		function has_good_map( $instance ) {
410
			// The lat and lon of an address that could not be plotted will have values of 0 and 0.
411
			return ! ( "0" == $instance['lat'] && "0" == $instance['lon'] ) && $this->get_google_api_key( $instance );
412
		}
413
414
	}
415
416
}
417