My Calendar - Version 3.3.15

Version Description

  • Bug fix: CPT base values shouldn't allow URL-invalid characters.
  • Bug fix: Improper variable type checking in mc_settings checkboxes.
  • Bug fix: Unset search variable in auto-generated display hashes.
  • New filters: Filter event object. (multilanguage support in Pro)
  • New filter: Filters on single event HTML. (multilanguage support in Pro)
  • Add: language attribute in main, today, and upcoming events shortcodes.
Download this release

Release Info

Developer joedolson
Plugin Icon 128x128 My Calendar
Version 3.3.15
Comparing to
See all releases

Code changes from version 3.3.12 to 3.3.15

css/reset.css CHANGED
@@ -391,4 +391,8 @@ button.mc-toggle:hover, button.mc-toggle:focus {
391
  max-width: 1em;
392
  padding: 0;
393
  display: inline-block;
 
 
 
 
394
  }
391
  max-width: 1em;
392
  padding: 0;
393
  display: inline-block;
394
+ }
395
+
396
+ .my-calendar-mask.mc-mask-active {
397
+ position: static !important; /* Override styles from 2021 styles, sadly. */
398
  }
includes/kses.php CHANGED
@@ -289,6 +289,7 @@ function mc_kses_elements() {
289
  'aria-live' => array(),
290
  'aria-hidden' => array(),
291
  'style' => array(),
 
292
  ),
293
  'i' => array(
294
  'id' => array(),
@@ -296,6 +297,17 @@ function mc_kses_elements() {
296
  'aria-live' => array(),
297
  'aria-hidden' => array(),
298
  ),
 
 
 
 
 
 
 
 
 
 
 
299
  'p' => array(
300
  'class' => array(),
301
  ),
@@ -307,6 +319,7 @@ function mc_kses_elements() {
307
  'data-default' => array(),
308
  'aria-labelledby' => array(),
309
  'style' => array(),
 
310
  ),
311
  'img' => array(
312
  'class' => true,
289
  'aria-live' => array(),
290
  'aria-hidden' => array(),
291
  'style' => array(),
292
+ 'lang' => array(),
293
  ),
294
  'i' => array(
295
  'id' => array(),
297
  'aria-live' => array(),
298
  'aria-hidden' => array(),
299
  ),
300
+ 'strong' => array(
301
+ 'id' => array(),
302
+ 'class' => array(),
303
+ ),
304
+ 'b' => array(
305
+ 'id' => array(),
306
+ 'class' => array(),
307
+ ),
308
+ 'hr' => array(
309
+ 'class' => array(),
310
+ ),
311
  'p' => array(
312
  'class' => array(),
313
  ),
319
  'data-default' => array(),
320
  'aria-labelledby' => array(),
321
  'style' => array(),
322
+ 'lang' => array(),
323
  ),
324
  'img' => array(
325
  'class' => true,
includes/screen-options.php CHANGED
@@ -95,7 +95,7 @@ function mc_show_event_editing( $status, $args ) {
95
  $output .= "<label for='mci_$key'><input type='checkbox' id='mci_$key' name='mc_show_on_page[$key]' value='on' $checked /> $value</label>";
96
  }
97
  }
98
- $button = get_submit_button( __( 'Apply' ), 'button', 'screen-options-apply', false );
99
  $return .= '
100
  <fieldset>
101
  <legend>' . __( 'Event editing fields to show', 'my-calendar' ) . "</legend>
95
  $output .= "<label for='mci_$key'><input type='checkbox' id='mci_$key' name='mc_show_on_page[$key]' value='on' $checked /> $value</label>";
96
  }
97
  }
98
+ $button = get_submit_button( __( 'Apply', 'my-calendar' ), 'button', 'screen-options-apply', false );
99
  $return .= '
100
  <fieldset>
101
  <legend>' . __( 'Event editing fields to show', 'my-calendar' ) . "</legend>
js/mc-ajax.js DELETED
@@ -1,122 +0,0 @@
1
- (function ($) {
2
- 'use strict';
3
- $(function () {
4
- mc_display_usertime();
5
- $(document).on('click', ".my-calendar-header a.mcajax, .my-calendar-footer a.mcajax, .my-calendar-header input[type=submit], .my-calendar-footer input[type=submit]", function (e) {
6
- e.preventDefault();
7
- var calendar = $( this ).closest( '.mc-main' );
8
- var ref = calendar.attr('id');
9
- var month = '';
10
- var day = '';
11
- var year = '';
12
- var mcat = '';
13
- var loc = '';
14
- var access = '';
15
- var mcs = '';
16
- if ( 'INPUT' === this.nodeName ) {
17
- var inputForm = $( this ).parents( 'form' );
18
- if ( inputForm.hasClass( 'mc-date-switcher' ) ) {
19
- var month = inputForm.find( 'select[name=month]' ).val();
20
- var day = inputForm.find( 'select[name=dy]' ).val();
21
- var year = inputForm.find( 'select[name=yr]' ).val();
22
- }
23
- if ( inputForm.hasClass( 'mc-categories-switcher' ) ) {
24
- var mcat = inputForm.find( 'select[name=mcat]' ).val();
25
- }
26
- if ( inputForm.hasClass( 'mc-locations-switcher' ) ) {
27
- var loc = inputForm.find( 'select[name=loc]' ).val();
28
- }
29
- if ( inputForm.hasClass( 'mc-access-switcher' ) ) {
30
- var access = inputForm.find( 'select[name=access]' ).val();
31
- }
32
- var mcs = calendar.find( '#mcs' ).val();
33
- var link = $( this ).attr( 'data-href' );
34
- } else {
35
- var link = $(this).attr('href');
36
- }
37
- let url;
38
- try {
39
- url = new URL(link);
40
- url.searchParams.delete('embed');
41
- if ( 'INPUT' === this.nodeName ) {
42
- if ( '' !== month ) {
43
- url.searchParams.delete( 'month' );
44
- url.searchParams.delete( 'dy' );
45
- url.searchParams.delete( 'yr' );
46
-
47
- url.searchParams.append( 'month', parseInt( month ) );
48
- if ( 'undefined' !== typeof( day ) ) {
49
- url.searchParams.append( 'dy', parseInt( day ) );
50
- }
51
- url.searchParams.append( 'yr', parseInt( year ) );
52
- }
53
- if ( '' !== mcat ) {
54
- url.searchParams.delete( 'mcat' );
55
- url.searchParams.append( 'mcat', mcat );
56
- }
57
- if ( '' !== loc ) {
58
- url.searchParams.delete( 'loc' );
59
- url.searchParams.delete( 'ltype' );
60
- url.searchParams.append( 'ltype', 'name' );
61
- url.searchParams.append( 'loc', loc );
62
- }
63
- if ( '' !== access ) {
64
- url.searchParams.delete( 'access' );
65
- url.searchParams.append( 'access', parseInt( access ) );
66
- }
67
- url.searchParams.delete( 'mcs' );
68
- if ( '' !== mcs && 'undefined' !== typeof( mcs ) ) {
69
- console.log( 'mcs', mcs );
70
- url.searchParams.append( 'mcs', encodeURIComponent( mcs ) );
71
- }
72
-
73
- link = url.toString();
74
- }
75
-
76
- window.history.pushState({}, '', url );
77
- } catch(_) {
78
- url = false;
79
- }
80
-
81
- var height = calendar.height();
82
- /* $('#' + ref + ' .mc-content' ).html('<div class=\"mc-loading\"></div><div class=\"loading\" style=\"height:' + height + 'px\"><span class="screen-reader-text">Loading...</span></div>');
83
- $( '#' + ref + ' .mc-content' ).load(link + ' #' + ref + ' .mc-content > *', function ( response, status, xhr ) { */
84
- $('#' + ref ).html('<div class=\"mc-loading\"></div><div class=\"loading\" style=\"height:' + height + 'px\"><span class="screen-reader-text">Loading...</span></div>');
85
- $( '#' + ref ).load(link + ' #' + ref + ' > *', function ( response, status, xhr ) {
86
-
87
- if ( status == 'error' ) {
88
- $( '#' + ref ).html( xhr.status + " " + xhr.statusText );
89
- }
90
- // functions to execute when new view loads.
91
- // List view.
92
- if ( typeof( mclist ) !== "undefined" && mclist.list == 'true' ) {
93
- $('li.mc-events').children().not('.event-date').hide();
94
- $('li.current-day').children().show();
95
- }
96
- // Grid view.
97
- if ( typeof( mcgrid ) !== "undefined" && mcgrid.grid == 'true' ) {
98
- $('.calendar-event').children().not('.event-title').hide();
99
- }
100
- // Mini view.
101
- if ( typeof( mcmini ) !== "undefined" && mcmini.mini == 'true' ) {
102
- $('.mini .has-events').children().not('.trigger, .mc-date, .event-date').hide();
103
- }
104
- // All views.
105
- $( '#' + ref ).attr('tabindex', '-1').trigger( 'focus' );
106
- mc_display_usertime();
107
- // Your Custom ajax load changes if needed.
108
- });
109
- });
110
- });
111
-
112
- function mc_display_usertime() {
113
- var utime = $( '.mc-user-time' );
114
- utime.each(function() {
115
- var time = $( this ).text();
116
- var label = $( this ).attr( 'data-label' );
117
- var utime = '<span class="mc-local-time-time">' + new Date( time ).toLocaleTimeString().replace( ':00 ', ' ' ) + '</span>';
118
- var udate = '<span class="mc-local-time-date">' + new Date( time ).toLocaleDateString() + '</span>';
119
- $( this ).html( '<span class="mc-local-time-label">' + label + '</span>' + ' ' + udate + '<span class="sep">, </span>' + utime ).attr( 'data-time', time );
120
- });
121
- }
122
- }(jQuery));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/mc-grid.js DELETED
@@ -1,60 +0,0 @@
1
- (function ($) {
2
- 'use strict';
3
- $(function () {
4
- $('.calendar-event').children().not('.event-title,.screen-reader-text').hide();
5
- var mask = document.createElement( 'div' );
6
- mask.classList.add( 'my-calendar-mask' );
7
- var body = document.querySelector( 'body' );
8
- body.insertAdjacentElement( 'beforeend', mask );
9
- $(document).on('click', '.calendar-event .event-title .open',
10
- function (e) {
11
- e.preventDefault();
12
- var current_date = $(this).parents( '.mc-event' ).children();
13
- mask.classList.add( 'mc-mask-active' );
14
-
15
- $(this).closest( '.mc-main' ).toggleClass( 'grid-open' );
16
- $(this).parents( '.mc-event' ).children().not('.event-title').toggle().attr('tabindex', '-1');
17
- $(this).parents( '.mc-event' ).trigger( 'focus' );
18
-
19
- var focusable = current_date.find( 'a, object, :input, iframe, [tabindex]' );
20
- var lastFocus = focusable.last();
21
- var firstFocus = focusable.first();
22
- lastFocus.attr( 'data-action', 'shiftback' );
23
-
24
- $('.calendar-event').children().not('.event-title,.screen-reader-text').not( current_date ).hide();
25
- return false;
26
- });
27
-
28
- $(document).on('click', '.calendar-event .close',
29
- function (e) {
30
- mask.classList.remove( 'mc-mask-active' );
31
- e.preventDefault();
32
- $(this).closest( '.mc-main' ).removeClass( 'grid-open' );
33
- $(this).closest('.mc-event').find('.event-title a').trigger( 'focus' );
34
- $(this).closest('div.details').toggle();
35
- });
36
-
37
- $(document).on( 'keydown', function(e) {
38
- var keycode = ( e.keyCode ? e.keyCode : e.which );
39
- if ( keycode == 27 ) {
40
- mask.classList.remove( 'mc-mask-active' );
41
- $( '.mc-main ').removeClass( 'grid-open' );
42
- $( '.calendar-event div.details' ).hide();
43
- }
44
- });
45
-
46
- $(document).on( 'keydown', '.details a, .details object, .details :input, .details iframe, .details [tabindex]',
47
- function(e) {
48
- var keycode = ( e.keyCode ? e.keyCode : e.which );
49
- var action = $( ':focus' ).attr( 'data-action' );
50
- if ( ( !e.shiftKey && keycode == 9 ) && action == 'shiftback' ) {
51
- e.preventDefault();
52
- $( '.mc-toggle.close' ).trigger( 'focus' );
53
- }
54
- if ( ( e.shiftKey && keycode == 9 ) && action == 'shiftforward' ) {
55
- e.preventDefault();
56
- $( '[data-action=shiftback]' ).trigger( 'focus' );
57
- }
58
- });
59
- });
60
- }(jQuery));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/mc-list.js DELETED
@@ -1,21 +0,0 @@
1
- (function ($) {
2
- 'use strict';
3
- $(function () {
4
- $('li.mc-events').children().not('.event-date').hide();
5
- $('li.current-day').children().show();
6
- $('li.current-day .event-date .mc-text-button' ).attr( 'aria-expanded', true );
7
- $(document).on( 'click', '.event-date button',
8
- function (e) {
9
- e.preventDefault();
10
- var mcEvent = $( this ).closest( '.mc-events' ).find( '.mc-event:first' );
11
- $( this ).closest( '.mc-events' ).find( '.mc-event' ).toggle();
12
- mcEvent.attr('tabindex', '-1').trigger( 'focus' );
13
- var visible = $(this).closest( '.mc-events' ).find('.mc-event').is(':visible');
14
- if ( visible ) {
15
- $(this).attr('aria-expanded', 'true');
16
- } else {
17
- $(this).attr('aria-expanded', 'false');
18
- }
19
- });
20
- });
21
- }(jQuery));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/mc-mini.js DELETED
@@ -1,19 +0,0 @@
1
- (function ($) {
2
- 'use strict';
3
- $(function () {
4
- $( ".mini .has-events" ).children().not( ".trigger, .mc-date, .event-date" ).hide();
5
- $( document ).on( "click", ".mini .has-events .trigger", function (e) {
6
- e.preventDefault();
7
- var current_date = $(this).parent().children();
8
- current_date.not(".trigger").toggle().attr( "tabindex", "-1" ).trigger( 'focus' );
9
- $( '.mini .has-events' ).children( '.trigger' ).removeClass( 'active-toggle' );
10
- $( '.mini .has-events' ).children().not( '.trigger, .mc-date, .event-date' ).not( current_date ).hide();
11
- $( this ).addClass( 'active-toggle' );
12
- } );
13
- $( document ).on( "click", ".calendar-events .close", function (e) {
14
- e.preventDefault();
15
- $(this).closest( '.mini .has-events' ).children( '.trigger' ).removeClass( 'active-toggle' );
16
- $(this).closest( 'div.calendar-events' ).toggle();
17
- } );
18
- });
19
- }(jQuery));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/mcjs.js CHANGED
@@ -1,8 +1,228 @@
1
  (function ($) {
2
  'use strict';
3
- $(function () {
 
4
  $( '.mc-main' ).removeClass( 'mcjs' );
5
  });
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  $('.mc-main a[target=_blank]').append( ' <span class="dashicons dashicons-external" aria-hidden="true"></span><span class="screen-reader-text"> ' + my_calendar.newWindow + '</span>' );
8
  }(jQuery));
