2 Commits

Author SHA1 Message Date
f8919af31a Fix SDK autoloader path for Twilio namespace
All checks were successful
Create Release / build (push) Successful in 3s
The SDK files are at twilio/sdk/Twilio/Rest/Client.php but the
autoloader was looking at twilio/sdk/Rest/Client.php. Fixed by
using the full class name in the path instead of stripping the
Twilio\ prefix.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 18:32:19 -08:00
3e4dff5c4e Add SDK persistence and configurable edge location
All checks were successful
Create Release / build (push) Successful in 4s
- Add external SDK installation (wp-content/twilio-sdk/) that survives
  WordPress plugin updates
- Add install-twilio-sdk-external.sh script for external SDK setup
- Update SDK loading to check external location first, internal fallback
- Add post-update detection hook to warn if SDK was deleted
- Add configurable Twilio Edge Location setting (default: roaming)
- Fix US calls failing due to hardcoded Sydney edge location

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 18:17:25 -08:00
8 changed files with 401 additions and 35 deletions

View File

@@ -6,6 +6,7 @@
- **URL**: `https://phone.cloud-hosting.io/` - **URL**: `https://phone.cloud-hosting.io/`
- **Deployment**: rsync to Docker (remote server only, not local) - **Deployment**: rsync to Docker (remote server only, not local)
- **SDK**: Twilio PHP SDK v8.7.0 - **SDK**: Twilio PHP SDK v8.7.0
- **External SDK**: `wp-content/twilio-sdk/` (survives plugin updates)
## Phone Variable Names ## Phone Variable Names
**Use**: `incoming_number`, `agent_number`, `customer_number`, `workflow_number`, `queue_number`, `default_number` **Use**: `incoming_number`, `agent_number`, `customer_number`, `workflow_number`, `queue_number`, `default_number`
@@ -47,6 +48,25 @@ $api->update_call($customer_call_sid, ['twiml' => $twiml_xml]);
- Firefox support added - Firefox support added
- 1-min agent status auto-revert - 1-min agent status auto-revert
## SDK Installation
- **External SDK (Recommended)**: Use `install-twilio-sdk-external.sh` to install SDK to `wp-content/twilio-sdk/`
- Survives WordPress plugin updates
- SDK location defined by `TWP_EXTERNAL_SDK_DIR` constant
- Loading priority: External first, then internal `vendor/` fallback
- **Internal SDK (Alternative)**: Use `install-twilio-sdk.sh` to install to `vendor/`
- Will be deleted when WordPress updates the plugin
- Requires reinstallation after each plugin update
- **SDK Loading**: Plugin checks external location first via autoloader, falls back to internal
- **Post-Update Detection**: Hook on `upgrader_process_complete` checks SDK status and shows warning
## Browser Phone Configuration
- **Edge Location Setting**: Configurable via Settings → Twilio Edge Location
- Default: `roaming` (auto-select closest edge)
- Options: ashburn, umatilla, dublin, frankfurt, singapore, sydney, tokyo, sao-paulo
- Stored in: `twp_twilio_edge` option
- Used by: Browser phone JavaScript for WebRTC connection
- Critical: Wrong edge causes immediate call failures (e.g., US calls with Sydney edge)
## Development Notes ## Development Notes
- **API**: E.164 format (+1XXXXXXXXXX) - **API**: E.164 format (+1XXXXXXXXXX)
- **Database**: Use `$wpdb`, prepared statements - **Database**: Use `$wpdb`, prepared statements
@@ -61,5 +81,28 @@ $api->update_call($customer_call_sid, ['twiml' => $twiml_xml]);
- ElevenLabs TTS with Alice fallback - ElevenLabs TTS with Alice fallback
- 68 AJAX actions, 26 REST endpoints - 68 AJAX actions, 26 REST endpoints
## Recent Technical Changes (v2.8.9)
### SDK Persistence Between Plugin Updates
- **Problem**: WordPress plugin updates delete entire plugin folder including `vendor/` SDK
- **Solution**: External SDK installation at `wp-content/twilio-sdk/` survives updates
- **Implementation**:
- New constant: `TWP_EXTERNAL_SDK_DIR` points to `wp-content/twilio-sdk/`
- Loading priority in `twp_check_sdk_installation()`: External first, internal fallback
- Classes updated: `TWP_Twilio_API`, `TWP_Webhooks` constructors check external location first
- New script: `install-twilio-sdk-external.sh` automates external installation
- Post-update hook: `twp_check_sdk_after_update()` detects missing SDK after updates
- Admin notices: `twp_sdk_missing_notice()` shows both installation options
- Warning system: `twp_show_sdk_update_warning()` via transient after plugin updates
### US Calls Failing Fix (Browser Phone)
- **Problem**: Browser phone had hardcoded `edge: 'sydney'`, causing US calls to fail with immediate HANGUP
- **Solution**: Configurable edge location via WordPress settings
- **Implementation**:
- New setting: `twp_twilio_edge` with default value `roaming`
- Settings UI: Dropdown in admin settings with 8 edge options
- Browser phone JS: Uses `get_option('twp_twilio_edge', 'roaming')` instead of hardcoded value
- Edge options: roaming, ashburn, umatilla, dublin, frankfurt, singapore, sydney, tokyo, sao-paulo
--- ---
*Updated: Sept 2025* *Updated: Jan 2026*

