<?php
/**
* My Calendar Pro, Premium Accessible Events Manager for WordPress
*
* @package MyCalendarPro
* @author Joe Dolson
* @copyright 2012-2025 Joe Dolson
* @license GPL-2.0+
*
* @wordpress-plugin
* Plugin Name: My Calendar Pro
* Plugin URI: https://www.joedolson.com/my-calendar-pro/
* Description: Expands the capabilities of My Calendar to add premium features.
* Author: Joe Dolson
* Author URI: https://www.joedolson.com
* Text Domain: my-calendar-pro
* License: GPL-2.0+
* License URI: http://www.gnu.org/license/gpl-2.0.txt
* Domain Path: /lang
* Version: 3.2.1
* Requires Plugins: my-calendar
*/
/*
Copyright 2012-2025 Joe Dolson (email : joe@joedolson.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $mcs_version, $wpdb;
$mcs_version = '3.2.1';
// The URL of the site with EDD installed.
define( 'EDD_MCP_STORE_URL', 'https://www.joedolson.com' );
if ( ! class_exists( 'EDD_SL_Plugin_Updater' ) ) {
// load our custom updater if it doesn't already exist.
require __DIR__ . '/updates/EDD_SL_Plugin_Updater.php';
}
// retrieve our license key from the DB.
$license_key = ( ! defined( 'MCS_LICENSE_KEY' ) ) ? trim( get_option( 'mcs_license_key' ) ) : MCS_LICENSE_KEY;
// setup the updater.
$edd_updater = new EDD_SL_Plugin_Updater(
EDD_MCP_STORE_URL,
__FILE__,
array(
'version' => $mcs_version, // current version number.
'license' => $license_key, // license key (used get_option above to retrieve from DB).
'item_id' => 5734, // ID of this plugin.
'author' => 'Joe Dolson', // author of this plugin.
'url' => home_url(),
)
);
// Define the tables used in My Calendar.
define( 'MY_CALENDAR_PAYMENTS_TABLE', $wpdb->prefix . 'my_calendar_payments' );
if ( function_exists( 'is_multisite' ) && is_multisite() ) {
// Define the tables used in My Calendar.
define( 'MY_CALENDAR_GLOBAL_PAYMENTS_TABLE', $wpdb->base_prefix . 'my_calendar_payments' );
}
/**
* Checks for existence; used in My Calendar to check for support.
*/
function mcs_submissions() {
return true;
}
add_action( 'init', 'mcs_load_textdomain' );
/**
* Load internationalization.
*/
function mcs_load_textdomain() {
// Shipped translations removed @v3.3.0.
load_plugin_textdomain( 'my-calendar-pro', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' );
}
require __DIR__ . '/inc/utilities.php';
require __DIR__ . '/my-calendar-payment-functions.php';
require __DIR__ . '/my-calendar-generator.php';
require __DIR__ . '/my-calendar-geolocation.php';
require __DIR__ . '/my-calendar-manage.php';
require __DIR__ . '/my-calendar-submit.php';
require __DIR__ . '/my-calendar-submit-ajax.php';
require __DIR__ . '/my-calendar-submit-payments.php';
require __DIR__ . '/my-calendar-notifications.php';
require __DIR__ . '/my-calendar-custom-fields.php';
require __DIR__ . '/my-calendar-default-fields.php';
require __DIR__ . '/classes/class-mc-submissions-widget.php';
require __DIR__ . '/my-calendar-submit-settings.php';
require __DIR__ . '/my-calendar-event-posts.php';
require __DIR__ . '/my-calendar-post-events.php';
require __DIR__ . '/my-calendar-advanced-search.php';
require __DIR__ . '/my-calendar-responsive-mode.php';
require __DIR__ . '/my-calendar-import.php';
require __DIR__ . '/my-calendar-api.php';
require __DIR__ . '/my-calendar-multilingual.php';
require __DIR__ . '/my-calendar-private-content.php';
require __DIR__ . '/my-calendar-hosts.php';
require __DIR__ . '/my-calendar-miscellaneous.php';
require __DIR__ . '/my-calendar-license.php';
if ( mcs_is_enabled( 'client-api' ) ) {
require __DIR__ . '/my-calendar-api-client/post.php';
require __DIR__ . '/my-calendar-api-client/settings.php';
require __DIR__ . '/my-calendar-api-client/ui-admin.php';
}
if ( mcs_is_enabled( 'server-api' ) ) {
require __DIR__ . '/my-calendar-api-server/api.php';
require __DIR__ . '/my-calendar-api-server/settings.php';
require __DIR__ . '/my-calendar-api-server/ui-public.php';
}
register_activation_hook( __FILE__, 'mcs_activation_hook' );
/**
* Execute on activation. Check requirements.
*/
function mcs_activation_hook() {
$required_php_version = '7.4.0';
if ( version_compare( PHP_VERSION, $required_php_version, '<' ) ) {
$plugin_data = get_plugin_data( __FILE__, false );
// Translators: Plugin name, PHP version required, your PHP version.
$message = sprintf( __( '%1$s requires PHP version %2$s or higher. Your current PHP version is %3$s', 'my-calendar-pro' ), $plugin_data['Name'], $required_php_version, phpversion() );
wp_admin_notice(
$message,
array(
'type' => 'error',
)
);
deactivate_plugins( plugin_basename( __FILE__ ) );
exit;
}
mcs_check();
}
add_action( 'admin_notices', 'mcs_license_notice' );
/**
* Display license notice if needs current.
*
* @return string
*/
function mcs_license_notice() {
global $current_screen;
if ( stripos( $current_screen->id, 'my-calendar' ) ) {
// only check license on main site in network environments.
if ( is_main_site() ) {
if ( 'true' === get_option( 'mcs_license_key_valid' ) || 'active' === get_option( 'mcs_license_key_valid' ) || 'valid' === get_option( 'mcs_license_key_valid' ) ) {
return;
}
// Translators: License input URL.
$message = sprintf( __( "You must <a href='%s'>enter your license key</a> to get support and updates for My Calendar Pro.", 'my-calendar-pro' ), admin_url( 'admin.php?page=my-calendar-submissions#mcs_license_tab' ) );
if ( ! current_user_can( 'manage_options' ) ) {
return;
} else {
wp_admin_notice(
$message,
array(
'type' => 'error',
)
);
}
}
}
}
add_action( 'init', 'mcs_register_actions', 9 );
/**
* Register actions for My Calendar Pro.
*/
function mcs_register_actions() {
add_action( 'wp_loaded', 'mcs_verify_receipt' );
add_action( 'parse_request', 'mcs_receive_ipn' );
add_action( 'parse_request', 'mcs_show_receipt' );
add_action( 'mcs_complete_submission', 'mcs_notify_admin', 10, 4 );
add_action( 'mcs_complete_submission', 'mcs_notify_submitter', 10, 4 );
add_action( 'mc_transition_event', 'mcs_notify_submitter_transition', 10, 5 );
add_filter( 'mc_generator_tabs', 'mcs_form_builder_tab', 10, 1 );
add_filter( 'mc_generator_tab_content', 'mcs_form_builder_tab_content', 10, 2 );
}
add_action( 'widgets_init', 'mcs_register_widgets' );
/**
* Register widgets for My CalendarPro.
*/
function mcs_register_widgets() {
register_widget( 'My_Calendar_Advanced_Search' );
register_widget( 'Mc_Submissions_Widget' );
}
/**
* Check status of plug-in and install if necessary.
*/
function mcs_check() {
global $wpdb, $mcs_version;
$current_version = get_option( 'mcs_version' );
// If current version matches, don't bother running this.
if ( $current_version === $mcs_version ) {
return true;
}
// Run the My Calendar DB updates first.
if ( function_exists( 'mc_upgrade_db' ) ) {
mc_upgrade_db();
}
// Lets see if this is first run and create a table if it is!
// Assume this is not a new install until we prove otherwise.
$new_install = false;
$my_calendar_exists = false;
$upgrade_path = array();
$db_engine = defined( 'DB_ENGINE' ) && 'sqlite' === DB_ENGINE ? 'sqlite' : 'mysql';
if ( 'sqlite' !== $db_engine ) {
$tables = $wpdb->get_results( 'show tables;' );
foreach ( $tables as $table ) {
foreach ( $table as $value ) {
if ( MY_CALENDAR_PAYMENTS_TABLE === $value ) {
$my_calendar_exists = true;
}
}
}
}
if ( false === $my_calendar_exists ) {
$new_install = true;
}
// having determined upgrade path, assign new version number.
update_option( 'mcs_version', $mcs_version );
// Now we've determined what the current install is or isn't.
if ( true === $new_install ) {
mcs_default_settings();
} else {
if ( version_compare( $current_version, '1.5.8', '<' ) ) {
$upgrade_path[] = '1.5.8';
}
if ( version_compare( $current_version, '2.0.0', '<' ) ) {
$upgrade_path[] = '2.0.0';
}
if ( version_compare( $current_version, '3.0.0', '<' ) ) {
$upgrade_path[] = '3.0.0';
}
}
// switch for different upgrade paths.
foreach ( $upgrade_path as $upgrade ) {
switch ( $upgrade ) {
case '3.0.0':
add_option( 'mcs_private_content', 'true' );
mcs_update_database(); // Adds two new columns to payments table.
case '2.0.0':
delete_option( 'mcs_options' );
delete_option( 'mcs_quantity' );
break;
case '1.5.8':
delete_option( 'mcs-parsed-files' );
delete_option( 'mcs-number-of-files' );
delete_option( 'mcs-delimiter' );
delete_option( 'mcs_parsing_now_0' );
delete_option( 'mcs_parsing_now_1' );
delete_option( 'mcs_parsing_now_2' );
delete_option( 'mcs_parsing_now_3' );
delete_option( 'mcs_parsing_now_4' );
delete_option( 'mcs_parsing_now_5' );
delete_option( 'mcs_parsing_now_6' );
break;
}
}
}
/**
* Generate submit page on installation.
*
* @param string $slug Proposed page slug.
*
* @return id postID
*/
function mcs_generate_submit_page( $slug ) {
$current_user = wp_get_current_user();
if ( ! get_page_by_path( $slug ) ) {
$page = array(
'post_title' => __( 'Submit Events', 'my-calendar-pro' ),
'post_status' => 'publish',
'post_type' => 'page',
'post_author' => $current_user->ID,
'ping_status' => 'closed',
'post_content' => '<!-- wp:shortcode -->[submit_event]<!-- /wp:shortcode -->',
);
$post_ID = wp_insert_post( $page );
$post_slug = wp_unique_post_slug( $slug, $post_ID, 'publish', 'page', 0 );
wp_update_post(
array(
'ID' => $post_ID,
'post_name' => $post_slug,
)
);
} else {
$post = get_page_by_path( $slug );
$post_ID = $post->ID;
}
update_option( 'mcs_submit_id', $post_ID );
return $post_ID;
}
/**
* Generate event edit page on installation.
*
* @param string $slug Proposed page slug.
*
* @return id postID
*/
function mcs_generate_edit_page( $slug ) {
$current_user = wp_get_current_user();
if ( ! get_page_by_path( $slug ) ) {
$page = array(
'post_title' => __( 'Edit Events', 'my-calendar-pro' ),
'post_status' => 'publish',
'post_type' => 'page',
'post_author' => $current_user->ID,
'ping_status' => 'closed',
'post_content' => '[submitted_events]',
);
$post_ID = wp_insert_post( $page );
$post_slug = wp_unique_post_slug( $slug, $post_ID, 'publish', 'page', 0 );
wp_update_post(
array(
'ID' => $post_ID,
'post_name' => $post_slug,
)
);
} else {
$post = get_page_by_path( $slug );
$post_ID = $post->ID;
}
update_option( 'mcs_edit_id', $post_ID );
return $post_ID;
}
/**
* Plugin default settings.
*
* @return void
*/
function mcs_default_settings() {
global $mcs_version;
update_option( 'mcs_criteria', '2' );
update_option( 'mcs_ajax', 'true' );
mcs_update_database();
mcs_generate_submit_page( 'submit-events' );
mcs_generate_edit_page( 'edit-events' );
mcs_generate_search_page( 'advanced-event-search' );
add_option( 'mcs_db_version', $mcs_version ); // sync db version to version.
}
/**
* Return default settings.
*/
function mcs_get_default_settings() {
$options = array(
'fields' => mcs_default_fields(),
'location_fields' => mcs_default_location_fields(),
'defaults' => array(
'mcs_response' => '
A new event has been submitted by {name}.
Title: {title}
Date & Time: {date}, {time}
Review this event: {edit_link}',
'mcs_confirmation' => '
Thanks for proposing a new event, {name}!
Title: {title}
Date & Time: {date}, {time}
This event must be approved by a site administrator.',
'mcs_edit_response' => '
An event has been edited by {name}.
Title: {title}
Date & Time: {date}, {time}
Review this event: {edit_link}',
'mcs_edit_confirmation' => '
Thanks for editing your event, {name}!
Title: {title}
Date & Time: {date}, {time}',
'mcs_subject' => 'New event on {blogname}',
'mcs_edit_subject' => 'Event on {blogname} has been edited',
'mcs_confirmation_subject' => 'Your event submission has been received.',
'mcs_edit_confirmation_subject' => 'Your event submission has been edited.',
'mcs_publication_subject' => 'Your event at {blogname} has been published.',
'mcs_publication' => 'Your submitted event {title} has been published.',
'mcs_payment_response' => '
A payment to create events has been submitted by {first_name} {last_name}.
New payment key: {key}
Paid: ${price} for {quantity} event/s',
'mcs_payment_confirmation' => '
Thanks for purchasing an event submission key for {blogname} a new event, {first_name}!
Your payment key: {key}. You paid ${price} for {quantity} event/s.
Your Receipt: {receipt}
You may use this key to submit your events.',
'mcs_payment_subject' => 'New event submission payment on {blogname}',
'mcs_payment_confirmation_subject' => 'Your event submission payment has been received.',
'mcs_payment_message' => 'Payment is required to submit an event! Submission costs <strong>{price} {currency}</strong>.',
'mcs_criteria' => 2,
'mcs_payments' => 'false',
'mcs_use_sandbox' => 'false',
'mcs_submission_fee' => '5.00',
'mcs_currency' => 'USD',
'mcs_check_conflicts' => 'false',
'mcs_upload_images' => 'false',
),
'widget_defaults' => array(
'title' => 'Submit an Event',
'categories' => 'true',
'category' => 1,
'locations' => 'choose',
'location' => '',
),
);
return $options;
}
/**
* These two functions are called from My Calendar via admin_head action
*/
function my_calendar_sub_js() {
global $mcs_version;
$admin_js = plugins_url( 'js/mcs-admin.min.js', __FILE__ );
if ( SCRIPT_DEBUG ) {
$mcs_version .= '-' . wp_rand( 10000, 100000 );
$admin_js = plugins_url( 'js/mcs-admin.js', __FILE__ );
}
if ( isset( $_GET['page'] ) && 'my-calendar-submissions' === $_GET['page'] ) {
wp_enqueue_script( 'mc.tabs' );
}
if ( isset( $_GET['page'] ) && ( 'my-calendar-shortcodes' === $_GET['page'] || 'my-calendar-submissions' === $_GET['page'] ) ) {
wp_enqueue_script( 'mcs.admin', $admin_js, array( 'jquery', 'wp-a11y' ), $mcs_version );
wp_localize_script(
'mcs.admin',
'mcs_fields',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'security' => wp_create_nonce( 'mcs-fields-action' ),
'action' => 'mcs_fields_action',
)
);
}
}
/**
* Enqueue styles for submissions and payments settings.
*/
function my_calendar_sub_styles() {
global $mcs_version;
if ( ! empty( $_GET['page'] ) ) {
$p = sanitize_text_field( $_GET['page'] );
if ( ( strpos( $p, 'my-calendar-submissions' ) !== false ) || 'my-calendar-payments' === $p || 'my-calendar-shortcodes' === $p ) {
wp_enqueue_style( 'mc-styles', plugins_url( 'my-calendar/css/mc-styles.css' ), array(), $mcs_version );
wp_enqueue_style( 'mcs-admin', plugins_url( 'css/mcs-admin.css', __FILE__ ), array(), $mcs_version );
}
}
$post_events = ( is_array( get_option( 'mcs_post_event_types' ) ) ) ? get_option( 'mcs_post_event_types' ) : array();
foreach ( $post_events as $post_type ) {
global $current_screen;
if ( 'post' === $current_screen->base && $current_screen->post_type === $post_type ) {
wp_enqueue_style( 'my-calendar-pro-style' );
}
}
}
/**
* Debug hook.
*
* @param Exception $e Exception.
*/
function mcs_log_error( $e ) {
/**
* Perform an action if an error is logged. Only executed in payment handling. No default behavior.
*
* @hook mcs_log_error
*
* @param {Exception} $e Exception.
*/
do_action( 'mcs_log_error', $e );
}
add_action( 'init', 'mcs_register_styles' );
/**
* Register styles for datepicker & submissions.
*/
function mcs_register_styles() {
global $mcs_version;
if ( SCRIPT_DEBUG && true === SCRIPT_DEBUG ) {
$mcs_version = $mcs_version . uniqid();
}
wp_register_style( 'my-calendar-pro-style', plugins_url( 'css/mcs-styles.css', __FILE__ ), array( 'dashicons' ), $mcs_version );
wp_register_style( 'my-calendar-responsive-base', apply_filters( 'mcs_responsive_base', plugins_url( 'css/mcs-responsive-base.css', __FILE__ ) ), array(), $mcs_version );
}
add_action( 'wp_enqueue_scripts', 'mcs_styles' );
/**
* Enqueue My Calendar Pro stylesheet.
*/
function mcs_styles() {
global $mcs_version;
if ( SCRIPT_DEBUG && true === SCRIPT_DEBUG ) {
$mcs_version = $mcs_version . uniqid();
}
wp_enqueue_style( 'my-calendar-pro-style' );
// If the current My Calendar version is above 3.5, these don't need to be enqueued.
$mc_version = mc_get_version();
if ( version_compare( $mc_version, '3.5.0', '<=' ) ) {
wp_enqueue_script( 'my-calendar-responsive', plugins_url( 'js/mcs-responsive.js', __FILE__ ), array( 'jquery' ), $mcs_version, true );
if ( 'true' !== get_option( 'mcs_responsive_mode' ) ) {
wp_enqueue_style( 'my-calendar-responsive-base' );
}
}
}
/**
* Update payment database
*/
function mcs_update_database() {
global $wpdb;
$payments = 'CREATE TABLE ' . my_calendar_payments_table() . ' (
`id` BIGINT( 20 ) NOT NULL AUTO_INCREMENT ,
`item_number` BIGINT( 20 ) NOT NULL ,
`event_id` BIGINT( 20 ) NOT NULL ,
`quantity` BIGINT( 20 ) NOT NULL ,
`total` BIGINT( 20 ) NOT NULL ,
`hash` VARCHAR( 255 ) NOT NULL ,
`txn_id` VARCHAR( 255 ) NOT NULL ,
`price` FLOAT( 10, 2 ) NOT NULL ,
`fee` FLOAT( 10, 2 ) NOT NULL ,
`status` VARCHAR( 255 ) NOT NULL ,
`transaction_date` DATETIME NOT NULL ,
`first_name` VARCHAR( 255 ) NOT NULL ,
`last_name` VARCHAR( 255 ) NOT NULL ,
`payer_email` VARCHAR( 255 ) NOT NULL ,
`gateway` VARCHAR( 255 ) NOT NULL ,
`metadata` TEXT NOT NULL ,
PRIMARY KEY (id)
) ' . $wpdb->get_charset_collate();
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta( $payments );
}