1
  (function ($) {
2
  'use strict';
3
+ $(function () {
4
+ mc_display_usertime();
5
  $( '.mc-main' ).removeClass( 'mcjs' );
6
  });
7
 
8
+ if ( 'true' === my_calendar.mini ) {
9
+ $(function () {
10
+ $( ".mini .has-events" ).children().not( ".trigger, .mc-date, .event-date" ).hide();
11
+ $( document ).on( "click", ".mini .has-events .trigger", function (e) {
12
+ e.preventDefault();
13
+ var current_date = $(this).parent().children();
14
+ current_date.not(".trigger").toggle().attr( "tabindex", "-1" ).trigger( 'focus' );
15
+ $( '.mini .has-events' ).children( '.trigger' ).removeClass( 'active-toggle' );
16
+ $( '.mini .has-events' ).children().not( '.trigger, .mc-date, .event-date' ).not( current_date ).hide();
17
+ $( this ).addClass( 'active-toggle' );
18
+ } );
19
+ $( document ).on( "click", ".calendar-events .close", function (e) {
20
+ e.preventDefault();
21
+ $(this).closest( '.mini .has-events' ).children( '.trigger' ).removeClass( 'active-toggle' );
22
+ $(this).closest( 'div.calendar-events' ).toggle();
23
+ } );
24
+ });
25
+ }
26
+
27
+ if ( 'true' === my_calendar.list ) {
28
+ $(function () {
29
+ $('li.mc-events').children().not('.event-date').hide();
30
+ $('li.current-day').children().show();
31
+ $('li.current-day .event-date .mc-text-button' ).attr( 'aria-expanded', true );
32
+ $(document).on( 'click', '.event-date button',
33
+ function (e) {
34
+ e.preventDefault();
35
+ var mcEvent = $( this ).closest( '.mc-events' ).find( '.mc-event:first' );
36
+ $( this ).closest( '.mc-events' ).find( '.mc-event' ).toggle();
37
+ mcEvent.attr('tabindex', '-1').trigger( 'focus' );
38
+ var visible = $(this).closest( '.mc-events' ).find('.mc-event').is(':visible');
39
+ if ( visible ) {
40
+ $(this).attr('aria-expanded', 'true');
41
+ } else {
42
+ $(this).attr('aria-expanded', 'false');
43
+ }
44
+ });
45
+ });
46
+ }
47
+
48
+ if ( 'true' === my_calendar.grid ) {
49
+ $(function () {
50
+ $('.calendar-event').children().not('.event-title,.screen-reader-text').hide();
51
+ var mask = document.createElement( 'div' );
52
+ mask.classList.add( 'my-calendar-mask' );
53
+ var body = document.querySelector( 'body' );
54
+ body.insertAdjacentElement( 'beforeend', mask );
55
+ $(document).on('click', '.calendar-event .event-title .open',
56
+ function (e) {
57
+ e.preventDefault();
58
+ var current_date = $(this).parents( '.mc-event' ).children();
59
+ mask.classList.add( 'mc-mask-active' );
60
+
61
+ $(this).closest( '.mc-main' ).toggleClass( 'grid-open' );
62
+ $(this).parents( '.mc-event' ).children().not('.event-title').toggle().attr('tabindex', '-1');
63
+ $(this).parents( '.mc-event' ).trigger( 'focus' );
64
+
65
+ var focusable = current_date.find( 'a, object, :input, iframe, [tabindex]' );
66
+ var lastFocus = focusable.last();
67
+ var firstFocus = focusable.first();
68
+ lastFocus.attr( 'data-action', 'shiftback' );
69
+
70
+ $('.calendar-event').children().not('.event-title,.screen-reader-text').not( current_date ).hide();
71
+ return false;
72
+ });
73
+
74
+ $(document).on('click', '.calendar-event .close',
75
+ function (e) {
76
+ mask.classList.remove( 'mc-mask-active' );
77
+ e.preventDefault();
78
+ $(this).closest( '.mc-main' ).removeClass( 'grid-open' );
79
+ $(this).closest('.mc-event').find('.event-title a').trigger( 'focus' );
80
+ $(this).closest('div.details').toggle();
81
+ });
82
+
83
+ $(document).on( 'keydown', function(e) {
84
+ var keycode = ( e.keyCode ? e.keyCode : e.which );
85
+ if ( keycode == 27 ) {
86
+ mask.classList.remove( 'mc-mask-active' );
87
+ $( '.mc-main ').removeClass( 'grid-open' );
88
+ $( '.calendar-event div.details' ).hide();
89
+ }
90
+ });
91
+
92
+ $(document).on( 'keydown', '.details a, .details object, .details :input, .details iframe, .details [tabindex]',
93
+ function(e) {
94
+ var keycode = ( e.keyCode ? e.keyCode : e.which );
95
+ var action = $( ':focus' ).attr( 'data-action' );
96
+ if ( ( !e.shiftKey && keycode == 9 ) && action == 'shiftback' ) {
97
+ e.preventDefault();
98
+ $( '.mc-toggle.close' ).trigger( 'focus' );
99
+ }
100
+ if ( ( e.shiftKey && keycode == 9 ) && action == 'shiftforward' ) {
101
+ e.preventDefault();
102
+ $( '[data-action=shiftback]' ).trigger( 'focus' );
103
+ }
104
+ });
105
+ });
106
+ }
107
+
108
+ if ( 'true' === my_calendar.ajax ) {
109
+ $(function () {
110
+ $(document).on('click', ".my-calendar-header a.mcajax, .my-calendar-footer a.mcajax, .my-calendar-header input[type=submit], .my-calendar-footer input[type=submit]", function (e) {
111
+ e.preventDefault();
112
+ var calendar = $( this ).closest( '.mc-main' );
113
+ var ref = calendar.attr('id');
114
+ var month = '';
115
+ var day = '';
116
+ var year = '';
117
+ var mcat = '';
118
+ var loc = '';
119
+ var access = '';
120
+ var mcs = '';
121
+ if ( 'INPUT' === this.nodeName ) {
122
+ var inputForm = $( this ).parents( 'form' );
123
+ if ( inputForm.hasClass( 'mc-date-switcher' ) ) {
124
+ var month = inputForm.find( 'select[name=month]' ).val();
125
+ var day = inputForm.find( 'select[name=dy]' ).val();
126
+ var year = inputForm.find( 'select[name=yr]' ).val();
127
+ }
128
+ if ( inputForm.hasClass( 'mc-categories-switcher' ) ) {
129
+ var mcat = inputForm.find( 'select[name=mcat]' ).val();
130
+ }
131
+ if ( inputForm.hasClass( 'mc-locations-switcher' ) ) {
132
+ var loc = inputForm.find( 'select[name=loc]' ).val();
133
+ }
134
+ if ( inputForm.hasClass( 'mc-access-switcher' ) ) {
135
+ var access = inputForm.find( 'select[name=access]' ).val();
136
+ }
137
+ var mcs = calendar.find( '#mcs' ).val();
138
+ var link = $( this ).attr( 'data-href' );
139
+ } else {
140
+ var link = $(this).attr('href');
141
+ }
142
+ let url;
143
+ try {
144
+ url = new URL(link);
145
+ url.searchParams.delete('embed');
146
+ if ( 'INPUT' === this.nodeName ) {
147
+ if ( '' !== month ) {
148
+ url.searchParams.delete( 'month' );
149
+ url.searchParams.delete( 'dy' );
150
+ url.searchParams.delete( 'yr' );
151
+
152
+ url.searchParams.append( 'month', parseInt( month ) );
153
+ if ( 'undefined' !== typeof( day ) ) {
154
+ url.searchParams.append( 'dy', parseInt( day ) );
155
+ }
156
+ url.searchParams.append( 'yr', parseInt( year ) );
157
+ }
158
+ if ( '' !== mcat ) {
159
+ url.searchParams.delete( 'mcat' );
160
+ url.searchParams.append( 'mcat', mcat );
161
+ }
162
+ if ( '' !== loc ) {
163
+ url.searchParams.delete( 'loc' );
164
+ url.searchParams.delete( 'ltype' );
165
+ url.searchParams.append( 'ltype', 'name' );
166
+ url.searchParams.append( 'loc', loc );
167
+ }
168
+ if ( '' !== access ) {
169
+ url.searchParams.delete( 'access' );
170
+ url.searchParams.append( 'access', parseInt( access ) );
171
+ }
172
+ url.searchParams.delete( 'mcs' );
173
+ if ( '' !== mcs && 'undefined' !== typeof( mcs ) ) {
174
+ url.searchParams.append( 'mcs', encodeURIComponent( mcs ) );
175
+ }
176
+
177
+ link = url.toString();
178
+ }
179
+
180
+ window.history.pushState({}, '', url );
181
+ } catch(_) {
182
+ url = false;
183
+ }
184
+
185
+ var height = calendar.height();
186
+ /* $('#' + ref + ' .mc-content' ).html('<div class=\"mc-loading\"></div><div class=\"loading\" style=\"height:' + height + 'px\"><span class="screen-reader-text">Loading...</span></div>');
187
+ $( '#' + ref + ' .mc-content' ).load(link + ' #' + ref + ' .mc-content > *', function ( response, status, xhr ) { */
188
+ $('#' + ref ).html('<div class=\"mc-loading\"></div><div class=\"loading\" style=\"height:' + height + 'px\"><span class="screen-reader-text">Loading...</span></div>');
189
+ $( '#' + ref ).load(link + ' #' + ref + ' > *', function ( response, status, xhr ) {
190
+
191
+ if ( status == 'error' ) {
192
+ $( '#' + ref ).html( xhr.status + " " + xhr.statusText );
193
+ }
194
+ // functions to execute when new view loads.
195
+ // List view.
196
+ if ( typeof( my_calendar ) !== "undefined" && my_calendar.list == 'true' ) {
197
+ $('li.mc-events').children().not('.event-date').hide();
198
+ $('li.current-day').children().show();
199
+ }
200
+ // Grid view.
201
+ if ( typeof( my_calendar ) !== "undefined" && my_calendar.grid == 'true' ) {
202
+ $('.calendar-event').children().not('.event-title').hide();
203
+ }
204
+ // Mini view.
205
+ if ( typeof( my_calendar ) !== "undefined" && my_calendar.mini == 'true' ) {
206
+ $('.mini .has-events').children().not('.trigger, .mc-date, .event-date').hide();
207
+ }
208
+ // All views.
209
+ $( '#' + ref ).attr('tabindex', '-1').trigger( 'focus' );
210
+ mc_display_usertime();
211
+ });
212
+ });
213
+ });
214
+ }
215
+
216
+ function mc_display_usertime() {
217
+ var utime = $( '.mc-user-time' );
218
+ utime.each(function() {
219
+ var time = $( this ).text();
220
+ var label = $( this ).attr( 'data-label' );
221
+ var utime = '<span class="mc-local-time-time">' + new Date( time ).toLocaleTimeString().replace( ':00 ', ' ' ) + '</span>';
222
+ var udate = '<span class="mc-local-time-date">' + new Date( time ).toLocaleDateString() + '</span>';
223
+ $( this ).html( '<span class="mc-local-time-label">' + label + '</span>' + ' ' + udate + '<span class="sep">, </span>' + utime ).attr( 'data-time', time );
224
+ });
225
+ }
226
+
227
  $('.mc-main a[target=_blank]').append( ' <span class="dashicons dashicons-external" aria-hidden="true"></span><span class="screen-reader-text"> ' + my_calendar.newWindow + '</span>' );
228
  }(jQuery));
