settingsUpToDate(); // Create Activation and Deactivation Hooks register_activation_hook(__FILE__, array(&$this, 'activate')); register_deactivation_hook(__FILE__, array(&$this, 'deactivate')); // Internationalization load_plugin_textdomain('wp-updates-notifier', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/'); // Add Filters add_filter('plugin_action_links', array(&$this, 'plugin_action_links'), 10, 2); // Add settings link to plugin in plugin list add_filter('sc_wpun_plugins_need_update', array(&$this, 'check_plugins_against_notified')); // Filter out plugins that need update if already been notified add_filter('sc_wpun_themes_need_update', array(&$this, 'check_themes_against_notified')); // Filter out themes that need update if already been notified // Add Actions add_action('admin_menu', array(&$this, 'admin_settings_menu')); // Add menu to options add_action('admin_init', array(&$this, 'admin_settings_init')); // Add admin init functions add_action('admin_init', array(&$this, 'remove_update_nag_for_nonadmins')); // See if we remove update nag for non admins add_action('sc_wpun_enable_cron', array(&$this, 'enable_cron')); // action to enable cron add_action('sc_wpun_disable_cron', array(&$this, 'disable_cron')); // action to disable cron add_action(self::$cron_name, array(&$this, 'do_update_check')); // action to link cron task to actual task } /** * Check if this plugin settings are up to date. Firstly check the version in * the DB. If they don't match then load in defaults but don't override values * already set. Also this will remove obsolete settings that are not needed. * * @return void */ protected function settingsUpToDate() { $current_ver = get_option(self::$options_field_ver); // Get current plugin version if(self::$options_field_current_ver != $current_ver) { // is the version the same as this plugin? $options = (array) get_option(self::$options_field); // get current settings from DB $defaults = array( // Here are our default values for this plugin 'frequency' => self::$frequency_intervals[0], 'notify_to' => get_option('admin_email'), 'notify_from' => get_option('admin_email'), 'notify_plugins' => 1, 'notify_themes' => 1, 'hide_updates' => 1, 'notified' => array( 'core' => 0, 'plugin' => array(), 'theme' => array(), ) ); // Intersect current options with defaults. Basically removing settings that are obsolete $options = array_intersect_key($options, $defaults); // Merge current settings with defaults. Basically adding any new settings with defaults that we dont have. $options = array_merge($defaults, $options); update_option(self::$options_field, $options); // update settings update_option(self::$options_field_ver, self::$options_field_current_ver); // update settings version } } /** * Function that deals with activation of this plugin * * @return void */ public function activate() { do_action("sc_wpun_enable_cron"); // Enable cron } /** * Function that deals with de-activation of this plugin * * @return void */ public function deactivate() { do_action("sc_wpun_disable_cron"); // Disable cron } /** * Enable cron for this plugin. Check if a cron should be scheduled. * * @param bool|string $manual_interval For setting a manual cron interval. * @return void */ public function enable_cron($manual_interval = false) { $options = get_option(self::$options_field); // get current settings $currentSchedule = wp_get_schedule(self::$cron_name); // find if a schedule already exists if(false !== $manual_interval) {$options['frequency'] = $manual_interval;} // if a manual cron interval is set, use this if($currentSchedule != $options['frequency']) { // check if the current schedule matches the one set in settings if(in_array($options['frequency'], self::$frequency_intervals)) { // check the cron setting is valid do_action("sc_wpun_disable_cron"); // remove any crons for this plugin first so we don't end up with multiple crons doing the same thing. wp_schedule_event(time(), $options['frequency'], self::$cron_name); // schedule cron for this plugin. } } } /** * Removes cron for this plugin. * * @return void */ public function disable_cron() { wp_clear_scheduled_hook(self::$cron_name); // clear cron } /** * Adds the settings link under the plugin on the plugin screen. * * @param array $links * @param string $file * @return array $links */ public function plugin_action_links($links, $file) { static $this_plugin; if (!$this_plugin) { $this_plugin = plugin_basename(__FILE__); } if ($file == $this_plugin){ $settings_link = ''.__("Settings", "wp-updates-notifier").''; array_unshift($links, $settings_link); } return $links; } /** * This is run by the cron. The update check checks the core always, the * plugins and themes if asked. If updates found email notification sent. * * @return void */ public function do_update_check() { $options = get_option(self::$options_field); // get settings $message = ""; // start with a blank message $core_updated = $this->core_update_check(&$message); // check the WP core for updates if(0 != $options['notify_plugins']) { // are we to check for plugin updates? $plugins_updated = $this->plugins_update_check(&$message, $options['notify_plugins']); // check for plugin updates } else { $plugins_updated = false; // no plugin updates } if(0 != $options['notify_themes']) { // are we to check for theme updates? $themes_updated = $this->themes_update_check(&$message, $options['notify_themes']); // check for theme updates } else { $themes_updated = false; // no theme updates } if ($core_updated || $plugins_updated || $themes_updated) { // Did anything come back as need updating? $message = __("There are updates available for your WordPress site:", "wp-updates-notifier")."\n\n".$message."\n"; $message .= sprintf(__("Please visit %s to update.", "wp-updates-notifier"), admin_url('update-core.php')); $this->send_notification_email($message); // send our notification email. } } /** * Checks to see if any WP core updates * * @param string $message holds message to be sent via notification * @return bool */ protected function core_update_check(&$message) { $settings = get_option(self::$options_field); // get settings do_action("wp_version_check"); // force WP to check its core for updates $update_core = get_site_transient("update_core"); // get information of updates if('upgrade' == $update_core->updates[0]->response) { // is WP core update available? if($update_core->updates[0]->current != $settings['notified']['core']) { // have we already notified about this version? include( ABSPATH . WPINC . '/version.php' ); // Including this because some plugins can mess with the real version stored in the DB. $new_core_ver = $update_core->updates[0]->current; // The new WP core version $old_core_ver = $wp_version; // the old WP core version $message .= sprintf(__("WP-Core: WordPress is out of date. Please update from version %s to %s", "wp-updates-notifier"), $old_core_ver, $new_core_ver)."\n"; $settings['notified']['core'] = $new_core_ver; // set core version we are notifying about update_option(self::$options_field, $settings); // update settings return true; // we have updates so return true } } $settings['notified']['core'] = 0; // no updates lets set this 0 update_option(self::$options_field, $settings); // update settings return false; // no updates return false } /** * Check to see if any plugin updates. * * @param string $message holds message to be sent via notification * @param int $allOrActive should we look for all plugins or just active ones * @return bool */ protected function plugins_update_check(&$message, $allOrActive) { $settings = get_option(self::$options_field); // get settings do_action("wp_update_plugins"); // force WP to check plugins for updates $update_plugins = get_site_transient('update_plugins'); // get information of updates if (!empty($update_plugins->response)) { // any plugin updates available? $plugins_need_update = $update_plugins->response; // plugins that need updating if(2 == $allOrActive) { // are we to check just active plugins? $active_plugins = array_flip(get_option('active_plugins')); // find which plugins are active $plugins_need_update = array_intersect_key($plugins_need_update, $active_plugins); // only keep plugins that are active } $plugins_need_update = apply_filters('sc_wpun_plugins_need_update', $plugins_need_update); // additional filtering of plugins need update if(count($plugins_need_update) >= 1) { // any plugins need updating after all the filtering gone on above? foreach($plugins_need_update as $key => $data) { // loop through the plugins that need updating $plugin_info = get_plugin_data(WP_PLUGIN_DIR . "/" . $key); // get plugin info $message .= sprintf(__("Plugin: %s is out of date. Please update from version %s to %s", "wp-updates-notifier"), $plugin_info['Name'], $plugin_info['Version'], $data->new_version)."\n"; $settings['notified']['plugin'][$key] = $data->new_version; // set plugin version we are notifying about } update_option(self::$options_field, $settings); // save settings return true; // we have plugin updates return true } } else { if(0 != count($settings['notified']['plugin'])) { // is there any plugin notifications? $settings['notified']['plugin'] = array(); // set plugin notifications to empty as all plugins up-to-date update_option(self::$options_field, $settings); // save settings } } return false; // No plugin updates so return false } /** * Check to see if any theme updates. * * @param string $message holds message to be sent via notification * @param int $allOrActive should we look for all themes or just active ones * @return bool */ protected function themes_update_check(&$message, $allOrActive) { $settings = get_option(self::$options_field); // get settings do_action("wp_update_themes"); // force WP to check for theme updates $update_themes = get_site_transient('update_themes'); // get information of updates if (!empty($update_themes->response)) { // any theme updates available? $themes_need_update = $update_themes->response; // themes that need updating if(2 == $allOrActive) { // are we to check just active themes? $active_theme = array(get_option('template') => array()); // find current theme that is active $themes_need_update = array_intersect_key($themes_need_update, $active_theme); // only keep theme that is active } $themes_need_update = apply_filters('sc_wpun_themes_need_update', $themes_need_update); // additional filtering of themes need update if(count($themes_need_update) >= 1) { // any themes need updating after all the filtering gone on above? foreach($themes_need_update as $key => $data) { // loop through the themes that need updating $theme_info = get_theme_data(WP_CONTENT_DIR . "/themes/" . $key . "/style.css"); // get theme info $message .= sprintf(__("Theme: %s is out of date. Please update from version %s to %s", "wp-updates-notifier"), $theme_info['Name'], $theme_info['Version'], $data['new_version'])."\n"; $settings['notified']['theme'][$key] = $data['new_version']; // set theme version we are notifying about } update_option(self::$options_field, $settings); // save settings return true; // we have theme updates return true } } else { if(0 != count($settings['notified']['theme'])) { // is there any theme notifications? $settings['notified']['theme'] = array(); // set theme notifications to empty as all themes up-to-date update_option(self::$options_field, $settings); // save settings } } return false; // No theme updates so return false } /** * Filter for removing plugins from update list if already been notified about * * @param array $plugins_need_update * @return array $plugins_need_update */ public function check_plugins_against_notified($plugins_need_update) { $settings = get_option(self::$options_field); // get settings foreach($plugins_need_update as $key => $data) { // loop through plugins that need update if(isset($settings['notified']['plugin'][$key])) { // has this plugin been notified before? if($data->new_version == $settings['notified']['plugin'][$key]) { // does this plugin version match that of the one that's been notified? unset($plugins_need_update[$key]); // don't notify this plugin as has already been notified } } } return $plugins_need_update; } /** * Filter for removing themes from update list if already been notified about * * @param array $themes_need_update * @return array $themes_need_update */ public function check_themes_against_notified($themes_need_update) { $settings = get_option(self::$options_field); // get settings foreach($themes_need_update as $key => $data) { // loop through themes that need update if(isset($settings['notified']['theme'][$key])) { // has this theme been notified before? if($data['new_version'] == $settings['notified']['theme'][$key]) { // does this theme version match that of the one that's been notified? unset($themes_need_update[$key]); // don't notify this theme as has already been notified } } } return $themes_need_update; } /** * Sends email notification. * * @param string $message holds message to be sent in body of email * @return void */ public function send_notification_email($message) { $settings = get_option(self::$options_field); // get settings $subject = sprintf(__("WP Updates Notifier: Updates Available @ %s", "wp-updates-notifier"), site_url()); add_filter('wp_mail_from', array(&$this, 'sc_wpun_wp_mail_from')); // add from filter add_filter('wp_mail_from_name', array(&$this, 'sc_wpun_wp_mail_from_name')); // add from name filter add_filter('wp_mail_content_type', array(&$this, 'sc_wpun_wp_mail_content_type')); // add content type filter wp_mail($settings['notify_to'], $subject, $message); // send email remove_filter('wp_mail_from', array(&$this, 'sc_wpun_wp_mail_from')); // remove from filter remove_filter('wp_mail_from_name', array(&$this, 'sc_wpun_wp_mail_from_name')); // remove from name filter remove_filter('wp_mail_content_type', array(&$this, 'sc_wpun_wp_mail_content_type')); // remove content type filter } public function sc_wpun_wp_mail_from() { $settings = get_option(self::$options_field); return $settings['notify_from']; } public function sc_wpun_wp_mail_from_name() { return __("WP Updates Notifier", "wp-updates-notifier"); } public function sc_wpun_wp_mail_content_type() { return "text/plain"; } /** * Removes the update nag for non admin users. * * @return void */ public function remove_update_nag_for_nonadmins() { $settings = get_option(self::$options_field); // get settings if(1 == $settings['hide_updates']) { // is this enabled? if (!current_user_can('update_plugins')) { // can the current user update plugins? remove_action('admin_notices', 'update_nag', 3); // no they cannot so remove the nag for them. } } } /* * EVERYTHING SETTINGS * * I'm not going to comment any of this as its all pretty * much straight forward use of the WordPress Settings API. */ public function admin_settings_menu() { $page = add_options_page('WP Updates Notifier', 'WP Updates Notifier', 'manage_options', 'wp-updates-notifier', array(&$this, 'settings_page')); } public function settings_page() { ?>