PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.27
Booktics – Appointment Booking Calendar for Service Businesses v1.0.27
1.0.29 1.0.28 1.0.27 1.0.26 1.0.25 1.0.24 1.0.23 1.0.22 1.0.21 1.0.20 1.0.19 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.2 1.0.3 All 31 releases
← All changes | core/extensions/plugin-manager.php +366 -263 1.0.1 → 1.0.27 View file →
@@ -1,263 +1,366 @@
1 -<?php
2 -
3 -namespace Booktics\Extensions;
4 -
5 -/**
6 - * Plugin manager
7 - */
8 -class Plugin_Manager {
9 -
10 - /**
11 - * Check if a plugin is installed.
12 - *
13 - * @param string $slug The slug of the plugin.
14 - *
15 - * @return bool True if installed, false otherwise.
16 - */
17 - public static function is_installed( string $slug ): bool {
18 - $plugins = get_plugins();
19 -
20 - if ( is_array( $plugins ) ) {
21 - foreach ( $plugins as $plugin ) {
22 - if ( $plugin['TextDomain'] === $slug ) {
23 - return true;
24 - }
25 - }
26 - }
27 -
28 - return false;
29 - }
30 -
31 - /**
32 - * Check if a plugin is active.
33 - *
34 - * @param string $slug The slug of the plugin.
35 - *
36 - * @return bool True if activated, false otherwise.
37 - */
38 - public static function is_activated( string $slug ): bool {
39 - if ( ! self::is_installed( $slug ) ) {
40 - return false;
41 - }
42 -
43 - return is_plugin_active( self::get_plugin_path( $slug ) );
44 - }
45 -
46 - /**
47 - * Install a plugin from the WordPress repository by slug.
48 - *
49 - * @param string $slug The slug of the plugin.
50 - *
51 - * @return bool True if installation succeeds, false otherwise.
52 - */
53 - public static function install_plugin( string $slug ): bool {
54 - if ( self::is_installed( $slug ) ) {
55 - return true; // Already installed
56 - }
57 -
58 - include_once ABSPATH . 'wp-admin/includes/file.php';
59 - include_once ABSPATH . 'wp-admin/includes/misc.php';
60 - include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
61 -
62 - $skin = new \Automatic_Upgrader_Skin();
63 - $upgrader = new \Plugin_Upgrader( $skin );
64 - $download_link = isset( self::extensions()[ $slug ] ) ? self::extensions()[ $slug ]['download_link'] : null;
65 - $result = $upgrader->install( $download_link );
66 -
67 - return (bool) $result;
68 - }
69 -
70 - /**
71 - * Activate a plugin by slug.
72 - *
73 - * @param string $slug The slug of the plugin.
74 - *
75 - * @return bool True if activated, false otherwise.
76 - */
77 - public static function activate_plugin( string $slug ): bool {
78 - if ( ! self::is_installed( $slug ) ) {
79 - return false; // Plugin isn't installed
80 - }
81 -
82 - $plugin_path = self::get_plugin_path( $slug );
83 - $result = activate_plugin( $plugin_path );
84 -
85 - if ( is_wp_error( $result ) ) {
86 - return $result;
87 - }
88 -
89 - return true;
90 - }
91 -
92 - /**
93 - * Deactivate a plugin by slug.
94 - *
95 - * @param string $slug The slug of the plugin.
96 - *
97 - * @return bool True if deactivated, false otherwise.
98 - */
99 - public static function deactivate_plugin( string $slug ) {
100 - if ( ! self::is_activated( $slug ) ) {
101 - return false; // Plugin isn't activated
102 - }
103 -
104 - $plugin_path = self::get_plugin_path( $slug );
105 -
106 - deactivate_plugins( $plugin_path );
107 -
108 - return true;
109 - }
110 -
111 - /**
112 - * Get the plugin path by slug.
113 - *
114 - * @param string $slug The slug of the plugin.
115 - *
116 - * @return string The path to the plugin file.
117 - */
118 - private static function get_plugin_path( string $slug ) {
119 - $plugins = get_plugins();
120 -
121 - if ( is_array( $plugins ) ) {
122 - foreach ( $plugins as $plugin_path => $plugin ) {
123 - if ( $plugin['TextDomain'] === $slug ) {
124 - return $plugin_path;
125 - }
126 - }
127 - }
128 -
129 - return false;
130 - }
131 -
132 - /**
133 - * Check if the provided file is the main plugin file.
134 - *
135 - * @param string $file Path to the file.
136 - *
137 - * @return bool True if it is the main plugin file, false otherwise.
138 - */
139 - private static function is_main_plugin_file( string $file ): bool {
140 -
141 - $plugin_data = get_file_data( $file, array( 'Name' => 'Plugin Name' ) );
142 -
143 - return ! empty( $plugin_data['Name'] );
144 - }
145 -
146 - /**
147 - * Get the plugin name by slug.
148 - *
149 - * @param string $slug Plugin slug (e.g., 'woocommerce).
150 - *
151 - * @return string|null Returns the plugin name if found, or null if not found.
152 - */
153 - public static function get_plugin_name_by_slug( string $slug ) {
154 - if ( ! function_exists( 'get_plugins' ) ) {
155 - require_once ABSPATH . 'wp-admin/includes/plugin.php';
156 - }
157 -
158 - $all_plugins = get_plugins();
159 -
160 - foreach ( $all_plugins as $plugin_file => $plugin_data ) {
161 - if ( strpos( $plugin_file, $slug ) !== false ) {
162 - return $plugin_data['Name'];
163 - }
164 - }
165 -
166 - return null;
167 - }
168 -
169 - /**
170 - * List of all extensions
171 - *
172 - * @return array
173 - */
174 - public static function extensions(): array {
175 - return array(
176 - 'booktics-stripe-addon' => array(
177 - 'name' => 'booktics-stripe-addon',
178 - 'slug' => 'booktics-stripe-addon',
179 - 'type' => 'addon',
180 - 'upgrade' => true,
181 - 'upgrade_link' => 'https://themewinter.com/purchase-history',
182 - 'status' => 'off',
183 - 'is_pro' => false,
184 - 'title' => __( 'Booktics Stripe Addon', 'booktics' ),
185 - 'description' => __( 'It allows you to use stripe payment.', 'booktics' ),
186 - 'icon' => Extension_Icon::get( 'booktics-stripe-addon' ),
187 - 'notice' => '',
188 - 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-stripe-addon',
189 - 'settings_link' => '',
190 - 'doc_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-stripe-addon',
191 - 'download_link' => 'https://products.arraytics.com/booktics-addons/booktics-stripe-addon-1.0.0.zip',
192 - ),
193 - 'booktics-google-calendar' => array(
194 - 'name' => 'booktics-google-calendar',
195 - 'slug' => 'booktics-google-calendar',
196 - 'type' => 'addon',
197 - 'upgrade' => true,
198 - 'upgrade_link' => 'https://themewinter.com/purchase-history',
199 - 'status' => 'off',
200 - 'is_pro' => false,
201 - 'title' => __( 'Booktics Google Calendar', 'booktics' ),
202 - 'description' => __( 'It allows you to use google calendar.', 'booktics' ),
203 - 'icon' => Extension_Icon::get( 'booktics-google-calendar' ),
204 - 'notice' => '',
205 - 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-google-calendar',
206 - 'settings_link' => '',
207 - 'doc_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-google-calendar',
208 - 'download_link' => 'https://products.arraytics.com/booktics-addons/booktics-google-calendar-1.0.0.zip',
209 - ),
210 - 'booktics-outlook-calendar' => array(
211 - 'name' => 'booktics-outlook-calendar',
212 - 'slug' => 'booktics-outlook-calendar',
213 - 'type' => 'addon',
214 - 'upgrade' => true,
215 - 'upgrade_link' => 'https://themewinter.com/purchase-history',
216 - 'status' => 'off',
217 - 'is_pro' => false,
218 - 'title' => __( 'Booktics Outlook Calendar', 'booktics' ),
219 - 'description' => __( 'It allows you to use outlook calendar.', 'booktics' ),
220 - 'icon' => Extension_Icon::get( 'booktics-outlook-calendar' ),
221 - 'notice' => '',
222 - 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-outlook-calendar-addon',
223 - 'settings_link' => '',
224 - 'doc_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-outlook-calendar-addon',
225 - 'download_link' => 'https://products.arraytics.com/booktics-addons/booktics-outlook-calendar-addon-1.0.0.zip',
226 - ),
227 - 'booktics-fluentcrm-addon' => array(
228 - 'name' => 'booktics-fluentcrm-addon',
229 - 'slug' => 'booktics-fluentcrm-addon',
230 - 'type' => 'addon',
231 - 'upgrade' => true,
232 - 'upgrade_link' => 'https://themewinter.com/purchase-history',
233 - 'status' => 'off',
234 - 'is_pro' => false,
235 - 'title' => __( 'Booktics FluentCRM Addon', 'booktics' ),
236 - 'description' => __( 'It allows you to use FluentCRM.', 'booktics' ),
237 - 'icon' => Extension_Icon::get( 'booktics-fluentcrm-addon' ),
238 - 'notice' => '',
239 - 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-fluentcrm-addon',
240 - 'settings_link' => '',
241 - 'doc_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-fluentcrm-addon',
242 - 'download_link' => 'https://products.arraytics.com/booktics-addons/booktics-fluentcrm-addon-1.0.0.zip',
243 - ),
244 - 'booktics-paypal-addon' => array(
245 - 'name' => 'booktics-paypal-addon',
246 - 'slug' => 'booktics-paypal-addon',
247 - 'type' => 'addon',
248 - 'upgrade' => true,
249 - 'upgrade_link' => 'https://themewinter.com/purchase-history',
250 - 'status' => 'off',
251 - 'is_pro' => false,
252 - 'title' => __( 'Booktics PayPal Addon', 'booktics' ),
253 - 'description' => __( 'It allows you to use PayPal.', 'booktics' ),
254 - 'icon' => Extension_Icon::get( 'booktics-paypal-addon' ),
255 - 'notice' => '',
256 - 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-paypal-addon',
257 - 'settings_link' => '',
258 - 'doc_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-paypal-addon',
259 - 'download_link' => 'https://products.arraytics.com/booktics-addons/booktics-paypal-addon-1.0.0.zip',
260 - ),
261 - );
262 - }
263 -}
1 +<?php
2 +
3 +namespace Booktics\Extensions;
4 +
5 +/**
6 + * Plugin manager
7 + */
8 +class Plugin_Manager {
9 +
10 + /**
11 + * Check if a plugin is installed.
12 + *
13 + * @param string $slug The slug of the plugin.
14 + *
15 + * @return bool True if installed, false otherwise.
16 + */
17 + public static function is_installed( string $slug ): bool {
18 + if ( ! function_exists( 'get_plugins' ) ) {
19 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
20 + }
21 +
22 + $plugins = get_plugins();
23 +
24 + if ( is_array( $plugins ) ) {
25 + foreach ( $plugins as $plugin_path => $plugin ) {
26 + if ( strpos( $plugin_path, $slug . '/' ) === 0 ) {
27 + return true;
28 + }
29 + }
30 + }
31 +
32 + return false;
33 + }
34 +
35 + /**
36 + * Check if a plugin is active.
37 + *
38 + * @param string $slug The slug of the plugin.
39 + *
40 + * @return bool True if activated, false otherwise.
41 + */
42 + public static function is_activated( string $slug ): bool {
43 + if ( ! self::is_installed( $slug ) ) {
44 + return false;
45 + }
46 +
47 + return is_plugin_active( self::get_plugin_path( $slug ) );
48 + }
49 +
50 + /**
51 + * Install a plugin from the WordPress repository by slug.
52 + *
53 + * @param string $slug The slug of the plugin.
54 + *
55 + * @return bool True if installation succeeds, false otherwise.
56 + */
57 + public static function install_plugin( string $slug ): bool {
58 + if ( self::is_installed( $slug ) ) {
59 + return true; // Already installed
60 + }
61 +
62 + include_once ABSPATH . 'wp-admin/includes/file.php';
63 + include_once ABSPATH . 'wp-admin/includes/misc.php';
64 + include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
65 +
66 + $skin = new \Automatic_Upgrader_Skin();
67 + $upgrader = new \Plugin_Upgrader( $skin );
68 + $download_link = null;
69 + foreach ( self::extensions() as $extension ) {
70 + if ( $extension['slug'] === $slug && ! empty( $extension['download_link'] ) ) {
71 + $download_link = $extension['download_link'];
72 + break;
73 + }
74 + }
75 +
76 + if ( ! $download_link ) {
77 + return false;
78 + }
79 +
80 + $result = $upgrader->install( $download_link );
81 +
82 + return (bool) $result;
83 + }
84 +
85 + /**
86 + * Activate a plugin by slug.
87 + *
88 + * @param string $slug The slug of the plugin.
89 + *
90 + * @return bool True if activated, false otherwise.
91 + */
92 + public static function activate_plugin( string $slug ): bool {
93 + if ( ! self::is_installed( $slug ) ) {
94 + return false; // Plugin isn't installed
95 + }
96 +
97 + $plugin_path = self::get_plugin_path( $slug );
98 + $result = activate_plugin( $plugin_path );
99 +
100 + if ( is_wp_error( $result ) ) {
101 + return $result;
102 + }
103 +
104 + return true;
105 + }
106 +
107 + /**
108 + * Deactivate a plugin by slug.
109 + *
110 + * @param string $slug The slug of the plugin.
111 + *
112 + * @return bool True if deactivated, false otherwise.
113 + */
114 + public static function deactivate_plugin( string $slug ) {
115 + if ( ! self::is_activated( $slug ) ) {
116 + return false; // Plugin isn't activated
117 + }
118 +
119 + $plugin_path = self::get_plugin_path( $slug );
120 +
121 + deactivate_plugins( $plugin_path );
122 +
123 + return true;
124 + }
125 +
126 + /**
127 + * Get the plugin path by slug.
128 + *
129 + * @param string $slug The slug of the plugin.
130 + *
131 + * @return string The path to the plugin file.
132 + */
133 + private static function get_plugin_path( string $slug ) {
134 + if ( ! function_exists( 'get_plugins' ) ) {
135 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
136 + }
137 +
138 + $plugins = get_plugins();
139 +
140 + if ( is_array( $plugins ) ) {
141 + foreach ( $plugins as $plugin_path => $plugin ) {
142 + if ( strpos( $plugin_path, $slug . '/' ) === 0 ) {
143 + return $plugin_path;
144 + }
145 + }
146 + }
147 +
148 + return false;
149 + }
150 +
151 + /**
152 + * Check if the provided file is the main plugin file.
153 + *
154 + * @param string $file Path to the file.
155 + *
156 + * @return bool True if it is the main plugin file, false otherwise.
157 + */
158 + private static function is_main_plugin_file( string $file ): bool {
159 +
160 + $plugin_data = get_file_data( $file, array( 'Name' => 'Plugin Name' ) );
161 +
162 + return ! empty( $plugin_data['Name'] );
163 + }
164 +
165 + /**
166 + * Get the plugin name by slug.
167 + *
168 + * @param string $slug Plugin slug (e.g., 'woocommerce).
169 + *
170 + * @return string|null Returns the plugin name if found, or null if not found.
171 + */
172 + public static function get_plugin_name_by_slug( string $slug ) {
173 + if ( ! function_exists( 'get_plugins' ) ) {
174 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
175 + }
176 +
177 + $all_plugins = get_plugins();
178 +
179 + foreach ( $all_plugins as $plugin_file => $plugin_data ) {
180 + if ( strpos( $plugin_file, $slug ) !== false ) {
181 + return $plugin_data['Name'];
182 + }
183 + }
184 +
185 + return null;
186 + }
187 +
188 + /**
189 + * List of all extensions
190 + *
191 + * @return array
192 + */
193 + public static function extensions(): array {
194 + return array(
195 + 'booktics-stripe-addon' => array(
196 + 'name' => 'booktics-stripe-addon',
197 + 'slug' => 'booktics-stripe-addon',
198 + 'type' => 'addon',
199 + 'upgrade' => true,
200 + 'upgrade_link' => 'https://themewinter.com/purchase-history',
201 + 'status' => 'off',
202 + 'is_pro' => false,
203 + 'title' => __( 'Booktics Stripe Addon', 'booktics' ),
204 + 'description' => __( 'It allows you to use stripe payment.', 'booktics' ),
205 + 'icon' => Extension_Icon::get( 'booktics-stripe-addon' ),
206 + 'notice' => '',
207 + 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-stripe-addon',
208 + 'settings_link' => '',
209 + 'doc_link' => 'https://docs.arraytics.com/docs/booktics/payment-type/how-to-configure-the-stripe-in-booktics/',
210 + 'download_link' => 'https://products.arraytics.com/booktics-addons/booktics-stripe-addon-1.0.0.zip',
211 + ),
212 + 'booktics-google-calendar' => array(
213 + 'name' => 'booktics-google-calendar',
214 + 'slug' => 'booktics-google-calendar',
215 + 'type' => 'addon',
216 + 'upgrade' => true,
217 + 'upgrade_link' => 'https://themewinter.com/purchase-history',
218 + 'status' => 'off',
219 + 'is_pro' => false,
220 + 'title' => __( 'Booktics Google Calendar', 'booktics' ),
221 + 'description' => __( 'It allows you to use google calendar.', 'booktics' ),
222 + 'icon' => Extension_Icon::get( 'booktics-google-calendar' ),
223 + 'notice' => '',
224 + 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-google-calendar',
225 + 'settings_link' => '',
226 + 'doc_link' => 'https://docs.arraytics.com/docs/booktics/integration/how-to-integrate-google-calendar-with-booktics/',
227 + 'download_link' => 'https://products.arraytics.com/booktics-addons/booktics-google-calendar-1.0.0.zip',
228 + ),
229 + 'booktics-outlook-calendar' => array(
230 + 'name' => 'booktics-outlook-calendar',
231 + 'slug' => 'booktics-outlook-calendar',
232 + 'type' => 'addon',
233 + 'upgrade' => true,
234 + 'upgrade_link' => 'https://themewinter.com/purchase-history',
235 + 'status' => 'off',
236 + 'is_pro' => false,
237 + 'title' => __( 'Booktics Outlook Calendar', 'booktics' ),
238 + 'description' => __( 'It allows you to use outlook calendar.', 'booktics' ),
239 + 'icon' => Extension_Icon::get( 'booktics-outlook-calendar' ),
240 + 'notice' => '',
241 + 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-outlook-calendar-addon',
242 + 'settings_link' => '',
243 + 'doc_link' => 'https://docs.arraytics.com/docs/booktics/integration/how-to-integrate-outlook-calendar-with-booktics/',
244 + 'download_link' => 'https://products.arraytics.com/booktics-addons/booktics-outlook-calendar-addon-1.0.0.zip',
245 + ),
246 + 'booktics-fluentcrm-addon' => array(
247 + 'name' => 'booktics-fluentcrm-addon',
248 + 'slug' => 'booktics-fluentcrm-addon',
249 + 'type' => 'addon',
250 + 'upgrade' => true,
251 + 'upgrade_link' => 'https://themewinter.com/purchase-history',
252 + 'status' => 'off',
253 + 'is_pro' => false,
254 + 'title' => __( 'Booktics FluentCRM Addon', 'booktics' ),
255 + 'description' => __( 'It allows you to use FluentCRM.', 'booktics' ),
256 + 'icon' => Extension_Icon::get( 'booktics-fluentcrm-addon' ),
257 + 'notice' => '',
258 + 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-fluentcrm-addon',
259 + 'settings_link' => '',
260 + 'doc_link' => 'https://docs.arraytics.com/docs/booktics/',
261 + 'download_link' => 'https://products.arraytics.com/booktics-addons/booktics-fluentcrm-addon-1.0.0.zip',
262 + ),
263 + 'booktics-paypal-addon' => array(
264 + 'name' => 'booktics-paypal-addon',
265 + 'slug' => 'booktics-paypal-addon',
266 + 'type' => 'addon',
267 + 'upgrade' => true,
268 + 'upgrade_link' => 'https://themewinter.com/purchase-history',
269 + 'status' => 'off',
270 + 'is_pro' => false,
271 + 'title' => __( 'Booktics PayPal Addon', 'booktics' ),
272 + 'description' => __( 'It allows you to use PayPal.', 'booktics' ),
273 + 'icon' => Extension_Icon::get( 'booktics-paypal-addon' ),
274 + 'notice' => '',
275 + 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-paypal-addon',
276 + 'settings_link' => '',
277 + 'doc_link' => 'https://docs.arraytics.com/docs/booktics/payment-type/how-to-configure-the-paypal-in-booktics-pro/',
278 + 'download_link' => 'https://products.arraytics.com/booktics-addons/booktics-paypal-addon-1.0.0.zip',
279 + ),
280 + 'eventin' => array(
281 + 'name' => 'eventin',
282 + 'slug' => 'wp-event-solution',
283 + 'type' => 'plugin',
284 + 'upgrade' => false,
285 + 'upgrade_link' => '',
286 + 'status' => 'off',
287 + 'is_pro' => false,
288 + 'title' => __( 'Eventin', 'booktics' ),
289 + 'description' => __( 'Best Free WordPress Event Calendar Plugin to manage booking, registration, RSVPs, schedule recurring events and sell event tickets with WooCommerce.', 'booktics' ),
290 + 'icon' => Extension_Icon::get( 'eventin' ),
291 + 'notice' => '',
292 + 'demo_link' => 'https://product.themewinter.com/eventin',
293 + 'settings_link' => '',
294 + 'doc_link' => 'https://support.themewinter.com/docs/plugins/docs/eventin/',
295 + 'download_link' => 'https://downloads.wordpress.org/plugin/wp-event-solution.latest-stable.zip',
296 + ),
297 + 'wp-cafe' => array(
298 + 'name' => 'wp-cafe',
299 + 'slug' => 'wp-cafe',
300 + 'type' => 'plugin',
301 + 'upgrade' => false,
302 + 'upgrade_link' => '',
303 + 'status' => 'off',
304 + 'is_pro' => false,
305 + 'title' => __( 'WPCafe', 'booktics' ),
306 + 'description' => __( 'WPCafe - A restaurant plugin to increase sales with an Online Ordering System, Delivery, Pickup, Food Menu, Reservations, and Table Management.', 'booktics' ),
307 + 'icon' => Extension_Icon::get( 'wpcafe' ),
308 + 'notice' => '',
309 + 'demo_link' => 'https://product.themewinter.com/wpcafe',
310 + 'settings_link' => '',
311 + 'doc_link' => 'https://support.themewinter.com/docs/plugins/docs/wp-cafe/',
312 + 'download_link' => 'https://downloads.wordpress.org/plugin/wp-cafe.latest-stable.zip',
313 + ),
314 + 'timetics' => array(
315 + 'name' => 'timetics',
316 + 'slug' => 'timetics',
317 + 'type' => 'plugin',
318 + 'upgrade' => false,
319 + 'upgrade_link' => '',
320 + 'status' => 'off',
321 + 'is_pro' => false,
322 + 'title' => __( 'WP Timetics', 'booktics' ),
323 + 'description' => __( 'Appointment Booking and Scheduling Calendar Plugin - WP Timetics', 'booktics' ),
324 + 'icon' => Extension_Icon::get( 'timetics' ),
325 + 'notice' => '',
326 + 'demo_link' => 'https://arraytics.com/timetics',
327 + 'settings_link' => '',
328 + 'doc_link' => 'https://docs.arraytics.com/docs/timetics/getting-started/',
329 + 'download_link' => 'https://downloads.wordpress.org/plugin/timetics.latest-stable.zip',
330 + ),
331 + 'aisentic' => array(
332 + 'name' => 'aisentic',
333 + 'slug' => 'aisentic',
334 + 'type' => 'plugin',
335 + 'upgrade' => false,
336 + 'upgrade_link' => '',
337 + 'status' => 'off',
338 + 'is_pro' => false,
339 + 'title' => __( 'Aisentic', 'booktics' ),
340 + 'description' => __( 'Your AI assistant for Booktics. Manage bookings, analyze schedules, and automate routine tasks using plain English.', 'booktics' ),
341 + 'icon' => '<svg width="155" height="35.838" viewBox="0 0 155 35.838" fill="none" xmlns="http://www.w3.org/2000/svg"><path width="40" height="40" rx="7.018" fill="#6443f9" d="M6.288 0H29.55A6.288 6.288 0 0 1 35.838 6.288V29.55A6.288 6.288 0 0 1 29.55 35.838H6.288A6.288 6.288 0 0 1 0 29.55V6.288A6.288 6.288 0 0 1 6.288 0z"/><path d="M17.919 3.772c0.609 0 1.193 0.244 1.623 0.676a2.303 2.303 0 0 1 0.216 3c-0.296 0.395 -0.71 0.685 -1.184 0.824v3.397h6.561c1.044 0 2.045 0.417 2.784 1.158a3.942 3.942 0 0 1 1.153 2.791v0.731h0.553a1.975 1.975 0 0 1 1.968 1.974v4.605c0 0.524 -0.207 1.026 -0.576 1.397a1.971 1.971 0 0 1 -1.392 0.578h-0.553v3.216a3.942 3.942 0 0 1 -1.153 2.792 3.942 3.942 0 0 1 -2.784 1.157h-14.434a3.942 3.942 0 0 1 -2.784 -1.157 3.942 3.942 0 0 1 -1.153 -2.791v-3.217h-0.553a1.971 1.971 0 0 1 -1.392 -0.578 1.971 1.971 0 0 1 -0.576 -1.396v-4.605c0 -0.524 0.207 -1.026 0.576 -1.396a1.971 1.971 0 0 1 1.392 -0.579h0.553v-0.731c0 -1.047 0.416 -2.052 1.153 -2.791a3.942 3.942 0 0 1 2.784 -1.158h6.561v-3.396a2.294 2.294 0 0 1 -1.64 -2.197c0 -0.61 0.242 -1.196 0.673 -1.628A2.294 2.294 0 0 1 17.919 3.772m-3.638 21.497a0.655 0.655 0 0 0 -0.908 0.787 0.663 0.663 0 0 0 0.31 0.384 9.291 9.291 0 0 0 8.472 0 0.659 0.659 0 0 0 -0.599 -1.171 8.028 8.028 0 0 1 -7.273 0m-0.627 -8.337a2.294 2.294 0 0 0 -1.623 0.675 2.308 2.308 0 0 0 0 3.258 2.294 2.294 0 0 0 3.92 -1.629c0 -0.611 -0.242 -1.197 -0.672 -1.629a2.294 2.294 0 0 0 -1.623 -0.675m8.529 0a2.294 2.294 0 0 0 -2.122 1.422 2.308 2.308 0 0 0 1.243 3.01 2.294 2.294 0 0 0 2.502 -0.499 2.308 2.308 0 0 0 0 -3.258 2.294 2.294 0 0 0 -1.624 -0.675" fill="#fff"/><path d="M148.257 29.181c-4.408 0 -7.453 -3.172 -7.453 -7.58 0 -4.407 3.044 -7.546 7.453 -7.546 2.569 0 4.661 1.141 5.929 2.949l-2.822 2.188c-0.507 -0.602 -1.395 -1.395 -3.012 -1.395 -2.188 0 -3.679 1.617 -3.679 3.805s1.491 3.805 3.679 3.805c1.617 0 2.474 -0.666 3.012 -1.331l2.822 2.123c-1.269 1.84 -3.361 2.982 -5.929 2.982m-14.589 -0.285v-13.69a0.896 0.896 0 0 1 0.896 -0.896h2.202a0.896 0.896 0 0 1 0.896 0.898l-0.03 13.688z" fill="currentColor"/><path d="M135.793 7.841a0.251 0.251 0 0 1 0.237 0.165l0.173 0.468c0.236 0.636 0.331 0.879 0.507 1.055s0.418 0.271 1.055 0.507l0.468 0.173a0.251 0.251 0 0 1 0 0.473l-0.468 0.173c-0.636 0.236 -0.879 0.332 -1.055 0.507s-0.271 0.418 -0.507 1.055l-0.173 0.469a0.252 0.252 0 0 1 -0.473 0l-0.173 -0.469c-0.236 -0.636 -0.332 -0.878 -0.507 -1.055 -0.176 -0.176 -0.418 -0.271 -1.055 -0.507l-0.469 -0.173a0.252 0.252 0 0 1 0 -0.473l0.469 -0.173c0.636 -0.236 0.879 -0.332 1.055 -0.507s0.271 -0.418 0.507 -1.055l0.173 -0.468a0.251 0.251 0 0 1 0.237 -0.165m-3.058 -1.344a0.251 0.251 0 0 1 0.237 0.165l0.074 0.201c0.106 0.285 0.136 0.352 0.184 0.4 0.048 0.048 0.116 0.079 0.4 0.185l0.201 0.073a0.253 0.253 0 0 1 0 0.473l-0.201 0.074c-0.285 0.106 -0.352 0.136 -0.4 0.184 -0.047 0.048 -0.078 0.116 -0.184 0.4l-0.074 0.201a0.252 0.252 0 0 1 -0.472 0l-0.074 -0.201c-0.106 -0.285 -0.136 -0.352 -0.185 -0.4s-0.115 -0.078 -0.4 -0.184l-0.201 -0.074a0.251 0.251 0 0 1 0 -0.473l0.201 -0.073c0.285 -0.106 0.352 -0.136 0.4 -0.185 0.048 -0.047 0.079 -0.115 0.185 -0.4l0.074 -0.201a0.251 0.251 0 0 1 0.236 -0.165" fill="#6443f9"/><path d="M127.903 28.895c-2.917 0 -4.281 -1.521 -4.281 -4.217v-7.356h-1.902V14.308h1.902v-3.575a0.896 0.896 0 0 1 0.896 -0.896h2.172a0.896 0.896 0 0 1 0.896 0.896v3.575h3.108v3.012h-3.108v6.722c0 1.713 1.046 1.776 1.967 1.776h0.983v3.076zm-22.202 0v-13.69a0.896 0.896 0 0 1 0.896 -0.896h2.172a0.896 0.896 0 0 1 0.896 0.896v0.499c1.11 -1.205 2.664 -1.617 4.091 -1.617 2.631 0 5.676 1.426 5.676 5.898v8.91h-3.964v-8.308c0 -2.569 -1.807 -3.172 -2.917 -3.172 -1.141 0 -2.886 0.603 -2.886 3.172v8.308zm-9.81 0.317c-4.472 0 -7.42 -3.266 -7.42 -7.61s2.854 -7.579 7.262 -7.579c4.344 0 7.008 3.234 7.008 7.58v1.078h-10.465c0.381 1.966 1.807 3.139 3.615 3.139 1.934 0 2.949 -0.887 3.457 -1.554l2.695 1.967c-1.269 1.838 -3.488 2.98 -6.152 2.98m-3.552 -9.037h6.691c-0.349 -1.713 -1.427 -3.013 -3.298 -3.013 -1.808 0 -3.013 1.174 -3.393 3.013M80.38 29.34c-3.584 0 -5.803 -1.744 -6.532 -3.519L76.541 24.012c0.349 0.824 2.061 2.157 3.9 2.157 1.364 0 2.093 -0.412 2.093 -1.364 0 -1.174 -1.871 -1.49 -3.012 -1.871s-5.042 -1.3 -5.042 -4.503c0 -3.107 2.726 -4.439 5.866 -4.439 3.172 0 5.295 1.491 6.025 3.076l-2.569 1.649c-0.444 -0.697 -2.029 -1.711 -3.584 -1.711 -1.299 0 -1.871 0.507 -1.871 1.236 0 1.174 1.808 1.49 2.949 1.871s5.105 1.395 5.105 4.534c0 3.076 -2.283 4.693 -6.025 4.693m-11.352 -17.185c-1.079 0 -2.189 -0.824 -2.189 -2.219 0 -1.364 1.111 -2.093 2.188 -2.093 1.046 0 2.189 0.729 2.189 2.093 0 1.395 -1.142 2.219 -2.188 2.219m-1.998 16.744V14.31h3.996l-0.032 14.586zM44.798 28.895 52.942 8.843a0.896 0.896 0 0 1 0.831 -0.559h1.9a0.896 0.896 0 0 1 0.831 0.56l8.113 20.051h-4.344l-1.332 -3.393h-8.467l-1.331 3.393zm7.167 -7.134h5.517l-2.76 -7.008z" fill="currentColor"/></svg>',
342 + 'notice' => '',
343 + 'demo_link' => '',
344 + 'settings_link' => '',
345 + 'doc_link' => 'https://support.themewinter.com/docs/plugins/docs/aisentic/',
346 + ),
347 + 'optiontics' => array(
348 + 'name' => 'optiontics',
349 + 'slug' => 'optiontics',
350 + 'type' => 'plugin',
351 + 'upgrade' => false,
352 + 'upgrade_link' => '',
353 + 'status' => 'off',
354 + 'is_pro' => false,
355 + 'title' => __( 'Optiontics', 'booktics' ),
356 + 'description' => __( 'Offer paid add-ons and extra options with every booking — services, extras, packages, or custom upgrades.', 'booktics' ),
357 + 'icon' => '<svg width="150px" height="40px" viewBox="0 0 155 27.5" fill="none" xmlns="http://www.w3.org/2000/svg"><path width="36" height="42" rx="5" fill="#F6F3FF" d="M3.125 0H19.375A3.125 3.125 0 0 1 22.5 3.125V23.125A3.125 3.125 0 0 1 19.375 26.25H3.125A3.125 3.125 0 0 1 0 23.125V3.125A3.125 3.125 0 0 1 3.125 0z"/><path x="3.375" y="3.5" width="29.25" height="10.5" rx="5.25" fill="#4A3BD6" d="M5.391 2.188H17.109A3.281 3.281 0 0 1 20.391 5.469V5.469A3.281 3.281 0 0 1 17.109 8.75H5.391A3.281 3.281 0 0 1 2.109 5.469V5.469A3.281 3.281 0 0 1 5.391 2.188z"/><path x="3.375" y="15.75" width="29.25" height="10.5" rx="5.25" fill="#6F33EC" d="M5.391 9.844H17.109A3.281 3.281 0 0 1 20.391 13.125V13.125A3.281 3.281 0 0 1 17.109 16.406H5.391A3.281 3.281 0 0 1 2.109 13.125V13.125A3.281 3.281 0 0 1 5.391 9.844z"/><path x="3.375" y="28" width="29.25" height="10.5" rx="5.25" fill="#1AB89C" d="M5.391 17.5H17.109A3.281 3.281 0 0 1 20.391 20.781V20.781A3.281 3.281 0 0 1 17.109 24.063H5.391A3.281 3.281 0 0 1 2.109 20.781V20.781A3.281 3.281 0 0 1 5.391 17.5z"/><path d="M5.274 3.879c0.833 0 1.523 0.703 1.523 1.589S6.107 7.056 5.274 7.056C4.44 7.056 3.75 6.354 3.75 5.468s0.69 -1.589 1.524 -1.589Z" stroke="white" stroke-width="0.46875"/><path cx="8.4375" cy="33.2487" rx="2.8125" ry="2.91667" fill="white" d="M7.031 20.78A1.758 1.823 0 0 1 5.273 22.603A1.758 1.823 0 0 1 3.516 20.78A1.758 1.823 0 0 1 7.031 20.78z"/><path cx="8.4375" cy="20.9987" rx="2.8125" ry="2.91667" fill="white" d="M7.031 13.124A1.758 1.823 0 0 1 5.273 14.947A1.758 1.823 0 0 1 3.516 13.124A1.758 1.823 0 0 1 7.031 13.124z"/><path d="m4.571 13.216 0.439 0.456 0.967 -1.094" stroke="#6F33EC" stroke-width="0.234375" stroke-linecap="round" stroke-linejoin="round"/><path d="M46.759 13.235q0 2.929 -1.11 4.984 -1.102 2.054 -3.008 3.138 -1.898 1.075 -4.266 1.075 -2.386 0 -4.284 -1.084t-2.999 -3.138q-1.102 -2.055 -1.102 -4.975 0 -2.928 1.102 -4.983 1.101 -2.054 2.999 -3.129Q35.989 4.037 38.375 4.037q2.369 0 4.266 1.084 1.906 1.075 3.008 3.129 1.11 2.055 1.11 4.983m-3.837 0q0 -1.897 -0.569 -3.2 -0.559 -1.302 -1.583 -1.975 -1.022 -0.674 -2.395 -0.674t-2.396 0.674q-1.023 0.673 -1.591 1.975 -0.559 1.303 -0.559 3.2t0.559 3.2q0.569 1.302 1.591 1.976 1.023 0.673 2.396 0.673t2.395 -0.673q1.022 -0.673 1.583 -1.976 0.569 -1.303 0.569 -3.2M49.494 27.223V8.759h3.672v2.256h0.166q0.244 -0.542 0.708 -1.102 0.472 -0.569 1.224 -0.944 0.761 -0.385 1.888 -0.385 1.469 0 2.711 0.769 1.241 0.761 1.984 2.3 0.743 1.529 0.743 3.837 0 2.247 -0.726 3.794 -0.717 1.539 -1.958 2.334 -1.233 0.787 -2.763 0.787 -1.084 0 -1.845 -0.359 -0.752 -0.358 -1.232 -0.9 -0.481 -0.551 -0.734 -1.111h-0.114v7.186zm3.646 -11.75q0 1.198 0.332 2.089 0.333 0.892 0.962 1.39 0.629 0.49 1.53 0.49 0.909 0 1.539 -0.498 0.629 -0.507 0.953 -1.399 0.332 -0.9 0.332 -2.072 0 -1.163 -0.323 -2.046 -0.324 -0.883 -0.953 -1.381 -0.63 -0.499 -1.547 -0.498 -0.909 0 -1.539 0.481 -0.621 0.481 -0.953 1.364 -0.332 0.883 -0.332 2.081m19.076 -6.714v2.798h-8.086v-2.797zm-6.251 -3.217h3.724v12.519q0 0.516 0.158 0.805 0.158 0.279 0.437 0.393 0.289 0.114 0.664 0.114 0.263 0 0.524 -0.044 0.263 -0.053 0.403 -0.079l0.586 2.771q-0.279 0.088 -0.787 0.201 -0.507 0.122 -1.232 0.149 -1.346 0.052 -2.361 -0.359 -1.005 -0.411 -1.565 -1.276 -0.559 -0.866 -0.551 -2.186zM74.641 22.188V8.759h3.724V22.188zm1.871 -15.159q-0.831 0 -1.425 -0.551 -0.586 -0.559 -0.586 -1.338 0 -0.769 0.586 -1.321 0.594 -0.559 1.425 -0.559t1.416 0.559q0.594 0.551 0.594 1.321 0 0.778 -0.594 1.338 -0.586 0.55 -1.416 0.55m10.904 15.422q-2.037 0 -3.523 -0.866 -1.478 -0.875 -2.282 -2.431 -0.804 -1.565 -0.804 -3.628 0 -2.081 0.804 -3.637 0.804 -1.564 2.282 -2.43 1.486 -0.875 3.523 -0.875 2.037 0 3.514 0.875 1.486 0.865 2.291 2.43 0.804 1.556 0.804 3.638 0 2.063 -0.804 3.628 -0.804 1.556 -2.291 2.431 -1.478 0.866 -3.514 0.866m0.018 -2.885q0.927 0 1.547 -0.525 0.621 -0.533 0.936 -1.451 0.323 -0.917 0.323 -2.089t-0.323 -2.089q-0.315 -0.917 -0.936 -1.451 -0.621 -0.533 -1.547 -0.533 -0.936 0 -1.574 0.533 -0.629 0.534 -0.953 1.451 -0.314 0.919 -0.314 2.089 0 1.172 0.314 2.089 0.324 0.919 0.953 1.451 0.638 0.525 1.574 0.525m12.737 -5.141V22.188h-3.724V8.759h3.549v2.369h0.157a3.75 3.75 0 0 1 1.495 -1.853q1.049 -0.691 2.544 -0.691 1.399 0 2.439 0.612t1.618 1.749q0.577 1.128 0.577 2.692V22.188h-3.724V14.302q0.008 -1.232 -0.63 -1.924 -0.637 -0.699 -1.757 -0.699 -0.752 0 -1.329 0.324 -0.569 0.324 -0.892 0.944 -0.315 0.613 -0.324 1.478m18.733 -5.665v2.797h-8.087v-2.797zm-6.251 -3.217h3.724v12.519q0 0.516 0.158 0.805 0.158 0.279 0.438 0.393 0.288 0.114 0.664 0.114 0.262 0 0.524 -0.044 0.263 -0.053 0.402 -0.079l0.586 2.771q-0.28 0.088 -0.787 0.201 -0.508 0.122 -1.233 0.149 -1.346 0.052 -2.36 -0.359 -1.006 -0.411 -1.565 -1.276 -0.56 -0.866 -0.551 -2.186zM121.331 22.188V8.759h3.724V22.188zm1.871 -15.159q-0.831 0 -1.425 -0.551 -0.586 -0.559 -0.586 -1.338 0 -0.769 0.586 -1.321 0.594 -0.559 1.425 -0.559t1.416 0.559q0.594 0.551 0.594 1.321 0 0.778 -0.594 1.338 -0.586 0.55 -1.416 0.55m10.904 15.422q-2.063 0 -3.549 -0.875 -1.478 -0.882 -2.272 -2.447 -0.787 -1.565 -0.787 -3.602 0 -2.063 0.796 -3.619 0.804 -1.565 2.281 -2.439 1.478 -0.883 3.515 -0.883 1.757 0 3.077 0.637 1.321 0.639 2.089 1.792 0.769 1.154 0.848 2.711h-3.514q-0.148 -1.006 -0.787 -1.618 -0.629 -0.621 -1.653 -0.621 -0.865 0 -1.512 0.472 -0.639 0.463 -0.997 1.355t-0.359 2.159q0 1.286 0.35 2.186 0.358 0.9 1.006 1.373 0.647 0.473 1.512 0.473 0.639 0 1.146 -0.263a2.219 2.219 0 0 0 0.848 -0.761q0.341 -0.506 0.446 -1.215h3.514q-0.088 1.539 -0.839 2.71 -0.742 1.163 -2.054 1.819 -1.311 0.656 -3.104 0.656m19.555 -9.862 -3.409 0.21a1.75 1.75 0 0 0 -0.376 -0.787 2 2 0 0 0 -0.761 -0.569q-0.463 -0.218 -1.11 -0.218 -0.866 0 -1.46 0.367 -0.594 0.358 -0.594 0.961 0 0.481 0.384 -2.666 0 -4.249 -1.111 -1.574 -1.119 -1.845 -3.043l3.663 -0.192q0.166 0.813 0.804 1.241 0.639 0.419 1.635 0.419 0.979 0 1.574 -0.376 0.603 -0.384 0.612 -0.988 -0.009 -0.508 -0.429 -0.831 -0.419 -0.332 -1.294 -0.506l-2.326 -0.464q-1.967 -0.394 -2.929 -1.364 -0.953 -0.971 -0.953 -2.474 0 -1.294 0.699 -2.229 0.708 -0.936 1.984 -1.442 1.286 -0.506 3.008 -0.507 2.544 0 4.004 1.075 1.469 1.076 1.714 2.929" fill="currentColor"/></svg>',
358 + 'notice' => '',
359 + 'demo_link' => '',
360 + 'settings_link' => '',
361 + 'doc_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/optiontics/how-to-create-product-options/',
362 + 'download_link' => 'https://github.com/themewinter/optiontics-public/releases/download/release/optiontics.zip',
363 + ),
364 + );
365 + }
366 +}