PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 7.2.2
Jetpack – WP Security, Backup, Speed, & Growth v7.2.2
16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 All 503 releases
jetpack / modules / widgets / milestone / milestone.php

milestone.php in Jetpack – WP Security, Backup, Speed, & Growth 7.2.2, at modules/widgets/milestone/milestone.php

684 lines 21.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: Milestone
4 Description: Countdown to a specific date.
5 Version: 1.0
6 Author: Automattic Inc.
7 Author URI: http://automattic.com/
8 License: GPLv2 or later
9 */
10
11 function jetpack_register_widget_milestone() {
12 register_widget( 'Milestone_Widget' );
13 }
14 add_action( 'widgets_init', 'jetpack_register_widget_milestone' );
15
16 class Milestone_Widget extends WP_Widget {
17 private static $dir = null;
18 private static $url = null;
19 private static $defaults = null;
20 private static $config_js = null;
21
22 /**
23 * Available time units sorted in descending order.
24 * @var Array
25 */
26 protected $available_units = array(
27 'years',
28 'months',
29 'days',
30 'hours',
31 'minutes',
32 'seconds'
33 );
34
35 function __construct() {
36 $widget = array(
37 'classname' => 'milestone-widget',
38 'description' => __( 'Display a countdown to a certain date.', 'jetpack' ),
39 );
40
41 parent::__construct(
42 'Milestone_Widget',
43 /** This filter is documented in modules/widgets/facebook-likebox.php */
44 apply_filters( 'jetpack_widget_name', __( 'Milestone', 'jetpack' ) ),
45 $widget
46 );
47
48 self::$dir = trailingslashit( dirname( __FILE__ ) );
49 self::$url = plugin_dir_url( __FILE__ );
50
51 add_action( 'wp_enqueue_scripts', array( __class__, 'enqueue_template' ) );
52 add_action( 'admin_enqueue_scripts', array( __class__, 'enqueue_admin' ) );
53 add_action( 'wp_footer', array( $this, 'localize_script' ) );
54
55 if ( is_active_widget( false, false, $this->id_base, true ) || is_active_widget( false, false, 'monster', true ) || is_customize_preview() ) {
56 add_action( 'wp_head', array( __class__, 'styles_template' ) );
57 }
58 }
59
60 public static function enqueue_admin( $hook_suffix ) {
61 if ( 'widgets.php' == $hook_suffix ) {
62 wp_enqueue_style( 'milestone-admin', self::$url . 'style-admin.css', array(), '20161215' );
63 wp_enqueue_script(
64 'milestone-admin-js',
65 Jetpack::get_file_url_for_environment(
66 '_inc/build/widgets/milestone/admin.min.js',
67 'modules/widgets/milestone/admin.js'
68 ),
69 array( 'jquery' ),
70 '20170915',
71 true
72 );
73 }
74 }
75
76 public static function enqueue_template() {
77 if ( Jetpack_AMP_Support::is_amp_request() ) {
78 return;
79 }
80
81 wp_enqueue_script(
82 'milestone',
83 Jetpack::get_file_url_for_environment(
84 '_inc/build/widgets/milestone/milestone.min.js',
85 'modules/widgets/milestone/milestone.js'
86 ),
87 array( 'jquery' ),
88 '20160520',
89 true
90 );
91 }
92
93 public static function styles_template() {
94 global $themecolors;
95 $colors = wp_parse_args( $themecolors, array(
96 'bg' => 'ffffff',
97 'border' => 'cccccc',
98 'text' => '333333',
99 ) );
100 ?>
101 <style>
102 .milestone-widget {
103 margin-bottom: 1em;
104 }
105 .milestone-content {
106 line-height: 2;
107 margin-top: 5px;
108 max-width: 100%;
109 padding: 0;
110 text-align: center;
111 }
112 .milestone-header {
113 background-color: <?php echo self::sanitize_color_hex( $colors['text'] ); ?>;
114 color: <?php echo self::sanitize_color_hex( $colors['bg'] ); ?>;
115 line-height: 1.3;
116 margin: 0;
117 padding: .8em;
118 }
119 .milestone-header .event,
120 .milestone-header .date {
121 display: block;
122 }
123 .milestone-header .event {
124 font-size: 120%;
125 }
126 .milestone-countdown .difference {
127 display: block;
128 font-size: 500%;
129 font-weight: bold;
130 line-height: 1.2;
131 }
132 .milestone-countdown,
133 .milestone-message {
134 background-color: <?php echo self::sanitize_color_hex( $colors['bg'] ); ?>;
135 border: 1px solid <?php echo self::sanitize_color_hex( $colors['border'] ); ?>;
136 border-top: 0;
137 color: <?php echo self::sanitize_color_hex( $colors['text'] ); ?>;
138 padding-bottom: 1em;
139 }
140 .milestone-message {
141 padding-top: 1em
142 }
143 </style>
144 <?php
145 }
146
147 /**
148 * Ensure that a string representing a color in hexadecimal
149 * notation is safe for use in css and database saves.
150 *
151 * @param string Color in hexadecimal notation. "#" may or may not be prepended to the string.
152 * @return string Color in hexadecimal notation on success - the string "transparent" otherwise.
153 */
154 public static function sanitize_color_hex( $hex, $prefix = '#' ) {
155 $hex = trim( $hex );
156
157 /* Strip recognized prefixes. */
158 if ( 0 === strpos( $hex, '#' ) ) {
159 $hex = substr( $hex, 1 );
160 } elseif ( 0 === strpos( $hex, '%23' ) ) {
161 $hex = substr( $hex, 3 );
162 }
163
164 if ( 0 !== preg_match( '/^[0-9a-fA-F]{6}$/', $hex ) ) {
165 return $prefix . $hex;
166 }
167
168 return 'transparent';
169 }
170
171 /**
172 * Localize Front-end Script.
173 *
174 * Print the javascript configuration array only if the
175 * current template has an instance of the widget that
176 * is still counting down. In all other cases, this
177 * function will dequeue milestone.js.
178 *
179 * Hooks into the "wp_footer" action.
180 */
181 function localize_script() {
182 if ( Jetpack_AMP_Support::is_amp_request() ) {
183 return;
184 }
185
186 if ( empty( self::$config_js['instances'] ) ) {
187 wp_dequeue_script( 'milestone' );
188 return;
189 }
190 self::$config_js['api_root'] = esc_url_raw( rest_url() );
191 wp_localize_script( 'milestone', 'MilestoneConfig', self::$config_js );
192 }
193
194 /**
195 * Widget
196 */
197 function widget( $args, $instance ) {
198 echo $args['before_widget'];
199
200 /** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
201 $title = apply_filters( 'widget_title', $instance['title'] );
202 if ( ! empty( $title ) ) {
203 echo $args['before_title'] . $title . $args['after_title'];
204 }
205
206 $data = $this->get_widget_data( $instance );
207
208 self::$config_js['instances'][] = array(
209 'id' => $args['widget_id'],
210 'message' => $data['message'],
211 'refresh' => $data['refresh']
212 );
213
214 echo '<div class="milestone-content">';
215
216 echo '<div class="milestone-header">';
217 echo '<strong class="event">' . esc_html( $instance['event'] ) . '</strong>';
218 echo '<span class="date">' . esc_html( date_i18n( get_option( 'date_format' ), $data['milestone'] ) ) . '</span>';
219 echo '</div>';
220
221 echo $data['message'];
222
223 echo '</div><!--milestone-content-->';
224
225 echo $args['after_widget'];
226
227 /** This action is documented in modules/widgets/gravatar-profile.php */
228 do_action( 'jetpack_stats_extra', 'widget_view', 'milestone' );
229 }
230
231 function get_widget_data( $instance ) {
232 $data = array();
233
234 $instance = $this->sanitize_instance( $instance );
235
236 $milestone = mktime( $instance['hour'], $instance['min'], 0, $instance['month'], $instance['day'], $instance['year'] );
237 $now = (int) current_time( 'timestamp' );
238 $type = $instance['type'];
239
240 if ( 'since' === $type ) {
241 $diff = (int) floor( $now - $milestone );
242 } else {
243 $diff = (int) floor( $milestone - $now );
244 }
245
246 $data['diff'] = $diff;
247 $data['unit'] = $this->get_unit( $diff, $instance['unit'] );
248
249 // Setting the refresh counter to equal the number of seconds it takes to flip a unit
250 $refresh_intervals = array(
251 0, // should be YEAR_IN_SECONDS, but doing setTimeout for a year doesn't seem to be logical
252 0, // same goes for MONTH_IN_SECONDS,
253 DAY_IN_SECONDS,
254 HOUR_IN_SECONDS,
255 MINUTE_IN_SECONDS,
256 1
257 );
258
259 $data['refresh'] = $refresh_intervals[ array_search( $data['unit'], $this->available_units ) ];
260 $data['milestone'] = $milestone;
261
262 if ( ( 1 > $diff ) && ( 'until' === $type ) ) {
263 $data['message'] = '<div class="milestone-message">' . $instance['message'] . '</div>';
264 $data['refresh'] = 0; // No need to refresh, the milestone has been reached
265 } else {
266 $interval_text = $this->get_interval_in_units( $diff, $data['unit'] );
267 $interval = intval( $interval_text );
268
269 if ( 'since' === $type ) {
270
271 switch ( $data['unit'] ) {
272 case 'years':
273 $data['message'] = sprintf(
274 _n(
275 '<span class="difference">%s</span> <span class="label">year ago.</span>',
276 '<span class="difference">%s</span> <span class="label">years ago.</span>',
277 $interval,
278 'jetpack'
279 ),
280 $interval_text
281 );
282 break;
283 case 'months':
284 $data['message'] = sprintf(
285 _n(
286 '<span class="difference">%s</span> <span class="label">month ago.</span>',
287 '<span class="difference">%s</span> <span class="label">months ago.</span>',
288 $interval,
289 'jetpack'
290 ),
291 $interval_text
292 );
293 break;
294 case 'days':
295 $data['message'] = sprintf(
296 _n(
297 '<span class="difference">%s</span> <span class="label">day ago.</span>',
298 '<span class="difference">%s</span> <span class="label">days ago.</span>',
299 $interval,
300 'jetpack'
301 ),
302 $interval_text
303 );
304 break;
305 case 'hours':
306 $data['message'] = sprintf(
307 _n(
308 '<span class="difference">%s</span> <span class="label">hour ago.</span>',
309 '<span class="difference">%s</span> <span class="label">hours ago.</span>',
310 $interval,
311 'jetpack'
312 ),
313 $interval_text
314 );
315 break;
316 case 'minutes':
317 $data['message'] = sprintf(
318 _n(
319 '<span class="difference">%s</span> <span class="label">minute ago.</span>',
320 '<span class="difference">%s</span> <span class="label">minutes ago.</span>',
321 $interval,
322 'jetpack'
323 ),
324 $interval_text
325 );
326 break;
327 case 'seconds':
328 $data['message'] = sprintf(
329 _n(
330 '<span class="difference">%s</span> <span class="label">second ago.</span>',
331 '<span class="difference">%s</span> <span class="label">seconds ago.</span>',
332 $interval,
333 'jetpack'
334 ),
335 $interval_text
336 );
337 break;
338 }
339 } else {
340 switch ( $this->get_unit( $diff, $instance['unit'] ) ) {
341 case 'years':
342 $data['message'] = sprintf(
343 _n(
344 '<span class="difference">%s</span> <span class="label">year to go.</span>',
345 '<span class="difference">%s</span> <span class="label">years to go.</span>',
346 $interval,
347 'jetpack'
348 ),
349 $interval_text
350 );
351 break;
352 case 'months':
353 $data['message'] = sprintf(
354 _n(
355 '<span class="difference">%s</span> <span class="label">month to go.</span>',
356 '<span class="difference">%s</span> <span class="label">months to go.</span>',
357 $interval,
358 'jetpack'
359 ),
360 $interval_text
361 );
362 break;
363 case 'days':
364 $data['message'] = sprintf(
365 _n(
366 '<span class="difference">%s</span> <span class="label">day to go.</span>',
367 '<span class="difference">%s</span> <span class="label">days to go.</span>',
368 $interval,
369 'jetpack'
370 ),
371 $interval_text
372 );
373 break;
374 case 'hours':
375 $data['message'] = sprintf(
376 _n(
377 '<span class="difference">%s</span> <span class="label">hour to go.</span>',
378 '<span class="difference">%s</span> <span class="label">hours to go.</span>',
379 $interval,
380 'jetpack'
381 ),
382 $interval_text
383 );
384 break;
385 case 'minutes':
386 $data['message'] = sprintf(
387 _n(
388 '<span class="difference">%s</span> <span class="label">minute to go.</span>',
389 '<span class="difference">%s</span> <span class="label">minutes to go.</span>',
390 $interval,
391 'jetpack'
392 ),
393 $interval_text
394 );
395 break;
396 case 'seconds':
397 $data['message'] = sprintf(
398 _n(
399 '<span class="difference">%s</span> <span class="label">second to go.</span>',
400 '<span class="difference">%s</span> <span class="label">seconds to go.</span>',
401 $interval,
402 'jetpack'
403 ),
404 $interval_text
405 );
406 break;
407 }
408 }
409 $data['message'] = '<div class="milestone-countdown">' . $data['message'] . '</div>';
410 }
411
412 return $data;
413 }
414
415 /**
416 * Return the largest possible time unit that the difference will be displayed in.
417 *
418 * @param Integer $seconds the interval in seconds
419 * @param String $maximum_unit the maximum unit that will be used. Optional.
420 * @return String $calculated_unit
421 */
422 protected function get_unit( $seconds, $maximum_unit = 'automatic' ) {
423 $unit = '';
424
425 if ( $seconds >= YEAR_IN_SECONDS * 2 ) {
426 // more than 2 years - show in years, one decimal point
427 $unit = 'years';
428
429 } else if ( $seconds >= YEAR_IN_SECONDS ) {
430 if ( 'years' === $maximum_unit ) {
431 $unit = 'years';
432 } else {
433 // automatic mode - showing months even if it's between one and two years
434 $unit = 'months';
435 }
436
437 } else if ( $seconds >= MONTH_IN_SECONDS * 3 ) {
438 // fewer than 2 years - show in months
439 $unit = 'months';
440
441 } else if ( $seconds >= MONTH_IN_SECONDS ) {
442 if ( 'months' === $maximum_unit ) {
443 $unit = 'months';
444 } else {
445 // automatic mode - showing days even if it's between one and three months
446 $unit = 'days';
447 }
448
449 } else if ( $seconds >= DAY_IN_SECONDS - 1 ) {
450 // fewer than a month - show in days
451 $unit = 'days';
452
453 } else if ( $seconds >= HOUR_IN_SECONDS - 1 ) {
454 // less than 1 day - show in hours
455 $unit = 'hours';
456
457 } else if ( $seconds >= MINUTE_IN_SECONDS - 1 ) {
458 // less than 1 hour - show in minutes
459 $unit = 'minutes';
460
461 } else {
462 // less than 1 minute - show in seconds
463 $unit = 'seconds';
464 }
465
466 $maximum_unit_index = array_search( $maximum_unit, $this->available_units );
467 $unit_index = array_search( $unit, $this->available_units );
468
469 if (
470 false === $maximum_unit_index // the maximum unit parameter is automatic
471 || $unit_index > $maximum_unit_index // there is not enough seconds for even one maximum time unit
472 ) {
473 return $unit;
474 }
475 return $maximum_unit;
476 }
477
478 /**
479 * Returns a time difference value in specified units.
480 *
481 * @param Integer $seconds
482 * @param String $units
483 * @return Integer|String $time_in_units
484 */
485 protected function get_interval_in_units( $seconds, $units ) {
486 switch ( $units ) {
487 case 'years':
488 $years = $seconds / YEAR_IN_SECONDS;
489 $decimals = abs( round( $years, 1 ) - round( $years ) ) > 0 ? 1 : 0;
490 return number_format_i18n( $years, $decimals );
491 case 'months':
492 return (int) ( $seconds / 60 / 60 / 24 / 30 );
493 case 'days':
494 return (int) ( $seconds / 60 / 60 / 24 + 1 );
495 case 'hours':
496 return (int) ( $seconds / 60 / 60 );
497 case 'minutes':
498 return (int) ( $seconds / 60 + 1 );
499 default:
500 return $seconds;
501 }
502 }
503
504 /**
505 * Update
506 */
507 function update( $new_instance, $old_instance ) {
508 return $this->sanitize_instance( $new_instance );
509 }
510
511 /*
512 * Make sure that a number is within a certain range.
513 * If the number is too small it will become the possible lowest value.
514 * If the number is too large it will become the possible highest value.
515 *
516 * @param int $n The number to check.
517 * @param int $floor The lowest possible value.
518 * @param int $ceil The highest possible value.
519 */
520 function sanitize_range( $n, $floor, $ceil ) {
521 $n = (int) $n;
522 if ( $n < $floor ) {
523 $n = $floor;
524 } elseif ( $n > $ceil ) {
525 $n = $ceil;
526 }
527 return $n;
528 }
529
530 /*
531 * Sanitize an instance of this widget.
532 *
533 * Date ranges match the documentation for mktime in the php manual.
534 * @see http://php.net/manual/en/function.mktime.php#refsect1-function.mktime-parameters
535 *
536 * @uses Milestone_Widget::sanitize_range().
537 */
538 function sanitize_instance( $dirty ) {
539 $now = (int) current_time( 'timestamp' );
540
541 $dirty = wp_parse_args( $dirty, array(
542 'title' => '',
543 'event' => __( 'The Big Day', 'jetpack' ),
544 'unit' => 'automatic',
545 'type' => 'until',
546 'message' => __( 'The big day is here.', 'jetpack' ),
547 'day' => date( 'd', $now ),
548 'month' => date( 'm', $now ),
549 'year' => date( 'Y', $now ),
550 'hour' => 0,
551 'min' => 0,
552 ) );
553
554 $allowed_tags = array(
555 'a' => array( 'title' => array(), 'href' => array(), 'target' => array() ),
556 'em' => array( 'title' => array() ),
557 'strong' => array( 'title' => array() ),
558 );
559
560 $clean = array(
561 'title' => trim( strip_tags( stripslashes( $dirty['title'] ) ) ),
562 'event' => trim( strip_tags( stripslashes( $dirty['event'] ) ) ),
563 'unit' => $dirty['unit'],
564 'type' => $dirty['type'],
565 'message' => wp_kses( $dirty['message'], $allowed_tags ),
566 'year' => $this->sanitize_range( $dirty['year'], 1901, 2037 ),
567 'month' => $this->sanitize_range( $dirty['month'], 1, 12 ),
568 'hour' => $this->sanitize_range( $dirty['hour'], 0, 23 ),
569 'min' => zeroise( $this->sanitize_range( $dirty['min'], 0, 59 ), 2 ),
570 );
571
572 $clean['day'] = $this->sanitize_range( $dirty['day'], 1, date( 't', mktime( 0, 0, 0, $clean['month'], 1, $clean['year'] ) ) );
573
574 return $clean;
575 }
576
577 /**
578 * Form
579 */
580 function form( $instance ) {
581 $instance = $this->sanitize_instance( $instance );
582
583 $units = array(
584 'automatic' => _x( 'Automatic', 'Milestone widget: mode in which the date unit is determined automatically', 'jetpack' ),
585 'years' => _x( 'Years', 'Milestone widget: mode in which the date unit is set to years', 'jetpack' ),
586 'months' => _x( 'Months', 'Milestone widget: mode in which the date unit is set to months', 'jetpack' ),
587 'days' => _x( 'Days', 'Milestone widget: mode in which the date unit is set to days', 'jetpack' ),
588 'hours' => _x( 'Hours', 'Milestone widget: mode in which the date unit is set to hours', 'jetpack' ),
589 );
590 ?>
591
592 <div class="milestone-widget">
593 <p>
594 <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title', 'jetpack' ); ?></label>
595 <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>" />
596 </p>
597
598 <p>
599 <label for="<?php echo $this->get_field_id( 'event' ); ?>"><?php _e( 'Description', 'jetpack' ); ?></label>
600 <input class="widefat" id="<?php echo $this->get_field_id( 'event' ); ?>" name="<?php echo $this->get_field_name( 'event' ); ?>" type="text" value="<?php echo esc_attr( $instance['event'] ); ?>" />
601 </p>
602
603 <fieldset class="jp-ms-data-time">
604 <legend><?php esc_html_e( 'Date', 'jetpack' ); ?></legend>
605
606 <label for="<?php echo $this->get_field_id( 'month' ); ?>" class="assistive-text"><?php _e( 'Month', 'jetpack' ); ?></label>
607 <select id="<?php echo $this->get_field_id( 'month' ); ?>" class="month" name="<?php echo $this->get_field_name( 'month' ); ?>"><?php
608 global $wp_locale;
609 for ( $i = 1; $i < 13; $i++ ) {
610 $monthnum = zeroise( $i, 2 );
611 echo '<option value="' . esc_attr( $monthnum ) . '"' . selected( $i, $instance['month'], false ) . '>' . $monthnum . '-' . $wp_locale->get_month_abbrev( $wp_locale->get_month( $i ) ) . '</option>';
612 }
613 ?></select>
614
615 <label for="<?php echo $this->get_field_id( 'day' ); ?>" class="assistive-text"><?php _e( 'Day', 'jetpack' ); ?></label>
616 <input id="<?php echo $this->get_field_id( 'day' ); ?>" class="day" name="<?php echo $this->get_field_name( 'day' ); ?>" type="text" value="<?php echo esc_attr( $instance['day'] ); ?>">,
617
618 <label for="<?php echo $this->get_field_id( 'year' ); ?>" class="assistive-text"><?php _e( 'Year', 'jetpack' ); ?></label>
619 <input id="<?php echo $this->get_field_id( 'year' ); ?>" class="year" name="<?php echo $this->get_field_name( 'year' ); ?>" type="text" value="<?php echo esc_attr( $instance['year'] ); ?>">
620 </fieldset>
621
622 <fieldset class="jp-ms-data-time">
623 <legend><?php esc_html_e( 'Time', 'jetpack' ); ?></legend>
624
625 <label for="<?php echo $this->get_field_id( 'hour' ); ?>" class="assistive-text"><?php _e( 'Hour', 'jetpack' ); ?></label>
626 <input id="<?php echo $this->get_field_id( 'hour' ); ?>" class="hour" name="<?php echo $this->get_field_name( 'hour' ); ?>" type="text" value="<?php echo esc_attr( $instance['hour'] ); ?>">
627
628 <label for="<?php echo $this->get_field_id( 'min' ); ?>" class="assistive-text"><?php _e( 'Minutes', 'jetpack' ); ?></label>
629
630 <span class="time-separator">:</span>
631
632 <input id="<?php echo $this->get_field_id( 'min' ); ?>" class="minutes" name="<?php echo $this->get_field_name( 'min' ); ?>" type="text" value="<?php echo esc_attr( $instance['min'] ); ?>">
633 </fieldset>
634
635 <fieldset class="jp-ms-data-unit">
636 <legend><?php esc_html_e( 'Time Unit', 'jetpack' ); ?></legend>
637
638 <label for="<?php echo $this->get_field_id( 'unit' ); ?>" class="assistive-text">
639 <?php _e( 'Time Unit', 'jetpack' ); ?>
640 </label>
641 <select id="<?php echo $this->get_field_id( 'unit' ); ?>" class="unit" name="<?php echo $this->get_field_name( 'unit' ); ?>">
642 <?php
643 foreach ( $units as $key => $unit ) {
644 echo '<option value="' . esc_attr( $key ) . '"' . selected( $key, $instance['unit'], false ) . '>' . $unit . '</option>';
645 }
646 ?></select>
647 </fieldset>
648
649 <ul class="milestone-type">
650 <li>
651 <label>
652 <input
653 <?php checked( $instance['type'], 'until' ); ?>
654 name="<?php echo esc_attr( $this->get_field_name( 'type' ) ); ?>"
655 type="radio"
656 value="until"
657 />
658 <?php esc_html_e( 'Until your milestone', 'jetpack' ); ?>
659 </label>
660 </li>
661
662 <li>
663 <label>
664 <input
665 <?php checked( $instance['type'], 'since' ); ?>
666 name="<?php echo esc_attr( $this->get_field_name( 'type' ) ); ?>"
667 type="radio"
668 value="since"
669 />
670 <?php esc_html_e( 'Since your milestone', 'jetpack' ); ?>
671 </label>
672 </li>
673 </ul>
674
675 <p class="milestone-message-wrapper">
676 <label for="<?php echo $this->get_field_id( 'message' ); ?>"><?php _e( 'Milestone Reached Message', 'jetpack' ); ?></label>
677 <textarea id="<?php echo $this->get_field_id( 'message' ); ?>" name="<?php echo $this->get_field_name( 'message' ); ?>" class="widefat" rows="3"><?php echo esc_textarea( $instance['message'] ); ?></textarea>
678 </p>
679 </div>
680
681 <?php
682 }
683 }
684