rtMedia for WordPress, BuddyPress and bbPress - Version 2.5.2

Version Description

  • Fixes warning on admin side.
Download this release

Release Info

Developer saurabhshukla
Plugin Icon 128x128 rtMedia for WordPress, BuddyPress and bbPress
Version 2.5.2
Comparing to
See all releases

Code changes from version 2.5.1 to 2.5.2

Files changed (35) hide show
  1. app/admin/BPMediaAdmin.php +164 -136
  2. app/helper/BPMediaAddon.php +5 -0
  3. app/helper/BPMediaAdminWidget.php +7 -0
  4. app/helper/BPMediaFeed.php +5 -0
  5. app/helper/BPMediaLog.php +71 -50
  6. app/helper/BPMediaSettings.php +69 -15
  7. app/helper/BPMediaSupport.php +9 -0
  8. app/helper/BPMediaUpgrade.php +24 -8
  9. app/helper/rtPluginInfo.php +114 -106
  10. app/helper/rtPluginUpdate.php +121 -89
  11. app/helper/rtPluginUpdateChecker.php +655 -558
  12. app/main/BPMediaLoader.php +112 -96
  13. app/main/BuddyPressMedia.php +35 -7
  14. app/main/group/BPMediaGroup.php +52 -10
  15. app/main/group/BPMediaGroupAction.php +31 -3
  16. app/main/group/BPMediaGroupElementExtension.php +20 -4
  17. app/main/group/BPMediaGroupsExtension.php +35 -4
  18. app/main/group/dummy/BPMediaGroupAlbum.php +10 -7
  19. app/main/includes/BPMediaActions.php +93 -3
  20. app/main/includes/BPMediaComponent.php +353 -339
  21. app/main/includes/BPMediaFilters.php +75 -3
  22. app/main/includes/BPMediaFunction.php +54 -1
  23. app/main/includes/BPMediaHostWordpress.php +194 -28
  24. app/main/includes/BPMediaTemplateFunctions.php +36 -7
  25. app/main/includes/BPMediaUpgradeScript.php +10 -3
  26. app/main/profile/BPMediaAlbum.php +328 -259
  27. app/main/profile/BPMediaAlbumScreen.php +182 -136
  28. app/main/profile/BPMediaScreen.php +440 -398
  29. app/main/profile/BPMediaTemplate.php +241 -206
  30. app/main/profile/BPMediaUploadScreen.php +125 -115
  31. app/main/widgets/BPMediaPopularMedia.php +21 -6
  32. app/main/widgets/BPMediaRecentMedia.php +23 -8
  33. app/main/widgets/BPMediaWidget.php +41 -26
  34. index.php +1 -1
  35. readme.txt +6 -3
