PluginProbe
Post Grid Gutenberg Blocks – PostX / 5.0.24
Post Grid Gutenberg Blocks – PostX v5.0.24
5.0.41 5.0.39 5.0.38 5.0.37 5.0.36 5.0.35 5.0.34 5.0.33 5.0.32 5.0.31 5.0.30 5.0.29 5.0.28 5.0.27 5.0.26 5.0.25 5.0.23 5.0.24 5.0.22 5.0.21 5.0.20 5.0.19 5.0.18 5.0.17 2.1.1 All 238 releases
ultimate-post / includes / notice / class-wow-shipping-promotion.php

class-wow-shipping-promotion.php in Post Grid Gutenberg Blocks – PostX 5.0.24, at includes/notice/class-wow-shipping-promotion.php

752 lines 19.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php // phpcs:ignore
2 /**
3 * Initialization Action.
4 *
5 * @package ULTP
6 */
7 namespace ULTP\Includes\Notice;
8
9 defined( 'ABSPATH' ) || exit;
10
11 /**
12 * Initialization class.
13 */
14 class WowShippingPromotion {
15
16 private const VERSION = '20'; // Cache buster.
17 private const MENU_SLUG = 'ultp-settings'; // CHANGE THIS.
18 private const PROMOTED_PLUGIN_SLUG = 'wow-table-rate-shipping';
19 private const PROMOTED_PLUGIN_FILE = 'wow-table-rate-shipping/wow-table-rate-shipping.php';
20
21 /**
22 * Setup class.
23 */
24 public function __construct() {
25 add_filter( 'wtrs_promotion_hooks', array( $this, 'load' ) );
26 add_action( 'plugins_loaded', array( $this, 'run_promotions' ) );
27 }
28
29 /**
30 * Run promotions.
31 *
32 * @return void
33 */
34 public function run_promotions() {
35 if ( ! class_exists( '\WooCommerce' ) ||
36 defined( 'WTRS_VER' )
37 ) {
38 return;
39 }
40
41 // Plugin sidemenu (Plugin Specific, Always run).
42 add_action( 'admin_menu', array( $this, 'add_submenu' ), 9999 );
43
44 if ( $GLOBALS['wtrs_promotion']['init'] ?? false ) {
45 return;
46 }
47
48 $GLOBALS['wtrs_promotion'] = array(
49 'init' => true,
50 );
51
52 $hooks = apply_filters( 'wtrs_promotion_hooks', array() );
53
54 if ( ! is_array( $hooks ) ) {
55 return;
56 }
57
58 uksort( $hooks, 'version_compare' );
59
60 $latest_hook = end( $hooks );
61
62 if ( is_callable( $latest_hook ) ) {
63 $latest_hook();
64 }
65 }
66
67 /**
68 * Load plugin
69 *
70 * @param array $callbacks Callbacks.
71 * @return array
72 */
73 public function load( $callbacks ) {
74
75 if ( isset( $callbacks[ self::VERSION ] ) ) {
76 return $callbacks;
77 }
78
79 $callbacks[ self::VERSION ] = function () {
80 // Dismiss actions.
81 add_action( 'wp_ajax_wtrs_dismiss_promotion', array( $this, 'ajax_dismiss_promotion' ) );
82 add_action( 'wp_ajax_wtrs_install_promotion_plugin', array( $this, 'ajax_install_promotion_plugin' ) );
83
84 // Promotions.
85 // ------------------.
86
87 // Product edit shipping tab.
88 add_action( 'woocommerce_product_options_shipping', array( $this, 'render_shipping_notice' ) );
89
90 // Product category page.
91 add_action( 'product_cat_add_form_fields', array( $this, 'render_product_category_add_notice' ) );
92
93 // WC General settings.
94 add_filter( 'woocommerce_general_settings', array( $this, 'register_general_shipping_location_notice' ) );
95 add_filter( 'woocommerce_product_settings', array( $this, 'register_product_dimensions_notice' ) );
96 add_action( 'woocommerce_admin_field_wtrs_promotion_notice', array( $this, 'render_settings_promotion_field' ) );
97
98 // Order Page.
99 add_action( 'admin_notices', array( $this, 'render_orders_page_notice' ) );
100
101 // Shipping Settings page.
102 add_action( 'admin_notices', array( $this, 'render_shipping_page_notice' ) );
103 };
104
105 return $callbacks;
106 }
107
108
109 /**
110 * Add promotinal submenu link for the promoted plugin dashboard.
111 */
112 public function add_submenu() {
113
114 $url = admin_url( 'admin.php?page=ultp-settings#plugins/wow_shipping' ); // CHANGE THIS.
115
116 ob_start();
117 ?>
118 <style>
119 ul a[href="admin.php?page=wtrs-promotion"] {
120 display: none !important;
121 }
122 #wtrs-submenu-link {
123 color: #297cff !important;
124 }
125 </style>
126 <a id="wtrs-submenu-link" href="<?php echo esc_url( $url ); ?>">
127 <span>Add Shipping Rules</span>
128 </a>
129 <?php
130 $submenu_content = ob_get_clean();
131
132 add_submenu_page(
133 self::MENU_SLUG,
134 'Add Shipping Rules',
135 $submenu_content,
136 'edit_pages', // CHANGE THIS IF NEEDED.
137 'wtrs-promotion',
138 '__return_false'
139 );
140 }
141
142 /**
143 * Ajax handler for dismissing promotion notice.
144 *
145 * @return void
146 */
147 public function ajax_dismiss_promotion() {
148 check_ajax_referer( 'wtrs_promotion_nonce', 'nonce' );
149
150 $type = sanitize_text_field( wp_unslash( $_POST['type'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
151 $this->set_dismissed( $type );
152
153 wp_send_json_success();
154 }
155
156 /**
157 * Ajax handler for installing the promoted plugin.
158 *
159 * @return void
160 */
161 public function ajax_install_promotion_plugin() {
162 check_ajax_referer( 'wtrs_promotion_nonce', 'nonce' );
163
164 $plugin_exists = file_exists( WP_PLUGIN_DIR . '/' . self::PROMOTED_PLUGIN_FILE );
165
166 if ( ! $plugin_exists && ! current_user_can( 'install_plugins' ) ) {
167 wp_send_json_error(
168 array(
169 'message' => esc_html__( 'You are not allowed to install plugins.', 'ultimate-post' ),
170 )
171 );
172 }
173
174 if ( $plugin_exists && ! current_user_can( 'activate_plugins' ) ) {
175 wp_send_json_error(
176 array(
177 'message' => esc_html__( 'You are not allowed to activate plugins.', 'ultimate-post' ),
178 )
179 );
180 }
181
182 $result = $this->install_and_active_plugin();
183
184 if ( false === $result ) {
185 wp_send_json_error(
186 array(
187 'message' => esc_html__( 'Failed to install WowShipping.', 'ultimate-post' ),
188 )
189 );
190 }
191
192 wp_send_json_success(
193 array(
194 'status' => $result,
195 'dashboard_url' => $this->get_dashboard_url(),
196 'message' => esc_html__( 'WowShipping installed successfully.', 'ultimate-post' ),
197 )
198 );
199 }
200
201 /**
202 * Get dismiss key
203 *
204 * @param string $type Promotion type.
205 * @return string
206 */
207 private function get_dismiss_key( $type ) {
208 return 'wtrs_promotion_is_closed_' . self::VERSION . '_' . $type;
209 }
210
211 /**
212 * Should show a promotion
213 *
214 * @param string $type Promotion type.
215 * @return void
216 */
217 private function set_dismissed( $type ) {
218 set_transient( $this->get_dismiss_key( $type ), 'yes', DAY_IN_SECONDS * 30 );
219 }
220
221 /**
222 * Should show a promotion
223 * Dont show promotions if:
224 * - The promotion was dismissed by the user.
225 * - The promotion hook already ran in the current page load by another plugin.
226 *
227 * @param string $type Promotion type.
228 * @return boolean
229 */
230 private function should_show_promotion( $type ) {
231 $ran_once = boolval( $GLOBALS['wtrs_promotion'][ $type ] ?? false );
232 if ( $ran_once ) {
233 return false;
234 }
235 return get_transient( $this->get_dismiss_key( $type ) ) !== 'yes';
236 }
237
238 /**
239 * Render promotion notice in the new product shipping tab.
240 *
241 * @return void
242 */
243 public function render_shipping_notice() {
244 if ( ! $this->should_show_promotion( 'shipping_options' ) ) {
245 return;
246 }
247
248 global $pagenow;
249 $post_type = get_post_type();
250 if ( empty( $post_type ) ) {
251 $post_type = sanitize_text_field( wp_unslash( $_GET['post_type'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
252 }
253 $action = sanitize_text_field( wp_unslash( $_GET['action'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
254
255 $is_edit_product_page = 'post.php' === $pagenow && 'edit' === $action;
256 $is_new_product_page = 'post-new.php' === $pagenow;
257
258 if ( 'product' !== $post_type || ( ! $is_edit_product_page && ! $is_new_product_page ) ) {
259 return;
260 }
261
262 $this->render_promotion_notice(
263 'wtrs-product-shipping',
264 'shipping_options',
265 'Set shipping rates based on <strong>Cart Weight</strong> and <strong>Dimension</strong>',
266 'margin-inline:10px;',
267 true,
268 array(
269 'default' => 'Get Started',
270 'loading' => 'Starting...',
271 )
272 );
273 }
274
275 /**
276 * Render promotion notice in the product category create form.
277 *
278 * @return void
279 */
280 public function render_product_category_add_notice() {
281 if ( ! $this->should_show_promotion( 'product_category_options' ) ) {
282 return;
283 }
284
285 $this->render_promotion_notice(
286 'wtrs-product-category',
287 'product_category_options',
288 'Add Shipping Rule on the specific Products or Product Category',
289 'display:none;',
290 true,
291 array(
292 'default' => 'Start Now',
293 'loading' => 'Starting...',
294 ),
295 );
296
297 ob_start();
298 ?>
299 <script>
300 jQuery( function( $ ) {
301 $(document).ready(function() {
302 $( '#wtrs-product-category' ).insertAfter( '#addtag').slideDown(300);
303 });
304 } );
305 </script>
306 <?php
307 echo ob_get_clean(); // phpcs:ignore
308 }
309
310 /**
311 * Insert a promotion field after the Shipping location(s) setting.
312 *
313 * @param array $settings WooCommerce general settings.
314 * @return array
315 */
316 public function register_general_shipping_location_notice( $settings ) {
317 if ( ! is_array( $settings ) || ! $this->should_show_promotion( 'general_shipping_location' ) ) {
318 return $settings;
319 }
320
321 $notice = array(
322 'title' => '',
323 'type' => 'wtrs_promotion_notice',
324 'id' => 'wtrs-general-shipping-location',
325 );
326
327 $updated_settings = array();
328
329 foreach ( $settings as $setting ) {
330 $updated_settings[] = $setting;
331
332 if ( 'woocommerce_specific_ship_to_countries' === ( $setting['id'] ?? '' ) ) {
333 $updated_settings[] = $notice;
334 }
335 }
336
337 return $updated_settings;
338 }
339
340 /**
341 * Insert a promotion field after the Dimensions unit setting.
342 *
343 * @param array $settings WooCommerce products settings.
344 * @return array
345 */
346 public function register_product_dimensions_notice( $settings ) {
347 if ( ! is_array( $settings ) || ! $this->should_show_promotion( 'product_dimensions_unit' ) ) {
348 return $settings;
349 }
350
351 $notice = array(
352 'title' => '',
353 'type' => 'wtrs_promotion_notice',
354 'id' => 'wtrs-product-dimensions-unit',
355 );
356
357 $updated_settings = array();
358
359 foreach ( $settings as $setting ) {
360 $updated_settings[] = $setting;
361
362 if ( 'woocommerce_dimension_unit' === ( $setting['id'] ?? '' ) ) {
363 $updated_settings[] = $notice;
364 }
365 }
366
367 return $updated_settings;
368 }
369
370 /**
371 * Render the WooCommerce settings promotion row.
372 *
373 * @param array $field Custom field definition.
374 * @return void
375 */
376 public function render_settings_promotion_field( $field ) {
377
378 $field_id = $field['id'] ?? '';
379
380 if ( 'wtrs-general-shipping-location' === $field_id ) {
381 $message = 'Set Shipping Rules for Specific Location';
382 $type = 'general_shipping_location';
383 $id = 'wtrs-general-shipping-location';
384 $style = 'width:400px;';
385 $labels = array(
386 'default' => 'Quick Setup',
387 'loading' => 'Setting up...',
388 );
389 } elseif ( 'wtrs-product-dimensions-unit' === $field_id ) {
390 $message = 'Set shipping rates based on <strong>cart weight</strong> and <strong>dimension</strong>';
391 $type = 'product_dimensions_unit';
392 $id = 'wtrs-product-dimensions-unit';
393 $style = 'width:400px;';
394 $labels = array(
395 'default' => 'Get Started',
396 'loading' => 'Starting...',
397 );
398 } else {
399 return;
400 }
401
402 ?>
403 <tr valign="top">
404 <th scope="row"></th>
405 <td>
406 <?php
407 $this->render_promotion_notice(
408 $id,
409 $type,
410 $message,
411 $style,
412 true,
413 $labels
414 );
415 ?>
416 </td>
417 </tr>
418 <?php
419 }
420
421 /**
422 * Render promotion notice at the top of the WooCommerce orders page.
423 *
424 * @return void
425 */
426 public function render_orders_page_notice() {
427 if ( ! $this->should_show_promotion( 'orders_page' ) || ! $this->is_orders_page_screen() ) {
428 return;
429 }
430
431 $this->render_promotion_notice(
432 'wtrs-orders-page',
433 'orders_page',
434 'Want to increase order value? Add extra charges to every orders by adding shipping rules',
435 'margin:12px 0;',
436 false,
437 array(
438 'default' => 'Start Now',
439 'loading' => 'Starting...',
440 )
441 );
442 }
443
444 /**
445 * Render promotion notice at the top of the WooCommerce shipping page.
446 *
447 * @return void
448 */
449 public function render_shipping_page_notice() {
450
451 global $pagenow;
452 $page = sanitize_text_field( wp_unslash( $_GET['page'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
453 $tab = sanitize_text_field( wp_unslash( $_GET['tab'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
454
455 if (
456 ! $this->should_show_promotion( 'shipping_page' ) ||
457 'admin.php' !== $pagenow ||
458 'shipping' !== $tab ||
459 'wc-settings' !== $page
460 ) {
461 return;
462 }
463
464 $this->render_promotion_notice(
465 'wtrs-shipping-page',
466 'shipping_page',
467 'Automatically calculate shipping rates based on 30+ smart conditions',
468 'margin:12px 0;display:none;',
469 false,
470 array(
471 'default' => 'Activate Rules',
472 'loading' => 'Activating...',
473 )
474 );
475 ob_start();
476 ?>
477 <script>
478 jQuery( function( $ ) {
479 $(document).ready(function() {
480 $( '#wtrs-shipping-page' ).insertAfter( '.wc-shipping-zones-heading' ).slideDown(300);
481 });
482 } );
483 </script>
484 <?php
485 echo ob_get_clean(); // phpcs:ignore
486 }
487
488 /**
489 * Determine whether the current admin screen is a WooCommerce orders list.
490 *
491 * @return boolean
492 */
493 private function is_orders_page_screen() {
494 if ( ! function_exists( 'get_current_screen' ) ) {
495 return false;
496 }
497
498 $screen = get_current_screen();
499
500 if ( ! $screen || empty( $screen->id ) ) {
501 return false;
502 }
503
504 $screen_ids = array( 'edit-shop_order', 'woocommerce_page_wc-orders', 'admin_page_wc-orders' );
505
506 if ( function_exists( 'wc_get_page_screen_id' ) ) {
507 $screen_ids[] = wc_get_page_screen_id( 'shop_order' );
508 }
509
510 return in_array( $screen->id, array_filter( array_unique( $screen_ids ) ), true );
511 }
512
513 /**
514 * Render a reusable promotion notice block.
515 *
516 * @param string $id Notice DOM id.
517 * @param string $type Promotion type.
518 * @param string $message Notice message.
519 * @param string $style Inline wrapper style.
520 * @param boolean $inline Whether the notice should use inline positioning classes.
521 * @param array $button_labels Button text overrides.
522 * @return void
523 */
524 private function render_promotion_notice( $id, $type, $message, $style = '', $inline = true, $button_labels = array() ) {
525 $GLOBALS['wtrs_promotion'][ $type ] = true;
526
527 $button_labels = wp_parse_args(
528 is_array( $button_labels ) ? $button_labels : array(),
529 array(
530 'default' => 'Start Now',
531 'loading' => 'Starting...',
532 )
533 );
534
535 $classes = array( 'notice', 'notice-info', 'is-dismissible', 'wtrs-promotion-notice' );
536
537 if ( $inline ) {
538 $classes[] = 'inline';
539 }
540
541 ob_start();
542 ?>
543
544 <div
545 id="<?php echo esc_attr( $id ); ?>"
546 class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>"
547 data-type="<?php echo esc_attr( $type ); ?>"
548 style="<?php echo esc_attr( $style ); ?>"
549 >
550 <div style="padding-block:12px;display:flex;gap:1rem;align-items:center;">
551 <span>
552 <?php echo wp_kses_post( $message ); ?>
553 </span>
554 <a
555 href="#"
556 class="button button-secondary wtrs-promotion-install-link"
557 role="button"
558 data-default-label="<?php echo esc_attr( $button_labels['default'] ); ?>"
559 data-loading-label="<?php echo esc_attr( $button_labels['loading'] ); ?>"
560 >
561 <?php echo esc_html( $button_labels['default'] ); ?>
562 </a>
563 </div>
564 <button type="button" class="notice-dismiss">
565 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'ultimate-post' ); ?></span>
566 </button>
567 </div>
568 <?php $this->echo_dismiss_notice_js( '#' . $id ); ?>
569 <?php $this->echo_install_notice_js( '#' . $id ); ?>
570 <?php
571 echo ob_get_clean(); // phpcs:ignore
572 }
573
574 /**
575 * Notice dismiss js
576 *
577 * @param string $id Notice ID.
578 * @return void
579 */
580 private function echo_dismiss_notice_js( $id ) {
581 ob_start();
582 ?>
583 <script>
584 jQuery( function( $ ) {
585 $( document ).on( 'click', '<?php echo esc_js( $id ); ?> .notice-dismiss', function() {
586 var $notice = $( this ).closest( '<?php echo esc_js( $id ); ?>' );
587
588 if ( ! $notice.length || 'true' === $notice.attr( 'data-dismissed' ) ) {
589 return;
590 }
591
592 $notice.slideUp( 300, function() {
593 $notice.remove();
594 } ).attr( 'data-dismissed', 'true' );
595
596 $.ajax( {
597 url: <?php echo wp_json_encode( admin_url( 'admin-ajax.php' ) ); ?>,
598 type: 'POST',
599 data: {
600 action: 'wtrs_dismiss_promotion',
601 nonce: <?php echo wp_json_encode( wp_create_nonce( 'wtrs_promotion_nonce' ) ); ?>,
602 type: $notice.data( 'type' ) || ''
603 }
604 } )
605 } );
606 } );
607 </script>
608 <?php
609 echo ob_get_clean(); // phpcs:ignore
610 }
611
612 /**
613 * Notice install js.
614 *
615 * @param string $id Notice ID.
616 * @return void
617 */
618 private function echo_install_notice_js( $id ) {
619 ob_start();
620 ?>
621 <script>
622 jQuery( function( $ ) {
623 $( document ).on( 'click', '<?php echo esc_js( $id ); ?> .wtrs-promotion-install-link', function( event ) {
624 var $button = $( this );
625 var $notice = $button.closest( '<?php echo esc_js( $id ); ?>' );
626 var defaultErrorMessage = <?php echo wp_json_encode( esc_html__( 'Failed to install WowShipping.', 'ultimate-post' ) ); ?>;
627
628 event.preventDefault();
629
630 if ( ! $notice.length || 'true' === $button.attr( 'aria-disabled' ) ) {
631 return;
632 }
633
634 $button.attr( 'aria-disabled', 'true' )
635 .addClass( 'button-disabled' )
636 .text($button.data( 'loading-label' ))
637
638 $.ajax( {
639 url: <?php echo wp_json_encode( admin_url( 'admin-ajax.php' ) ); ?>,
640 type: 'POST',
641 dataType: 'json',
642 data: {
643 action: 'wtrs_install_promotion_plugin',
644 nonce: <?php echo wp_json_encode( wp_create_nonce( 'wtrs_promotion_nonce' ) ); ?>
645 }
646 } ).done( function( response ) {
647 if ( ! response || ! response.success || ! response.data ) {
648 $button.attr( 'aria-disabled', 'false' ).removeClass( 'button-disabled' ).text( $button.data( 'default-label' ) );
649 window.alert( defaultErrorMessage );
650 return;
651 }
652 window.location.href = "<?php echo esc_js( $this->get_dashboard_url() ); ?>";
653 } ).fail( function( xhr ) {
654 var message = xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message
655 ? xhr.responseJSON.data.message
656 : defaultErrorMessage;
657
658 $button.attr( 'aria-disabled', 'false' ).removeClass( 'button-disabled' ).text( $button.data( 'default-label' ) );
659 window.alert( message );
660 } );
661 } );
662 } );
663 </script>
664 <?php
665 echo ob_get_clean(); // phpcs:ignore
666 }
667
668 /**
669 * Get the dashboard URL for the promoted plugin.
670 *
671 * @return string
672 */
673 private function get_dashboard_url() {
674 return admin_url( 'admin.php?page=wtrs-dashboard#overview' );
675 }
676
677 /**
678 * Installs and activates the promoted plugin.
679 *
680 * @return string|false
681 */
682 public function install_and_active_plugin() {
683 include_once ABSPATH . 'wp-admin/includes/plugin.php';
684
685 if ( is_plugin_active( self::PROMOTED_PLUGIN_FILE ) ) {
686 return 'active';
687 }
688
689 if ( ! file_exists( WP_PLUGIN_DIR . '/' . self::PROMOTED_PLUGIN_FILE ) ) {
690 if ( ! $this->download_plugin( self::PROMOTED_PLUGIN_FILE, self::PROMOTED_PLUGIN_SLUG ) ) {
691 return false;
692 }
693 }
694
695 $res = activate_plugin( self::PROMOTED_PLUGIN_FILE );
696
697 return is_wp_error( $res ) ? false : 'installed';
698 }
699
700 /**
701 * Installs a plugin based on the provided plugin file and slug.
702 *
703 * This function is expected to handle the logic required to install a plugin,
704 * such as downloading, unpacking, and activating the plugin using the provided
705 * plugin file and slug.
706 *
707 * @param string $plugin The plugin file path or identifier (e.g., 'plugin-directory/plugin-file.php').
708 * @param string $slug The plugin slug (typically the directory name of the plugin).
709 */
710 private function download_plugin( $plugin, $slug ) {
711 include ABSPATH . 'wp-admin/includes/plugin-install.php';
712 include ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
713
714 if ( ! class_exists( 'Plugin_Upgrader' ) ) {
715 include ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
716 }
717 if ( ! class_exists( 'WP_Ajax_Upgrader_Skin' ) ) {
718 include ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';
719 }
720
721 $api = plugins_api(
722 'plugin_information',
723 array(
724 'slug' => $slug,
725 'fields' => array(
726 'short_description' => false,
727 'sections' => false,
728 'requires' => false,
729 'rating' => false,
730 'ratings' => false,
731 'downloaded' => false,
732 'last_updated' => false,
733 'added' => false,
734 'tags' => false,
735 'compatibility' => false,
736 'homepage' => false,
737 'donate_link' => false,
738 ),
739 )
740 );
741
742 if ( is_wp_error( $api ) ) {
743 return false;
744 }
745
746 $upgrader = new \Plugin_Upgrader( new \WP_Ajax_Upgrader_Skin() );
747 $install_result = $upgrader->install( $api->download_link );
748
749 return is_wp_error( $install_result ) || false === $install_result ? false : true;
750 }
751 }
752