Completed
Push — add/module-registration-refact... ( af2fe6...74b9d5 )
by
unknown
295:53 queued 288:51
created

modules/widgets/contact-info.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
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
			);
68
		}
69
70
		/**
71
		 * Outputs the HTML for this widget.
72
		 *
73
		 * @param array $args     An array of standard parameters for widgets in this theme
74
		 * @param array $instance An array of settings for this widget instance
75
		 *
76
		 * @return void Echoes it's output
77
		 **/
78
		function widget( $args, $instance ) {
79
			$instance = wp_parse_args( $instance, $this->defaults() );
80
81
			echo $args['before_widget'];
82
83
			if ( '' != $instance['title'] ) {
84
				echo $args['before_title'] . $instance['title'] . $args['after_title'];
85
			}
86
87
			/**
88
			 * Fires at the beginning of the Contact Info widget, after the title.
89
			 *
90
			 * @module widgets
91
			 *
92
			 * @since 3.9.2
93
			 */
94
			do_action( 'jetpack_contact_info_widget_start' );
95
96
			echo '<div itemscope itemtype="http://schema.org/LocalBusiness">';
97
98
			if ( '' != $instance['address'] ) {
99
100
				$showmap = $instance['showmap'];
101
102
				/** This action is documented in modules/widgets/contact-info.php */
103
				if ( $showmap && $this->has_good_map( $instance ) ) {
104
					/**
105
					 * Set a Google Maps API Key.
106
					 *
107
					 * @since 4.1.0
108
					 *
109
					 * @param string $api_key Google Maps API Key
110
					 */
111
					$api_key = apply_filters( 'jetpack_google_maps_api_key', $instance['apikey'] );
112
					echo $this->build_map( $instance['address'], $api_key );
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
				} else {
124
					echo '<div class="confit-phone"><span itemprop="telephone">' . esc_html( $instance['phone'] ) . '</span></div>';
125
				}
126
			}
127
128
			if ( is_email( trim( $instance['email'] ) ) ) {
129
				printf(
130
					'<div class="confit-email"><a href="mailto:%1$s">%1$s</a></div>',
131
					esc_html( $instance['email'] )
132
				);
133
			}
134
135
			if ( '' != $instance['hours'] ) {
136
				echo '<div class="confit-hours" itemprop="openingHours">' . str_replace( "\n", '<br/>', esc_html( $instance['hours'] ) ) . '</div>';
137
			}
138
139
			echo '</div>';
140
141
			/**
142
			 * Fires at the end of Contact Info widget.
143
			 *
144
			 * @module widgets
145
			 *
146
			 * @since 3.9.2
147
			 */
148
			do_action( 'jetpack_contact_info_widget_end' );
149
150
			echo $args['after_widget'];
151
152
			/** This action is documented in modules/widgets/gravatar-profile.php */
153
			do_action( 'jetpack_stats_extra', 'widget_view', 'contact_info' );
154
		}
155
156
157
		/**
158
		 * Deals with the settings when they are saved by the admin. Here is
159
		 * where any validation should be dealt with.
160
		 *
161
		 * @param array $new_instance New configuration values
162
		 * @param array $old_instance Old configuration values
163
		 *
164
		 * @return array
165
		 */
