class-wc-plugins-screen-updates.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. /**
  3. * Manages WooCommerce plugin updating on the Plugins screen.
  4. *
  5. * @package WooCommerce/Admin
  6. * @version 3.2.0
  7. */
  8. if ( ! defined( 'ABSPATH' ) ) {
  9. exit;
  10. }
  11. if ( ! class_exists( 'WC_Plugin_Updates' ) ) {
  12. include_once dirname( __FILE__ ) . '/class-wc-plugin-updates.php';
  13. }
  14. /**
  15. * Class WC_Plugins_Screen_Updates
  16. */
  17. class WC_Plugins_Screen_Updates extends WC_Plugin_Updates {
  18. /**
  19. * The upgrade notice shown inline.
  20. *
  21. * @var string
  22. */
  23. protected $upgrade_notice = '';
  24. /**
  25. * Constructor.
  26. */
  27. public function __construct() {
  28. add_action( 'in_plugin_update_message-woocommerce/woocommerce.php', array( $this, 'in_plugin_update_message' ), 10, 2 );
  29. }
  30. /**
  31. * Show plugin changes on the plugins screen. Code adapted from W3 Total Cache.
  32. *
  33. * @param array $args Unused parameter.
  34. * @param stdClass $response Plugin update response.
  35. */
  36. public function in_plugin_update_message( $args, $response ) {
  37. $this->new_version = $response->new_version;
  38. $this->upgrade_notice = $this->get_upgrade_notice( $response->new_version );
  39. $this->major_untested_plugins = $this->get_untested_plugins( $response->new_version, 'major' );
  40. $this->minor_untested_plugins = $this->get_untested_plugins( $response->new_version, 'minor' );
  41. $current_version_parts = explode( '.', WC_VERSION );
  42. $new_version_parts = explode( '.', $this->new_version );
  43. // If user has already moved to the minor version, we don't need to flag up anything.
  44. if ( version_compare( $current_version_parts[0] . '.' . $current_version_parts[1], $new_version_parts[0] . '.' . $new_version_parts[1], '=' ) ) {
  45. return;
  46. }
  47. if ( ! empty( $this->major_untested_plugins ) ) {
  48. $this->upgrade_notice .= $this->get_extensions_inline_warning_major();
  49. }
  50. if ( ! empty( $this->minor_untested_plugins ) ) {
  51. $this->upgrade_notice .= $this->get_extensions_inline_warning_minor();
  52. }
  53. if ( ! empty( $this->major_untested_plugins ) ) {
  54. $this->upgrade_notice .= $this->get_extensions_modal_warning();
  55. add_action( 'admin_print_footer_scripts', array( $this, 'plugin_screen_modal_js' ) );
  56. }
  57. echo apply_filters( 'woocommerce_in_plugin_update_message', $this->upgrade_notice ? '</p>' . wp_kses_post( $this->upgrade_notice ) . '<p class="dummy">' : '' ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
  58. }
  59. /**
  60. * Get the upgrade notice from WordPress.org.
  61. *
  62. * @param string $version WooCommerce new version.
  63. * @return string
  64. */
  65. protected function get_upgrade_notice( $version ) {
  66. $transient_name = 'wc_upgrade_notice_' . $version;
  67. $upgrade_notice = get_transient( $transient_name );
  68. if ( false === $upgrade_notice ) {
  69. $response = wp_safe_remote_get( 'https://plugins.svn.wordpress.org/woocommerce/trunk/readme.txt' );
  70. if ( ! is_wp_error( $response ) && ! empty( $response['body'] ) ) {
  71. $upgrade_notice = $this->parse_update_notice( $response['body'], $version );
  72. set_transient( $transient_name, $upgrade_notice, DAY_IN_SECONDS );
  73. }
  74. }
  75. return $upgrade_notice;
  76. }
  77. /**
  78. * Parse update notice from readme file.
  79. *
  80. * @param string $content WooCommerce readme file content.
  81. * @param string $new_version WooCommerce new version.
  82. * @return string
  83. */
  84. private function parse_update_notice( $content, $new_version ) {
  85. $version_parts = explode( '.', $new_version );
  86. $check_for_notices = array(
  87. $version_parts[0] . '.0', // Major.
  88. $version_parts[0] . '.0.0', // Major.
  89. $version_parts[0] . '.' . $version_parts[1], // Minor.
  90. $version_parts[0] . '.' . $version_parts[1] . '.' . $version_parts[2], // Patch.
  91. );
  92. $notice_regexp = '~==\s*Upgrade Notice\s*==\s*=\s*(.*)\s*=(.*)(=\s*' . preg_quote( $new_version ) . '\s*=|$)~Uis';
  93. $upgrade_notice = '';
  94. foreach ( $check_for_notices as $check_version ) {
  95. if ( version_compare( WC_VERSION, $check_version, '>' ) ) {
  96. continue;
  97. }
  98. $matches = null;
  99. if ( preg_match( $notice_regexp, $content, $matches ) ) {
  100. $notices = (array) preg_split( '~[\r\n]+~', trim( $matches[2] ) );
  101. if ( version_compare( trim( $matches[1] ), $check_version, '=' ) ) {
  102. $upgrade_notice .= '<p class="wc_plugin_upgrade_notice">';
  103. foreach ( $notices as $index => $line ) {
  104. $upgrade_notice .= preg_replace( '~\[([^\]]*)\]\(([^\)]*)\)~', '<a href="${2}">${1}</a>', $line );
  105. }
  106. $upgrade_notice .= '</p>';
  107. }
  108. break;
  109. }
  110. }
  111. return wp_kses_post( $upgrade_notice );
  112. }
  113. /**
  114. * JS for the modal window on the plugins screen.
  115. */
  116. public function plugin_screen_modal_js() {
  117. ?>
  118. <script>
  119. ( function( $ ) {
  120. var $update_box = $( '#woocommerce-update' );
  121. var $update_link = $update_box.find('a.update-link').first();
  122. var update_url = $update_link.attr( 'href' );
  123. // Set up thickbox.
  124. $update_link.removeClass( 'update-link' );
  125. $update_link.addClass( 'wc-thickbox' );
  126. $update_link.attr( 'href', '#TB_inline?height=600&width=550&inlineId=wc_untested_extensions_modal' );
  127. // Trigger the update if the user accepts the modal's warning.
  128. $( '#wc_untested_extensions_modal .accept' ).on( 'click', function( evt ) {
  129. evt.preventDefault();
  130. tb_remove();
  131. $update_link.removeClass( 'wc-thickbox open-plugin-details-modal' );
  132. $update_link.addClass( 'update-link' );
  133. $update_link.attr( 'href', update_url );
  134. $update_link.click();
  135. });
  136. $( '#wc_untested_extensions_modal .cancel' ).on( 'click', function( evt ) {
  137. evt.preventDefault();
  138. tb_remove();
  139. });
  140. })( jQuery );
  141. </script>
  142. <?php
  143. $this->generic_modal_js();
  144. }
  145. }
  146. new WC_Plugins_Screen_Updates();