* @copyright 2012 txtimpact Texting https://www.txtimpact.com * @license http://opensource.org/licenses/gpl-license.php GNU Public License * @version 1.0 * @since 1.0 */ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ require_once( 'class-txtimpact-plugin.php' ); /** * The main class of the plugin. */ class TXTIMPACT extends TXTIMPACT_Plugin { /** * The version of this file, for the purposes of rewrite * refreshes, JS/CSS cache bursting, etc. * * @var int **/ protected $version; /** * for test purpose * * @var W2A_Functions */ public static $_wp_functions = null; /** * Start point. * init base action */ public function __construct() { $this->setup( 'txtimpact' ); if ( is_admin() ) { $this->add_action( 'admin_init' ); $this->add_action( 'admin_menu' ); $this->add_action( 'wp_ajax_txtimpact_subscribe', 'ajax_subscribe' ); $this->add_action( 'wp_ajax_nopriv_txtimpact_subscribe', 'ajax_subscribe' ); } $this->add_action( 'transition_post_status', null, null, 3 ); $this->add_action( 'init' ); $this->version = 1; } /** * Hook admin init action */ public function admin_init() { $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '.dev' : ''; wp_enqueue_script( 'txtimpact-admin', $this->url( "/js/admin{$suffix}.js" ), array( 'jquery' ), $this->version ); $localized = array( 'top_menu_label' => __( 'TXTImpact SMS', 'txtimpact' ), ); wp_localize_script( 'txtimpact-admin', 'txtimpact', $localized ); wp_enqueue_style( 'txtimpact-admin', $this->url( "/css/admin{$suffix}.css" ), array(), $this->version, 'all' ); TXTIMPACT_Subscribers::check_update(); TXTIMPACT_Received_messages::check_update(); TXTIMPACT_Sent_messages::check_update(); } /** * Hooks the init action to: * * Process unsubscribe requests * * @return void **/ public function init() { $this->maybe_unsubscribe_request(); } /** * Hooks the WP admin_menu function to add in our top * level menu and various sub-pages. * * @return void **/ public function admin_menu() { // Create a top level SMS menu item, and some sub-items $hook_name = add_object_page( __( 'Your SMS Subscribers', 'txtimpact' ), __( 'Subscribers', 'txtimpact' ), 'edit_users', 'txtimpact_main', array( $this, 'manage_subscribers' ), plugin_dir_url ( __FILE__ )."img/mobile.png"); $this->add_action( "load-$hook_name", 'load_subscribers_action' ); $hook_name = add_submenu_page( 'txtimpact_main', __( 'SMS Settings', 'txtimpact' ), __( 'Settings', 'txtimpact' ), 'publish_posts', 'txtimpact_options', array( $this, 'manage_options' ) ); $this->add_action( "load-$hook_name", 'load_settings' ); $hook_name = add_submenu_page( 'txtimpact_main', __( 'SMS Sent Messages', 'txtimpact' ), __( 'Sent Messages', 'txtimpact' ), 'edit_users', 'txtimpact_sent_messages', array( $this, 'manage_sent_messages' ) ); $this->add_action( "load-$hook_name", 'load_sent_messages_action' ); $hook_name = add_submenu_page( 'txtimpact_main', __( 'SMS Received Messages', 'txtimpact' ), __( 'Received Messages', 'txtimpact' ), 'edit_users', 'txtimpact_received_messages', array( $this, 'manage_received_messages' ) ); $this->add_action( "load-$hook_name", 'load_received_messages_action' ); $hook_name = add_submenu_page( 'txtimpact_main', __( 'Send SMS', 'txtimpact' ), __( 'Send SMS', 'txtimpact' ), 'publish_posts', 'txtimpact_sendsms', array( $this, 'send_sms' ) ); $this->add_action( "load-$hook_name", 'load_send_message' ); } /** * Callback function for rendering options page * * @global WordPress database object $wpdb * @return void */ public function manage_options() { global $wpdb; $vars = array(); $vars['txtimpact_user'] = $this->get_option( 'txtimpact_user' ); $vars['txtimpact_password'] = $this->get_option( 'txtimpact_password' ); $vars['txtimpact_vasid'] = $this->get_option( 'txtimpact_vasid' ); $new_var = isset($_GET["newkey"]) ? $_GET["newkey"] : 0; $security_key = $this->get_option( 'txtimpact_security_key' ); if(empty($security_key) || !empty($new_var)){ $new_key = $this->createRandomKey(20); $options = get_option("txtimpact"); $new_options = $options; $new_options["txtimpact_security_key"] = $new_key; update_option('txtimpact',$new_options ); echo ""; } $options = get_option("txtimpact"); $vars['txtimpact_security_key'] = $options['txtimpact_security_key' ]; $vars['txtimpact_new_post'] = (bool) $this->get_option( 'txtimpact_new_post' ); $vars['txtimpact_new_post_message'] = $this->new_post_message(); $vars['length_post_title'] = (int) ceil( $wpdb->get_var( " SELECT AVG( CHAR_LENGTH( post_title ) ) FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 500 " ) ); $vars['length_post_author'] = (int) ceil( $wpdb->get_var( " SELECT AVG( CHAR_LENGTH( display_name ) ) FROM $wpdb->users LIMIT 500 " ) ); $max_post_id = $wpdb->get_var( " SELECT MAX(ID) FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish' " ); $vars['length_post_url'] = strlen( $this->get_post_short_link( $max_post_id ) ); $vars['length_blog_name'] = strlen( get_bloginfo( 'name' ) ); $vars['length_blog_url'] = strlen( home_url() ); $this->render_admin( 'options.php', $vars); } /** * Hook the load TXTImpact SMS setting page * * @return void */ public function load_settings() { if ( ! isset($_POST[ '_txtimpact_nonce' ]) ) return; if( isset($_POST['action']) ) { switch ( $_POST['action'] ) { case 'save-settings': $this->save_settings(); break; case 'delete-uninstall': $this->confirm_delete_uninstall(); break; case 'confirm-delete-uninstall': $this->delete_uninstall(); break; } } $wp_function = self::get_wp_functions(); $wp_function->wp_redirect(admin_url( '/admin.php?page=txtimpact_options' ), true); } /** * Callback function for rendering send sms page * * @return void */ public function send_sms() { $vars = array(); $vars['length_blog_name'] = strlen( get_bloginfo( 'name' ) ); $vars['length_blog_url'] = strlen( home_url() ); $this->render_admin( 'send-sms.php', $vars); } /** * Hook the load send message page * * @return void */ public function load_send_message() { if ( ! isset($_POST[ '_txtimpact_nonce' ]) ) return; $wp_function = self::get_wp_functions(); $wp_function->check_admin_referer( 'txtimpact-send-sms', '_txtimpact_nonce' ); $post = $_POST; $message = ( isset($_POST['txtimpact_message']) ) ? trim($_POST['txtimpact_message']) : ''; if( empty($message) ) { $this->set_admin_error( __("The Message field is required!", 'txtimpact') ); $wp_function->wp_redirect(txtimpact_current_page_url(), true ); } $message = $this->get_original_message($message); $response = txtimpact_send_sms_to_subscribers($message); if($response->failed) { if(isset($response->response["errors"]["301"])) { $this->set_admin_error( __($response->response["errors"]["301"]["message"].'! Your txtimpact username, password and/or vasid are missing or incorrect.', 'txtimpact') .' ' .__('Please visit the settings page', 'txtimpact') .'' ); }else if(isset($response->response["errors"]["304"])) { $this->set_admin_error( __($response->response["errors"][304]["message"].'!', 'txtimpact') ); }else{ foreach($response->response["errors"] as $key => $errors) $message_error .= $response->response["errors"][$key]["message"].' '; $this->set_admin_error( __($message_error.'!', 'txtimpact') ); } } else { $this->set_admin_notice( sprintf( __('Your Message has been sent to %d subscribers.', 'txtimpact'), $response->response["success"]["numbers"] ) ); } $wp_function->wp_redirect( txtimpact_current_page_url(), true ); } /** * Callback function for rendering messages sent page * * @return void */ public function manage_sent_messages() { $page = ( !isset($_GET['p']) || !is_numeric($_GET['p']) ) ? 1 : $_GET['p']; $total_items = TXTIMPACT_Sent_messages::get_count(); $page_size = 20; $total_page = ceil( $total_items / $page_size ); $vars = array( 'messages' => TXTIMPACT_Sent_Messages::fetch_all( $page, $page_size ), 'current_page' => $page, 'page_size' => $page_size, 'total_items' => $total_items, 'total_page' => $total_page ); $this->render_admin( 'sent-messages.php', $vars ); } /** * Callback function for rendering messages received page * * @return void */ public function manage_received_messages() { $page = ( !isset($_GET['p']) || !is_numeric($_GET['p']) ) ? 1 : $_GET['p']; $total_items = TXTIMPACT_Received_messages::get_count(); $page_size = 20; $total_page = ceil( $total_items / $page_size ); $vars = array( 'messages' => TXTIMPACT_Received_messages::fetch_all( $page, $page_size ), 'current_page' => $page, 'page_size' => $page_size, 'total_items' => $total_items, 'total_page' => $total_page ); $this->render_admin( 'received-messages.php', $vars ); } /** * Callback function for rendering subscribers page * * @return void */ public function manage_subscribers() { $page = ( !isset($_GET['p']) || !is_numeric($_GET['p']) ) ? 1 : $_GET['p']; $total_items = TXTIMPACT_Subscribers::get_count(); $page_size = 20; $total_page = ceil( $total_items / $page_size ); $vars = array( 'subscribers' => TXTIMPACT_Subscribers::fetch_all( $page, $page_size ), 'current_page' => $page, 'page_size' => $page_size, 'total_items' => $total_items, 'total_page' => $total_page ); $this->render_admin( 'subscribers.php', $vars ); } /** * Hook the load action for subscribe page * * @return void */ public function load_subscribers_action() { if ( ! isset($_POST[ '_txtimpact_nonce' ]) ) return; $wp_function = self::get_wp_functions(); $wp_function->check_admin_referer( 'txtimpact-subscribe-action', '_txtimpact_nonce' ); $subscribers_ids = isset ($_POST['subscriber_ids']) ? $_POST['subscriber_ids'] : array(); $action = ( isset($_POST['action']) && $_POST['action'] == 'delete' ); $action2 = ( isset($_POST['action2']) && $_POST['action2'] == 'delete' ); if( $action || $action2 ) { if( empty($subscribers_ids) ) { $this->set_admin_notice( __('Please select subscribers to delete.', 'txtimpact') ); $wp_function->wp_redirect( txtimpact_current_page_url(), true ); } $result = TXTIMPACT_Subscribers::delete( $subscribers_ids ); $this->set_admin_notice( sprintf( __( 'Deleted %d subscribers.', 'txtimpact' ), $result ) ); $wp_function->wp_redirect( txtimpact_current_page_url(), true ); } } /** * Hook the load action for received message page * * @return void */ public function load_received_messages_action() { if ( ! isset($_POST[ '_txtimpact_nonce' ]) ) return; $wp_function = self::get_wp_functions(); $wp_function->check_admin_referer( 'txtimpact-received-message-action', '_txtimpact_nonce' ); $messages_ids = isset ($_POST['message_ids']) ? $_POST['message_ids'] : array(); $action = ( isset($_POST['action']) && $_POST['action'] == 'delete' ); $action2 = ( isset($_POST['action2']) && $_POST['action2'] == 'delete' ); if( $action || $action2 ) { if( empty($messages_ids) ) { $this->set_admin_notice( __('Please select messages to delete.', 'txtimpact') ); $wp_function->wp_redirect( txtimpact_current_page_url(), true ); } $result = TXTIMPACT_Received_messages::delete( $messages_ids ); $this->set_admin_notice( sprintf( __( 'Deleted %d messages.', 'txtimpact' ), $result ) ); $wp_function->wp_redirect( txtimpact_current_page_url(), true ); } } /** * Hook the load action for sent message page * * @return void */ public function load_sent_messages_action() { if ( ! isset($_POST[ '_txtimpact_nonce' ]) ) return; $wp_function = self::get_wp_functions(); $wp_function->check_admin_referer( 'txtimpact-sent-message-action', '_txtimpact_nonce' ); $messages_ids = isset ($_POST['message_ids']) ? $_POST['message_ids'] : array(); $action = ( isset($_POST['action']) && $_POST['action'] == 'delete' ); $action2 = ( isset($_POST['action2']) && $_POST['action2'] == 'delete' ); if( $action || $action2 ) { if( empty($messages_ids) ) { $this->set_admin_notice( __('Please select messages to delete.', 'txtimpact') ); $wp_function->wp_redirect( txtimpact_current_page_url(), true ); } $result = TXTIMPACT_Sent_messages::delete( $messages_ids ); $this->set_admin_notice( sprintf( __( 'Deleted %d messages.', 'txtimpact' ), $result ) ); $wp_function->wp_redirect( txtimpact_current_page_url(), true ); } } /** * Hook for wp_ajax_txtimpact_subscribe. prcess subscibe form * * @return void */ public function ajax_subscribe() { $response = array( 'success' => true ); //filter phoen number $phone_number = trim( $_POST['phone_number'] ); $phone_number = preg_replace('/[^\d]/', '', $phone_number); $exist_phone_number = TXTIMPACT_Subscribers::fetch_row_by_phone_number($phone_number); if( ! empty($exist_phone_number) && $exist_phone_number->opt_out == 1) $response = array( 'success' => false, 'messages' => __('That phone number is opted out from txtimpact Texting services', 'txtimpact') ); elseif( !empty($exist_phone_number) ) $response = array( 'success' => false, 'messages' => __('That phone number is already subscribed to this list', 'txtimpact') ); else TXTIMPACT_Subscribers::save_number($phone_number); header( "Content-Type: application/json" ); echo json_encode( $response ); exit; } /** * Hook the transition_post_status for sending notifications * @param string $new_status Transition to this post status. * @param string $old_status Previous post status. * @param object $post Post data. */ public function transition_post_status($new_status, $old_status, $post) { if( $new_status == 'publish' && $old_status != 'publish' && (bool)$this->get_option('txtimpact_new_post') ) { $message = $this->get_original_message( $this->new_post_message(), $post ); txtimpact_send_sms_to_subscribers( $message ); } } /** * setup the default notification message template if message not set * * @return string */ protected function new_post_message() { $default = sprintf( __( 'New %1$s post: %2$s', 'mbe2s' ), '{blog_name}', '{post_url}' ); return stripslashes( $this->get_option( 'txtimpact_new_post_message', $default ) ); } /** * get a Random Key * * @return string */ function createRandomKey($number){ $keyset = "abcdefghijklmABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; $randkey = ""; for ($i=0; $i<$number; $i++) $randkey .= substr($keyset, rand(0, strlen($keyset)-1), 1); return $randkey; } /** * prepare message to send via sms * * @param string $message * @param object $post Post data. * @return string original message to send */ protected function get_original_message($message, $post = null) { $search = array( '{blog_name}', '{blog_url}' ); $replace = array( get_bloginfo('name'), home_url() ); if( $post ) { $account = new WP_User( $post->post_author ); $search[] = '{post_author}'; $search[] = '{post_title}'; $search[] = '{post_url}'; $replace[] = $account->display_name; $replace[] = get_the_title( $post->ID ); $replace[] = $this->get_post_short_link( $post->ID ); } return str_replace( $search, $replace, $message ); } /** * Save settings from the Options page. * * @return void **/ protected function save_settings() { $wp_function = self::get_wp_functions(); $wp_function->check_admin_referer( 'txtimpact-save-settings', '_txtimpact_nonce' ); $api = new TXTIMPACT_Sending($_POST['txtimpact_user'], $_POST['txtimpact_password'], $_POST['txtimpact_vasid']); if( (bool) @$_POST['txtimpact_new_post'] ) { if( empty($_POST['txtimpact_new_post_message']) ) { $this->update_option( 'txtimpact_new_post', false ); $this->update_option( 'txtimpact_new_post_message', '' ); $this->set_admin_error( __("The Message field is required", 'txtimpact') ); $wp_function->wp_redirect(txtimpact_current_page_url()); return; } } $this->update_option( 'txtimpact_user', ( isset($_POST['txtimpact_user']) ? $_POST['txtimpact_user'] : '' ) ); $this->update_option( 'txtimpact_password', ( isset($_POST['txtimpact_password']) ? $_POST['txtimpact_password'] : '' ) ); $this->update_option( 'txtimpact_vasid', ( isset($_POST['txtimpact_vasid']) ? $_POST['txtimpact_vasid'] : '' ) ); $this->update_option( 'txtimpact_new_post', (bool) @$_POST['txtimpact_new_post'] ); $this->update_option( 'txtimpact_new_post_message', ( isset( $_POST['txtimpact_new_post_message'] ) ? $_POST['txtimpact_new_post_message'] : '') ); $this->set_admin_notice( __( 'Settings saved.', 'txtimpact' ) ); } /** * Rendering confirmation page */ protected function confirm_delete_uninstall() { $wp_function = self::get_wp_functions(); $wp_function->check_admin_referer( 'txtimpact-delete-uninstall', '_txtimpact_nonce' ); if ( ! $wp_function->current_user_can( 'activate_plugins' ) ) $wp_function->wp_die( __( 'Sorry, you are not allowed to deactivate plugins.', 'txtimpact' ) ); $html = $this->capture_admin( 'confirm-delete-uninstall.php', array() ); $wp_function->wp_die( $html, __( 'Confirm uninstall and delete!', 'txtimpact' ), array( 'response' => 200 ) ); } /** * Rendering delete plugin page */ protected function delete_uninstall() { $wp_function = self::get_wp_functions(); $wp_function->check_admin_referer( 'txtimpact-confirm-delete-uninstall', '_txtimpact_nonce' ); if ( ! $wp_function->current_user_can( 'activate_plugins' ) ) $wp_function->wp_die( __( 'Sorry, you are not allowed to deactivate plugins.', 'txtimpact' ) ); TXTIMPACT_Subscribers::uninstall(); delete_option( $this->name ); $wp_function->deactivate_plugins( $this->folder . '/txtimpact-texting-sms-notifications.php' ); $wp_function->wp_die( sprintf( __( "txtimpact Texting: The SMS notifications plugin has been deactivated and all its data has been deleted; return to the Dashboard.", 'txtimpact' ), admin_url() ), __( 'Confirm uninstall and delete!', 'txtimpact' ), array( 'response' => 200 ) ); } /** * Callback function for unsubscribe request * * @return void */ protected function maybe_unsubscribe_request() { if ( ! isset ($_REQUEST['txtimpact-unsubscribe']) ) return; $vars = array(); $removed = false; if( isset($_POST['txtimpact-phone-number']) ) { $vars['txtimpact_phone_number'] = $_POST['txtimpact-phone-number']; $phone_number = trim( $_POST['txtimpact-phone-number'] ); $phone_number = preg_replace( '/[^\d]/', '', $phone_number ); $subscriber = TXTIMPACT_Subscribers::fetch_row_by_phone_number($phone_number); if( $subscriber ) $removed = TXTIMPACT_Subscribers::delete( $subscriber->ID ); else $vars['error'] = sprintf( __( "We could not find the phone number %s to unsubscribe.", 'txtimpact' ), $vars['txtimpact_phone_number'] ); } if ( $removed ) $html = $this->capture( 'unsubscribed.php', $vars ); else $html = $this->capture( 'unsubscribe.php', $vars ); $wp_function = self::get_wp_functions(); $wp_function->wp_die( $html, __( 'Unsubscribe from SMS Notifications', 'txtimpact' ), array( 'response' => 200 ) ); } protected function get_post_short_link($id) { return ( ( '' != get_option('permalink_structure') ) ? wp_get_shortlink($id) : get_permalink($id) ); } public static function set_wp_functions(W2A_Functions $class) { self::$_wp_functions = $class; } public static function get_wp_functions() { if( empty(self::$_wp_functions) ) self::$_wp_functions = new W2A_Functions(); return self::$_wp_functions; } } $txtimpact = new TXTIMPACT(); ?>