PluginProbe
Booking for Appointments and Events Calendar – Amelia / 1.2.30
Booking for Appointments and Events Calendar – Amelia v1.2.30
2.4.9 2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 All 59 releases
ameliabooking / ameliabooking.php
ameliabooking.php
592 lines 20.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: Amelia
4 Plugin URI: https://wpamelia.com/
5 Description: Amelia is a simple yet powerful automated booking specialist, working 24/7 to make sure your customers can make appointments and events even while you sleep!
6 Version: 1.2.30
7 Author: TMS
8 Author URI: https://tmsproducts.io/
9 Text Domain: ameliabooking
10 Domain Path: /languages
11 License: GPLv2 or later
12 License URI: http://www.gnu.org/licenses/gpl-2.0.html
13 */
14
15 namespace AmeliaBooking;
16
17 use AmeliaBooking\Domain\Services\Settings\SettingsService;
18 use AmeliaBooking\Infrastructure\Common\Container;
19 use AmeliaBooking\Infrastructure\Routes\Routes;
20 use AmeliaBooking\Infrastructure\Services\Payment\SquareService;
21 use AmeliaBooking\Infrastructure\WP\ButtonService\ButtonService;
22 use AmeliaBooking\Infrastructure\WP\config\Menu;
23 use AmeliaBooking\Infrastructure\WP\Elementor\ElementorBlock;
24 use AmeliaBooking\Infrastructure\WP\ErrorService\ErrorService;
25 use AmeliaBooking\Infrastructure\WP\GutenbergBlock\AmeliaBookingGutenbergBlock;
26 use AmeliaBooking\Infrastructure\WP\GutenbergBlock\AmeliaStepBookingGutenbergBlock;
27 use AmeliaBooking\Infrastructure\WP\GutenbergBlock\AmeliaCatalogBookingGutenbergBlock;
28 use AmeliaBooking\Infrastructure\WP\GutenbergBlock\AmeliaCatalogGutenbergBlock;
29 use AmeliaBooking\Infrastructure\WP\GutenbergBlock\AmeliaEventsGutenbergBlock;
30 use AmeliaBooking\Infrastructure\WP\GutenbergBlock\AmeliaEventsListBookingGutenbergBlock;
31 use AmeliaBooking\Infrastructure\WP\Integrations\WooCommerce\StarterWooCommerceService;
32 use AmeliaBooking\Infrastructure\WP\SettingsService\SettingsStorage;
33 use AmeliaBooking\Infrastructure\WP\Translations\BackendStrings;
34 use AmeliaBooking\Infrastructure\WP\UserRoles\UserRoles;
35 use AmeliaBooking\Infrastructure\WP\WPMenu\Submenu;
36 use AmeliaBooking\Infrastructure\WP\WPMenu\SubmenuPageHandler;
37 use Exception;
38 use Interop\Container\Exception\ContainerException;
39 use Slim\App;
40
41 // No direct access
42 defined('ABSPATH') or die('No script kiddies please!');
43
44 // Const for path root
45 if (!defined('AMELIA_PATH')) {
46 define('AMELIA_PATH', __DIR__);
47 }
48
49 // Const for uploads path
50 if (!defined('AMELIA_UPLOADS_PATH')) {
51 $uploadDir = wp_upload_dir();
52 define('AMELIA_UPLOADS_PATH', $uploadDir['basedir']);
53 }
54
55 // Const for uploads url
56 if (!defined('AMELIA_UPLOADS_URL')) {
57 $uploadUrl = wp_upload_dir();
58 define('AMELIA_UPLOADS_URL', set_url_scheme($uploadUrl['baseurl']));
59 }
60
61 // Const for uploads url
62 if (!defined('AMELIA_UPLOADS_FILES_URL')) {
63 define('AMELIA_UPLOADS_FILES_URL', AMELIA_UPLOADS_URL . '/amelia/files/');
64 }
65
66 // Const for uploads files path
67 if (!defined('AMELIA_UPLOADS_FILES_PATH')) {
68 define('AMELIA_UPLOADS_FILES_PATH', AMELIA_UPLOADS_PATH . '/amelia/files/');
69 }
70
71 // Const for uploads files path
72 if (!defined('AMELIA_UPLOADS_FILES_PATH_USE')) {
73 define('AMELIA_UPLOADS_FILES_PATH_USE', true);
74 }
75
76 // Const for URL root
77 if (!defined('AMELIA_URL')) {
78 define('AMELIA_URL', plugin_dir_url(__FILE__));
79 }
80
81 if (!defined('AMELIA_HOME_URL')) {
82 define('AMELIA_HOME_URL', get_home_url());
83 }
84
85 // Const for URL Actions identifier
86 if (!defined('AMELIA_ACTION_SLUG')) {
87 define('AMELIA_ACTION_SLUG', 'action=wpamelia_api&call=');
88 }
89
90 // Const for URL Actions identifier
91 if (!defined('AMELIA_ACTION_URL')) {
92 define('AMELIA_ACTION_URL', admin_url('admin-ajax.php', '') . '?' . AMELIA_ACTION_SLUG);
93 }
94
95 // Const for URL Actions identifier
96 if (!defined('AMELIA_PAGE_URL')) {
97 define('AMELIA_PAGE_URL', get_site_url() . '/wp-admin/admin.php?page=');
98 }
99
100 // Const for URL Actions identifier
101 if (!defined('AMELIA_LOGIN_URL')) {
102 define('AMELIA_LOGIN_URL', get_site_url() . '/wp-login.php?redirect_to=');
103 }
104
105 // Const for Amelia version
106 if (!defined('AMELIA_VERSION')) {
107 define('AMELIA_VERSION', '1.2.30');
108 }
109
110 // Const for site URL
111 if (!defined('AMELIA_SITE_URL')) {
112 define('AMELIA_SITE_URL', get_site_url());
113 }
114
115 // Const for plugin basename
116 if (!defined('AMELIA_PLUGIN_SLUG')) {
117 define('AMELIA_PLUGIN_SLUG', plugin_basename(__FILE__));
118 }
119
120 // Const for Amelia SMS API
121 if (!defined('AMELIA_SMS_API_URL')) {
122 define('AMELIA_SMS_API_URL', 'https://smsapi.wpamelia.com/');
123 define('AMELIA_SMS_VENDOR_ID', 36082);
124 define('AMELIA_SMS_PRODUCT_ID_10', 595657);
125 define('AMELIA_SMS_PRODUCT_ID_20', 595658);
126 define('AMELIA_SMS_PRODUCT_ID_50', 595659);
127 define('AMELIA_SMS_PRODUCT_ID_100', 595660);
128 define('AMELIA_SMS_PRODUCT_ID_200', 595661);
129 define('AMELIA_SMS_PRODUCT_ID_500', 595662);
130 }
131
132 if (!defined('AMELIA_STORE_API_URL')) {
133 define('AMELIA_STORE_API_URL', 'https://store.tms-plugins.com/api/');
134 }
135
136 if (!defined('AMELIA_DEV')) {
137 define('AMELIA_DEV', false);
138 }
139
140 if (!defined('AMELIA_NGROK_URL')) {
141 define('AMELIA_NGROK_URL', '97619f3954de.ngrok.app');
142 }
143
144 require_once AMELIA_PATH . '/vendor/autoload.php';
145
146 /**
147 * @noinspection AutoloadingIssuesInspection
148 *
149 * Class Plugin
150 *
151 * @package AmeliaBooking
152 *
153 * @phpcs:ignoreFile
154 * @SuppressWarnings(PHPMD)
155 */
156 class Plugin
157 {
158
159 /**
160 * API Call
161 *
162 * @throws \InvalidArgumentException
163 */
164 public static function wpAmeliaApiCall()
165 {
166 try {
167 /** @var Container $container */
168 $container = require AMELIA_PATH . '/src/Infrastructure/ContainerConfig/container.php';
169
170 $app = new App($container);
171
172 // Initialize all API routes
173 Routes::routes($app, $container);
174
175 $app->run();
176
177 exit();
178 } catch (Exception $e) {
179 echo 'ERROR: ' . esc_html($e->getMessage());
180 }
181 }
182
183 static function square_weekly_token_refresh( $schedules ) {
184 $schedules['weekly'] = array(
185 'interval' => 604800,
186 'display' => __('Add weekly cron to refresh square access token every 7 days')
187 );
188 return $schedules;
189 }
190
191 /**
192 * Initialize the plugin
193 */
194 public static function init()
195 {
196 $settingsService = new SettingsService(new SettingsStorage());
197
198 self::weglotConflict($settingsService, true);
199
200 // Const for path root
201 if (!defined('AMELIA_LOCALE')) {
202 define('AMELIA_LOCALE', get_user_locale());
203 }
204
205 load_plugin_textdomain('ameliabooking', false, plugin_basename(__DIR__) . '/languages/' . AMELIA_LOCALE . '/');
206
207 self::weglotConflict($settingsService, false);
208
209 if (StarterWooCommerceService::isEnabled()) {
210 if (!empty($settingsService->getCategorySettings('payments')['wc']['dashboard'])) {
211 add_filter('woocommerce_prevent_admin_access', '__return_false');
212 }
213
214 if (!empty($settingsService->getCategorySettings('payments')['wc']['enabled'])) {
215 try {
216 StarterWooCommerceService::init($settingsService);
217 } catch (ContainerException $e) {
218 }
219 } else {
220 StarterWooCommerceService::setContainer(require AMELIA_PATH . '/src/Infrastructure/ContainerConfig/container.php');
221 StarterWooCommerceService::$settingsService = $settingsService;
222
223 add_filter('woocommerce_after_order_itemmeta', [StarterWooCommerceService::class, 'orderItemMeta'], 10, 3);
224 }
225 }
226
227 if (!empty($settingsService->getCategorySettings('payments')['square']['enabled']) &&
228 !empty($settingsService->getCategorySettings('payments')['square']['accessToken'])) {
229 add_filter( 'cron_schedules', [self::class, 'square_weekly_token_refresh'] );
230
231 if ( ! wp_next_scheduled( 'amelia_square_access_token_refresh' ) ) {
232 wp_schedule_event( time(), 'weekly', 'amelia_square_access_token_refresh' );
233 }
234
235 /** @var Container $container */
236 $container = require AMELIA_PATH . '/src/Infrastructure/ContainerConfig/container.php';
237
238 /** @var SquareService $squareService */
239 $squareService = $container->get('infrastructure.payment.square.service');
240
241 add_action( 'amelia_square_access_token_refresh', [$squareService, 'refreshAccessToken'] );
242 }
243
244 $ameliaRole = UserRoles::getUserAmeliaRole(wp_get_current_user());
245
246 // Init menu if user is logged in with amelia role
247 if (in_array($ameliaRole, ['admin', 'manager', 'provider', 'customer'])) {
248 if ($ameliaRole === 'admin') {
249 ErrorService::setNotices();
250 }
251
252 // Add TinyMCE button for shortcode generator
253 ButtonService::renderButton();
254
255 // Add Gutenberg Block for shortcode generator
256 AmeliaStepBookingGutenbergBlock::init();
257 AmeliaCatalogBookingGutenbergBlock::init();
258 AmeliaBookingGutenbergBlock::init();
259 AmeliaCatalogGutenbergBlock::init();
260 AmeliaEventsGutenbergBlock::init();
261 AmeliaEventsListBookingGutenbergBlock::init();
262
263
264 add_filter('block_categories_all', array('AmeliaBooking\Plugin', 'addAmeliaBlockCategory'), 10, 2);
265 add_filter('learn-press/frontend-default-scripts', array('AmeliaBooking\Plugin', 'learnPressConflict'));
266 }
267
268 if (!is_admin()) {
269 add_filter('learn-press/frontend-default-scripts', array('AmeliaBooking\Plugin', 'learnPressConflict'));
270 add_shortcode('ameliabooking', array('AmeliaBooking\Infrastructure\WP\ShortcodeService\BookingShortcodeService', 'shortcodeHandler'));
271 add_shortcode('ameliacatalog', array('AmeliaBooking\Infrastructure\WP\ShortcodeService\CatalogShortcodeService', 'shortcodeHandler'));
272 add_shortcode('ameliaevents', array('AmeliaBooking\Infrastructure\WP\ShortcodeService\EventsShortcodeService', 'shortcodeHandler'));
273 add_shortcode('ameliaeventslistbooking', array('AmeliaBooking\Infrastructure\WP\ShortcodeService\EventsListBookingShortcodeService', 'shortcodeHandler'));
274 add_shortcode('ameliastepbooking', array('AmeliaBooking\Infrastructure\WP\ShortcodeService\StepBookingShortcodeService', 'shortcodeHandler'));
275 add_shortcode('ameliacatalogbooking', array('AmeliaBooking\Infrastructure\WP\ShortcodeService\CatalogBookingShortcodeService', 'shortcodeHandler'));
276 }
277
278 if (defined('ELEMENTOR_VERSION')) {
279 ElementorBlock::get_instance();
280 }
281
282 require_once AMELIA_PATH . '/extensions/divi_amelia/divi_amelia.php';
283
284
285 }
286
287 /**
288 * Creating Amelia block category in Gutenberg
289 */
290 public static function addAmeliaBlockCategory($categories, $post)
291 {
292 return array_merge(
293 array(
294 array(
295 'slug' => 'amelia-blocks',
296 'title' => 'Amelia',
297 ),
298 ),
299 $categories
300 );
301 }
302
303 /**
304 * Fix for conflict with Weglot plugin
305 * @param $settingsService
306 * @param $init
307 */
308 public static function weglotConflict($settingsService, $init)
309 {
310 if (defined('AMELIA_LOCALE_FORCED') &&
311 AMELIA_LOCALE_FORCED &&
312 function_exists('weglot_get_current_language')
313 ) {
314 try {
315 if ($init && !defined('AMELIA_LOCALE')) {
316 $weglotCurrentLanguage = weglot_get_current_language();
317
318 $ameliaUsedLanguages = array_flip($settingsService->getSetting('general', 'usedLanguages'));
319
320 require_once ABSPATH . 'wp-admin/includes/translation-install.php';
321
322 global $locale;
323
324 $potentialLanguages = [];
325
326 foreach (wp_get_available_translations() as $key => $value) {
327 if (substr($key, 0, 2) === substr($weglotCurrentLanguage, 0, 2)) {
328 $potentialLanguages[] = $key;
329 }
330 }
331
332 foreach ($potentialLanguages as $potentialLanguage) {
333 if (array_key_exists($potentialLanguage, $ameliaUsedLanguages)) {
334 $locale = $potentialLanguage;
335 break;
336 }
337 }
338 } else {
339 global $locale;
340
341 $locale = AMELIA_LOCALE_FORCED;
342 }
343 } catch (\Exception $e) {
344
345 }
346 }
347 }
348
349 /**
350 * Fix for conflict with LearnPress plugin
351 */
352 public static function learnPressConflict($data)
353 {
354
355 if (has_shortcode(get_post(get_the_ID())->post_content, 'ameliabooking') ||
356 has_shortcode(get_post(get_the_ID())->post_content, 'ameliacatalog') ||
357 has_shortcode(get_post(get_the_ID())->post_content, 'ameliaevents') ||
358 has_shortcode(get_post(get_the_ID())->post_content, 'ameliaeventslistbooking') ||
359 has_shortcode(get_post(get_the_ID())->post_content, 'ameliastepbooking')
360 ) {
361 return array();
362 } else {
363 return $data;
364 }
365
366 }
367
368 public static function initMenu()
369 {
370 $settingsService = new SettingsService(new SettingsStorage());
371
372 $menuItems = new Menu($settingsService);
373
374 // Init admin menu
375 $wpMenu = new Submenu(
376 new SubmenuPageHandler($settingsService),
377 $menuItems()
378 );
379
380 $wpMenu->addOptionsPages();
381 }
382
383 public static function adminInit()
384 {
385 $settingsService = new SettingsService(new SettingsStorage());
386
387 if (AMELIA_VERSION !== $settingsService->getSetting('activation', 'version')) {
388 $settingsService->setSetting('activation', 'version', AMELIA_VERSION);
389
390 require_once ABSPATH . 'wp-admin/includes/plugin.php';
391
392 deactivate_plugins(AMELIA_PLUGIN_SLUG);
393 activate_plugin(AMELIA_PLUGIN_SLUG);
394 }
395 }
396
397 /**
398 * @param $networkWide
399 */
400 public static function activation($networkWide)
401 {
402 load_plugin_textdomain('ameliabooking', false, plugin_basename(__DIR__) . '/languages/' . get_locale() . '/');
403
404 // Check PHP version
405 if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50500) {
406 deactivate_plugins(AMELIA_PLUGIN_SLUG);
407 wp_die(
408 BackendStrings::getCommonStrings()['php_version_message'],
409 BackendStrings::getCommonStrings()['php_version_title'],
410 array('response' => 200, 'back_link' => TRUE)
411 );
412 }
413 //Network activation
414 if ($networkWide && function_exists('is_multisite') && is_multisite()) {
415 Infrastructure\WP\InstallActions\ActivationMultisite::init();
416 }
417
418 Infrastructure\WP\InstallActions\ActivationDatabaseHook::init();
419 }
420
421 /**
422 * @param $dirPath
423 */
424 public static function deleteFolderContent($dirPath)
425 {
426 if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
427 $dirPath .= '/';
428 }
429
430 $files = glob($dirPath . '*', GLOB_MARK);
431
432 foreach ($files as $file) {
433 if (is_dir($file)) {
434 self::deleteFolderContent($file);
435 } else {
436 unlink($file);
437 }
438 }
439 }
440
441 /**
442 * @throws Domain\Common\Exceptions\InvalidArgumentException
443 */
444 public static function deletion()
445 {
446 $settingsService = new SettingsService(new SettingsStorage());
447
448 if ($settingsService->getSetting('activation', 'deleteTables')) {
449 //Network deletion
450 if (function_exists('is_multisite') &&
451 is_multisite()
452 ) {
453 Infrastructure\WP\InstallActions\DeletionMultisite::delete();
454 }
455
456 Infrastructure\WP\InstallActions\DeleteDatabaseHook::delete();
457
458
459 // Delete Roles
460 global $wp_roles;
461
462 $wp_roles->remove_role('wpamelia-customer');
463 $wp_roles->remove_role('wpamelia-provider');
464 $wp_roles->remove_role('wpamelia-manager');
465
466
467 // Delete Settings
468 delete_option('amelia_settings');
469 delete_option('amelia_stash');
470 delete_option('amelia_show_wpdt_promo');
471
472 // Delete Files
473 foreach (['/amelia/css', '/amelia/files/tmp', '/amelia/files', '/amelia'] as $path) {
474 if (is_dir(AMELIA_UPLOADS_PATH . $path)) {
475 self::deleteFolderContent(AMELIA_UPLOADS_PATH . $path);
476 rmdir(AMELIA_UPLOADS_PATH . $path);
477 }
478 }
479 }
480 }
481
482
483 public static function elementor_popup_notice(){
484 global $pagenow;
485 if ($pagenow == 'edit.php' &&
486 !empty($_REQUEST['post_type']) &&
487 $_REQUEST['post_type'] === 'elementor_library' &&
488 !empty($_REQUEST['tabs_group']) &&
489 $_REQUEST['tabs_group'] === 'popup'
490 ) {
491 echo "<div class='notice notice-warning'>
492 <p>" . esc_html__(BackendStrings::getCommonStrings()['elementor_popup_notice']) . "</p>
493 </div>";
494 }
495 }
496
497 /**
498 * Show WPDT promo notice
499 **/
500 public static function wpdt_dashboard_promo()
501 {
502 $wpAmeliaPage = isset($_GET['page']) ? $_GET['page'] : '';
503
504 require_once AMELIA_PATH . '/extensions/wpdt/functions.php';
505
506 if( is_admin() && (strpos($wpAmeliaPage,'wpamelia-dashboard') !== false) &&
507 amelia_installed_plugins_wpdt_promotion() &&
508 get_option( 'amelia_show_wpdt_promo' ) == 'yes'
509 ) {
510 include AMELIA_PATH . '/extensions/wpdt/promote_wpdt.php';
511 wp_enqueue_style('wdt-promo-css', AMELIA_URL . 'public/css/backend/promote_wpdt.css');
512 }
513 }
514
515 /**
516 * Remove WPDT promo notice
517 **/
518 public static function amelia_remove_wpdt_promo_notice()
519 {
520 update_option( 'amelia_show_wpdt_promo', 'no' );
521 echo json_encode( array("success") );
522 exit;
523 }
524
525 }
526
527 add_action('wp_ajax_amelia_remove_wpdt_promo_notice', array('AmeliaBooking\Plugin', 'amelia_remove_wpdt_promo_notice'));
528
529 add_action('admin_notices', array('AmeliaBooking\Plugin', 'elementor_popup_notice'));
530 add_action('admin_notices', array('AmeliaBooking\Plugin', 'wpdt_dashboard_promo'));
531
532 /** Redirect For Outlook Calendar */
533 if (is_admin()) {
534 add_action('wp_loaded', array('AmeliaBooking\Infrastructure\Services\Outlook\StarterOutlookCalendarService', 'handleCallback'));
535 }
536
537 /** Isolate API calls */
538 add_action('wp_ajax_wpamelia_api', array('AmeliaBooking\Plugin', 'wpAmeliaApiCall'));
539 add_action('wp_ajax_nopriv_wpamelia_api', array('AmeliaBooking\Plugin', 'wpAmeliaApiCall'));
540
541 /** Init the plugin */
542 add_action('plugins_loaded', array('AmeliaBooking\Plugin', 'init'));
543
544 add_action('admin_init', array('AmeliaBooking\Plugin', 'adminInit'));
545
546 add_action('admin_menu', array('AmeliaBooking\Plugin', 'initMenu'));
547
548 /** Activation hooks */
549 register_activation_hook(__FILE__, array('AmeliaBooking\Plugin', 'activation'));
550 register_activation_hook(__FILE__, array('AmeliaBooking\Infrastructure\WP\InstallActions\ActivationRolesHook', 'init'));
551 register_activation_hook(__FILE__, array('AmeliaBooking\Infrastructure\WP\InstallActions\ActivationSettingsHook', 'init'));
552 register_uninstall_hook(__FILE__, array('AmeliaBooking\Plugin', 'deletion'));
553
554 /** Activation hook for new site on multisite setup */
555 add_action('wpmu_new_blog', array('AmeliaBooking\Infrastructure\WP\InstallActions\ActivationNewSiteMultisite', 'init'));
556
557 /** Define the API for updating checking */
558
559 /** Define the alternative response for information checking */
560
561 /** Add a message for unavailable auto update if plugin is not activated */
562
563 /** Add error message on plugin update if plugin is not activated */
564
565 add_filter('script_loader_tag', array('AmeliaBooking\Infrastructure\WP\ShortcodeService\StepBookingShortcodeService', 'prepareScripts') , 10, 3);
566 add_filter('style_loader_tag', array('AmeliaBooking\Infrastructure\WP\ShortcodeService\StepBookingShortcodeService', 'prepareStyles') , 10, 3);
567
568 add_filter('script_loader_tag', array('AmeliaBooking\Infrastructure\WP\ShortcodeService\EventsListBookingShortcodeService', 'prepareScripts') , 10, 3);
569 add_filter('style_loader_tag', array('AmeliaBooking\Infrastructure\WP\ShortcodeService\EventsListBookingShortcodeService', 'prepareStyles') , 10, 3);
570
571 add_filter('submenu_file', function($submenu_file) {
572 global $submenu;
573
574 if (!empty($submenu['amelia'])) {
575 foreach ($submenu['amelia'] as $index => $item) {
576 foreach ($item as $key => $value) {
577 if ($value === 'wpamelia-customize-new') {
578 unset($submenu['amelia'][$index]);
579
580 break 2;
581 }
582 }
583 }
584 }
585
586 return $submenu_file;
587 });
588
589
590 add_action( 'wp_logout', array('AmeliaBooking\Infrastructure\WP\UserService\UserService', 'logoutAmeliaUser'));
591 add_action( 'profile_update', array('AmeliaBooking\Infrastructure\WP\UserService\UserService', 'updateAmeliaUser'), 10, 3);
592 add_action( 'deleted_user', array('AmeliaBooking\Infrastructure\WP\UserService\UserService', 'removeWPUserConnection'), 10, 1);