Adding new functionality
This commit is contained in:
		
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -455,6 +455,16 @@
 | 
			
		||||
    transform: translateY(-1px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.twp-btn-warning {
 | 
			
		||||
    background: #ffc107;
 | 
			
		||||
    color: #212529;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.twp-btn-warning:hover {
 | 
			
		||||
    background: #e0a800;
 | 
			
		||||
    transform: translateY(-1px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.twp-btn-success {
 | 
			
		||||
    background: #007cba;
 | 
			
		||||
    color: white;
 | 
			
		||||
 
 | 
			
		||||
@@ -277,6 +277,10 @@
 | 
			
		||||
            hangupCall();
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        $('#twp-resume-btn').on('click', function() {
 | 
			
		||||
            toggleHold(); // Resume the call
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        // Call control buttons
 | 
			
		||||
        $('#twp-hold-btn').on('click', function() {
 | 
			
		||||
            toggleHold();
 | 
			
		||||
@@ -531,6 +535,10 @@
 | 
			
		||||
        $('#twp-hold-btn').text('Hold').removeClass('btn-active');
 | 
			
		||||
        $('#twp-record-btn').text('Record').removeClass('btn-active');
 | 
			
		||||
        
 | 
			
		||||
        // Reset resume button
 | 
			
		||||
        const $resumeBtn = $('#twp-resume-btn');
 | 
			
		||||
        $resumeBtn.hide();
 | 
			
		||||
        
 | 
			
		||||
        // Restart alerts if enabled and there are waiting calls
 | 
			
		||||
        if (alertEnabled) {
 | 
			
		||||
            const hasWaitingCalls = userQueues.some(q => parseInt(q.current_waiting) > 0);
 | 
			
		||||
@@ -731,23 +739,27 @@
 | 
			
		||||
    function updateCallState(state) {
 | 
			
		||||
        const $callBtn = $('#twp-call-btn');
 | 
			
		||||
        const $hangupBtn = $('#twp-hangup-btn');
 | 
			
		||||
        const $resumeBtn = $('#twp-resume-btn');
 | 
			
		||||
        const $controlsPanel = $('#twp-call-controls-panel');
 | 
			
		||||
        
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case 'idle':
 | 
			
		||||
                $callBtn.show().prop('disabled', false);
 | 
			
		||||
                $hangupBtn.hide();
 | 
			
		||||
                $resumeBtn.hide();
 | 
			
		||||
                $controlsPanel.hide();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'connecting':
 | 
			
		||||
            case 'ringing':
 | 
			
		||||
                $callBtn.hide();
 | 
			
		||||
                $hangupBtn.show();
 | 
			
		||||
                $resumeBtn.hide();
 | 
			
		||||
                $controlsPanel.hide();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'connected':
 | 
			
		||||
                $callBtn.hide();
 | 
			
		||||
                $hangupBtn.show();
 | 
			
		||||
                $resumeBtn.hide(); // Will be shown by hold logic when needed
 | 
			
		||||
                $controlsPanel.show();
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
@@ -1596,19 +1608,33 @@
 | 
			
		||||
                    isOnHold = !currentHoldState;
 | 
			
		||||
                    console.log('Hold state updated to:', isOnHold);
 | 
			
		||||
                    
 | 
			
		||||
                    // Update hold button and show/hide dedicated resume button
 | 
			
		||||
                    const $resumeBtn = $('#twp-resume-btn');
 | 
			
		||||
                    
 | 
			
		||||
                    if (isOnHold) {
 | 
			
		||||
                        console.log('Setting button to Resume state...');
 | 
			
		||||
                        $holdBtn.text('Resume').addClass('btn-active').prop('disabled', false);
 | 
			
		||||
                        
 | 
			
		||||
                        // Show dedicated resume button
 | 
			
		||||
                        $resumeBtn.show();
 | 
			
		||||
                        console.log('Resume button shown - visible:', $resumeBtn.is(':visible'));
 | 
			
		||||
                        
 | 
			
		||||
                        console.log('Button after update - text:', $holdBtn.text(), 'classes:', $holdBtn.attr('class'));
 | 
			
		||||
                        showMessage('Call placed on hold - Click Resume to continue', 'info');
 | 
			
		||||
                        showMessage('Call placed on hold - Click Resume Call button to continue', 'info');
 | 
			
		||||
                        
 | 
			
		||||
                        // Verify the button was actually updated
 | 
			
		||||
                        setTimeout(function() {
 | 
			
		||||
                            console.log('Button state after 100ms:', $holdBtn.text(), $holdBtn.hasClass('btn-active'));
 | 
			
		||||
                            console.log('Resume button visible after 100ms:', $resumeBtn.is(':visible'));
 | 
			
		||||
                        }, 100);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        console.log('Setting button to Hold state...');
 | 
			
		||||
                        $holdBtn.text('Hold').removeClass('btn-active').prop('disabled', false);
 | 
			
		||||
                        
 | 
			
		||||
                        // Hide dedicated resume button
 | 
			
		||||
                        $resumeBtn.hide();
 | 
			
		||||
                        console.log('Resume button hidden');
 | 
			
		||||
                        
 | 
			
		||||
                        console.log('Button after update - text:', $holdBtn.text(), 'classes:', $holdBtn.attr('class'));
 | 
			
		||||
                        showMessage('Call resumed', 'info');
 | 
			
		||||
                    }
 | 
			
		||||
@@ -1676,10 +1702,8 @@
 | 
			
		||||
                if (response.success) {
 | 
			
		||||
                    showMessage('Call transferred successfully', 'success');
 | 
			
		||||
                    hideTransferDialog();
 | 
			
		||||
                    // End the call on our end
 | 
			
		||||
                    if (currentCall) {
 | 
			
		||||
                        currentCall.disconnect();
 | 
			
		||||
                    }
 | 
			
		||||
                    // Don't disconnect - let the transfer complete naturally
 | 
			
		||||
                    // The call will be disconnected by Twilio after successful transfer
 | 
			
		||||
                } else {
 | 
			
		||||
                    showMessage('Failed to transfer call: ' + (response.data || 'Unknown error'), 'error');
 | 
			
		||||
                }
 | 
			
		||||
@@ -1855,28 +1879,33 @@
 | 
			
		||||
    /**
 | 
			
		||||
     * Show agent selection transfer dialog
 | 
			
		||||
     */
 | 
			
		||||
    function showAgentTransferDialog() {
 | 
			
		||||
        // Load available agents for transfer
 | 
			
		||||
        $.ajax({
 | 
			
		||||
            url: twp_frontend_ajax.ajax_url,
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            data: {
 | 
			
		||||
                action: 'twp_get_transfer_agents',
 | 
			
		||||
                nonce: twp_frontend_ajax.nonce
 | 
			
		||||
            },
 | 
			
		||||
            success: function(response) {
 | 
			
		||||
                if (response.success) {
 | 
			
		||||
                    buildAgentTransferDialog(response.data);
 | 
			
		||||
                } else {
 | 
			
		||||
                    showMessage('Failed to load agents: ' + (response.data || 'Unknown error'), 'error');
 | 
			
		||||
    function showAgentTransferDialog(agents = null) {
 | 
			
		||||
        if (agents) {
 | 
			
		||||
            // Use passed agents data directly
 | 
			
		||||
            buildAgentTransferDialog(agents);
 | 
			
		||||
        } else {
 | 
			
		||||
            // Load available agents for transfer
 | 
			
		||||
            $.ajax({
 | 
			
		||||
                url: twp_frontend_ajax.ajax_url,
 | 
			
		||||
                method: 'POST',
 | 
			
		||||
                data: {
 | 
			
		||||
                    action: 'twp_get_transfer_agents',
 | 
			
		||||
                    nonce: twp_frontend_ajax.nonce
 | 
			
		||||
                },
 | 
			
		||||
                success: function(response) {
 | 
			
		||||
                    if (response.success) {
 | 
			
		||||
                        buildAgentTransferDialog(response.data);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        showMessage('Failed to load agents: ' + (response.data || 'Unknown error'), 'error');
 | 
			
		||||
                        showManualTransferDialog(); // Fallback to manual entry
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                error: function() {
 | 
			
		||||
                    showMessage('Failed to load agents', 'error');
 | 
			
		||||
                    showManualTransferDialog(); // Fallback to manual entry
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            error: function() {
 | 
			
		||||
                showMessage('Failed to load agents', 'error');
 | 
			
		||||
                showManualTransferDialog(); // Fallback to manual entry
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
@@ -2034,7 +2063,7 @@
 | 
			
		||||
            url: twp_frontend_ajax.ajax_url,
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            data: {
 | 
			
		||||
                action: 'twp_get_all_queues',
 | 
			
		||||
                action: 'twp_get_requeue_queues',
 | 
			
		||||
                nonce: twp_frontend_ajax.nonce
 | 
			
		||||
            },
 | 
			
		||||
            success: function(response) {
 | 
			
		||||
 
 | 
			
		||||
@@ -45,7 +45,9 @@ class TWP_Activator {
 | 
			
		||||
            'twp_group_members',
 | 
			
		||||
            'twp_agent_status',
 | 
			
		||||
            'twp_callbacks',
 | 
			
		||||
            'twp_call_recordings'
 | 
			
		||||
            'twp_call_recordings',
 | 
			
		||||
            'twp_user_extensions',
 | 
			
		||||
            'twp_queue_assignments'
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        $missing_tables = array();
 | 
			
		||||
@@ -104,21 +106,30 @@ class TWP_Activator {
 | 
			
		||||
            KEY phone_number (phone_number)
 | 
			
		||||
        ) $charset_collate;";
 | 
			
		||||
        
 | 
			
		||||
        // Call queues table
 | 
			
		||||
        // Call queues table (enhanced for user-specific queues)
 | 
			
		||||
        $table_queues = $wpdb->prefix . 'twp_call_queues';
 | 
			
		||||
        $sql_queues = "CREATE TABLE $table_queues (
 | 
			
		||||
            id int(11) NOT NULL AUTO_INCREMENT,
 | 
			
		||||
            queue_name varchar(100) NOT NULL,
 | 
			
		||||
            queue_type varchar(20) DEFAULT 'general',
 | 
			
		||||
            user_id bigint(20),
 | 
			
		||||
            extension varchar(10),
 | 
			
		||||
            notification_number varchar(20),
 | 
			
		||||
            agent_group_id int(11),
 | 
			
		||||
            max_size int(11) DEFAULT 10,
 | 
			
		||||
            wait_music_url varchar(255),
 | 
			
		||||
            tts_message text,
 | 
			
		||||
            timeout_seconds int(11) DEFAULT 300,
 | 
			
		||||
            voicemail_prompt text,
 | 
			
		||||
            is_hold_queue tinyint(1) DEFAULT 0,
 | 
			
		||||
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
 | 
			
		||||
            PRIMARY KEY (id),
 | 
			
		||||
            KEY agent_group_id (agent_group_id),
 | 
			
		||||
            KEY notification_number (notification_number)
 | 
			
		||||
            KEY notification_number (notification_number),
 | 
			
		||||
            KEY user_id (user_id),
 | 
			
		||||
            KEY extension (extension),
 | 
			
		||||
            KEY queue_type (queue_type),
 | 
			
		||||
            UNIQUE KEY user_queue (user_id, queue_type)
 | 
			
		||||
        ) $charset_collate;";
 | 
			
		||||
        
 | 
			
		||||
        // Queued calls table
 | 
			
		||||
@@ -247,12 +258,14 @@ class TWP_Activator {
 | 
			
		||||
            UNIQUE KEY group_user (group_id, user_id)
 | 
			
		||||
        ) $charset_collate;";
 | 
			
		||||
        
 | 
			
		||||
        // Agent status table
 | 
			
		||||
        // Agent status table (enhanced with login tracking)
 | 
			
		||||
        $table_agent_status = $wpdb->prefix . 'twp_agent_status';
 | 
			
		||||
        $sql_agent_status = "CREATE TABLE $table_agent_status (
 | 
			
		||||
            id int(11) NOT NULL AUTO_INCREMENT,
 | 
			
		||||
            user_id bigint(20) NOT NULL,
 | 
			
		||||
            status varchar(20) DEFAULT 'offline',
 | 
			
		||||
            is_logged_in tinyint(1) DEFAULT 0,
 | 
			
		||||
            logged_in_at datetime,
 | 
			
		||||
            current_call_sid varchar(100),
 | 
			
		||||
            last_activity datetime DEFAULT CURRENT_TIMESTAMP,
 | 
			
		||||
            available_for_queues tinyint(1) DEFAULT 1,
 | 
			
		||||
@@ -260,6 +273,38 @@ class TWP_Activator {
 | 
			
		||||
            UNIQUE KEY user_id (user_id)
 | 
			
		||||
        ) $charset_collate;";
 | 
			
		||||
        
 | 
			
		||||
        // User extensions table
 | 
			
		||||
        $table_user_extensions = $wpdb->prefix . 'twp_user_extensions';
 | 
			
		||||
        $sql_user_extensions = "CREATE TABLE $table_user_extensions (
 | 
			
		||||
            id int(11) NOT NULL AUTO_INCREMENT,
 | 
			
		||||
            user_id bigint(20) NOT NULL,
 | 
			
		||||
            extension varchar(10) NOT NULL,
 | 
			
		||||
            direct_dial_number varchar(20),
 | 
			
		||||
            personal_queue_id int(11),
 | 
			
		||||
            hold_queue_id int(11),
 | 
			
		||||
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
 | 
			
		||||
            updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 | 
			
		||||
            PRIMARY KEY (id),
 | 
			
		||||
            UNIQUE KEY user_id (user_id),
 | 
			
		||||
            UNIQUE KEY extension (extension),
 | 
			
		||||
            KEY personal_queue_id (personal_queue_id),
 | 
			
		||||
            KEY hold_queue_id (hold_queue_id)
 | 
			
		||||
        ) $charset_collate;";
 | 
			
		||||
        
 | 
			
		||||
        // Queue assignments table (many-to-many relationship)
 | 
			
		||||
        $table_queue_assignments = $wpdb->prefix . 'twp_queue_assignments';
 | 
			
		||||
        $sql_queue_assignments = "CREATE TABLE $table_queue_assignments (
 | 
			
		||||
            id int(11) NOT NULL AUTO_INCREMENT,
 | 
			
		||||
            user_id bigint(20) NOT NULL,
 | 
			
		||||
            queue_id int(11) NOT NULL,
 | 
			
		||||
            is_primary tinyint(1) DEFAULT 0,
 | 
			
		||||
            assigned_at datetime DEFAULT CURRENT_TIMESTAMP,
 | 
			
		||||
            PRIMARY KEY (id),
 | 
			
		||||
            UNIQUE KEY user_queue (user_id, queue_id),
 | 
			
		||||
            KEY user_id (user_id),
 | 
			
		||||
            KEY queue_id (queue_id)
 | 
			
		||||
        ) $charset_collate;";
 | 
			
		||||
        
 | 
			
		||||
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
 | 
			
		||||
        dbDelta($sql_schedules);
 | 
			
		||||
        dbDelta($sql_queues);
 | 
			
		||||
@@ -325,6 +370,8 @@ class TWP_Activator {
 | 
			
		||||
        dbDelta($sql_agent_status);
 | 
			
		||||
        dbDelta($sql_callbacks);
 | 
			
		||||
        dbDelta($sql_recordings);
 | 
			
		||||
        dbDelta($sql_user_extensions);
 | 
			
		||||
        dbDelta($sql_queue_assignments);
 | 
			
		||||
        
 | 
			
		||||
        // Add missing columns for existing installations
 | 
			
		||||
        self::add_missing_columns();
 | 
			
		||||
@@ -336,6 +383,64 @@ class TWP_Activator {
 | 
			
		||||
    private static function add_missing_columns() {
 | 
			
		||||
        global $wpdb;
 | 
			
		||||
        
 | 
			
		||||
        // Add new queue columns for user-specific queues
 | 
			
		||||
        $table_queues = $wpdb->prefix . 'twp_call_queues';
 | 
			
		||||
        
 | 
			
		||||
        // Check and add queue_type column
 | 
			
		||||
        $queue_type_exists = $wpdb->get_results("SHOW COLUMNS FROM $table_queues LIKE 'queue_type'");
 | 
			
		||||
        if (empty($queue_type_exists)) {
 | 
			
		||||
            $wpdb->query("ALTER TABLE $table_queues ADD COLUMN queue_type varchar(20) DEFAULT 'general' AFTER queue_name");
 | 
			
		||||
            $wpdb->query("ALTER TABLE $table_queues ADD INDEX queue_type (queue_type)");
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Check and add user_id column
 | 
			
		||||
        $user_id_exists = $wpdb->get_results("SHOW COLUMNS FROM $table_queues LIKE 'user_id'");
 | 
			
		||||
        if (empty($user_id_exists)) {
 | 
			
		||||
            $wpdb->query("ALTER TABLE $table_queues ADD COLUMN user_id bigint(20) AFTER queue_type");
 | 
			
		||||
            $wpdb->query("ALTER TABLE $table_queues ADD INDEX user_id (user_id)");
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Check and add extension column
 | 
			
		||||
        $extension_exists = $wpdb->get_results("SHOW COLUMNS FROM $table_queues LIKE 'extension'");
 | 
			
		||||
        if (empty($extension_exists)) {
 | 
			
		||||
            $wpdb->query("ALTER TABLE $table_queues ADD COLUMN extension varchar(10) AFTER user_id");
 | 
			
		||||
            $wpdb->query("ALTER TABLE $table_queues ADD INDEX extension (extension)");
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Check and add voicemail_prompt column
 | 
			
		||||
        $voicemail_prompt_exists = $wpdb->get_results("SHOW COLUMNS FROM $table_queues LIKE 'voicemail_prompt'");
 | 
			
		||||
        if (empty($voicemail_prompt_exists)) {
 | 
			
		||||
            $wpdb->query("ALTER TABLE $table_queues ADD COLUMN voicemail_prompt text AFTER timeout_seconds");
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Check and add is_hold_queue column
 | 
			
		||||
        $is_hold_queue_exists = $wpdb->get_results("SHOW COLUMNS FROM $table_queues LIKE 'is_hold_queue'");
 | 
			
		||||
        if (empty($is_hold_queue_exists)) {
 | 
			
		||||
            $wpdb->query("ALTER TABLE $table_queues ADD COLUMN is_hold_queue tinyint(1) DEFAULT 0 AFTER voicemail_prompt");
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Add unique constraint for user queues if it doesn't exist
 | 
			
		||||
        $unique_constraint_exists = $wpdb->get_results("SHOW INDEX FROM $table_queues WHERE Key_name = 'user_queue'");
 | 
			
		||||
        if (empty($unique_constraint_exists)) {
 | 
			
		||||
            // Only add if both columns exist
 | 
			
		||||
            if (!empty($user_id_exists) || $wpdb->get_results("SHOW COLUMNS FROM $table_queues LIKE 'user_id'")) {
 | 
			
		||||
                $wpdb->query("ALTER TABLE $table_queues ADD UNIQUE KEY user_queue (user_id, queue_type)");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Add login tracking columns to agent_status table
 | 
			
		||||
        $table_agent_status = $wpdb->prefix . 'twp_agent_status';
 | 
			
		||||
        
 | 
			
		||||
        $is_logged_in_exists = $wpdb->get_results("SHOW COLUMNS FROM $table_agent_status LIKE 'is_logged_in'");
 | 
			
		||||
        if (empty($is_logged_in_exists)) {
 | 
			
		||||
            $wpdb->query("ALTER TABLE $table_agent_status ADD COLUMN is_logged_in tinyint(1) DEFAULT 0 AFTER status");
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        $logged_in_at_exists = $wpdb->get_results("SHOW COLUMNS FROM $table_agent_status LIKE 'logged_in_at'");
 | 
			
		||||
        if (empty($logged_in_at_exists)) {
 | 
			
		||||
            $wpdb->query("ALTER TABLE $table_agent_status ADD COLUMN logged_in_at datetime AFTER is_logged_in");
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        $table_schedules = $wpdb->prefix . 'twp_phone_schedules';
 | 
			
		||||
        
 | 
			
		||||
        // Check if holiday_dates column exists
 | 
			
		||||
 
 | 
			
		||||
@@ -104,16 +104,22 @@ class TWP_Agent_Manager {
 | 
			
		||||
            $user_id
 | 
			
		||||
        ));
 | 
			
		||||
        
 | 
			
		||||
        // Preserve login status if not explicitly changing it
 | 
			
		||||
        $is_logged_in = $existing ? $existing->is_logged_in : 0;
 | 
			
		||||
        $logged_in_at = $existing ? $existing->logged_in_at : null;
 | 
			
		||||
        
 | 
			
		||||
        if ($existing) {
 | 
			
		||||
            return $wpdb->update(
 | 
			
		||||
                $table_name,
 | 
			
		||||
                array(
 | 
			
		||||
                    'status' => $status,
 | 
			
		||||
                    'current_call_sid' => $call_sid,
 | 
			
		||||
                    'last_activity' => current_time('mysql')
 | 
			
		||||
                    'last_activity' => current_time('mysql'),
 | 
			
		||||
                    'is_logged_in' => $is_logged_in,
 | 
			
		||||
                    'logged_in_at' => $logged_in_at
 | 
			
		||||
                ),
 | 
			
		||||
                array('user_id' => $user_id),
 | 
			
		||||
                array('%s', '%s', '%s'),
 | 
			
		||||
                array('%s', '%s', '%s', '%d', '%s'),
 | 
			
		||||
                array('%d')
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
@@ -123,13 +129,85 @@ class TWP_Agent_Manager {
 | 
			
		||||
                    'user_id' => $user_id,
 | 
			
		||||
                    'status' => $status,
 | 
			
		||||
                    'current_call_sid' => $call_sid,
 | 
			
		||||
                    'last_activity' => current_time('mysql')
 | 
			
		||||
                    'last_activity' => current_time('mysql'),
 | 
			
		||||
                    'is_logged_in' => 0,
 | 
			
		||||
                    'logged_in_at' => null
 | 
			
		||||
                ),
 | 
			
		||||
                array('%d', '%s', '%s', '%s')
 | 
			
		||||
                array('%d', '%s', '%s', '%s', '%d', '%s')
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Set agent login status
 | 
			
		||||
     */
 | 
			
		||||
    public static function set_agent_login_status($user_id, $is_logged_in) {
 | 
			
		||||
        global $wpdb;
 | 
			
		||||
        $table_name = $wpdb->prefix . 'twp_agent_status';
 | 
			
		||||
        
 | 
			
		||||
        $existing = $wpdb->get_row($wpdb->prepare(
 | 
			
		||||
            "SELECT * FROM $table_name WHERE user_id = %d",
 | 
			
		||||
            $user_id
 | 
			
		||||
        ));
 | 
			
		||||
        
 | 
			
		||||
        $logged_in_at = $is_logged_in ? current_time('mysql') : null;
 | 
			
		||||
        
 | 
			
		||||
        // Update queue timeout based on login status
 | 
			
		||||
        if (class_exists('TWP_User_Queue_Manager')) {
 | 
			
		||||
            TWP_User_Queue_Manager::update_queue_timeout_for_login($user_id, $is_logged_in);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Also ensure user has queues created if logging in
 | 
			
		||||
        if ($is_logged_in && class_exists('TWP_User_Queue_Manager')) {
 | 
			
		||||
            $extension_data = TWP_User_Queue_Manager::get_user_extension_data($user_id);
 | 
			
		||||
            if (!$extension_data) {
 | 
			
		||||
                TWP_User_Queue_Manager::create_user_queues($user_id);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if ($existing) {
 | 
			
		||||
            return $wpdb->update(
 | 
			
		||||
                $table_name,
 | 
			
		||||
                array(
 | 
			
		||||
                    'is_logged_in' => $is_logged_in ? 1 : 0,
 | 
			
		||||
                    'logged_in_at' => $logged_in_at,
 | 
			
		||||
                    'last_activity' => current_time('mysql'),
 | 
			
		||||
                    'status' => $is_logged_in ? 'available' : 'offline'
 | 
			
		||||
                ),
 | 
			
		||||
                array('user_id' => $user_id),
 | 
			
		||||
                array('%d', '%s', '%s', '%s'),
 | 
			
		||||
                array('%d')
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            return $wpdb->insert(
 | 
			
		||||
                $table_name,
 | 
			
		||||
                array(
 | 
			
		||||
                    'user_id' => $user_id,
 | 
			
		||||
                    'status' => $is_logged_in ? 'available' : 'offline',
 | 
			
		||||
                    'is_logged_in' => $is_logged_in ? 1 : 0,
 | 
			
		||||
                    'logged_in_at' => $logged_in_at,
 | 
			
		||||
                    'last_activity' => current_time('mysql')
 | 
			
		||||
                ),
 | 
			
		||||
                array('%d', '%s', '%d', '%s', '%s')
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if agent is logged in
 | 
			
		||||
     */
 | 
			
		||||
    public static function is_agent_logged_in($user_id) {
 | 
			
		||||
        global $wpdb;
 | 
			
		||||
        $table_name = $wpdb->prefix . 'twp_agent_status';
 | 
			
		||||
        
 | 
			
		||||
        $status = $wpdb->get_row($wpdb->prepare(
 | 
			
		||||
            "SELECT is_logged_in FROM $table_name WHERE user_id = %d",
 | 
			
		||||
            $user_id
 | 
			
		||||
        ));
 | 
			
		||||
        
 | 
			
		||||
        return $status && $status->is_logged_in == 1;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Get agent status
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,7 @@ class TWP_Core {
 | 
			
		||||
        require_once TWP_PLUGIN_DIR . 'includes/class-twp-agent-groups.php';
 | 
			
		||||
        require_once TWP_PLUGIN_DIR . 'includes/class-twp-agent-manager.php';
 | 
			
		||||
        require_once TWP_PLUGIN_DIR . 'includes/class-twp-callback-manager.php';
 | 
			
		||||
        require_once TWP_PLUGIN_DIR . 'includes/class-twp-user-queue-manager.php';
 | 
			
		||||
        require_once TWP_PLUGIN_DIR . 'includes/class-twp-shortcodes.php';
 | 
			
		||||
        
 | 
			
		||||
        // Admin classes
 | 
			
		||||
@@ -146,6 +147,17 @@ class TWP_Core {
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_delete_queue', $plugin_admin, 'ajax_delete_queue');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_get_dashboard_stats', $plugin_admin, 'ajax_get_dashboard_stats');
 | 
			
		||||
        
 | 
			
		||||
        // Queue management actions
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_get_queue_calls', $plugin_admin, 'ajax_get_queue_calls');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_toggle_agent_login', $plugin_admin, 'ajax_toggle_agent_login');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_answer_queue_call', $plugin_admin, 'ajax_answer_queue_call');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_monitor_call', $plugin_admin, 'ajax_monitor_call');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_toggle_call_recording', $plugin_admin, 'ajax_toggle_call_recording');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_transfer_call', $plugin_admin, 'ajax_transfer_call');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_send_to_voicemail', $plugin_admin, 'ajax_send_to_voicemail');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_disconnect_call', $plugin_admin, 'ajax_disconnect_call');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_get_transfer_targets', $plugin_admin, 'ajax_get_transfer_targets');
 | 
			
		||||
        
 | 
			
		||||
        // Eleven Labs AJAX
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_get_elevenlabs_voices', $plugin_admin, 'ajax_get_elevenlabs_voices');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_get_elevenlabs_models', $plugin_admin, 'ajax_get_elevenlabs_models');
 | 
			
		||||
@@ -176,6 +188,7 @@ class TWP_Core {
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_accept_next_queue_call', $plugin_admin, 'ajax_accept_next_queue_call');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_get_waiting_calls', $plugin_admin, 'ajax_get_waiting_calls');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_get_agent_queues', $plugin_admin, 'ajax_get_agent_queues');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_get_requeue_queues', $plugin_admin, 'ajax_get_requeue_queues');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_set_agent_status', $plugin_admin, 'ajax_set_agent_status');
 | 
			
		||||
        $this->loader->add_action('wp_ajax_twp_get_call_details', $plugin_admin, 'ajax_get_call_details');
 | 
			
		||||
        
 | 
			
		||||
 
 | 
			
		||||
@@ -158,6 +158,10 @@ class TWP_Shortcodes {
 | 
			
		||||
                    <span class="hangup-icon">📞</span>
 | 
			
		||||
                    <span class="hangup-text">Hang Up</span>
 | 
			
		||||
                </button>
 | 
			
		||||
                <button id="twp-resume-btn" class="twp-btn twp-btn-warning" style="display: none;">
 | 
			
		||||
                    <span class="resume-icon">▶️</span>
 | 
			
		||||
                    <span class="resume-text">Resume Call</span>
 | 
			
		||||
                </button>
 | 
			
		||||
            </div>
 | 
			
		||||
            
 | 
			
		||||
            <!-- Call Info -->
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										420
									
								
								includes/class-twp-user-queue-manager.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										420
									
								
								includes/class-twp-user-queue-manager.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,420 @@
 | 
			
		||||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * User Queue Manager
 | 
			
		||||
 * 
 | 
			
		||||
 * Handles user-specific queues, extensions, and hold queues
 | 
			
		||||
 */
 | 
			
		||||
class TWP_User_Queue_Manager {
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Create personal and hold queues for a user
 | 
			
		||||
     * 
 | 
			
		||||
     * @param int $user_id WordPress user ID
 | 
			
		||||
     * @param string $extension User's extension number
 | 
			
		||||
     * @return array Array with queue IDs and extension info
 | 
			
		||||
     */
 | 
			
		||||
    public static function create_user_queues($user_id, $extension = null) {
 | 
			
		||||
        global $wpdb;
 | 
			
		||||
        
 | 
			
		||||
        $user = get_user_by('id', $user_id);
 | 
			
		||||
        if (!$user) {
 | 
			
		||||
            return array('success' => false, 'error' => 'User not found');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Generate extension if not provided
 | 
			
		||||
        if (!$extension) {
 | 
			
		||||
            $extension = self::generate_unique_extension();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Check if extension already exists
 | 
			
		||||
        $existing = $wpdb->get_var($wpdb->prepare(
 | 
			
		||||
            "SELECT extension FROM {$wpdb->prefix}twp_user_extensions WHERE extension = %s",
 | 
			
		||||
            $extension
 | 
			
		||||
        ));
 | 
			
		||||
        
 | 
			
		||||
        if ($existing) {
 | 
			
		||||
            return array('success' => false, 'error' => 'Extension already exists');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Create personal queue
 | 
			
		||||
        $personal_queue_name = sprintf('%s (%s)', $user->display_name, $extension);
 | 
			
		||||
        $personal_queue_id = $wpdb->insert(
 | 
			
		||||
            $wpdb->prefix . 'twp_call_queues',
 | 
			
		||||
            array(
 | 
			
		||||
                'queue_name' => $personal_queue_name,
 | 
			
		||||
                'queue_type' => 'personal',
 | 
			
		||||
                'user_id' => $user_id,
 | 
			
		||||
                'extension' => $extension,
 | 
			
		||||
                'max_size' => 10,
 | 
			
		||||
                'timeout_seconds' => 300, // 5 minutes for logged-in users
 | 
			
		||||
                'voicemail_prompt' => sprintf('You have reached %s. Please leave a message after the tone.', $user->display_name),
 | 
			
		||||
                'is_hold_queue' => 0
 | 
			
		||||
            ),
 | 
			
		||||
            array('%s', '%s', '%d', '%s', '%d', '%d', '%s', '%d')
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        if (!$personal_queue_id) {
 | 
			
		||||
            return array('success' => false, 'error' => 'Failed to create personal queue');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        $personal_queue_id = $wpdb->insert_id;
 | 
			
		||||
        
 | 
			
		||||
        // Create hold queue
 | 
			
		||||
        $hold_queue_name = sprintf('Hold - %s', $user->display_name);
 | 
			
		||||
        $hold_queue_id = $wpdb->insert(
 | 
			
		||||
            $wpdb->prefix . 'twp_call_queues',
 | 
			
		||||
            array(
 | 
			
		||||
                'queue_name' => $hold_queue_name,
 | 
			
		||||
                'queue_type' => 'hold',
 | 
			
		||||
                'user_id' => $user_id,
 | 
			
		||||
                'extension' => null, // Hold queues don't have extensions
 | 
			
		||||
                'max_size' => 5,
 | 
			
		||||
                'timeout_seconds' => 0, // No timeout for hold queues
 | 
			
		||||
                'tts_message' => 'Your call is on hold. Please wait.',
 | 
			
		||||
                'is_hold_queue' => 1
 | 
			
		||||
            ),
 | 
			
		||||
            array('%s', '%s', '%d', '%s', '%d', '%d', '%s', '%d')
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        if (!$hold_queue_id) {
 | 
			
		||||
            // Rollback personal queue creation
 | 
			
		||||
            $wpdb->delete($wpdb->prefix . 'twp_call_queues', array('id' => $personal_queue_id));
 | 
			
		||||
            return array('success' => false, 'error' => 'Failed to create hold queue');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        $hold_queue_id = $wpdb->insert_id;
 | 
			
		||||
        
 | 
			
		||||
        // Create user extension record
 | 
			
		||||
        $extension_result = $wpdb->insert(
 | 
			
		||||
            $wpdb->prefix . 'twp_user_extensions',
 | 
			
		||||
            array(
 | 
			
		||||
                'user_id' => $user_id,
 | 
			
		||||
                'extension' => $extension,
 | 
			
		||||
                'personal_queue_id' => $personal_queue_id,
 | 
			
		||||
                'hold_queue_id' => $hold_queue_id
 | 
			
		||||
            ),
 | 
			
		||||
            array('%d', '%s', '%d', '%d')
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        if (!$extension_result) {
 | 
			
		||||
            // Rollback queue creations
 | 
			
		||||
            $wpdb->delete($wpdb->prefix . 'twp_call_queues', array('id' => $personal_queue_id));
 | 
			
		||||
            $wpdb->delete($wpdb->prefix . 'twp_call_queues', array('id' => $hold_queue_id));
 | 
			
		||||
            return array('success' => false, 'error' => 'Failed to create extension record');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Auto-assign user to their personal queue
 | 
			
		||||
        $wpdb->insert(
 | 
			
		||||
            $wpdb->prefix . 'twp_queue_assignments',
 | 
			
		||||
            array(
 | 
			
		||||
                'user_id' => $user_id,
 | 
			
		||||
                'queue_id' => $personal_queue_id,
 | 
			
		||||
                'is_primary' => 1
 | 
			
		||||
            ),
 | 
			
		||||
            array('%d', '%d', '%d')
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        // Auto-assign user to their hold queue
 | 
			
		||||
        $wpdb->insert(
 | 
			
		||||
            $wpdb->prefix . 'twp_queue_assignments',
 | 
			
		||||
            array(
 | 
			
		||||
                'user_id' => $user_id,
 | 
			
		||||
                'queue_id' => $hold_queue_id,
 | 
			
		||||
                'is_primary' => 0
 | 
			
		||||
            ),
 | 
			
		||||
            array('%d', '%d', '%d')
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        return array(
 | 
			
		||||
            'success' => true,
 | 
			
		||||
            'extension' => $extension,
 | 
			
		||||
            'personal_queue_id' => $personal_queue_id,
 | 
			
		||||
            'hold_queue_id' => $hold_queue_id
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Generate a unique extension number
 | 
			
		||||
     * 
 | 
			
		||||
     * @return string Extension number (3-4 digits)
 | 
			
		||||
     */
 | 
			
		||||
    private static function generate_unique_extension() {
 | 
			
		||||
        global $wpdb;
 | 
			
		||||
        
 | 
			
		||||
        // Start with 100 for 3-digit extensions
 | 
			
		||||
        $start = 100;
 | 
			
		||||
        $max_attempts = 900; // Up to 999
 | 
			
		||||
        
 | 
			
		||||
        for ($i = 0; $i < $max_attempts; $i++) {
 | 
			
		||||
            $extension = (string)($start + $i);
 | 
			
		||||
            
 | 
			
		||||
            $exists = $wpdb->get_var($wpdb->prepare(
 | 
			
		||||
                "SELECT extension FROM {$wpdb->prefix}twp_user_extensions WHERE extension = %s",
 | 
			
		||||
                $extension
 | 
			
		||||
            ));
 | 
			
		||||
            
 | 
			
		||||
            if (!$exists) {
 | 
			
		||||
                return $extension;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // If all 3-digit extensions are taken, try 4-digit starting at 1000
 | 
			
		||||
        $start = 1000;
 | 
			
		||||
        $max_attempts = 9000; // Up to 9999
 | 
			
		||||
        
 | 
			
		||||
        for ($i = 0; $i < $max_attempts; $i++) {
 | 
			
		||||
            $extension = (string)($start + $i);
 | 
			
		||||
            
 | 
			
		||||
            $exists = $wpdb->get_var($wpdb->prepare(
 | 
			
		||||
                "SELECT extension FROM {$wpdb->prefix}twp_user_extensions WHERE extension = %s",
 | 
			
		||||
                $extension
 | 
			
		||||
            ));
 | 
			
		||||
            
 | 
			
		||||
            if (!$exists) {
 | 
			
		||||
                return $extension;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        return null; // All extensions taken (unlikely)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Get user's extension and queue information
 | 
			
		||||
     * 
 | 
			
		||||
     * @param int $user_id WordPress user ID
 | 
			
		||||
     * @return array|null Extension and queue data
 | 
			
		||||
     */
 | 
			
		||||
    public static function get_user_extension_data($user_id) {
 | 
			
		||||
        global $wpdb;
 | 
			
		||||
        
 | 
			
		||||
        $data = $wpdb->get_row($wpdb->prepare(
 | 
			
		||||
            "SELECT * FROM {$wpdb->prefix}twp_user_extensions WHERE user_id = %d",
 | 
			
		||||
            $user_id
 | 
			
		||||
        ), ARRAY_A);
 | 
			
		||||
        
 | 
			
		||||
        return $data;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Get user by extension
 | 
			
		||||
     * 
 | 
			
		||||
     * @param string $extension Extension number
 | 
			
		||||
     * @return int|null User ID
 | 
			
		||||
     */
 | 
			
		||||
    public static function get_user_by_extension($extension) {
 | 
			
		||||
        global $wpdb;
 | 
			
		||||
        
 | 
			
		||||
        $user_id = $wpdb->get_var($wpdb->prepare(
 | 
			
		||||
            "SELECT user_id FROM {$wpdb->prefix}twp_user_extensions WHERE extension = %s",
 | 
			
		||||
            $extension
 | 
			
		||||
        ));
 | 
			
		||||
        
 | 
			
		||||
        return $user_id ? intval($user_id) : null;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Get all queues assigned to a user
 | 
			
		||||
     * 
 | 
			
		||||
     * @param int $user_id WordPress user ID
 | 
			
		||||
     * @return array Array of queue data
 | 
			
		||||
     */
 | 
			
		||||
    public static function get_user_assigned_queues($user_id) {
 | 
			
		||||
        global $wpdb;
 | 
			
		||||
        
 | 
			
		||||
        $query = $wpdb->prepare("
 | 
			
		||||
            SELECT q.*, qa.is_primary,
 | 
			
		||||
                   (SELECT COUNT(*) FROM {$wpdb->prefix}twp_queued_calls qc 
 | 
			
		||||
                    WHERE qc.queue_id = q.id AND qc.status = 'waiting') as waiting_calls
 | 
			
		||||
            FROM {$wpdb->prefix}twp_call_queues q
 | 
			
		||||
            INNER JOIN {$wpdb->prefix}twp_queue_assignments qa ON q.id = qa.queue_id
 | 
			
		||||
            WHERE qa.user_id = %d
 | 
			
		||||
            ORDER BY qa.is_primary DESC, q.queue_name ASC
 | 
			
		||||
        ", $user_id);
 | 
			
		||||
        
 | 
			
		||||
        $queues = $wpdb->get_results($query, ARRAY_A);
 | 
			
		||||
        
 | 
			
		||||
        return $queues;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Update queue timeout based on user login status
 | 
			
		||||
     * 
 | 
			
		||||
     * @param int $user_id WordPress user ID
 | 
			
		||||
     * @param bool $is_logged_in Whether user is logged in
 | 
			
		||||
     */
 | 
			
		||||
    public static function update_queue_timeout_for_login($user_id, $is_logged_in) {
 | 
			
		||||
        global $wpdb;
 | 
			
		||||
        
 | 
			
		||||
        // Get user's personal queue
 | 
			
		||||
        $extension_data = self::get_user_extension_data($user_id);
 | 
			
		||||
        
 | 
			
		||||
        if (!$extension_data || !$extension_data['personal_queue_id']) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Update timeout: 5 minutes if logged in, 0 (immediate voicemail) if logged out
 | 
			
		||||
        $timeout = $is_logged_in ? 300 : 0;
 | 
			
		||||
        
 | 
			
		||||
        $wpdb->update(
 | 
			
		||||
            $wpdb->prefix . 'twp_call_queues',
 | 
			
		||||
            array('timeout_seconds' => $timeout),
 | 
			
		||||
            array('id' => $extension_data['personal_queue_id']),
 | 
			
		||||
            array('%d'),
 | 
			
		||||
            array('%d')
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Transfer call to user's hold queue
 | 
			
		||||
     * 
 | 
			
		||||
     * @param int $user_id WordPress user ID
 | 
			
		||||
     * @param string $call_sid Call SID to transfer
 | 
			
		||||
     * @return array Result array
 | 
			
		||||
     */
 | 
			
		||||
    public static function transfer_to_hold_queue($user_id, $call_sid) {
 | 
			
		||||
        global $wpdb;
 | 
			
		||||
        
 | 
			
		||||
        // Get user's hold queue
 | 
			
		||||
        $extension_data = self::get_user_extension_data($user_id);
 | 
			
		||||
        
 | 
			
		||||
        if (!$extension_data || !$extension_data['hold_queue_id']) {
 | 
			
		||||
            return array('success' => false, 'error' => 'Hold queue not found for user');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Check if call exists in any queue
 | 
			
		||||
        $current_queue = $wpdb->get_row($wpdb->prepare(
 | 
			
		||||
            "SELECT * FROM {$wpdb->prefix}twp_queued_calls WHERE call_sid = %s AND status = 'waiting'",
 | 
			
		||||
            $call_sid
 | 
			
		||||
        ), ARRAY_A);
 | 
			
		||||
        
 | 
			
		||||
        if (!$current_queue) {
 | 
			
		||||
            return array('success' => false, 'error' => 'Call not found in queue');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Move call to hold queue
 | 
			
		||||
        $result = $wpdb->update(
 | 
			
		||||
            $wpdb->prefix . 'twp_queued_calls',
 | 
			
		||||
            array(
 | 
			
		||||
                'queue_id' => $extension_data['hold_queue_id'],
 | 
			
		||||
                'position' => 1 // Reset position in hold queue
 | 
			
		||||
            ),
 | 
			
		||||
            array('id' => $current_queue['id']),
 | 
			
		||||
            array('%d', '%d'),
 | 
			
		||||
            array('%d')
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        if ($result === false) {
 | 
			
		||||
            return array('success' => false, 'error' => 'Failed to transfer to hold queue');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        return array(
 | 
			
		||||
            'success' => true,
 | 
			
		||||
            'hold_queue_id' => $extension_data['hold_queue_id']
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Transfer call from hold queue back to original or specified queue
 | 
			
		||||
     * 
 | 
			
		||||
     * @param int $user_id WordPress user ID
 | 
			
		||||
     * @param string $call_sid Call SID to transfer
 | 
			
		||||
     * @param int $target_queue_id Optional target queue ID
 | 
			
		||||
     * @return array Result array
 | 
			
		||||
     */
 | 
			
		||||
    public static function resume_from_hold($user_id, $call_sid, $target_queue_id = null) {
 | 
			
		||||
        global $wpdb;
 | 
			
		||||
        
 | 
			
		||||
        // Get user's hold queue
 | 
			
		||||
        $extension_data = self::get_user_extension_data($user_id);
 | 
			
		||||
        
 | 
			
		||||
        if (!$extension_data || !$extension_data['hold_queue_id']) {
 | 
			
		||||
            return array('success' => false, 'error' => 'Hold queue not found for user');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Check if call is in hold queue
 | 
			
		||||
        $held_call = $wpdb->get_row($wpdb->prepare(
 | 
			
		||||
            "SELECT * FROM {$wpdb->prefix}twp_queued_calls 
 | 
			
		||||
             WHERE call_sid = %s AND queue_id = %d AND status = 'waiting'",
 | 
			
		||||
            $call_sid,
 | 
			
		||||
            $extension_data['hold_queue_id']
 | 
			
		||||
        ), ARRAY_A);
 | 
			
		||||
        
 | 
			
		||||
        if (!$held_call) {
 | 
			
		||||
            return array('success' => false, 'error' => 'Call not found in hold queue');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Determine target queue
 | 
			
		||||
        if (!$target_queue_id) {
 | 
			
		||||
            // Default to user's personal queue
 | 
			
		||||
            $target_queue_id = $extension_data['personal_queue_id'];
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Get next position in target queue
 | 
			
		||||
        $next_position = $wpdb->get_var($wpdb->prepare(
 | 
			
		||||
            "SELECT COALESCE(MAX(position), 0) + 1 FROM {$wpdb->prefix}twp_queued_calls 
 | 
			
		||||
             WHERE queue_id = %d AND status = 'waiting'",
 | 
			
		||||
            $target_queue_id
 | 
			
		||||
        ));
 | 
			
		||||
        
 | 
			
		||||
        // Move call to target queue
 | 
			
		||||
        $result = $wpdb->update(
 | 
			
		||||
            $wpdb->prefix . 'twp_queued_calls',
 | 
			
		||||
            array(
 | 
			
		||||
                'queue_id' => $target_queue_id,
 | 
			
		||||
                'position' => $next_position
 | 
			
		||||
            ),
 | 
			
		||||
            array('id' => $held_call['id']),
 | 
			
		||||
            array('%d', '%d'),
 | 
			
		||||
            array('%d')
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        if ($result === false) {
 | 
			
		||||
            return array('success' => false, 'error' => 'Failed to resume from hold');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        return array(
 | 
			
		||||
            'success' => true,
 | 
			
		||||
            'target_queue_id' => $target_queue_id,
 | 
			
		||||
            'position' => $next_position
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Initialize user queues for all existing users
 | 
			
		||||
     * This should be called during plugin activation or upgrade
 | 
			
		||||
     */
 | 
			
		||||
    public static function initialize_all_user_queues() {
 | 
			
		||||
        $users = get_users(array(
 | 
			
		||||
            'fields' => 'ID',
 | 
			
		||||
            'meta_key' => 'twp_phone_number',
 | 
			
		||||
            'meta_compare' => 'EXISTS'
 | 
			
		||||
        ));
 | 
			
		||||
        
 | 
			
		||||
        $results = array(
 | 
			
		||||
            'success' => 0,
 | 
			
		||||
            'failed' => 0,
 | 
			
		||||
            'skipped' => 0
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        foreach ($users as $user_id) {
 | 
			
		||||
            // Check if user already has queues
 | 
			
		||||
            $existing = self::get_user_extension_data($user_id);
 | 
			
		||||
            
 | 
			
		||||
            if ($existing) {
 | 
			
		||||
                $results['skipped']++;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            $result = self::create_user_queues($user_id);
 | 
			
		||||
            
 | 
			
		||||
            if ($result['success']) {
 | 
			
		||||
                $results['success']++;
 | 
			
		||||
            } else {
 | 
			
		||||
                $results['failed']++;
 | 
			
		||||
                error_log('TWP: Failed to create queues for user ' . $user_id . ': ' . $result['error']);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        return $results;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -15,8 +15,8 @@ if (!defined('WPINC')) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Plugin constants
 | 
			
		||||
define('TWP_VERSION', '2.2.0');
 | 
			
		||||
define('TWP_DB_VERSION', '1.1.0'); // Track database version separately
 | 
			
		||||
define('TWP_VERSION', '2.4.2');
 | 
			
		||||
define('TWP_DB_VERSION', '1.6.0'); // Track database version separately
 | 
			
		||||
define('TWP_PLUGIN_DIR', plugin_dir_path(__FILE__));
 | 
			
		||||
define('TWP_PLUGIN_URL', plugin_dir_url(__FILE__));
 | 
			
		||||
define('TWP_PLUGIN_BASENAME', plugin_basename(__FILE__));
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user