PluginProbe
Termin-Kalender / trunk
Termin-Kalender vtrunk
trunk 0.96.3 0.97.2 0.97.7 0.98 0.98.1 0.98.3 0.98.5 0.98.6 0.98.8 0.98.9 0.98.9.1 0.98.9.2 0.98.9.4 0.99.0 0.99.01 0.99.04 0.99.05 0.99.08 0.99.13 0.99.15 0.99.16 0.99.19 0.99.30 0.99.37 All 97 releases
termin-kalender / termin-kalender.php

termin-kalender.php in Termin-Kalender trunk, at termin-kalender.php

350 lines 20.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Termin-Kalender
4 * Plugin URI: https://termin-kalender.pro
5 * Description: Termin-Kalender is your easy monthly planner. This calendar app provides a clear, monthly overview to keep you organized.
6 * Version: 1.3.4
7 * Requires at least: 6.0
8 * Requires PHP: 8.0
9 * Author: beat.k
10 * License: GPL2+
11 * Text Domain: termin-kalender
12 * Domain Path: /languages/
13 *
14 */
15
16 defined('ABSPATH') || exit;
17
18 //------------------------------------------------
19 /*
20 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: https://www.gnu.org/licenses/.
21 Limitation of Liability
22 By using this software, you acknowledge and agree that the authors, developers, and copyright holders shall not be held liable for any damages, claims, or liabilities arising out of or in connection with the use of this software, including its integration into commercial products or applications. You assume all responsibility for ensuring compliance with applicable laws, regulations, and standards in such use cases.
23 */
24 //------------------------------------------------
25 class Termin_Kalender_Plugin
26 {
27 // Define the plugin constants
28 const TER_KAL_TK_VERSION = '1.3.4';
29 const TER_KAL_SHORTCODES = ['termin-kalender-calendar', 'my-termin-kalender', 'termin-kalender-simple-list', 'termin-kalender-pro-list', 'termin-kalender-fullpage', 'termin-kalender-pro-reservation', 'termin-kalender-pro-ical', 'termin-kalender-pro-todo', 'termin-kalender-calendar-editable', 'termin-kalender-pro-teammessage', 'ter_kal_editable_frontend'];
30 const TER_KAL_BLOCKS = ['termin-kalender/simplelist', 'termin-kalender/kalender-block', 'termin-kalender/list-pro', 'termin-kalender/reservation-pro', 'termin-kalender/ical-block', 'termin-kalender/todo-list', 'termin-kalender/post-meta-header'];
31 const LOCALE_MAP = [
32 'de' => 'de_DE',
33 'fr' => 'fr_FR',
34 'en' => 'en_US'
35 ];
36 // Define a static property for allowed admin page hook suffixes.
37 public static $ter_kal_admin_pages_hook_suffixes = [];
38 public static $plugin_url;
39 public static $plugin_dir_path;
40 public static $ajax_url;
41 protected $manager;
42 protected $block_list;
43 //-------------------------------------------------------------------------------------------------
44 public function __construct()
45 {
46 self::$ajax_url = admin_url('admin-ajax.php');
47 self::$plugin_url = plugin_dir_url(__FILE__);
48 self::$plugin_dir_path = plugin_dir_path(__FILE__);
49 // actions
50 add_action('init', [$this, 'load_textdomain']);
51 add_action('init', [$this, 'init_termin_kalender_update']);
52 add_action('admin_enqueue_scripts', [$this, 'ter_kal_enqueue_admin_assets']);
53 // filters
54 // require
55 require_once plugin_dir_path(__FILE__) . 'includes/dashicons.php';
56 require_once plugin_dir_path(__FILE__) . 'classes/class-termin-kalender-functions.php';
57 new Termin_Kalender_Functions();
58 require_once plugin_dir_path(__FILE__) . 'classes/class-termin-kalender-event-repository.php';
59 require_once plugin_dir_path(__FILE__) . 'classes/class-termin-kalender-rest-api.php';
60 new Termin_Kalender_REST_API();
61 require_once plugin_dir_path(__FILE__) . 'classes/class_termin_kalender_manager.php';
62 $this->manager = Termin_Kalender_Manager::get_instance();
63 require_once plugin_dir_path(__FILE__) . 'classes/class-termin-kalender-admin-page.php';
64 new Termin_Kalender_Admin_Page();
65 require_once plugin_dir_path(__FILE__) . 'classes/class-termin-kalender-page-overview.php';
66 require_once plugin_dir_path(__FILE__) . 'classes/class-termin-kalender-admin-menu.php';
67 Termin_Kalender_Admin_Menu::init();
68 require_once plugin_dir_path(__FILE__) . 'classes/class-termin-kalender-magic-pages.php';
69 new Termin_Kalender_Magic_Pages();
70 require_once plugin_dir_path(__FILE__) . 'includes/admin_page_initial_setup_rest_api.php';
71 require_once plugin_dir_path(__FILE__) . 'includes/admin_page_initial_setup.php'; // 14
72 //--------------------------------------------------------------------------------
73 require_once plugin_dir_path(__FILE__) . 'includes/admin_page_block_calendar.php'; // 16
74 require_once plugin_dir_path(__FILE__) . 'includes/admin_page_block_simple_list.php'; // 18
75 if (!defined('TERMIN_KALENDER_PRO_ON')) {
76 require_once plugin_dir_path(__FILE__) . 'includes/admin_page_PRO_info.php'; // 90
77 }
78 require_once plugin_dir_path(__FILE__) . 'classes/class-termin-kalender-block-list.php';
79 $this->block_list = Termin_Kalender_Block_List::get_instance();
80 require_once plugin_dir_path(__FILE__) . 'includes/plugin_rating_request.php';
81 }
82 //-------------------------------------------------------------------------------------------------
83 //-------------------------------------------------------------------------------------------------
84 //-------------------------------------------------------------------------------------------------
85 //-------------------------------------------------------------------------------------------------
86 //-------------------------------------------------------------------------------------------------
87 //-------------------------------------------------------------------------------------------------
88 public function load_textdomain()
89 {
90 // Engage JIT JS filter
91 add_filter('load_script_translation_file', [$this, 'map_script_translations'], 10, 3);
92
93 // Engage JIT PHP filters
94 // Covers lightning fast PHP .l10n.php loading introduced in WP 6.5
95 add_filter('load_translation_file', [$this, 'force_local_translation'], 10, 2);
96 // Fallback for WP 6.0 to 6.4 (since the baseline requirement is WP 6.0)
97 add_filter('load_textdomain_mofile', [$this, 'force_local_translation'], 10, 2);
98
99 // Trigger the standard WP process internally, the filters above will intercept it natively
100 /* NOTE FOR REPO REVIEWERS:
101 * We intentionally use load_plugin_textdomain() to bundle and serve local translation files
102 * (de_DE, en_US, fr_FR) directly with the plugin. This guarantees
103 * terminology consistency without relying entirely on external GlotPress community syncs.
104 */
105 // phpcs:ignore PluginCheck.CodeAnalysis.DiscouragedFunctions.load_plugin_textdomainFound
106 load_plugin_textdomain('termin-kalender', false, dirname(plugin_basename(__FILE__)) . '/languages/');
107 }
108 //-------------------------------------------------------------------------------------------------
109 public function force_local_translation($file, $domain)
110 {
111 if ('termin-kalender' !== $domain) {
112 return $file;
113 }
114
115 $locale = determine_locale();
116 $prefix = substr($locale, 0, 2);
117
118 // English: skip loading entirely to use original source texts
119 if ('en' === $prefix) {
120 return false;
121 }
122
123 // Only evaluate local files for DE and FR, skipping disk checks for other languages
124 if (!in_array($prefix, ['de', 'fr'], true)) {
125 return $file;
126 }
127
128 $main_locale = self::LOCALE_MAP[$prefix] ?? $locale;
129 $languages_dir = plugin_dir_path(__FILE__) . 'languages/';
130
131 // Check for WP 6.5+ lightning-fast PHP translation file
132 $local_l10n = $languages_dir . 'termin-kalender-' . $main_locale . '.l10n.php';
133 if (is_file($local_l10n)) {
134 return $local_l10n; // Force our local file, ignoring global wp-content/languages
135 }
136
137 // Fallback to older MO file format for WP 6.0 - 6.4 users
138 $local_mo = $languages_dir . 'termin-kalender-' . $main_locale . '.mo';
139 if (is_file($local_mo)) {
140 return $local_mo;
141 }
142
143 return $file;
144 }
145 //-------------------------------------------------------------------------------------------------
146 public function map_script_translations($file, $handle, $domain)
147 {
148 // Don't process empty files or different domains
149 if ('termin-kalender' !== $domain || empty($file)) {
150 return $file;
151 }
152
153 $locale = determine_locale();
154 $prefix = substr($locale, 0, 2);
155
156 // English: return false to use native JS texts via wp.i18n.__ fallback without file loads
157 if ('en' === $prefix) {
158 return false;
159 }
160
161 // Skip optimizing if language is not supported locally
162 if (!in_array($prefix, ['de', 'fr'], true)) {
163 return $file;
164 }
165
166 $main_locale = self::LOCALE_MAP[$prefix] ?? $locale;
167
168 // Extract filename from the generated string
169 $filename = basename($file);
170
171 if ($main_locale !== $locale) {
172 $filename = str_replace('-' . $locale . '-', '-' . $main_locale . '-', $filename);
173 }
174
175 $local_file = plugin_dir_path(__FILE__) . 'languages/' . $filename;
176
177 // Force return local JSON to completely bypass WordPress Repo fallbacks, ONLY if it exists natively
178 if (is_file($local_file)) {
179 return $local_file;
180 }
181
182 return $file;
183 }
184 //-------------------------------------------------------------------------------------------------
185 //-------------------------------------------------------------------------------------------------
186 //-------------------------------------------------------------------------------------------------
187 public function ter_kal_enqueue_admin_assets($hook)
188 {
189 //-------------------------------------------------------------------------
190 if (class_exists('Termin_Kalender_PRO_Plugin')) {
191 $pro_version = Termin_Kalender_PRO_Plugin::TER_KAL_PRO_TK_VERSION;
192 if ($pro_version && version_compare($pro_version, '1.2.3.9', '<')) {
193 deactivate_plugins('termin-kalender-pro/termin-kalender-pro.php', true);
194 add_action('admin_notices', function () use ($pro_version) {
195 echo '<div class="notice notice-warning"><p>';
196 echo '<strong>Termin-Kalender PRO ' . esc_html($pro_version) . ': </strong>';
197 echo esc_html__('You are using an outdated version. Please update both plugins.', 'termin-kalender');
198 echo '</p></div>';
199 });
200 }
201 }
202 //-------------------------------------------------------------------------
203 //-------------------------------------------------------------------------
204 wp_enqueue_script('termin_kalender_namespace', Termin_Kalender_Plugin::$plugin_url . 'js/termin_kalender_namespace.js', ['jquery'], Termin_Kalender_Plugin::TER_KAL_TK_VERSION, true);
205 //-------------------------------------------------------------------------
206 // enqueue wenn frontend seite oder post edit
207 //$screen = get_current_screen();
208 // moved inside toplevel_page_termin-kalender
209 //-------------------------------------------------------------------------
210 $is_free_admin = in_array($hook, Termin_Kalender_Plugin::$ter_kal_admin_pages_hook_suffixes, true);
211 //------------------------------------------------------------------------------------------------
212 if (!$is_free_admin) {
213 return;
214 }
215 //-------------------------------------------------------------------------
216 // brauchen wir nur für die admin seiten
217 //-------------------------------------------------------------------------
218 require_once plugin_dir_path(__FILE__) . 'includes/enqueue_jquery_base.php';
219 //-------------------------------------------------------------------------
220 wp_enqueue_script('fullcalendar_js', self::$plugin_url . 'dist/index.global.min.js', ['jquery', 'moment'], self::TER_KAL_TK_VERSION, true);
221 wp_enqueue_script('fullcalendar_locales', self::$plugin_url . 'dist/locales-all.global.min.js', ['fullcalendar_js'], self::TER_KAL_TK_VERSION, true);
222 wp_enqueue_script('rrule_js', self::$plugin_url . 'dist/rrule.js', [], self::TER_KAL_TK_VERSION, true); // keep for downgrade
223 wp_register_script('terminkalender_fullcalendar-rrule', self::$plugin_url . 'dist/@fullcalendar/rrule/index.global.min.js', ['rrule_js'], self::TER_KAL_TK_VERSION, true); // keep for downgrade
224 wp_enqueue_script('termin_kalender_common', Termin_Kalender_Plugin::$plugin_url . 'js/common.js', ['termin_kalender_namespace', 'jquery', 'fullcalendar_js', 'fullcalendar_locales', 'rrule_js', 'terminkalender_fullcalendar-rrule'], Termin_Kalender_Plugin::TER_KAL_TK_VERSION, true);
225 wp_enqueue_script('termin_kalender_common_admin', Termin_Kalender_Plugin::$plugin_url . 'js/common_admin.js', ['termin_kalender_namespace', 'jquery'], Termin_Kalender_Plugin::TER_KAL_TK_VERSION, true);
226 //-------------------------------------------------------------------------
227 wp_enqueue_style('termin_kalender', self::$plugin_url . 'css/termin_kalender.css', [], self::TER_KAL_TK_VERSION, 'all');
228 wp_enqueue_style('termin_kalender_admin', self::$plugin_url . 'css/termin_kalender_admin.css', [], self::TER_KAL_TK_VERSION, 'all');
229 //-------------------------------------------------------------------------
230
231 //-------------------------------------------------------------------------
232 if ($hook == 'toplevel_page_termin-kalender') {
233 $terminKalenderData = $this->manager->get_termin_kalender_data(true);
234
235 wp_enqueue_style('termin_kalender_ui_dialog', Termin_Kalender_Plugin::$plugin_url . 'css/termin_kalender_ui_dialog.css', ['termin_kalender'], Termin_Kalender_Plugin::TER_KAL_TK_VERSION, 'all');
236 wp_enqueue_style('terminkalender_calendar_css', Termin_Kalender_Plugin::$plugin_url . 'css/termin_kalender_calendar.css', ['termin_kalender'], Termin_Kalender_Plugin::TER_KAL_TK_VERSION, 'all');
237 wp_enqueue_style('flatpickr', self::$plugin_url . 'dist/flatpickr/flatpickr.min.css', [], self::TER_KAL_TK_VERSION, 'all');
238 wp_enqueue_style('flatpickr-theme', self::$plugin_url . 'dist/flatpickr/themes/light.css', ['flatpickr'], self::TER_KAL_TK_VERSION, 'all');
239 wp_enqueue_style('termin_kalender_flatpickr', self::$plugin_url . 'css/termin_kalender_flatpickr.css', ['flatpickr-theme'], self::TER_KAL_TK_VERSION, 'all');
240 wp_enqueue_script('flatpickr', self::$plugin_url . 'dist/flatpickr/flatpickr.min.js', [], '4.6.13', true);
241 $lang = $terminKalenderData['ter_kal_lang'];
242 if ($lang !== 'en') {
243 $locale_file = self::$plugin_url . 'dist/flatpickr/l10n/' . $lang . '.js';
244 wp_enqueue_script('flatpickr-locale', $locale_file, ['termin_kalender_namespace', 'flatpickr'], '4.6.13', true);
245 }
246 //-------------------------------------------------------------------------
247 wp_enqueue_script('termin_kalender_api', self::$plugin_url . 'js/termin-kalender-api.js', ['termin_kalender_namespace'], self::TER_KAL_TK_VERSION, true);
248 wp_enqueue_script('termin_kalender_dialogs', self::$plugin_url . 'js/termin-kalender-dialogs.js', ['termin_kalender_api', 'termin_kalender_namespace', 'jquery', 'jquery-ui-dialog'], self::TER_KAL_TK_VERSION, true);
249 wp_enqueue_script('termin_kalender_calendar', self::$plugin_url . 'js/calendar.js', ['termin_kalender_api', 'termin_kalender_dialogs', 'termin_kalender_namespace', 'fullcalendar_js', 'fullcalendar_locales', 'rrule_js', 'terminkalender_fullcalendar-rrule', 'flatpickr', 'termin_kalender_common'], self::TER_KAL_TK_VERSION, true);
250 //error_log(print_r($terminKalenderData, true));
251 wp_localize_script('termin_kalender_calendar', 'terminKalenderData', $terminKalenderData);
252 //////
253 wp_set_script_translations('termin_kalender_calendar', 'termin-kalender', self::$plugin_dir_path . 'languages');
254 //////
255 // nicht fuer frontend:
256 wp_enqueue_script('google_calendar', self::$plugin_url . 'dist/@fullcalendar/google-calendar/index.global.min.js', ['jquery'], self::TER_KAL_TK_VERSION, true); // keep for downgrade
257 wp_enqueue_script('termin_kalender_format_buttons', self::$plugin_url . 'js/termin_kalender_format_buttons.js', ['termin_kalender_namespace'], self::TER_KAL_TK_VERSION, true);
258 wp_set_script_translations('termin_kalender_format_buttons', 'termin-kalender', self::$plugin_dir_path . 'languages');
259 }
260 //------------------------------------------------------------------
261 }
262 //------------------------------------------------------------------
263
264 public static function activate()
265 {
266
267 $options = get_option('termin_kalender_options', array());
268 $options['termin_kalender_version'] = self::TER_KAL_TK_VERSION;
269 update_option('termin_kalender_options', $options);
270
271 // Attempt table creation immediately so the fallback flag is set
272 // correctly before first_run() writes any demo data.
273 require_once plugin_dir_path(__FILE__) . 'classes/class-termin-kalender-event-repository.php';
274 Termin_Kalender_Event_Repository::create_table();
275
276 require_once plugin_dir_path(__FILE__) . 'includes/first_run_cleanup_old_versions.php';
277 termin_kalender_cleanup_old_versions();
278 require_once plugin_dir_path(__FILE__) . 'includes/dashicons.php';
279 require_once plugin_dir_path(__FILE__) . 'includes/first_run.php';
280 termin_kalender_first_run();
281 }
282
283 // to run cleanup logic also at plugin update.
284 public static function init_termin_kalender_update()
285 {
286 // ----------------------------------------------------
287 // Auto-Migration to DB Table without requiring reactivation
288 // ----------------------------------------------------
289 if (class_exists('Termin_Kalender_Event_Repository') && get_option('termin_kalender_events') !== false) {
290 Termin_Kalender_Event_Repository::migrate_from_option();
291 }
292
293 $options = get_option('termin_kalender_options', array());
294 $stored_version = isset($options['termin_kalender_version']) ? $options['termin_kalender_version'] : '0';
295 // Run cleanup if version mismatch (new install or update)
296 if (version_compare($stored_version, self::TER_KAL_TK_VERSION, '<')) {
297 require_once plugin_dir_path(__FILE__) . 'includes/first_run_cleanup_old_versions.php';
298 termin_kalender_cleanup_old_versions();
299 // Keep rewrite flushing limited to actual upgrades.
300 flush_rewrite_rules();
301 $options['termin_kalender_version'] = self::TER_KAL_TK_VERSION;
302 update_option('termin_kalender_options', $options);
303 }
304 }
305
306 /**
307 * Plugin deactivation hook callback.
308 Auto data-backup, cleanup, DB deletion? IF PRO: ter_kal_backup_selected_tables()
309 Ask if DB entries should be deleted.
310 Remove options
311 */
312 public static function deactivate()
313 {
314 flush_rewrite_rules();
315 }
316
317 public static function uninstall()
318 {
319 // Delete here with user confirmation
320 delete_option('termin_kalender_options');
321 remove_role('termin_kalender_user');
322 remove_role('termin_kalender_manager');
323 remove_role('termin_kalender_team');
324 $editor = get_role('editor'); // keep admin
325 if ($editor) {
326 foreach (['edit', 'delete'] as $action) {
327 $editor->remove_cap("termin_kalender_{$action}");
328 }
329 }
330 }
331
332 }
333 // Register activation and deactivation hooks.
334 register_activation_hook(__FILE__, ['Termin_Kalender_Plugin', 'activate']);
335 register_deactivation_hook(__FILE__, ['Termin_Kalender_Plugin', 'deactivate']);
336 register_uninstall_hook(__FILE__, ['Termin_Kalender_Plugin', 'uninstall']);
337 // ----------------------------
338 function termin_kalender_load_plugin()
339 {
340 new Termin_Kalender_Plugin();
341 if (function_exists('wp_register_data_request_type')) {
342 wp_register_data_request_type('termin-kalender', [
343 'supports_consent' => true,
344 'categories' => ['functional'],
345 ]);
346 }
347 }
348 add_action('plugins_loaded', 'termin_kalender_load_plugin', 10);
349 // ----------------------------
350