<?php
/*
Plugin Name: ICS Calendar Pro
Plugin URI: https://icscalendar.com
Description: Includes all features of the free ICS Calendar plugin, plus several additional calendar views, the easy-to-use Calendar Builder, ICS Events for creating and managing events directly in WordPress, extensive customization tools, and the Illustrations Library.
Version: 6.1.9.3
Requires at least: 5.3
Requires PHP: 7.4
Author: Room 34 Creative Services, LLC
Author URI: https://room34.com
License: Copyright 2026 Room 34 Creative Services, LLC. All rights reserved.
Text Domain: ics-calendar-pro
Domain Path: /i18n/languages/
*/

/*
  Copyright 2026 Room 34 Creative Services, LLC. All rights reserved.
  
  NOTE: ICS CALENDAR PRO IS **NOT** OPEN SOURCE.
    
  This program (ICS Calendar Pro) is paid commercial software. It MAY NOT be redistributed
  or modified, without the express written permission of Room 34 Creative Services, LLC.
  
  This program contains both free and commercial software made by other developers, which
  is included in compliance with the terms of the respective owners. Please see
  documentation in each program's subfolder inside the *vendors* folder for their terms.

	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.

	NOTE: The ICS Calendar and ICS Calendar Pro names, logos, and related branding assets
	are trademarks of Room 34 Creative Services, LLC and may not be used without permission.
	They are distributed with this software for the purpose of identification only. Reuse or
	redistribution of these assets is hereby prohibited.
*/


// Don't load directly
if (!defined('ABSPATH')) { exit; }