View File

@@ -8,11 +8,20 @@ This plugin **requires** the Twilio PHP SDK v8.7.0 to function. The plugin will
## Quick Installation ## Quick Installation
1. **Install the Twilio SDK** (Required): 1. **Install the Twilio SDK** (Required - Recommended Method):
```bash
chmod +x install-twilio-sdk-external.sh
./install-twilio-sdk-external.sh
```
This installs the SDK to `wp-content/twilio-sdk/` which **survives WordPress plugin updates**. The plugin will automatically detect and use this external SDK.
**Alternative Method** (SDK will be deleted during plugin updates):
```bash ```bash
chmod +x install-twilio-sdk.sh chmod +x install-twilio-sdk.sh
./install-twilio-sdk.sh ./install-twilio-sdk.sh
``` ```
This installs the SDK inside the plugin folder. You'll need to reinstall the SDK after each plugin update.
2. **Test the SDK installation**: 2. **Test the SDK installation**:
```bash ```bash
@@ -23,6 +32,7 @@ This plugin **requires** the Twilio PHP SDK v8.7.0 to function. The plugin will
- Go to **Twilio** → **Settings** - Go to **Twilio** → **Settings**
- Enter Account SID and Auth Token - Enter Account SID and Auth Token
- Configure default phone numbers - Configure default phone numbers
- Set Twilio Edge Location (for browser phone - see Browser Phone Setup below)
4. **Set up Phone Numbers** in Twilio Console: 4. **Set up Phone Numbers** in Twilio Console:
- Configure webhook URLs for voice and SMS - Configure webhook URLs for voice and SMS
@@ -333,8 +343,20 @@ Comprehensive redesign of hold, transfer, and requeue functionality with profess
2. **Configure in WordPress**: 2. **Configure in WordPress**:
- Go to **Twilio** → **Settings** - Go to **Twilio** → **Settings**
- Enter TwiML App SID - Enter TwiML App SID
- **Set Twilio Edge Location**: Select the edge location closest to your users (IMPORTANT)
- **Auto-select closest (Recommended)**: Automatically selects the best edge
- **US East (Ashburn)**: For East Coast USA users
- **US West (Umatilla)**: For West Coast USA users
- **Europe - Ireland (Dublin)**: For European users
- **Europe - Germany (Frankfurt)**: For Central European users
- **Singapore**: For Southeast Asian users
- **Sydney**: For Australian users
- **Tokyo**: For Japanese users
- **Sao Paulo**: For South American users
- Save settings - Save settings
**Note**: Selecting the wrong edge location can cause calls to fail immediately. If you're experiencing browser phone connection issues, verify your edge location is appropriate for your region.
3. **Access Browser Phone** (Admin Only): 3. **Access Browser Phone** (Admin Only):
- Navigate to **WordPress Admin** → **Twilio** → **Browser Phone** - Navigate to **WordPress Admin** → **Twilio** → **Browser Phone**
- Select caller ID from available numbers - Select caller ID from available numbers
@@ -432,14 +454,34 @@ Access the full browser phone interface at: **WordPress Admin → Twilio → Bro
- **Login Required**: Users must be logged in to access browser phone functionality - **Login Required**: Users must be logged in to access browser phone functionality
- Check TwiML App SID is configured in WordPress admin settings - Check TwiML App SID is configured in WordPress admin settings
#### Browser Phone Calls Failing Immediately
If browser phone calls disconnect immediately or show HANGUP errors:
- **Check Edge Location Setting**: Go to **Twilio** → **Settings** → **Twilio Edge Location**
- **US Users**: Should use "Auto-select closest" (roaming), "US East (Ashburn)", or "US West (Umatilla)"
- **International Users**: Select the edge location closest to your region
- **Problem**: Wrong edge location causes gateway to immediately reject calls
- **Solution**: Change edge location setting and try the call again (no restart needed)
#### "Twilio SDK classes not available" #### "Twilio SDK classes not available"
**Recommended Solution** (SDK survives plugin updates):
```bash ```bash
# Reinstall SDK # Install SDK to external location
./install-twilio-sdk-external.sh
# Test installation
php test-sdk.php
```
**Alternative Solution** (will need reinstall after plugin updates):
```bash
# Install SDK inside plugin folder
./install-twilio-sdk.sh ./install-twilio-sdk.sh
# Test installation # Test installation
php test-sdk.php php test-sdk.php
``` ```
**After WordPress Plugin Update**: If you get this error after updating the plugin and used the internal SDK method, you'll need to reinstall the SDK. This won't happen if you use the external SDK method.
#### Calls Not Routing to Queues #### Calls Not Routing to Queues
- Verify queue exists and is active - Verify queue exists and is active
- Check agent group has members - Check agent group has members
@@ -551,7 +593,19 @@ All webhooks are REST API endpoints under `/wp-json/twilio-webhook/v1/`:
## Version History ## Version History
### v2.3.0 (Current - September 2025) - ENTERPRISE READY ### v2.8.9 (Current - January 2026) - SDK PERSISTENCE & BROWSER PHONE FIXES
- **SDK PERSISTENCE**: External SDK installation option that survives WordPress plugin updates
- New installation script: `install-twilio-sdk-external.sh` installs SDK to `wp-content/twilio-sdk/`
- Automatic detection: Plugin checks external SDK location first, falls back to internal
- Post-update warnings: Notifies if SDK was deleted during plugin update
- Zero downtime: Phone system continues working through plugin updates
- **BROWSER PHONE FIX**: Resolved US calls failing immediately with HANGUP errors
- Made Twilio Edge Location configurable (was hardcoded to Sydney)
- New setting: Twilio Edge Location with 8 options (roaming/auto-select, ashburn, umatilla, dublin, frankfurt, singapore, sydney, tokyo, sao-paulo)
- Default: "roaming" (auto-select closest edge for optimal performance)
- Critical fix: US users can now make calls successfully (were failing with Sydney edge)
### v2.3.0 (September 2025) - ENTERPRISE READY
- **SECURITY ENHANCEMENT**: Removed frontend browser phone interface, moved to admin-only access for enhanced security - **SECURITY ENHANCEMENT**: Removed frontend browser phone interface, moved to admin-only access for enhanced security
- **ASSET REDUCTION**: Eliminated 108KB of frontend assets (browser-phone-frontend.js and CSS files) - **ASSET REDUCTION**: Eliminated 108KB of frontend assets (browser-phone-frontend.js and CSS files)
- **SHORTCODE SECURITY**: Browser phone shortcode now provides secure redirect with authentication checks - **SHORTCODE SECURITY**: Browser phone shortcode now provides secure redirect with authentication checks
@@ -611,4 +665,4 @@ This plugin integrates with Twilio services and requires a Twilio account.
--- ---
**Enterprise Ready v2.3.0** - Extension transfers, browser phone compatibility, and automatic agent management now production-ready with comprehensive reliability improvements. **Production Ready v2.8.9** - SDK persistence through plugin updates and configurable edge locations ensure zero-downtime phone operations.

