2025-09-18 18:29:20 -07:00
# Twilio WordPress Plugin - Quick Reference
## Environment
- **Production**: `/home/shadowdao/public_html/wp-content/plugins/twilio-wp-plugin/`
- **Dev**: `/home/jknapp/code/twilio-wp-plugin/`
- **URL**: `https://phone.cloud-hosting.io/`
- **Deployment**: rsync to Docker (remote server only, not local)
- **SDK**: Twilio PHP SDK v8.7.0
2026-03-06 14:43:21 -08:00
- **PHP**: 8.0+ required
- **Optional**: AWS SDK (`aws/aws-sdk-php` ) for SNS SMS provider
2026-01-23 18:03:38 -08:00
- **External SDK**: `wp-content/twilio-sdk/` (survives plugin updates)
2025-09-18 18:29:20 -07:00
2026-03-06 14:43:21 -08:00
## Commands
- **Install SDK (recommended)**: `./install-twilio-sdk-external.sh` (installs to `wp-content/twilio-sdk/` )
- **Install SDK (internal)**: `./install-twilio-sdk.sh` (installs to `vendor/` , lost on plugin update)
- **Test SDK**: `php test-sdk.php`
- **Composer install SDK**: `composer install-sdk`
- **Deploy**: rsync to Docker (remote server, see production path above)
- **CI/CD**: Gitea workflows in `.gitea/workflows/` — `release.yml` , `update-version.yml`
## Directory Structure
- `twilio-wp-plugin.php` — Main plugin file, constants, SDK loading
- `includes/` — All backend classes (28 class files)
- `admin/` — Admin UI class (`TWP_Admin` ), mobile app settings page
- `assets/js/` — Browser phone JS, service worker
- `assets/images/` , `assets/sounds/` — Static assets
- `.gitea/workflows/` — CI/CD (release, version update)
2025-09-18 18:29:20 -07:00
## Phone Variable Names
**Use**: `incoming_number` , `agent_number` , `customer_number` , `workflow_number` , `queue_number` , `default_number`
**Don't use**: `from_number` , `to_number` , `phone_number` , `$agent_phone`
**Test numbers**: Twilio `+19516215107` , Agent `+19095737372`
## Key Classes
- **TWP_Twilio_API**: Use `new TWP_Twilio_API()` not singleton
- **TWP_Admin**: Has `find_customer_call_leg()` - CRITICAL for call control
- **TWP_TTS_Helper**: ElevenLabs/Alice fallback, 30-day cache
- **TWP_User_Queue_Manager**: Auto-creates queues/extensions (100-9999)
2026-03-06 14:43:21 -08:00
- **TWP_Webhooks**: 35 endpoints at `twilio-webhook/v1`
- **TWP_Activator**: Creates 16 DB tables, run `ensure_tables_exist()` if missing
- **TWP_Core**: Main plugin orchestrator, hooks all classes together
- **TWP_SMS_Manager**: SMS abstraction with provider interface
- **TWP_SMS_Provider_Twilio** / **TWP_SMS_Provider_SNS ** : SMS providers (Twilio default, AWS SNS optional)
- **TWP_Mobile_API**: REST API for mobile app
- **TWP_Mobile_Auth** / **TWP_Mobile_SSE ** / **TWP_FCM ** : Mobile auth, server-sent events, push notifications
- **TWP_Call_Queue**: Queue operations and management
- **TWP_Callback_Manager**: Callback request handling
- **TWP_Workflow**: Workflow step execution engine
- **TWP_Auto_Updater**: Plugin auto-update from Gitea releases
2025-09-18 18:29:20 -07:00
## Database
2026-03-06 14:43:21 -08:00
16 tables with `twp_` prefix. Key notes:
2025-09-18 18:29:20 -07:00
- `twp_call_queues` : User queues (general/personal/hold)
- `twp_agent_status` : Has `auto_busy_at` for 1-min auto-revert
- `twp_queued_calls` : Uses `enqueued_at` not `joined_at`
## Critical Functions
### Call Control (MUST use call leg detection)
2025-09-01 09:34:07 -07:00
```php
2025-09-18 18:29:20 -07:00
// ALWAYS do this for hold/transfer/requeue:
2025-09-01 09:34:07 -07:00
$customer_call_sid = $this->find_customer_call_leg($call_sid, $twilio);
2025-09-18 18:29:20 -07:00
$api->update_call($customer_call_sid, ['twiml' => $twiml_xml]);
2025-09-01 09:34:07 -07:00
```
2025-08-06 15:25:47 -07:00
2025-09-18 18:29:20 -07:00
### Common Fixes
- Recording: Use `Twilio.CURRENT` for SDK v8
- Queue: Pass `waitUrl` as option in `enqueue()`
- TwiML: Use SDK classes, not raw XML
## Development Notes
- **API**: E.164 format (+1XXXXXXXXXX)
- **Database**: Use `$wpdb` , prepared statements
- **AJAX**: Verify nonce, return JSON
- **Naming**: TWP_ for classes, twp_ for tables/options
- **Debugging**: Look for "TWP Call Leg Detection" in logs
## Features
- Agents accept calls via SMS "1"
- User-specific queues with extensions
- Browser phone at `admin.php?page=twilio-wp-browser-phone`
- ElevenLabs TTS with Alice fallback
2026-03-06 14:43:21 -08:00
- 77 AJAX actions, 35 REST endpoints
- Browser phone moved to admin-only (v2.3.0)
- Firefox, Chrome, Safari, Edge support
- 1-min agent status auto-revert
2025-09-01 09:34:07 -07:00
2026-03-06 14:43:21 -08:00
## SDK Loading
- **External SDK (Recommended)**: `wp-content/twilio-sdk/` — survives plugin updates
- **Internal SDK**: `vendor/` — deleted on plugin update, needs reinstall
- Loading priority: External first (`TWP_EXTERNAL_SDK_DIR` ), then internal fallback
- Post-update hook (`upgrader_process_complete` ) warns if SDK missing
2026-01-23 18:03:38 -08:00
2026-03-06 14:43:21 -08:00
## Browser Phone Configuration
- **Edge Location**: `twp_twilio_edge` option, default `roaming`
- Options: roaming, ashburn, umatilla, dublin, frankfurt, singapore, sydney, tokyo, sao-paulo
- Wrong edge causes immediate call failures (e.g., US calls with Sydney edge)
2026-01-23 18:03:38 -08:00
2026-03-07 17:11:02 -08:00
## Mobile App SSE (Server-Sent Events)
The mobile app uses SSE for real-time updates (queue changes, agent status). If SSE doesn't work (green dot stays red), the app automatically falls back to 5-second polling.
### Apache + PHP-FPM Buffering Fix
`mod_proxy_fcgi` buffers PHP output by default, which breaks SSE streaming. Fix by adding a config file on the server:
```bash
echo 'ProxyPassMatch "^/wp-json/twilio-mobile/v1/stream/events$" "unix:/run/php-fpm/www.sock|fcgi://localhost/home/shadowdao/public_html/index.php" flushpackets=on' > /etc/httpd/conf.d/twp-sse.conf
httpd -t && systemctl restart httpd
```
- **`flushpackets=on` ** is the key — tells Apache to flush PHP-FPM output immediately
- This is a `ProxyPassMatch` directive — **cannot ** go in `.htaccess` , must be server config
- The PHP-FPM socket path (`/run/php-fpm/www.sock` ) must match `/etc/httpd/conf.d/php.conf`
- If the server uses nginx instead of Apache, add `X-Accel-Buffering: no` header (already in PHP code)
- If behind HAProxy with HTTP/2, the issue is Apache→client buffering, not HTTP/2 framing
### Diagnosis
```bash
# Check PHP-FPM proxy config
grep -r "fcgi\|php-fpm" /etc/httpd/conf.d/
# Check if flushpackets is configured
grep -r "flushpackets" /etc/httpd/conf.d/
# Test SSE endpoint (should stream data, not hang)
curl -N -H "Authorization: Bearer TOKEN" https://phone.cloud-hosting.io/wp-json/twilio-mobile/v1/stream/events
```
2026-03-06 14:43:21 -08:00
## Changelog
See `README.md` for detailed version history. Current version: v2.8.9.
2026-01-23 18:03:38 -08:00
2025-09-01 09:34:07 -07:00
---
2026-03-06 14:43:21 -08:00
*Updated: Mar 2026*