PluginProbe ʕ •ᴥ•ʔ
SiteGuard WP Plugin / 1.8.9
SiteGuard WP Plugin v1.8.9
1.8.9 1.8.8 1.8.7 1.8.6 1.8.6-beta1 1.8.6-beta2 1.8.4 1.8.5 1.8.3 1.8.2 1.8.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.2 1.2.3 1.4.3 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.7.0 1.7.1 1.7.10 1.7.11 1.7.12 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.0-beta1 1.8.0-beta2 1.8.0-beta3 1.8.0-beta4
siteguard / classes / siteguard-updates-notify.php
siteguard / classes Last commit date
siteguard-admin-filter.php 3 months ago siteguard-base.php 3 weeks ago siteguard-captcha.php 1 week ago siteguard-config.php 1 year ago siteguard-disable-author-query.php 2 months ago siteguard-disable-pingback.php 3 months ago siteguard-disable-xmlrpc.php 3 months ago siteguard-htaccess.php 3 weeks ago siteguard-login-alert.php 3 months ago siteguard-login-history.php 2 months ago siteguard-login-lock.php 2 months ago siteguard-rename-login.php 1 week ago siteguard-updates-notify.php 1 week ago siteguard-waf-exclude-rule.php 3 months ago
siteguard-updates-notify.php
302 lines
1 <?php
2 /*
3 This function based on WP Updates Notifier 1.4.1 by Scott Cariss.
4 */
5 class SiteGuard_UpdatesNotify extends SiteGuard_Base {
6 const CRON_NAME = 'siteguard_update_check';
7
8 function __construct() {
9 add_action( self::CRON_NAME, array( $this, 'do_update_check' ) ); // action to link cron task to actual task
10 }
11
12 public function init() {
13 global $siteguard_config;
14 $siteguard_config->set( 'notify_wpcore', '1' );
15 $siteguard_config->set( 'notify_plugins', '2' );
16 $siteguard_config->set( 'notify_themes', '2' );
17 $siteguard_config->set(
18 'notified',
19 array(
20 'core' => '',
21 'plugin' => array(),
22 'theme' => array(),
23 )
24 );
25 $siteguard_config->set( 'last_check_time', false );
26 // We need save the configuration before calling self::check_requirements.
27 $siteguard_config->update();
28 if ( true === self::check_requirements() ) {
29 $siteguard_config->set( 'updates_notify_enable', '1' );
30 $siteguard_config->update();
31 self::feature_on();
32 } else {
33 $siteguard_config->set( 'updates_notify_enable', '0' );
34 $siteguard_config->update();
35 // The feature reads as OFF from here on, so the cron event has to go
36 // with it. An event scheduled while the requirements were still met
37 // survives an install whose deactivation hook never ran (a directory
38 // replaced over FTP, for instance), and it would keep sending mail.
39 self::feature_off();
40 }
41 }
42 public static function check_requirements() {
43 $error = siteguard_check_multisite();
44 if ( is_wp_error( $error ) ) {
45 return $error;
46 }
47 $error = self::check_disable_wp_cron();
48 if ( is_wp_error( $error ) ) {
49 return $error;
50 }
51 $error = self::check_wp_cron_access();
52 if ( is_wp_error( $error ) ) {
53 return $error;
54 }
55 return true;
56 }
57 static function check_disable_wp_cron() {
58 if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) {
59 $message = esc_html__( 'DISABLE_WP_CRON is set to true. This feature cannot be used.', 'siteguard' );
60 $error = new WP_Error( 'siteguard_updates_notify', $message );
61 return $error;
62 }
63 return true;
64 }
65 static function check_wp_cron_access() {
66 $result = wp_remote_post( site_url( '/wp-cron.php' ) );
67 if ( ! is_wp_error( $result ) && 200 === $result['response']['code'] ) {
68 return true;
69 }
70 $message = esc_html__( 'wp-cron.php cannot be accessed. This may be caused by access control settings.', 'siteguard' );
71 $error = new WP_Error( 'siteguard_updates_notify', $message );
72 return $error;
73 }
74 public static function feature_on() {
75 // Already scheduled
76 if ( false !== wp_get_schedule( self::CRON_NAME ) ) {
77 return;
78 }
79
80 // Schedule cron for this plugin.
81 wp_schedule_event( time(), 'daily', self::CRON_NAME );
82 }
83
84 public static function feature_off() {
85 wp_clear_scheduled_hook( self::CRON_NAME ); // clear cron
86 }
87
88 public function do_update_check() {
89 global $siteguard_config;
90 // The setting decides, not the presence of the cron event. The two can
91 // drift apart -- the event outlives an install whose deactivation hook
92 // never ran, and it used to be left behind whenever check_requirements()
93 // turned the feature off -- and this handler is registered on every
94 // request regardless of the setting. Sites in that state kept sending
95 // notifications with the setting showing OFF. Drop the orphaned event on
96 // the way out so those installs repair themselves on the next run.
97 if ( '1' != $siteguard_config->get( 'updates_notify_enable' ) ) {
98 self::feature_off();
99 return;
100 }
101 $message = ''; // start with a blank message //
102 // Only the values the settings page can produce enable a check. The test
103 // used to be `'0' != get()`, and get() returns '' for a key that is not
104 // stored, so a configuration missing these keys counted as fully enabled.
105 $notify_wpcore = $siteguard_config->get( 'notify_wpcore' );
106 $notify_plugins = $siteguard_config->get( 'notify_plugins' );
107 $notify_themes = $siteguard_config->get( 'notify_themes' );
108 if ( '1' == $notify_wpcore ) { // are we to check for WordPress core?
109 $core_updated = self::core_update_check( $message ); // check the WP core for updates
110 } else {
111 $core_updated = false; // no core updates
112 }
113 if ( '1' == $notify_plugins || '2' == $notify_plugins ) { // are we to check for plugin updates? //
114 $plugins_updated = self::plugins_update_check( $message, $notify_plugins ); // check for plugin updates
115 } else {
116 $plugins_updated = false; // no plugin updates
117 }
118 if ( '1' == $notify_themes || '2' == $notify_themes ) { // are we to check for theme updates? //
119 $themes_updated = self::themes_update_check( $message, $notify_themes ); // check for theme updates //
120 } else {
121 $themes_updated = false; // no theme updates
122 }
123 if ( $core_updated || $plugins_updated || $themes_updated ) { // Did anything come back as need updating?
124 $message = esc_html__( 'There are updates available for your WordPress site:', 'siteguard' ) . "\n" . $message . "\n";
125 $message .= sprintf( esc_html__( 'Please visit %s to update.', 'siteguard' ), admin_url( 'update-core.php' ) ) . "\n\n--\nSiteGuard WP Plugin";
126 self::send_notify( $message ); // send our notification email.
127 }
128
129 self::log_last_check_time();
130 }
131
132 private static function core_update_check( &$message ) {
133 global $siteguard_config, $wp_version;
134 do_action( 'wp_version_check' ); // force WP to check its core for updates
135 $update_core = get_site_transient( 'update_core' ); // get information of updates
136 $notified = $siteguard_config->get( 'notified' );
137 if ( 'upgrade' == $update_core->updates[0]->response ) { // is WP core update available?
138 if ( $update_core->updates[0]->current != $notified['core'] ) { // have we already notified about this version?
139 require_once ABSPATH . WPINC . '/version.php'; // Including this because some plugins can mess with the real version stored in the DB.
140 $new_core_ver = $update_core->updates[0]->current; // The new WP core version
141 $old_core_ver = $wp_version; // the old WP core version
142 $message .= "\n" . sprintf( esc_html__( 'WordPress core: Update available. Please update from version %1$s to %2$s.', 'siteguard' ), $old_core_ver, $new_core_ver ) . "\n";
143 $notified['core'] = $new_core_ver; // set core version we are notifying about
144 $siteguard_config->set( 'notified', $notified );
145 $siteguard_config->update();
146 return true; // we have updates so return true
147 } else {
148 return false; // There are updates but we have already notified in the past.
149 }
150 }
151 $notified['core'] = ''; // no updates lets set this nothing
152 $siteguard_config->set( 'notified', $notified );
153 $siteguard_config->update();
154 return false; // no updates return false
155 }
156
157 private static function plugins_update_check( &$message, $allOrActive ) {
158 global $siteguard_config, $wp_version;
159 $cur_wp_version = preg_replace( '/-.*$/', '', $wp_version );
160 $notified = $siteguard_config->get( 'notified' );
161 do_action( 'wp_update_plugins' ); // force WP to check plugins for updates
162 $update_plugins = get_site_transient( 'update_plugins' ); // get information of updates
163 if ( ! empty( $update_plugins->response ) ) { // any plugin updates available?
164 $plugins_need_update = $update_plugins->response; // plugins that need updating
165 if ( 2 == $allOrActive ) { // are we to check just active plugins?
166 $active_plugins = array_flip( get_option( 'active_plugins' ) ); // find which plugins are active
167 $plugins_need_update = array_intersect_key( $plugins_need_update, $active_plugins ); // only keep plugins that are active
168 }
169 $plugins_need_update = self::check_plugins_against_notified( $plugins_need_update ); // additional filtering of plugins need update
170 if ( is_array( $plugins_need_update ) && count( $plugins_need_update ) >= 1 ) { // any plugins need updating after all the filtering gone on above?
171 require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; // Required for plugin API
172 require_once ABSPATH . WPINC . '/version.php'; // Required for WP core version
173 foreach ( $plugins_need_update as $key => $data ) { // loop through the plugins that need updating
174 $plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $key ); // get local plugin info
175 $info = plugins_api( 'plugin_information', array( 'slug' => $data->slug ) ); // get repository plugin info
176 $message .= "\n" . sprintf( esc_html__( 'Plugin: %1$s has an update available. Please update from version %2$s to %3$s.', 'siteguard' ), $plugin_info['Name'], $plugin_info['Version'], $data->new_version ) . "\n";
177 $message .= "\t" . sprintf( esc_html__( 'Details: %s', 'siteguard' ), $data->url ) . "\n";
178 $message .= "\t" . sprintf( esc_html__( 'Changelog: %1$s%2$s', 'siteguard' ), $data->url, 'changelog/' ) . "\n";
179 if ( isset( $info->tested ) && version_compare( $info->tested, $wp_version, '>=' ) ) {
180 $compat = sprintf( esc_html__( 'Compatibility with WordPress %1$s: 100%% (according to its author)' ), $cur_wp_version );
181 } elseif ( isset( $info->compatibility[ $wp_version ][ $data->new_version ] ) ) {
182 $compat = $info->compatibility[ $wp_version ][ $data->new_version ];
183 $compat = sprintf( esc_html__( 'Compatibility with WordPress %1$s: %2$d%% (%3$d "works" votes out of %4$d total)' ), $wp_version, $compat[0], $compat[2], $compat[1] );
184 } else {
185 $compat = sprintf( esc_html__( 'Compatibility with WordPress %1$s: Unknown' ), $wp_version );
186 }
187 $message .= "\t" . sprintf( esc_html__( 'Compatibility: %s', 'siteguard' ), $compat ) . "\n";
188 $notified['plugin'][ $key ] = $data->new_version; // set plugin version we are notifying about
189 }
190 $siteguard_config->set( 'notified', $notified );
191 $siteguard_config->update();
192 return true; // we have plugin updates return true
193 }
194 } elseif ( 0 != count( $notified['plugin'] ) ) {
195 // is there any plugin notifications?
196 $notified['plugin'] = array(); // set plugin notifications to empty as all plugins up-to-date
197 $siteguard_config->set( 'notified', $notified );
198 $siteguard_config->update();
199 } //
200 return false; // No plugin updates so return false
201 }
202
203 private static function themes_update_check( &$message, $allOrActive ) {
204 global $siteguard_config;
205 $notified = $siteguard_config->get( 'notified' );
206 do_action( 'wp_update_themes' ); // force WP to check for theme updates
207 $update_themes = get_site_transient( 'update_themes' ); // get information of updates
208 if ( ! empty( $update_themes->response ) ) { // any theme updates available?
209 $themes_need_update = $update_themes->response; // themes that need updating
210 if ( 2 == $allOrActive ) { // are we to check just active themes?
211 $active_theme = array( get_option( 'template' ) => array() ); // find current theme that is active
212 $themes_need_update = array_intersect_key( $themes_need_update, $active_theme ); // only keep theme that is active
213 }
214 $themes_need_update = self::check_themes_against_notified( $themes_need_update ); // additional filtering of themes need update
215 if ( is_array( $themes_need_update ) && count( $themes_need_update ) >= 1 ) { // any themes need updating after all the filtering gone on above?
216 foreach ( $themes_need_update as $key => $data ) { // loop through the themes that need updating
217 $theme_info = wp_get_theme( $key ); // get theme info
218 $message .= "\n" . sprintf( esc_html__( 'Theme: %1$s has an update available. Please update from version %2$s to %3$s.', 'siteguard' ), $theme_info['Name'], $theme_info['Version'], $data['new_version'] ) . "\n";
219 $notified['theme'][ $key ] = $data['new_version']; // set theme version we are notifying about
220 }
221 $siteguard_config->set( 'notified', $notified );
222 $siteguard_config->update();
223 return true; // we have theme updates return true
224 }
225 } elseif ( 0 != count( $notified['theme'] ) ) {
226 // is there any theme notifications?
227 $notified['theme'] = array(); // set theme notifications to empty as all themes up-to-date
228 $siteguard_config->set( 'notified', $notified );
229 $siteguard_config->update();
230 } //
231 return false; // No theme updates so return false
232 }
233
234 public static function check_plugins_against_notified( $plugins_need_update ) {
235 global $siteguard_config;
236 $notified = $siteguard_config->get( 'notified' );
237 if ( is_array( $plugins_need_update ) ) {
238 foreach ( $plugins_need_update as $key => $data ) { // loop through plugins that need update
239 if ( isset( $notified['plugin'][ $key ] ) ) { // has this plugin been notified before?
240 if ( $data->new_version == $notified['plugin'][ $key ] ) { // does this plugin version match that of the one that's been notified?
241 unset( $plugins_need_update[ $key ] ); // don't notify this plugin as has already been notified
242 }
243 }
244 }
245 }
246 return $plugins_need_update;
247 }
248
249 public static function check_themes_against_notified( $themes_need_update ) {
250 global $siteguard_config;
251 $notified = $siteguard_config->get( 'notified' );
252 if ( is_array( $themes_need_update ) ) {
253 foreach ( $themes_need_update as $key => $data ) { // loop through themes that need update
254 if ( isset( $notified['theme'][ $key ] ) ) { // has this theme been notified before?
255 if ( $data['new_version'] == $notified['theme'][ $key ] ) { // does this theme version match that of the one that's been notified?
256 unset( $themes_need_update[ $key ] ); // don't notify this theme as has already been notified
257 }
258 }
259 }
260 }
261 return $themes_need_update;
262 }
263
264 public function send_notify( $message ) {
265 global $siteguard_config;
266 $subject = sprintf( esc_html__( 'WordPress: Updates available for %s', 'siteguard' ), home_url() );
267
268 $user_query = new WP_User_Query( array( 'role' => 'Administrator' ) );
269 if ( is_array( $user_query->results ) ) {
270 foreach ( $user_query->results as $user ) {
271 $user_email = $user->get( 'user_email' );
272 if ( true !== @wp_mail( $user_email, $subject, $message ) ) {
273 siteguard_error_log( 'Failed send mail. To:' . $user_email . ' Subject:' . esc_html( $subject ) );
274 }
275 }
276 }
277 }
278
279 private function log_last_check_time() {
280 global $siteguard_config;
281 $siteguard_config->set( 'last_check_time', current_time( 'timestamp' ) );
282 $siteguard_config->update();
283 }
284
285 private static function get_schedules() {
286 $schedules = wp_get_schedules();
287 uasort( $schedules, array( __CLASS__, 'sort_by_interval' ) );
288 return $schedules;
289 }
290
291
292 private static function get_intervals() {
293 $intervals = array_keys( self::get_schedules() );
294 return $intervals;
295 }
296
297
298 private static function sort_by_interval( $a, $b ) {
299 return $a['interval'] - $b['interval'];
300 }
301 }
302