View File

@@ -347,6 +347,25 @@ class TWP_Admin {
</td> </td>
</tr> </tr>
<tr>
<th scope="row">Twilio Edge Location</th>
<td>
<?php $current_edge = get_option('twp_twilio_edge', 'roaming'); ?>
<select name="twp_twilio_edge" class="regular-text">
<option value="roaming" <?php selected($current_edge, 'roaming'); ?>>Auto-select closest (Recommended)</option>
<option value="ashburn" <?php selected($current_edge, 'ashburn'); ?>>US East (Ashburn)</option>
<option value="umatilla" <?php selected($current_edge, 'umatilla'); ?>>US West (Umatilla)</option>
<option value="dublin" <?php selected($current_edge, 'dublin'); ?>>Europe - Ireland (Dublin)</option>
<option value="frankfurt" <?php selected($current_edge, 'frankfurt'); ?>>Europe - Germany (Frankfurt)</option>
<option value="singapore" <?php selected($current_edge, 'singapore'); ?>>Asia Pacific (Singapore)</option>
<option value="sydney" <?php selected($current_edge, 'sydney'); ?>>Australia (Sydney)</option>
<option value="tokyo" <?php selected($current_edge, 'tokyo'); ?>>Japan (Tokyo)</option>
<option value="sao-paulo" <?php selected($current_edge, 'sao-paulo'); ?>>South America (Sao Paulo)</option>
</select>
<p class="description">Edge location for browser phone calls. Use "Auto-select closest" for best call quality, or select a specific region.</p>
</td>
</tr>
</table> </table>
<h2>Eleven Labs API Settings</h2> <h2>Eleven Labs API Settings</h2>
@@ -3818,6 +3837,7 @@ class TWP_Admin {
register_setting('twilio-wp-settings-group', 'twp_twilio_account_sid'); register_setting('twilio-wp-settings-group', 'twp_twilio_account_sid');
register_setting('twilio-wp-settings-group', 'twp_twilio_auth_token'); register_setting('twilio-wp-settings-group', 'twp_twilio_auth_token');
register_setting('twilio-wp-settings-group', 'twp_twiml_app_sid'); register_setting('twilio-wp-settings-group', 'twp_twiml_app_sid');
register_setting('twilio-wp-settings-group', 'twp_twilio_edge');
register_setting('twilio-wp-settings-group', 'twp_elevenlabs_api_key'); register_setting('twilio-wp-settings-group', 'twp_elevenlabs_api_key');
register_setting('twilio-wp-settings-group', 'twp_elevenlabs_voice_id'); register_setting('twilio-wp-settings-group', 'twp_elevenlabs_voice_id');
register_setting('twilio-wp-settings-group', 'twp_elevenlabs_model_id'); register_setting('twilio-wp-settings-group', 'twp_elevenlabs_model_id');
@@ -7779,7 +7799,7 @@ class TWP_Admin {
device = new Twilio.Device(token, { device = new Twilio.Device(token, {
logLevel: 1, // 0 = TRACE, 1 = DEBUG logLevel: 1, // 0 = TRACE, 1 = DEBUG
codecPreferences: ['opus', 'pcmu'], codecPreferences: ['opus', 'pcmu'],
edge: 'sydney', // Or closest edge location edge: '<?php echo esc_js(get_option('twp_twilio_edge', 'roaming')); ?>',
enableIceRestart: true, // Important for mobile network switching enableIceRestart: true, // Important for mobile network switching
audioConstraints: audioConstraints, audioConstraints: audioConstraints,
maxCallSignalingTimeoutMs: 30000, // 30 seconds timeout for mobile maxCallSignalingTimeoutMs: 30000, // 30 seconds timeout for mobile

View File

@@ -41,11 +41,26 @@ class TWP_Twilio_API {
* Initialize Twilio SDK client * Initialize Twilio SDK client
*/ */
private function init_sdk_client() { private function init_sdk_client() {
// Check if autoloader exists // Check for SDK autoloader - external location first (survives plugin updates)
$autoloader_path = TWP_PLUGIN_DIR . 'vendor/autoload.php'; $autoloader_path = null;
if (!file_exists($autoloader_path)) {
error_log('TWP Plugin: Autoloader not found at: ' . $autoloader_path); // Priority 1: External SDK location (recommended)
throw new Exception('Twilio SDK not found. Please run: ./install-twilio-sdk.sh'); $external_autoloader = TWP_EXTERNAL_SDK_DIR . 'autoload.php';
if (file_exists($external_autoloader)) {
$autoloader_path = $external_autoloader;
}
// Priority 2: Internal vendor directory (fallback)
if (!$autoloader_path) {
$internal_autoloader = TWP_PLUGIN_DIR . 'vendor/autoload.php';
if (file_exists($internal_autoloader)) {
$autoloader_path = $internal_autoloader;
}
}
if (!$autoloader_path) {
error_log('TWP Plugin: Autoloader not found. Checked: ' . $external_autoloader . ' and ' . TWP_PLUGIN_DIR . 'vendor/autoload.php');
throw new Exception('Twilio SDK not found. Please run: ./install-twilio-sdk-external.sh');
} }
// Load the autoloader // Load the autoloader

View File

@@ -9,9 +9,25 @@ class TWP_Webhooks {
*/ */
public function __construct() { public function __construct() {
// Load Twilio SDK if not already loaded // Load Twilio SDK if not already loaded
// Check external location first (survives plugin updates), then internal
if (!class_exists('\Twilio\Rest\Client')) { if (!class_exists('\Twilio\Rest\Client')) {
$autoloader_path = plugin_dir_path(dirname(__FILE__)) . 'vendor/autoload.php'; $autoloader_path = null;
if (file_exists($autoloader_path)) {
// Priority 1: External SDK location
$external_autoloader = dirname(dirname(plugin_dir_path(dirname(__FILE__)))) . '/twilio-sdk/autoload.php';
if (file_exists($external_autoloader)) {
$autoloader_path = $external_autoloader;
}
// Priority 2: Internal vendor directory
if (!$autoloader_path) {
$internal_autoloader = plugin_dir_path(dirname(__FILE__)) . 'vendor/autoload.php';
if (file_exists($internal_autoloader)) {
$autoloader_path = $internal_autoloader;
}
}
if ($autoloader_path) {
require_once $autoloader_path; require_once $autoloader_path;
} }
} }

158
install-twilio-sdk-external.sh Executable file
View File

@@ -0,0 +1,158 @@
#!/bin/bash
# Script to install Twilio PHP SDK to an external location
# This prevents SDK from being deleted when WordPress updates the plugin
#
# Location: wp-content/twilio-sdk/ (outside plugin folder)
echo "Installing Twilio PHP SDK v8.7.0 to external location..."
echo "This will install the SDK outside the plugin folder to survive plugin updates."
# Check if we can download files
if ! command -v curl &> /dev/null; then
echo "ERROR: curl is required to download the SDK"
echo "Please install curl and try again"
exit 1
fi
if ! command -v tar &> /dev/null; then
echo "ERROR: tar is required to extract the SDK"
echo "Please install tar and try again"
exit 1
fi
# Get the script directory (plugin directory)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Calculate wp-content directory (two levels up from plugin)
# Plugin is at: wp-content/plugins/twilio-wp-plugin/
# We want: wp-content/twilio-sdk/
WP_CONTENT_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
SDK_DIR="$WP_CONTENT_DIR/twilio-sdk"
echo "Plugin directory: $SCRIPT_DIR"
echo "SDK will be installed to: $SDK_DIR"
# Create SDK directory
mkdir -p "$SDK_DIR/twilio/sdk"
# Download the latest release (8.7.0)
echo "Downloading Twilio SDK from GitHub..."
TEMP_DIR=$(mktemp -d)
cd "$TEMP_DIR"
if ! curl -L https://github.com/twilio/twilio-php/archive/refs/tags/8.7.0.tar.gz -o twilio-sdk.tar.gz; then
echo "ERROR: Failed to download Twilio SDK"
echo "Please check your internet connection and try again"
rm -rf "$TEMP_DIR"
exit 1
fi
# Extract the archive
echo "Extracting SDK files..."
if ! tar -xzf twilio-sdk.tar.gz; then
echo "ERROR: Failed to extract SDK files"
rm -rf "$TEMP_DIR"
exit 1
fi
# Check if the extracted directory exists
if [ ! -d "twilio-php-8.7.0/src" ]; then
echo "ERROR: Extracted SDK directory structure is unexpected"
rm -rf "$TEMP_DIR"
exit 1
fi
# Remove existing SDK if it exists
if [ -d "$SDK_DIR/twilio/sdk" ]; then
echo "Removing existing SDK installation..."
rm -rf "$SDK_DIR/twilio/sdk"
mkdir -p "$SDK_DIR/twilio/sdk"
fi
# Move the entire src directory to be the sdk
echo "Installing SDK files..."
if ! mv twilio-php-8.7.0/src/* "$SDK_DIR/twilio/sdk/"; then
echo "ERROR: Failed to move SDK files"
rm -rf "$TEMP_DIR"
exit 1
fi
# Create a comprehensive autoloader
cat > "$SDK_DIR/autoload.php" << 'EOF'
<?php
/**
* Twilio SDK v8.7.0 Autoloader (External Installation)
* This file loads the Twilio PHP SDK classes
*
* Location: wp-content/twilio-sdk/autoload.php
* This location survives WordPress plugin updates
*/
// Prevent multiple registrations
if (!defined('TWILIO_AUTOLOADER_REGISTERED')) {
define('TWILIO_AUTOLOADER_REGISTERED', true);
// Register the autoloader
spl_autoload_register(function ($class) {
// Only handle Twilio classes
if (strpos($class, 'Twilio\\') !== 0) {
return false;
}
// Convert class name to file path
// The SDK structure is: twilio/sdk/Twilio/Rest/Client.php for Twilio\Rest\Client
$file = __DIR__ . '/twilio/sdk/' . str_replace('\\', '/', $class) . '.php';
if (file_exists($file)) {
require_once $file;
return true;
}
return false;
});
// Try to load the SDK's own autoloader if it exists
$sdk_autoloader = __DIR__ . '/twilio/sdk/autoload.php';
if (file_exists($sdk_autoloader)) {
require_once $sdk_autoloader;
}
// Load essential Twilio classes manually to ensure they're available
$essential_classes = [
__DIR__ . '/twilio/sdk/Twilio/Rest/Client.php',
__DIR__ . '/twilio/sdk/Twilio/TwiML/VoiceResponse.php',
__DIR__ . '/twilio/sdk/Twilio/Exceptions/TwilioException.php',
__DIR__ . '/twilio/sdk/Twilio/Security/RequestValidator.php'
];
foreach ($essential_classes as $class_file) {
if (file_exists($class_file)) {
require_once $class_file;
}
}
}
EOF
# Clean up temp directory
cd "$SCRIPT_DIR"
rm -rf "$TEMP_DIR"
# Verify installation
echo ""
echo "Verifying installation..."
if [ -f "$SDK_DIR/autoload.php" ] && [ -d "$SDK_DIR/twilio/sdk" ]; then
echo "=============================================="
echo "Twilio SDK v8.7.0 installed successfully!"
echo "=============================================="
echo ""
echo "Installation location: $SDK_DIR"
echo ""
echo "This SDK is installed OUTSIDE the plugin folder,"
echo "so it will NOT be deleted when WordPress updates the plugin."
echo ""
echo "The plugin will automatically detect this external SDK."
else
echo "Installation failed - files not found"
exit 1
fi

View File

@@ -79,8 +79,8 @@ if (!defined('TWILIO_AUTOLOADER_REGISTERED')) {
} }
// Convert class name to file path // Convert class name to file path
$relative_class = substr($class, 7); // Remove 'Twilio\' // The SDK structure is: twilio/sdk/Twilio/Rest/Client.php for Twilio\Rest\Client
$file = __DIR__ . '/twilio/sdk/' . str_replace('\\', '/', $relative_class) . '.php'; $file = __DIR__ . '/twilio/sdk/' . str_replace('\\', '/', $class) . '.php';
if (file_exists($file)) { if (file_exists($file)) {
require_once $file; require_once $file;
@@ -98,10 +98,10 @@ if (!defined('TWILIO_AUTOLOADER_REGISTERED')) {
// Load essential Twilio classes manually to ensure they're available // Load essential Twilio classes manually to ensure they're available
$essential_classes = [ $essential_classes = [
__DIR__ . '/twilio/sdk/Rest/Client.php', __DIR__ . '/twilio/sdk/Twilio/Rest/Client.php',
__DIR__ . '/twilio/sdk/TwiML/VoiceResponse.php', __DIR__ . '/twilio/sdk/Twilio/TwiML/VoiceResponse.php',
__DIR__ . '/twilio/sdk/Exceptions/TwilioException.php', __DIR__ . '/twilio/sdk/Twilio/Exceptions/TwilioException.php',
__DIR__ . '/twilio/sdk/Security/RequestValidator.php' __DIR__ . '/twilio/sdk/Twilio/Security/RequestValidator.php'
]; ];
foreach ($essential_classes as $class_file) { foreach ($essential_classes as $class_file) {

View File

@@ -20,6 +20,8 @@ define('TWP_DB_VERSION', '1.6.2'); // Track database version separately
define('TWP_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('TWP_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('TWP_PLUGIN_URL', plugin_dir_url(__FILE__)); define('TWP_PLUGIN_URL', plugin_dir_url(__FILE__));
define('TWP_PLUGIN_BASENAME', plugin_basename(__FILE__)); define('TWP_PLUGIN_BASENAME', plugin_basename(__FILE__));
// External SDK location - survives plugin updates (wp-content/twilio-sdk/)
define('TWP_EXTERNAL_SDK_DIR', dirname(dirname(TWP_PLUGIN_DIR)) . '/twilio-sdk/');
/** /**
* Plugin activation hook * Plugin activation hook
@@ -31,17 +33,27 @@ function twp_activate() {
/** /**
* Check if Twilio SDK is installed and show admin notice if not * Check if Twilio SDK is installed and show admin notice if not
* Checks external location first (survives plugin updates), then internal fallback
*/ */
function twp_check_sdk_installation() { function twp_check_sdk_installation() {
$autoloader_path = TWP_PLUGIN_DIR . 'vendor/autoload.php';
$sdk_installed = false; $sdk_installed = false;
if (file_exists($autoloader_path)) { // Priority 1: Check external SDK location (survives plugin updates)
// Try to load autoloader and check for classes $external_autoloader = TWP_EXTERNAL_SDK_DIR . 'autoload.php';
require_once $autoloader_path; if (file_exists($external_autoloader)) {
require_once $external_autoloader;
$sdk_installed = class_exists('Twilio\Rest\Client'); $sdk_installed = class_exists('Twilio\Rest\Client');
} }
// Priority 2: Fall back to internal vendor directory
if (!$sdk_installed) {
$internal_autoloader = TWP_PLUGIN_DIR . 'vendor/autoload.php';
if (file_exists($internal_autoloader)) {
require_once $internal_autoloader;
$sdk_installed = class_exists('Twilio\Rest\Client');
}
}
if (!$sdk_installed) { if (!$sdk_installed) {
add_action('admin_notices', 'twp_sdk_missing_notice'); add_action('admin_notices', 'twp_sdk_missing_notice');
} }
@@ -55,10 +67,12 @@ function twp_sdk_missing_notice() {
<div class="notice notice-error is-dismissible"> <div class="notice notice-error is-dismissible">
<h3>Twilio WordPress Plugin - SDK Required</h3> <h3>Twilio WordPress Plugin - SDK Required</h3>
<p><strong>The Twilio PHP SDK is required for this plugin to work.</strong></p> <p><strong>The Twilio PHP SDK is required for this plugin to work.</strong></p>
<p>To install the SDK, run this command in your plugin directory:</p> <p><strong>Recommended:</strong> Install SDK to external location (survives plugin updates):</p>
<code>chmod +x install-twilio-sdk-external.sh && ./install-twilio-sdk-external.sh</code>
<p style="margin-top: 10px;"><strong>Alternative:</strong> Install SDK inside plugin folder:</p>
<code>chmod +x install-twilio-sdk.sh && ./install-twilio-sdk.sh</code> <code>chmod +x install-twilio-sdk.sh && ./install-twilio-sdk.sh</code>
<p>Or install via Composer: <code>composer install</code></p> <p style="margin-top: 10px;"><em>Plugin path: <?php echo esc_html(TWP_PLUGIN_DIR); ?></em></p>
<p><em>Plugin path: <?php echo TWP_PLUGIN_DIR; ?></em></p> <p><em>External SDK path: <?php echo esc_html(TWP_EXTERNAL_SDK_DIR); ?></em></p>
</div> </div>
<?php <?php
} }
@@ -126,6 +140,52 @@ function twp_deactivate() {
register_activation_hook(__FILE__, 'twp_activate'); register_activation_hook(__FILE__, 'twp_activate');
register_deactivation_hook(__FILE__, 'twp_deactivate'); register_deactivation_hook(__FILE__, 'twp_deactivate');
/**
* Check SDK status after plugin updates
* Shows warning if SDK was deleted during update and external SDK not available
*/
function twp_check_sdk_after_update($upgrader_object, $options) {
// Only run for plugin updates
if ($options['action'] !== 'update' || $options['type'] !== 'plugin') {
return;
}
// Check if this plugin was updated
$updated_plugins = isset($options['plugins']) ? $options['plugins'] : array();
if (!in_array(TWP_PLUGIN_BASENAME, $updated_plugins)) {
return;
}
// Check if SDK is available
$external_sdk = file_exists(TWP_EXTERNAL_SDK_DIR . 'autoload.php');
$internal_sdk = file_exists(TWP_PLUGIN_DIR . 'vendor/autoload.php');
if (!$external_sdk && !$internal_sdk) {
// Set a transient to show warning on next admin page load
set_transient('twp_sdk_update_warning', true, 60 * 5);
}
}
add_action('upgrader_process_complete', 'twp_check_sdk_after_update', 10, 2);
/**
* Show SDK update warning
*/
function twp_show_sdk_update_warning() {
if (get_transient('twp_sdk_update_warning')) {
delete_transient('twp_sdk_update_warning');
?>
<div class="notice notice-warning is-dismissible">
<h3>Twilio WordPress Plugin - SDK Reinstall Required</h3>
<p><strong>The plugin was updated and the Twilio SDK needs to be reinstalled.</strong></p>
<p>To prevent this in the future, install the SDK to the external location:</p>
<code>cd <?php echo esc_html(TWP_PLUGIN_DIR); ?> && ./install-twilio-sdk-external.sh</code>
<p style="margin-top: 10px;">The external SDK at <code><?php echo esc_html(TWP_EXTERNAL_SDK_DIR); ?></code> survives plugin updates.</p>
</div>
<?php
}
}
add_action('admin_notices', 'twp_show_sdk_update_warning');
/** /**
* Core plugin class * Core plugin class
*/ */