PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 4.9.2
WP STAGING – WordPress Backup, Restore, Migration & Clone v4.9.2
4.9.2 4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Backend / DashboardWidget / DashboardWidget.php
wp-staging / Backend / DashboardWidget Last commit date
DashboardWidget.php 1 month ago DashboardWidgetServiceProvider.php 1 month ago
DashboardWidget.php
174 lines
1 <?php
2
3 namespace WPStaging\Backend\DashboardWidget;
4
5 use WPStaging\Core\WPStaging;
6 use WPStaging\Framework\Language\Language;
7
8 /**
9 * Renders the WP Staging admin dashboard widget.
10 *
11 * The widget loads a curated list of WP Staging documentation articles via WordPress'
12 * built-in feed loader. The feed is cached on the site for 24 hours.
13 */
14 class DashboardWidget
15 {
16 const WIDGET_ID = 'wpstg_dashboard_widget';
17 const FEED_URL_EN = 'https://wp-staging.com/newsfeed/dashboard-en.xml';
18 const FEED_URL_DE = 'https://wp-staging.com/newsfeed/dashboard-de.xml';
19 const FEED_CACHE_SECONDS = DAY_IN_SECONDS;
20 const MAX_ARTICLES = 5;
21
22 /** @var Language */
23 private $language;
24
25 /**
26 * @param Language $language
27 */
28 public function __construct(Language $language)
29 {
30 $this->language = $language;
31 }
32
33 /**
34 * Registers the widget with WordPress.
35 *
36 * Hooked to `wp_dashboard_setup` by DashboardWidgetServiceProvider.
37 * Users can hide the widget via the standard WordPress "Screen Options" menu.
38 *
39 * @return void
40 */
41 public function register()
42 {
43 if (!current_user_can('manage_options')) {
44 return;
45 }
46
47 wp_add_dashboard_widget(
48 self::WIDGET_ID,
49 __('WP Staging — Tips & Guides', 'wp-staging'),
50 [$this, 'render']
51 );
52 }
53
54 /**
55 * Outputs the widget body. Called by WordPress when rendering the dashboard.
56 *
57 * @return void
58 */
59 public function render()
60 {
61 $items = $this->fetchArticles();
62
63 if (empty($items)) {
64 $this->renderEmptyState();
65 return;
66 }
67
68 $this->renderArticles($items);
69 }
70
71 /**
72 * Fetches the curated documentation feed and returns the parsed items.
73 *
74 * @return array<int, array{title:string, link:string, summary:string}>
75 */
76 private function fetchArticles()
77 {
78 add_filter('wp_feed_cache_transient_lifetime', [$this, 'feedCacheLifetime'], 10, 1);
79 $feed = fetch_feed($this->getFeedUrl());
80 remove_filter('wp_feed_cache_transient_lifetime', [$this, 'feedCacheLifetime'], 10);
81
82 if (is_wp_error($feed) || !is_object($feed)) {
83 return [];
84 }
85
86 $maxItems = $feed->get_item_quantity(self::MAX_ARTICLES);
87 $rssItems = $feed->get_items(0, $maxItems);
88
89 $articles = [];
90 foreach ($rssItems as $item) {
91 $title = (string)$item->get_title();
92 $link = (string)$item->get_permalink();
93 if ($title === '' || $link === '') {
94 continue;
95 }
96
97 $articles[] = [
98 'title' => $title,
99 'link' => $link,
100 'summary' => wp_trim_words((string)$item->get_description(), 18, '&hellip;'),
101 ];
102 }
103
104 return $articles;
105 }
106
107 /**
108 * Returns the feed URL for the current admin locale, with plugin version and
109 * multisite query parameters appended for access-log segmentation.
110 *
111 * @return string
112 */
113 private function getFeedUrl()
114 {
115 $baseUrl = $this->language->getLocaleLanguageCode() === 'de' ? self::FEED_URL_DE : self::FEED_URL_EN;
116 $version = defined('WPSTGPRO_VERSION') ? WPSTGPRO_VERSION : (defined('WPSTG_VERSION') ? WPSTG_VERSION : '');
117 $edition = WPStaging::isBasic() ? 'free' : 'pro';
118
119 return add_query_arg(
120 [
121 'v' => $version,
122 'e' => $edition,
123 'ms' => is_multisite() ? '1' : '0',
124 ],
125 $baseUrl
126 );
127 }
128
129 /**
130 * Filter callback that overrides the default 12h SimplePie transient lifetime.
131 *
132 * @param int $seconds Default lifetime in seconds passed by WordPress.
133 * @return int
134 */
135 public function feedCacheLifetime($seconds)
136 {
137 return self::FEED_CACHE_SECONDS;
138 }
139
140 /**
141 * @return void
142 */
143 private function renderEmptyState()
144 {
145 ?>
146 <p><?php echo esc_html__('Documentation links will appear here as soon as the feed is available.', 'wp-staging'); ?></p>
147 <?php
148 }
149
150 /**
151 * @param array<int, array{title:string, link:string, summary:string}> $items
152 * @return void
153 */
154 private function renderArticles(array $items)
155 {
156 ?>
157 <ul class="wpstg-dashboard-widget-list">
158 <?php foreach ($items as $item) : ?>
159 <li style="margin-bottom:10px;">
160 <a href="<?php echo esc_url($item['link']); ?>" target="_blank" rel="noopener noreferrer">
161 <strong><?php echo esc_html($item['title']); ?></strong>
162 </a>
163 <?php if ($item['summary'] !== '') : ?>
164 <div style="color:#646970;font-size:12px;margin-top:2px;">
165 <?php echo esc_html($item['summary']); ?>
166 </div>
167 <?php endif; ?>
168 </li>
169 <?php endforeach; ?>
170 </ul>
171 <?php
172 }
173 }
174