166
		function update( $new_instance, $old_instance ) {
167
			$update_lat_lon = false;
168
			if (
169
				! isset( $old_instance['address'] ) ||
170
				$this->urlencode_address( $old_instance['address'] ) != $this->urlencode_address( $new_instance['address'] )
171
			) {
172
				$update_lat_lon = true;
173
			}
174
175
			$instance            = array();
176
			$instance['title']   = wp_kses( $new_instance['title'], array() );
177
			$instance['address'] = wp_kses( $new_instance['address'], array() );
178
			$instance['phone']   = wp_kses( $new_instance['phone'], array() );
179
			$instance['email']   = wp_kses( $new_instance['email'], array() );
180
			$instance['hours']   = wp_kses( $new_instance['hours'], array() );
181
			$instance['apikey']  = wp_kses( isset( $new_instance['apikey'] ) ? $new_instance['apikey'] : $old_instance['apikey'], array() );
182
			$instance['lat']     = isset( $old_instance['lat'] ) ? floatval( $old_instance['lat'] ) : 0;
183
			$instance['lon']     = isset( $old_instance['lon'] ) ? floatval( $old_instance['lon'] ) : 0;
184
185
			if ( ! $instance['lat'] || ! $instance['lon'] ) {
186
				$update_lat_lon = true;
187
			}
188
189
			if ( $instance['address'] && $update_lat_lon ) {
190
191
				// Get the lat/lon of the user specified address.
192
				$address = $this->urlencode_address( $instance['address'] );
193
				$path    = 'https://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=' . $address;
194
				/** This action is documented in modules/widgets/contact-info.php */
195
				$key = apply_filters( 'jetpack_google_maps_api_key', $instance['apikey'] );
196
197
				if ( ! empty( $key ) ) {
198
					$path = add_query_arg( 'key', $key, $path );
199
				}
200
				$json = wp_remote_retrieve_body( wp_remote_get( esc_url( $path, null, null ) ) );
201
202
				if ( ! $json ) {
203
					// The read failed :(
204
					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' );
205
					die();
206
				}
207
208
				$json_obj = json_decode( $json );
209
210
				if ( 'ZERO_RESULTS' == $json_obj->status ) {
211
					// The address supplied does not have a matching lat / lon.
212
					// No map is available.
213
					$instance['lat'] = '0';
214
					$instance['lon'] = '0';
215
				} else {
216
217
					$loc = $json_obj->results[0]->geometry->location;
218
219
					$lat = floatval( $loc->lat );
220
					$lon = floatval( $loc->lng );
221
222
					$instance['lat'] = "$lat";
223
					$instance['lon'] = "$lon";
224
				}
225
			}
226
227
			if ( ! isset( $new_instance['showmap'] ) ) {
228
				$instance['showmap'] = 0;
229
			} else {
230
				$instance['showmap'] = intval( $new_instance['showmap'] );
231
			}
232
233
			return $instance;
234
		}
235
236
237
		/**
238
		 * Displays the form for this widget on the Widgets page of the WP Admin area.
239
		 *
240
		 * @param array $instance Instance configuration.
241
		 *
242
		 * @return void
243
		 */
244
		function form( $instance ) {
245
			$instance = wp_parse_args( $instance, $this->defaults() );
246
			wp_enqueue_script(
247
				'contact-info-admin',
248
				Jetpack::get_file_url_for_environment(
249
					'_inc/build/widgets/contact-info/contact-info-admin.min.js',
250
					'modules/widgets/contact-info/contact-info-admin.js'
251
				),
252
				array( 'jquery' ),
253
				20160727
254
			);
255
256
			?>
257
			<p>
258
				<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Title:', 'jetpack' ); ?></label>
259
				<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'] ); ?>" />
260
			</p>
261
262
			<p>
263
				<label for="<?php echo esc_attr( $this->get_field_id( 'address' ) ); ?>"><?php esc_html_e( 'Address:', 'jetpack' ); ?></label>
264
				<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>
265
				<?php
266
				if ( $this->has_good_map( $instance ) ) {
267
					?>
268
					<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 ); ?> />
269
					<label for="<?php echo esc_attr( $this->get_field_id( 'showmap' ) ); ?>"><?php esc_html_e( 'Show map', 'jetpack' ); ?></label>
270
					<?php
271
				} else {
272
					?>
273
					<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>
274
					<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" />
275
					<?php
276
				}
277
				?>
278
			</p>
279
280
			<p class="jp-contact-info-apikey" style="<?php echo $instance['showmap'] ? '' : 'display: none;'; ?>">
281
				<label for="<?php echo esc_attr( $this->get_field_id( 'apikey' ) ); ?>">
282
					<?php _e( 'Google Maps API Key', 'jetpack' ); ?>
283
					<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'] ); ?>" />
284
					<br />
285
					<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>
286
				</label>
287
			</p>
288
289
			<p>