if (!class_exists('R34ICSPro')) {
		
	// Plugin constants
	// @todo These constants are only used by deprecated "Grid" view; remove when appropriate
	define('R34ICSPRO_ENTIRELY_IN_RANGE', 1);
	define('R34ICSPRO_ENTIRELY_OUT_OF_RANGE', 0);
	define('R34ICSPRO_STARTS_OUT_OF_RANGE', -1);
	define('R34ICSPRO_ENDS_OUT_OF_RANGE', -2);
	define('R34ICSPRO_STARTS_AND_ENDS_OUT_OF_RANGE', -3);
	
	
	// Load required files (must come before 'plugins_loaded')
	require_once(plugin_dir_path(__FILE__) . 'functions.php');
	
	
	// Load the embedded version of ICS Calendar (free) if it's not already loaded (priority = 1)
	function r34icspro_plugins_loaded_1() {
		global $r34ics_embedded;
		$r34ics_embedded = false;
		include_once(ABSPATH . 'wp-admin/includes/plugin.php');
		if (!is_plugin_active('ics-calendar/ics-calendar.php')) {
			$r34ics_embedded = true;
			require_once(plugin_dir_path(__FILE__) . 'vendors/ics-calendar/ics-calendar.php');
		}
	}
	add_action('plugins_loaded', 'r34icspro_plugins_loaded_1', 1);

	
	// Initialize plugin (priority = 11)
	function r34icspro_plugins_loaded_11() {
	
		// Load and instantiate main plugin class
		require_once(plugin_dir_path(__FILE__) . 'classes/class-r34icspro.php');
		global $R34ICSPro;
		$R34ICSPro = new R34ICSPro();
		
		// Load and instantiate CSS class
		// Replaced use of the WP Customizer in version 6.0
		require_once(plugin_dir_path(__FILE__) . 'classes/class-r34icspro-css.php');
		global $R34ICSProCSS;
		$R34ICSProCSS = new R34ICSProCSS();
		
		// Load and instantiate ICS Event CPT class, if option is set
		if (get_option('r34icspro_enable_event_cpt')) {
			require_once(plugin_dir_path(__FILE__) . 'classes/class-r34icspro-event.php');
			if (class_exists('R34ICSProEvent')) {
				global $R34ICSProEvent;
				$R34ICSProEvent = new R34ICSProEvent();
			}
		}
		
		// Load and instantiate license class (admin only)
		/**
		 * This loads regardless of whether or not the R34ICS and R34ICSPro classes
		 * have been loaded because without it, Multisite installations can only check
		 * for updates if ICS Calendar (free) is network activated.
		 */
		if ((is_admin() && !r34icspro_ltwc()) || wp_doing_cron()) {
			require_once(plugin_dir_path(__FILE__) . 'classes/class-r34icspro-license.php');
			global $R34ICSProLicense;
			$R34ICSProLicense = new R34ICSProLicense();
		}
	
		// Load and register widget class
		require_once(plugin_dir_path(__FILE__) . 'classes/class-r34icspro-widget.php');
		add_action('widgets_init', 'r34icspro_widgets_init', 10, 0);
		function r34icspro_widgets_init() {
			return register_widget("R34ICSProWidget");
		}
		
	}
	add_action('plugins_loaded', 'r34icspro_plugins_loaded_11', 11);
	
	
	// Force loading of embedded translation files
	function r34icspro_load_textdomain_mofile($file='', $domain='') {
		if ($domain == 'ics-calendar-pro') {
			// Determine the plugin locale with fallback generic language files
			$locales = r34icspro_i18n_locales();
			$locale = determine_locale();
			if (!in_array($locale, $locales)) { $locale = substr($locale, 0, 2); }
			$file = plugin_dir_path(__FILE__) . 'i18n/languages/' . $domain . '-' . $locale . '.l10n.php';
			if (!file_exists($file)) {
				$file = plugin_dir_path(__FILE__) . 'i18n/languages/' . $domain . '-' . $locale . '.mo';
			}
		}
		return $file;
	}
	add_filter('load_textdomain_mofile', 'r34icspro_load_textdomain_mofile', 10, 2);

	
	// Force loading of script translations for Block Editor
	function r34icspro_load_script_translation_file($file, $handle, $domain) {
		if ($domain == 'ics-calendar-pro') {
			// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
			$locale = apply_filters('plugin_locale', determine_locale(), $domain);
			// Note: If new blocks or other script translations are added, the following will need to be repeated for each file
			$hash = md5('blocks/shortcode/block.src.js');
			$file = plugin_dir_path(__FILE__) . 'i18n/languages/' . $domain . '-' . $locale . '-' . $hash . '.json';
		}
		return $file;
	}
	add_filter('load_script_translation_file', 'r34icspro_load_script_translation_file', 10, 3);
	
	
	// Force loading of vendor translation files
	function r34icspro_vendor_load_plugin_textdomain() {
		// phpcs:ignore PluginCheck.CodeAnalysis.DiscouragedFunctions.load_plugin_textdomainFound
		load_plugin_textdomain('ics-calendar', false, 'ics-calendar-pro/vendors/ics-calendar/i18n/languages/');
		/* if (function_exists('acf_load_textdomain')) { acf_load_textdomain(); } */ // Doesn't work
	}
	add_action('init', 'r34icspro_vendor_load_plugin_textdomain', 10);
	
	
	// Install/upgrade (must be loaded as part of admin for is_plugin_active(), but only needs to run there anyway
	function r34icspro_admin_init() {
		global $R34ICSPro;
		if (isset($R34ICSPro) && get_option('r34icspro_version') != @$R34ICSPro->version) {
			r34icspro_install();
		}
		// Install mu-plugins file to prevent free ACF/SCF from loading on ICS Calendar Pro editing screens
		if ((is_plugin_active('advanced-custom-fields/acf.php') ||
				is_plugin_active('secure-custom-fields/secure-custom-fields.php')) &&
				!file_exists(WPMU_PLUGIN_DIR . '/r34icspro-no-acf.php'))
		{
			r34icspro_mu_plugins_install();
		}
	}
	add_action('admin_init', 'r34icspro_admin_init');
	
	
	// Plugin installation
	// See: https://codex.wordpress.org/Creating_Tables_with_Plugins
	function r34icspro_install() {
		global $R34ICSPro;
	
		// Remember previous version
		$previous_version = get_option('r34icspro_version', 0);
		update_option('r34icspro_previous_version', $previous_version, false);
		update_option('r34icspro_last_update', wp_date('r'), false);
		
		// Update version and locale
		if (isset($R34ICSPro->version)) {
			update_option('r34icspro_version', $R34ICSPro->version);
			update_option('r34icspro_locale', determine_locale());
		}
	
		// Set unique "instance" value for license management
		if (!r34icspro_check_instance()) {
			update_option('r34icspro_instance', r34icspro_generate_instance(), false);
		}
		
		// Force mu-plugins installation if ACF (free) or SCF is present
		// Note: We run this on every activation to pick up any new updates to this file!
		if (is_plugin_active('advanced-custom-fields/acf.php') ||
				is_plugin_active('secure-custom-fields/secure-custom-fields.php'))
		{
			r34icspro_mu_plugins_install(true);
		}
		
		// Resolve Loco Translate conflict by copying general languages file to locale files (symlink if possible)
		if (is_plugin_active('loco-translate/loco.php')) {
			r34icspro_i18n_symlinks();
		}
			
		// New installation; write non-empty defaults
		// Note: function_exists() works around a fatal error on activation when ICS Calendar < v.12 is active
		if (empty($previous_version) && function_exists('r34ics_reset_non_empty_defaults')) {
			r34ics_reset_non_empty_defaults();
		}
		
		// Purge saved locale list
		delete_option('r34icspro_i18n_locales');
	
		// Purge calendar transients
		if (function_exists('r34ics_purge_calendar_transients')) {
			r34ics_purge_calendar_transients();
		}
		
		// Run deprecated feature check
		if (method_exists('R34ICSPro', 'deprecated_feature_check')) {
			$R34ICSPro->deprecated_feature_check(array('no_transient' => true));
		}
		
		// Flush rewrite rules
		flush_rewrite_rules();
	
		// Set options for first run redirect (runs on admin_init hook, below)
		//update_option('r34ics_admin_first_run', true, false); // Reserved for future use
		//update_option('r34icspro_admin_first_run', true, false); // Reserved for future use
		update_option('r34icspro_activation_redirect', true, false);
	}
	register_activation_hook(__FILE__, 'r34icspro_install');
	
	// Redirect to Getting Started page with first run message
	add_action('admin_init', function() {
		// We check that we're not doing AJAX to fix an issue where the admin page might appear instead of the calendar for logged-in admins
		if (is_admin() && !wp_doing_ajax() && get_option('r34icspro_activation_redirect')) {
			update_option('r34icspro_activation_redirect', false, false); // DO NOT REMOVE THIS LINE! You'll have to manually delete the plugin to stop the redirect loops
			// Version-specific redirects
			$previous_version = get_option('r34icspro_previous_version', 0);
			if (empty($previous_version) || version_compare($previous_version, '6.1', '<')) {
				wp_safe_redirect(admin_url('edit.php?post_type=r34icspro_calendar&page=ics-calendar-pro-settings#appearance'));
			}
			else {
				wp_safe_redirect(admin_url('edit.php?post_type=r34icspro_calendar&page=ics-calendar-pro-settings#getting-started'));
			}
			exit;
		}
	}, PHP_INT_MAX - 1);
	
	
	// mu-plugins install
	function r34icspro_mu_plugins_install($overwrite=false) {
		// Note: This should run on activation whether or not the file already exists, in case it's been changed
		if (is_plugin_active('advanced-custom-fields/acf.php') ||
				is_plugin_active('secure-custom-fields/secure-custom-fields.php'))
		{
			// Add setting to reactivate ACF if we're deactivated in the future
			update_option('r34icspro_reactivate_acf_on_mu_plugins_uninstall', true, false);
			// Create mu-plugins directory
			if (!is_dir(WPMU_PLUGIN_DIR)) {
				// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_mkdir
				mkdir(WPMU_PLUGIN_DIR);
			}
			// Copy our file into mu-plugins
			if	(
						(!empty($overwrite) || !file_exists(WPMU_PLUGIN_DIR . '/r34icspro-no-acf.php')) &&
						file_exists(plugin_dir_path(__FILE__) . 'r34icspro-no-acf.php')
					)
			{
				copy(plugin_dir_path(__FILE__) . 'r34icspro-no-acf.php', WPMU_PLUGIN_DIR . '/r34icspro-no-acf.php');
			}
		}
	}
	register_activation_hook(__FILE__, 'r34icspro_mu_plugins_install');
	
	
	// mu-plugins uninstall
	function r34icspro_mu_plugins_uninstall() {
		if (file_exists(WPMU_PLUGIN_DIR . '/r34icspro-no-acf.php')) {
			wp_delete_file(WPMU_PLUGIN_DIR . '/r34icspro-no-acf.php');
		}
	}
	register_deactivation_hook(__FILE__, 'r34icspro_mu_plugins_uninstall');
	
	
	// WP-Cron jobs
	function r34icspro_wp_cron_activation() {
		if (!wp_next_scheduled('r34icspro_wp_cron_hourly')) {
			wp_schedule_event(time(), 'hourly', 'r34icspro_wp_cron_hourly');
		}
	}
	register_activation_hook(__FILE__, 'r34icspro_wp_cron_activation');
	
	
	function r34icspro_wp_cron_deactivation() {
		if ($next_scheduled = wp_next_scheduled('r34icspro_wp_cron_hourly')) {
			wp_unschedule_event($next_scheduled, 'r34icspro_wp_cron_hourly');
		}
		wp_clear_scheduled_hook('r34icspro_wp_cron_hourly');
	}
	register_deactivation_hook(__FILE__, 'r34icspro_wp_cron_deactivation');
	
	
	function r34icspro_wp_cron_hourly() {
		return; // @todo Pre-caching temporarily removed in v. 6.0.0 pending needed performance improvements
		// Pre-cache feeds
		global $R34ICSPro;
		$R34ICSPro->precache_feeds();
	}
	add_action('r34icspro_wp_cron_hourly', 'r34icspro_wp_cron_hourly');
	
	
	// Development only -- used with Plugin Check (PCP) plugin
	add_filter('wp_plugin_check_ignore_directories', function ($directories) {
			$directories[] = 'i18n';
			$directories[] = 'vendors';
			return $directories;
	});
	
}
