/class.jetpack-autoupdate.php

  1. <?php 
  2.  
  3. /** 
  4. * Handles items that have been selected for automatic updates. 
  5. * Hooks into WP_Automatic_Updater 
  6. */ 
  7. class Jetpack_Autoupdate { 
  8.  
  9. public $updates_allowed; 
  10. public $jetpack; 
  11. public $autoupdate_results; 
  12. public $is_updating = false; 
  13.  
  14. public $autoupdate_expected = array( 
  15. 'plugin'=> array(),  
  16. 'theme' => array(),  
  17. ); 
  18.  
  19. public $log = array( 
  20. 'plugin' => array(),  
  21. 'theme' => array(),  
  22. ); 
  23.  
  24. private static $instance = null; 
  25.  
  26. static function init() { 
  27. if ( is_null( self::$instance ) ) { 
  28. self::$instance = new Jetpack_Autoupdate; 
  29. return self::$instance; 
  30.  
  31. private function __construct() { 
  32.  
  33. $this->updates_allowed = Jetpack::is_module_active( 'manage' ); 
  34. // Only run automatic updates if a user as opted in by activating the manage module. 
  35. if ( $this->updates_allowed ) { 
  36. add_filter( 'auto_update_plugin', array( $this, 'autoupdate_plugin' ), 10, 2 ); 
  37. add_filter( 'auto_update_theme', array( $this, 'autoupdate_theme' ), 10, 2 ); 
  38. add_filter( 'auto_update_core', array( $this, 'autoupdate_core' ), 10, 2 ); 
  39. add_action( 'automatic_updates_complete', array( $this, 'automatic_updates_complete' ), 10, 1 ); 
  40. add_action( 'shutdown', array( $this, 'log_results' ) ); 
  41.  
  42. function autoupdate_plugin( $update, $item ) { 
  43. $autoupdate_plugin_list = Jetpack_Options::get_option( 'autoupdate_plugins', array() ); 
  44. if ( in_array( $item->plugin, $autoupdate_plugin_list ) ) { 
  45. $this->expect( $item->plugin ); 
  46. return true; 
  47.  
  48. return $update; 
  49.  
  50. function autoupdate_theme( $update, $item ) { 
  51. $autoupdate_theme_list = Jetpack_Options::get_option( 'autoupdate_themes', array() ); 
  52. if ( in_array( $item->theme , $autoupdate_theme_list) ) { 
  53. $this->expect( $item->theme, $type = 'theme' ); 
  54. return true; 
  55. return $update; 
  56.  
  57. function autoupdate_core( $update, $item ) { 
  58. $autoupdate_core = Jetpack_Options::get_option( 'autoupdate_core', false ); 
  59. if ( $autoupdate_core ) { 
  60. return $autoupdate_core; 
  61. return $update; 
  62.  
  63. /** 
  64. * Stores the an item identifier to the autoupdate_expected array. 
  65. * 
  66. * @param string $item Example: 'jetpack/jetpack.php' for type 'plugin' or 'twentyfifteen' for type 'theme' 
  67. * @param string $type 'plugin' or 'theme' 
  68. */ 
  69. function expect( $item, $type='plugin' ) { 
  70. $this->is_updating = true; 
  71. $this->autoupdate_expected[ $type ][] = $item; 
  72.  
  73. /** 
  74. * On completion of an automatic update, let's store the results. 
  75. * 
  76. * @param $results - Sent by WP_Automatic_Updater after it completes an autoupdate action. Results may be empty. 
  77. */ 
  78. function automatic_updates_complete( $results ) { 
  79. $this->autoupdate_results = $results; 
  80.  
  81. /** 
  82. * On shutdown, let's check to see if we've preformed an automatic update. 
  83. * If so, let's compare the expected results to the actual results, and log our findings. 
  84. * 
  85. * Results are logged locally via Jetpack::log(), and globally via Jetpack::do_stats() 
  86. */ 
  87. function log_results() { 
  88.  
  89. if ( $this->is_updating ) { 
  90.  
  91. $this->jetpack = Jetpack::init(); 
  92. $items_to_log = array( 'plugin', 'theme' ); 
  93.  
  94. foreach( $items_to_log as $items ) { 
  95. $this->log_items( $items ); 
  96.  
  97. $this->jetpack->do_stats( 'server_side' ); 
  98. $this->jetpack->log( 'autoupdates', $this->log ); 
  99.  
  100. /** 
  101. * Iterates through expected items ( plugins or themes ) and compares them to actual results. 
  102. * 
  103. * @param $items 'plugin' or 'theme' 
  104. */ 
  105. function log_items( $items ) { 
  106. $num_items_updated = 0; 
  107. $num_items_failed = 0; 
  108. $item_results = $this->get_successful_updates( $items ); 
  109. $items_failed = array(); 
  110. $items_success = array(); 
  111.  
  112. foreach( $this->autoupdate_expected[ $items ] as $item ) { 
  113. if ( in_array( $item, $item_results ) ) { 
  114. $num_items_updated++; 
  115. $this->log[ $items ][ $item ] = true; 
  116. $items_success[] = $item; 
  117. } else { 
  118. $num_items_failed++; 
  119. $this->log[ $items ][ $item ] = new WP_Error( "$items-fail", $this->get_error_message( $item, $type = $items ) ); 
  120. $items_failed[] = $item; 
  121.  
  122. if ( $num_items_updated ) { 
  123. $this->jetpack->stat( "autoupdates/$items-success", $num_items_updated ); 
  124.  
  125. if ( $num_items_failed ) { 
  126. // bump stats 
  127. $this->jetpack->stat( "autoupdates/$items-fail", $num_items_failed ); 
  128.  
  129. Jetpack::load_xml_rpc_client(); 
  130. $xml = new Jetpack_IXR_Client( array( 
  131. 'user_id' => get_current_user_id() 
  132. ) ); 
  133. $request = array( 
  134. 'plugins' => $items_failed,  
  135. 'success' => $items_success,  
  136. 'blog_id' => Jetpack_Options::get_option( 'id' ),  
  137. ); 
  138. $xml->query( 'jetpack.debug_autoupdate', $request ); 
  139.  
  140.  
  141. /** 
  142. * Parses the autoupdate results generated by WP_Automatic_Updater and returns a simple array of successful items 
  143. * 
  144. * @param string $type 'plugin' or 'theme' 
  145. * 
  146. * @return array 
  147. */ 
  148. private function get_successful_updates( $type = 'plugin' ) { 
  149. $successful_updates = array(); 
  150.  
  151. if ( ! isset( $this->autoupdate_results[ $type ] ) ) { 
  152. return $successful_updates; 
  153.  
  154. foreach( $this->autoupdate_results[ $type ] as $result ) { 
  155. if ( $result->result ) { 
  156. switch( $type ) { 
  157. case 'theme': 
  158. $successful_updates[] = $result->item->theme; 
  159. break; 
  160. default: 
  161. $successful_updates[] = $result->item->plugin; 
  162.  
  163. return $successful_updates; 
  164.  
  165. /** 
  166. * Cycles through results generated by WP_Automatic_Updater to find the messages for the given item and item type. 
  167. * 
  168. * @param $item Example: 'jetpack/jetpack.php' for type 'plugin' or 'twentyfifteen' for type 'theme' 
  169. * @param string $type 'plugin' or 'theme' 
  170. * 
  171. * @return bool|string 
  172. */ 
  173. private function get_error_message( $item, $type = 'plugin' ) { 
  174. if ( ! isset( $this->autoupdate_results[ $type ] ) ) { 
  175. return false; 
  176. foreach( $this->autoupdate_results[ $type ] as $result ) { 
  177. switch( $type ) { 
  178. case 'theme': 
  179. $id = $result->item->theme; 
  180. break; 
  181. default: 
  182. $id = $result->item->plugin; 
  183. if ( $id == $item && isset( $result->messages ) ) { 
  184. return implode( ', ', $result->messages ); 
  185. return false; 
  186.  
  187. Jetpack_Autoupdate::init(); 
.