* @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 );
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_menu_page( __( 'Your SMS Subscribers', 'txtimpact' ), __( 'TXTImpact SMS', 'txtimpact' ), 'edit_users', 'txtimpact_main', array(
$this,
'manage_subscribers',
), 'dashicons-smartphone' );
$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; // phpcs:ignore
$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 " ) ); // phpcs:ignore
$vars['length_post_author'] = (int) ceil( $wpdb->get_var( " SELECT AVG( CHAR_LENGTH( display_name ) ) FROM $wpdb->users LIMIT 500 " ) ); // phpcs:ignore
$max_post_id = $wpdb->get_var( " SELECT MAX(ID) FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish' " ); // phpcs:ignore
$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'] ) ) { // phpcs:ignore
return;
}
$action = $_POST['action']; // phpcs:ignore
if ( isset( $action ) ) {
switch ( $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'] ) ) { // phpcs:ignore
return;
}
$wp_function = self::get_wp_functions();
$wp_function->check_admin_referer( 'txtimpact-send-sms', '_txtimpact_nonce' );
$post = $_POST; // phpcs:ignore
$message = ( isset( $_POST['txtimpact_message'] ) ) ? trim( $_POST['txtimpact_message'] ) : ''; // phpcs:ignore
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' ) . '' ); // phpcs:ignore
} elseif ( isset( $response->response['errors']['304'] ) ) {
$this->set_admin_error( __( $response->response['errors'][304]['message'] . '!', 'txtimpact' ) ); // phpcs:ignore
} else {
$message_error = '';
foreach ( $response->response['errors'] as $key => $errors ) {
$message_error .= $response->response['errors'][ $key ]['message'] . '';
}
$this->set_admin_error( __( $message_error . '!', 'txtimpact' ) ); // phpcs:ignore
}
} else {
$this->set_admin_notice( sprintf( __( 'Your Message has been sent to %d subscribers.', 'txtimpact' ), $response->response['success']['numbers'] ) ); // phpcs:ignore
}
$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']; // phpcs:ignore
$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']; // phpcs:ignore
$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']; // phpcs:ignore
$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'] ) ) { // phpcs:ignore
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(); // phpcs:ignore
$action = ( isset( $_POST['action'] ) && $_POST['action'] == 'delete' ); // phpcs:ignore
$action2 = ( isset( $_POST['action2'] ) && $_POST['action2'] == 'delete' ); // phpcs:ignore
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 ) ); // phpcs:ignore
$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'] ) ) { // phpcs:ignore
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(); // phpcs:ignore
$action = ( isset( $_POST['action'] ) && $_POST['action'] == 'delete' ); // phpcs:ignore
$action2 = ( isset( $_POST['action2'] ) && $_POST['action2'] == 'delete' ); // phpcs:ignore
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 ) ); // phpcs:ignore
$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'] ) ) { // phpcs:ignore
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(); // phpcs:ignore
$action = ( isset( $_POST['action'] ) && $_POST['action'] == 'delete' ); // phpcs:ignore
$action2 = ( isset( $_POST['action2'] ) && $_POST['action2'] == 'delete' ); // phpcs:ignore
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 ) ); // phpcs:ignore
$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'] ); // phpcs:ignore
$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 ) { // phpcs:ignore
$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 wp_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 ( 'publish' === $new_status && 'publish' !== $old_status && (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}' ); // phpcs:ignore
return stripslashes( $this->get_option( 'txtimpact_new_post_message', $default ) );
}
/**
* Get a Random Key
*
* @param int $number number.
*
* @return string
*/
public 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 messge.
* @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'] ); // phpcs:ignore
if ( (bool) @$_POST['txtimpact_new_post'] ) { // phpcs:ignore
if ( empty( $_POST['txtimpact_new_post_message'] ) ) { // phpcs:ignore
$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'] : '' ) ); // phpcs:ignore
$this->update_option( 'txtimpact_password', ( isset( $_POST['txtimpact_password'] ) ? $_POST['txtimpact_password'] : '' ) ); // phpcs:ignore
$this->update_option( 'txtimpact_vasid', ( isset( $_POST['txtimpact_vasid'] ) ? $_POST['txtimpact_vasid'] : '' ) ); // phpcs:ignore
$this->update_option( 'txtimpact_new_post', (bool) @$_POST['txtimpact_new_post'] ); // phpcs:ignore
$this->update_option( 'txtimpact_new_post_message', ( isset( $_POST['txtimpact_new_post_message'] ) ? $_POST['txtimpact_new_post_message'] : '' ) ); // phpcs:ignore
$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( esc_html( 'Sorry, you are not allowed to deactivate plugins.', 'txtimpact' ) );
}
$html = $this->capture_admin( 'confirm-delete-uninstall.php', array() );
$wp_function->wp_die( $html, esc_html( 'Confirm uninstall and delete!', 'txtimpact' ), array( 'response' => 200 ) ); // phpcs:ignore
}
/**
* 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( esc_html( '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 ) ); // phpcs:ignore
}
/**
* Callback function for unsubscribe request
*
* @return void
*/
protected function maybe_unsubscribe_request() {
if ( ! isset ( $_REQUEST['txtimpact-unsubscribe'] ) ) { // phpcs:ignore
return;
}
$vars = array();
$removed = false;
if ( isset( $_POST['txtimpact-phone-number'] ) ) { // phpcs:ignore
$vars['txtimpact_phone_number'] = $_POST['txtimpact-phone-number']; // phpcs:ignore
$phone_number = trim( $_POST['txtimpact-phone-number'] ); // phpcs:ignore
$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( esc_html( '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, esc_html( 'Unsubscribe from SMS Notifications', 'txtimpact' ), array( 'response' => 200 ) ); // phpcs:ignore
}
/**
* @param $id
*
* @return false|string
*/
protected function get_post_short_link( $id ) {
return ( ( '' !== get_option( 'permalink_structure' ) ) ? wp_get_shortlink( $id ) : get_permalink( $id ) );
}
/**
* @param W2A_Functions $class
*/
public static function set_wp_functions( W2A_Functions $class ) {
self::$_wp_functions = $class;
}
/**
* @return W2A_Functions
*/
public static function get_wp_functions() {
if ( empty( self::$_wp_functions ) ) {
self::$_wp_functions = new W2A_Functions();
}
return self::$_wp_functions;
}
}
$txtimpact = new TXTIMPACT();