Implement multiple phone numbers per workflow feature

Database Changes:
- Added twp_workflow_phones junction table for many-to-many relationship
- Updated activator to create and manage new table
- Maintained backward compatibility with existing phone_number field

Workflow Management:
- Added set_workflow_phone_numbers() and get_workflow_phone_numbers() methods
- Updated get_workflow_by_phone_number() to check both old and new structures
- Enhanced save/update handlers to support phone_numbers array
- Added AJAX endpoint for retrieving workflow phone numbers

User Interface:
- Replaced single phone number select with dynamic multi-select interface
- Added "Add Number" and "Remove" buttons for managing multiple numbers
- Updated workflow listing to display all assigned phone numbers
- Enhanced JavaScript for phone number management and validation

The webhook routing already supports multiple numbers since get_workflow_by_phone_number()
was updated to check both structures. This feature allows users to assign multiple
Twilio phone numbers to trigger the same workflow.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-13 10:35:21 -07:00
parent 30b0cd355f
commit aa58b45501
5 changed files with 254 additions and 19 deletions

View File

@@ -1476,10 +1476,14 @@ class TWP_Admin {
foreach ($workflows as $workflow) {
$workflow_data = json_decode($workflow->workflow_data, true);
$step_count = isset($workflow_data['steps']) ? count($workflow_data['steps']) : 0;
// Get phone numbers for this workflow
$phone_numbers = TWP_Workflow::get_workflow_phone_numbers($workflow->id);
$phone_display = !empty($phone_numbers) ? implode(', ', $phone_numbers) : $workflow->phone_number;
?>
<tr>
<td><?php echo esc_html($workflow->workflow_name); ?></td>
<td><?php echo esc_html($workflow->phone_number); ?></td>
<td><?php echo esc_html($phone_display); ?></td>
<td><?php echo $step_count; ?> steps</td>
<td>
<span class="twp-status <?php echo $workflow->is_active ? 'active' : 'inactive'; ?>">
@@ -1510,11 +1514,17 @@ class TWP_Admin {
<input type="text" id="workflow-name" name="workflow_name" required>
</div>
<div>
<label>Phone Number:</label>
<select id="workflow-phone" name="phone_number" required>
<option value="">Select a phone number...</option>
<!-- Will be populated via AJAX -->
</select>
<label>Phone Numbers:</label>
<div id="workflow-phone-numbers">
<div class="phone-number-row">
<select name="phone_numbers[]" class="workflow-phone-select" required>
<option value="">Select a phone number...</option>
<!-- Will be populated via AJAX -->
</select>
<button type="button" class="button add-phone-number" style="margin-left: 10px;">Add Number</button>
</div>
</div>
<p class="description">You can assign multiple phone numbers to this workflow. All selected numbers will trigger this workflow when called.</p>
</div>
<div>
<label>
@@ -2913,9 +2923,27 @@ class TWP_Admin {
}
}
// Handle phone numbers - can be a single number (legacy) or array (new)
$phone_numbers = array();
if (isset($_POST['phone_numbers']) && is_array($_POST['phone_numbers'])) {
// New multi-number format
foreach ($_POST['phone_numbers'] as $number) {
$number = sanitize_text_field($number);
if (!empty($number)) {
$phone_numbers[] = $number;
}
}
} elseif (isset($_POST['phone_number'])) {
// Legacy single number format
$number = sanitize_text_field($_POST['phone_number']);
if (!empty($number)) {
$phone_numbers[] = $number;
}
}
$data = array(
'workflow_name' => sanitize_text_field($_POST['workflow_name']),
'phone_number' => sanitize_text_field($_POST['phone_number']),
'phone_number' => isset($phone_numbers[0]) ? $phone_numbers[0] : '', // Keep first number for backward compatibility
'steps' => isset($workflow_data_parsed['steps']) ? $workflow_data_parsed['steps'] : array(),
'conditions' => isset($workflow_data_parsed['conditions']) ? $workflow_data_parsed['conditions'] : array(),
'actions' => isset($workflow_data_parsed['actions']) ? $workflow_data_parsed['actions'] : array(),
@@ -2927,13 +2955,21 @@ class TWP_Admin {
$result = TWP_Workflow::update_workflow($workflow_id, $data);
} else {
$result = TWP_Workflow::create_workflow($data);
if ($result !== false) {
global $wpdb;
$workflow_id = $wpdb->insert_id;
}
}
// Save phone numbers to junction table
if ($result !== false && !empty($phone_numbers)) {
TWP_Workflow::set_workflow_phone_numbers($workflow_id, $phone_numbers);
}
if ($result === false) {
wp_send_json_error('Failed to save workflow to database');
} else {
global $wpdb;
wp_send_json_success(array('success' => true, 'workflow_id' => $workflow_id ?: $wpdb->insert_id));
wp_send_json_success(array('success' => true, 'workflow_id' => $workflow_id));
}
}
@@ -2953,6 +2989,23 @@ class TWP_Admin {
wp_send_json_success($workflow);
}
/**
* AJAX handler for getting workflow phone numbers
*/
public function ajax_get_workflow_phone_numbers() {
check_ajax_referer('twp_ajax_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error('Unauthorized');
return;
}
$workflow_id = intval($_POST['workflow_id']);
$phone_numbers = TWP_Workflow::get_workflow_phone_numbers($workflow_id);
wp_send_json_success($phone_numbers);
}
/**
* AJAX handler for deleting workflow
*/