js/mcjs.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e){"use strict";function t(){e(".mc-user-time").each(function(){var t=e(this).text(),a=e(this).attr("data-label"),n='<span class="mc-local-time-time">'+new Date(t).toLocaleTimeString().replace(":00 "," ")+"</span>",s='<span class="mc-local-time-date">'+new Date(t).toLocaleDateString()+"</span>";e(this).html('<span class="mc-local-time-label">'+a+"</span> "+s+'<span class="sep">, </span>'+n).attr("data-time",t)})}e(function(){t(),e(".mc-main").removeClass("mcjs")}),"true"===my_calendar.mini&&e(function(){e(".mini .has-events").children().not(".trigger, .mc-date, .event-date").hide(),e(document).on("click",".mini .has-events .trigger",function(t){t.preventDefault();var a=e(this).parent().children();a.not(".trigger").toggle().attr("tabindex","-1").trigger("focus"),e(".mini .has-events").children(".trigger").removeClass("active-toggle"),e(".mini .has-events").children().not(".trigger, .mc-date, .event-date").not(a).hide(),e(this).addClass("active-toggle")}),e(document).on("click",".calendar-events .close",function(t){t.preventDefault(),e(this).closest(".mini .has-events").children(".trigger").removeClass("active-toggle"),e(this).closest("div.calendar-events").toggle()})}),"true"===my_calendar.list&&e(function(){e("li.mc-events").children().not(".event-date").hide(),e("li.current-day").children().show(),e("li.current-day .event-date .mc-text-button").attr("aria-expanded",!0),e(document).on("click",".event-date button",function(t){t.preventDefault();var a=e(this).closest(".mc-events").find(".mc-event:first");e(this).closest(".mc-events").find(".mc-event").toggle(),a.attr("tabindex","-1").trigger("focus"),e(this).closest(".mc-events").find(".mc-event").is(":visible")?e(this).attr("aria-expanded","true"):e(this).attr("aria-expanded","false")})}),"true"===my_calendar.grid&&e(function(){e(".calendar-event").children().not(".event-title,.screen-reader-text").hide();var t=document.createElement("div");t.classList.add("my-calendar-mask"),document.querySelector("body").insertAdjacentElement("beforeend",t),e(document).on("click",".calendar-event .event-title .open",function(a){a.preventDefault();var n=e(this).parents(".mc-event").children();t.classList.add("mc-mask-active"),e(this).closest(".mc-main").toggleClass("grid-open"),e(this).parents(".mc-event").children().not(".event-title").toggle().attr("tabindex","-1"),e(this).parents(".mc-event").trigger("focus");var s=n.find("a, object, :input, iframe, [tabindex]"),i=s.last();s.first();return i.attr("data-action","shiftback"),e(".calendar-event").children().not(".event-title,.screen-reader-text").not(n).hide(),!1}),e(document).on("click",".calendar-event .close",function(a){t.classList.remove("mc-mask-active"),a.preventDefault(),e(this).closest(".mc-main").removeClass("grid-open"),e(this).closest(".mc-event").find(".event-title a").trigger("focus"),e(this).closest("div.details").toggle()}),e(document).on("keydown",function(a){27==(a.keyCode?a.keyCode:a.which)&&(t.classList.remove("mc-mask-active"),e(".mc-main ").removeClass("grid-open"),e(".calendar-event div.details").hide())}),e(document).on("keydown",".details a, .details object, .details :input, .details iframe, .details [tabindex]",function(t){var a=t.keyCode?t.keyCode:t.which,n=e(":focus").attr("data-action");t.shiftKey||9!=a||"shiftback"!=n||(t.preventDefault(),e(".mc-toggle.close").trigger("focus")),t.shiftKey&&9==a&&"shiftforward"==n&&(t.preventDefault(),e("[data-action=shiftback]").trigger("focus"))})}),"true"===my_calendar.ajax&&e(function(){e(document).on("click",".my-calendar-header a.mcajax, .my-calendar-footer a.mcajax, .my-calendar-header input[type=submit], .my-calendar-footer input[type=submit]",function(a){a.preventDefault();var n=e(this).closest(".mc-main"),s=n.attr("id"),i="",c="",r="",d="",l="",o="",m="";if("INPUT"===this.nodeName){var h=e(this).parents("form");if(h.hasClass("mc-date-switcher"))i=h.find("select[name=month]").val(),c=h.find("select[name=dy]").val(),r=h.find("select[name=yr]").val();if(h.hasClass("mc-categories-switcher"))d=h.find("select[name=mcat]").val();if(h.hasClass("mc-locations-switcher"))l=h.find("select[name=loc]").val();if(h.hasClass("mc-access-switcher"))o=h.find("select[name=access]").val();m=n.find("#mcs").val();var v=e(this).attr("data-href")}else v=e(this).attr("href");let f;try{(f=new URL(v)).searchParams.delete("embed"),"INPUT"===this.nodeName&&(""!==i&&(f.searchParams.delete("month"),f.searchParams.delete("dy"),f.searchParams.delete("yr"),f.searchParams.append("month",parseInt(i)),void 0!==c&&f.searchParams.append("dy",parseInt(c)),f.searchParams.append("yr",parseInt(r))),""!==d&&(f.searchParams.delete("mcat"),f.searchParams.append("mcat",d)),""!==l&&(f.searchParams.delete("loc"),f.searchParams.delete("ltype"),f.searchParams.append("ltype","name"),f.searchParams.append("loc",l)),""!==o&&(f.searchParams.delete("access"),f.searchParams.append("access",parseInt(o))),f.searchParams.delete("mcs"),""!==m&&void 0!==m&&f.searchParams.append("mcs",encodeURIComponent(m)),v=f.toString()),window.history.pushState({},"",f)}catch(e){f=!1}var u=n.height();e("#"+s).html('<div class="mc-loading"></div><div class="loading" style="height:'+u+'px"><span class="screen-reader-text">Loading...</span></div>'),e("#"+s).load(v+" #"+s+" > *",function(a,n,i){"error"==n&&e("#"+s).html(i.status+" "+i.statusText),"undefined"!=typeof my_calendar&&"true"==my_calendar.list&&(e("li.mc-events").children().not(".event-date").hide(),e("li.current-day").children().show()),"undefined"!=typeof my_calendar&&"true"==my_calendar.grid&&e(".calendar-event").children().not(".event-title").hide(),"undefined"!=typeof my_calendar&&"true"==my_calendar.mini&&e(".mini .has-events").children().not(".trigger, .mc-date, .event-date").hide(),e("#"+s).attr("tabindex","-1").trigger("focus"),t()})})}),e(".mc-main a[target=_blank]").append(' <span class="dashicons dashicons-external" aria-hidden="true"></span><span class="screen-reader-text"> '+my_calendar.newWindow+"</span>")}(jQuery);
my-calendar-categories.php CHANGED
@@ -802,14 +802,14 @@ function mc_manage_categories() {
802
  // Translators: Category name.
803
  $default_text = sprintf( __( 'Set %s as Default', 'my-calendar' ), '<span class="screen-reader-text">' . $cat_name . '</span>' );
804
  if ( $default_category === (string) $cat->category_id ) {
805
- echo ' <strong>' . __( '(Default)' ) . '</strong>';
806
  $default = '<span class="mc_default">' . __( 'Default Category', 'my-calendar' ) . '</span>';
807
  } else {
808
  $url = admin_url( "admin.php?page=my-calendar-categories&amp;default=$cat->category_id" );
809
  $default = '<a href="' . esc_url( $url ) . '">' . $default_text . '</a>';
810
  }
811
  if ( get_option( 'mc_skip_holidays_category' ) === (string) $cat->category_id ) {
812
- echo ' <strong>' . __( '(Holiday)' ) . '</strong>';
813
  }
814
  ?>
815
  <div class="row-actions">
802
  // Translators: Category name.
803
  $default_text = sprintf( __( 'Set %s as Default', 'my-calendar' ), '<span class="screen-reader-text">' . $cat_name . '</span>' );
804
  if ( $default_category === (string) $cat->category_id ) {
805
+ echo ' <strong>' . __( '(Default)', 'my-calendar' ) . '</strong>';
806
  $default = '<span class="mc_default">' . __( 'Default Category', 'my-calendar' ) . '</span>';
807
  } else {
808
  $url = admin_url( "admin.php?page=my-calendar-categories&amp;default=$cat->category_id" );
809
  $default = '<a href="' . esc_url( $url ) . '">' . $default_text . '</a>';
810
  }
811
  if ( get_option( 'mc_skip_holidays_category' ) === (string) $cat->category_id ) {
812
+ echo ' <strong>' . __( '(Holiday)', 'my-calendar' ) . '</strong>';
813
  }
814
  ?>
815
  <div class="row-actions">
my-calendar-core.php CHANGED
@@ -470,64 +470,59 @@ function mc_footer_js() {
470
  echo ( '' !== $inner ) ? $script . $mcjs : '';
471
  } else {
472
  $enqueue_mcjs = false;
 
 
 
 
473
  if ( ! $id || ( is_array( $pages ) && in_array( $id, $pages, true ) ) || '' === $show_js ) {
474
  if ( '1' !== get_option( 'mc_calendar_javascript' ) && 'true' !== get_option( 'mc_open_uri' ) ) {
475
- $url = apply_filters( 'mc_grid_js', plugins_url( 'js/mc-grid.js', __FILE__ ) );
476
  $enqueue_mcjs = true;
477
- wp_enqueue_script( 'mc.grid', $url, array( 'jquery' ), $version );
478
- wp_localize_script(
479
- 'mc.grid',
480
- 'mcgrid',
481
- array(
482
- 'grid' => 'true',
483
- )
484
- );
485
  }
486
  if ( '1' !== get_option( 'mc_list_javascript' ) ) {
487
- $url = apply_filters( 'mc_list_js', plugins_url( 'js/mc-list.js', __FILE__ ) );
488
  $enqueue_mcjs = true;
489
- wp_enqueue_script( 'mc.list', $url, array( 'jquery' ), $version );
490
- wp_localize_script(
491
- 'mc.list',
492
- 'mclist',
493
- array(
494
- 'list' => 'true',
495
- )
496
- );
497
  }
498
  if ( '1' !== get_option( 'mc_mini_javascript' ) && 'true' !== get_option( 'mc_open_day_uri' ) ) {
499
- $url = apply_filters( 'mc_mini_js', plugins_url( 'js/mc-mini.js', __FILE__ ) );
500
  $enqueue_mcjs = true;
501
- wp_enqueue_script( 'mc.mini', $url, array( 'jquery' ), $version );
502
- wp_localize_script(
503
- 'mc.mini',
504
- 'mcmini',
505
- array(
506
- 'mini' => 'true',
507
- )
508
- );
509
  }
510
  if ( '1' !== get_option( 'mc_ajax_javascript' ) ) {
511
- $url = apply_filters( 'mc_ajax_js', plugins_url( 'js/mc-ajax.js', __FILE__ ) );
512
  $enqueue_mcjs = true;
513
- wp_enqueue_script( 'mc.ajax', $url, array( 'jquery' ), $version );
514
- wp_localize_script(
515
- 'mc.ajax',
516
- 'mcAjax',
517
- array(
518
- 'ajax' => 'true',
519
- )
520
- );
521
  }
522
  if ( $enqueue_mcjs ) {
523
- wp_enqueue_script( 'mc.mcjs', plugins_url( 'js/mcjs.js', __FILE__ ), array( 'jquery' ), $version );
524
- wp_localize_script(
525
- 'mc.mcjs',
526
- 'my_calendar',
527
- array(
528
- 'newWindow' => __( 'Opens in new tab', 'my-calendar' ),
529
- )
 
530
  );
 
531
  }
532
  }
533
  }
@@ -618,7 +613,7 @@ function mc_admin_styles() {
618
  );
619
  }
