Files
twilio-wp-plugin/includes/class-twp-mobile-phone-page.php

227 lines
7.7 KiB
PHP
Raw Normal View History

<?php
/**
* Standalone Mobile Phone Page
*
* Registers a front-end endpoint at /twp-phone/ that serves the browser phone UI
* without any wp-admin chrome. Designed for mobile WebView usage.
*
* @package Twilio_WP_Plugin
*/
class TWP_Mobile_Phone_Page {
/**
* The endpoint slug.
*/
const ENDPOINT = 'twp-phone';
/**
* Constructor wire up hooks.
*/
public function __construct() {
add_action('init', array($this, 'register_rewrite'));
add_action('template_redirect', array($this, 'handle_request'));
add_filter('query_vars', array($this, 'add_query_var'));
// Extend session cookie for phone agents.
add_filter('auth_cookie_expiration', array($this, 'extend_agent_cookie'), 10, 3);
// AJAX action for FCM token registration (uses WP cookie auth).
add_action('wp_ajax_twp_register_fcm_token', array($this, 'ajax_register_fcm_token'));
}
/**
* AJAX handler: register FCM token for the current user.
*/
public function ajax_register_fcm_token() {
check_ajax_referer('twp_ajax_nonce', 'nonce');
$fcm_token = sanitize_text_field($_POST['fcm_token'] ?? '');
if (empty($fcm_token)) {
wp_send_json_error('Missing FCM token');
}
$user_id = get_current_user_id();
if (!$user_id) {
wp_send_json_error('Not authenticated');
}
// Store FCM token (same as TWP_Mobile_API::register_fcm_token)
global $wpdb;
$table = $wpdb->prefix . 'twp_mobile_sessions';
// Update existing session or insert new one
$existing = $wpdb->get_row($wpdb->prepare(
"SELECT id FROM $table WHERE user_id = %d AND fcm_token = %s AND is_active = 1",
$user_id, $fcm_token
));
if ($existing) {
// Refresh the expiry on existing session
$wpdb->update($table,
array('expires_at' => date('Y-m-d H:i:s', time() + 7 * DAY_IN_SECONDS)),
array('id' => $existing->id),
array('%s'),
array('%d')
);
} else {
$wpdb->insert($table, array(
'user_id' => $user_id,
'refresh_token' => 'webview-' . wp_generate_password(32, false),
'fcm_token' => $fcm_token,
'device_info' => 'WebView Mobile App',
'is_active' => 1,
'created_at' => current_time('mysql'),
'expires_at' => date('Y-m-d H:i:s', time() + 7 * DAY_IN_SECONDS),
));
if ($wpdb->last_error) {
error_log('TWP FCM: Failed to insert token: ' . $wpdb->last_error);
wp_send_json_error('Failed to store token');
}
}
error_log("TWP FCM: Token registered for user $user_id");
wp_send_json_success('FCM token registered');
}
/**
* Register custom rewrite rule.
*/
public function register_rewrite() {
add_rewrite_rule(
'^' . self::ENDPOINT . '/?$',
'index.php?twp_phone_page=1',
'top'
);
}
/**
* Expose query variable.
*
* @param array $vars Existing query vars.
* @return array
*/
public function add_query_var($vars) {
$vars[] = 'twp_phone_page';
return $vars;
}
/**
* Handle the request on template_redirect.
*/
public function handle_request() {
if (!get_query_var('twp_phone_page')) {
return;
}
// Authentication check — redirect to login if not authenticated.
if (!is_user_logged_in()) {
$redirect_url = home_url('/' . self::ENDPOINT . '/');
wp_redirect(wp_login_url($redirect_url));
exit;
}
// Capability check.
if (!current_user_can('twp_access_browser_phone')) {
wp_die(
'You do not have permission to access the browser phone.',
'Access Denied',
array('response' => 403)
);
}
// Render the standalone page and exit.
$this->render_page();
exit;
}
/**
* Extend auth cookie to 7 days for phone agents.
*
* @param int $expiration Default expiration in seconds.
* @param int $user_id User ID.
* @param bool $remember Whether "Remember Me" was checked.
* @return int
*/
public function extend_agent_cookie($expiration, $user_id, $remember) {
$user = get_userdata($user_id);
if ($user && $user->has_cap('twp_access_browser_phone')) {
return 7 * DAY_IN_SECONDS;
}
return $expiration;
}
// ------------------------------------------------------------------
// Rendering
// ------------------------------------------------------------------
/**
* Output the complete standalone HTML page.
*/
private function render_page() {
// Gather data needed by the template (same as display_browser_phone_page).
$current_user_id = get_current_user_id();
global $wpdb;
$extensions_table = $wpdb->prefix . 'twp_user_extensions';
$extension_data = $wpdb->get_row($wpdb->prepare(
"SELECT extension FROM $extensions_table WHERE user_id = %d",
$current_user_id
));
if (!$extension_data) {
TWP_User_Queue_Manager::create_user_queues($current_user_id);
$extension_data = $wpdb->get_row($wpdb->prepare(
"SELECT extension FROM $extensions_table WHERE user_id = %d",
$current_user_id
));
}
$agent_status = TWP_Agent_Manager::get_agent_status($current_user_id);
$agent_stats = TWP_Agent_Manager::get_agent_stats($current_user_id);
$is_logged_in = TWP_Agent_Manager::is_agent_logged_in($current_user_id);
$current_mode = get_user_meta($current_user_id, 'twp_call_mode', true);
if (empty($current_mode)) {
$current_mode = 'cell';
}
$user_phone = get_user_meta($current_user_id, 'twp_phone_number', true);
// Smart routing check (for admin-only setup notice).
$smart_routing_configured = false;
try {
$twilio = new TWP_Twilio_API();
$phone_numbers = $twilio->get_phone_numbers();
if ($phone_numbers['success']) {
$smart_routing_url = home_url('/wp-json/twilio-webhook/v1/smart-routing');
foreach ($phone_numbers['data']['incoming_phone_numbers'] as $number) {
if (isset($number['voice_url']) && strpos($number['voice_url'], 'smart-routing') !== false) {
$smart_routing_configured = true;
break;
}
}
}
} catch (Exception $e) {
// Silently continue.
}
// Nonce for AJAX.
$nonce = wp_create_nonce('twp_ajax_nonce');
// URLs.
$ajax_url = admin_url('admin-ajax.php');
$ringtone_url = plugins_url('assets/sounds/ringtone.mp3', dirname(__FILE__));
$phone_icon_url = plugins_url('assets/images/phone-icon.png', dirname(__FILE__));
$sw_url = plugins_url('assets/js/twp-service-worker.js', dirname(__FILE__));
$twilio_edge = esc_js(get_option('twp_twilio_edge', 'roaming'));
$smart_routing_webhook = home_url('/wp-json/twilio-webhook/v1/smart-routing');
// Plugin file reference for plugins_url() in template.
$plugin_file = dirname(__FILE__) . '/../twilio-wp-plugin.php';
// Load the template (all variables above are in scope).
require TWP_PLUGIN_DIR . 'assets/mobile/phone-template.php';
}
}