290
				<label for="<?php echo esc_attr( $this->get_field_id( 'phone' ) ); ?>"><?php esc_html_e( 'Phone:', 'jetpack' ); ?></label>
291
				<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'] ); ?>" />
292
			</p>
293
294
			<p>
295
				<label for="<?php echo esc_attr( $this->get_field_id( 'email' ) ); ?>"><?php esc_html_e( 'Email Address:', 'jetpack' ); ?></label>
296
				<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'] ); ?>" />
297
			</p>
298
299
			<p>
300
				<label for="<?php echo esc_attr( $this->get_field_id( 'hours' ) ); ?>"><?php esc_html_e( 'Hours:', 'jetpack' ); ?></label>
301
				<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>
302
			</p>
303
304
			<?php
305
		}
306
307
308
		/**
309
		 * Generate a Google Maps link for the supplied address.
310
		 *
311
		 * @param string $address Address to link to.
312
		 *
313
		 * @return string
314
		 */
315
		function build_map_link( $address ) {
316
			// Google map urls have lots of available params but zoom (z) and query (q) are enough.
317
			return 'https://maps.google.com/maps?z=16&q=' . $this->urlencode_address( $address );
318
		}
319
320
321
		/**
322
		 * Builds map display HTML code from the supplied latitude and longitude.
323
		 *
324
		 * @param string $address Address.
325
		 * @param string $api_key API Key.
0 ignored issues
show
Should the type for parameter $api_key not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
326
		 *
327
		 * @return string HTML of the map.
328
		 */
329
		function build_map( $address, $api_key = null ) {
330
			$this->enqueue_scripts();
331
			$src = add_query_arg( 'q', rawurlencode( $address ), 'https://www.google.com/maps/embed/v1/place' );
332
			if ( ! empty( $api_key ) ) {
333
				$src = add_query_arg( 'key', $api_key, $src );
334
			}
335
336
			$height = 216;
337
338
			$iframe_attributes = sprintf(
339
				' height="%d" frameborder="0" src="%s" class="contact-map"',
340
				esc_attr( $height ),
341
				esc_url( $src )
342
			);
343
344
			$iframe_html = sprintf( '<iframe width="600" %s></iframe>', $iframe_attributes );
345
346
			if ( ! Jetpack_AMP_Support::is_amp_request() ) {
347
				return $iframe_html;
348
			}
349
350
			$amp_iframe_html = sprintf( '<amp-iframe layout="fixed-height" width="auto" sandbox="allow-scripts allow-same-origin" %s>', $iframe_attributes );
351
352
			// Add placeholder to avoid AMP error: <amp-iframe> elements must be positioned outside the first 75% of the viewport or 600px from the top (whichever is smaller).
353
			$amp_iframe_html .= sprintf( '<span placeholder>%s</span>', esc_html__( 'Loading map&hellip;', 'jetpack' ) );
354
355
			// Add original iframe as fallback in case JavaScript is disabled.
356
			$amp_iframe_html .= sprintf( '<noscript>%s</noscript>', $iframe_html );
357
358
			$amp_iframe_html .= '</amp-iframe>';
359
			return $amp_iframe_html;
360
		}
361
362
		/**
363
		 * Encode an URL
364
		 *
365
		 * @param string $address The URL to encode
366
		 *
367
		 * @return string The encoded URL
368
		 */
369
		function urlencode_address( $address ) {
370
371
			$address = strtolower( $address );
372
			$address = preg_replace( '/\s+/', ' ', trim( $address ) ); // Get rid of any unwanted whitespace
373
			$address = str_ireplace( ' ', '+', $address ); // Use + not %20
374
			return urlencode( $address );
375
		}
376
377
		/**
378
		 * Check if the instance has a valid Map location.
379
		 *
380
		 * @param array $instance Widget instance configuration.
381
		 *
382
		 * @return bool Whether or not there is a valid map.
383
		 */
384
		function has_good_map( $instance ) {
385
			// The lat and lon of an address that could not be plotted will have values of 0 and 0.
386
			return ! ( '0' == $instance['lat'] && '0' == $instance['lon'] );
387
		}
388
389
	}
390
391
}
392