620
  }
621
- wp_enqueue_style( 'mc-styles', plugins_url( 'css/mc-styles.css', __FILE__ ), $version );
622
  }
623
  }
624
 
@@ -1801,18 +1796,18 @@ add_action( 'load-options-permalink.php', 'mc_load_permalinks' );
1801
  */
1802
  function mc_load_permalinks() {
1803
  if ( isset( $_POST['mc_cpt_base'] ) ) {
1804
- update_option( 'mc_cpt_base', sanitize_text_field( $_POST['mc_cpt_base'] ) );
1805
  }
1806
  $opts = array( 'label_for' => 'mc_cpt_base' );
1807
  // Add a settings field to the permalink page.
1808
- add_settings_field( 'mc_cpt_base', __( 'My Calendar Events base' ), 'mc_field_callback', 'permalink', 'optional', $opts );
1809
 
1810
  if ( isset( $_POST['mc_location_cpt_base'] ) ) {
1811
- update_option( 'mc_location_cpt_base', sanitize_text_field( $_POST['mc_location_cpt_base'] ) );
1812
  }
1813
  $opts = array( 'label_for' => 'mc_location_cpt_base' );
1814
  // Add a settings field to the permalink page.
1815
- add_settings_field( 'mc_location_cpt_base', __( 'My Calendar Locations base' ), 'mc_location_field_callback', 'permalink', 'optional', $opts );
1816
  }
1817
 
1818
  /**
@@ -1825,7 +1820,11 @@ function mc_load_permalinks() {
1825
  */
1826
  function mc_previous_post_link( $output, $format ) {
1827
  if ( mc_is_single_event() ) {
1828
- $mc_id = (int) $_GET['mc_id'];
 
 
 
 
1829
  $event = mc_adjacent_event( $mc_id, 'previous' );
1830
  if ( empty( $event ) ) {
1831
  return '';
@@ -1852,7 +1851,11 @@ function mc_previous_post_link( $output, $format ) {
1852
  */
1853
  function mc_next_post_link( $output, $format ) {
1854
  if ( mc_is_single_event() ) {
1855
- $mc_id = (int) $_GET['mc_id'];
 
 
 
 
1856
  $event = mc_adjacent_event( $mc_id, 'next' );
1857
  if ( empty( $event ) ) {
1858
  return '';
@@ -2124,21 +2127,21 @@ function mc_posttypes_messages( $messages ) {
2124
  $messages[ $key ] = array(
2125
  0 => '', // Unused. Messages start at index 1.
2126
  // Translators: URL to view event.
2127
- 1 => sprintf( __( 'Event updated. <a href="%s">View Event</a>' ), esc_url( get_permalink( $post_ID ) ) ),
2128
- 2 => __( 'Custom field updated.' ),
2129
- 3 => __( 'Custom field deleted.' ),
2130
- 4 => __( 'Event updated.' ),
2131
  // Translators: %s: date and time of the revision.
2132
- 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Event restored to revision from %s' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
2133
  // Translators: URL to view event.
2134
- 6 => sprintf( __( 'Event published. <a href="%s">View event</a>' ), esc_url( get_permalink( $post_ID ) ) ),
2135
- 7 => sprintf( __( 'Event saved.' ) ),
2136
  // Translators: URL to preview event.
2137
- 8 => sprintf( __( 'Event submitted. <a target="_blank" href="%s">Preview event</a>' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) ),
2138
  // Translators: Date event scheduled to be published, URL to preview event.
2139
- 9 => sprintf( __( 'Event scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview event</a>' ), date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post_ID ) ) ),
2140
  // Translators: URL to preview event.
2141
- 10 => sprintf( __( 'Event draft updated. <a target="_blank" href="%s">Preview event</a>' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) ),
2142
  );
2143
  }
2144
  }
@@ -2165,6 +2168,10 @@ add_action( 'admin_notices', 'mc_update_notice' );
2165
  */
2166
  function mc_update_notice() {
2167
  if ( current_user_can( 'manage_options' ) && isset( $_GET['page'] ) && stripos( $_GET['page'], 'my-calendar' ) !== false ) {
 
 
 
 
2168
  if ( 'true' === get_option( 'mc_remote' ) ) {
2169
  mc_show_notice( __( 'My Calendar is configured to retrieve events from a remote source.', 'my-calendar' ) . ' <a href="' . admin_url( 'admin.php?page=my-calendar-config' ) . '">' . __( 'Update Settings', 'my-calendar' ) . '</a>' );
2170
  }
470
  echo ( '' !== $inner ) ? $script . $mcjs : '';
471
  } else {
472
  $enqueue_mcjs = false;
473
+ $grid = 'false';
474
+ $list = 'false';
475
+ $mini = 'false';
476
+ $ajax = 'false';
477
  if ( ! $id || ( is_array( $pages ) && in_array( $id, $pages, true ) ) || '' === $show_js ) {
478
  if ( '1' !== get_option( 'mc_calendar_javascript' ) && 'true' !== get_option( 'mc_open_uri' ) ) {
479
+ $url = apply_filters( 'mc_grid_js', '' );
480
  $enqueue_mcjs = true;
481
+ if ( $url ) {
482
+ wp_enqueue_script( 'mc.grid', $url, array( 'jquery' ), $version );
483
+ } else {
484
+ $grid = 'true';
485
+ }
 
 
 
486
  }
487
  if ( '1' !== get_option( 'mc_list_javascript' ) ) {
488
+ $url = apply_filters( 'mc_list_js', '' );
489
  $enqueue_mcjs = true;
490
+ if ( $url ) {
491
+ wp_enqueue_script( 'mc.list', $url, array( 'jquery' ), $version );
492
+ } else {
493
+ $list = 'true';
494
+ }
 
 
 
495
  }
496
  if ( '1' !== get_option( 'mc_mini_javascript' ) && 'true' !== get_option( 'mc_open_day_uri' ) ) {
497
+ $url = apply_filters( 'mc_mini_js', '' );
498
  $enqueue_mcjs = true;
499
+
500
+ if ( $url ) {
501
+ wp_enqueue_script( 'mc.mini', $url, array( 'jquery' ), $version );
502
+ } else {
503
+ $mini = 'true';
504
+ }
 
 
505
  }
506
  if ( '1' !== get_option( 'mc_ajax_javascript' ) ) {
507
+ $url = apply_filters( 'mc_ajax_js', '' );
508
  $enqueue_mcjs = true;
509
+ if ( $url ) {
510
+ wp_enqueue_script( 'mc.ajax', $url, array( 'jquery' ), $version );
511
+ } else {
512
+ $ajax = 'true';
513
+ }
 
 
 
514
  }
515
  if ( $enqueue_mcjs ) {
516
+ $url = ( true === SCRIPT_DEBUG ) ? plugins_url( 'js/mcjs.js', __FILE__ ) : plugins_url( 'js/mcjs.min.js', __FILE__ );
517
+ wp_enqueue_script( 'mc.mcjs', $url, array( 'jquery' ), $version );
518
+ $args = array(
519
+ 'grid' => $grid,
520
+ 'list' => $list,
521
+ 'mini' => $mini,
522
+ 'ajax' => $ajax,
523
+ 'newWindow' => __( 'Opens in new tab', 'my-calendar' ),
524
  );
525
+ wp_localize_script( 'mc.mcjs', 'my_calendar', $args );
526
  }
527
  }
528
  }
613
  );
614
  }
615
  }
616
+ wp_enqueue_style( 'mc-styles', plugins_url( 'css/mc-styles.css', __FILE__ ), array(), $version );
617
  }
618
  }
