Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80167ed6eb | ||
|
|
4737101254 | ||
|
|
d5a09fb337 | ||
|
|
fd14a9d6ba | ||
|
|
a2f450bb19 | ||
|
|
2b61bb11d8 | ||
|
|
ee8e111970 | ||
|
|
bc091dd69d | ||
|
|
8b032fb96f | ||
|
|
3407f4c705 | ||
|
|
fe8ddd51bb |
@@ -16,6 +16,24 @@ jobs:
|
||||
password: ${{ secrets.CI_TOKEN }}
|
||||
fetch-depth: 0 # Important: Fetch all history for commit messages
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.1'
|
||||
tools: composer
|
||||
|
||||
- name: Generate composer.lock if missing
|
||||
run: |
|
||||
if [ ! -f composer.lock ]; then
|
||||
echo "No composer.lock present — resolving dependencies."
|
||||
composer update --no-dev --no-install --no-interaction --prefer-dist
|
||||
else
|
||||
echo "Using committed composer.lock."
|
||||
fi
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction
|
||||
|
||||
- name: Get version
|
||||
id: get_version
|
||||
run: |
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
- **URL**: `https://phone.cloud-hosting.io/`
|
||||
- **Deployment**: rsync to Docker (remote server only, not local)
|
||||
- **SDK**: Twilio PHP SDK v8.7.0
|
||||
- **PHP**: 8.0+ required
|
||||
- **PHP**: 8.1+ required (AWS SDK v3.371+ requires PHP 8.1; production runs 8.5)
|
||||
- **Optional**: AWS SDK (`aws/aws-sdk-php`) for SNS SMS provider
|
||||
- **External SDK**: `wp-content/twilio-sdk/` (survives plugin updates)
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ This plugin **requires** the Twilio PHP SDK v8.7.0 to function. The plugin will
|
||||
|
||||
## Requirements
|
||||
|
||||
- **PHP 8.0+** (required for Twilio SDK v8.7.0)
|
||||
- **PHP 8.1+** (required by AWS SDK for SNS provider; Twilio SDK works on 8.0+)
|
||||
- **WordPress 5.0+**
|
||||
- **Twilio Account** with active phone number
|
||||
- **curl** and **tar** (for SDK installation)
|
||||
|
||||
+74
-1
@@ -110,6 +110,8 @@ var twpTwilioEdge = window.twpConfig.twilioEdge;
|
||||
var serviceWorkerRegistration = null;
|
||||
var currentCallDirection = null;
|
||||
var callHistory = [];
|
||||
var wakeLock = null;
|
||||
var deviceKeepaliveTimer = null;
|
||||
|
||||
// ============================================================
|
||||
// AudioContext & Ringtone
|
||||
@@ -193,13 +195,79 @@ var twpTwilioEdge = window.twpConfig.twilioEdge;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Screen Wake Lock
|
||||
// ============================================================
|
||||
async function requestWakeLock() {
|
||||
if (!('wakeLock' in navigator)) return;
|
||||
try {
|
||||
wakeLock = await navigator.wakeLock.request('screen');
|
||||
console.log('TWP: Wake lock acquired');
|
||||
wakeLock.addEventListener('release', function() {
|
||||
console.log('TWP: Wake lock released');
|
||||
wakeLock = null;
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn('TWP: Wake lock request failed:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
function releaseWakeLock() {
|
||||
if (wakeLock) {
|
||||
wakeLock.release().catch(function() {});
|
||||
wakeLock = null;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Device Keepalive Monitor
|
||||
// ============================================================
|
||||
function startDeviceKeepalive() {
|
||||
stopDeviceKeepalive();
|
||||
deviceKeepaliveTimer = setInterval(function() {
|
||||
if (device && deviceConnectionState !== 'connected' && !currentCall) {
|
||||
console.log('TWP: Keepalive — device disconnected, re-registering');
|
||||
device.register().catch(function(e) {
|
||||
console.warn('TWP: Keepalive re-register failed:', e.message);
|
||||
});
|
||||
}
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
function stopDeviceKeepalive() {
|
||||
if (deviceKeepaliveTimer) {
|
||||
clearInterval(deviceKeepaliveTimer);
|
||||
deviceKeepaliveTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Page Visibility
|
||||
// ============================================================
|
||||
function setupPageVisibility() {
|
||||
document.addEventListener('visibilitychange', function() {
|
||||
isPageVisible = !document.hidden;
|
||||
if (isPageVisible && audioContext) initializeAudioContext();
|
||||
if (isPageVisible) {
|
||||
console.log('TWP: Page visible — checking connections');
|
||||
// Resume audio
|
||||
if (audioContext) initializeAudioContext();
|
||||
// Re-request wake lock (auto-released when tab hidden)
|
||||
requestWakeLock();
|
||||
// Check token expiry — refresh if expired or within 2 minutes
|
||||
if (tokenExpiry && (Date.now() > tokenExpiry - 2 * 60 * 1000)) {
|
||||
console.log('TWP: Token expired or expiring soon, refreshing');
|
||||
refreshToken();
|
||||
}
|
||||
// Check device registration
|
||||
if (device && deviceConnectionState !== 'connected' && !currentCall) {
|
||||
console.log('TWP: Device disconnected, re-registering');
|
||||
device.register().catch(function(e) {
|
||||
console.warn('TWP: Visibility re-register failed:', e.message);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log('TWP: Page hidden — wake lock auto-released by browser');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -352,6 +420,8 @@ var twpTwilioEdge = window.twpConfig.twilioEdge;
|
||||
device.on('tokenWillExpire', function() { refreshToken(); });
|
||||
|
||||
await device.register();
|
||||
requestWakeLock();
|
||||
startDeviceKeepalive();
|
||||
} catch (error) {
|
||||
showError('Failed to setup device: ' + error.message);
|
||||
}
|
||||
@@ -363,6 +433,7 @@ var twpTwilioEdge = window.twpConfig.twilioEdge;
|
||||
function setupCallHandlers(call) {
|
||||
call.on('accept', function() {
|
||||
stopRingtone();
|
||||
requestWakeLock();
|
||||
$('#phone-status').text('Connected').css('color', 'var(--accent)');
|
||||
$('#call-btn').hide();
|
||||
$('#answer-btn').hide();
|
||||
@@ -1041,6 +1112,8 @@ var twpTwilioEdge = window.twpConfig.twilioEdge;
|
||||
// ============================================================
|
||||
$(window).on('beforeunload', function() {
|
||||
if (tokenRefreshTimer) clearTimeout(tokenRefreshTimer);
|
||||
releaseWakeLock();
|
||||
stopDeviceKeepalive();
|
||||
if (device) device.destroy();
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
"description": "WordPress plugin for Twilio voice and SMS integration - REQUIRES Twilio SDK",
|
||||
"type": "wordpress-plugin",
|
||||
"require": {
|
||||
"php": ">=8.0",
|
||||
"php": ">=8.1",
|
||||
"twilio/sdk": "^8.7",
|
||||
"aws/aws-sdk-php": "^3.0"
|
||||
},
|
||||
@@ -19,7 +19,7 @@
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"platform": {
|
||||
"php": "8.0"
|
||||
"php": "8.1"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -177,7 +177,6 @@ class TWP_Auto_Updater {
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if (!$response || $http_code !== 200) {
|
||||
error_log("TWP Auto-Updater: Gitea API returned status $http_code");
|
||||
|
||||
@@ -30,6 +30,11 @@ class TWP_Core {
|
||||
// Loader class
|
||||
require_once TWP_PLUGIN_DIR . 'includes/class-twp-loader.php';
|
||||
|
||||
// Activator (defines TWP_Activator). Loaded here so runtime callers in
|
||||
// webhook/REST/cron contexts can use ::ensure_tables_exist() and
|
||||
// ::force_table_updates() without each site needing its own require_once.
|
||||
require_once TWP_PLUGIN_DIR . 'includes/class-twp-activator.php';
|
||||
|
||||
// API classes
|
||||
require_once TWP_PLUGIN_DIR . 'includes/class-twp-twilio-api.php';
|
||||
require_once TWP_PLUGIN_DIR . 'includes/class-twp-elevenlabs-api.php';
|
||||
|
||||
@@ -119,7 +119,6 @@ class TWP_FCM {
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($http_code !== 200) {
|
||||
error_log("TWP FCM: Failed to send notification. HTTP $http_code: $response");
|
||||
@@ -173,7 +172,6 @@ class TWP_FCM {
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($http_code !== 200) {
|
||||
error_log("TWP FCM: Failed to get access token. HTTP $http_code: $response");
|
||||
|
||||
@@ -39,28 +39,31 @@ class TWP_Twilio_API {
|
||||
|
||||
/**
|
||||
* Initialize Twilio SDK client
|
||||
*
|
||||
* Loader priority:
|
||||
* 1. Internal bundled vendor/autoload.php (shipped with release zip — primary)
|
||||
* 2. External wp-content/twilio-sdk/autoload.php (legacy/manual install fallback)
|
||||
*/
|
||||
private function init_sdk_client() {
|
||||
// Check for SDK autoloader - external location first (survives plugin updates)
|
||||
$autoloader_path = null;
|
||||
|
||||
// Priority 1: External SDK location (recommended)
|
||||
$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) {
|
||||
// Priority 1: Internal bundled vendor (shipped via release zip)
|
||||
$internal_autoloader = TWP_PLUGIN_DIR . 'vendor/autoload.php';
|
||||
if (file_exists($internal_autoloader)) {
|
||||
$autoloader_path = $internal_autoloader;
|
||||
}
|
||||
|
||||
// Priority 2: External legacy SDK location
|
||||
if (!$autoloader_path) {
|
||||
$external_autoloader = TWP_EXTERNAL_SDK_DIR . 'autoload.php';
|
||||
if (file_exists($external_autoloader)) {
|
||||
$autoloader_path = $external_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');
|
||||
error_log('TWP Plugin: Autoloader not found. Checked: ' . TWP_PLUGIN_DIR . 'vendor/autoload.php and ' . TWP_EXTERNAL_SDK_DIR . 'autoload.php');
|
||||
throw new Exception('Twilio SDK not found. Reinstall or update the plugin (release zips bundle the SDK), or run ./install-twilio-sdk-external.sh as a fallback.');
|
||||
}
|
||||
|
||||
// Load the autoloader
|
||||
|
||||
@@ -9,22 +9,22 @@ class TWP_Webhooks {
|
||||
*/
|
||||
public function __construct() {
|
||||
// Load Twilio SDK if not already loaded
|
||||
// Check external location first (survives plugin updates), then internal
|
||||
// Priority: bundled vendor/ first (shipped via release zip), external legacy path as fallback
|
||||
if (!class_exists('\Twilio\Rest\Client')) {
|
||||
$autoloader_path = null;
|
||||
|
||||
// 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) {
|
||||
// Priority 1: Internal bundled vendor directory
|
||||
$internal_autoloader = plugin_dir_path(dirname(__FILE__)) . 'vendor/autoload.php';
|
||||
if (file_exists($internal_autoloader)) {
|
||||
$autoloader_path = $internal_autoloader;
|
||||
}
|
||||
|
||||
// Priority 2: External legacy SDK location
|
||||
if (!$autoloader_path) {
|
||||
$external_autoloader = dirname(dirname(plugin_dir_path(dirname(__FILE__)))) . '/twilio-sdk/autoload.php';
|
||||
if (file_exists($external_autoloader)) {
|
||||
$autoloader_path = $external_autoloader;
|
||||
}
|
||||
}
|
||||
|
||||
if ($autoloader_path) {
|
||||
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to install AWS SDK for PHP to an external location
|
||||
# This prevents SDK from being deleted when WordPress updates the plugin
|
||||
#
|
||||
# Location: wp-content/aws-sdk/ (outside plugin folder)
|
||||
#
|
||||
# Uses the official single-file PHAR distribution from aws/aws-sdk-php releases.
|
||||
# The PHAR ships its own composer-generated autoloader, so no PSR-4 wiring needed.
|
||||
|
||||
echo "Installing AWS SDK for PHP (latest) 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
|
||||
|
||||
# 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/aws-sdk/
|
||||
WP_CONTENT_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||||
SDK_DIR="$WP_CONTENT_DIR/aws-sdk"
|
||||
|
||||
echo "Plugin directory: $SCRIPT_DIR"
|
||||
echo "SDK will be installed to: $SDK_DIR"
|
||||
|
||||
# Create SDK directory
|
||||
mkdir -p "$SDK_DIR"
|
||||
|
||||
# Download the latest PHAR release
|
||||
echo "Downloading AWS SDK PHAR from GitHub..."
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
cd "$TEMP_DIR"
|
||||
|
||||
if ! curl -L https://github.com/aws/aws-sdk-php/releases/latest/download/aws.phar -o aws.phar; then
|
||||
echo "ERROR: Failed to download AWS SDK PHAR"
|
||||
echo "Please check your internet connection and try again"
|
||||
rm -rf "$TEMP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify the download is non-empty (PHAR is roughly 12 MB)
|
||||
if [ ! -s "$TEMP_DIR/aws.phar" ]; then
|
||||
echo "ERROR: Downloaded AWS SDK PHAR is empty or missing"
|
||||
rm -rf "$TEMP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Remove existing SDK if it exists
|
||||
if [ -f "$SDK_DIR/aws.phar" ]; then
|
||||
echo "Removing existing AWS SDK installation..."
|
||||
rm -f "$SDK_DIR/aws.phar"
|
||||
fi
|
||||
|
||||
# Move the PHAR into place
|
||||
echo "Installing SDK files..."
|
||||
if ! mv "$TEMP_DIR/aws.phar" "$SDK_DIR/aws.phar"; then
|
||||
echo "ERROR: Failed to move AWS SDK PHAR into place"
|
||||
rm -rf "$TEMP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create the autoloader shim
|
||||
cat > "$SDK_DIR/autoload.php" << 'EOF'
|
||||
<?php
|
||||
/**
|
||||
* AWS SDK for PHP Autoloader (External Installation)
|
||||
* This file loads the AWS SDK via its bundled PHAR distribution.
|
||||
*
|
||||
* Location: wp-content/aws-sdk/autoload.php
|
||||
* This location survives WordPress plugin updates.
|
||||
*
|
||||
* The aws.phar file is the official single-file build from aws/aws-sdk-php
|
||||
* and ships with its own composer-generated autoloader, so all we need to
|
||||
* do is require_once the PHAR itself.
|
||||
*/
|
||||
|
||||
// Prevent multiple registrations
|
||||
if (!defined('TWP_AWS_AUTOLOADER_REGISTERED')) {
|
||||
define('TWP_AWS_AUTOLOADER_REGISTERED', true);
|
||||
|
||||
// The PHAR contains its own autoloader stub; requiring it registers
|
||||
// the AWS\, Aws\, GuzzleHttp\, and supporting namespaces.
|
||||
$aws_phar = __DIR__ . '/aws.phar';
|
||||
if (file_exists($aws_phar)) {
|
||||
require_once $aws_phar;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Clean up temp directory
|
||||
cd "$SCRIPT_DIR"
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
# Verify installation
|
||||
echo ""
|
||||
echo "Verifying installation..."
|
||||
if [ -f "$SDK_DIR/aws.phar" ] && [ -s "$SDK_DIR/aws.phar" ] && [ -f "$SDK_DIR/autoload.php" ]; then
|
||||
echo "=============================================="
|
||||
echo "AWS SDK for PHP 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 "Next steps:"
|
||||
echo " 1. In WP admin, open the Twilio plugin Settings page."
|
||||
echo " 2. Switch SMS provider to \"Amazon SNS\"."
|
||||
echo " 3. Enter AWS Access Key, Secret Key, and Region (e.g. us-west-2)."
|
||||
else
|
||||
echo "Installation failed - files not found"
|
||||
exit 1
|
||||
fi
|
||||
@@ -27,6 +27,7 @@ migrate_working_dir/
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.pub-cache/
|
||||
.pub/
|
||||
|
||||
@@ -35,11 +35,26 @@ public final class GeneratedPluginRegistrant {
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error registering plugin flutter_secure_storage, com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin", e);
|
||||
}
|
||||
try {
|
||||
flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin());
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error registering plugin package_info_plus, dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin", e);
|
||||
}
|
||||
try {
|
||||
flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin());
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e);
|
||||
}
|
||||
try {
|
||||
flutterEngine.getPlugins().add(new com.baseflow.permissionhandler.PermissionHandlerPlugin());
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error registering plugin permission_handler_android, com.baseflow.permissionhandler.PermissionHandlerPlugin", e);
|
||||
}
|
||||
try {
|
||||
flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.wakelock.WakelockPlusPlugin());
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error registering plugin wakelock_plus, dev.fluttercommunity.plus.wakelock.WakelockPlusPlugin", e);
|
||||
}
|
||||
try {
|
||||
flutterEngine.getPlugins().add(new io.flutter.plugins.webviewflutter.WebViewFlutterPlugin());
|
||||
} catch (Exception e) {
|
||||
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
import 'package:webview_flutter_android/webview_flutter_android.dart';
|
||||
import '../services/push_notification_service.dart';
|
||||
@@ -52,10 +53,27 @@ class _PhoneScreenState extends State<PhoneScreen> with WidgetsBindingObserver {
|
||||
}
|
||||
_initWebView();
|
||||
_initPush();
|
||||
WakelockPlus.enable();
|
||||
debugPrint('TWP: Wake lock enabled');
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
debugPrint('TWP: App resumed — re-enabling wake lock');
|
||||
WakelockPlus.enable();
|
||||
// Dispatch synthetic visibilitychange to trigger JS-side recovery
|
||||
_controller.runJavaScript(
|
||||
'document.dispatchEvent(new Event("visibilitychange"));'
|
||||
'Object.defineProperty(document, "hidden", {value: false, configurable: true});',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WakelockPlus.disable();
|
||||
debugPrint('TWP: Wake lock disabled');
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
+88
-32
@@ -37,26 +37,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
||||
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.4.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
version: "1.1.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.19.0"
|
||||
version: "1.19.1"
|
||||
dbus:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -69,10 +69,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -224,30 +224,46 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.6.0"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.2"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
|
||||
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.7"
|
||||
version: "11.0.2"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
|
||||
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.8"
|
||||
version: "3.0.10"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
||||
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
version: "3.0.2"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -260,34 +276,50 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16+1"
|
||||
version: "0.12.19"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.11.1"
|
||||
version: "0.13.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
|
||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
version: "1.17.0"
|
||||
package_info_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.0.0"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.0"
|
||||
version: "1.9.1"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -425,18 +457,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.0"
|
||||
version: "1.12.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
version: "2.1.4"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -457,10 +489,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
||||
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.3"
|
||||
version: "0.7.10"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -469,14 +501,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.4"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
version: "2.2.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -485,6 +525,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.0"
|
||||
wakelock_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: wakelock_plus
|
||||
sha256: "8b12256f616346910c519a35606fb69b1fe0737c06b6a447c6df43888b097f39"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
wakelock_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_plus_platform_interface
|
||||
sha256: "24b84143787220a403491c2e5de0877fbbb87baf3f0b18a2a988973863db4b03"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -550,5 +606,5 @@ packages:
|
||||
source: hosted
|
||||
version: "6.5.0"
|
||||
sdks:
|
||||
dart: ">=3.6.0 <4.0.0"
|
||||
flutter: ">=3.27.0"
|
||||
dart: ">=3.10.0 <4.0.0"
|
||||
flutter: ">=3.38.0"
|
||||
|
||||
+2
-1
@@ -1,7 +1,7 @@
|
||||
name: twp_softphone
|
||||
description: TWP Softphone - WebView client for Twilio WordPress Plugin
|
||||
publish_to: 'none'
|
||||
version: 2.0.1+7
|
||||
version: 2.0.2+8
|
||||
|
||||
environment:
|
||||
sdk: ^3.5.0
|
||||
@@ -16,6 +16,7 @@ dependencies:
|
||||
webview_flutter: ^4.10.0
|
||||
webview_flutter_android: ^4.3.0
|
||||
permission_handler: ^11.3.0
|
||||
wakelock_plus: ^1.2.8
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
+80
-29
@@ -4,6 +4,7 @@
|
||||
* Plugin URI: https://repo.anhonesthost.net/wp-plugins/twilio-wp-plugin
|
||||
* Description: WordPress plugin for Twilio integration with phone scheduling, call forwarding, queue management, and Eleven Labs TTS
|
||||
* Version: {auto_update_value_on_deploy}
|
||||
* Requires PHP: 8.1
|
||||
* Author: Josh Knapp
|
||||
* License: GPL v2 or later
|
||||
* Text Domain: twilio-wp-plugin
|
||||
@@ -20,8 +21,11 @@ define('TWP_DB_VERSION', '1.6.2'); // 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__));
|
||||
// External SDK location - survives plugin updates (wp-content/twilio-sdk/)
|
||||
// External SDK location - legacy/manual install path (wp-content/twilio-sdk/)
|
||||
// Bundled vendor/ inside the plugin (shipped via release zip) is now the primary source.
|
||||
define('TWP_EXTERNAL_SDK_DIR', dirname(dirname(TWP_PLUGIN_DIR)) . '/twilio-sdk/');
|
||||
// External AWS SDK location - installed via install-aws-sdk-external.sh (wp-content/aws-sdk/)
|
||||
define('TWP_EXTERNAL_AWS_SDK_DIR', dirname(dirname(TWP_PLUGIN_DIR)) . '/aws-sdk/');
|
||||
|
||||
/**
|
||||
* Plugin activation hook
|
||||
@@ -32,47 +36,91 @@ function twp_activate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Twilio SDK is installed and show admin notice if not
|
||||
* Checks external location first (survives plugin updates), then internal fallback
|
||||
* Check if Twilio (and optionally AWS) SDKs are available, load them, and
|
||||
* register admin notices if anything required is missing.
|
||||
*
|
||||
* Priority for the Twilio autoloader:
|
||||
* 1. Internal bundled `vendor/autoload.php` (shipped with release zip — always current)
|
||||
* 2. External legacy `wp-content/twilio-sdk/autoload.php` (manual install fallback)
|
||||
*
|
||||
* Composer's bundled autoloader handles BOTH `Twilio\…` and `Aws\…` via PSR-4. If
|
||||
* the bundled vendor doesn't supply Aws (e.g. someone installed Twilio-only
|
||||
* externally), we fall back to `wp-content/aws-sdk/autoload.php`.
|
||||
*/
|
||||
function twp_check_sdk_installation() {
|
||||
$sdk_installed = false;
|
||||
$twilio_sdk_installed = false;
|
||||
$aws_sdk_installed = false;
|
||||
|
||||
// Priority 1: Check external SDK location (survives plugin updates)
|
||||
$external_autoloader = TWP_EXTERNAL_SDK_DIR . 'autoload.php';
|
||||
if (file_exists($external_autoloader)) {
|
||||
require_once $external_autoloader;
|
||||
$sdk_installed = class_exists('Twilio\Rest\Client');
|
||||
}
|
||||
|
||||
// Priority 2: Fall back to internal vendor directory
|
||||
if (!$sdk_installed) {
|
||||
// --- Twilio SDK ---
|
||||
// Priority 1: Internal bundled vendor (shipped via release zip)
|
||||
$internal_autoloader = TWP_PLUGIN_DIR . 'vendor/autoload.php';
|
||||
if (file_exists($internal_autoloader)) {
|
||||
require_once $internal_autoloader;
|
||||
$sdk_installed = class_exists('Twilio\Rest\Client');
|
||||
$twilio_sdk_installed = class_exists('Twilio\Rest\Client');
|
||||
}
|
||||
|
||||
// Priority 2: External legacy location (manual installs)
|
||||
if (!$twilio_sdk_installed) {
|
||||
$external_autoloader = TWP_EXTERNAL_SDK_DIR . 'autoload.php';
|
||||
if (file_exists($external_autoloader)) {
|
||||
require_once $external_autoloader;
|
||||
$twilio_sdk_installed = class_exists('Twilio\Rest\Client');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$sdk_installed) {
|
||||
// --- AWS SDK ---
|
||||
// The bundled composer vendor may already provide it (if shipped with release).
|
||||
$aws_sdk_installed = class_exists('Aws\Sns\SnsClient');
|
||||
if (!$aws_sdk_installed) {
|
||||
$aws_external_autoloader = TWP_EXTERNAL_AWS_SDK_DIR . 'autoload.php';
|
||||
if (file_exists($aws_external_autoloader)) {
|
||||
require_once $aws_external_autoloader;
|
||||
$aws_sdk_installed = class_exists('Aws\Sns\SnsClient');
|
||||
}
|
||||
}
|
||||
|
||||
// Twilio is the hard requirement — always notify if missing.
|
||||
if (!$twilio_sdk_installed) {
|
||||
add_action('admin_notices', 'twp_sdk_missing_notice');
|
||||
}
|
||||
|
||||
// AWS is only required when the SNS provider is selected.
|
||||
if (!$aws_sdk_installed && get_option('twp_sms_provider') === 'aws_sns') {
|
||||
add_action('admin_notices', 'twp_aws_sdk_missing_notice');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display admin notice for missing SDK
|
||||
* Display admin notice for missing Twilio SDK
|
||||
*/
|
||||
function twp_sdk_missing_notice() {
|
||||
?>
|
||||
<div class="notice notice-error is-dismissible">
|
||||
<h3>Twilio WordPress Plugin - SDK Required</h3>
|
||||
<h3>Twilio WordPress Plugin - Twilio SDK Required</h3>
|
||||
<p><strong>The Twilio PHP SDK is required for this plugin to work.</strong></p>
|
||||
<p><strong>Recommended:</strong> Install SDK to external location (survives plugin updates):</p>
|
||||
<p><strong>Recommended:</strong> Reinstall or update the plugin. Plugin updates now bundle the SDK (the release zip ships a pre-built <code>vendor/</code> directory), so a fresh install or update is the simplest fix.</p>
|
||||
<p style="margin-top: 10px;"><strong>Legacy / manual install:</strong> If you can't update the plugin, you can install the SDK to the external location instead:</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>
|
||||
<p style="margin-top: 10px;"><em>Plugin path: <?php echo esc_html(TWP_PLUGIN_DIR); ?></em></p>
|
||||
<p><em>External SDK path: <?php echo esc_html(TWP_EXTERNAL_SDK_DIR); ?></em></p>
|
||||
<p><em>Bundled vendor path: <?php echo esc_html(TWP_PLUGIN_DIR . 'vendor/'); ?></em></p>
|
||||
<p><em>External SDK fallback path: <?php echo esc_html(TWP_EXTERNAL_SDK_DIR); ?></em></p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Display admin notice for missing AWS SDK (only fired when SNS provider is selected)
|
||||
*/
|
||||
function twp_aws_sdk_missing_notice() {
|
||||
?>
|
||||
<div class="notice notice-error is-dismissible">
|
||||
<h3>Twilio WordPress Plugin - AWS SDK Required for SNS SMS</h3>
|
||||
<p><strong>You have selected AWS SNS as your SMS provider, but the AWS PHP SDK is not available.</strong></p>
|
||||
<p><strong>Recommended:</strong> Update the plugin to a release-bundled version — newer release zips bundle the AWS SDK alongside the Twilio SDK in <code>vendor/</code>.</p>
|
||||
<p style="margin-top: 10px;"><strong>Legacy / manual install:</strong> Install the AWS SDK to the external location:</p>
|
||||
<code>chmod +x install-aws-sdk-external.sh && ./install-aws-sdk-external.sh</code>
|
||||
<p style="margin-top: 10px;"><em>External AWS SDK path: <?php echo esc_html(TWP_EXTERNAL_AWS_SDK_DIR); ?></em></p>
|
||||
<p><em>If you don't need AWS SNS, switch the SMS provider back to Twilio under the plugin settings.</em></p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
@@ -142,7 +190,8 @@ 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
|
||||
* Shows warning if neither the bundled vendor/ nor the external SDK is available
|
||||
* after an update — this should be rare now that release zips ship vendor/.
|
||||
*/
|
||||
function twp_check_sdk_after_update($upgrader_object, $options) {
|
||||
// Only run for plugin updates
|
||||
@@ -156,11 +205,11 @@ function twp_check_sdk_after_update($upgrader_object, $options) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if SDK is available
|
||||
$external_sdk = file_exists(TWP_EXTERNAL_SDK_DIR . 'autoload.php');
|
||||
// Check if a Twilio SDK autoloader is available anywhere
|
||||
$internal_sdk = file_exists(TWP_PLUGIN_DIR . 'vendor/autoload.php');
|
||||
$external_sdk = file_exists(TWP_EXTERNAL_SDK_DIR . 'autoload.php');
|
||||
|
||||
if (!$external_sdk && !$internal_sdk) {
|
||||
if (!$internal_sdk && !$external_sdk) {
|
||||
// Set a transient to show warning on next admin page load
|
||||
set_transient('twp_sdk_update_warning', true, 60 * 5);
|
||||
}
|
||||
@@ -175,11 +224,13 @@ function twp_show_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>
|
||||
<h3>Twilio WordPress Plugin - SDK Missing After Update</h3>
|
||||
<p><strong>The plugin was updated, but no Twilio SDK could be found.</strong></p>
|
||||
<p>Plugin release zips normally bundle the SDK in <code>vendor/</code>, so this usually means the release was built without dependencies, or the upload was incomplete. Try downloading the release zip again and reinstalling.</p>
|
||||
<p style="margin-top: 10px;"><strong>Manual install fallback:</strong></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>
|
||||
<p style="margin-top: 10px;"><em>Bundled vendor path: <?php echo esc_html(TWP_PLUGIN_DIR . 'vendor/'); ?></em></p>
|
||||
<p><em>External SDK fallback path: <?php echo esc_html(TWP_EXTERNAL_SDK_DIR); ?></em></p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user