Panel.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <?php
  2. namespace YahnisElsts\PluginUpdateChecker\v5p1\DebugBar;
  3. use YahnisElsts\PluginUpdateChecker\v5p1\UpdateChecker;
  4. if ( !class_exists(Panel::class, false) && class_exists('Debug_Bar_Panel', false) ):
  5. class Panel extends \Debug_Bar_Panel {
  6. /** @var UpdateChecker */
  7. protected $updateChecker;
  8. private $responseBox = '<div class="puc-ajax-response" style="display: none;"></div>';
  9. public function __construct($updateChecker) {
  10. $this->updateChecker = $updateChecker;
  11. $title = sprintf(
  12. '<span class="puc-debug-menu-link-%s">PUC (%s)</span>',
  13. esc_attr($this->updateChecker->getUniqueName('uid')),
  14. $this->updateChecker->slug
  15. );
  16. parent::__construct($title);
  17. }
  18. public function render() {
  19. printf(
  20. '<div class="puc-debug-bar-panel-v5" id="%1$s" data-slug="%2$s" data-uid="%3$s" data-nonce="%4$s">',
  21. esc_attr($this->updateChecker->getUniqueName('debug-bar-panel')),
  22. esc_attr($this->updateChecker->slug),
  23. esc_attr($this->updateChecker->getUniqueName('uid')),
  24. esc_attr(wp_create_nonce('puc-ajax'))
  25. );
  26. $this->displayConfiguration();
  27. $this->displayStatus();
  28. $this->displayCurrentUpdate();
  29. echo '</div>';
  30. }
  31. private function displayConfiguration() {
  32. echo '<h3>Configuration</h3>';
  33. echo '<table class="puc-debug-data">';
  34. $this->displayConfigHeader();
  35. $this->row('Slug', htmlentities($this->updateChecker->slug));
  36. $this->row('DB option', htmlentities($this->updateChecker->optionName));
  37. $requestInfoButton = $this->getMetadataButton();
  38. $this->row('Metadata URL', htmlentities($this->updateChecker->metadataUrl) . ' ' . $requestInfoButton . $this->responseBox);
  39. $scheduler = $this->updateChecker->scheduler;
  40. if ( $scheduler->checkPeriod > 0 ) {
  41. $this->row('Automatic checks', 'Every ' . $scheduler->checkPeriod . ' hours');
  42. } else {
  43. $this->row('Automatic checks', 'Disabled');
  44. }
  45. if ( isset($scheduler->throttleRedundantChecks) ) {
  46. if ( $scheduler->throttleRedundantChecks && ($scheduler->checkPeriod > 0) ) {
  47. $this->row(
  48. 'Throttling',
  49. sprintf(
  50. 'Enabled. If an update is already available, check for updates every %1$d hours instead of every %2$d hours.',
  51. $scheduler->throttledCheckPeriod,
  52. $scheduler->checkPeriod
  53. )
  54. );
  55. } else {
  56. $this->row('Throttling', 'Disabled');
  57. }
  58. }
  59. $this->updateChecker->onDisplayConfiguration($this);
  60. echo '</table>';
  61. }
  62. protected function displayConfigHeader() {
  63. //Do nothing. This should be implemented in subclasses.
  64. }
  65. protected function getMetadataButton() {
  66. return '';
  67. }
  68. private function displayStatus() {
  69. echo '<h3>Status</h3>';
  70. echo '<table class="puc-debug-data">';
  71. $state = $this->updateChecker->getUpdateState();
  72. $checkButtonId = $this->updateChecker->getUniqueName('check-now-button');
  73. if ( function_exists('get_submit_button') ) {
  74. $checkNowButton = get_submit_button(
  75. 'Check Now',
  76. 'secondary',
  77. 'puc-check-now-button',
  78. false,
  79. array('id' => $checkButtonId)
  80. );
  81. } else {
  82. //get_submit_button() is not available in the frontend. Make a button directly.
  83. //It won't look the same without admin styles, but it should still work.
  84. $checkNowButton = sprintf(
  85. '<input type="button" id="%1$s" name="puc-check-now-button" value="%2$s" class="button button-secondary" />',
  86. esc_attr($checkButtonId),
  87. esc_attr('Check Now')
  88. );
  89. }
  90. if ( $state->getLastCheck() > 0 ) {
  91. $this->row('Last check', $this->formatTimeWithDelta($state->getLastCheck()) . ' ' . $checkNowButton . $this->responseBox);
  92. } else {
  93. $this->row('Last check', 'Never');
  94. }
  95. $nextCheck = wp_next_scheduled($this->updateChecker->scheduler->getCronHookName());
  96. $this->row('Next automatic check', $this->formatTimeWithDelta($nextCheck));
  97. if ( $state->getCheckedVersion() !== '' ) {
  98. $this->row('Checked version', htmlentities($state->getCheckedVersion()));
  99. $this->row('Cached update', $state->getUpdate());
  100. }
  101. $this->row('Update checker class', htmlentities(get_class($this->updateChecker)));
  102. echo '</table>';
  103. }
  104. private function displayCurrentUpdate() {
  105. $update = $this->updateChecker->getUpdate();
  106. if ( $update !== null ) {
  107. echo '<h3>An Update Is Available</h3>';
  108. echo '<table class="puc-debug-data">';
  109. $fields = $this->getUpdateFields();
  110. foreach($fields as $field) {
  111. if ( property_exists($update, $field) ) {
  112. $this->row(
  113. ucwords(str_replace('_', ' ', $field)),
  114. isset($update->$field) ? htmlentities($update->$field) : null
  115. );
  116. }
  117. }
  118. echo '</table>';
  119. } else {
  120. echo '<h3>No updates currently available</h3>';
  121. }
  122. }
  123. protected function getUpdateFields() {
  124. return array('version', 'download_url', 'slug',);
  125. }
  126. private function formatTimeWithDelta($unixTime) {
  127. if ( empty($unixTime) ) {
  128. return 'Never';
  129. }
  130. $delta = time() - $unixTime;
  131. $result = human_time_diff(time(), $unixTime);
  132. if ( $delta < 0 ) {
  133. $result = 'after ' . $result;
  134. } else {
  135. $result = $result . ' ago';
  136. }
  137. $result .= ' (' . $this->formatTimestamp($unixTime) . ')';
  138. return $result;
  139. }
  140. private function formatTimestamp($unixTime) {
  141. return gmdate('Y-m-d H:i:s', $unixTime + (get_option('gmt_offset') * 3600));
  142. }
  143. public function row($name, $value) {
  144. if ( is_object($value) || is_array($value) ) {
  145. //This is specifically for debugging, so print_r() is fine.
  146. //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
  147. $value = '<pre>' . htmlentities(print_r($value, true)) . '</pre>';
  148. } else if ($value === null) {
  149. $value = '<code>null</code>';
  150. }
  151. printf(
  152. '<tr><th scope="row">%1$s</th> <td>%2$s</td></tr>',
  153. esc_html($name),
  154. //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped above.
  155. $value
  156. );
  157. }
  158. }
  159. endif;