619
 
1796
  */
1797
  function mc_load_permalinks() {
1798
  if ( isset( $_POST['mc_cpt_base'] ) ) {
1799
+ update_option( 'mc_cpt_base', sanitize_key( $_POST['mc_cpt_base'] ) );
1800
  }
1801
  $opts = array( 'label_for' => 'mc_cpt_base' );
1802
  // Add a settings field to the permalink page.
1803
+ add_settings_field( 'mc_cpt_base', __( 'My Calendar Events base', 'my-calendar' ), 'mc_field_callback', 'permalink', 'optional', $opts );
1804
 
1805
  if ( isset( $_POST['mc_location_cpt_base'] ) ) {
1806
+ update_option( 'mc_location_cpt_base', sanitize_key( $_POST['mc_location_cpt_base'] ) );
1807
  }
1808
  $opts = array( 'label_for' => 'mc_location_cpt_base' );
1809
  // Add a settings field to the permalink page.
1810
+ add_settings_field( 'mc_location_cpt_base', __( 'My Calendar Locations base', 'my-calendar' ), 'mc_location_field_callback', 'permalink', 'optional', $opts );
1811
  }
1812
 
1813
  /**
1820
  */
1821
  function mc_previous_post_link( $output, $format ) {
1822
  if ( mc_is_single_event() ) {
1823
+ $mc_id = ( isset( $_GET['mc_id'] ) && is_numeric( $_GET['mc_id'] ) ) ? $_GET['mc_id'] : false;
1824
+ if ( ! $mc_id ) {
1825
+ $post_id = get_the_ID();
1826
+ $mc_id = get_post_meta( $post_id, '_mc_event_id', true );
1827
+ }
1828
  $event = mc_adjacent_event( $mc_id, 'previous' );
1829
  if ( empty( $event ) ) {
1830
  return '';
1851
  */
1852
  function mc_next_post_link( $output, $format ) {
1853
  if ( mc_is_single_event() ) {
1854
+ $mc_id = ( isset( $_GET['mc_id'] ) && is_numeric( $_GET['mc_id'] ) ) ? $_GET['mc_id'] : false;
1855
+ if ( ! $mc_id ) {
1856
+ $post_id = get_the_ID();
1857
+ $mc_id = get_post_meta( $post_id, '_mc_event_id', true );
1858
+ }
1859
  $event = mc_adjacent_event( $mc_id, 'next' );
1860
  if ( empty( $event ) ) {
1861
  return '';
2127
  $messages[ $key ] = array(
2128
  0 => '', // Unused. Messages start at index 1.
2129
  // Translators: URL to view event.
2130
+ 1 => sprintf( __( 'Event updated. <a href="%s">View Event</a>', 'my-calendar' ), esc_url( get_permalink( $post_ID ) ) ),
2131
+ 2 => __( 'Custom field updated.', 'my-calendar' ),
2132
+ 3 => __( 'Custom field deleted.', 'my-calendar' ),
2133
+ 4 => __( 'Event updated.', 'my-calendar' ),
2134
  // Translators: %s: date and time of the revision.
2135
+ 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Event restored to revision from %s', 'my-calendar' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
2136
  // Translators: URL to view event.
2137
+ 6 => sprintf( __( 'Event published. <a href="%s">View event</a>', 'my-calendar' ), esc_url( get_permalink( $post_ID ) ) ),
2138
+ 7 => sprintf( __( 'Event saved.', 'my-calendar' ) ),
2139
  // Translators: URL to preview event.
2140
+ 8 => sprintf( __( 'Event submitted. <a target="_blank" href="%s">Preview event</a>', 'my-calendar' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) ),
2141
  // Translators: Date event scheduled to be published, URL to preview event.
2142
+ 9 => sprintf( __( 'Event scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview event</a>', 'my-calendar' ), date_i18n( __( 'M j, Y @ G:i', 'my-calendar' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post_ID ) ) ),
2143
  // Translators: URL to preview event.
2144
+ 10 => sprintf( __( 'Event draft updated. <a target="_blank" href="%s">Preview event</a>', 'my-calendar' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) ),
2145
  );
2146
  }
2147
  }
2168
  */
2169
  function mc_update_notice() {
2170
  if ( current_user_can( 'manage_options' ) && isset( $_GET['page'] ) && stripos( $_GET['page'], 'my-calendar' ) !== false ) {
2171
+ if ( '1' === get_option( 'mc_use_custom_js' ) ) {
2172
+ mc_show_notice( __( 'Stored custom JS will be removed from My Calendar in version 3.4.0. You should adapt your custom JS to a file-based replacement file or use the standard scripts.', 'my-calendar' ) . ' <a href="' . admin_url( 'admin.php?page=my-calendar-design#my-calendar-scripts' ) . '">' . __( 'Update Script Settings', 'my-calendar' ) . '</a>' );
2173
+
2174
+ }
2175
  if ( 'true' === get_option( 'mc_remote' ) ) {
2176
  mc_show_notice( __( 'My Calendar is configured to retrieve events from a remote source.', 'my-calendar' ) . ' <a href="' . admin_url( 'admin.php?page=my-calendar-config' ) . '">' . __( 'Update Settings', 'my-calendar' ) . '</a>' );
2177
  }
my-calendar-event-editor.php CHANGED
@@ -923,7 +923,7 @@ function mc_show_block( $field, $has_data, $data, $echo = true, $default = '', $
923
  $image_id = '';
924
  }
925
  if ( $show_block ) {
926
- $button_text = __( 'Select Featured Image' );
927
  $remove = '';
928
  if ( '' !== $image ) {
929
  $alt = ( $image_id ) ? get_post_meta( $image_id, '_wp_attachment_image_alt', true ) : '';
@@ -960,7 +960,7 @@ function mc_show_block( $field, $has_data, $data, $echo = true, $default = '', $
960
  </div>';
961
  $return .= '
962
  <p class="mc-primary-category">
963
- <label for="e_category">' . __( 'Primary Category', 'my-calendar-submissions' ) . '</label>
964
  <select name="primary_category" id="e_category">' . $select . '</select>
965
  </p>';
966
  } else {
@@ -1733,7 +1733,7 @@ function mc_check_data( $action, $post, $i, $ignore_required = false ) {
1733
  $event_latitude = '';
1734
  $event_location = '';
1735
 
1736
- if ( version_compare( PHP_VERSION, '7.4', '<' ) && get_magic_quotes_gpc() ) {
1737
  $post = array_map( 'stripslashes_deep', $post );
1738
  }
1739
  if ( ! wp_verify_nonce( $post['event_nonce_name'], 'event_nonce' ) ) {
923
  $image_id = '';
924
  }
925
  if ( $show_block ) {
926
+ $button_text = __( 'Select Featured Image', 'my-calendar' );
927
  $remove = '';
928
  if ( '' !== $image ) {
929
  $alt = ( $image_id ) ? get_post_meta( $image_id, '_wp_attachment_image_alt', true ) : '';
960
  </div>';
961
  $return .= '
962
  <p class="mc-primary-category">
963
+ <label for="e_category">' . __( 'Primary Category', 'my-calendar' ) . '</label>
964
  <select name="primary_category" id="e_category">' . $select . '</select>
965
  </p>';
966
  } else {
1733
  $event_latitude = '';
1734
  $event_location = '';
1735
 
1736
+ if ( version_compare( PHP_VERSION, '7.4', '<' ) && get_magic_quotes_gpc() ) { //phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.get_magic_quotes_gpcDeprecated
1737
  $post = array_map( 'stripslashes_deep', $post );
1738
  }
1739
  if ( ! wp_verify_nonce( $post['event_nonce_name'], 'event_nonce' ) ) {
my-calendar-group-manager.php CHANGED
@@ -408,7 +408,7 @@ function my_calendar_print_group_fields( $data, $mode, $event_id, $group_id = ''
408
  $addnew = '<div class="new-event-category">
409
  <p><label for="event_category_name">' . __( 'Category Name', 'my-calendar' ) . '</label> <input type="text" value="" id="event_category_name" name="event_category_name" disabled /> <button type="button" class="button add-category">' . __( 'Add Category', 'my-calendar' ) . '</button></p>
410
  </div>';
411
- $return = '<fieldset class="categories"><legend>' . __( 'Categories', 'my-calendar' ) . $match . '</legend><ul class="checkboxes">' . mc_category_select( $data, true, true ) . '<li class="event-new-category"> ' . $add_category . '</li></ul></fieldset>' . $addnew . '<p class="mc-primary-category"><label for="event_category">' . __( 'Primary Category', 'my-calendar-submissions' ) . '</label><select name="primary_category" id="e_category">' . $select . '</select></p>';
412
  echo wp_kses( $return, mc_kses_elements() );
413
  } else {
414
  ?>
@@ -439,7 +439,7 @@ function my_calendar_print_group_fields( $data, $mode, $event_id, $group_id = ''
439
  $image = ( $has_data && '' !== $data->event_image ) ? $data->event_image : '';
440
  $image_id = '';
441
  }
442
- $button_text = __( 'Select Featured Image' );
443
  $remove = '';
444
  if ( '' !== $image ) {
445
  $alt = ( $image_id ) ? get_post_meta( $image_id, '_wp_attachment_image_alt', true ) : '';
@@ -531,7 +531,7 @@ function my_calendar_print_group_fields( $data, $mode, $event_id, $group_id = ''
531
  </div>
532
  </div>
533
  <?php
534
- if ( mc_show_edit_block( 'event_open' ) ) {
535
  ?>
536
  <div class="ui-sortable meta-box-sortables">
537
  <div class="postbox">
@@ -595,7 +595,7 @@ function mc_check_group_data( $action, $post ) {
595
  $url_ok = 0;
596
  $title_ok = 0;
597
  $submit = array();
598
- if ( version_compare( PHP_VERSION, '7.4', '<' ) && get_magic_quotes_gpc() ) {
599
  $post = array_map( 'stripslashes_deep', $post );
600
  }
601
  if ( ! wp_verify_nonce( $post['event_nonce_name'], 'event_nonce' ) ) {
408
  $addnew = '<div class="new-event-category">
409
  <p><label for="event_category_name">' . __( 'Category Name', 'my-calendar' ) . '</label> <input type="text" value="" id="event_category_name" name="event_category_name" disabled /> <button type="button" class="button add-category">' . __( 'Add Category', 'my-calendar' ) . '</button></p>
410
  </div>';
411
+ $return = '<fieldset class="categories"><legend>' . __( 'Categories', 'my-calendar' ) . $match . '</legend><ul class="checkboxes">' . mc_category_select( $data, true, true ) . '<li class="event-new-category"> ' . $add_category . '</li></ul></fieldset>' . $addnew . '<p class="mc-primary-category"><label for="event_category">' . __( 'Primary Category', 'my-calendar' ) . '</label><select name="primary_category" id="e_category">' . $select . '</select></p>';
412
  echo wp_kses( $return, mc_kses_elements() );
413
  } else {
414
  ?>
439
  $image = ( $has_data && '' !== $data->event_image ) ? $data->event_image : '';
440
  $image_id = '';
441
  }
442
+ $button_text = __( 'Select Featured Image', 'my-calendar' );
443
  $remove = '';
444
  if ( '' !== $image ) {
445
  $alt = ( $image_id ) ? get_post_meta( $image_id, '_wp_attachment_image_alt', true ) : '';
531
  </div>
532
  </div>
533
  <?php
534
+ if ( mc_show_edit_block( 'event_open' ) && '' !== apply_filters( 'mc_event_registration', '', $has_data, $data, 'admin' ) ) {
535
  ?>
536
  <div class="ui-sortable meta-box-sortables">
537
  <div class="postbox">
595
  $url_ok = 0;
596
  $title_ok = 0;
597
  $submit = array();
598
+ if ( version_compare( PHP_VERSION, '7.4', '<' ) && get_magic_quotes_gpc() ) { //phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.get_magic_quotes_gpcDeprecated
599
  $post = array_map( 'stripslashes_deep', $post );
600
  }
601
  if ( ! wp_verify_nonce( $post['event_nonce_name'], 'event_nonce' ) ) {
my-calendar-help.php CHANGED
@@ -45,7 +45,7 @@ function my_calendar_help() {
45
  $permalink = mc_get_uri();
46
  $edit_url = get_edit_post_link( absint( get_option( 'mc_uri_id' ) ) );
47
  // Translators: Calendar link, calendar edit link.
48
- echo '<li>' . sprintf( __( '<a href="%1$s">View your calendar</a> or <a href="%2$s">Edit the calendar page</a>' ), esc_url( $permalink ), esc_url( $edit_url ) ) . '</li>';
49
  }
50
  $add_categories = admin_url( 'admin.php?page=my-calendar-categories' );
51
  $add_locations = admin_url( 'admin.php?page=my-calendar-locations' );
45
  $permalink = mc_get_uri();
46
  $edit_url = get_edit_post_link( absint( get_option( 'mc_uri_id' ) ) );
47
  // Translators: Calendar link, calendar edit link.
48
+ echo '<li>' . sprintf( __( '<a href="%1$s">View your calendar</a> or <a href="%2$s">Edit the calendar page</a>', 'my-calendar' ), esc_url( $permalink ), esc_url( $edit_url ) ) . '</li>';
49
  }
50
  $add_categories = admin_url( 'admin.php?page=my-calendar-categories' );
51
  $add_locations = admin_url( 'admin.php?page=my-calendar-locations' );
my-calendar-output.php CHANGED
@@ -154,6 +154,7 @@ function my_calendar_draw_event( $event, $type, $process_date, $time, $template
154
  if ( $exit_early ) {
155
  return '';
156
  }
 
157
 
158
  // assign empty values to template sections.
159
  $header = '';
@@ -463,6 +464,8 @@ function my_calendar_draw_event( $event, $type, $process_date, $time, $template
463
  } else {
464
  $details = apply_filters( 'mc_before_event_no_details', $container, $event, $type, $time ) . $header . apply_filters( 'mc_after_event_no_details', '', $event, $type, $time ) . '</div>';
465
  }
 
 
466
 
467
  return $details;
468
  }
@@ -1137,11 +1140,12 @@ function mc_calendar_params( $args ) {
1137
  'search' => $search,
1138
  );
1139
 
1140
- // Hash cannot include 'time', 'category', or 'format', since those can be changed by navigation.
1141
  $hash_args = $params;
1142
  unset( $hash_args['time'] );
1143
  unset( $hash_args['category'] );
1144
  unset( $hash_args['format'] );
 
1145
 
1146
  $hash = md5( implode( ',', $hash_args ) );
1147
  $id = ( ! $id ) ? "mc-$hash" : $id;
@@ -1200,6 +1204,27 @@ function mc_get_calendar_header( $params, $id, $tr, $start_of_week ) {
1200
  return '<div class="mc-content">' . $body;
1201
  }
1202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1203
  /**
1204
  * Create calendar output and return.
1205
  *
@@ -1208,6 +1233,12 @@ function mc_get_calendar_header( $params, $id, $tr, $start_of_week ) {
1208
  * @return string HTML output of calendar
1209
  */
1210
  function my_calendar( $args ) {
 
 
 
 
 
 
1211
  $template = isset( $args['template'] ) ? $args['template'] : '';
1212
  $content = isset( $args['content'] ) ? $args['content'] : '';
1213
  $source = isset( $args['source'] ) ? $args['source'] : 'shortcode';
@@ -1215,10 +1246,10 @@ function my_calendar( $args ) {
1215
  $months = isset( $args['months'] ) ? $args['months'] : false;
1216
 
1217
  // Get options before switching sites in multisite environments.
1218
- $list_js_class = ( '0' === get_option( 'mc_list_javascript' ) ) ? 'listjs' : '';
1219
- $grid_js_class = ( '0' === get_option( 'mc_calendar_javascript' ) ) ? 'gridjs' : '';
1220
- $mini_js_class = ( '0' === get_option( 'mc_mini_javascript' ) ) ? 'minijs' : '';
1221
- $ajax_js_class = ( '0' === get_option( 'mc_ajax_javascript' ) ) ? 'ajaxjs' : '';
1222
  $style_class = sanitize_html_class( str_replace( '.css', '', get_option( 'mc_css_file' ) ) );
1223
  $date_format = mc_date_format();
1224
  $start_of_week = ( get_option( 'start_of_week' ) === '1' ) ? 1 : 7; // convert start of week to ISO 8601 (Monday/Sunday).
@@ -1247,8 +1278,9 @@ function my_calendar( $args ) {
1247
  $id = $params['id'];
1248
  $main_class = ( '' !== $id ) ? sanitize_title( $id ) : 'all';
1249
  $cid = ( isset( $_GET['cid'] ) ) ? esc_attr( strip_tags( $_GET['cid'] ) ) : $main_class;
 
1250
  $mc_wrapper = "
1251
- <div id=\"$id\" class=\"mc-main mcjs $list_js_class $grid_js_class $mini_js_class $ajax_js_class $style_class $params[format] $params[time] $main_class\" aria-live='assertive' aria-atomic='true' aria-relevant='additions'>";
1252
  $mc_closer = '
1253
  </div>';
1254
 
@@ -1441,7 +1473,7 @@ function my_calendar( $args ) {
1441
  } else {
1442
  $title = '';
1443
  // Translators: Number of events on this date.
1444
- $inner = ' <span class="mc-list-details event-count">(' . sprintf( _n( '%d event', '%d events', count( $events ) ), count( $events ) ) . ')</span>';
1445
  }
1446
  if ( '' !== $event_output ) {
1447
  $body .= "<li id='$params[format]-$date_is'$ariacurrent class='mc-events $dateclass $events_class $odd'><strong class=\"event-date\">" . mc_wrap_title( date_i18n( $date_format, $start ) . $inner ) . "$title</strong>" . $event_output . '</li>';
@@ -1450,7 +1482,7 @@ function my_calendar( $args ) {
1450
  } else {
1451
  $marker = ( count( $events ) > 1 ) ? '&#9679;&#9679;' : '&#9679;';
1452
  // Translators: Number of events on this date.
1453
- $inner = ( count( $events ) > 0 ) ? '<span class="event-icon" aria-hidden="true">' . $marker . '</span><span class="screen-reader-text"><span class="mc-list-details event-count">(' . sprintf( _n( '%d event', '%d events', count( $events ) ), count( $events ) ) . ')</span></span>' : '';
1454
  $body .= "<$td id='$params[format]-$date_is'$ariacurrent class='$dateclass $weekend_class $monthclass $events_class day-with-date'>" . "\n <$element class='mc-date$trigger'><span aria-hidden='true'>$thisday_heading</span><span class='screen-reader-text'>" . date_i18n( $date_format, strtotime( $date_is ) ) . "</span>$inner</$close>" . $event_output . "\n</$td>\n";
1455
  }
1456
  }
@@ -1501,7 +1533,11 @@ function my_calendar( $args ) {
1501
  }
1502
  }
1503
 
1504
- return $mc_wrapper . $json_ld . apply_filters( 'my_calendar_body', $body ) . $mc_closer;
 
 
 
 
1505
  }
1506
 
1507
  /**
154
  if ( $exit_early ) {
155
  return '';
156
  }
157
+ do_action( 'my_calendar_drawing_event', $event );
158
 
159
  // assign empty values to template sections.
160
  $header = '';
464
  } else {
465
  $details = apply_filters( 'mc_before_event_no_details', $container, $event, $type, $time ) . $header . apply_filters( 'mc_after_event_no_details', '', $event, $type, $time ) . '</div>';
466
  }
467
+ $details = apply_filters( 'mc_event_details_output', $details, $event );
468
+ do_action( 'my_calendar_event_drawn', $event );
469
 
470
  return $details;
471
  }
1140
  'search' => $search,
1141
  );
1142
 
1143
+ // Hash cannot include 'time', 'category', 'search', or 'format', since those can be changed by navigation.
1144
  $hash_args = $params;
1145
  unset( $hash_args['time'] );
1146
  unset( $hash_args['category'] );
1147
  unset( $hash_args['format'] );
1148
+ unset( $hash_args['search'] );
1149
 
1150
  $hash = md5( implode( ',', $hash_args ) );
1151
  $id = ( ! $id ) ? "mc-$hash" : $id;
1204
  return '<div class="mc-content">' . $body;
1205
  }
1206
 
1207
+ /**
1208
+ * Handle switching languages in shortcodes.
1209
+ *
1210
+ * @param string $current Current language set.
1211
+ * @param string $switch Language to switch to.
1212
+ *
1213
+ * @return string HTML attribute.
1214
+ */
1215
+ function mc_switch_language( $current, $switch ) {
1216
+ $available = get_available_languages();
1217
+ $lang = '';
1218
+ if ( in_array( $switch, $available, true ) ) {
1219
+ if ( $switch && ( $current !== $switch ) ) {
1220
+ switch_to_locale( $switch );
1221
+ }
1222
+ $lang = explode( '_', $switch )[0];
1223
+ }
1224
+
1225
+ return $lang;
1226
+ }
1227
+
1228
  /**
1229
  * Create calendar output and return.
1230
  *
1233
  * @return string HTML output of calendar
1234
  */
1235
  function my_calendar( $args ) {
1236
+ $language = isset( $args['language'] ) ? $args['language'] : '';
1237
+ $switched = '';
1238
+ if ( $language ) {
1239
+ $locale = get_locale();
1240
+ $switched = mc_switch_language( $locale, $language );
1241
+ }
1242
  $template = isset( $args['template'] ) ? $args['template'] : '';
1243
  $content = isset( $args['content'] ) ? $args['content'] : '';
1244
  $source = isset( $args['source'] ) ? $args['source'] : 'shortcode';
1246
  $months = isset( $args['months'] ) ? $args['months'] : false;
1247
 
1248
  // Get options before switching sites in multisite environments.
1249
+ $list_js_class = ( '1' !== get_option( 'mc_list_javascript' ) ) ? 'listjs' : '';
1250
+ $grid_js_class = ( '1' !== get_option( 'mc_calendar_javascript' ) ) ? 'gridjs' : '';
1251
+ $mini_js_class = ( '1' !== get_option( 'mc_mini_javascript' ) ) ? 'minijs' : '';
1252
+ $ajax_js_class = ( '1' !== get_option( 'mc_ajax_javascript' ) ) ? 'ajaxjs' : '';
1253
  $style_class = sanitize_html_class( str_replace( '.css', '', get_option( 'mc_css_file' ) ) );
1254
  $date_format = mc_date_format();
1255
  $start_of_week = ( get_option( 'start_of_week' ) === '1' ) ? 1 : 7; // convert start of week to ISO 8601 (Monday/Sunday).
1278
  $id = $params['id'];
1279
  $main_class = ( '' !== $id ) ? sanitize_title( $id ) : 'all';
1280
  $cid = ( isset( $_GET['cid'] ) ) ? esc_attr( strip_tags( $_GET['cid'] ) ) : $main_class;
1281
+ $lang = ( $switched ) ? ' lang="' . esc_attr( $switched ) . '"' : '';
1282
  $mc_wrapper = "
1283
+ <div id=\"$id\" class=\"mc-main mcjs $list_js_class $grid_js_class $mini_js_class $ajax_js_class $style_class $params[format] $params[time] $main_class\" aria-live='assertive' aria-atomic='true' aria-relevant='additions'$lang>";
1284
  $mc_closer = '
1285
  </div>';
1286
 
1473
  } else {
1474
  $title = '';
1475
  // Translators: Number of events on this date.
1476
+ $inner = ' <span class="mc-list-details event-count">(' . sprintf( _n( '%d event', '%d events', count( $events ), 'my-calendar' ), count( $events ) ) . ')</span>';
1477
  }
1478
  if ( '' !== $event_output ) {
1479
  $body .= "<li id='$params[format]-$date_is'$ariacurrent class='mc-events $dateclass $events_class $odd'><strong class=\"event-date\">" . mc_wrap_title( date_i18n( $date_format, $start ) . $inner ) . "$title</strong>" . $event_output . '</li>';
1482
  } else {
1483
  $marker = ( count( $events ) > 1 ) ? '&#9679;&#9679;' : '&#9679;';
1484
  // Translators: Number of events on this date.
1485
+ $inner = ( count( $events ) > 0 ) ? '<span class="event-icon" aria-hidden="true">' . $marker . '</span><span class="screen-reader-text"><span class="mc-list-details event-count">(' . sprintf( _n( '%d event', '%d events', count( $events ), 'my-calendar' ), count( $events ) ) . ')</span></span>' : '';
1486
  $body .= "<$td id='$params[format]-$date_is'$ariacurrent class='$dateclass $weekend_class $monthclass $events_class day-with-date'>" . "\n <$element class='mc-date$trigger'><span aria-hidden='true'>$thisday_heading</span><span class='screen-reader-text'>" . date_i18n( $date_format, strtotime( $date_is ) ) . "</span>$inner</$close>" . $event_output . "\n</$td>\n";
1487
  }
1488
  }
1533
  }
1534
  }
1535
 
1536
+ $output = $mc_wrapper . $json_ld . apply_filters( 'my_calendar_body', $body ) . $mc_closer;
1537
+ if ( $language ) {
1538
+ mc_switch_language( $language, $locale );
1539
+ }
1540
+ return $output;
1541
  }
1542
 
1543
  /**
my-calendar-settings.php CHANGED
@@ -42,7 +42,12 @@ function mc_settings_field( $name, $label, $default = '', $note = '', $atts = ar
42
  }
43
  }
44
  if ( 'checkbox' !== $type ) {
45
- $value = ( '' !== $value ) ? esc_attr( stripslashes( $value ) ) : $default;
 
 
 
 
 
46
  } else {
47
  $value = ( ! empty( $value ) ) ? (array) $value : $default;
48
  }
@@ -118,7 +123,7 @@ function mc_settings_field( $name, $label, $default = '', $note = '', $atts = ar
118
  }
119
  if ( is_array( $default ) ) {
120
  foreach ( $default as $k => $v ) {
121
- $checked = ( $k === $value ) ? ' selected="selected"' : '';
122
  $options .= "<option value='" . esc_attr( $k ) . "'$checked>$v</option>";
123
  }
124
  }
@@ -229,8 +234,8 @@ function mc_update_management_settings( $post ) {
229
  update_option( 'mc_remote', $mc_remote );
230
  update_option( 'mc_drop_tables', $mc_drop_tables );
231
  update_option( 'mc_drop_settings', $mc_drop_settings );
232
- update_option( 'mc_default_sort', $post['mc_default_sort'] );
233
- update_option( 'mc_default_direction', $post['mc_default_direction'] );
234
  if ( 2 === (int) get_site_option( 'mc_multisite' ) ) {
235
  $mc_current_table = ( isset( $post['mc_current_table'] ) ) ? (int) $post['mc_current_table'] : 0;
236
  update_option( 'mc_current_table', $mc_current_table );
@@ -1149,7 +1154,7 @@ function mc_remote_db() {
1149
  <input type="radio" value="1" id="ms1" name="mc_multisite"<?php checked( get_site_option( 'mc_multisite' ), '1' ); ?> /> <label for="ms1"><?php esc_html_e( 'Site owners may only post to the central calendar.', 'my-calendar' ); ?></label>
1150
  </li>
1151
  <li>
1152
- <input type="radio" value="2" id="ms2" name="mc_multisite"<?php checked( get_site_option( 'mc_multisite' ), 2 ); ?> /> <label for="ms2"><?php esc_html_e( 'Site owners may manage either calendar', 'my-calendar.' ); ?></label>
1153
  </li>
1154
  </ul>
1155
  <p>
42
  }
43
  }
44
  if ( 'checkbox' !== $type ) {
45
+ if ( is_array( $default ) ) {
46
+ $hold = '';
47
+ } else {
48
+ $hold = $default;
49
+ }
50
+ $value = ( '' !== $value ) ? esc_attr( stripslashes( $value ) ) : $hold;
51
  } else {
52
  $value = ( ! empty( $value ) ) ? (array) $value : $default;
53
  }
123
  }
124
  if ( is_array( $default ) ) {
125
  foreach ( $default as $k => $v ) {
126
+ $checked = ( (string) $k === (string) $value ) ? ' selected="selected"' : '';
127
  $options .= "<option value='" . esc_attr( $k ) . "'$checked>$v</option>";
128
  }
129
  }
234
  update_option( 'mc_remote', $mc_remote );
235
  update_option( 'mc_drop_tables', $mc_drop_tables );
236
  update_option( 'mc_drop_settings', $mc_drop_settings );
237
+ update_option( 'mc_default_sort', absint( $post['mc_default_sort'] ) );
238
+ update_option( 'mc_default_direction', sanitize_text_field( $post['mc_default_direction'] ) );
239
  if ( 2 === (int) get_site_option( 'mc_multisite' ) ) {
240
  $mc_current_table = ( isset( $post['mc_current_table'] ) ) ? (int) $post['mc_current_table'] : 0;
241
  update_option( 'mc_current_table', $mc_current_table );
1154
  <input type="radio" value="1" id="ms1" name="mc_multisite"<?php checked( get_site_option( 'mc_multisite' ), '1' ); ?> /> <label for="ms1"><?php esc_html_e( 'Site owners may only post to the central calendar.', 'my-calendar' ); ?></label>
1155
  </li>
1156
  <li>
1157
+ <input type="radio" value="2" id="ms2" name="mc_multisite"<?php checked( get_site_option( 'mc_multisite' ), 2 ); ?> /> <label for="ms2"><?php esc_html_e( 'Site owners may manage either calendar', 'my-calendar' ); ?></label>
1158
  </li>
1159
  </ul>
1160
  <p>
my-calendar-shortcodes.php CHANGED
@@ -43,6 +43,7 @@ function my_calendar_insert( $atts, $content = null ) {
43
  'months' => false,
44
  'search' => '',
45
  'self' => '',
 
46
  ),
47
  $atts,
48
  'my_calendar'
@@ -102,6 +103,7 @@ function my_calendar_insert_upcoming( $atts ) {
102
  'from' => false,
103
  'to' => false,
104
  'site' => false,
 
105
  ),
106
  $atts,
107
  'my_calendar_upcoming'
@@ -135,6 +137,7 @@ function my_calendar_insert_today( $atts ) {
135
  'fallback' => '',
136
  'date' => false,
137
  'site' => false,
 
138
  ),
139
  $atts,
140
  'my_calendar_today'
43
  'months' => false,
44
  'search' => '',
45
  'self' => '',
46
+ 'language' => '',
47
  ),
48
  $atts,
49
  'my_calendar'
103
  'from' => false,
104
  'to' => false,
105
  'site' => false,
106
+ 'language' => '',
107
  ),
108
  $atts,
109
  'my_calendar_upcoming'
137
  'fallback' => '',
138
  'date' => false,
139
  'site' => false,
140
+ 'language' => '',
141
  ),
142
  $atts,
143
  'my_calendar_today'
my-calendar-templates.php CHANGED
@@ -16,13 +16,14 @@ if ( ! defined( 'ABSPATH' ) ) {
16
  /**
17
  * Draw array of information into a template with {$key} formatted tags
18
  *
19
- * @param array $array associative array of information intended to be parsed.
20
- * @param string $template template containing braced tags (e.g. `{title}`) using keys of passed array.
21
- * @param string $type my calendar needs to render a different link for list versions and other views.
 
22
  *
23
  * @return string HTML output of template.
24
  */
25
- function mc_draw_template( $array, $template, $type = 'list' ) {
26
  $template = stripcslashes( $template );
27
  // If there are no brace characters, there is nothing to replace.
28
  if ( strpos( $template, '{' ) === false ) {
@@ -72,6 +73,7 @@ function mc_draw_template( $array, $template, $type = 'list' ) {
72
  // End {$key check.
73
  }
74
  }
 
75
 
76
  return stripslashes( trim( $template ) );
77
  }
@@ -285,6 +287,7 @@ function mc_create_tags( $event, $context = 'filters' ) {
285
  if ( ! is_object( $event ) ) {
286
  return;
287
  }
 
288
  $calendar_id = '';
289
  if ( 'filters' !== $context && 'related' !== $context ) {
290
  $calendar_id = $context;
@@ -513,6 +516,7 @@ function mc_create_tags( $event, $context = 'filters' ) {
513
  $e['ical'] = $ical_link;
514
  $e['ical_html'] = "<a class='ical' rel='nofollow' href='" . esc_url( $ical_link ) . "' aria-describedby='mc_$event->occur_id-title-$calendar_id'>" . __( 'iCal', 'my-calendar' ) . '</a>';
515
  $e = apply_filters( 'mc_filter_shortcodes', $e, $event );
 
516
 
517
  return $e;
518
  }
16
  /**
17
  * Draw array of information into a template with {$key} formatted tags
18
  *
19
+ * @param array $array associative array of information intended to be parsed.
20
+ * @param string $template template containing braced tags (e.g. `{title}`) using keys of passed array.
21
+ * @param string $type my calendar needs to render a different link for list versions and other views.
22
+ * @param object|bool $event Event object. Optional.
23
  *
24
  * @return string HTML output of template.
25
  */
26
+ function mc_draw_template( $array, $template, $type = 'list', $event = false ) {
27
  $template = stripcslashes( $template );
28
  // If there are no brace characters, there is nothing to replace.
29
  if ( strpos( $template, '{' ) === false ) {
73
  // End {$key check.
74
  }
75
  }
76
+ $template = apply_filters( 'mc_template', $template, $array, $type, $event );
77
 
78
  return stripslashes( trim( $template ) );
79
  }
287
  if ( ! is_object( $event ) ) {
288
  return;
289
  }
290
+ do_action( 'mc_create_tags', $event, $context );
291
  $calendar_id = '';
292
  if ( 'filters' !== $context && 'related' !== $context ) {
293
  $calendar_id = $context;
516
  $e['ical'] = $ical_link;
517
  $e['ical_html'] = "<a class='ical' rel='nofollow' href='" . esc_url( $ical_link ) . "' aria-describedby='mc_$event->occur_id-title-$calendar_id'>" . __( 'iCal', 'my-calendar' ) . '</a>';
518
  $e = apply_filters( 'mc_filter_shortcodes', $e, $event );
519
+ do_action( 'mc_tags_created', $event, $context );
520
 
521
  return $e;
522
  }
my-calendar-widgets.php CHANGED
@@ -27,6 +27,12 @@ include( dirname( __FILE__ ) . '/includes/widgets/class-my-calendar-mini-widget.
27
  * @return String HTML output list.
28
  */
29
  function my_calendar_upcoming_events( $args ) {
 
 
 
 
 
 
30
  $before = ( isset( $args['before'] ) ) ? $args['before'] : 'default';
31
  $after = ( isset( $args['after'] ) ) ? $args['after'] : 'default';
32
  $type = ( isset( $args['type'] ) ) ? $args['type'] : 'default';
@@ -77,7 +83,8 @@ function my_calendar_upcoming_events( $args ) {
77
 
78
  $template = apply_filters( 'mc_upcoming_events_template', $template );
79
  $no_event_text = ( '' === $substitute ) ? $defaults['upcoming']['text'] : $substitute;
80
- $header = "<ul id='upcoming-events-$hash' class='upcoming-events'>";
 
81
  $footer = '</ul>';
82
  $display_events = ( 'events' === $display_type || 'event' === $display_type ) ? true : false;
83
  if ( ! $display_events ) {
@@ -193,7 +200,7 @@ function my_calendar_upcoming_events( $args ) {
193
  $omit[] = $event->event_group_id;
194
  }
195
  if ( '' === $item ) {
196
- $item = mc_draw_template( $details, $template );
197
  }
198
  if ( $i < $skip && 0 !== $skip ) {
199
  $i ++;
@@ -252,6 +259,10 @@ function my_calendar_upcoming_events( $args ) {
252
  restore_current_blog();
253
  }
254
 
 
 
 
 
255
  return $return;
256
  }
257
 
@@ -445,7 +456,7 @@ function mc_produce_upcoming_events( $events, $template, $type = 'list', $order
445
 
446
  $item = apply_filters( 'mc_draw_upcoming_event', '', $details, $template, $type );
447
  if ( '' === $item ) {
448
- $item = mc_draw_template( $details, $template, $type );
449
  }
450
 
451
  $output[] = apply_filters( 'mc_event_upcoming', $prepend . $item . $append, $event );
@@ -482,6 +493,13 @@ function mc_produce_upcoming_events( $events, $template, $type = 'list', $order
482
  * @return string HTML.
483
  */
484
  function my_calendar_todays_events( $args ) {
 
 
 
 
 
 
 
485
  $category = ( isset( $args['category'] ) ) ? $args['category'] : 'default';
486
  $template = ( isset( $args['template'] ) ) ? $args['template'] : 'default';
487
  $substitute = ( isset( $args['fallback'] ) ) ? $args['fallback'] : '';
@@ -543,7 +561,8 @@ function my_calendar_todays_events( $args ) {
543
  $events = my_calendar_events( $args );
544
 
545
  $today = ( isset( $events[ $from ] ) ) ? $events[ $from ] : false;
546
- $header = "<ul id='todays-events-$hash' class='todays-events'>";
 
547
  $footer = '</ul>';
548
  $groups = array();
549
  $todays_events = array();
@@ -560,7 +579,7 @@ function my_calendar_todays_events( $args ) {
560
 
561
  $item = apply_filters( 'mc_draw_todays_event', '', $event_details, $template );
562
  if ( '' === $item ) {
563
- $item = mc_draw_template( $event_details, $template );
564
  }
565
  $todays_events[ $ts ][] = $prepend . $item . $append;
566
  }
@@ -584,5 +603,11 @@ function my_calendar_todays_events( $args ) {
584
  restore_current_blog();
585
  }
586
 
587
- return mc_run_shortcodes( $return );
 
 
 
 
 
 
588
  }
27
  * @return String HTML output list.
28
  */
29
  function my_calendar_upcoming_events( $args ) {
30
+ $language = isset( $args['language'] ) ? $args['language'] : '';
31
+ $switched = '';
32
+ if ( $language ) {
33
+ $locale = get_locale();
34
+ $switched = mc_switch_language( $locale, $language );
35
+ }
36
  $before = ( isset( $args['before'] ) ) ? $args['before'] : 'default';
37
  $after = ( isset( $args['after'] ) ) ? $args['after'] : 'default';
38
  $type = ( isset( $args['type'] ) ) ? $args['type'] : 'default';
83
 
84
  $template = apply_filters( 'mc_upcoming_events_template', $template );
85
  $no_event_text = ( '' === $substitute ) ? $defaults['upcoming']['text'] : $substitute;
86
+ $lang = ( $switched ) ? ' lang="' . esc_attr( $switched ) . '"' : '';
87
+ $header = "<ul id='upcoming-events-$hash' class='upcoming-events'$lang>";
88
  $footer = '</ul>';
89
  $display_events = ( 'events' === $display_type || 'event' === $display_type ) ? true : false;
90
  if ( ! $display_events ) {
200
  $omit[] = $event->event_group_id;
201
  }
202
  if ( '' === $item ) {
203
+ $item = mc_draw_template( $details, $template, 'upcoming', $event );
204
  }
205
  if ( $i < $skip && 0 !== $skip ) {
206
  $i ++;
259
  restore_current_blog();
260
  }
261
 
262
+ if ( $language ) {
263
+ mc_switch_language( $language, $locale );
264
+ }
265
+
266
  return $return;
267
  }
268
 
456
 
457
  $item = apply_filters( 'mc_draw_upcoming_event', '', $details, $template, $type );
458
  if ( '' === $item ) {
459
+ $item = mc_draw_template( $details, $template, $type, $event );
460
  }
461
 
462
  $output[] = apply_filters( 'mc_event_upcoming', $prepend . $item . $append, $event );
493
  * @return string HTML.
494
  */
495
  function my_calendar_todays_events( $args ) {
496
+ $language = isset( $args['language'] ) ? $args['language'] : '';
497
+ $switched = '';
498
+ if ( $language ) {
499
+ $locale = get_locale();
500
+ $switched = mc_switch_language( $locale, $language );
501
+ }
502
+
503
  $category = ( isset( $args['category'] ) ) ? $args['category'] : 'default';
504
  $template = ( isset( $args['template'] ) ) ? $args['template'] : 'default';
505
  $substitute = ( isset( $args['fallback'] ) ) ? $args['fallback'] : '';
561
  $events = my_calendar_events( $args );
562
 
563
  $today = ( isset( $events[ $from ] ) ) ? $events[ $from ] : false;
564
+ $lang = ( $switched ) ? ' lang="' . esc_attr( $switched ) . '"' : '';
565
+ $header = "<ul id='todays-events-$hash' class='todays-events'$lang>";
566
  $footer = '</ul>';
567
  $groups = array();
568
  $todays_events = array();
579
 
580
  $item = apply_filters( 'mc_draw_todays_event', '', $event_details, $template );
581
  if ( '' === $item ) {
582
+ $item = mc_draw_template( $event_details, $template, 'today', $e );
583
  }
584
  $todays_events[ $ts ][] = $prepend . $item . $append;
585
  }
603
  restore_current_blog();
604
  }
605
 
606
+ $output = mc_run_shortcodes( $return );
607
+
608
+ if ( $language ) {
609
+ mc_switch_language( $language, $locale );
610
+ }
611
+
612
+ return $output;
613
  }
my-calendar.php CHANGED
@@ -17,7 +17,7 @@
17
  * License: GPL-2.0+
18
  * License URI: http://www.gnu.org/license/gpl-2.0.txt
19
  * Domain Path: lang
20
- * Version: 3.3.12
21
  */
22
 
23
  /*
@@ -42,7 +42,7 @@ if ( ! defined( 'ABSPATH' ) ) {
42
  }
43
 
44
  global $mc_version, $wpdb;
45
- $mc_version = '3.3.12';
46
 
47
  define( 'MC_DEBUG', false );
48
 
17
  * License: GPL-2.0+
18
  * License URI: http://www.gnu.org/license/gpl-2.0.txt
19
  * Domain Path: lang
20
+ * Version: 3.3.15
21
  */
22
 
23
  /*
42
  }
43
 
44
  global $mc_version, $wpdb;
45
+ $mc_version = '3.3.15';
46
 
47
  define( 'MC_DEBUG', false );
48
 
readme.txt CHANGED
@@ -3,10 +3,10 @@ Contributors: joedolson
3
  Donate link: http://www.joedolson.com/donate/
4
  Tags: calendar, dates, times, event, events, scheduling, schedule, event manager, event calendar, class, concert, venue, location, box office, tickets, registration
5
  Requires at least: 4.4
6
- Tested up to: 5.9
7
  Requires PHP: 7.0
8
  Text domain: my-calendar
9
- Stable tag: 3.3.12
10
  License: GPLv2 or later
11
 
12
  Accessible WordPress event calendar plugin. Show events from multiple calendars on pages, in posts, or in widgets.
@@ -84,6 +84,32 @@ Translating my plugins is always appreciated. Visit <a href="https://translate.w
84
 
85
  == Changelog ==
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  = 3.3.12 =
88
 
89
  * Bug fix: Find title and find event should use nearest event, not first event.
3
  Donate link: http://www.joedolson.com/donate/
4
  Tags: calendar, dates, times, event, events, scheduling, schedule, event manager, event calendar, class, concert, venue, location, box office, tickets, registration
5
  Requires at least: 4.4
6
+ Tested up to: 6.0
7
  Requires PHP: 7.0
8
  Text domain: my-calendar
9
+ Stable tag: 3.3.15
10
  License: GPLv2 or later
11
 
12
  Accessible WordPress event calendar plugin. Show events from multiple calendars on pages, in posts, or in widgets.
84
 
85
  == Changelog ==
86
 
87
+ = 3.3.15 =
88
+
89
+ * Bug fix: CPT base values shouldn't allow URL-invalid characters.
90
+ * Bug fix: Improper variable type checking in mc_settings checkboxes.
91
+ * Bug fix: Unset search variable in auto-generated display hashes.
92
+ * New filters: Filter event object. (multilanguage support in Pro)
93
+ * New filter: Filters on single event HTML. (multilanguage support in Pro)
94
+ * Add: `language` attribute in main, today, and upcoming events shortcodes.
95
+
96
+ = 3.3.14 =
97
+
98
+ * Bug fix: Variables undefined if scripts disabled.
99
+ * Update tested to value for WP 6.0.
100
+
101
+ = 3.3.13 =
102
+
103
+ * Bug fix: Don't display empty field containers if field settings are empty.
104
+ * Bug fix: Pass version number to core stylesheet.
105
+ * Bug fix: Prevent warning from undefined GET variable in previous/next event links.
106
+ * Bug fix: Allow strong, b, and hr in shortcode output.
107
+ * Bug fix: Override masking; causing too many display problems.
108
+ * Bug fix: JS classes in main output used inverted comparisons.
109
+ * Notice: Custom JS will be disabled and removed in 3.4.
110
+ * Change: Collapsed view scripts from five files to one file.
111
+ * Change: Load new combined file minified.
112
+
113
  = 3.3.12 =
114
 
115
  * Bug fix: Find title and find event should use nearest event, not first event.