Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/my-calendar/includes/conditionals.php
+++ b/my-calendar/includes/conditionals.php
@@ -50,7 +50,7 @@
* @return boolean
*/
function mc_is_custom_icon() {
- $on = ( WP_DEBUG ) ? false : get_transient( 'mc_custom_icons' );
+ $on = get_transient( 'mc_custom_icons' );
$dir = trailingslashit( dirname( __DIR__, 1 ) );
$base = trailingslashit( basename( $dir ) );
if ( str_contains( $dir, 'my-calendar/src' ) ) {
@@ -75,9 +75,7 @@
} else {
$return = true;
}
- if ( ! WP_DEBUG ) {
- set_transient( 'mc_custom_icons', true, HOUR_IN_SECONDS );
- }
+ set_transient( 'mc_custom_icons', true, HOUR_IN_SECONDS );
}
}
--- a/my-calendar/includes/date-utilities.php
+++ b/my-calendar/includes/date-utilities.php
@@ -459,58 +459,62 @@
* @return int de-internationalized change
*/
function mc_strtotime( $date ) {
- $months = array(
- date_i18n( 'F', strtotime( 'January 1' ) ),
- date_i18n( 'F', strtotime( 'February 1' ) ),
- date_i18n( 'F', strtotime( 'March 1' ) ),
- date_i18n( 'F', strtotime( 'April 1' ) ),
- date_i18n( 'F', strtotime( 'May 1' ) ),
- date_i18n( 'F', strtotime( 'June 1' ) ),
- date_i18n( 'F', strtotime( 'July 1' ) ),
- date_i18n( 'F', strtotime( 'August 1' ) ),
- date_i18n( 'F', strtotime( 'September 1' ) ),
- date_i18n( 'F', strtotime( 'October 1' ) ),
- date_i18n( 'F', strtotime( 'November 1' ) ),
- date_i18n( 'F', strtotime( 'December 1' ) ),
- date_i18n( 'M', strtotime( 'January 1' ) ),
- date_i18n( 'M', strtotime( 'February 1' ) ),
- date_i18n( 'M', strtotime( 'March 1' ) ),
- date_i18n( 'M', strtotime( 'April 1' ) ),
- date_i18n( 'M', strtotime( 'May 1' ) ),
- date_i18n( 'M', strtotime( 'June 1' ) ),
- date_i18n( 'M', strtotime( 'July 1' ) ),
- date_i18n( 'M', strtotime( 'August 1' ) ),
- date_i18n( 'M', strtotime( 'September 1' ) ),
- date_i18n( 'M', strtotime( 'October 1' ) ),
- date_i18n( 'M', strtotime( 'November 1' ) ),
- date_i18n( 'M', strtotime( 'December 1' ) ),
- );
- $english = array(
- 'January',
- 'February',
- 'March',
- 'April',
- 'May',
- 'June',
- 'July',
- 'August',
- 'September',
- 'October',
- 'November',
- 'December',
- 'Jan',
- 'Feb',
- 'Mar',
- 'Apr',
- 'May',
- 'Jun',
- 'Jul',
- 'Aug',
- 'Sep',
- 'Oct',
- 'Nov',
- 'Dec',
- );
+ static $months = null;
+ static $english = null;
+ if ( null === $months ) {
+ $months = array(
+ date_i18n( 'F', strtotime( 'January 1' ) ),
+ date_i18n( 'F', strtotime( 'February 1' ) ),
+ date_i18n( 'F', strtotime( 'March 1' ) ),
+ date_i18n( 'F', strtotime( 'April 1' ) ),
+ date_i18n( 'F', strtotime( 'May 1' ) ),
+ date_i18n( 'F', strtotime( 'June 1' ) ),
+ date_i18n( 'F', strtotime( 'July 1' ) ),
+ date_i18n( 'F', strtotime( 'August 1' ) ),
+ date_i18n( 'F', strtotime( 'September 1' ) ),
+ date_i18n( 'F', strtotime( 'October 1' ) ),
+ date_i18n( 'F', strtotime( 'November 1' ) ),
+ date_i18n( 'F', strtotime( 'December 1' ) ),
+ date_i18n( 'M', strtotime( 'January 1' ) ),
+ date_i18n( 'M', strtotime( 'February 1' ) ),
+ date_i18n( 'M', strtotime( 'March 1' ) ),
+ date_i18n( 'M', strtotime( 'April 1' ) ),
+ date_i18n( 'M', strtotime( 'May 1' ) ),
+ date_i18n( 'M', strtotime( 'June 1' ) ),
+ date_i18n( 'M', strtotime( 'July 1' ) ),
+ date_i18n( 'M', strtotime( 'August 1' ) ),
+ date_i18n( 'M', strtotime( 'September 1' ) ),
+ date_i18n( 'M', strtotime( 'October 1' ) ),
+ date_i18n( 'M', strtotime( 'November 1' ) ),
+ date_i18n( 'M', strtotime( 'December 1' ) ),
+ );
+ $english = array(
+ 'January',
+ 'February',
+ 'March',
+ 'April',
+ 'May',
+ 'June',
+ 'July',
+ 'August',
+ 'September',
+ 'October',
+ 'November',
+ 'December',
+ 'Jan',
+ 'Feb',
+ 'Mar',
+ 'Apr',
+ 'May',
+ 'Jun',
+ 'Jul',
+ 'Aug',
+ 'Sep',
+ 'Oct',
+ 'Nov',
+ 'Dec',
+ );
+ }
return strtotime( str_replace( $months, $english, $date ) );
}
@@ -530,11 +534,11 @@
$timestamp = time();
}
if ( $offset ) {
- $offset = intval( get_option( 'gmt_offset', 0 ) ) * 60 * 60;
+ $gmt_offset = intval( get_option( 'gmt_offset', 0 ) ) * 60 * 60;
} else {
- $offset = 0;
+ $gmt_offset = 0;
}
- $timestamp = $timestamp + $offset;
+ $timestamp = $timestamp + $gmt_offset;
return ( '' === $format ) ? $timestamp : gmdate( $format, $timestamp );
}
@@ -576,6 +580,10 @@
* @return array HTML for each day in an array.
*/
function mc_name_days( $format ) {
+ static $cache = array();
+ if ( isset( $cache[ $format ] ) ) {
+ return $cache[ $format ];
+ }
$name_days = array(
'<abbr title="' . date_i18n( 'l', strtotime( 'Monday' ) ) . '" aria-hidden="true">' . date_i18n( 'D', strtotime( 'Monday' ) ) . '</abbr><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Monday' ) ) . '</span>',
'<abbr title="' . date_i18n( 'l', strtotime( 'Tuesday' ) ) . '" aria-hidden="true">' . date_i18n( 'D', strtotime( 'Tuesday' ) ) . '</abbr><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Tuesday' ) ) . '</span>',
@@ -597,6 +605,7 @@
'<span aria-hidden="true">' . __( '<abbr title="Sunday">S</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Sunday' ) ) . '</span>', // phpcs:ignore WordPress.WP.I18n.NoHtmlWrappedStrings
);
}
+ $cache[ $format ] = $name_days;
return $name_days;
}
@@ -805,12 +814,36 @@
* @return string
*/
function mc_date_format() {
- $date_format = ( '' === mc_get_option( 'date_format' ) ) ? get_option( 'date_format' ) : mc_get_option( 'date_format' );
+ static $date_format = null;
+ if ( null === $date_format ) {
+ $date_format = ( '' === mc_get_option( 'date_format' ) ) ? get_option( 'date_format' ) : mc_get_option( 'date_format' );
+ }
return $date_format;
}
/**
+ * Get the My Calendar time format.
+ *
+ * @return string format.
+ */
+function mc_time_format() {
+ static $mc_time_format = null;
+ if ( null === $mc_time_format ) {
+ $mc_time_format = mc_get_option( 'time_format' );
+ $time_format = get_option( 'time_format', '' );
+ if ( '' === $mc_time_format ) {
+ $mc_time_format = $time_format;
+ }
+ if ( '' === $mc_time_format ) {
+ $mc_time_format = 'h:i a';
+ }
+ }
+
+ return $mc_time_format;
+}
+
+/**
* Produce the human-readable string for recurrence.
*
* @param object $event Event object.
--- a/my-calendar/includes/db.php
+++ b/my-calendar/includes/db.php
@@ -90,6 +90,11 @@
* @return string properly prefixed table name
*/
function my_calendar_select_table( $table = 'my_calendar_events', $site = false ) {
+ static $table_cache = array();
+ $cache_key = $table . '_' . ( $site ? $site : get_current_blog_id() );
+ if ( isset( $table_cache[ $cache_key ] ) ) {
+ return $table_cache[ $cache_key ];
+ }
global $wpdb;
/**
@@ -136,6 +141,7 @@
} else {
$return = $local;
}
+ $table_cache[ $cache_key ] = $return;
return $return;
}
--- a/my-calendar/includes/general-utilities.php
+++ b/my-calendar/includes/general-utilities.php
@@ -211,21 +211,26 @@
* @return string white or black hex value
*/
function mc_inverse_color( $color ) {
- $color = str_replace( '#', '', $color );
+ static $cache = array();
+ $color = str_replace( '#', '', $color );
if ( strlen( $color ) !== 6 ) {
return '#000000';
}
- $rgb = '';
- $total = 0;
+ if ( isset( $cache[ $color ] ) ) {
+ return $cache[ $color ];
+ }
$red = 0.299 * ( 255 - hexdec( substr( $color, 0, 2 ) ) );
$green = 0.587 * ( 255 - hexdec( substr( $color, 2, 2 ) ) );
$blue = 0.114 * ( 255 - hexdec( substr( $color, 4, 2 ) ) );
$luminance = 1 - ( ( $red + $green + $blue ) / 255 );
if ( $luminance < 0.5 ) {
- return '#ffffff';
+ $return = '#ffffff';
} else {
- return '#000000';
+ $return = '#000000';
}
+ $cache[ $color ] = $return;
+
+ return $return;
}
/**
--- a/my-calendar/my-calendar-api.php
+++ b/my-calendar/my-calendar-api.php
@@ -80,10 +80,9 @@
*
* @return {array}
*/
- $args = apply_filters( 'mc_filter_api_args', $args, $request );
- $data = my_calendar_events( $args );
- $output = mc_format_api( $data, $format );
- echo wp_kses_post( $output );
+ $args = apply_filters( 'mc_filter_api_args', $args, $request );
+ $data = my_calendar_events( $args );
+ mc_format_api( $data, $format );
}
die;
} else {
@@ -159,11 +158,11 @@
unset( $values['event_id'] );
}
- foreach ( $values as $key => $text ) {
+ foreach ( $values as $k => $text ) {
if ( is_array( $text ) ) {
$text = implode( '|', $text );
}
- $values[ $key ] = mc_clean_data( $text );
+ $values[ $k ] = mc_clean_data( $text );
}
if ( ! $keyed ) {
$keys = array_keys( $values );
@@ -274,14 +273,14 @@
* Generate Google subscribe feed data.
*/
function mc_ics_subscribe_google() {
- mc_ics_subscribe( 'google' );
+ mc_ics_subscribe();
}
/**
* Generate Outlook subscribe feed data.
*/
function mc_ics_subscribe_outlook() {
- mc_ics_subscribe( 'outlook' );
+ mc_ics_subscribe();
}
/**
--- a/my-calendar/my-calendar-categories.php
+++ b/my-calendar/my-calendar-categories.php
@@ -28,6 +28,7 @@
$result = $wpdb->query( $wpdb->prepare( 'UPDATE ' . my_calendar_categories_table() . " SET $field = %d WHERE category_id=%d", $data, $category ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
// Delete category caches.
delete_transient( 'mc_cat_' . $category );
+ delete_transient( 'mc_private_categories' );
return $result;
}
@@ -50,7 +51,7 @@
if ( ! $wp_filesystem->exists( $directory ) ) {
return array();
}
- $results = ( WP_DEBUG ) ? array() : get_transient( 'mc_icon_list' );
+ $results = get_transient( 'mc_icon_list' );
if ( empty( $results ) ) {
$results = array();
$files = list_files( $directory );
@@ -111,6 +112,10 @@
* @return array private categories
*/
function mc_get_private_categories() {
+ $cache = get_transient( 'mc_private_categories' );
+ if ( $cache ) {
+ return $cache;
+ }
$mcdb = mc_is_remote_db();
$table = my_calendar_categories_table();
$query = 'SELECT category_id FROM `' . $table . '` WHERE category_private = 1';
@@ -129,7 +134,10 @@
*
* @return {array}
*/
- return apply_filters( 'mc_private_categories', $categories );
+ $return = apply_filters( 'mc_private_categories', $categories );
+ set_transient( 'mc_private_categories', $return, WEEK_IN_SECONDS );
+
+ return $return;
}
/**
@@ -792,9 +800,14 @@
* @return object
*/
function mc_get_category( $category ) {
+ static $cat_cache = array();
+ if ( is_int( $category ) && isset( $cat_cache[ $category ] ) && ! is_admin() ) {
+ return $cat_cache[ $category ];
+ }
if ( is_int( $category ) ) {
$cat = get_transient( 'mc_cat_' . $category );
if ( $cat ) {
+ $cat_cache[ (int) $category ] = $cat;
return $cat;
}
}
--- a/my-calendar/my-calendar-core.php
+++ b/my-calendar/my-calendar-core.php
@@ -1528,6 +1528,16 @@
);
$wp_admin_bar->add_node( $args );
}
+ if ( function_exists( 'mcs_submissions' ) && is_numeric( get_option( 'mcs_edit_id' ) ) && mcs_user_can_submit_events() ) {
+ $url = get_permalink( get_option( 'mcs_edit_id' ) );
+ $args = array(
+ 'id' => 'mc-edit-events',
+ 'title' => __( 'Public Event List', 'my-calendar' ),
+ 'href' => $url,
+ 'parent' => 'mc-my-calendar',
+ );
+ $wp_admin_bar->add_node( $args );
+ }
}
/**
@@ -1827,7 +1837,8 @@
'mc.duet',
'duetFormats',
array(
- 'date' => ( get_option( 'mcs_date_format', '' ) ) ? get_option( 'mcs_date_format' ) : 'Y-m-d',
+ 'date' => ( get_option( 'mcs_date_format', '' ) ) ? get_option( 'mcs_date_format' ) : 'Y-m-d',
+ 'error' => __( 'Your selected end date is before your start date.', 'my-calendar' ),
)
);
wp_localize_script(
@@ -2050,25 +2061,6 @@
}
}
-
-/**
- * Get the My Calendar time format.
- *
- * @return string format.
- */
-function mc_time_format() {
- $mc_time_format = mc_get_option( 'time_format' );
- $time_format = get_option( 'time_format', '' );
- if ( '' === $mc_time_format ) {
- $mc_time_format = $time_format;
- }
- if ( '' === $mc_time_format ) {
- $mc_time_format = 'h:i a';
- }
-
- return $mc_time_format;
-}
-
/**
* Return a table header with sortability.
*
--- a/my-calendar/my-calendar-event-editor.php
+++ b/my-calendar/my-calendar-event-editor.php
@@ -283,17 +283,26 @@
$post_status = $privacy;
$auth = $data['event_author'];
$type = 'mc-events';
- $my_post = array(
+ /**
+ * Filter the permalink slug for My Calendar events. Return value will be run through `sanitize_title()`.
+ *
+ * @hook mc_event_permalink_slug
+ *
+ * @param {string} $title The event title, before sanitizing.
+ * @param {array} $data Array of event data.
+ */
+ $post_name = apply_filters( 'mc_event_permalink_slug', $title, $data );
+ $my_post = array(
'post_title' => $title,
'post_content' => $description,
'post_status' => $post_status,
'post_author' => $auth,
- 'post_name' => sanitize_title( $title ),
+ 'post_name' => sanitize_title( $post_name ),
'post_date' => current_time( 'Y-m-d H:i:s' ),
'post_type' => $type,
'post_excerpt' => $excerpt,
);
- $post_id = wp_insert_post( $my_post );
+ $post_id = wp_insert_post( $my_post );
wp_set_object_terms( $post_id, $terms, 'mc-event-category' );
$attachment_id = false;
if ( isset( $post['event_image_id'] ) ) {
@@ -563,6 +572,7 @@
$proceed = (bool) $output[0];
$post = $output[4];
$message = '';
+ $type = 'notice';
$event_post = false;
$formats = array( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d' );
@@ -792,10 +802,6 @@
} else {
// do an action using the $action and processed event data.
$new_event_status = ( current_user_can( 'mc_approve_events' ) ) ? 1 : 0;
- // check for event_approved provides support for older versions of My Calendar Pro.
- if ( isset( $post['event_approved'] ) && $post['event_approved'] !== $new_event_status ) {
- $new_event_status = absint( $post['event_approved'] );
- }
if ( isset( $post['prev_event_status'] ) ) {
/**
* Execute an action when an event changes status.
@@ -858,6 +864,15 @@
$instance = false;
$post_id = mc_get_data( 'event_post', $event_id );
if ( empty( $_POST['event_instance'] ) ) {
+ /**
+ * Action run just before an event is deleted.
+ *
+ * @hook mc_before_delete_event
+ *
+ * @param {int} $event_id Event ID.
+ * @param {int} $post_id Event Post ID.
+ */
+ do_action( 'mc_before_delete_event', $event_id, $post_id );
// Delete from instance table.
$wpdb->query( $wpdb->prepare( 'DELETE FROM ' . my_calendar_event_table() . ' WHERE occur_event_id=%d', $event_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
// Delete from event table.
@@ -1137,7 +1152,7 @@
* @param string $default_str Default string value.
* @param int|false $group_id If in group editing, group ID.
*
- * @return string.
+ * @return string
*/
function mc_show_block( $field, $has_data, $data, $display = true, $default_str = '', $group_id = false ) {
global $user_ID;
@@ -2235,9 +2250,6 @@
$desc = '';
$primary = 1;
- if ( version_compare( PHP_VERSION, '7.4', '<' ) && get_magic_quotes_gpc() ) { //phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.get_magic_quotes_gpcDeprecated
- $post = array_map( 'stripslashes_deep', $post );
- }
if ( ! wp_verify_nonce( $post['event_nonce_name'], 'event_nonce' ) ) {
return array();
}
@@ -2380,10 +2392,6 @@
$event_link = ! empty( $post['event_link'] ) ? trim( $post['event_link'] ) : '';
$expires = ! empty( $post['event_link_expires'] ) ? $post['event_link_expires'] : '0';
$approved = ( current_user_can( 'mc_approve_events' ) ) ? 1 : 0;
- // Check for event_approved provides support for older versions of My Calendar Pro.
- if ( isset( $post['event_approved'] ) && $post['event_approved'] !== $approved ) {
- $approved = absint( $post['event_approved'] );
- }
$saved_location = ! empty( $post['preset_location'] ) ? $post['preset_location'] : '';
$select_location = ( ! empty( $post['location_preset'] ) ) ? $post['location_preset'] : '';
@@ -2921,7 +2929,7 @@
<label for="mc_event_date" id="eblabel">' . __( 'Date', 'my-calendar' ) . '</label> ' . $picker_begin . '
</p>
<p>
- <label for="mc_event_enddate" id="eelabel" aria-labelledby="eelabel event_date_error"><em>' . __( 'End Date (optional)', 'my-calendar' ) . '</em></label> ' . $picker_end . '<span id="event_date_error" aria-live="assertive"><span class="dashicons dashicons-no" aria-hidden="true"></span>' . __( 'Your selected end date is before your start date.', 'my-calendar' ) . '</span>
+ <label for="mc_event_enddate" id="eelabel" aria-labelledby="eelabel event_date_error"><em>' . __( 'End Date (optional)', 'my-calendar' ) . '</em></label> ' . $picker_end . '<span id="event_date_error" aria-live="assertive"></span>
</p>
</div>
<ul class="checkboxes">
--- a/my-calendar/my-calendar-event-manager.php
+++ b/my-calendar/my-calendar-event-manager.php
@@ -93,10 +93,10 @@
*
* @hook mcs_complete_submission
*
- * @param {string} $name Submitter's name.
- * @param {string} $email Submitter's email.
- * @param {int} $id Event ID.
- * @param {string} $action Action performed ('edit').
+ * @param {string} $name Submitter's name.
+ * @param {string} $email Submitter's email.
+ * @param {int|object} $id Event ID in bulk actions; event object in single actions.
+ * @param {string} $action Action performed ('edit').
*/
do_action( 'mcs_complete_submission', $name, $email, $id, 'edit' );
}
@@ -712,6 +712,8 @@
$filter = $filters['filter'];
$restrict = $filters['restrict'];
$allow_filters = true;
+ $nav_label = __( 'Events Pagination', 'my-calendar' );
+ $user_count = $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(DISTINCT event_author) FROM %i', my_calendar_table() ) );
if ( ! current_user_can( 'mc_manage_events' ) && ! current_user_can( 'mc_approve_events' ) ) {
$restrict = 'event_author';
@@ -763,21 +765,20 @@
$found_rows = $wpdb->get_col( 'SELECT COUNT(*) FROM ' . my_calendar_table() . ' AS e ' . $join . ' JOIN ' . my_calendar_categories_table() . " AS c WHERE e.event_category = c.category_id $limit ORDER BY c.category_name $sortbydirection" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
}
- $items = $found_rows[0];
- $num_pages = ceil( $items / $query['items_per_page'] );
+ $items = $found_rows[0];
+ $num_pages = ceil( $items / $query['items_per_page'] );
+ $page_links = paginate_links(
+ array(
+ 'base' => add_query_arg( 'paged', '%#%' ),
+ 'format' => '',
+ 'prev_text' => __( '« Previous<span class="screen-reader-text"> Events</span>', 'my-calendar' ),
+ 'next_text' => __( 'Next<span class="screen-reader-text"> Events</span> »', 'my-calendar' ),
+ 'total' => $num_pages,
+ 'current' => $query['current'],
+ 'mid_size' => 2,
+ )
+ );
if ( $num_pages > 1 ) {
- $page_links = paginate_links(
- array(
- 'base' => add_query_arg( 'paged', '%#%' ),
- 'format' => '',
- 'prev_text' => __( '« Previous<span class="screen-reader-text"> Events</span>', 'my-calendar' ),
- 'next_text' => __( 'Next<span class="screen-reader-text"> Events</span> »', 'my-calendar' ),
- 'total' => $num_pages,
- 'current' => $query['current'],
- 'mid_size' => 2,
- )
- );
- $nav_label = __( 'Events Pagination', 'my-calendar' );
?>
<nav class='tablenav' aria-label='<?php echo esc_attr( $nav_label ); ?>'>
<div class='tablenav-pages'>
@@ -831,8 +832,10 @@
$col_head .= mc_table_header( __( 'Location', 'my-calendar' ), $sortbydirection, $sortby, '7', $url );
$url = add_query_arg( 'sort', '4', $admin_url );
$col_head .= mc_table_header( __( 'Date/Time', 'my-calendar' ), $sortbydirection, $sortby, '4', $url );
- $url = add_query_arg( 'sort', '5', $admin_url );
- $col_head .= mc_table_header( __( 'Author', 'my-calendar' ), $sortbydirection, $sortby, '5', $url );
+ if ( $user_count > 1 ) {
+ $url = add_query_arg( 'sort', '5', $admin_url );
+ $col_head .= mc_table_header( __( 'Author', 'my-calendar' ), $sortbydirection, $sortby, '5', $url );
+ }
$url = add_query_arg( 'sort', '6', $admin_url );
$col_head .= mc_table_header( __( 'Category', 'my-calendar' ), $sortbydirection, $sortby, '6', $url );
echo wp_kses( $col_head, 'mycalendar' );
@@ -896,7 +899,8 @@
*/
function mc_admin_events_table( $events ) {
global $wpdb;
- $class = '';
+ $class = '';
+ $user_count = $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(DISTINCT event_author) FROM %i', my_calendar_table() ) );
foreach ( array_keys( $events ) as $key ) {
$e =& $events[ $key ];
@@ -937,7 +941,7 @@
$can_edit = mc_can_edit_event( $event );
if ( current_user_can( 'mc_manage_events' ) || current_user_can( 'mc_approve_events' ) || $can_edit ) {
?>
- <tr class="<?php echo esc_attr( "$class $spam $pending $trashed $problem $cancelled" ); ?>">
+ <tr class="<?php echo esc_attr( trim( "$class $spam $pending $trashed $problem $cancelled" ) ); ?>">
<th scope="row">
<input type="checkbox" value="<?php echo absint( $event->event_id ); ?>" name="mass_edit[]" id="mc<?php echo absint( $event->event_id ); ?>" aria-describedby='event<?php echo absint( $event->event_id ); ?>' />
<label for="mc<?php echo absint( $event->event_id ); ?>">
@@ -1048,21 +1052,30 @@
}
$begin = date_i18n( mc_date_format(), mc_strtotime( $event->event_begin ) );
echo esc_html( "$begin, $event_time" );
- ?>
+ $recurs = mc_recur_string( $event );
+ if ( $recurs ) {
+ ?>
<div class="recurs">
- <?php echo wp_kses_post( mc_recur_string( $event ) ); ?>
+ <?php echo wp_kses_post( $recurs ); ?>
</div>
+ <?php
+ }
+ ?>
</td>
<?php
- $auth = ( is_object( $author ) ) ? $author->ID : 0;
- $filter = mc_admin_url( "admin.php?page=my-calendar-manage&filter=$auth&restrict=author" );
- $author = ( is_object( $author ) ? $author->display_name : $author );
- ?>
+ if ( $user_count > 1 ) {
+ $auth = ( is_object( $author ) ) ? $author->ID : 0;
+ $filter = mc_admin_url( "admin.php?page=my-calendar-manage&filter=$auth&restrict=author" );
+ $author = ( is_object( $author ) ? $author->display_name : $author );
+ ?>
<td>
<a class='mc_filter' href="<?php echo esc_url( $filter ); ?>">
<span class="screen-reader-text"><?php esc_html_e( 'Show only: ', 'my-calendar' ); ?></span><?php echo esc_html( $author ); ?>
</a>
</td>
+ <?php
+ }
+ ?>
<td>
<div class="mc-category-list">
<?php echo wp_kses( mc_admin_category_list( $event ), mc_kses_elements() ); ?>
@@ -1156,7 +1169,7 @@
}
/**
- * Filter permissions to edit an event via the My Calendar Pro REST API..
+ * Filter permissions to edit an event via the My Calendar Pro REST API.
*
* @hook mc_api_can_edit_event
*
--- a/my-calendar/my-calendar-events.php
+++ b/my-calendar/my-calendar-events.php
@@ -365,6 +365,7 @@
$ts_string = mc_ts();
$select_window = ( ! $before ) ? 'AND occur_begin > ' . $now_limit : '';
$select_window = ( ! $after ) ? 'AND occur_end < ' . $now_limit : $select_window;
+ $now_limit = "$select_published $select_category $select_author $select_host $select_access $search";
$limit = "$select_published $select_category $select_author $select_host $select_access $search $select_window";
// New Query style.
@@ -385,6 +386,25 @@
ORDER BY $ordering ASC LIMIT 0,$total"
);
+ if ( 'now' === $time ) {
+ $now_events_time = current_time( 'Y-m-d H:i:s' );
+ $event_query = 'SELECT *, ' . $ts_string . '
+ FROM ' . my_calendar_event_table( $site ) . ' AS o
+ JOIN ' . my_calendar_table( $site ) . " AS e
+ ON (event_id=occur_event_id)
+ $join
+ $location_join
+ JOIN " . my_calendar_categories_table( $site ) . " AS c
+ ON (event_category=category_id)
+ WHERE $now_limit
+ $exclude_categories
+ AND ( CAST('$now_events_time' AS DATETIME) BETWEEN occur_begin AND occur_end )
+ ORDER BY $ordering ASC LIMIT 0,$total";
+
+ $now_events = $mcdb->get_results( $event_query );
+ $events = array_merge( $events, $now_events );
+ }
+
$cats = array();
foreach ( array_keys( $events ) as $key ) {
$event =& $events[ $key ];
@@ -555,7 +575,8 @@
*
* @return {int}
*/
- $after = apply_filters( 'mc_future_search_results', 15 );
+ $after = apply_filters( 'mc_future_search_results', 15 );
+ $event_array = array();
if ( is_array( $search ) ) {
// If from & to are set, we need to use a date-based event query.
$from = mc_checkdate( $search['from'] );
@@ -832,7 +853,7 @@
$select_author = '';
$select_host = '';
/**
- * Set primary sort for getting today's events. Default 'occur_begin'.
+ * Set primary sort for getting happening events. Default 'occur_begin'.
*
* @hook mc_primary_sort
*
@@ -843,7 +864,7 @@
*/
$primary_sort = apply_filters( 'mc_primary_sort', 'occur_begin', 'my_calendar_events_now' );
/**
- * Set secondary sort for getting today's events. Default 'event_title ASC'.
+ * Set secondary sort for getting happening events. Default 'event_title ASC'.
*
* @hook mc_secondary_sort
*
@@ -1385,19 +1406,22 @@
// Translators: Number of total events.
$arc_text = sprintf( __( 'Archived (%d)', 'my-calendar' ), $counts['archive'] );
- $can_text = '';
+ $can_text = '';
+ $can_attributes = '';
if ( isset( $counts['cancel'] ) && 0 < (int) $counts['cancel'] ) {
$can_attributes = ( isset( $_GET['limit'] ) && 'cancelled' === $_GET['limit'] ) ? ' aria-current="true"' : '';
// Translators: Number of total events.
$can_text = sprintf( __( 'Cancelled (%d)', 'my-calendar' ), $counts['cancel'] );
}
- $pri_text = '';
+ $pri_text = '';
+ $pri_attributes = '';
if ( isset( $counts['private'] ) && 0 < (int) $counts['private'] ) {
$pri_attributes = ( isset( $_GET['limit'] ) && 'private' === $_GET['limit'] ) ? ' aria-current="true"' : '';
// Translators: Number of total events.
$pri_text = sprintf( __( 'Private (%d)', 'my-calendar' ), $counts['private'] );
}
- $per_text = '';
+ $per_text = '';
+ $per_attributes = '';
if ( isset( $counts['personal'] ) && 0 < (int) $counts['personal'] ) {
$per_attributes = ( isset( $_GET['limit'] ) && 'personal' === $_GET['limit'] ) ? ' aria-current="true"' : '';
// Translators: Number of total events.
--- a/my-calendar/my-calendar-help.php
+++ b/my-calendar/my-calendar-help.php
@@ -384,7 +384,7 @@
*/
function mc_display_icons() {
$is_custom = mc_is_custom_icon();
- $output = ( WP_DEBUG ) ? false : get_transient( 'mc_svg_list' );
+ $output = get_transient( 'mc_svg_list' );
if ( ! $output ) {
if ( $is_custom ) {
$dir = plugin_dir_path( __FILE__ );
--- a/my-calendar/my-calendar-limits.php
+++ b/my-calendar/my-calendar-limits.php
@@ -178,6 +178,7 @@
} else {
$authors = explode( ',', $author );
}
+ $add = false;
foreach ( $authors as $index => $key ) {
$key = trim( $key );
if ( is_numeric( $key ) ) {
@@ -189,8 +190,9 @@
$author = get_user_by( 'login', $key ); // Get author by username.
$add = ( $author ) ? $author->ID : false;
}
-
- $return[] = ( $add ) ?? $add;
+ if ( $add ) {
+ $return[] = $add;
+ }
}
} else {
if ( is_numeric( $author ) ) {
--- a/my-calendar/my-calendar-locations.php
+++ b/my-calendar/my-calendar-locations.php
@@ -350,7 +350,7 @@
* @param {array} $add Array of location parameters to add.
* @param {array} $post POST array.
*
- * @return Before priority 10, returns the location ID; after priority 10 returns the location post ID. Sorry.
+ * @return int Before priority 10, returns the location ID; after priority 10 returns the location post ID. Sorry.
*/
$results = apply_filters( 'mc_save_location', $insert_id, $add, $post );
@@ -367,7 +367,12 @@
*/
function mc_count_locations() {
global $wpdb;
+ $count = get_transient( 'mc_location_count' );
+ if ( $count ) {
+ return $count;
+ }
$count = $wpdb->get_var( 'SELECT COUNT(*) FROM ' . my_calendar_locations_table() ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
+ set_transient( 'mc_location_count', $count, DAY_IN_SECONDS );
return $count;
}
@@ -490,6 +495,7 @@
$post = map_deep( $_POST, 'wp_kses_post' );
if ( isset( $post['mode'] ) && 'add' === $post['mode'] ) {
+ delete_transient( 'mc_location_count' );
$results = mc_insert_location( $post );
$location_id = $results['location_id'];
@@ -514,6 +520,7 @@
mc_update_option( 'default_location', (int) $location_id );
}
} elseif ( isset( $_GET['location_id'] ) && 'delete' === $_GET['mode'] ) {
+ delete_transient( 'mc_location_count' );
$loc = absint( $_GET['location_id'] );
echo wp_kses_post( mc_delete_location( $loc ) );
} elseif ( isset( $_GET['mode'] ) && isset( $_GET['location_id'] ) && 'edit' === $_GET['mode'] && ! isset( $post['mode'] ) ) {
@@ -706,6 +713,10 @@
* @return object|false location if found
*/
function mc_get_location( $location_id, $update_location = true ) {
+ static $location_cache = array();
+ if ( isset( $location_cache[ $location_id ] ) ) {
+ return $location_cache[ $location_id ];
+ }
if ( ! is_admin() ) {
$location = get_transient( 'mc_location_' . $location_id );
if ( $location ) {
@@ -750,6 +761,7 @@
if ( ! is_admin() ) {
set_transient( 'mc_location_' . $location_id, $location, WEEK_IN_SECONDS );
}
+ $location_cache[ $location_id ] = $location;
return $location;
}
--- a/my-calendar/my-calendar-output.php
+++ b/my-calendar/my-calendar-output.php
@@ -331,6 +331,10 @@
* @return bool
*/
function mc_legacy_templates_enabled() {
+ static $result = null;
+ if ( null !== $result ) {
+ return $result;
+ }
$enabled = mc_get_option( 'disable_legacy_templates' );
$legacy = ( 'true' === $enabled ) ? false : true;
/**
@@ -347,6 +351,7 @@
if ( version_compare( $GLOBALS['wp_version'], '5.5', '<' ) ) {
$enabled = true;
}
+ $result = $enabled;
return $enabled;
}
--- a/my-calendar/my-calendar-settings.php
+++ b/my-calendar/my-calendar-settings.php
@@ -22,12 +22,16 @@
* @return mixed A boolean false return means the setting doesn't exist.
*/
function mc_get_option( $key, $fallback = '' ) {
- $options = get_option( 'my_calendar_options', mc_default_options() );
- if ( ! is_array( $options ) ) {
- $options = mc_default_options();
+ static $options = null;
+ static $default = null;
+ if ( is_admin() || null === $options ) {
+ $options = get_option( 'my_calendar_options', mc_default_options() );
+ if ( ! is_array( $options ) ) {
+ $options = mc_default_options();
+ }
+ $default = mc_default_options();
+ $options = array_merge( $default, $options );
}
- $default = mc_default_options();
- $options = array_merge( $default, $options );
$new_key = str_replace( 'mc_', '', $key );
$value = isset( $options[ $new_key ] ) ? $options[ $new_key ] : false;
if ( ( ( 0 !== $value && ! $value ) || '' === $options[ $new_key ] ) && ( isset( $default[ $new_key ] ) && ! empty( $default[ $new_key ] ) ) ) {
--- a/my-calendar/my-calendar-templates.php
+++ b/my-calendar/my-calendar-templates.php
@@ -221,7 +221,8 @@
if ( ! is_object( $event ) ) {
return '';
}
- $event = mc_get_event_location( $event, $source );
+ $map_string = '';
+ $event = mc_get_event_location( $event, $source );
if ( $event ) {
$map_string = $event->location_street . ' ' . $event->location_street2 . ' ' . $event->location_city . ' ' . $event->location_state . ' ' . $event->location_postcode . ' ' . $event->location_country;
}
@@ -548,6 +549,10 @@
if ( ! is_object( $event ) ) {
return array();
}
+ static $tag_cache = array();
+ if ( isset( $tag_cache[ $event->occur_id ] ) ) {
+ return $tag_cache[ $event->occur_id ];
+ }
$location = mc_get_event_location( $event, 'event' );
/**
* Execute action before tags are created.
@@ -595,15 +600,16 @@
$terms = wp_get_object_terms( $event->event_post, 'mc-event-access' );
$term_list = implode( ', ', wp_list_pluck( $terms, 'name' ) );
$e['access'] = $term_list;
+ $is_all_day = mc_is_all_day( $event );
// Date & time fields.
$real_end_date = ( isset( $event->occur_end ) ) ? $event->occur_end : $event->event_end . ' ' . $event->event_endtime;
- $real_end_time = ( mc_is_all_day( $event ) ) ? strtotime( $real_end_date ) + 60 : strtotime( $real_end_date );
+ $real_end_time = ( $is_all_day ) ? strtotime( $real_end_date ) + 60 : strtotime( $real_end_date );
$real_begin_date = ( isset( $event->occur_begin ) ) ? $event->occur_begin : $event->event_begin . ' ' . $event->event_time;
- $dtstart = mc_format_timestamp( strtotime( $real_begin_date ), $context );
- $dtend = mc_format_timestamp( $real_end_time, $context );
- $recur_start = mc_format_timestamp( strtotime( $event->event_begin . ' ' . $event->event_time ), $context );
- $recur_end = mc_format_timestamp( strtotime( $event->event_end . ' ' . $event->event_endtime ), $context );
+ $dtstart = mc_format_timestamp( strtotime( $real_begin_date ) );
+ $dtend = mc_format_timestamp( $real_end_time );
+ $recur_start = mc_format_timestamp( strtotime( $event->event_begin . ' ' . $event->event_time ) );
+ $recur_end = mc_format_timestamp( strtotime( $event->event_end . ' ' . $event->event_endtime ) );
/**
* Start date format used in 'date_utc'. Default from My Calendar settings.
*
@@ -627,14 +633,14 @@
*/
$e['date_end_utc'] = date_i18n( apply_filters( 'mc_date_utc_format', $date_format, 'template_end_ts' ), $event->ts_occur_end );
$notime = esc_html( mc_notime_label( $event ) );
- $e['time'] = ( mc_is_all_day( $event ) ) ? $notime : mc_date( mc_time_format(), strtotime( $real_begin_date ), false );
- $e['time24'] = ( mc_is_all_day( $event ) ) ? $notime : mc_date( 'G:i', strtotime( $real_begin_date ), false );
+ $e['time'] = ( $is_all_day ) ? $notime : mc_date( mc_time_format(), strtotime( $real_begin_date ), false );
+ $e['time24'] = ( $is_all_day ) ? $notime : mc_date( 'G:i', strtotime( $real_begin_date ), false );
$endtime = ( '23:59:59' === $event->event_end ) ? '00:00:00' : mc_date( 'H:i:s', strtotime( $real_end_date ), false );
$e['endtime'] = ( $real_end_date === $real_begin_date || '1' === $event->event_hide_end || '23:59:59' === mc_date( 'H:i:s', strtotime( $real_end_date ), false ) ) ? '' : date_i18n( mc_time_format(), strtotime( $endtime ) );
$e['runtime'] = mc_runtime( $event->ts_occur_begin, $event->ts_occur_end, $event );
$e['duration'] = mc_duration( $event );
$e['dtstart'] = mc_date( 'Y-m-dTH:i:s', strtotime( $real_begin_date ), false ); // Date: hcal formatted.
- $hcal_dt_end = ( mc_is_all_day( $event ) ) ? strtotime( $real_end_date ) + 60 : strtotime( $real_end_date );
+ $hcal_dt_end = ( $is_all_day ) ? strtotime( $real_end_date ) + 60 : strtotime( $real_end_date );
$e['dtend'] = mc_date( 'Y-m-dTH:i:s', $hcal_dt_end, false ); // Date: hcal formatted end.
$e['userstart'] = '<time class="mc-user-time" data-type="datetime" data-label="' . __( 'Local time:', 'my-calendar' ) . '">' . mc_date( 'Y-m-dTH:i:sZ', $event->ts_occur_begin, false ) . '</time>';
$e['userend'] = '<time class="mc-user-time" data-type="datetime" data-label="' . __( 'Local time:', 'my-calendar' ) . '">' . mc_date( 'Y-m-dTH:i:sZ', $event->ts_occur_end, false ) . '</time>';
@@ -888,14 +894,14 @@
}
$strip_desc = mc_newline_replace( wp_strip_all_tags( $event->event_desc ) ) . ' ' . $e['link'];
- if ( mc_is_all_day( $event ) ) {
+ if ( $is_all_day ) {
$google_start = mc_date( 'Ymd', strtotime( $dtstart ), false );
$google_end = mc_date( 'Ymd', strtotime( $dtend ), false );
} else {
$google_start = $dtstart;
$google_end = $dtend;
}
- $allday = mc_is_all_day( $event ) ? 'true' : 'false';
+ $allday = $is_all_day ? 'true' : 'false';
$aria_described = ( $calendar_id ) ? " aria-describedby='mc_$event->occur_id-title-$calendar_id'" : '';
$e['gcal'] = mc_google_cal( $google_start, $google_end, $e_link, wp_unslash( $e['title'] ), $map_gcal, $strip_desc );
$e['gcal_link'] = "<a href='" . esc_url( $e['gcal'] ) . "' class='gcal external' rel='nofollow'" . $aria_described . "><span class='mc-icon' aria-hidden='true'></span>" . __( 'Google', 'my-calendar' ) . '</a>';
@@ -912,10 +918,10 @@
// ICAL.
$e['ical_desc'] = $strip_desc;
- $e['ical_start'] = ( mc_is_all_day( $event ) ) ? mc_date( 'Ymd', strtotime( $recur_start ), false ) : $recur_start;
- $e['ical_end'] = ( mc_is_all_day( $event ) ) ? mc_date( 'Ymd', strtotime( $recur_end ) + 60, false ) : $recur_end;
- $e['ical_date_start'] = ( mc_is_all_day( $event ) ) ? mc_date( 'Ymd', strtotime( $dtstart ), false ) : $dtstart;
- $e['ical_date_end'] = ( mc_is_all_day( $event ) ) ? mc_date( 'Ymd', strtotime( $dtend ) + 60, false ) : $dtend;
+ $e['ical_start'] = ( $is_all_day ) ? mc_date( 'Ymd', strtotime( $recur_start ), false ) : $recur_start;
+ $e['ical_end'] = ( $is_all_day ) ? mc_date( 'Ymd', strtotime( $recur_end ) + 60, false ) : $recur_end;
+ $e['ical_date_start'] = ( $is_all_day ) ? mc_date( 'Ymd', strtotime( $dtstart ), false ) : $dtstart;
+ $e['ical_date_end'] = ( $is_all_day ) ? mc_date( 'Ymd', strtotime( $dtend ) + 60, false ) : $dtend;
$e['ical_recur'] = mc_generate_rrule( $event );
$ical_link = mc_build_url(
array( 'vcal' => $event->occur_id ),
@@ -954,6 +960,7 @@
* @param {string} $context Current execution context.
*/
do_action( 'mc_tags_created', $event, $context );
+ $tag_cache[ $event->occur_id ] = $e;
return $e;
}
@@ -1163,10 +1170,7 @@
*/
function mc_date_badge( $date ) {
$time = strtotime( $date );
- $badge = '<time class="mc-date-badge" datetime="' . mc_date( 'Y-m-d', $time, false ) . '">
- <span class="month">' . date_i18n( 'M', mc_date( '', $time, false ) ) . '</span>
- <span class="day">' . mc_date( 'j', $time, false ) . '</span>
- </time>';
+ $badge = '<time class="mc-date-badge" datetime="' . mc_date( 'Y-m-d', $time, false ) . '"><span class="month">' . date_i18n( 'M', mc_date( '', $time, false ) ) . '</span><span class="day">' . mc_date( 'j', $time, false ) . '</span></time>';
/**
* Filter the date badge HTML.
*
@@ -1687,16 +1691,17 @@
} else {
$use = $string1;
}
- $use = wp_strip_all_tags( $use );
- $length = strlen( $use );
- $start = 0;
+ $use = wp_strip_all_tags( $use );
+ $length = strlen( $use );
+ $start = 0;
+ $positions = array();
if ( $length > 160 ) {
foreach ( $terms as $t ) {
$positions[] = stripos( $use, $t );
}
// Use the first term referenced for positioning.
sort( $positions );
- $position = $positions[0];
+ $position = $positions[0] ?? false;
// Search term not found.
if ( false === $position ) {
return substr( $use, 0, 160 );
--- a/my-calendar/my-calendar.php
+++ b/my-calendar/my-calendar.php
@@ -16,7 +16,7 @@
* Text Domain: my-calendar
* License: GPL-2.0+
* License URI: http://www.gnu.org/license/gpl-2.0.txt
- * Version: 3.7.9
+ * Version: 3.7.10
*/
/*
@@ -53,7 +53,7 @@
if ( ! $version ) {
return get_option( 'mc_version', '' );
}
- return '3.7.9';
+ return '3.7.10';
}
define( 'MC_DEBUG', false );