app/admin/BPMediaAdmin.php CHANGED
@@ -41,6 +41,11 @@ if (!class_exists('BPMediaAdmin')) {
41
*
42
* @param string $hook
43
*/
44
public function ui($hook) {
45
$admin_ajax = admin_url('admin-ajax.php');
46
wp_enqueue_script('bp-media-admin', BP_MEDIA_URL . 'app/assets/js/admin.js');
@@ -81,6 +86,10 @@ if (!class_exists('BPMediaAdmin')) {
81
$this->render_page('bp-media-support');
82
}
83
84
static function get_current_tab() {
85
return isset($_GET['page']) ? $_GET['page'] : "bp-media-settings";
86
}
@@ -90,6 +99,12 @@ if (!class_exists('BPMediaAdmin')) {
90
*
91
* @global string BP_MEDIA_TXT_DOMAIN
92
*/
93
public function render_page($page, $option_group = NULL) {
94
?>
95
@@ -99,7 +114,7 @@ if (!class_exists('BPMediaAdmin')) {
99
<?php settings_errors(); ?>
100
<div class="columns-2">
101
<h3 class="bp-media-settings-tabs"><?php
102
- $this->sub_tabs();
103
?>
104
</h3>
105
@@ -126,85 +141,90 @@ if (!class_exists('BPMediaAdmin')) {
126
</div>
127
</div><!-- .metabox-holder -->
128
</div><!-- .bp-media-admin --><?php
129
- }
130
-
131
- /**
132
- * Adds a tab for Media settings in the BuddyPress settings page
133
- *
134
- * @global type $bp_media
135
- */
136
- public function tab() {
137
-
138
- $tabs_html = '';
139
- $idle_class = 'nav-tab';
140
- $active_class = 'nav-tab nav-tab-active';
141
- $tabs = array();
142
-
143
- // Check to see which tab we are on
144
- $tab = $this->get_current_tab();
145
- /* BuddyPress Media */
146
- $tabs[] = array(
147
- 'href' => bp_get_admin_url(add_query_arg(array('page' => 'bp-media-settings'), 'admin.php')),
148
- 'title' => __('BuddyPress Media', BP_MEDIA_TXT_DOMAIN),
149
- 'name' => __('BuddyPress Media', BP_MEDIA_TXT_DOMAIN),
150
- 'class' => ($tab == 'bp-media-settings' || $tab == 'bp-media-addons' || $tab == 'bp-media-support') ? $active_class : $idle_class
151
- );
152
-
153
- foreach ($tabs as $tab) {
154
- $tabs_html.= '<a id="bp-media" title= "' . $tab['title'] . '" href="' . $tab['href'] . '" class="' . $tab['class'] . '">' . $tab['name'] . '</a>';
155
- }
156
- echo $tabs_html;
157
- }
158
-
159
- /**
160
- * Adds a sub tabs to the BuddyPress Media settings page
161
- *
162
- * @global type $bp_media
163
- */
164
- public function sub_tabs() {
165
- $tabs_html = '';
166
- $idle_class = 'nav-tab';
167
- $active_class = 'nav-tab nav-tab-active';
168
- $tabs = array();
169
-
170
- // Check to see which tab we are on
171
- $tab = $this->get_current_tab();
172
- /* BuddyPress Media */
173
- $tabs[] = array(
174
- 'href' => bp_get_admin_url(add_query_arg(array('page' => 'bp-media-settings'), 'admin.php')),
175
- 'title' => __('BuddyPress Media Settings', BP_MEDIA_TXT_DOMAIN),
176
- 'name' => __('Settings', BP_MEDIA_TXT_DOMAIN),
177
- 'class' => ($tab == 'bp-media-settings') ? $active_class : $idle_class . ' first_tab'
178
- );
179
-
180
- $tabs[] = array(
181
- 'href' => bp_get_admin_url(add_query_arg(array('page' => 'bp-media-addons'), 'admin.php')),
182
- 'title' => __('BuddyPress Media Addons', BP_MEDIA_TXT_DOMAIN),
183
- 'name' => __('Addons', BP_MEDIA_TXT_DOMAIN),
184
- 'class' => ($tab == 'bp-media-addons') ? $active_class : $idle_class
185
- );
186
-
187
- $tabs[] = array(
188
- 'href' => bp_get_admin_url(add_query_arg(array('page' => 'bp-media-support'), 'admin.php')),
189
- 'title' => __('BuddyPress Media Support', BP_MEDIA_TXT_DOMAIN),
190
- 'name' => __('Support', BP_MEDIA_TXT_DOMAIN),
191
- 'class' => ($tab == 'bp-media-support') ? $active_class : $idle_class . ' last_tab'
192
- );
193
- $tabs = apply_filters('bp_media_add_sub_tabs', $tabs, $tab);
194
- foreach ($tabs as $tab) {
195
- $tabs_html.= '<a title="' . $tab['title'] . '" href="' . $tab['href'] . '" class="' . $tab['class'] . '">' . $tab['name'] . '</a>';
196
- }
197
- echo $tabs_html;
198
- }
199
-
200
- /*
201
- * Updates the media count of all users.
202
- */
203
-
204
- public function update_count() {
205
- global $wpdb;
206
- $query =
207
- "SELECT
208
post_author,
209
SUM(CASE WHEN post_mime_type LIKE 'image%' THEN 1 ELSE 0 END) as Images,
210
SUM(CASE WHEN post_mime_type LIKE 'audio%' THEN 1 ELSE 0 END) as Audio,
@@ -218,82 +238,90 @@ if (!class_exists('BPMediaAdmin')) {
218
`meta_value` > 0 AND
219
( post_mime_type LIKE 'image%' OR post_mime_type LIKE 'audio%' OR post_mime_type LIKE 'video%' OR post_type LIKE 'bp_media_album')
220
GROUP BY post_author";
221
- $result = $wpdb->get_results($query);
222
- if (!is_array($result))
223
- return false;
224
-
225
- foreach ($result as $obj) {
226
-
227
- $count = array(
228
- 'images' => isset($obj->Images) ? $obj->Images : 0,
229
- 'videos' => isset($obj->Videos) ? $obj->Videos : 0,
230
- 'audio' => isset($obj->Audio) ? $obj->Audio : 0,
231
- 'albums' => isset($obj->Albums) ? $obj->Albums : 0
232
- );
233
- bp_update_user_meta($obj->post_author, 'bp_media_count', $count);
234
- }
235
- return true;
236
- }
237
-
238
- /* Multisite Save Options - http://wordpress.stackexchange.com/questions/64968/settings-api-in-multisite-missing-update-message#answer-72503 */
239
-
240
- public function save_multisite_options() {
241
- global $bp_media_admin;
242
- if (isset($_POST['refresh-count'])) {
243
- $bp_media_admin->update_count();
244
- }
245
- do_action('bp_media_sanitize_settings', $_POST);
246
-
247
- if (isset($_POST['bp_media_options'])) {
248
- bp_update_option('bp_media_options', $_POST['bp_media_options']);
249
-
250
- // redirect to settings page in network
251
- wp_redirect(
252
- add_query_arg(
253
- array('page' => 'bp-media-settings', 'updated' => 'true'), (is_multisite() ? network_admin_url('admin.php') : admin_url('admin.php'))
254
- )
255
- );
256
- exit;
257
- }
258
- }
259
-
260
- /* Admin Sidebar */
261
-
262
- public function admin_sidebar() {
263
- global $bp_media;
264
- $branding = '<a href="http://rtcamp.com" title="' . __('Empowering The Web With WordPress', BP_MEDIA_TXT_DOMAIN) . '" id="logo"><img src="' . BP_MEDIA_URL . 'app/assets/img/rtcamp-logo.png" alt="' . __('rtCamp', BP_MEDIA_TXT_DOMAIN) . '" /></a>
265
<ul id="social">
266
<li><a href="' . sprintf('%s', 'http://www.facebook.com/rtCamp.solutions/') . '" title="' . __('Become a fan on Facebook', BP_MEDIA_TXT_DOMAIN) . '" class="bp-media-facebook bp-media-social">' . __('Facebook', BP_MEDIA_TXT_DOMAIN) . '</a></li>
267
<li><a href="' . sprintf('%s', 'https://twitter.com/rtcamp/') . '" title="' . __('Follow us on Twitter', BP_MEDIA_TXT_DOMAIN) . '" class="bp-media-twitter bp-media-social">' . __('Twitter', BP_MEDIA_TXT_DOMAIN) . '</a></li>
268
<li><a href="' . sprintf('%s', 'http://feeds.feedburner.com/rtcamp/') . '" title="' . __('Subscribe to our feeds', BP_MEDIA_TXT_DOMAIN) . '" class="bp-media-rss bp-media-social">' . __('RSS Feed', BP_MEDIA_TXT_DOMAIN) . '</a></li>
269
</ul>';
270
- new BPMediaAdminWidget('branding', '', $branding);
271
272
- $support = '<p><ul>
273
<li>' . sprintf('<a href="%s">' . __("Read FAQ", BP_MEDIA_TXT_DOMAIN) . '</a>', 'http://rtcamp.com/buddypress-media/faq/') . '</li>
274
<li>' . sprintf('<a href="%s">' . __("Free Support Forum", BP_MEDIA_TXT_DOMAIN) . '</a>', $bp_media->support_url) . '</li>
275
<li>' . sprintf('<a href="%s">' . __("Github Issue Tracker", BP_MEDIA_TXT_DOMAIN) . '</a>', 'https://github.com/rtCamp/buddypress-media/issues/') . '</li>
276
<li>' . sprintf('<a href="%s">' . __("Hire Us!", BP_MEDIA_TXT_DOMAIN) . '</a> ' . __("To get professional customisation/setup service.", BP_MEDIA_TXT_DOMAIN), 'http://rtcamp.com/buddypress-media/hire/') . '</li>
277
</ul></p>';
278
- new BPMediaAdminWidget('support', __('Need Help?', BP_MEDIA_TXT_DOMAIN), $support);
279
280
- $donate = '<span><a href="http://rtcamp.com/donate/" title="' . __('Help the development keep going.', BP_MEDIA_TXT_DOMAIN) . '"><img class="bp-media-donation-image" src ="' . BP_MEDIA_URL . 'app/assets/img/donate.gif" /></a></span>
281
<p>' . sprintf(__('Help us release more amazing features faster. Consider making a donation to our consistent efforts.', BP_MEDIA_TXT_DOMAIN)) . '</p>';
282
- new BPMediaAdminWidget('donate', __('Donate', BP_MEDIA_TXT_DOMAIN), $donate);
283
284
- $addons = '<ul>
285
<li><a href="http://rtcamp.com/store/buddypress-media-kaltura/" title="' . __('BuddyPress Media Kaltura', BP_MEDIA_TXT_DOMAIN) . '">' . __('BPM-Kaltura', BP_MEDIA_TXT_DOMAIN) . '</a> - ' . __('Add support for Kaltura.com/Kaltura-CE based video conversion support', BP_MEDIA_TXT_DOMAIN) . '</li>
286
<li><a href="http://rtcamp.com/store/buddy-press-media-ffmpeg/" title="' . __('BuddyPress Media FFMPEG', BP_MEDIA_TXT_DOMAIN) . '">' . __('BPM-FFMPEG', BP_MEDIA_TXT_DOMAIN) . '</a> - ' . __('Add FFMEG-based audio/video conversion support', BP_MEDIA_TXT_DOMAIN) . '</li>
287
</ul>
288
<h4>' . sprintf(__('Are you a developer?', BP_MEDIA_TXT_DOMAIN)) . '</h4>
289
<p>' . sprintf(__('If you are developing a BuddyPress Media addon we would like to include it in above list. We can also help you sell them. <a href="%s">More info!</a>', BP_MEDIA_TXT_DOMAIN), 'http://rtcamp.com/contact/') . '</p></h4>';
290
- new BPMediaAdminWidget('premium-addons', __('Premium Addons', BP_MEDIA_TXT_DOMAIN), $addons);
291
292
- $news = '<img src ="' . admin_url('/images/wpspin_light.gif') . '" /> Loading...';
293
- new BPMediaAdminWidget('latest-news', __('Latest News', BP_MEDIA_TXT_DOMAIN), $news);
294
- }
295
296
- }
297
298
- }
299
?>
41
*
42
* @param string $hook
43
*/
44
+
45
+ /**
46
+ *
47
+ * @param type $hook
48
+ */
49
public function ui($hook) {
50
$admin_ajax = admin_url('admin-ajax.php');
51
wp_enqueue_script('bp-media-admin', BP_MEDIA_URL . 'app/assets/js/admin.js');
86
$this->render_page('bp-media-support');
87
}
88
89
+ /**
90
+ *
91
+ * @return type
92
+ */
93
static function get_current_tab() {
94
return isset($_GET['page']) ? $_GET['page'] : "bp-media-settings";
95
}
99
*
100
* @global string BP_MEDIA_TXT_DOMAIN
101
*/
102
+
103
+ /**
104
+ *
105
+ * @param type $page
106
+ * @param type $option_group
107
+ */
108
public function render_page($page, $option_group = NULL) {
109
?>
110
114
<?php settings_errors(); ?>
115
<div class="columns-2">
116
<h3 class="bp-media-settings-tabs"><?php
117
+ $this->sub_tabs();
118
?>
119
</h3>
120
141
</div>
142
</div><!-- .metabox-holder -->
143
</div><!-- .bp-media-admin --><?php
144
+ }
145
+
146
+ /**
147
+ * Adds a tab for Media settings in the BuddyPress settings page
148
+ *
149
+ * @global type $bp_media
150
+ */
151
+ public function tab() {
152
+
153
+ $tabs_html = '';
154
+ $idle_class = 'nav-tab';
155
+ $active_class = 'nav-tab nav-tab-active';
156
+ $tabs = array();
157
+
158
+ // Check to see which tab we are on
159
+ $tab = $this->get_current_tab();
160
+ /* BuddyPress Media */
161
+ $tabs[] = array(
162
+ 'href' => bp_get_admin_url(add_query_arg(array('page' => 'bp-media-settings'), 'admin.php')),
163
+ 'title' => __('BuddyPress Media', BP_MEDIA_TXT_DOMAIN),
164
+ 'name' => __('BuddyPress Media', BP_MEDIA_TXT_DOMAIN),
165
+ 'class' => ($tab == 'bp-media-settings' || $tab == 'bp-media-addons' || $tab == 'bp-media-support') ? $active_class : $idle_class
166
+ );
167
+
168
+ foreach ($tabs as $tab) {
169
+ $tabs_html.= '<a id="bp-media" title= "' . $tab['title'] . '" href="' . $tab['href'] . '" class="' . $tab['class'] . '">' . $tab['name'] . '</a>';
170
+ }
171
+ echo $tabs_html;
172
+ }
173
+
174
+ /**
175
+ * Adds a sub tabs to the BuddyPress Media settings page
176
+ *
177
+ * @global type $bp_media
178
+ */
179
+ public function sub_tabs() {
180
+ $tabs_html = '';
181
+ $idle_class = 'nav-tab';
182
+ $active_class = 'nav-tab nav-tab-active';
183
+ $tabs = array();
184
+
185
+ // Check to see which tab we are on
186
+ $tab = $this->get_current_tab();
187
+ /* BuddyPress Media */
188
+ $tabs[] = array(
189
+ 'href' => bp_get_admin_url(add_query_arg(array('page' => 'bp-media-settings'), 'admin.php')),
190
+ 'title' => __('BuddyPress Media Settings', BP_MEDIA_TXT_DOMAIN),
191
+ 'name' => __('Settings', BP_MEDIA_TXT_DOMAIN),
192
+ 'class' => ($tab == 'bp-media-settings') ? $active_class : $idle_class . ' first_tab'
193
+ );
194
+
195
+ $tabs[] = array(
196
+ 'href' => bp_get_admin_url(add_query_arg(array('page' => 'bp-media-addons'), 'admin.php')),
197
+ 'title' => __('BuddyPress Media Addons', BP_MEDIA_TXT_DOMAIN),
198
+ 'name' => __('Addons', BP_MEDIA_TXT_DOMAIN),
199
+ 'class' => ($tab == 'bp-media-addons') ? $active_class : $idle_class
200
+ );
201
+
202
+ $tabs[] = array(
203
+ 'href' => bp_get_admin_url(add_query_arg(array('page' => 'bp-media-support'), 'admin.php')),
204
+ 'title' => __('BuddyPress Media Support', BP_MEDIA_TXT_DOMAIN),
205
+ 'name' => __('Support', BP_MEDIA_TXT_DOMAIN),
206
+ 'class' => ($tab == 'bp-media-support') ? $active_class : $idle_class . ' last_tab'
207
+ );
208
+ $tabs = apply_filters('bp_media_add_sub_tabs', $tabs, $tab);
209
+ foreach ($tabs as $tab) {
210
+ $tabs_html.= '<a title="' . $tab['title'] . '" href="' . $tab['href'] . '" class="' . $tab['class'] . '">' . $tab['name'] . '</a>';
211
+ }
212
+ echo $tabs_html;
213
+ }
214
+
215
+ /*
216
+ * Updates the media count of all users.
217
+ */
218
+
219
+ /**
220
+ *
221
+ * @global type $wpdb
222
+ * @return boolean
223
+ */
224
+ public function update_count() {
225
+ global $wpdb;
226
+ $query =
227
+ "SELECT
228
post_author,
229
SUM(CASE WHEN post_mime_type LIKE 'image%' THEN 1 ELSE 0 END) as Images,
230
SUM(CASE WHEN post_mime_type LIKE 'audio%' THEN 1 ELSE 0 END) as Audio,
238
`meta_value` > 0 AND
239
( post_mime_type LIKE 'image%' OR post_mime_type LIKE 'audio%' OR post_mime_type LIKE 'video%' OR post_type LIKE 'bp_media_album')
240
GROUP BY post_author";
241
+ $result = $wpdb->get_results($query);
242
+ if (!is_array($result))
243
+ return false;
244
+
245
+ foreach ($result as $obj) {
246
+
247
+ $count = array(
248
+ 'images' => isset($obj->Images) ? $obj->Images : 0,
249
+ 'videos' => isset($obj->Videos) ? $obj->Videos : 0,
250
+ 'audio' => isset($obj->Audio) ? $obj->Audio : 0,
251
+ 'albums' => isset($obj->Albums) ? $obj->Albums : 0
252
+ );
253
+ bp_update_user_meta($obj->post_author, 'bp_media_count', $count);
254
+ }
255
+ return true;
256
+ }
257
+
258
+ /* Multisite Save Options - http://wordpress.stackexchange.com/questions/64968/settings-api-in-multisite-missing-update-message#answer-72503 */
259
+
260
+ /**
261
+ *
262
+ * @global type $bp_media_admin
263
+ */
264
+ public function save_multisite_options() {
265
+ global $bp_media_admin;
266
+ if (isset($_POST['refresh-count'])) {
267
+ $bp_media_admin->update_count();
268
+ }
269
+ do_action('bp_media_sanitize_settings', $_POST);
270
+
271
+ if (isset($_POST['bp_media_options'])) {
272
+ bp_update_option('bp_media_options', $_POST['bp_media_options']);
273
+
274
+ // redirect to settings page in network
275
+ wp_redirect(
276
+ add_query_arg(
277
+ array('page' => 'bp-media-settings', 'updated' => 'true'), (is_multisite() ? network_admin_url('admin.php') : admin_url('admin.php'))
278
+ )
279
+ );
280
+ exit;
281
+ }
282
+ }
283
+
284
+ /* Admin Sidebar */
285
+
286
+ /**
287
+ *
288
+ * @global type $bp_media
289
+ */
290
+ public function admin_sidebar() {
291
+ global $bp_media;
292
+ $branding = '<a href="http://rtcamp.com" title="' . __('Empowering The Web With WordPress', BP_MEDIA_TXT_DOMAIN) . '" id="logo"><img src="' . BP_MEDIA_URL . 'app/assets/img/rtcamp-logo.png" alt="' . __('rtCamp', BP_MEDIA_TXT_DOMAIN) . '" /></a>
293
<ul id="social">
294
<li><a href="' . sprintf('%s', 'http://www.facebook.com/rtCamp.solutions/') . '" title="' . __('Become a fan on Facebook', BP_MEDIA_TXT_DOMAIN) . '" class="bp-media-facebook bp-media-social">' . __('Facebook', BP_MEDIA_TXT_DOMAIN) . '</a></li>
295
<li><a href="' . sprintf('%s', 'https://twitter.com/rtcamp/') . '" title="' . __('Follow us on Twitter', BP_MEDIA_TXT_DOMAIN) . '" class="bp-media-twitter bp-media-social">' . __('Twitter', BP_MEDIA_TXT_DOMAIN) . '</a></li>
296
<li><a href="' . sprintf('%s', 'http://feeds.feedburner.com/rtcamp/') . '" title="' . __('Subscribe to our feeds', BP_MEDIA_TXT_DOMAIN) . '" class="bp-media-rss bp-media-social">' . __('RSS Feed', BP_MEDIA_TXT_DOMAIN) . '</a></li>
297
</ul>';
298
+ new BPMediaAdminWidget('branding', '', $branding);
299
300
+ $support = '<p><ul>
301
<li>' . sprintf('<a href="%s">' . __("Read FAQ", BP_MEDIA_TXT_DOMAIN) . '</a>', 'http://rtcamp.com/buddypress-media/faq/') . '</li>
302
<li>' . sprintf('<a href="%s">' . __("Free Support Forum", BP_MEDIA_TXT_DOMAIN) . '</a>', $bp_media->support_url) . '</li>
303
<li>' . sprintf('<a href="%s">' . __("Github Issue Tracker", BP_MEDIA_TXT_DOMAIN) . '</a>', 'https://github.com/rtCamp/buddypress-media/issues/') . '</li>
304
<li>' . sprintf('<a href="%s">' . __("Hire Us!", BP_MEDIA_TXT_DOMAIN) . '</a> ' . __("To get professional customisation/setup service.", BP_MEDIA_TXT_DOMAIN), 'http://rtcamp.com/buddypress-media/hire/') . '</li>
305
</ul></p>';
306
+ new BPMediaAdminWidget('support', __('Need Help?', BP_MEDIA_TXT_DOMAIN), $support);
307
308
+ $donate = '<span><a href="http://rtcamp.com/donate/" title="' . __('Help the development keep going.', BP_MEDIA_TXT_DOMAIN) . '"><img class="bp-media-donation-image" src ="' . BP_MEDIA_URL . 'app/assets/img/donate.gif" /></a></span>
309
<p>' . sprintf(__('Help us release more amazing features faster. Consider making a donation to our consistent efforts.', BP_MEDIA_TXT_DOMAIN)) . '</p>';
310
+ new BPMediaAdminWidget('donate', __('Donate', BP_MEDIA_TXT_DOMAIN), $donate);
311
312
+ $addons = '<ul>
313
<li><a href="http://rtcamp.com/store/buddypress-media-kaltura/" title="' . __('BuddyPress Media Kaltura', BP_MEDIA_TXT_DOMAIN) . '">' . __('BPM-Kaltura', BP_MEDIA_TXT_DOMAIN) . '</a> - ' . __('Add support for Kaltura.com/Kaltura-CE based video conversion support', BP_MEDIA_TXT_DOMAIN) . '</li>
314
<li><a href="http://rtcamp.com/store/buddy-press-media-ffmpeg/" title="' . __('BuddyPress Media FFMPEG', BP_MEDIA_TXT_DOMAIN) . '">' . __('BPM-FFMPEG', BP_MEDIA_TXT_DOMAIN) . '</a> - ' . __('Add FFMEG-based audio/video conversion support', BP_MEDIA_TXT_DOMAIN) . '</li>
315
</ul>
316
<h4>' . sprintf(__('Are you a developer?', BP_MEDIA_TXT_DOMAIN)) . '</h4>
317
<p>' . sprintf(__('If you are developing a BuddyPress Media addon we would like to include it in above list. We can also help you sell them. <a href="%s">More info!</a>', BP_MEDIA_TXT_DOMAIN), 'http://rtcamp.com/contact/') . '</p></h4>';
318
+ new BPMediaAdminWidget('premium-addons', __('Premium Addons', BP_MEDIA_TXT_DOMAIN), $addons);
319
320
+ $news = '<img src ="' . admin_url('/images/wpspin_light.gif') . '" /> Loading...';
321
+ new BPMediaAdminWidget('latest-news', __('Latest News', BP_MEDIA_TXT_DOMAIN), $news);
322
+ }
323
324
+ }
325
326
+ }
327
?>
app/helper/BPMediaAddon.php CHANGED
@@ -52,6 +52,11 @@ if (!class_exists('BPMediaAddon')) {
52
}
53
}
54
55
public function addon($args) {
56
global $bp_media;
57
52
}
53
}
54
55
+ /**
56
+ *
57
+ * @global type $bp_media
58
+ * @param type $args
59
+ */
60
public function addon($args) {
61
global $bp_media;
62
app/helper/BPMediaAdminWidget.php CHANGED
@@ -9,6 +9,13 @@ if (!class_exists('BPMediaAdminWidget')) {
9
10
class BPMediaAdminWidget {
11
12
public function __construct($id = NULL, $title = NULL, $content = NULL) {
13
global $bp_media;
14
if ($id) {
9
10
class BPMediaAdminWidget {
11
12
+ /**
13
+ *
14
+ * @global type $bp_media
15
+ * @param type $id
16
+ * @param type $title
17
+ * @param type $content
18
+ */
19
public function __construct($id = NULL, $title = NULL, $content = NULL) {
20
global $bp_media;
21
if ($id) {
app/helper/BPMediaFeed.php CHANGED
@@ -18,6 +18,11 @@ class BPMediaFeed {
18
/**
19
* Get BuddyPress Media Feed from rtCamp.com
20
*/
21
public function fetch_feed() {
22
global $bp_media;
23
// Get RSS Feed(s)
18
/**
19
* Get BuddyPress Media Feed from rtCamp.com
20
*/
21
+
22
+ /**
23
+ *
24
+ * @global type $bp_media
25
+ */
26
public function fetch_feed() {
27
global $bp_media;
28
// Get RSS Feed(s)
app/helper/BPMediaLog.php CHANGED
@@ -5,61 +5,82 @@
5
*
6
* @author Saurabh Shukla <saurabh.shukla@rtcamp.com>
7
*/
8
- if ( ! class_exists( 'BPMediaLog' ) ) {
9
10
- class BPMediaLog {
11
12
- /**
13
- * Formats and logs the error message
14
- *
15
- * @param any $msg The message to log
16
- * @param string $context The context string, optional
17
- * @return boolean True if successful
18
- */
19
- public function __construct( $msg, $context = '', $log_file = '' ) {
20
- $log_msg = $this->log_msg( $msg, $context = '' );
21
- if ($log_file == ''){
22
- $log_file = BP_MEDIA_PATH.'log/bpmedia.log';
23
- }
24
- return $this->log( $log_msg, $log_file );
25
- }
26
27
- /**
28
- * Formats the message
29
- *
30
- * @param any $msg The message to format
31
- * @param string $context The context string, optional
32
- * @return string The formatted log entry
33
- */
34
- function log_msg( $msg, $context = '' ) {
35
- $logmsg = gmdate( "Y-m-d H:i:s " ) . " | ";
36
- if ( $context ) {
37
- $logmsg .= $context . " | ";
38
- }
39
- if ( ! is_string( $msg ) ) {
40
- $msg = var_export( $msg, false );
41
- }
42
- $logmsg .= $msg;
43
- return $logmsg;
44
- }
45
46
- /**
47
- * Logs the entry to the log file
48
- *
49
- * @param string $logmsg The formatted log entry
50
- * @param string $file The log file's path
51
- * @return boolean Success
52
- */
53
- public function log( $logmsg, $file ) {
54
- $fp = fopen( BP_MEDIA_PATH . 'plugin.log', "a+" );
55
- if ( $fp ) {
56
- fwrite( $fp, "\n" . $logmsg );
57
- fclose( $fp );
58
- }
59
- return true;
60
- }
61
62
- }
63
64
}
65
?>
5
*
6
* @author Saurabh Shukla <saurabh.shukla@rtcamp.com>
7
*/
8
+ if (!class_exists('BPMediaLog')) {
9
10
+ class BPMediaLog {
11
+ /**
12
+ * Formats and logs the error message
13
+ *
14
+ * @param any $msg The message to log
15
+ * @param string $context The context string, optional
16
+ * @return boolean True if successful
17
+ */
18
19
+ /**
20
+ *
21
+ * @param type $msg
22
+ * @param string $context
23
+ * @param string $log_file
24
+ * @return type
25
+ */
26
+ public function __construct($msg, $context = '', $log_file = '') {
27
+ $log_msg = $this->log_msg($msg, $context = '');
28
+ if ($log_file == '') {
29
+ $log_file = BP_MEDIA_PATH . 'log/bpmedia.log';
30
+ }
31
+ return $this->log($log_msg, $log_file);
32
+ }
33
34
+ /**
35
+ * Formats the message
36
+ *
37
+ * @param any $msg The message to format
38
+ * @param string $context The context string, optional
39
+ * @return string The formatted log entry
40
+ */
41
42
+ /**
43
+ *
44
+ * @param type $msg
45
+ * @param type $context
46
+ * @return type
47
+ */
48
+ function log_msg($msg, $context = '') {
49
+ $logmsg = gmdate("Y-m-d H:i:s ") . " | ";
50
+ if ($context) {
51
+ $logmsg .= $context . " | ";
52
+ }
53
+ if (!is_string($msg)) {
54
+ $msg = var_export($msg, false);
55
+ }
56
+ $logmsg .= $msg;
57
+ return $logmsg;
58
+ }
59
60
+ /**
61
+ * Logs the entry to the log file
62
+ *
63
+ * @param string $logmsg The formatted log entry
64
+ * @param string $file The log file's path
65
+ * @return boolean Success
66
+ */
67
+
68
+ /**
69
+ *
70
+ * @param type $logmsg
71
+ * @param type $file
72
+ * @return boolean
73
+ */
74
+ public function log($logmsg, $file) {
75
+ $fp = fopen(BP_MEDIA_PATH . 'plugin.log', "a+");
76
+ if ($fp) {
77
+ fwrite($fp, "\n" . $logmsg);
78
+ fclose($fp);
79
+ }
80
+ return true;
81
+ }
82
+
83
+ }
84
85
}
86
?>
app/helper/BPMediaSettings.php CHANGED
@@ -15,9 +15,14 @@ if (!class_exists('BPMediaSettings')) {
15
16
/**
17
* Register Settings
18
- *
19
* @global string BP_MEDIA_TXT_DOMAIN
20
*/
21
public function settings() {
22
global $bp_media_addon;
23
add_settings_section('bpm-settings', __('BuddyPress Media Settings', BP_MEDIA_TXT_DOMAIN), is_multisite() ? array($this, 'network_notices') : '', 'bp-media-settings');
@@ -56,6 +61,15 @@ if (!class_exists('BPMediaSettings')) {
56
'name' => __('Re-Count', BP_MEDIA_TXT_DOMAIN),
57
'desc' => __('It will re-count all media entries of all users and correct any discrepancies.', BP_MEDIA_TXT_DOMAIN)
58
));
59
$bp_media_addon = new BPMediaAddon();
60
add_settings_section('bpm-addons', __('BuddyPress Media Addons for Audio/Video Conversion', BP_MEDIA_TXT_DOMAIN), array($bp_media_addon, 'get_addons'), 'bp-media-addons');
61
add_settings_section('bpm-support', __('Submit a request form', BP_MEDIA_TXT_DOMAIN), '', 'bp-media-support');
@@ -84,6 +98,13 @@ if (!class_exists('BPMediaSettings')) {
84
/**
85
* Sanitizes the settings
86
*/
87
public function sanitize($input) {
88
global $bp_media_admin;
89
if (isset($_POST['refresh-count'])) {
@@ -107,10 +128,17 @@ if (!class_exists('BPMediaSettings')) {
107
108
/**
109
* Output a checkbox
110
- *
111
* @global array $bp_media
112
* @param array $args
113
*/
114
public function checkbox($args) {
115
global $bp_media;
116
$options = $bp_media->options;
@@ -137,16 +165,23 @@ if (!class_exists('BPMediaSettings')) {
137
?>
138
<label for="<?php echo $option; ?>">
139
<input<?php checked($options[$option]); ?> name="<?php echo $name; ?>" id="<?php echo $option; ?>" value="1" type="checkbox" />
140
- <?php echo $desc; ?>
141
</label><?php
142
}
143
144
/**
145
* Outputs Radio Buttons
146
- *
147
* @global array $bp_media
148
* @param array $args
149
*/
150
public function radio($args) {
151
global $bp_media;
152
$options = $bp_media->options;
@@ -177,17 +212,24 @@ if (!class_exists('BPMediaSettings')) {
177
}
178
179
foreach ($radios as $value => $desc) {
180
- ?>
181
<label for="<?php echo sanitize_title($desc); ?>"><input<?php checked($options[$option], $value); ?> value="<?php echo $value; ?>" name="<?php echo $name; ?>" id="<?php echo sanitize_title($desc); ?>" type="radio" /><?php echo $desc; ?></label><br /><?php
182
}
183
}
184
185
/**
186
* Outputs Textbox
187
- *
188
* @global array $bp_media
189
* @param array $args
190
*/
191
public function textbox($args) {
192
global $bp_media;
193
$options = $bp_media->options;
@@ -213,20 +255,26 @@ if (!class_exists('BPMediaSettings')) {
213
if ((isset($options[$option]) && empty($options[$option])) || !isset($options[$option])) {
214
$options[$option] = '';
215
}
216
- ?>
217
<label for="<?php echo sanitize_title($option); ?>"><input value="<?php echo $options[$option]; ?>" name="<?php echo $name; ?>" id="<?php echo sanitize_title($option); ?>" type="<?php echo $password ? 'password' : 'text'; ?>" /><?php
218
if (!empty($desc)) {
219
echo '<br /><span class="description">' . $desc . '</span>';
220
}
221
- ?></label><br /><?php
222
}
223
224
/**
225
* Outputs Dropdown
226
- *
227
* @global array $bp_media
228
* @param array $args
229
*/
230
public function dropdown($args) {
231
$defaults = array(
232
'setting' => '',
@@ -253,23 +301,29 @@ if (!class_exists('BPMediaSettings')) {
253
if ((isset($options[$option]) && empty($options[$option])) || !isset($options[$option])) {
254
$options[$option] = '';
255
}
256
- ?>
257
<select name="<?php echo $name; ?>" id="<?php echo $option; ?>"><?php if ($none) { ?>
258
<option><?php __e('None', BP_MEDIA_TXT_DOMAIN); ?></option><?php
259
}
260
foreach ($values as $value => $text) {
261
- ?>
262
- <option<?php selected($options[$option], $value); ?> value="<?php echo $value; ?>"><?php echo $text; ?></option><?php }
263
?>
264
</select><?php
265
}
266
267
/**
268
* Outputs a Button
269
- *
270
* @global array $bp_media
271
* @param array $args
272
*/
273
public function button($args) {
274
$defaults = array(
275
'setting' => '',
@@ -289,7 +343,7 @@ if (!class_exists('BPMediaSettings')) {
289
$button = $option;
290
submit_button($name, '', $button, false);
291
if (!empty($desc)) {
292
- ?>
293
<span class="description"><?php echo $desc; ?></a><?php
294
}
295
}
@@ -297,4 +351,4 @@ if (!class_exists('BPMediaSettings')) {
297
}
298
299
}
300
- ?>
15
16
/**
17
* Register Settings
18
+ *
19
* @global string BP_MEDIA_TXT_DOMAIN
20
*/
21
+
22
+ /**
23
+ *
24
+ * @global BPMediaAddon $bp_media_addon
25
+ */
26
public function settings() {
27
global $bp_media_addon;
28
add_settings_section('bpm-settings', __('BuddyPress Media Settings', BP_MEDIA_TXT_DOMAIN), is_multisite() ? array($this, 'network_notices') : '', 'bp-media-settings');
61
'name' => __('Re-Count', BP_MEDIA_TXT_DOMAIN),
62
'desc' => __('It will re-count all media entries of all users and correct any discrepancies.', BP_MEDIA_TXT_DOMAIN)
63
));
64
+ /*add_settings_section('bpm-admin-bar-menu', __('Admin Bar Menu', BP_MEDIA_TXT_DOMAIN), '', 'bp-media-settings');
65
+ add_settings_field('bpm-admin-bar-menu', __('Spread the Word', BP_MEDIA_TXT_DOMAIN), array($this, 'radio'), 'bp-media-settings', 'bpm-spread-the-word', array(
66
+ 'setting' => 'bp_media_options',
67
+ 'option' => 'remove_linkback',
68
+ 'radios' => array(
69
+ 2 => __('Yes, I support BuddyPress Media', BP_MEDIA_TXT_DOMAIN),
70
+ 1 => __('No, I don\'t want to support BuddyPress Media', BP_MEDIA_TXT_DOMAIN)),
71
+ 'default' => 2)
72
+ );*/
73
$bp_media_addon = new BPMediaAddon();
74
add_settings_section('bpm-addons', __('BuddyPress Media Addons for Audio/Video Conversion', BP_MEDIA_TXT_DOMAIN), array($bp_media_addon, 'get_addons'), 'bp-media-addons');
75
add_settings_section('bpm-support', __('Submit a request form', BP_MEDIA_TXT_DOMAIN), '', 'bp-media-support');
98
/**
99
* Sanitizes the settings
100
*/
101
+
102
+ /**
103
+ *
104
+ * @global type $bp_media_admin
105
+ * @param type $input
106
+ * @return type
107
+ */
108
public function sanitize($input) {
109
global $bp_media_admin;
110
if (isset($_POST['refresh-count'])) {
128
129
/**
130
* Output a checkbox
131
+ *
132
* @global array $bp_media
133
* @param array $args
134
*/
135
+
136
+ /**
137
+ *
138
+ * @global array $bp_media
139
+ * @param type $args
140
+ * @return type
141
+ */
142
public function checkbox($args) {
143
global $bp_media;
144
$options = $bp_media->options;
165
?>
166
<label for="<?php echo $option; ?>">
167
<input<?php checked($options[$option]); ?> name="<?php echo $name; ?>" id="<?php echo $option; ?>" value="1" type="checkbox" />
168
+ <?php echo $desc; ?>
169
</label><?php
170
}
171
172
/**
173
* Outputs Radio Buttons
174
+ *
175
* @global array $bp_media
176
* @param array $args
177
*/
178
+
179
+ /**
180
+ *
181
+ * @global array $bp_media
182
+ * @param type $args
183
+ * @return type
184
+ */
185
public function radio($args) {
186
global $bp_media;
187
$options = $bp_media->options;
212
}
213
214
foreach ($radios as $value => $desc) {
215
+ ?>
216
<label for="<?php echo sanitize_title($desc); ?>"><input<?php checked($options[$option], $value); ?> value="<?php echo $value; ?>" name="<?php echo $name; ?>" id="<?php echo sanitize_title($desc); ?>" type="radio" /><?php echo $desc; ?></label><br /><?php
217
}
218
}
219
220
/**
221
* Outputs Textbox
222
+ *
223
* @global array $bp_media
224
* @param array $args
225
*/
226
+
227
+ /**
228
+ *
229
+ * @global array $bp_media
230
+ * @param type $args
231
+ * @return type
232
+ */
233
public function textbox($args) {
234
global $bp_media;
235
$options = $bp_media->options;
255
if ((isset($options[$option]) && empty($options[$option])) || !isset($options[$option])) {
256
$options[$option] = '';
257
}
258
+ ?>
259
<label for="<?php echo sanitize_title($option); ?>"><input value="<?php echo $options[$option]; ?>" name="<?php echo $name; ?>" id="<?php echo sanitize_title($option); ?>" type="<?php echo $password ? 'password' : 'text'; ?>" /><?php
260
if (!empty($desc)) {
261
echo '<br /><span class="description">' . $desc . '</span>';
262
}
263
+ ?></label><br /><?php
264
}
265
266
/**
267
* Outputs Dropdown
268
+ *
269
* @global array $bp_media
270
* @param array $args
271
*/
272
+
273
+ /**
274
+ *
275
+ * @param type $args
276
+ * @return type
277
+ */
278
public function dropdown($args) {
279
$defaults = array(
280
'setting' => '',
301
if ((isset($options[$option]) && empty($options[$option])) || !isset($options[$option])) {
302
$options[$option] = '';
303
}
304
+ ?>
305
<select name="<?php echo $name; ?>" id="<?php echo $option; ?>"><?php if ($none) { ?>
306
<option><?php __e('None', BP_MEDIA_TXT_DOMAIN); ?></option><?php
307
}
308
foreach ($values as $value => $text) {
309
?>
310
+ <option<?php selected($options[$option], $value); ?> value="<?php echo $value; ?>"><?php echo $text; ?></option><?php }
311
+ ?>
312
</select><?php
313
}
314
315
/**
316
* Outputs a Button
317
+ *
318
* @global array $bp_media
319
* @param array $args
320
*/
321
+
322
+ /**
323
+ *
324
+ * @param type $args
325
+ * @return type
326
+ */
327
public function button($args) {
328
$defaults = array(
329
'setting' => '',
343
$button = $option;
344
submit_button($name, '', $button, false);
345
if (!empty($desc)) {
346
+ ?>
347
<span class="description"><?php echo $desc; ?></a><?php
348
}
349
}
351
}
352
353
}
354
+ ?>
app/helper/BPMediaSupport.php CHANGED
@@ -13,6 +13,11 @@ if (!class_exists('BPMediaSupport')) {
13
;
14
}
15
16
public function get_form($form) {
17
if (empty($form))
18
$form = (isset($_POST['form'])) ? $_POST['form'] : '';
@@ -91,6 +96,10 @@ if (!class_exists('BPMediaSupport')) {
91
}
92
}
93
94
public function submit_request() {
95
global $bp_media;
96
$form_data = wp_parse_args($_POST['form_data']);
13
;
14
}
15
16
+ /**
17
+ *
18
+ * @global type $current_user
19
+ * @param type $form
20
+ */
21
public function get_form($form) {
22
if (empty($form))
23
$form = (isset($_POST['form'])) ? $_POST['form'] : '';
96
}
97
}
98
99
+ /**
100
+ *
101
+ * @global type $bp_media
102
+ */
103
public function submit_request() {
104
global $bp_media;
105
$form_data = wp_parse_args($_POST['form_data']);
app/helper/BPMediaUpgrade.php CHANGED
@@ -23,6 +23,11 @@ if (!class_exists('BPMediaUpgrade')) {
23
*
24
* @global string BP_MEDIA_TXT_DOMAIN
25
*/
26
public function upgrade_db() {
27
global $bp_media;
28
?>
@@ -53,9 +58,15 @@ if (!class_exists('BPMediaUpgrade')) {
53
* @global wpdb $wpdb
54
* @global string BP_MEDIA_TXT_DOMAIN
55
*/
56
public function upgrade_1_0_to_2_1() {
57
global $wpdb, $bp_media;
58
- $post_wall =__( 'Wall Posts', BP_MEDIA_TXT_DOMAIN );
59
remove_filter('bp_activity_get_user_join_filter', 'BPMediaFilters::activity_query_filter', 10);
60
/* @var $wpdb wpdb */
61
$wall_posts_album_ids = array();
@@ -124,17 +135,22 @@ if (!class_exists('BPMediaUpgrade')) {
124
*
125
* @global string BP_MEDIA_TXT_DOMAIN
126
*/
127
public function upgrade_2_0_to_2_1() {
128
global $bp_media;
129
$page = 0;
130
while ($media_entries = BPMediaUpgradeScript::return_query_posts(array(
131
- 'post_type' => 'attachment',
132
- 'post_status' => 'any',
133
- 'meta_key' => 'bp-media-key',
134
- 'meta_value' => 0,
135
- 'meta_compare' => '>',
136
- 'paged' => ++$page,
137
- 'postsperpage' => 10
138
))) {
139
foreach ($media_entries as $media) {
140
try {
23
*
24
* @global string BP_MEDIA_TXT_DOMAIN
25
*/
26
+
27
+ /**
28
+ *
29
+ * @global type $bp_media
30
+ */
31
public function upgrade_db() {
32
global $bp_media;
33
?>
58
* @global wpdb $wpdb
59
* @global string BP_MEDIA_TXT_DOMAIN
60
*/
61
+
62
+ /**
63
+ *
64
+ * @global wpdb $wpdb
65
+ * @global type $bp_media
66
+ */
67
public function upgrade_1_0_to_2_1() {
68
global $wpdb, $bp_media;
69
+ $post_wall = __('Wall Posts', BP_MEDIA_TXT_DOMAIN);
70
remove_filter('bp_activity_get_user_join_filter', 'BPMediaFilters::activity_query_filter', 10);
71
/* @var $wpdb wpdb */
72
$wall_posts_album_ids = array();
135
*
136
* @global string BP_MEDIA_TXT_DOMAIN
137
*/
138
+
139
+ /**
140
+ *
141
+ * @global type $bp_media
142
+ */
143
public function upgrade_2_0_to_2_1() {
144
global $bp_media;
145
$page = 0;
146
while ($media_entries = BPMediaUpgradeScript::return_query_posts(array(
147
+ 'post_type' => 'attachment',
148
+ 'post_status' => 'any',
149
+ 'meta_key' => 'bp-media-key',
150
+ 'meta_value' => 0,
151
+ 'meta_compare' => '>',
152
+ 'paged' => ++$page,
153
+ 'postsperpage' => 10
154
))) {
155
foreach ($media_entries as $media) {
156
try {
app/helper/rtPluginInfo.php CHANGED
@@ -1,116 +1,124 @@
1
<?php
2
/**
3
* A container class for holding and transforming various plugin metadata.
4
*
5
* @author faishal
6
*/
7
class rtPluginInfo {
8
- //Most fields map directly to the contents of the plugin's info.json file.
9
- //See the relevant docs for a description of their meaning.
10
- public $name;
11
- public $slug;
12
- public $version;
13
- public $homepage;
14
- public $sections;
15
- public $download_url;
16
-
17
- public $author;
18
- public $author_homepage;
19
-
20
- public $requires;
21
- public $tested;
22
- public $upgrade_notice;
23
-
24
- public $rating;
25
- public $num_ratings;
26
- public $downloaded;
27
- public $last_updated;
28
-
29
- public $id = 0; //The native WP.org API returns numeric plugin IDs, but they're not used for anything.
30
-
31
- /**
32
- * Create a new instance of PluginInfo from JSON-encoded plugin info
33
- * returned by an external update API.
34
- *
35
- * @param string $json Valid JSON string representing plugin info.
36
- * @param bool $triggerErrors
37
- * @return PluginInfo|null New instance of PluginInfo, or NULL on error.
38
- */
39
- public static function fromJson($json, $triggerErrors = false){
40
- /** @var StdClass $apiResponse */
41
- $apiResponse = json_decode($json);
42
- if ( empty($apiResponse) || !is_object($apiResponse) ){
43
- if ( $triggerErrors ) {
44
- trigger_error(
45
- "Failed to parse plugin metadata. Try validating your .json file with http://jsonlint.com/",
46
- E_USER_NOTICE
47
- );
48
- }
49
- return null;
50
- }
51
-
52
- //Very, very basic validation.
53
- $valid = isset($apiResponse->name) && !empty($apiResponse->name) && isset($apiResponse->version) && !empty($apiResponse->version);
54
- if ( !$valid ){
55
- if ( $triggerErrors ) {
56
- trigger_error(
57
- "The plugin metadata file does not contain the required 'name' and/or 'version' keys.",
58
- E_USER_NOTICE
59
- );
60
- }
61
- return null;
62
- }
63
-
64
- $info = new self();
65
- foreach(get_object_vars($apiResponse) as $key => $value){
66
- $info->$key = $value;
67
- }
68
-
69
- return $info;
70
- }
71
-
72
- /**
73
- * Transform plugin info into the format used by the native WordPress.org API
74
- *
75
- * @return object
76
- */
77
- public function toWpFormat(){
78
- $info = new StdClass;
79
-
80
- //The custom update API is built so that many fields have the same name and format
81
- //as those returned by the native WordPress.org API. These can be assigned directly.
82
- $sameFormat = array(
83
- 'name', 'slug', 'version', 'requires', 'tested', 'rating', 'upgrade_notice',
84
- 'num_ratings', 'downloaded', 'homepage', 'last_updated',
85
- );
86
- foreach($sameFormat as $field){
87
- if ( isset($this->$field) ) {
88
- $info->$field = $this->$field;
89
- } else {
90
- $info->$field = null;
91
- }
92
- }
93
-
94
- //Other fields need to be renamed and/or transformed.
95
- $info->download_link = $this->download_url;
96
-
97
- if ( !empty($this->author_homepage) ){
98
- $info->author = sprintf('<a href="%s">%s</a>', $this->author_homepage, $this->author);
99
- } else {
100
- $info->author = $this->author;
101
- }
102
-
103
- if ( is_object($this->sections) ){
104
- $info->sections = get_object_vars($this->sections);
105
- } elseif ( is_array($this->sections) ) {
106
- $info->sections = $this->sections;
107
- } else {
108
- $info->sections = array('description' => '');
109
- }
110
-
111
- return $info;
112
- }
113
}
114
-
115
116
?>
1
<?php
2
+
3
/**
4
* A container class for holding and transforming various plugin metadata.
5
*
6
* @author faishal
7
*/
8
class rtPluginInfo {
9
+
10
+ //Most fields map directly to the contents of the plugin's info.json file.
11
+ //See the relevant docs for a description of their meaning.
12
+ public $name;
13
+ public $slug;
14
+ public $version;
15
+ public $homepage;
16
+ public $sections;
17
+ public $download_url;
18
+ public $author;
19
+ public $author_homepage;
20
+ public $requires;
21
+ public $tested;
22
+ public $upgrade_notice;
23
+ public $rating;
24
+ public $num_ratings;
25
+ public $downloaded;
26
+ public $last_updated;
27
+ public $id = 0; //The native WP.org API returns numeric plugin IDs, but they're not used for anything.
28
+
29
+ /**
30
+ * Create a new instance of PluginInfo from JSON-encoded plugin info
31
+ * returned by an external update API.
32
+ *
33
+ * @param string $json Valid JSON string representing plugin info.
34
+ * @param bool $triggerErrors
35
+ * @return PluginInfo|null New instance of PluginInfo, or NULL on error.
36
+ */
37
+
38
+ /**
39
+ *
40
+ * @param type $json
41
+ * @param type $triggerErrors
42
+ * @return null|\self
43
+ */
44
+ public static function fromJson($json, $triggerErrors = false) {
45
+ /** @var StdClass $apiResponse */
46
+ $apiResponse = json_decode($json);
47
+ if (empty($apiResponse) || !is_object($apiResponse)) {
48
+ if ($triggerErrors) {
49
+ trigger_error(
50
+ "Failed to parse plugin metadata. Try validating your .json file with http://jsonlint.com/", E_USER_NOTICE
51
+ );
52
+ }
53
+ return null;
54
+ }
55
+
56
+ //Very, very basic validation.
57
+ $valid = isset($apiResponse->name) && !empty($apiResponse->name) && isset($apiResponse->version) && !empty($apiResponse->version);
58
+ if (!$valid) {
59
+ if ($triggerErrors) {
60
+ trigger_error(
61
+ "The plugin metadata file does not contain the required 'name' and/or 'version' keys.", E_USER_NOTICE
62
+ );
63
+ }
64
+ return null;
65
+ }
66
+
67
+ $info = new self();
68
+ foreach (get_object_vars($apiResponse) as $key => $value) {
69
+ $info->$key = $value;
70
+ }
71
+
72
+ return $info;
73
+ }
74
+
75
+ /**
76
+ * Transform plugin info into the format used by the native WordPress.org API
77
+ *
78
+ * @return object
79
+ */
80
+
81
+ /**
82
+ *
83
+ * @return \StdClass
84
+ */
85
+ public function toWpFormat() {
86
+ $info = new StdClass;
87
+
88
+ //The custom update API is built so that many fields have the same name and format
89
+ //as those returned by the native WordPress.org API. These can be assigned directly.
90
+ $sameFormat = array(
91
+ 'name', 'slug', 'version', 'requires', 'tested', 'rating', 'upgrade_notice',
92
+ 'num_ratings', 'downloaded', 'homepage', 'last_updated',
93
+ );
94
+ foreach ($sameFormat as $field) {
95
+ if (isset($this->$field)) {
96
+ $info->$field = $this->$field;
97
+ } else {
98
+ $info->$field = null;
99
+ }
100
+ }
101
+
102
+ //Other fields need to be renamed and/or transformed.
103
+ $info->download_link = $this->download_url;
104
+
105
+ if (!empty($this->author_homepage)) {
106
+ $info->author = sprintf('<a href="%s">%s</a>', $this->author_homepage, $this->author);
107
+ } else {
108
+ $info->author = $this->author;
109
+ }
110
+
111
+ if (is_object($this->sections)) {
112
+ $info->sections = get_object_vars($this->sections);
113
+ } elseif (is_array($this->sections)) {
114
+ $info->sections = $this->sections;
115
+ } else {
116
+ $info->sections = array('description' => '');
117
+ }
118
+
119
+ return $info;
120
+ }
121
+
122
}
123
124
?>
app/helper/rtPluginUpdate.php CHANGED
@@ -1,98 +1,130 @@
1
<?php
2
/**
3
* Description of rtPluginUpdate
4
* A simple container class for holding information about an available update.
5
* @author faishal
6
*/
7
class rtPluginUpdate {
8
- public $id = 0;
9
- public $slug;
10
- public $version;
11
- public $homepage;
12
- public $download_url;
13
- public $upgrade_notice;
14
- private static $fields = array('id', 'slug', 'version', 'homepage', 'download_url', 'upgrade_notice');
15
-
16
- /**
17
- * Create a new instance of PluginUpdate from its JSON-encoded representation.
18
- *
19
- * @param string $json
20
- * @param bool $triggerErrors
21
- * @return PluginUpdate|null
22
- */
23
- public static function fromJson($json, $triggerErrors = false){
24
- //Since update-related information is simply a subset of the full plugin info,
25
- //we can parse the update JSON as if it was a plugin info string, then copy over
26
- //the parts that we care about.
27
- $pluginInfo = rtPluginInfo::fromJson($json, $triggerErrors);
28
- if ( $pluginInfo != null ) {
29
- return self::fromPluginInfo($pluginInfo);
30
- } else {
31
- return null;
32
- }
33
- }
34
-
35
- /**
36
- * Create a new instance of PluginUpdate based on an instance of PluginInfo.
37
- * Basically, this just copies a subset of fields from one object to another.
38
- *
39
- * @param PluginInfo $info
40
- * @return PluginUpdate
41
- */
42
- public static function fromPluginInfo($info){
43
- return self::fromObject($info);
44
- }
45
-
46
- /**
47
- * Create a new instance of PluginUpdate by copying the necessary fields from
48
- * another object.
49
- *
50
- * @param StdClass|PluginInfo|PluginUpdate $object The source object.
51
- * @return PluginUpdate The new copy.
52
- */
53
- public static function fromObject($object) {
54
- $update = new self();
55
- foreach(self::$fields as $field){
56
- $update->$field = $object->$field;
57
- }
58
- return $update;
59
- }
60
-
61
- /**
62
- * Create an instance of StdClass that can later be converted back to
63
- * a PluginUpdate. Useful for serialization and caching, as it avoids
64
- * the "incomplete object" problem if the cached value is loaded before
65
- * this class.
66
- *
67
- * @return StdClass
68
- */
69
- public function toStdClass() {
70
- $object = new StdClass();
71
- foreach(self::$fields as $field){
72
- $object->$field = $this->$field;
73
- }
74
- return $object;
75
- }
76
-
77
-
78
- /**
79
- * Transform the update into the format used by WordPress native plugin API.
80
- *
81
- * @return object
82
- */
83
- public function toWpFormat(){
84
- $update = new StdClass;
85
-
86
- $update->id = $this->id;
87
- $update->slug = $this->slug;
88
- $update->new_version = $this->version;
89
- $update->url = $this->homepage;
90
- $update->package = $this->download_url;
91
- if ( !empty($this->upgrade_notice) ){
92
- $update->upgrade_notice = $this->upgrade_notice;
93
- }
94
-
95
- return $update;
96
- }
97
}
98
?>
1
<?php
2
+
3
/**
4
* Description of rtPluginUpdate
5
* A simple container class for holding information about an available update.
6
* @author faishal
7
*/
8
class rtPluginUpdate {
9
+
10
+ public $id = 0;
11
+ public $slug;
12
+ public $version;
13
+ public $homepage;
14
+ public $download_url;
15
+ public $upgrade_notice;
16
+ private static $fields = array('id', 'slug', 'version', 'homepage', 'download_url', 'upgrade_notice');
17
+
18
+ /**
19
+ * Create a new instance of PluginUpdate from its JSON-encoded representation.
20
+ *
21
+ * @param string $json
22
+ * @param bool $triggerErrors
23
+ * @return PluginUpdate|null
24
+ */
25
+
26
+ /**
27
+ *
28
+ * @param type $json
29
+ * @param type $triggerErrors
30
+ * @return null
31
+ */
32
+ public static function fromJson($json, $triggerErrors = false) {
33
+ //Since update-related information is simply a subset of the full plugin info,
34
+ //we can parse the update JSON as if it was a plugin info string, then copy over
35
+ //the parts that we care about.
36
+ $pluginInfo = rtPluginInfo::fromJson($json, $triggerErrors);
37
+ if ($pluginInfo != null) {
38
+ return self::fromPluginInfo($pluginInfo);
39
+ } else {
40
+ return null;
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Create a new instance of PluginUpdate based on an instance of PluginInfo.
46
+ * Basically, this just copies a subset of fields from one object to another.
47
+ *
48
+ * @param PluginInfo $info
49
+ * @return PluginUpdate
50
+ */
51
+
52
+ /**
53
+ *
54
+ * @param type $info
55
+ * @return type
56
+ */
57
+ public static function fromPluginInfo($info) {
58
+ return self::fromObject($info);
59
+ }
60
+
61
+ /**
62
+ * Create a new instance of PluginUpdate by copying the necessary fields from
63
+ * another object.
64
+ *
65
+ * @param StdClass|PluginInfo|PluginUpdate $object The source object.
66
+ * @return PluginUpdate The new copy.
67
+ */
68
+
69
+ /**
70
+ *
71
+ * @param type $object
72
+ * @return \self
73
+ */
74
+ public static function fromObject($object) {
75
+ $update = new self();
76
+ foreach (self::$fields as $field) {
77
+ $update->$field = $object->$field;
78
+ }
79
+ return $update;
80
+ }
81
+
82
+ /**
83
+ * Create an instance of StdClass that can later be converted back to
84
+ * a PluginUpdate. Useful for serialization and caching, as it avoids
85
+ * the "incomplete object" problem if the cached value is loaded before
86
+ * this class.
87
+ *
88
+ * @return StdClass
89
+ */
90
+
91
+ /**
92
+ *
93
+ * @return \StdClass
94
+ */
95
+ public function toStdClass() {
96
+ $object = new StdClass();
97
+ foreach (self::$fields as $field) {
98
+ $object->$field = $this->$field;
99
+ }
100
+ return $object;
101
+ }
102
+
103
+ /**
104
+ * Transform the update into the format used by WordPress native plugin API.
105
+ *
106
+ * @return object
107
+ */
108
+
109
+ /**
110
+ *
111
+ * @return \StdClass
112
+ */
113
+ public function toWpFormat() {
114
+ $update = new StdClass;
115
+
116
+ $update->id = $this->id;
117
+ $update->slug = $this->slug;
118
+ $update->new_version = $this->version;
119
+ $update->url = $this->homepage;
120
+ $update->package = $this->download_url;
121
+ if (!empty($this->upgrade_notice)) {
122
+ $update->upgrade_notice = $this->upgrade_notice;
123
+ }
124
+
125
+ return $update;
126
+ }
127
+
128
}
129
+
130
?>
app/helper/rtPluginUpdateChecker.php CHANGED
@@ -7,563 +7,660 @@
7
* @author faishal
8
*/
9
class rtPluginUpdateChecker {
10
- public $metadataUrl = ''; //The URL of the plugin's metadata file.
11
- public $pluginFile = ''; //Plugin filename relative to the plugins directory.
12
- public $slug = ''; //Plugin slug.
13
- public $checkPeriod = 12; //How often to check for updates (in hours).
14
- public $optionName = ''; //Where to store the update info.
15
-
16
- public $debugMode = true; //Set to TRUE to enable error reporting. Errors are raised using trigger_error()
17
- //and should be logged to the standard PHP error log.
18
-
19
- private $cronHook = null;
20
- private $debugBarPlugin = null;
21
-
22
- /**
23
- * Class constructor.
24
- *
25
- * @param string $metadataUrl The URL of the plugin's metadata file.
26
- * @param string $pluginFile Fully qualified path to the main plugin file.
27
- * @param string $slug The plugin's 'slug'. If not specified, the filename part of $pluginFile sans '.php' will be used as the slug.
28
- * @param integer $checkPeriod How often to check for updates (in hours). Defaults to checking every 12 hours. Set to 0 to disable automatic update checks.
29
- * @param string $optionName Where to store book-keeping info about update checks. Defaults to 'external_updates-$slug'.
30
- */
31
- public function __construct($metadataUrl, $pluginFile, $slug = '', $checkPeriod = 12, $optionName = ''){
32
- $this->metadataUrl = $metadataUrl;
33
- $this->pluginFile = plugin_basename($pluginFile);
34
- $this->checkPeriod = $checkPeriod;
35
- $this->slug = $slug;
36
- $this->optionName = $optionName;
37
- $this->debugMode = defined('WP_DEBUG') && WP_DEBUG;
38
-
39
- //If no slug is specified, use the name of the main plugin file as the slug.
40
- //For example, 'my-cool-plugin/cool-plugin.php' becomes 'cool-plugin'.
41
- if ( empty($this->slug) ){
42
- $this->slug = basename($this->pluginFile, '.php');
43
- }
44
-
45
- if ( empty($this->optionName) ){
46
- $this->optionName = 'external_updates-' . $this->slug;
47
- }
48
-
49
- $this->installHooks();
50
- }
51
-
52
- /**
53
- * Install the hooks required to run periodic update checks and inject update info
54
- * into WP data structures.
55
- *
56
- * @return void
57
- */
58
- protected function installHooks(){
59
- //Override requests for plugin information
60
- add_filter('plugins_api', array($this, 'injectInfo'), 20, 3);
61
-
62
- //Insert our update info into the update array maintained by WP
63
- add_filter('site_transient_update_plugins', array($this,'injectUpdate')); //WP 3.0+
64
- add_filter('transient_update_plugins', array($this,'injectUpdate')); //WP 2.8+
65
-
66
- add_filter('plugin_row_meta', array($this, 'addCheckForUpdatesLink'), 10, 4);
67
- add_action('admin_init', array($this, 'handleManualCheck'));
68
- add_action('all_admin_notices', array($this, 'displayManualCheckResult'));
69
-
70
- //Set up the periodic update checks
71
- $this->cronHook = 'check_plugin_updates-' . $this->slug;
72
- if ( $this->checkPeriod > 0 ){
73
-
74
- //Trigger the check via Cron
75
- add_filter('cron_schedules', array($this, '_addCustomSchedule'));
76
- if ( !wp_next_scheduled($this->cronHook) && !defined('WP_INSTALLING') ) {
77
- $scheduleName = 'every' . $this->checkPeriod . 'hours';
78
- wp_schedule_event(time(), $scheduleName, $this->cronHook);
79
- }
80
- add_action($this->cronHook, array($this, 'checkForUpdates'));
81
-
82
- register_deactivation_hook($this->pluginFile, array($this, '_removeUpdaterCron'));
83
-
84
- //In case Cron is disabled or unreliable, we also manually trigger
85
- //the periodic checks while the user is browsing the Dashboard.
86
- add_action( 'admin_init', array($this, 'maybeCheckForUpdates') );
87
-
88
- } else {
89
- //Periodic checks are disabled.
90
- wp_clear_scheduled_hook($this->cronHook);
91
- }
92
-
93
- add_action('plugins_loaded', array($this, 'initDebugBarPanel'));
94
- }
95
-
96
- /**
97
- * Add our custom schedule to the array of Cron schedules used by WP.
98
- *
99
- * @param array $schedules
100
- * @return array
101
- */
102
- public function _addCustomSchedule($schedules){
103
- if ( $this->checkPeriod && ($this->checkPeriod > 0) ){
104
- $scheduleName = 'every' . $this->checkPeriod . 'hours';
105
- $schedules[$scheduleName] = array(
106
- 'interval' => $this->checkPeriod * 3600,
107
- 'display' => sprintf('Every %d hours', $this->checkPeriod),
108
- );
109
- }
110
- return $schedules;
111
- }
112
-
113
- /**
114
- * Remove the scheduled cron event that the library uses to check for updates.
115
- *
116
- * @return void
117
- */
118
- public function _removeUpdaterCron(){
119
- wp_clear_scheduled_hook($this->cronHook);
120
- }
121
-
122
- /**
123
- * Get the name of the update checker's WP-cron hook. Mostly useful for debugging.
124
- *
125
- * @return string
126
- */
127
- public function getCronHookName() {
128
- return $this->cronHook;
129
- }
130
-
131
- /**
132
- * Retrieve plugin info from the configured API endpoint.
133
- *
134
- * @uses wp_remote_get()
135
- *
136
- * @param array $queryArgs Additional query arguments to append to the request. Optional.
137
- * @return PluginInfo
138
- */
139
- public function requestInfo($queryArgs = array()){
140
- //Query args to append to the URL. Plugins can add their own by using a filter callback (see addQueryArgFilter()).
141
- $installedVersion = $this->getInstalledVersion();
142
- $queryArgs['installed_version'] = ($installedVersion !== null) ? $installedVersion : '';
143
- $queryArgs['admin_email'] = get_option("admin_email");
144
- $queryArgs['slug'] =$this->slug;
145
- $queryArgs = apply_filters('puc_request_info_query_args-'.$this->slug, $queryArgs);
146
- //Various options for the wp_remote_get() call. Plugins can filter these, too.
147
- $options = array(
148
- 'timeout' => 10, //seconds
149
- 'headers' => array(
150
- 'Accept' => 'application/json'
151
- ),
152
- );
153
- $options = apply_filters('puc_request_info_options-'.$this->slug, $options);
154
-
155
- //The plugin info should be at 'http://your-api.com/url/here/$slug/info.json'
156
- $url = $this->metadataUrl;
157
- if ( !empty($queryArgs) ){
158
- $url = add_query_arg($queryArgs, $url);
159
- }
160
-
161
- $result = wp_remote_get(
162
- $url,
163
- $options
164
- );
165
- //Try to parse the response
166
- $pluginInfo = null;
167
- if ( !is_wp_error($result) && isset($result['response']['code']) && ($result['response']['code'] == 200) && !empty($result['body']) ){
168
- $pluginInfo = rtPluginInfo::fromJson($result['body'], $this->debugMode);
169
-
170
- } else if ( $this->debugMode ) {
171
- $message = sprintf("The URL %s does not point to a valid plugin metadata file. ", $url);
172
- if ( is_wp_error($result) ) {
173
- $message .= "WP HTTP error: " . $result->get_error_message();
174
- } else if ( isset($result['response']['code']) ) {
175
- $message .= "HTTP response code is " . $result['response']['code'] . " (expected: 200)";
176
- } else {
177
- $message .= "wp_remote_get() returned an unexpected result.";
178
- }
179
- trigger_error($message, E_USER_WARNING);
180
- }
181
-
182
- $pluginInfo = apply_filters('puc_request_info_result-'.$this->slug, $pluginInfo, $result);
183
- return $pluginInfo;
184
- }
185
-
186
- /**
187
- * Retrieve the latest update (if any) from the configured API endpoint.
188
- *
189
- * @uses PluginUpdateChecker::requestInfo()
190
- *
191
- * @return PluginUpdate An instance of PluginUpdate, or NULL when no updates are available.
192
- */
193
- public function requestUpdate(){
194
- //For the sake of simplicity, this function just calls requestInfo()
195
- //and transforms the result accordingly.
196
- $pluginInfo = $this->requestInfo(array('checking_for_updates' => '1'));
197
- if ( $pluginInfo == null ){
198
- return null;
199
- }
200
- return rtPluginUpdate::fromPluginInfo($pluginInfo);
201
- }
202
-
203
- /**
204
- * Get the currently installed version of the plugin.
205
- *
206
- * @return string Version number.
207
- */
208
- public function getInstalledVersion(){
209
-
210
- if ( !function_exists('get_plugins') ){
211
- if(is_multisite()){
212
- require_once( ABSPATH .'/wp-admin/network/includes/plugin.php' );
213
- }else{require_once( ABSPATH .'/wp-admin/includes/plugin.php' );}
214
- }
215
- $allPlugins = get_plugins();
216
- if ( array_key_exists($this->pluginFile, $allPlugins) && array_key_exists('Version', $allPlugins[$this->pluginFile]) ){
217
- return $allPlugins[$this->pluginFile]['Version'];
218
-
219
- } else {
220
- //This can happen if the filename is wrong or the plugin is installed in mu-plugins.
221
- if ( $this->debugMode ) {
222
- trigger_error(
223
- sprintf(
224
- "Can't to read the Version header for %s. The filename may be incorrect, or the file is not present in /wp-content/plugins.",
225
- $this->pluginFile
226
- ),
227
- E_USER_WARNING
228
- );
229
- }
230
- return null;
231
- }
232
- }
233
-
234
- /**
235
- * Check for plugin updates.
236
- * The results are stored in the DB option specified in $optionName.
237
- *
238
- * @return PluginUpdate|null
239
- */
240
- public function checkForUpdates(){
241
- $installedVersion = $this->getInstalledVersion();
242
- //Fail silently if we can't find the plugin or read its header.
243
- if ( $installedVersion === null ) {
244
- if ( $this->debugMode ) {
245
- trigger_error(
246
- sprintf('Skipping update check for %s - installed version unknown.', $this->pluginFile),
247
- E_USER_WARNING
248
- );
249
- }
250
- return null;
251
- }
252
-
253
- $state = $this->getUpdateState();
254
- if ( empty($state) ){
255
- $state = new StdClass;
256
- $state->lastCheck = 0;
257
- $state->checkedVersion = '';
258
- $state->update = null;
259
- }
260
-
261
- $state->lastCheck = time();
262
- $state->checkedVersion = $installedVersion;
263
- $this->setUpdateState($state); //Save before checking in case something goes wrong
264
-
265
- $state->update = $this->requestUpdate();
266
- $this->setUpdateState($state);
267
-
268
- return $this->getUpdate();
269
- }
270
-
271
- /**
272
- * Check for updates only if the configured check interval has already elapsed.
273
- *
274
- * @return void
275
- */
276
- public function maybeCheckForUpdates(){
277
- if ( empty($this->checkPeriod) ){
278
- return;
279
- }
280
- $state = $this->getUpdateState();
281
-
282
- $shouldCheck =
283
- empty($state) ||
284
- !isset($state->lastCheck) ||
285
- ( (time() - $state->lastCheck) >= $this->checkPeriod*3600 );
286
-
287
- if ( $shouldCheck ){
288
- $this->checkForUpdates();
289
- }
290
- }
291
-
292
- /**
293
- * Load the update checker state from the DB.
294
- *
295
- * @return StdClass|null
296
- */
297
- public function getUpdateState() {
298
- $state = get_site_option($this->optionName, null);
299
- if ( empty($state) || !is_object($state)) {
300
- $state = null;
301
- }
302
-
303
- if ( !empty($state) && isset($state->update) && is_object($state->update) ){
304
- $state->update = rtPluginUpdate::fromObject($state->update);
305
- }
306
- return $state;
307
- }
308
-
309
-
310
- /**
311
- * Persist the update checker state to the DB.
312
- *
313
- * @param StdClass $state
314
- * @return void
315
- */
316
- private function setUpdateState($state) {
317
- if ( isset($state->update) && is_object($state->update) && method_exists($state->update, 'toStdClass') ) {
318
- $update = $state->update; /** @var PluginUpdate $update */
319
- $state->update = $update->toStdClass();
320
- }
321
- update_site_option($this->optionName, $state);
322
- }
323
-
324
- /**
325
- * Reset update checker state - i.e. last check time, cached update data and so on.
326
- *
327
- * Call this when your plugin is being uninstalled, or if you want to
328
- * clear the update cache.
329
- */
330
- public function resetUpdateState() {
331
- delete_site_option($this->optionName);
332
- }
333
-
334
- /**
335
- * Intercept plugins_api() calls that request information about our plugin and
336
- * use the configured API endpoint to satisfy them.
337
- *
338
- * @see plugins_api()
339
- *
340
- * @param mixed $result
341
- * @param string $action
342
- * @param array|object $args
343
- * @return mixed
344
- */
345
- public function injectInfo($result, $action = null, $args = null){
346
- $relevant = ($action == 'plugin_information') && isset($args->slug) && ($args->slug == $this->slug);
347
- if ( !$relevant ){
348
- return $result;
349
- }
350
-
351
- $pluginInfo = $this->requestInfo();
352
- $pluginInfo = apply_filters('puc_pre_inject_info-' . $this->slug, $pluginInfo);
353
- if ($pluginInfo){
354
- return $pluginInfo->toWpFormat();
355
- }
356
-
357
- return $result;
358
- }
359
-
360
- /**
361
- * Insert the latest update (if any) into the update list maintained by WP.
362
- *
363
- * @param StdClass $updates Update list.
364
- * @return StdClass Modified update list.
365
- */
366
- public function injectUpdate($updates){
367
- //Is there an update to insert?
368
- $update = $this->getUpdate();
369
- if ( !empty($update) ) {
370
- //Let plugins filter the update info before it's passed on to WordPress.
371
- $update = apply_filters('puc_pre_inject_update-' . $this->slug, $update);
372
- if ( !is_object($updates) ) {
373
- $updates = new StdClass();
374
- $updates->response = array();
375
- }
376
- $updates->response[$this->pluginFile] = $update->toWpFormat();
377
- } else if ( isset($updates, $updates->response) ) {
378
- unset($updates->response[$this->pluginFile]);
379
- }
380
-
381
- return $updates;
382
- }
383
-
384
- /**
385
- * Get the details of the currently available update, if any.
386
- *
387
- * If no updates are available, or if the last known update version is below or equal
388
- * to the currently installed version, this method will return NULL.
389
- *
390
- * Uses cached update data. To retrieve update information straight from
391
- * the metadata URL, call requestUpdate() instead.
392
- *
393
- * @return PluginUpdate|null
394
- */
395
- public function getUpdate() {
396
- $state = $this->getUpdateState(); /** @var StdClass $state */
397
-
398
- //Is there an update available insert?
399
- if ( !empty($state) && isset($state->update) && !empty($state->update) ){
400
- $update = $state->update;
401
- //Check if the update is actually newer than the currently installed version.
402
- $installedVersion = $this->getInstalledVersion();
403
- if ( ($installedVersion !== null) && version_compare($update->version, $installedVersion, '>') ){
404
- return $update;
405
- }
406
- }
407
- return null;
408
- }
409
-
410
- /**
411
- * Add a "Check for updates" link to the plugin row in the "Plugins" page. By default,
412
- * the new link will appear after the "Visit plugin site" link.
413
- *
414
- * You can change the link text by using the "puc_manual_check_link-$slug" filter.
415
- * Returning an empty string from the filter will disable the link.
416
- *
417
- * @param array $pluginMeta Array of meta links.
418
- * @param string $pluginFile
419
- * @param array|null $pluginData Currently ignored.
420
- * @param string|null $status Currently ignored.
421
- * @return array
422
- */
423
- public function addCheckForUpdatesLink($pluginMeta, $pluginFile, $pluginData = null, $status = null) {
424
- if ( $pluginFile == $this->pluginFile && current_user_can('update_plugins') ) {
425
- $linkUrl = wp_nonce_url(
426
- add_query_arg(
427
- array(
428
- 'puc_check_for_updates' => 1,
429
- 'puc_slug' => $this->slug,
430
- ),
431
- is_network_admin() ? network_admin_url('plugins.php') : admin_url('plugins.php')
432
- ),
433
- 'puc_check_for_updates'
434
- );
435
-
436
- $linkText = apply_filters('puc_manual_check_link-' . $this->slug, 'Check for updates');
437
- if ( !empty($linkText) ) {
438
- $pluginMeta[] = sprintf('<a href="%s">%s</a>', esc_attr($linkUrl), $linkText);
439
- }
440
- }
441
- return $pluginMeta;
442
- }
443
-
444
- /**
445
- * Check for updates when the user clicks the "Check for updates" link.
446
- * @see self::addCheckForUpdatesLink()
447
- *
448
- * @return void
449
- */
450
- public function handleManualCheck() {
451
- $shouldCheck =
452
- isset($_GET['puc_check_for_updates'], $_GET['puc_slug'])
453
- && $_GET['puc_slug'] == $this->slug
454
- && current_user_can('update_plugins')
455
- && check_admin_referer('puc_check_for_updates');
456
-
457
- if ( $shouldCheck ) {
458
- $update = $this->checkForUpdates();
459
- $status = ($update === null) ? 'no_update' : 'update_available';
460
- wp_redirect(add_query_arg(
461
- array(
462
- 'puc_update_check_result' => $status,
463
- 'puc_slug' => $this->slug,
464
- ),
465
- is_network_admin() ? network_admin_url('plugins.php') : admin_url('plugins.php')
466
- ));
467
- }
468
- }
469
-
470
- /**
471
- * Display the results of a manual update check.
472
- * @see self::handleManualCheck()
473
- *
474
- * You can change the result message by using the "puc_manual_check_message-$slug" filter.
475
- */
476
- public function displayManualCheckResult() {
477
- if ( isset($_GET['puc_update_check_result'], $_GET['puc_slug']) && ($_GET['puc_slug'] == $this->slug) ) {
478
- $status = strval($_GET['puc_update_check_result']);
479
- if ( $status == 'no_update' ) {
480
- $message = 'This plugin is up to date.';
481
- } else if ( $status == 'update_available' ) {
482
- $message = 'A new version of this plugin is available.';
483
- } else {
484
- $message = sprintf('Unknown update checker status "%s"', htmlentities($status));
485
- }
486
- printf(
487
- '<div class="updated"><p>%s</p></div>',
488
- apply_filters('puc_manual_check_message-' . $this->slug, $message, $status)
489
- );
490
- }
491
- }
492
-
493
- /**
494
- * Register a callback for filtering query arguments.
495
- *
496
- * The callback function should take one argument - an associative array of query arguments.
497
- * It should return a modified array of query arguments.
498
- *
499
- * @uses add_filter() This method is a convenience wrapper for add_filter().
500
- *
501
- * @param callable $callback
502
- * @return void
503
- */
504
- public function addQueryArgFilter($callback){
505
- add_filter('puc_request_info_query_args-'.$this->slug, $callback);
506
- }
507
-
508
- /**
509
- * Register a callback for filtering arguments passed to wp_remote_get().
510
- *
511
- * The callback function should take one argument - an associative array of arguments -
512
- * and return a modified array or arguments. See the WP documentation on wp_remote_get()
513
- * for details on what arguments are available and how they work.
514
- *
515
- * @uses add_filter() This method is a convenience wrapper for add_filter().
516
- *
517
- * @param callable $callback
518
- * @return void
519
- */
520
- public function addHttpRequestArgFilter($callback){
521
- add_filter('puc_request_info_options-'.$this->slug, $callback);
522
- }
523
-
524
- /**
525
- * Register a callback for filtering the plugin info retrieved from the external API.
526
- *
527
- * The callback function should take two arguments. If the plugin info was retrieved
528
- * successfully, the first argument passed will be an instance of PluginInfo. Otherwise,
529
- * it will be NULL. The second argument will be the corresponding return value of
530
- * wp_remote_get (see WP docs for details).
531
- *
532
- * The callback function should return a new or modified instance of PluginInfo or NULL.
533
- *
534
- * @uses add_filter() This method is a convenience wrapper for add_filter().
535
- *
536
- * @param callable $callback
537
- * @return void
538
- */
539
- public function addResultFilter($callback){
540
- add_filter('puc_request_info_result-'.$this->slug, $callback, 10, 2);
541
- }
542
-
543
- /**
544
- * Register a callback for one of the update checker filters.
545
- *
546
- * Identical to add_filter(), except it automatically adds the "puc_" prefix
547
- * and the "-$plugin_slug" suffix to the filter name. For example, "request_info_result"
548
- * becomes "puc_request_info_result-your_plugin_slug".
549
- *
550
- * @param string $tag
551
- * @param callable $callback
552
- * @param int $priority
553
- * @param int $acceptedArgs
554
- */
555
- public function addFilter($tag, $callback, $priority = 10, $acceptedArgs = 1) {
556
- add_filter('puc_' . $tag . '-' . $this->slug, $callback, $priority, $acceptedArgs);
557
- }
558
-
559
- /**
560
- * Initialize the update checker Debug Bar plugin/add-on thingy.
561
- */
562
- public function initDebugBarPanel() {
563
- if ( class_exists('Debug_Bar') ) {
564
- require_once dirname(__FILE__) . '/debug-bar-plugin.php';
565
- $this->debugBarPlugin = new PucDebugBarPlugin($this);
566
- }
567
- }
568
}
569
?>
7
* @author faishal
8
*/
9
class rtPluginUpdateChecker {
10
+
11
+ public $metadataUrl = ''; //The URL of the plugin's metadata file.
12
+ public $pluginFile = ''; //Plugin filename relative to the plugins directory.
13
+ public $slug = ''; //Plugin slug.
14
+ public $checkPeriod = 12; //How often to check for updates (in hours).
15
+ public $optionName = ''; //Where to store the update info.
16
+ public $debugMode = true; //Set to TRUE to enable error reporting. Errors are raised using trigger_error()
17
+ //and should be logged to the standard PHP error log.
18
+ private $cronHook = null;
19
+ private $debugBarPlugin = null;
20
+
21
+ /**
22
+ * Class constructor.
23
+ *
24
+ * @param string $metadataUrl The URL of the plugin's metadata file.
25
+ * @param string $pluginFile Fully qualified path to the main plugin file.
26
+ * @param string $slug The plugin's 'slug'. If not specified, the filename part of $pluginFile sans '.php' will be used as the slug.
27
+ * @param integer $checkPeriod How often to check for updates (in hours). Defaults to checking every 12 hours. Set to 0 to disable automatic update checks.
28
+ * @param string $optionName Where to store book-keeping info about update checks. Defaults to 'external_updates-$slug'.
29
+ */
30
+
31
+ /**
32
+ *
33
+ * @param type $metadataUrl
34
+ * @param type $pluginFile
35
+ * @param type $slug
36
+ * @param type $checkPeriod
37
+ * @param type $optionName
38
+ */
39
+ public function __construct($metadataUrl, $pluginFile, $slug = '', $checkPeriod = 12, $optionName = '') {
40
+ $this->metadataUrl = $metadataUrl;
41
+ $this->pluginFile = plugin_basename($pluginFile);
42
+ $this->checkPeriod = $checkPeriod;
43
+ $this->slug = $slug;
44
+ $this->optionName = $optionName;
45
+ $this->debugMode = defined('WP_DEBUG') && WP_DEBUG;
46
+
47
+ //If no slug is specified, use the name of the main plugin file as the slug.
48
+ //For example, 'my-cool-plugin/cool-plugin.php' becomes 'cool-plugin'.
49
+ if (empty($this->slug)) {
50
+ $this->slug = basename($this->pluginFile, '.php');
51
+ }
52
+
53
+ if (empty($this->optionName)) {
54
+ $this->optionName = 'external_updates-' . $this->slug;
55
+ }
56
+
57
+ $this->installHooks();
58
+ }
59
+
60
+ /**
61
+ * Install the hooks required to run periodic update checks and inject update info
62
+ * into WP data structures.
63
+ *
64
+ * @return void
65
+ */
66
+ protected function installHooks() {
67
+ //Override requests for plugin information
68
+ add_filter('plugins_api', array($this, 'injectInfo'), 20, 3);
69
+
70
+ //Insert our update info into the update array maintained by WP
71
+ add_filter('site_transient_update_plugins', array($this, 'injectUpdate')); //WP 3.0+
72
+ add_filter('transient_update_plugins', array($this, 'injectUpdate')); //WP 2.8+
73
+
74
+ add_filter('plugin_row_meta', array($this, 'addCheckForUpdatesLink'), 10, 4);
75
+ add_action('admin_init', array($this, 'handleManualCheck'));
76
+ add_action('all_admin_notices', array($this, 'displayManualCheckResult'));
77
+
78
+ //Set up the periodic update checks
79
+ $this->cronHook = 'check_plugin_updates-' . $this->slug;
80
+ if ($this->checkPeriod > 0) {
81
+
82
+ //Trigger the check via Cron
83
+ add_filter('cron_schedules', array($this, '_addCustomSchedule'));
84
+ if (!wp_next_scheduled($this->cronHook) && !defined('WP_INSTALLING')) {
85
+ $scheduleName = 'every' . $this->checkPeriod . 'hours';
86
+ wp_schedule_event(time(), $scheduleName, $this->cronHook);
87
+ }
88
+ add_action($this->cronHook, array($this, 'checkForUpdates'));
89
+
90
+ register_deactivation_hook($this->pluginFile, array($this, '_removeUpdaterCron'));
91
+
92
+ //In case Cron is disabled or unreliable, we also manually trigger
93
+ //the periodic checks while the user is browsing the Dashboard.
94
+ add_action('admin_init', array($this, 'maybeCheckForUpdates'));
95
+ } else {
96
+ //Periodic checks are disabled.
97
+ wp_clear_scheduled_hook($this->cronHook);
98
+ }
99
+
100
+ add_action('plugins_loaded', array($this, 'initDebugBarPanel'));
101
+ }
102
+
103
+ /**
104
+ * Add our custom schedule to the array of Cron schedules used by WP.
105
+ *
106
+ * @param array $schedules
107
+ * @return array
108
+ */
109
+
110
+ /**
111
+ *
112
+ * @param type $schedules
113
+ * @return type
114
+ */
115
+ public function _addCustomSchedule($schedules) {
116
+ if ($this->checkPeriod && ($this->checkPeriod > 0)) {
117
+ $scheduleName = 'every' . $this->checkPeriod . 'hours';
118
+ $schedules[$scheduleName] = array(
119
+ 'interval' => $this->checkPeriod * 3600,
120
+ 'display' => sprintf('Every %d hours', $this->checkPeriod),
121
+ );
122
+ }
123
+ return $schedules;
124
+ }
125
+
126
+ /**
127
+ * Remove the scheduled cron event that the library uses to check for updates.
128
+ *
129
+ * @return void
130
+ */
131
+ public function _removeUpdaterCron() {
132
+ wp_clear_scheduled_hook($this->cronHook);
133
+ }
134
+
135
+ /**
136
+ * Get the name of the update checker's WP-cron hook. Mostly useful for debugging.
137
+ *
138
+ * @return string
139
+ */
140
+
141
+ /**
142
+ *
143
+ * @return type
144
+ */
145
+ public function getCronHookName() {
146
+ return $this->cronHook;
147
+ }
148
+
149
+ /**
150
+ * Retrieve plugin info from the configured API endpoint.
151
+ *
152
+ * @uses wp_remote_get()
153
+ *
154
+ * @param array $queryArgs Additional query arguments to append to the request. Optional.
155
+ * @return PluginInfo
156
+ */
157
+
158
+ /**
159
+ *
160
+ * @param type $queryArgs
161
+ * @return type
162
+ */
163
+ public function requestInfo($queryArgs = array()) {
164
+ //Query args to append to the URL. Plugins can add their own by using a filter callback (see addQueryArgFilter()).
165
+ $installedVersion = $this->getInstalledVersion();
166
+ $queryArgs['installed_version'] = ($installedVersion !== null) ? $installedVersion : '';
167
+ $queryArgs['admin_email'] = get_option("admin_email");
168
+ $queryArgs['slug'] = $this->slug;
169
+ $queryArgs = apply_filters('puc_request_info_query_args-' . $this->slug, $queryArgs);
170
+ //Various options for the wp_remote_get() call. Plugins can filter these, too.
171
+ $options = array(
172
+ 'timeout' => 10, //seconds
173
+ 'headers' => array(
174
+ 'Accept' => 'application/json'
175
+ ),
176
+ );
177
+ $options = apply_filters('puc_request_info_options-' . $this->slug, $options);
178
+
179
+ //The plugin info should be at 'http://your-api.com/url/here/$slug/info.json'
180
+ $url = $this->metadataUrl;
181
+ if (!empty($queryArgs)) {
182
+ $url = add_query_arg($queryArgs, $url);
183
+ }
184
+
185
+ $result = wp_remote_get(
186
+ $url, $options
187
+ );
188
+ //Try to parse the response
189
+ $pluginInfo = null;
190
+ if (!is_wp_error($result) && isset($result['response']['code']) && ($result['response']['code'] == 200) && !empty($result['body'])) {
191
+ $pluginInfo = rtPluginInfo::fromJson($result['body'], $this->debugMode);
192
+ } else if ($this->debugMode) {
193
+ $message = sprintf("The URL %s does not point to a valid plugin metadata file. ", $url);
194
+ if (is_wp_error($result)) {
195
+ $message .= "WP HTTP error: " . $result->get_error_message();
196
+ } else if (isset($result['response']['code'])) {
197
+ $message .= "HTTP response code is " . $result['response']['code'] . " (expected: 200)";
198
+ } else {
199
+ $message .= "wp_remote_get() returned an unexpected result.";
200
+ }
201
+ trigger_error($message, E_USER_WARNING);
202
+ }
203
+
204
+ $pluginInfo = apply_filters('puc_request_info_result-' . $this->slug, $pluginInfo, $result);
205
+ return $pluginInfo;
206
+ }
207
+
208
+ /**
209
+ * Retrieve the latest update (if any) from the configured API endpoint.
210
+ *
211
+ * @uses PluginUpdateChecker::requestInfo()
212
+ *
213
+ * @return PluginUpdate An instance of PluginUpdate, or NULL when no updates are available.
214
+ */
215
+
216
+ /**
217
+ *
218
+ * @return null
219
+ */
220
+ public function requestUpdate() {
221
+ //For the sake of simplicity, this function just calls requestInfo()
222
+ //and transforms the result accordingly.
223
+ $pluginInfo = $this->requestInfo(array('checking_for_updates' => '1'));
224
+ if ($pluginInfo == null) {
225
+ return null;
226
+ }
227
+ return rtPluginUpdate::fromPluginInfo($pluginInfo);
228
+ }
229
+
230
+ /**
231
+ * Get the currently installed version of the plugin.
232
+ *
233
+ * @return string Version number.
234
+ */
235
+
236
+ /**
237
+ *
238
+ * @return null
239
+ */
240
+ public function getInstalledVersion() {
241
+
242
+ if (!function_exists('get_plugins')) {
243
+ if (is_multisite()) {
244
+ require_once( ABSPATH . '/wp-admin/network/includes/plugin.php' );
245
+ } else {
246
+ require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
247
+ }
248
+ }
249
+ $allPlugins = get_plugins();
250
+ if (array_key_exists($this->pluginFile, $allPlugins) && array_key_exists('Version', $allPlugins[$this->pluginFile])) {
251
+ return $allPlugins[$this->pluginFile]['Version'];
252
+ } else {
253
+ //This can happen if the filename is wrong or the plugin is installed in mu-plugins.
254
+ if ($this->debugMode) {
255
+ trigger_error(
256
+ sprintf(
257
+ "Can't to read the Version header for %s. The filename may be incorrect, or the file is not present in /wp-content/plugins.", $this->pluginFile
258
+ ), E_USER_WARNING
259
+ );
260
+ }
261
+ return null;
262
+ }
263
+ }
264
+
265
+ /**
266
+ * Check for plugin updates.
267
+ * The results are stored in the DB option specified in $optionName.
268
+ *
269
+ * @return PluginUpdate|null
270
+ */
271
+
272
+ /**
273
+ *
274
+ * @return null
275
+ */
276
+ public function checkForUpdates() {
277
+ $installedVersion = $this->getInstalledVersion();
278
+ //Fail silently if we can't find the plugin or read its header.
279
+ if ($installedVersion === null) {
280
+ if ($this->debugMode) {
281
+ trigger_error(
282
+ sprintf('Skipping update check for %s - installed version unknown.', $this->pluginFile), E_USER_WARNING
283
+ );
284
+ }
285
+ return null;
286
+ }
287
+
288
+ $state = $this->getUpdateState();
289
+ if (empty($state)) {
290
+ $state = new StdClass;
291
+ $state->lastCheck = 0;
292
+ $state->checkedVersion = '';
293
+ $state->update = null;
294
+ }
295
+
296
+ $state->lastCheck = time();
297
+ $state->checkedVersion = $installedVersion;
298
+ $this->setUpdateState($state); //Save before checking in case something goes wrong
299
+
300
+ $state->update = $this->requestUpdate();
301
+ $this->setUpdateState($state);
302
+
303
+ return $this->getUpdate();
304
+ }
305
+
306
+ /**
307
+ * Check for updates only if the configured check interval has already elapsed.
308
+ *
309
+ * @return void
310
+ */
311
+
312
+ /**
313
+ *
314
+ * @return type
315
+ */
316
+ public function maybeCheckForUpdates() {
317
+ if (empty($this->checkPeriod)) {
318
+ return;
319
+ }
320
+ $state = $this->getUpdateState();
321
+
322
+ $shouldCheck =
323
+ empty($state) ||
324
+ !isset($state->lastCheck) ||
325
+ ( (time() - $state->lastCheck) >= $this->checkPeriod * 3600 );
326
+
327
+ if ($shouldCheck) {
328
+ $this->checkForUpdates();
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Load the update checker state from the DB.
334
+ *
335
+ * @return StdClass|null
336
+ */
337
+
338
+ /**
339
+ *
340
+ * @return null
341
+ */
342
+ public function getUpdateState() {
343
+ $state = get_site_option($this->optionName, null);
344
+ if (empty($state) || !is_object($state)) {
345
+ $state = null;
346
+ }
347
+
348
+ if (!empty($state) && isset($state->update) && is_object($state->update)) {
349
+ $state->update = rtPluginUpdate::fromObject($state->update);
350
+ }
351
+ return $state;
352
+ }
353
+
354
+ /**
355
+ * Persist the update checker state to the DB.
356
+ *
357
+ * @param StdClass $state
358
+ * @return void
359
+ */
360
+
361
+ /**
362
+ *
363
+ * @param type $state
364
+ */
365
+ private function setUpdateState($state) {
366
+ if (isset($state->update) && is_object($state->update) && method_exists($state->update, 'toStdClass')) {
367
+ $update = $state->update;/** @var PluginUpdate $update */
368
+ $state->update = $update->toStdClass();
369
+ }
370
+ update_site_option($this->optionName, $state);
371
+ }
372
+
373
+ /**
374
+ * Reset update checker state - i.e. last check time, cached update data and so on.
375
+ *
376
+ * Call this when your plugin is being uninstalled, or if you want to
377
+ * clear the update cache.
378
+ */
379
+ public function resetUpdateState() {
380
+ delete_site_option($this->optionName);
381
+ }
382
+
383
+ /**
384
+ * Intercept plugins_api() calls that request information about our plugin and
385
+ * use the configured API endpoint to satisfy them.
386
+ *
387
+ * @see plugins_api()
388
+ *
389
+ * @param mixed $result
390
+ * @param string $action
391
+ * @param array|object $args
392
+ * @return mixed
393
+ */
394
+
395
+ /**
396
+ *
397
+ * @param type $result
398
+ * @param type $action
399
+ * @param type $args
400
+ * @return type
401
+ */
402
+ public function injectInfo($result, $action = null, $args = null) {
403
+ $relevant = ($action == 'plugin_information') && isset($args->slug) && ($args->slug == $this->slug);
404
+ if (!$relevant) {
405
+ return $result;
406
+ }
407
+
408
+ $pluginInfo = $this->requestInfo();
409
+ $pluginInfo = apply_filters('puc_pre_inject_info-' . $this->slug, $pluginInfo);
410
+ if ($pluginInfo) {
411
+ return $pluginInfo->toWpFormat();
412
+ }
413
+
414
+ return $result;
415
+ }
416
+
417
+ /**
418
+ * Insert the latest update (if any) into the update list maintained by WP.
419
+ *
420
+ * @param StdClass $updates Update list.
421
+ * @return StdClass Modified update list.
422
+ */
423
+
424
+ /**
425
+ *
426
+ * @param StdClass $updates
427
+ * @return \StdClass
428
+ */
429
+ public function injectUpdate($updates) {
430
+ //Is there an update to insert?
431
+ $update = $this->getUpdate();
432
+ if (!empty($update)) {
433
+ //Let plugins filter the update info before it's passed on to WordPress.
434
+ $update = apply_filters('puc_pre_inject_update-' . $this->slug, $update);
435
+ if (!is_object($updates)) {
436
+ $updates = new StdClass();
437
+ $updates->response = array();
438
+ }
439
+ $updates->response[$this->pluginFile] = $update->toWpFormat();
440
+ } else if (isset($updates, $updates->response)) {
441
+ unset($updates->response[$this->pluginFile]);
442
+ }
443
+
444
+ return $updates;
445
+ }
446
+
447
+ /**
448
+ * Get the details of the currently available update, if any.
449
+ *
450
+ * If no updates are available, or if the last known update version is below or equal
451
+ * to the currently installed version, this method will return NULL.
452
+ *
453
+ * Uses cached update data. To retrieve update information straight from
454
+ * the metadata URL, call requestUpdate() instead.
455
+ *
456
+ * @return PluginUpdate|null
457
+ */
458
+
459
+ /**
460
+ *
461
+ * @return null
462
+ */
463
+ public function getUpdate() {
464
+ $state = $this->getUpdateState();/** @var StdClass $state */
465
+ //Is there an update available insert?
466
+ if (!empty($state) && isset($state->update) && !empty($state->update)) {
467
+ $update = $state->update;
468
+ //Check if the update is actually newer than the currently installed version.
469
+ $installedVersion = $this->getInstalledVersion();
470
+ if (($installedVersion !== null) && version_compare($update->version, $installedVersion, '>')) {
471
+ return $update;
472
+ }
473
+ }
474
+ return null;
475
+ }
476
+
477
+ /**
478
+ * Add a "Check for updates" link to the plugin row in the "Plugins" page. By default,
479
+ * the new link will appear after the "Visit plugin site" link.
480
+ *
481
+ * You can change the link text by using the "puc_manual_check_link-$slug" filter.
482
+ * Returning an empty string from the filter will disable the link.
483
+ *
484
+ * @param array $pluginMeta Array of meta links.
485
+ * @param string $pluginFile
486
+ * @param array|null $pluginData Currently ignored.
487
+ * @param string|null $status Currently ignored.
488
+ * @return array
489
+ */
490
+
491
+ /**
492
+ *
493
+ * @param type $pluginMeta
494
+ * @param type $pluginFile
495
+ * @param type $pluginData
496
+ * @param type $status
497
+ * @return type
498
+ */
499
+ public function addCheckForUpdatesLink($pluginMeta, $pluginFile, $pluginData = null, $status = null) {
500
+ if ($pluginFile == $this->pluginFile && current_user_can('update_plugins')) {
501
+ $linkUrl = wp_nonce_url(
502
+ add_query_arg(
503
+ array(
504
+ 'puc_check_for_updates' => 1,
505
+ 'puc_slug' => $this->slug,
506
+ ), is_network_admin() ? network_admin_url('plugins.php') : admin_url('plugins.php')
507
+ ), 'puc_check_for_updates'
508
+ );
509
+
510
+ $linkText = apply_filters('puc_manual_check_link-' . $this->slug, 'Check for updates');
511
+ if (!empty($linkText)) {
512
+ $pluginMeta[] = sprintf('<a href="%s">%s</a>', esc_attr($linkUrl), $linkText);
513
+ }
514
+ }
515
+ return $pluginMeta;
516
+ }
517
+
518
+ /**
519
+ * Check for updates when the user clicks the "Check for updates" link.
520
+ * @see self::addCheckForUpdatesLink()
521
+ *
522
+ * @return void
523
+ */
524
+ public function handleManualCheck() {
525
+ $shouldCheck =
526
+ isset($_GET['puc_check_for_updates'], $_GET['puc_slug'])
527
+ && $_GET['puc_slug'] == $this->slug
528
+ && current_user_can('update_plugins')
529
+ && check_admin_referer('puc_check_for_updates');
530
+
531
+ if ($shouldCheck) {
532
+ $update = $this->checkForUpdates();
533
+ $status = ($update === null) ? 'no_update' : 'update_available';
534
+ wp_redirect(add_query_arg(
535
+ array(
536
+ 'puc_update_check_result' => $status,
537
+ 'puc_slug' => $this->slug,
538
+ ), is_network_admin() ? network_admin_url('plugins.php') : admin_url('plugins.php')
539
+ ));
540
+ }
541
+ }
542
+
543
+ /**
544
+ * Display the results of a manual update check.
545
+ * @see self::handleManualCheck()
546
+ *
547
+ * You can change the result message by using the "puc_manual_check_message-$slug" filter.
548
+ */
549
+ public function displayManualCheckResult() {
550
+ if (isset($_GET['puc_update_check_result'], $_GET['puc_slug']) && ($_GET['puc_slug'] == $this->slug)) {
551
+ $status = strval($_GET['puc_update_check_result']);
552
+ if ($status == 'no_update') {
553
+ $message = 'This plugin is up to date.';
554
+ } else if ($status == 'update_available') {
555
+ $message = 'A new version of this plugin is available.';
556
+ } else {
557
+ $message = sprintf('Unknown update checker status "%s"', htmlentities($status));
558
+ }
559
+ printf(
560
+ '<div class="updated"><p>%s</p></div>', apply_filters('puc_manual_check_message-' . $this->slug, $message, $status)
561
+ );
562
+ }
563
+ }
564
+
565
+ /**
566
+ * Register a callback for filtering query arguments.
567
+ *
568
+ * The callback function should take one argument - an associative array of query arguments.
569
+ * It should return a modified array of query arguments.
570
+ *
571
+ * @uses add_filter() This method is a convenience wrapper for add_filter().
572
+ *
573
+ * @param callable $callback
574
+ * @return void
575
+ */
576
+
577
+ /**
578
+ *
579
+ * @param type $callback
580
+ */
581
+ public function addQueryArgFilter($callback) {
582
+ add_filter('puc_request_info_query_args-' . $this->slug, $callback);
583
+ }
584
+
585
+ /**
586
+ * Register a callback for filtering arguments passed to wp_remote_get().
587
+ *
588
+ * The callback function should take one argument - an associative array of arguments -
589
+ * and return a modified array or arguments. See the WP documentation on wp_remote_get()
590
+ * for details on what arguments are available and how they work.
591
+ *
592
+ * @uses add_filter() This method is a convenience wrapper for add_filter().
593
+ *
594
+ * @param callable $callback
595
+ * @return void
596
+ */
597
+
598
+ /**
599
+ *
600
+ * @param type $callback
601
+ */
602