/** * Sets up and stores any pre upgrade information * that will be used for notifications. * * @access public * @since 1.0.0 */ public function handle_pre_upgrade_information() { global $wp_version; // Get current filter $current_filter = preg_replace('/^admin\\_action\\_/i', '', current_filter()); // Going to store pre-upgrade plugin/theme/core info for // notification that gets sent out after update $pre_upgrade_info = array(); // Will hold type info for processing $plugins = array(); $themes = array(); switch ($current_filter) { case 'upgrade-plugin': $plugins[] = isset($_REQUEST['plugin']) ? trim($_REQUEST['plugin']) : null; break; case 'do-plugin-upgrade': $plugins = isset($_GET['plugins']) ? explode(',', $_GET['plugins']) : (isset($_POST['checked']) ? (array) $_POST['checked'] : false); break; case 'update-selected': $plugins = isset($_GET['plugins']) ? explode(',', stripslashes($_GET['plugins'])) : (isset($_POST['checked']) ? (array) $_POST['checked'] : false); break; case 'upgrade-theme': $themes[] = isset($_REQUEST['theme']) ? urldecode($_REQUEST['theme']) : null; break; case 'do-theme-upgrade': $themes = isset($_GET['themes']) ? explode(',', $_GET['themes']) : (isset($_POST['checked']) ? (array) $_POST['checked'] : false); break; case 'update-selected-themes': $themes = isset($_GET['themes']) ? explode(',', stripslashes($_GET['themes'])) : (isset($_POST['checked']) ? (array) $_POST['checked'] : false); break; case 'upgrade-core': case 'do-core-upgrade': case 'do-core-reinstall': $pre_upgrade_info['core'] = array('version' => $wp_version); break; } // Process plugins if ($plugins) { foreach ($plugins as $plugin_file) { if ($plugin = get_plugin_data(WP_CONTENT_DIR . '/plugins/' . $plugin_file)) { $pre_upgrade_info[$plugin_file] = $plugin; } } } // Process themes if ($themes) { foreach ($themes as $theme_name) { if ($theme = wp_get_theme($theme_name)) { $pre_upgrade_info[$theme_name] = $theme; } } } // Store the info if ($pre_upgrade_info) { if (rock_the_slackbot()->is_network_active) { set_site_transient('rock_the_slackbot_pre_upgrade_information', $pre_upgrade_info, 60); } else { set_transient('rock_the_slackbot_pre_upgrade_information', $pre_upgrade_info, 60); } } }
/** * Sends a notification to Slack when * core, plugins, or themes are updated. * * Fires when the bulk upgrader process is complete. * * In $upgrade_info: * 'action' is always 'update' * 'type': 'plugin', 'theme' or 'core' * 'bulk': will be boolean true if true, might not always exist * 'plugins': will hold array of plugins being updated * 'themes': will hold array of themes being updated * * @access public * @since 1.0.0 * @param Plugin_Upgrader - $upgrader * upgrader instance: Plugin_Upgrader, Theme_Upgrader or Core_Upgrade * @param array - $upgrade_info - Array of bulk item update data. * @type string $action Type of action. Default 'update'. * @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'. * @type bool $bulk Whether the update process is a bulk update. Default true. * @type array $packages Array of plugin, theme, or core packages to update. * @return bool - returns false if nothing happened */ public function upgrade_notification($upgrader, $upgrade_info) { global $wp_version; // Make sure the action is update. if (!(!empty($upgrade_info['action']) && 'update' == strtolower($upgrade_info['action']))) { return false; } // Make sure we have a valid type. $upgrade_type = !empty($upgrade_info['type']) ? strtolower($upgrade_info['type']) : false; if (!in_array($upgrade_type, array('core', 'plugin', 'theme'))) { return false; } // Which event are we processing? $notification_event = "{$upgrade_type}_updated"; // Get the outgoing webhooks. $outgoing_webhooks = $this->get_outgoing_webhooks($notification_event); // If we have no webhooks, then there's no point. if (!$outgoing_webhooks) { return false; } // Is this a bulk upgrade? $is_bulk = !empty($upgrade_info['bulk']) && $upgrade_info['bulk'] > 0 ? true : false; // Get upgrade items (if applicable). $upgrade_item_index = $is_bulk ? "{$upgrade_type}s" : $upgrade_type; $upgrade_items = 'core' == $upgrade_type ? false : (!empty($upgrade_info[$upgrade_item_index]) ? $upgrade_info[$upgrade_item_index] : false); // Convert to array. if (!is_array($upgrade_items)) { $upgrade_items = explode(',', $upgrade_items); } // Get the pre upgrade info. if (rock_the_slackbot()->is_network_active) { $pre_upgrade_info = get_site_transient('rock_the_slackbot_pre_upgrade_information'); delete_site_transient('rock_the_slackbot_pre_upgrade_information'); } else { $pre_upgrade_info = get_transient('rock_the_slackbot_pre_upgrade_information'); delete_transient('rock_the_slackbot_pre_upgrade_information'); } // Get current user. $current_user = wp_get_current_user(); // Get site URL and name. $site_url = get_bloginfo('url'); $site_name = get_bloginfo('name'); // Create general message for the notification. $general_message = null; // Set the message for the different updates. if ('core' == $upgrade_type) { $general_message = "WordPress {$upgrade_type} has"; } else { // Start the message. $general_message = "The following WordPress {$upgrade_type}"; // Depending on how many are being updated. if (count($upgrade_items) == 1) { $general_message .= ' has'; } else { $general_message .= 's have'; } } // Add on to the message. $general_message .= ' been updated'; // Include the core version. if ('core' == $upgrade_type) { if (!empty($pre_upgrade_info['core']['version'])) { $general_message .= ' from version ' . $pre_upgrade_info['core']['version']; } $general_message .= ' to ' . $wp_version; } // Add the use who updated. if (false !== $current_user && !empty($current_user->display_name)) { $general_message .= ' by ' . $current_user->display_name; } // Finish the message. $general_message .= ' on the ' . $site_name . ' website at <' . $site_url . '>.'; // Loop through each webhook and send the notification. foreach ($outgoing_webhooks as $hook) { // We must have a webhook URL. if (empty($hook['webhook_url'])) { continue; } // Start creating the payload. $payload = array('text' => $general_message); // Create attachments. $attachments = array(); // Will hold the event info we want to pass to the filters. $event_args = array(); /* * Get event info for core upgrade type. * * Add some more info for plugins and themes. */ if ('core' != $upgrade_type) { // Store version numbers for the filters. $event_args['current_version'] = $wp_version; $event_args['old_version'] = $pre_upgrade_info['core']['version']; } elseif ('core' != $upgrade_type) { // Store the upgrade item(s) for themes and plugins. $event_args[$upgrade_type] = $upgrade_items; // Add upgrade items to the fields. if ($upgrade_items) { foreach ($upgrade_items as $item) { // Get pre upgrade info. $item_pre_upgrade_info = isset($pre_upgrade_info) && !empty($pre_upgrade_info[$item]) ? $pre_upgrade_info[$item] : false; /* * Get item data. * * @TODO: * For some reason wp_get_theme() is picking up the old version instead of new one. */ $item_data = 'plugin' == $upgrade_type ? get_plugin_data(WP_CONTENT_DIR . '/plugins/' . $item) : wp_get_theme($item); // Set item title. $item_title = 'plugin' == $upgrade_type ? !empty($item_data['Name']) ? $item_data['Name'] : false : $item_data->get('Name'); // Set item URI. $item_uri = 'plugin' == $upgrade_type ? !empty($item_data['PluginURI']) ? $item_data['PluginURI'] : false : $item_data->get('ThemeURI'); // Set item description. $item_desc = 'plugin' == $upgrade_type ? !empty($item_data['Description']) ? strip_tags(html_entity_decode($item_data['Description'])) : false : $item_data->get('Description'); // Set item author name. $author_name = 'plugin' == $upgrade_type ? !empty($item_data['AuthorName']) ? $item_data['AuthorName'] : false : $item_data->get('Author'); // Set item author URI. $author_uri = 'plugin' == $upgrade_type ? !empty($item_data['AuthorURI']) ? $item_data['AuthorURI'] : false : $item_data->get('AuthorURI'); // Set item version. $item_version = 'plugin' == $upgrade_type ? !empty($item_data['Version']) ? $item_data['Version'] : false : $item_data->get('Version'); // Get previous version. $previous_version = 'plugin' == $upgrade_type ? !empty($item_pre_upgrade_info['Version']) ? $item_pre_upgrade_info['Version'] : false : $item_pre_upgrade_info->get('Version'); // Start creating the fields. $fields = array(); // Add version. $fields[] = array('title' => __('Current Version', 'rock-the-slackbot'), 'value' => $item_version, 'short' => true); // Add previous version. if ($previous_version) { $fields[] = array('title' => __('Previous Version', 'rock-the-slackbot'), 'value' => $previous_version, 'short' => true); } // Add plugin URI. $fields[] = array('title' => sprintf(__('Manage %s', 'rock-the-slackbot'), ucwords($upgrade_type) . 's'), 'value' => is_multisite() ? network_admin_url("{$upgrade_type}s.php") : admin_url("{$upgrade_type}s.php"), 'short' => true); // Add to attachments. $attachments[] = array('fallback' => $general_message, 'text' => wp_trim_words(strip_tags($item_desc), 30, '...'), 'title' => $item_title, 'title_link' => $item_uri, 'author_name' => $author_name, 'author_link' => $author_uri, 'fields' => $fields); } } } // Send each webhook. $this->send_outgoing_webhooks($notification_event, $outgoing_webhooks, $payload, $attachments); } }
/** * Handles when someone wants to delete an outgoing webhook. * * @access public * @since 1.0.0 */ public function delete_outgoing_webhook() { // Check for our page if (!(isset($_REQUEST['page']) && 'rock-the-slackbot' == $_REQUEST['page'])) { return false; } // Make sure we have a webhook ID to delete if (!($hook_id = isset($_REQUEST['delete']) ? $_REQUEST['delete'] : false)) { return false; } // Check for our nonce name if (!($nonce = isset($_REQUEST['_wpnonce']) ? $_REQUEST['_wpnonce'] : false)) { return false; } // Check the nonce itself if (!wp_verify_nonce($nonce, 'rts_delete_outgoing_webhook')) { $die_message = __('Oops. Looks like something went wrong.', 'rock-the-slackbot'); wp_die($die_message, $die_message, array('back_link' => true)); } // Get all of the outgoing webhooks if ($outgoing_webhooks = rock_the_slackbot()->get_all_outgoing_webhooks()) { // Will be true if we deleted a hook $deleted_hook = false; foreach ($outgoing_webhooks as $webhook_index => $webhook) { // Delete this specific webhook if (isset($webhook['ID']) && $hook_id == $webhook['ID']) { unset($outgoing_webhooks[$webhook_index]); $deleted_hook = true; } } // If we deleted, update the option if ($deleted_hook) { // If an empty array, then make null if (empty($outgoing_webhooks)) { $outgoing_webhooks = null; } else { $outgoing_webhooks = array_values($outgoing_webhooks); } // Update the option update_option('rock_the_slackbot_outgoing_webhooks', $outgoing_webhooks); // Webhook deleted // Redirect to the main page and prompt message wp_redirect(add_query_arg(array('page' => 'rock-the-slackbot', 'webhook_deleted' => 1), admin_url('tools.php'))); exit; } } // This means there was no webhook with this ID // Redirect to the main page and prompt message wp_redirect(add_query_arg(array('page' => 'rock-the-slackbot', 'error_deleting_webhook' => 1), admin_url('tools.php'))); exit; }
/** * Sends a payload notification to Slack. * * @access public * @since 1.0.0 * @param string - $webhook_url - send the payload to this URL * @param array - $payload - the notification information * @return boolean - whether or not it was sent without error */ function send_notification($webhook_url, $payload = array()) { // Set defaults $payload_defaults = array('channel' => null, 'username' => get_bloginfo('name'), 'text' => __('This is a WordPress to Slack notification', 'rock-the-slackbot'), 'icon_emoji' => null, 'icon_url' => trailingslashit(plugin_dir_url(dirname(__FILE__))) . 'images/wordpress-icon-emoji.png', 'attachments' => array()); // Mix payload with defaults $payload = wp_parse_args($payload, $payload_defaults); // Set attachment defaults $attachment_defaults = array('fallback' => null, 'color' => '#21759b', 'pretext' => null, 'text' => null, 'title' => null, 'title_link' => null, 'author_name' => null, 'author_link' => null, 'author_icon' => null, 'image_url' => null, 'thumb_url' => null, 'fields' => array()); // Set field defaults $field_defaults = array('title' => null, 'value' => null, 'short' => false); // Go through each attachment and mix with defaults if (!empty($payload['attachments']) && is_array($payload['attachments'])) { // Setup each attachment foreach ($payload['attachments'] as &$attachment) { // Mix attachment with defaults $attachment = wp_parse_args($attachment, $attachment_defaults); // Go through each attachment and mix with defaults if (!empty($attachment['fields']) && is_array($attachment['fields'])) { // Setup each field foreach ($attachment['fields'] as &$field) { // Mix field with defaults $field = wp_parse_args($field, $field_defaults); } } } } // Allows you to filter notifications $notification_pieces = (array) apply_filters_ref_array('rock_the_slackbot_notification', array(compact(array('webhook_url', 'payload')))); // Extract the filtered notification pieces extract($notification_pieces); // No point if we don't have a channel if (!$payload['channel']) { return false; } // Send to Slack $slack_response = wp_remote_post($webhook_url, array('body' => json_encode($payload), 'headers' => array('Content-Type' => 'application/json'))); // If there's an error, send an email if (is_wp_error($slack_response)) { // @TODO add settings to disable this or change who the email goes to // @TODO be able to filter this email // Set email to be HTML add_filter('wp_mail_content_type', array($this, 'set_html_content_type')); // Build email message $message = __('There was an error when trying to post to Slack from WordPress.', 'rock-the-slackbot'); // Add payload URL and channel $message .= "\n\n<br /><br /><strong>" . __('Payload URL', 'rock-the-slackbot') . ":</strong> {$webhook_url}"; $message .= "\n<br /><strong>" . __('Channel', 'rock-the-slackbot') . ":</strong> " . $payload['channel']; // Fix any links in the general text message if (!empty($payload['text'])) { // Replace Slack links $payload['text'] = rock_the_slackbot()->unformat_slack_links($payload['text']); } // Add general message $message .= "\n\n<br /><br /><strong>" . __('Message', 'rock-the-slackbot') . ":</strong> " . $payload['text']; // Add attachment info if (isset($payload['attachments'])) { $message .= "\n\n<br /><br /><strong>" . __('Attachments', 'rock-the-slackbot') . ":</strong>"; foreach ($payload['attachments'] as $attachment) { $message .= "\n<br />"; // Add fields if (isset($attachment['fields'])) { foreach ($attachment['fields'] as $field) { $message .= "\n\t<br /> <strong>" . $field['title'] . ":</strong> " . $field['value']; } } } } // Send email notification to the admin wp_mail(get_bloginfo('admin_email'), __('WordPress to Slack error', 'rock-the-slackbot'), $message); // Reset content-type to avoid conflicts remove_filter('wp_mail_content_type', array($this, 'set_html_content_type')); // Return an error return new WP_Error('slack_notification_error', $slack_response->get_error_message()); } return true; }
/** * Retrieves saved outgoing webhooks. * * If event names are passed, then only * retrieves webhooks tied to the event(s). * * @access private * @since 1.0.0 * @param string|array - $events - when you want webhooks tied to specific events * @param array - $event_data - allows hooks to pass event specific data to test with webhooks * @return array|false - the webhooks or false if none */ private function get_outgoing_webhooks($events = null, $event_data = array()) { return rock_the_slackbot()->get_outgoing_webhooks($events, $event_data); }
{ // Get all outgoing webhooks if (!($outgoing_webhooks = $this->get_all_outgoing_webhooks())) { return false; } // Go through and find one with ID foreach ($outgoing_webhooks as $hook) { if (isset($hook['ID']) && $hook['ID'] == $hook_id) { return $hook; } } return false; } } /** * Returns the instance of our main Rock_The_Slackbot class. * * Will come in handy when we need to access the * class to retrieve data throughout the plugin. * * @since 1.0.0 * @access public * @return Rock_The_Slackbot */ function rock_the_slackbot() { return Rock_The_Slackbot::instance(); } // Let's get this show on the road rock_the_slackbot();
/** * Is used on the settings page to run an * AJAX call to test the provided webhook URL. * * @access public * @since 1.1.1 */ public function ajax_test_webhook_url() { // Set the passed webhook URL. $webhook_url = !empty($_POST['webhook_url']) ? $_POST['webhook_url'] : null; // We must have a URL and message. if ($webhook_url) { // Set the passed channel. $channel = !empty($_POST['channel']) ? $_POST['channel'] : array(); // Make sure its an array. if (!is_array($channel)) { $channel = explode(',', str_replace(' ', '', $channel)); } // Make sure we only pass one channel. if (!empty($channel) && count($channel) > 1) { $channel = array_shift($channel); } // Get site URL and name for message. $site_url = get_bloginfo('url'); $site_name = get_bloginfo('name'); // Set the test message. $message = sprintf(__('This is a Rock The Slackbot test message from the %1$s website at <%2$s>.', 'rock-the-slackbot'), $site_name, $site_url); // Try sending the message. $send_message = rock_the_slackbot()->send_webhook_message($webhook_url, $message, $channel); // Return a message to the JS. if (is_wp_error($send_message)) { echo json_encode(array('error' => $send_message)); } else { echo json_encode(array('sent' => $send_message)); } } die; }
/** * Send the "error" email when sending a payload fails. * * @since 1.2.0 * @param string - the email address. * @param array - the email arguments. */ public function send_error_email($email, $args = array()) { // Define the defaults. $defaults = array('webhook_url' => '', 'payload' => ''); // Merge incoming arguments. $args = wp_parse_args($args, $defaults); // Build email message. $message = __('There was an error when trying to post to Slack from WordPress.', 'rock-the-slackbot'); // Add payload URL. if (!empty($args['webhook_url'])) { $message .= "\n\n<br /><br /><strong>" . __('Payload URL', 'rock-the-slackbot') . ':</strong> ' . $args['webhook_url']; } // Add payload channel. if (!empty($args['payload']['channel'])) { $message .= "\n<br /><strong>" . __('Channel', 'rock-the-slackbot') . ':</strong> ' . $args['payload']['channel']; } // Fix any links in the general text message. if (!empty($args['payload']['text'])) { // Replace Slack links. $args['payload']['text'] = rock_the_slackbot()->unformat_slack_links($args['payload']['text']); // Add general message. $message .= "\n\n<br /><br /><strong>" . __('Message', 'rock-the-slackbot') . ':</strong> ' . $args['payload']['text']; } // Add attachment info. if (!empty($args['payload']['attachments'])) { $message .= "\n\n<br /><br /><strong>" . __('Attachments', 'rock-the-slackbot') . ':</strong>'; foreach ($args['payload']['attachments'] as $attachment) { $message .= "\n<br />"; // Add fields. if (!empty($attachment['fields'])) { foreach ($attachment['fields'] as $field) { $message .= "\n\t<br /> <strong>" . $field['title'] . ':</strong> ' . $field['value']; } } } } // Filter the email pieces. $email_pieces = apply_filters('rock_the_slackbot_error_email', array('to' => $email, 'subject' => __('WordPress to Slack error', 'rock-the-slackbot'), 'message' => $message), $args); // Make sure we still have email pieces. if (!empty($email_pieces['to']) && !empty($email_pieces['subject'])) { // Set email to be HTML. add_filter('wp_mail_content_type', 'rock_the_slackbot_set_html_content_type'); // Send email notification to the admin. $send_email = wp_mail($email_pieces['to'], $email_pieces['subject'], isset($email_pieces['message']) ? $email_pieces['message'] : ''); // Reset content-type to avoid conflicts. remove_filter('wp_mail_content_type', 'rock_the_slackbot_set_html_content_type'); } return $send_email; }