PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.29
Booktics – Appointment Booking Calendar for Service Businesses v1.0.29
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/controllers/module-controller.php +164 -14 1.0.3 → 1.0.29 View file →
@@ -3,8 +3,9 @@
3 3 namespace Booktics\Extensions\Controllers;
4 4
5 5 use Booktics\Abstracts\Base_Rest_Controller;
6 6 use Arraytics\ToolsSdk\Extension as ExtensionManager;
7 +use Arraytics\ToolsSdk\PluginManager;
7 8 use WP_HTTP_Response;
8 9 use WP_REST_Request;
9 10
10 11 /**
@@ -39,9 +40,10 @@
39 40 /**
40 41 * Initialize the class and set its properties.
41 42 */
42 43 public function __construct() {
43 - $this->extensions = new ExtensionManager('booktics_available_modules', booktics_modules_list());
44 + $this->extensions = new ExtensionManager('booktics_available_modules', booktics_modules_list());
45 + $this->plugin_manager = new PluginManager();
44 46 }
45 47
46 48 /**
47 49 * Register the routes for the objects of the controller.
@@ -105,9 +107,9 @@
105 107 * @param WP_REST_Request $request Full data about the request.
106 108 * @return WP_HTTP_Response Response object on success, or WP_Error object on failure.
107 109 */
108 110 public function get_items($request) {
109 - $type = !empty($request['type']) ? $request['type'] : 'all';
111 + $type = ! empty( $request['type'] ) ? sanitize_key( $request['type'] ) : 'all';
110 112
111 113 $types = [
112 114 'module' => $this->extensions->get_modules(),
113 115 'addon' => $this->extensions->get_addons(),
@@ -123,8 +125,12 @@
123 125 );
124 126 }
125 127
126 128 foreach ($types[$type] as $data) {
129 + if ( isset( $data['slug'] ) && 'woocommerce' === $data['slug'] ) {
130 + $data = $this->enrich_woocommerce( $data );
131 + }
132 +
127 133 $modules_list[] = $data;
128 134 }
129 135
130 136 return $this->response($modules_list);
@@ -130,8 +136,48 @@
130 136 return $this->response($modules_list);
131 137 }
132 138
133 139 /**
140 + * Attach WooCommerce install state to the module card payload.
141 + *
142 + * The Modules screen does not load the settings REST payload, so the card
143 + * has no other way to know whether WooCommerce is installed. With this it
144 + * can offer the same Install/Activate action the settings panel does.
145 + *
146 + * @param array $data WooCommerce module row.
147 + * @return array
148 + */
149 + protected function enrich_woocommerce( array $data ): array {
150 + if ( ! function_exists( 'get_plugins' ) ) {
151 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
152 + }
153 +
154 + $active = class_exists( 'WooCommerce' );
155 + $installed = $active || array_key_exists( 'woocommerce/woocommerce.php', get_plugins() );
156 +
157 + $data['woocommerce_install_status'] = $active ? 1 : 0;
158 +
159 + // Installed but switched off gets a real one-click activation; not
160 + // installed at all is sent to WordPress' own plugin install screen.
161 + // Built with add_query_arg, not wp_nonce_url: the latter esc_html's its
162 + // output (& -> &), which survives an HTML href but breaks once the
163 + // URL is carried through JSON and assigned to window.location.
164 + $data['woocommerce_activate_url'] = ( $installed && ! $active )
165 + ? add_query_arg(
166 + array(
167 + 'action' => 'activate',
168 + 'plugin' => 'woocommerce/woocommerce.php',
169 + '_wpnonce' => wp_create_nonce( 'activate-plugin_woocommerce/woocommerce.php' ),
170 + ),
171 + admin_url( 'plugins.php' )
172 + )
173 + : '';
174 + $data['woocommerce_install_url'] = admin_url( 'plugin-install.php?tab=plugin-information&plugin=woocommerce&TB_iframe=true' );
175 +
176 + return $data;
177 + }
178 +
179 + /**
134 180 * Update extension status
135 181 *
136 182 * @since 1.0.0
137 183 *
@@ -138,14 +184,14 @@
138 184 * @param WP_REST_Request $request Full data about the request.
139 185 * @return WP_HTTP_Response Response object on success, or WP_Error object on failure.
140 186 */
141 187 public function update_item($request) {
142 - $params = json_decode($request->get_body(), true);
188 + $params = json_decode( $request->get_body(), true);
143 189
144 190 $name = isset($params['name']) ? sanitize_text_field($params['name']) : '';
145 191 $status = isset($params['status']) ? sanitize_text_field($params['status']) : '';
146 192
147 - $valid_statuses = ['off', 'on', 'install', 'activate', 'deactivate'];
193 + $valid_statuses = ['off', 'on', 'install', 'activate', 'deactivate', 'upgrade'];
148 194
149 195 if (empty($name)) {
150 196 return $this->error(
151 197 __('Please enter extension name', 'booktics'),
@@ -171,8 +217,41 @@
171 217 'invalid_status'
172 218 );
173 219 }
174 220
221 + // WooCommerce is a module in this list, but Install/Activate act on the
222 + // WooCommerce *plugin*, not the module toggle. Handle it up front so the
223 + // Modules card can bring WooCommerce up in place, without bouncing the
224 + // admin to wp-admin/plugins.php.
225 + if ( 'woocommerce' === $name && in_array( $status, array( 'install', 'activate' ), true ) ) {
226 + if ( 'install' === $status && ! $this->plugin_manager::is_installed( 'woocommerce' ) ) {
227 + $installed = $this->plugin_manager->install_plugin( 'woocommerce' );
228 +
229 + if ( is_wp_error( $installed ) ) {
230 + return $this->error( $installed->get_error_message(), 500, 'operation_failed' );
231 + }
232 +
233 + if ( false === $installed ) {
234 + return $this->error( __( 'Could not install WooCommerce.', 'booktics' ), 500, 'operation_failed' );
235 + }
236 + }
237 +
238 + $activated = $this->plugin_manager->activate_plugin( 'woocommerce' );
239 +
240 + if ( is_wp_error( $activated ) ) {
241 + return $this->error( $activated->get_error_message(), 500, 'operation_failed' );
242 + }
243 +
244 + if ( false === $activated ) {
245 + return $this->error( __( 'Could not activate WooCommerce.', 'booktics' ), 500, 'operation_failed' );
246 + }
247 +
248 + return $this->response(
249 + array( 'name' => $name, 'status' => 'activate' ),
250 + __( 'WooCommerce activated successfully', 'booktics' )
251 + );
252 + }
253 +
175 254 $extension = $this->extensions->find($name);
176 255
177 256 if (!$extension) {
178 257 return $this->error(
@@ -182,21 +261,68 @@
182 261 'extension_not_found'
183 262 );
184 263 }
185 264
186 - $result = $this->extensions->update($name, $status);
265 + if ( in_array( $extension['type'], array( 'module', 'integration' ), true ) ) {
266 + $result = $this->extensions->update($name, $status);
187 267
188 - if (false === $result) {
189 - return $this->error(
190 - /* translators: %s: extension name */
191 - sprintf(__('Could not %s the extension', 'booktics'), $status),
192 - 500,
193 - 'operation_failed'
194 - );
268 + if (false === $result) {
269 + return $this->error(
270 + /* translators: %s: extension name */
271 + sprintf(__('Could not turn %s the module', 'booktics'), $status),
272 + 500,
273 + 'operation_failed'
274 + );
275 + }
276 +
277 + $this->update_relevant_settings($name, $status);
278 +
279 + /**
280 + * Fires after a module has been turned on or off.
281 + *
282 + * Lets a module react to being enabled without polling, e.g. to
283 + * reset a throttle so its first sync runs immediately.
284 + *
285 + * @param string $name Module slug.
286 + * @param string $status New status.
287 + */
288 + do_action( 'booktics_module_status_updated', $name, $status );
289 +
290 + return $this->response( [
291 + 'name' => $name,
292 + 'status' => $status
293 + ],
294 + /* translators: %s: extension name */
295 + sprintf( __('Module turned %s successfully', 'booktics'), $status) );
195 296 }
196 297
197 - $this->update_relevant_settings($name, $status);
298 + // When updating plugin status using tools-sdk change actual plugin status
299 + if ( 'plugin' === $extension['type'] ) {
300 + switch ( $status ) {
301 + case 'install':
302 + $result = $this->plugin_manager->install_plugin($name);
303 + break;
304 + case 'activate':
305 + $result = $this->plugin_manager->activate_plugin($name);
306 + break;
307 + case 'deactivate':
308 + $result = $this->plugin_manager->deactivate_plugin($name);
309 + break;
310 + case 'upgrade':
311 + return $this->response( [ 'redirect_url' => $extension['upgrade_link'] ] );
312 + break;
313 + }
198 314
315 + if ( false === $result ) {
316 + return $this->error(
317 + /* translators: %s: extension name */
318 + sprintf(__('Could not %s the extension', 'booktics'), $status),
319 + 500,
320 + 'operation_failed'
321 + );
322 + }
323 + }
324 +
199 325 return $this->response([
200 326 'name' => $name,
201 327 'status' => $status,
202 328 ],
@@ -227,20 +353,44 @@
227 353 booktics_update_option('paypal_connected', $is_enabled);
228 354 booktics_update_option('enable_paypal', $is_enabled);
229 355 break;
230 356
357 + case 'woocommerce':
358 + // The booking frontend gates the gateway on this setting, so a
359 + // module toggled from the Modules screen must flip it too;
360 + // otherwise the module boots but no customer can select it.
361 + booktics_update_option('enable_woocommerce_payment', $is_enabled);
362 + break;
363 +
231 364 case 'google-calendar':
232 365 booktics_update_option('google_redirect_url', booktics_get_auth_redirect_uri('google-auth'));
233 - booktics_update_option('google_calendar_connected', $is_enabled);
366 + booktics_update_option('google_calendar_connected', false);
234 367 booktics_update_option('enable_google_calendar', $is_enabled);
235 368 break;
236 369
237 370 case 'outlook-calendar':
371 + booktics_update_option('microsoft_redirect_url', booktics_get_auth_redirect_uri('microsoft-auth'));
238 372 booktics_update_option('enable_outlook_calendar', $is_enabled);
239 373 break;
240 374
241 375 case 'fluentcrm':
242 376 booktics_update_option('enable_fluentcrm', $is_enabled);
377 + break;
378 +
379 + case 'pabbly':
380 + booktics_update_option('enable_pabbly', $is_enabled);
381 + break;
382 +
383 + case 'zapier':
384 + booktics_update_option('enable_zapier', $is_enabled);
385 + break;
386 +
387 + case 'zoho':
388 + booktics_update_option('enable_zoho', $is_enabled);
389 + break;
390 +
391 + case 'mailpoet':
392 + booktics_update_option('enable_mailpoet', $is_enabled);
243 393 break;
244 394 }
245 395 }
246 396 }