An updated theme (based on Atticus Finch) for ClassicPress
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

198 lines
6.9 KiB

3 years ago
  1. <?php
  2. if ( !class_exists('Puc_v4p1_UpgraderStatus', false) ):
  3. /**
  4. * A utility class that helps figure out which plugin or theme WordPress is upgrading.
  5. *
  6. * It may seem strange to have a separate class just for that, but the task is surprisingly complicated.
  7. * Core classes like Plugin_Upgrader don't expose the plugin file name during an in-progress update (AFAICT).
  8. * This class uses a few workarounds and heuristics to get the file name.
  9. */
  10. class Puc_v4p1_UpgraderStatus {
  11. private $currentType = null; //"plugin" or "theme".
  12. private $currentId = null; //Plugin basename or theme directory name.
  13. public function __construct() {
  14. //Keep track of which plugin/theme WordPress is currently upgrading.
  15. add_filter('upgrader_pre_install', array($this, 'setUpgradedThing'), 10, 2);
  16. add_filter('upgrader_package_options', array($this, 'setUpgradedPluginFromOptions'), 10, 1);
  17. add_filter('upgrader_post_install', array($this, 'clearUpgradedThing'), 10, 1);
  18. add_action('upgrader_process_complete', array($this, 'clearUpgradedThing'), 10, 1);
  19. }
  20. /**
  21. * Is there and update being installed RIGHT NOW, for a specific plugin?
  22. *
  23. * Caution: This method is unreliable. WordPress doesn't make it easy to figure out what it is upgrading,
  24. * and upgrader implementations are liable to change without notice.
  25. *
  26. * @param string $pluginFile The plugin to check.
  27. * @param WP_Upgrader|null $upgrader The upgrader that's performing the current update.
  28. * @return bool True if the plugin identified by $pluginFile is being upgraded.
  29. */
  30. public function isPluginBeingUpgraded($pluginFile, $upgrader = null) {
  31. return $this->isBeingUpgraded('plugin', $pluginFile, $upgrader);
  32. }
  33. /**
  34. * Is there an update being installed for a specific theme?
  35. *
  36. * @param string $stylesheet Theme directory name.
  37. * @param WP_Upgrader|null $upgrader The upgrader that's performing the current update.
  38. * @return bool
  39. */
  40. public function isThemeBeingUpgraded($stylesheet, $upgrader = null) {
  41. return $this->isBeingUpgraded('theme', $stylesheet, $upgrader);
  42. }
  43. /**
  44. * Check if a specific theme or plugin is being upgraded.
  45. *
  46. * @param string $type
  47. * @param string $id
  48. * @param Plugin_Upgrader|WP_Upgrader|null $upgrader
  49. * @return bool
  50. */
  51. protected function isBeingUpgraded($type, $id, $upgrader = null) {
  52. if ( isset($upgrader) ) {
  53. list($currentType, $currentId) = $this->getThingBeingUpgradedBy($upgrader);
  54. if ( $currentType !== null ) {
  55. $this->currentType = $currentType;
  56. $this->currentId = $currentId;
  57. }
  58. }
  59. return ($this->currentType === $type) && ($this->currentId === $id);
  60. }
  61. /**
  62. * Figure out which theme or plugin is being upgraded by a WP_Upgrader instance.
  63. *
  64. * Returns an array with two items. The first item is the type of the thing that's being
  65. * upgraded: "plugin" or "theme". The second item is either the plugin basename or
  66. * the theme directory name. If we can't determine what the upgrader is doing, both items
  67. * will be NULL.
  68. *
  69. * Examples:
  70. * ['plugin', 'plugin-dir-name/plugin.php']
  71. * ['theme', 'theme-dir-name']
  72. *
  73. * @param Plugin_Upgrader|WP_Upgrader $upgrader
  74. * @return array
  75. */
  76. private function getThingBeingUpgradedBy($upgrader) {
  77. if ( !isset($upgrader, $upgrader->skin) ) {
  78. return array(null, null);
  79. }
  80. //Figure out which plugin or theme is being upgraded.
  81. $pluginFile = null;
  82. $themeDirectoryName = null;
  83. $skin = $upgrader->skin;
  84. if ( isset($skin->theme_info) && ($skin->theme_info instanceof WP_Theme) ) {
  85. $themeDirectoryName = $skin->theme_info->get_stylesheet();
  86. } elseif ( $skin instanceof Plugin_Upgrader_Skin ) {
  87. if ( isset($skin->plugin) && is_string($skin->plugin) && ($skin->plugin !== '') ) {
  88. $pluginFile = $skin->plugin;
  89. }
  90. } elseif ( $skin instanceof Theme_Upgrader_Skin ) {
  91. if ( isset($skin->theme) && is_string($skin->theme) && ($skin->theme !== '') ) {
  92. $themeDirectoryName = $skin->theme;
  93. }
  94. } elseif ( isset($skin->plugin_info) && is_array($skin->plugin_info) ) {
  95. //This case is tricky because Bulk_Plugin_Upgrader_Skin (etc) doesn't actually store the plugin
  96. //filename anywhere. Instead, it has the plugin headers in $plugin_info. So the best we can
  97. //do is compare those headers to the headers of installed plugins.
  98. $pluginFile = $this->identifyPluginByHeaders($skin->plugin_info);
  99. }
  100. if ( $pluginFile !== null ) {
  101. return array('plugin', $pluginFile);
  102. } elseif ( $themeDirectoryName !== null ) {
  103. return array('theme', $themeDirectoryName);
  104. }
  105. return array(null, null);
  106. }
  107. /**
  108. * Identify an installed plugin based on its headers.
  109. *
  110. * @param array $searchHeaders The plugin file header to look for.
  111. * @return string|null Plugin basename ("foo/bar.php"), or NULL if we can't identify the plugin.
  112. */
  113. private function identifyPluginByHeaders($searchHeaders) {
  114. if ( !function_exists('get_plugins') ){
  115. /** @noinspection PhpIncludeInspection */
  116. require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
  117. }
  118. $installedPlugins = get_plugins();
  119. $matches = array();
  120. foreach($installedPlugins as $pluginBasename => $headers) {
  121. $diff1 = array_diff_assoc($headers, $searchHeaders);
  122. $diff2 = array_diff_assoc($searchHeaders, $headers);
  123. if ( empty($diff1) && empty($diff2) ) {
  124. $matches[] = $pluginBasename;
  125. }
  126. }
  127. //It's possible (though very unlikely) that there could be two plugins with identical
  128. //headers. In that case, we can't unambiguously identify the plugin that's being upgraded.
  129. if ( count($matches) !== 1 ) {
  130. return null;
  131. }
  132. return reset($matches);
  133. }
  134. /**
  135. * @access private
  136. *
  137. * @param mixed $input
  138. * @param array $hookExtra
  139. * @return mixed Returns $input unaltered.
  140. */
  141. public function setUpgradedThing($input, $hookExtra) {
  142. if ( !empty($hookExtra['plugin']) && is_string($hookExtra['plugin']) ) {
  143. $this->currentId = $hookExtra['plugin'];
  144. $this->currentType = 'plugin';
  145. } elseif ( !empty($hookExtra['theme']) && is_string($hookExtra['theme']) ) {
  146. $this->currentId = $hookExtra['theme'];
  147. $this->currentType = 'theme';
  148. } else {
  149. $this->currentType = null;
  150. $this->currentId = null;
  151. }
  152. return $input;
  153. }
  154. /**
  155. * @access private
  156. *
  157. * @param array $options
  158. * @return array
  159. */
  160. public function setUpgradedPluginFromOptions($options) {
  161. if ( isset($options['hook_extra']['plugin']) && is_string($options['hook_extra']['plugin']) ) {
  162. $this->currentType = 'plugin';
  163. $this->currentId = $options['hook_extra']['plugin'];
  164. } else {
  165. $this->currentType = null;
  166. $this->currentId = null;
  167. }
  168. return $options;
  169. }
  170. /**
  171. * @access private
  172. *
  173. * @param mixed $input
  174. * @return mixed Returns $input unaltered.
  175. */
  176. public function clearUpgradedThing($input = null) {
  177. $this->currentId = null;
  178. $this->currentType = null;
  179. return $input;
  180. }
  181. }
  182. endif;