Fix workflow forward task immediate disconnection issue
Fixed critical bug where forward tasks in workflows would immediately disconnect calls instead of forwarding them properly. Changes: - Fixed append_twiml_element function to properly handle Dial elements with child Number elements - Enhanced create_forward_twiml to extract numbers from nested data structures - Added comprehensive error handling for missing forward numbers - Added detailed logging throughout workflow execution for debugging - Set default timeout of 30 seconds for forward operations The issue was caused by the Dial element being converted to string which lost all child Number elements, resulting in an empty dial that would immediately disconnect. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -79,7 +79,9 @@ class TWP_Workflow {
|
||||
break;
|
||||
|
||||
case 'forward':
|
||||
error_log('TWP Workflow: Processing forward step: ' . json_encode($step));
|
||||
$step_twiml = self::create_forward_twiml($step);
|
||||
error_log('TWP Workflow: Forward step TwiML generated: ' . $step_twiml);
|
||||
$stop_after_step = true; // Forward ends the workflow
|
||||
break;
|
||||
|
||||
@@ -135,6 +137,9 @@ class TWP_Workflow {
|
||||
|
||||
// Add step TwiML to combined response
|
||||
if ($step_twiml) {
|
||||
error_log('TWP Workflow: Appending step TwiML to combined response');
|
||||
error_log('TWP Workflow: Step TwiML before append: ' . $step_twiml);
|
||||
|
||||
// Parse the step TwiML and append to combined response
|
||||
$step_xml = simplexml_load_string($step_twiml);
|
||||
if ($step_xml) {
|
||||
@@ -142,10 +147,15 @@ class TWP_Workflow {
|
||||
self::append_twiml_element($response, $element);
|
||||
}
|
||||
$has_response = true;
|
||||
|
||||
error_log('TWP Workflow: Combined response after append: ' . $response->asXML());
|
||||
} else {
|
||||
error_log('TWP Workflow: ERROR - Failed to parse step TwiML: ' . $step_twiml);
|
||||
}
|
||||
|
||||
|
||||
// Stop processing if this step type should end the workflow
|
||||
if ($stop_after_step) {
|
||||
error_log('TWP Workflow: Stopping after this step (stop_after_step = true)');
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -153,10 +163,13 @@ class TWP_Workflow {
|
||||
|
||||
// Return combined response or default
|
||||
if ($has_response) {
|
||||
return $response->asXML();
|
||||
$final_twiml = $response->asXML();
|
||||
error_log('TWP Workflow: Final workflow TwiML response: ' . $final_twiml);
|
||||
return $final_twiml;
|
||||
}
|
||||
|
||||
|
||||
// Default response
|
||||
error_log('TWP Workflow: No response generated, returning default response');
|
||||
return self::create_default_response();
|
||||
}
|
||||
|
||||
@@ -196,7 +209,23 @@ class TWP_Workflow {
|
||||
$response->record($attributes);
|
||||
break;
|
||||
case 'Dial':
|
||||
$response->dial((string) $element, $attributes);
|
||||
// Create dial instance
|
||||
$dial = $response->dial('', $attributes);
|
||||
// Add child Number elements
|
||||
foreach ($element->children() as $child) {
|
||||
$child_name = $child->getName();
|
||||
if ($child_name === 'Number') {
|
||||
$dial->number((string) $child, self::get_attributes($child));
|
||||
} elseif ($child_name === 'Client') {
|
||||
$dial->client((string) $child, self::get_attributes($child));
|
||||
} elseif ($child_name === 'Queue') {
|
||||
$dial->queue((string) $child, self::get_attributes($child));
|
||||
} elseif ($child_name === 'Conference') {
|
||||
$dial->conference((string) $child, self::get_attributes($child));
|
||||
} elseif ($child_name === 'Sip') {
|
||||
$dial->sip((string) $child, self::get_attributes($child));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Queue':
|
||||
$response->queue((string) $element, $attributes);
|
||||
@@ -485,25 +514,72 @@ class TWP_Workflow {
|
||||
* Create forward TwiML
|
||||
*/
|
||||
private static function create_forward_twiml($step) {
|
||||
error_log('TWP Workflow Forward: Creating forward TwiML with step data: ' . print_r($step, true));
|
||||
|
||||
$twiml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><Response></Response>');
|
||||
|
||||
|
||||
// Check if data is nested (workflow steps have data nested)
|
||||
$step_data = isset($step['data']) ? $step['data'] : $step;
|
||||
|
||||
// Get the forward number(s) from the proper location
|
||||
$forward_numbers = array();
|
||||
|
||||
// Check various possible locations for forward numbers
|
||||
if (isset($step_data['forward_numbers']) && is_array($step_data['forward_numbers'])) {
|
||||
$forward_numbers = $step_data['forward_numbers'];
|
||||
error_log('TWP Workflow Forward: Found forward_numbers array in data: ' . print_r($forward_numbers, true));
|
||||
} elseif (isset($step_data['forward_number']) && !empty($step_data['forward_number'])) {
|
||||
$forward_numbers = array($step_data['forward_number']);
|
||||
error_log('TWP Workflow Forward: Found single forward_number in data: ' . $step_data['forward_number']);
|
||||
} elseif (isset($step_data['number']) && !empty($step_data['number'])) {
|
||||
$forward_numbers = array($step_data['number']);
|
||||
error_log('TWP Workflow Forward: Found number in data: ' . $step_data['number']);
|
||||
} elseif (isset($step['forward_numbers']) && is_array($step['forward_numbers'])) {
|
||||
$forward_numbers = $step['forward_numbers'];
|
||||
error_log('TWP Workflow Forward: Found forward_numbers array: ' . print_r($forward_numbers, true));
|
||||
} elseif (isset($step['forward_number']) && !empty($step['forward_number'])) {
|
||||
$forward_numbers = array($step['forward_number']);
|
||||
error_log('TWP Workflow Forward: Found single forward_number: ' . $step['forward_number']);
|
||||
} elseif (isset($step['number']) && !empty($step['number'])) {
|
||||
$forward_numbers = array($step['number']);
|
||||
error_log('TWP Workflow Forward: Found number: ' . $step['number']);
|
||||
}
|
||||
|
||||
// Filter out empty numbers
|
||||
$forward_numbers = array_filter($forward_numbers, function($num) {
|
||||
return !empty($num);
|
||||
});
|
||||
|
||||
if (empty($forward_numbers)) {
|
||||
error_log('TWP Workflow Forward: ERROR - No forward numbers found in step data');
|
||||
// Return error message instead of empty dial
|
||||
$say = $twiml->addChild('Say', 'Sorry, the forwarding destination is not configured. Please try again later.');
|
||||
$say->addAttribute('voice', 'alice');
|
||||
$twiml->addChild('Hangup');
|
||||
return $twiml->asXML();
|
||||
}
|
||||
|
||||
error_log('TWP Workflow Forward: Forwarding to numbers: ' . implode(', ', $forward_numbers));
|
||||
|
||||
$dial = $twiml->addChild('Dial');
|
||||
$dial->addAttribute('answerOnBridge', 'true');
|
||||
|
||||
if (isset($step['timeout'])) {
|
||||
$dial->addAttribute('timeout', $step['timeout']);
|
||||
|
||||
// Set timeout (default to 30 seconds if not specified)
|
||||
$timeout = isset($step_data['timeout']) ? $step_data['timeout'] :
|
||||
(isset($step['timeout']) ? $step['timeout'] : '30');
|
||||
$dial->addAttribute('timeout', $timeout);
|
||||
error_log('TWP Workflow Forward: Using timeout: ' . $timeout);
|
||||
|
||||
// Add all forward numbers
|
||||
foreach ($forward_numbers as $number) {
|
||||
error_log('TWP Workflow Forward: Adding number to Dial: ' . $number);
|
||||
$dial->addChild('Number', $number);
|
||||
}
|
||||
|
||||
if (isset($step['forward_numbers']) && is_array($step['forward_numbers'])) {
|
||||
// Sequential forwarding
|
||||
foreach ($step['forward_numbers'] as $number) {
|
||||
$dial->addChild('Number', $number);
|
||||
}
|
||||
} elseif (isset($step['forward_number'])) {
|
||||
$dial->addChild('Number', $step['forward_number']);
|
||||
}
|
||||
|
||||
return $twiml->asXML();
|
||||
|
||||
$result = $twiml->asXML();
|
||||
error_log('TWP Workflow Forward: Final Forward TwiML: ' . $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user