upskill-event-manager/wordpress-dev/bin/deploy-zoho-fixes.sh

1261 lines
No EOL
47 KiB
Bash
Executable file

#!/bin/bash
#
# Deploy Zoho CRM integration fixes to staging server
# This script uploads the modified PHP files and applies the changes
#
# Set variables
STAGING_HOST="wordpress-974670-5399585.cloudwaysapps.com"
STAGING_USER="uberrxmprk" # Default Cloudways username
REMOTE_DIR="/home/974670.cloudwaysapps.com/uberrxmprk/public_html"
PLUGIN_DIR="/wp-content/plugins/hvac-community-events"
PLUGIN_PATH="${REMOTE_DIR}${PLUGIN_DIR}"
# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Make script executable
chmod +x $0
echo -e "${YELLOW}========================================"
echo -e "Deploying Zoho CRM integration fixes"
echo -e "========================================${NC}"
# Check if SSH key authentication is set up
echo -e "${YELLOW}Checking SSH connection...${NC}"
ssh -o BatchMode=yes -o ConnectTimeout=5 ${STAGING_USER}@${STAGING_HOST} "echo Connected" >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo -e "${RED}Error: Cannot connect to staging server using SSH key authentication."
echo -e "Please make sure your SSH key is added to the staging server.${NC}"
echo -e "You may need to run: ssh-copy-id ${STAGING_USER}@${STAGING_HOST}"
echo -e "Or use password authentication by modifying this script.${NC}"
exit 1
fi
echo -e "${GREEN}SSH connection successful.${NC}"
# Create backup of original files
echo -e "${YELLOW}1. Creating backups of original files${NC}"
BACKUP_CMD="mkdir -p ${PLUGIN_PATH}/includes/backup-$(date +%Y%m%d) && \
cp ${PLUGIN_PATH}/includes/zoho/class-zoho-crm-auth.php ${PLUGIN_PATH}/includes/backup-$(date +%Y%m%d)/class-zoho-crm-auth.php.bak && \
cp ${PLUGIN_PATH}/includes/admin/class-zoho-admin.php ${PLUGIN_PATH}/includes/backup-$(date +%Y%m%d)/class-zoho-admin.php.bak && \
echo 'Backups created successfully'"
ssh ${STAGING_USER}@${STAGING_HOST} "${BACKUP_CMD}"
if [ $? -ne 0 ]; then
echo -e "${RED}Error: Failed to create backups on the server${NC}"
exit 1
fi
echo -e "${GREEN}Backups created successfully.${NC}"
# Create local files with fixes
echo -e "${YELLOW}2. Creating fixed PHP files locally${NC}"
# Create a temporary directory for our fixes
TMP_DIR=$(mktemp -d)
mkdir -p ${TMP_DIR}/includes/zoho
mkdir -p ${TMP_DIR}/includes/admin
# Create the fixed zoho-crm-auth.php file
cat > ${TMP_DIR}/includes/zoho/class-zoho-crm-auth.php << 'EOF'
<?php
/**
* Zoho CRM Authentication Handler
*
* Handles OAuth token management and API authentication
*
* @package HVAC_Community_Events
* @subpackage Zoho_Integration
*/
if (!defined('ABSPATH')) {
exit;
}
class HVAC_Zoho_CRM_Auth {
private $client_id;
private $client_secret;
private $refresh_token;
private $redirect_uri;
private $access_token;
private $token_expiry;
private $last_error = null;
public function __construct() {
// Load environment variables first
$this->load_env_variables();
// Load configuration if available
$config_file = plugin_dir_path(__FILE__) . 'zoho-config.php';
if (file_exists($config_file)) {
require_once $config_file;
$this->client_id = defined('ZOHO_CLIENT_ID') ? ZOHO_CLIENT_ID : '';
$this->client_secret = defined('ZOHO_CLIENT_SECRET') ? ZOHO_CLIENT_SECRET : '';
$this->refresh_token = defined('ZOHO_REFRESH_TOKEN') ? ZOHO_REFRESH_TOKEN : '';
$this->redirect_uri = defined('ZOHO_REDIRECT_URI') ? ZOHO_REDIRECT_URI : 'http://localhost:8080/callback';
}
// Load stored access token from WordPress options
$this->load_access_token();
}
/**
* Load environment variables from .env file
* This helps with local development and staging environments
*
* @return array Array of loaded environment variables
*/
public function load_env_variables() {
$env_vars = array();
$env_file = ABSPATH . '../.env';
if (file_exists($env_file)) {
$this->log_debug('Loading environment variables from .env file');
$env_contents = file_get_contents($env_file);
$env_lines = explode("\n", $env_contents);
foreach ($env_lines as $line) {
$line = trim($line);
// Skip comments and empty lines
if (empty($line) || strpos($line, '#') === 0) {
continue;
}
// Parse variable assignments
if (strpos($line, '=') !== false) {
list($key, $value) = explode('=', $line, 2);
$key = trim($key);
$value = trim($value);
// Remove quotes if present
if (strpos($value, '"') === 0 && strrpos($value, '"') === strlen($value) - 1) {
$value = substr($value, 1, -1);
} elseif (strpos($value, "'") === 0 && strrpos($value, "'") === strlen($value) - 1) {
$value = substr($value, 1, -1);
}
$env_vars[$key] = $value;
// Define constants for Zoho configuration
if (strpos($key, 'ZOHO_') === 0 && !defined($key)) {
define($key, $value);
$this->log_debug("Defined $key from .env file");
}
}
}
$zoho_vars_count = 0;
foreach ($env_vars as $key => $value) {
if (strpos($key, 'ZOHO_') === 0) {
$zoho_vars_count++;
}
}
$this->log_debug("Loaded $zoho_vars_count Zoho-related environment variables");
} else {
$this->log_debug('No .env file found at: ' . $env_file);
}
return $env_vars;
}
/**
* Generate authorization URL for initial setup
*/
public function get_authorization_url() {
$params = array(
'scope' => defined('ZOHO_SCOPES') ? ZOHO_SCOPES : 'ZohoCRM.settings.all,ZohoCRM.modules.all,ZohoCRM.users.all,ZohoCRM.org.all',
'client_id' => $this->client_id,
'response_type' => 'code',
'access_type' => 'offline',
'redirect_uri' => $this->redirect_uri,
'prompt' => 'consent'
);
$accounts_url = defined('ZOHO_ACCOUNTS_URL') ? ZOHO_ACCOUNTS_URL : 'https://accounts.zoho.com';
return $accounts_url . '/oauth/v2/auth?' . http_build_query($params);
}
/**
* Exchange authorization code for tokens
*/
public function exchange_code_for_tokens($auth_code) {
$accounts_url = defined('ZOHO_ACCOUNTS_URL') ? ZOHO_ACCOUNTS_URL : 'https://accounts.zoho.com';
$url = $accounts_url . '/oauth/v2/token';
$params = array(
'grant_type' => 'authorization_code',
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'redirect_uri' => $this->redirect_uri,
'code' => $auth_code
);
$response = wp_remote_post($url, array(
'body' => $params,
'headers' => array(
'Content-Type' => 'application/x-www-form-urlencoded'
)
));
if (is_wp_error($response)) {
$this->log_error('Failed to exchange code: ' . $response->get_error_message());
return false;
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
if (isset($data['access_token']) && isset($data['refresh_token'])) {
$this->access_token = $data['access_token'];
$this->refresh_token = $data['refresh_token'];
$this->token_expiry = time() + $data['expires_in'];
// Save tokens
$this->save_tokens();
return true;
}
$this->log_error('Invalid token response: ' . $body);
return false;
}
/**
* Get valid access token (refresh if needed)
*/
public function get_access_token() {
// Check if token is expired or will expire soon (5 mins buffer)
if (!$this->access_token || (time() + 300) >= $this->token_expiry) {
$this->refresh_access_token();
}
return $this->access_token;
}
/**
* Refresh access token using refresh token
*/
private function refresh_access_token() {
$accounts_url = defined('ZOHO_ACCOUNTS_URL') ? ZOHO_ACCOUNTS_URL : 'https://accounts.zoho.com';
$url = $accounts_url . '/oauth/v2/token';
$params = array(
'refresh_token' => $this->refresh_token,
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'grant_type' => 'refresh_token'
);
$response = wp_remote_post($url, array(
'body' => $params,
'headers' => array(
'Content-Type' => 'application/x-www-form-urlencoded'
)
));
if (is_wp_error($response)) {
$this->log_error('Failed to refresh token: ' . $response->get_error_message());
return false;
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
if (isset($data['access_token'])) {
$this->access_token = $data['access_token'];
$this->token_expiry = time() + $data['expires_in'];
$this->save_access_token();
return true;
}
$this->log_error('Failed to refresh token: ' . $body);
return false;
}
/**
* Make authenticated API request
*/
public function make_api_request($endpoint, $method = 'GET', $data = null) {
// Check if we're in staging mode
$site_url = get_site_url();
$is_staging = strpos($site_url, 'upskillhvac.com') === false;
// In staging mode, only allow read operations, no writes
if ($is_staging && in_array($method, array('POST', 'PUT', 'DELETE', 'PATCH'))) {
$this->log_debug('STAGING MODE: Simulating ' . $method . ' request to ' . $endpoint);
return array(
'data' => array(
array(
'code' => 'STAGING_MODE',
'details' => array(
'message' => 'Staging mode active. Write operations are disabled.'
),
'message' => 'This would have been a ' . $method . ' request to: ' . $endpoint,
'status' => 'success'
)
)
);
}
// Debug logging of config status
if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) {
$config_status = $this->get_configuration_status();
$this->log_debug('Configuration status: ' . json_encode($config_status));
if (!$config_status['client_id_exists']) {
$this->log_error('Client ID is missing or empty');
}
if (!$config_status['client_secret_exists']) {
$this->log_error('Client Secret is missing or empty');
}
if (!$config_status['refresh_token_exists']) {
$this->log_error('Refresh Token is missing or empty');
}
if ($config_status['token_expired']) {
$this->log_debug('Access token is expired, will attempt to refresh');
}
}
$access_token = $this->get_access_token();
if (!$access_token) {
$error_message = 'No valid access token available';
$this->log_error($error_message);
return new WP_Error('no_token', $error_message);
}
$api_base_url = defined('ZOHO_API_BASE_URL') ? ZOHO_API_BASE_URL : 'https://www.zohoapis.com/crm/v2';
$url = $api_base_url . $endpoint;
// Log the request details
$this->log_debug('Making ' . $method . ' request to: ' . $url);
$args = array(
'method' => $method,
'headers' => array(
'Authorization' => 'Zoho-oauthtoken ' . $access_token,
'Content-Type' => 'application/json'
),
'timeout' => 30 // Increase timeout to 30 seconds for potentially slow responses
);
if ($data && in_array($method, array('POST', 'PUT', 'PATCH'))) {
$args['body'] = json_encode($data);
$this->log_debug('Request payload: ' . json_encode($data));
}
// Execute the request
$this->log_debug('Executing request to Zoho API');
$response = wp_remote_request($url, $args);
// Handle WordPress errors
if (is_wp_error($response)) {
$error_message = 'API request failed: ' . $response->get_error_message();
$error_data = $response->get_error_data();
$this->log_error($error_message);
$this->log_debug('Error details: ' . json_encode($error_data));
return $response;
}
// Get response code and body
$status_code = wp_remote_retrieve_response_code($response);
$headers = wp_remote_retrieve_headers($response);
$body = wp_remote_retrieve_body($response);
$this->log_debug('Response code: ' . $status_code);
// Log headers for debugging
if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) {
$this->log_debug('Response headers: ' . json_encode($headers->getAll()));
}
// Handle empty responses
if (empty($body)) {
$error_message = 'Empty response received from Zoho API';
$this->log_error($error_message);
return array(
'error' => $error_message,
'code' => $status_code,
'details' => 'No response body received'
);
}
// Parse the JSON response
$data = json_decode($body, true);
// Check for JSON parsing errors
if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
$error_message = 'Invalid JSON response: ' . json_last_error_msg();
$this->log_error($error_message);
$this->log_debug('Raw response: ' . $body);
return array(
'error' => $error_message,
'code' => 'JSON_PARSE_ERROR',
'details' => 'Raw response: ' . substr($body, 0, 255) . (strlen($body) > 255 ? '...' : '')
);
}
// Log response for debugging
if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE) {
$this->log_debug('API Response: ' . $body);
}
// Check for API errors
if ($status_code >= 400) {
$error_message = isset($data['message']) ? $data['message'] : 'API error with status code ' . $status_code;
$this->log_error($error_message);
// Add HTTP error information to the response
$data['http_status'] = $status_code;
$data['error'] = $error_message;
// Extract more detailed error information if available
if (isset($data['code'])) {
$this->log_debug('Error code: ' . $data['code']);
}
if (isset($data['details'])) {
$this->log_debug('Error details: ' . json_encode($data['details']));
}
}
return $data;
}
/**
* Save tokens to WordPress options
*/
private function save_tokens() {
update_option('hvac_zoho_refresh_token', $this->refresh_token);
$this->save_access_token();
}
/**
* Save access token
*/
private function save_access_token() {
update_option('hvac_zoho_access_token', $this->access_token);
update_option('hvac_zoho_token_expiry', $this->token_expiry);
}
/**
* Load access token from WordPress options
*/
private function load_access_token() {
$this->access_token = get_option('hvac_zoho_access_token');
$this->token_expiry = get_option('hvac_zoho_token_expiry', 0);
// Load refresh token if not set
if (!$this->refresh_token) {
$this->refresh_token = get_option('hvac_zoho_refresh_token');
}
}
/**
* Log error messages
*/
private function log_error($message) {
$this->last_error = $message;
if (defined('ZOHO_LOG_FILE')) {
error_log('[' . date('Y-m-d H:i:s') . '] ERROR: ' . $message . PHP_EOL, 3, ZOHO_LOG_FILE);
}
// Also log to WordPress debug log if available
if (defined('WP_DEBUG') && WP_DEBUG && defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
error_log('[ZOHO CRM] ' . $message);
}
}
/**
* Log debug messages
*/
private function log_debug($message) {
if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE && defined('ZOHO_LOG_FILE')) {
error_log('[' . date('Y-m-d H:i:s') . '] DEBUG: ' . $message . PHP_EOL, 3, ZOHO_LOG_FILE);
}
// Also log to WordPress debug log if available
if (defined('ZOHO_DEBUG_MODE') && ZOHO_DEBUG_MODE && defined('WP_DEBUG') && WP_DEBUG && defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
error_log('[ZOHO CRM DEBUG] ' . $message);
}
}
/**
* Get the last error message
*
* @return string|null
*/
public function get_last_error() {
return $this->last_error;
}
/**
* Get client ID (for debugging only)
*
* @return string
*/
public function get_client_id() {
return $this->client_id;
}
/**
* Check if client secret exists (for debugging only)
*
* @return bool
*/
public function get_client_secret() {
return !empty($this->client_secret);
}
/**
* Check if refresh token exists (for debugging only)
*
* @return bool
*/
public function get_refresh_token() {
return !empty($this->refresh_token);
}
/**
* Get configuration status (for debugging)
*
* @return array
*/
public function get_configuration_status() {
return array(
'client_id_exists' => !empty($this->client_id),
'client_secret_exists' => !empty($this->client_secret),
'refresh_token_exists' => !empty($this->refresh_token),
'access_token_exists' => !empty($this->access_token),
'token_expired' => $this->token_expiry < time(),
'config_loaded' => file_exists(plugin_dir_path(__FILE__) . 'zoho-config.php')
);
}
}
EOF
# Create the enhanced zoho-admin.php file
cat > ${TMP_DIR}/includes/admin/class-zoho-admin.php << 'EOF'
<?php
/**
* Zoho CRM Admin Interface
*
* @package HVACCommunityEvents
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Zoho CRM Admin Class
*/
class HVAC_Zoho_Admin {
/**
* Initialize the admin interface
*/
public function __construct() {
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
add_action('wp_ajax_hvac_zoho_test_connection', array($this, 'test_connection'));
add_action('wp_ajax_hvac_zoho_sync_data', array($this, 'sync_data'));
}
/**
* Add admin menu
*/
public function add_admin_menu() {
add_submenu_page(
'hvac-community-events',
'Zoho CRM Sync',
'Zoho CRM Sync',
'manage_options',
'hvac-zoho-sync',
array($this, 'render_admin_page')
);
}
/**
* Enqueue admin scripts
*/
public function enqueue_admin_scripts($hook) {
if ($hook !== 'hvac-community-events_page_hvac-zoho-sync') {
return;
}
wp_enqueue_script(
'hvac-zoho-admin',
HVAC_CE_PLUGIN_URL . 'assets/js/zoho-admin.js',
array('jquery'),
HVAC_CE_VERSION,
true
);
wp_localize_script('hvac-zoho-admin', 'hvacZoho', array(
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('hvac_zoho_nonce')
));
wp_enqueue_style(
'hvac-zoho-admin',
HVAC_CE_PLUGIN_URL . 'assets/css/zoho-admin.css',
array(),
HVAC_CE_VERSION
);
}
/**
* Render admin page
*/
public function render_admin_page() {
$config_file = HVAC_CE_PLUGIN_DIR . 'includes/zoho/zoho-config.php';
$is_configured = file_exists($config_file);
$site_url = get_site_url();
$is_staging = strpos($site_url, 'upskillhvac.com') === false;
?>
<div class="wrap">
<h1>Zoho CRM Sync</h1>
<?php if ($is_staging): ?>
<div class="notice notice-info">
<h3>🔧 STAGING MODE ACTIVE</h3>
<p><strong>Current site:</strong> <?php echo esc_html($site_url); ?></p>
<p>Staging mode is active. Data sync will be simulated only. No actual data will be sent to Zoho CRM.</p>
<p>Production sync is only enabled on <strong>upskillhvac.com</strong></p>
</div>
<?php endif; ?>
<?php if (!$is_configured): ?>
<div class="notice notice-warning">
<p>Zoho CRM is not configured. Please complete the OAuth setup first.</p>
<p>Run: <code>./bin/zoho-setup-complete.sh</code></p>
</div>
<?php else: ?>
<div class="hvac-zoho-status">
<h2>Connection Status</h2>
<button class="button button-primary" id="test-connection">Test Connection</button>
<div id="connection-status"></div>
</div>
<div class="hvac-zoho-sync">
<h2>Data Sync</h2>
<div class="sync-section">
<h3>Events → Campaigns</h3>
<p>Sync events from The Events Calendar to Zoho CRM Campaigns</p>
<button class="button sync-button" data-type="events">Sync Events</button>
<div class="sync-status" id="events-status"></div>
</div>
<div class="sync-section">
<h3>Users → Contacts</h3>
<p>Sync trainers and attendees to Zoho CRM Contacts</p>
<button class="button sync-button" data-type="users">Sync Users</button>
<div class="sync-status" id="users-status"></div>
</div>
<div class="sync-section">
<h3>Purchases → Invoices</h3>
<p>Sync ticket purchases to Zoho CRM Invoices</p>
<button class="button sync-button" data-type="purchases">Sync Purchases</button>
<div class="sync-status" id="purchases-status"></div>
</div>
</div>
<div class="hvac-zoho-settings">
<h2>Sync Settings</h2>
<form id="zoho-settings-form">
<label>
<input type="checkbox" name="auto_sync" value="1" <?php checked(get_option('hvac_zoho_auto_sync'), '1'); ?>>
Enable automatic sync
</label>
<br><br>
<label>
Sync frequency:
<select name="sync_frequency">
<option value="hourly" <?php selected(get_option('hvac_zoho_sync_frequency'), 'hourly'); ?>>Hourly</option>
<option value="daily" <?php selected(get_option('hvac_zoho_sync_frequency'), 'daily'); ?>>Daily</option>
<option value="weekly" <?php selected(get_option('hvac_zoho_sync_frequency'), 'weekly'); ?>>Weekly</option>
</select>
</label>
<br><br>
<button type="submit" class="button button-primary">Save Settings</button>
</form>
</div>
<?php endif; ?>
</div>
<?php
}
/**
* Test Zoho connection with enhanced error reporting
*/
public function test_connection() {
check_ajax_referer('hvac_zoho_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_die('Unauthorized');
}
try {
require_once HVAC_CE_PLUGIN_DIR . 'includes/zoho/class-zoho-crm-auth.php';
// Enable debug logging
if (!defined('ZOHO_DEBUG_MODE')) {
define('ZOHO_DEBUG_MODE', true);
}
// Create a temporary log file if needed
if (!defined('ZOHO_LOG_FILE')) {
$log_dir = HVAC_CE_PLUGIN_DIR . 'logs';
if (!file_exists($log_dir)) {
mkdir($log_dir, 0755, true);
}
define('ZOHO_LOG_FILE', $log_dir . '/zoho-debug.log');
}
// Load the general logger for additional context
require_once HVAC_CE_PLUGIN_DIR . 'includes/class-hvac-logger.php';
HVAC_Logger::set_enabled(true);
HVAC_Logger::info('Starting Zoho connection test', 'ZOHO_TEST');
// Create auth instance
$auth = new HVAC_Zoho_CRM_Auth();
$config_status = $auth->get_configuration_status();
// Check for essential configuration
if (!$config_status['client_id_exists'] || !$config_status['client_secret_exists'] || !$config_status['refresh_token_exists']) {
// Detailed error about missing configuration
$missing = array();
if (!$config_status['client_id_exists']) $missing[] = 'Client ID';
if (!$config_status['client_secret_exists']) $missing[] = 'Client Secret';
if (!$config_status['refresh_token_exists']) $missing[] = 'Refresh Token';
HVAC_Logger::error('Configuration incomplete', 'ZOHO_TEST', array(
'missing_items' => $missing,
'config_status' => $config_status
));
// Check if .env file exists and has Zoho variables
$env_file = ABSPATH . '../.env';
$env_info = array(
'env_file_exists' => file_exists($env_file),
'env_file_path' => $env_file
);
if ($env_info['env_file_exists']) {
$env_contents = file_get_contents($env_file);
$env_info['has_zoho_vars'] = (strpos($env_contents, 'ZOHO_') !== false);
$env_info['file_size'] = filesize($env_file);
$env_info['file_perms'] = substr(sprintf('%o', fileperms($env_file)), -4);
}
HVAC_Logger::info('Environment file status', 'ZOHO_TEST', $env_info);
wp_send_json_error(array(
'message' => 'Zoho CRM configuration is incomplete',
'missing' => $missing,
'config_status' => $config_status,
'env_info' => $env_info,
'fix_suggestions' => array(
'Check if .env file contains the necessary Zoho variables',
'Ensure zoho-config.php file is properly created with required constants',
'Try running the setup script: ./bin/zoho-setup-complete.sh',
'Verify environment variables are properly loaded'
)
));
return;
}
// Debug connection parameters
HVAC_Logger::info('Checking Zoho configuration', 'ZOHO_TEST', array(
'client_id_exists' => !empty($auth->get_client_id()),
'client_secret_exists' => !empty($auth->get_client_secret()),
'refresh_token_exists' => !empty($auth->get_refresh_token()),
'config_file' => plugin_dir_path(__FILE__) . '../zoho/zoho-config.php',
'config_file_exists' => file_exists(plugin_dir_path(__FILE__) . '../zoho/zoho-config.php')
));
// Test API call
$response = $auth->make_api_request('/settings/modules', 'GET');
// Detailed logging of the response
if (is_wp_error($response)) {
$error_data = array(
'error_message' => $response->get_error_message(),
'error_code' => $response->get_error_code(),
'error_data' => $response->get_error_data()
);
HVAC_Logger::error('WP Error in API request', 'ZOHO_TEST', $error_data);
// Check for common error patterns
$error_message = $response->get_error_message();
$suggestions = array();
if (strpos($error_message, 'cURL error 6') !== false) {
$suggestions[] = 'Could not resolve host: Check your internet connection or DNS configuration';
$suggestions[] = 'Verify that ZOHO_API_BASE_URL is correctly defined';
} else if (strpos($error_message, 'cURL error 28') !== false) {
$suggestions[] = 'Connection timed out: The server took too long to respond';
$suggestions[] = 'Check your firewall settings or network connectivity';
} else if (strpos($error_message, '401') !== false) {
$suggestions[] = 'Authentication failed: Check your client credentials';
$suggestions[] = 'Try refreshing your tokens manually using the refresh token';
}
wp_send_json_error(array(
'message' => 'Connection failed - WordPress Error',
'error' => $response->get_error_message(),
'details' => $error_data,
'suggestions' => $suggestions
));
return;
}
if ($response && !isset($response['error'])) {
$success_data = array(
'modules_count' => isset($response['modules']) ? count($response['modules']) : 0
);
if (isset($response['modules']) && is_array($response['modules'])) {
$modules_list = array();
foreach ($response['modules'] as $module) {
if (isset($module['api_name'])) {
$modules_list[] = $module['api_name'];
}
}
$success_data['available_modules'] = $modules_list;
}
HVAC_Logger::info('Connection successful', 'ZOHO_TEST', $success_data);
wp_send_json_success(array(
'message' => 'Connection successful!',
'modules' => isset($response['modules']) ? count($response['modules']) . ' modules available' : 'No modules found',
'modules_list' => isset($success_data['available_modules']) ? $success_data['available_modules'] : array(),
'status' => 'Zoho CRM is properly configured and responding'
));
} else {
$error_message = isset($response['error']) ? $response['error'] : 'Unknown error';
$error_code = isset($response['code']) ? $response['code'] : '';
$error_details = isset($response['details']) ? $response['details'] : '';
// Extract more detailed error information if available
if (isset($response['data']) && is_array($response['data']) && !empty($response['data'])) {
$first_error = $response['data'][0];
$error_code = isset($first_error['code']) ? $first_error['code'] : $error_code;
$error_message = isset($first_error['message']) ? $first_error['message'] : $error_message;
if (isset($first_error['details']) && is_array($first_error['details'])) {
$error_details = json_encode($first_error['details']);
}
}
$error_data = array(
'error' => $error_message,
'code' => $error_code,
'details' => $error_details,
'full_response' => $response
);
HVAC_Logger::error('Connection failed', 'ZOHO_TEST', $error_data);
// Generate helpful suggestions based on error
$suggestions = array();
if (strpos($error_message, 'invalid_client') !== false) {
$suggestions[] = 'Client credentials are invalid. Verify Client ID and Client Secret';
$suggestions[] = 'Ensure the OAuth app in Zoho is properly configured';
} else if (strpos($error_message, 'invalid_code') !== false) {
$suggestions[] = 'Authorization code is invalid or expired';
$suggestions[] = 'Re-authorize the application to get a new code';
} else if (strpos($error_message, 'invalid_token') !== false) {
$suggestions[] = 'Access token is invalid or expired';
$suggestions[] = 'Check refresh token and try to get a new access token';
}
wp_send_json_error(array(
'message' => 'Connection failed',
'error' => $error_message,
'code' => $error_code,
'details' => $error_details,
'raw' => json_encode($response),
'suggestions' => $suggestions
));
}
} catch (Exception $e) {
$exception_data = array(
'exception' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString()
);
HVAC_Logger::error('Exception in Zoho connection test', 'ZOHO_TEST', $exception_data);
wp_send_json_error(array(
'message' => 'Connection failed due to exception',
'error' => $e->getMessage(),
'file' => $e->getFile() . ':' . $e->getLine(),
'trace' => $e->getTraceAsString(),
'suggestions' => array(
'Check PHP error logs for more details',
'Verify that all required PHP extensions are enabled',
'Ensure the Zoho API endpoints are accessible from your server'
)
));
}
}
/**
* Sync data to Zoho
*/
public function sync_data() {
check_ajax_referer('hvac_zoho_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_die('Unauthorized');
}
$type = sanitize_text_field($_POST['type']);
try {
require_once HVAC_CE_PLUGIN_DIR . 'includes/zoho/class-zoho-sync.php';
$sync = new HVAC_Zoho_Sync();
switch ($type) {
case 'events':
$result = $sync->sync_events();
break;
case 'users':
$result = $sync->sync_users();
break;
case 'purchases':
$result = $sync->sync_purchases();
break;
default:
throw new Exception('Invalid sync type');
}
wp_send_json_success($result);
} catch (Exception $e) {
wp_send_json_error(array(
'message' => 'Sync failed',
'error' => $e->getMessage()
));
}
}
}
EOF
# Create check-zoho-env.php for diagnostic purposes
cat > ${TMP_DIR}/check-zoho-env.php << 'EOF'
<?php
/**
* Zoho Environment Checker
*
* This file helps diagnose Zoho CRM integration issues by checking environment variables
* and configuration files.
*
* Add ?run_check=1 to the URL to run the check.
*/
// Only allow execution via WordPress admin or direct check
if (!defined('ABSPATH')) {
if (!isset($_GET['run_check']) || $_GET['run_check'] != 1) {
die('Access denied. Add ?run_check=1 to run this diagnostic tool.');
}
// Get WordPress root directory
$wp_root = dirname(dirname(dirname(dirname(dirname(__FILE__)))));
define('ABSPATH', $wp_root . '/');
// Include wp-load.php to get access to WordPress functions
require_once(ABSPATH . 'wp-load.php');
// Check user authentication for security
if (!is_user_logged_in() || !current_user_can('manage_options')) {
die('You must be logged in as an administrator to run this tool.');
}
}
header('Content-Type: text/plain');
echo "=== Zoho Environment Check ===\n\n";
// Check for .env file
$env_paths = [
ABSPATH . '../.env',
ABSPATH . '.env',
dirname(__FILE__) . '/../.env',
dirname(__FILE__) . '/.env',
];
$env_found = false;
$zoho_vars = [];
foreach ($env_paths as $env_path) {
echo "Checking for .env at: " . $env_path . "\n";
if (file_exists($env_path)) {
echo "FOUND .env file at: " . $env_path . "\n";
$env_found = true;
// Check for Zoho variables in the .env file
$env_contents = file_get_contents($env_path);
$env_lines = explode("\n", $env_contents);
foreach ($env_lines as $line) {
$line = trim($line);
if (empty($line) || strpos($line, '#') === 0) {
continue;
}
if (strpos($line, '=') !== false) {
list($key, $value) = explode('=', $line, 2);
$key = trim($key);
if (strpos($key, 'ZOHO_') === 0) {
$zoho_vars[] = $key;
}
}
}
echo "Found " . count($zoho_vars) . " Zoho-related variables in .env\n";
if (count($zoho_vars) > 0) {
echo "Variables: " . implode(', ', $zoho_vars) . "\n";
}
break;
}
}
if (!$env_found) {
echo "WARNING: No .env file found in any standard location.\n";
}
// Check for zoho-config.php
$config_file = dirname(__FILE__) . '/includes/zoho/zoho-config.php';
echo "\nChecking for zoho-config.php at: " . $config_file . "\n";
if (file_exists($config_file)) {
echo "FOUND zoho-config.php at: " . $config_file . "\n";
// Check if we can require the file
try {
require_once($config_file);
echo "Successfully included zoho-config.php\n";
// Check if essential constants are defined
$required_constants = [
'ZOHO_CLIENT_ID',
'ZOHO_CLIENT_SECRET',
'ZOHO_REFRESH_TOKEN',
];
$missing_constants = [];
foreach ($required_constants as $constant) {
if (!defined($constant) || empty(constant($constant))) {
$missing_constants[] = $constant;
}
}
if (count($missing_constants) > 0) {
echo "WARNING: The following required constants are missing or empty: " . implode(', ', $missing_constants) . "\n";
} else {
echo "All required Zoho constants are defined.\n";
}
} catch (Exception $e) {
echo "ERROR: Could not include zoho-config.php: " . $e->getMessage() . "\n";
}
} else {
echo "WARNING: zoho-config.php not found.\n";
}
// Check if the auth class is available
$auth_file = dirname(__FILE__) . '/includes/zoho/class-zoho-crm-auth.php';
echo "\nChecking for class-zoho-crm-auth.php at: " . $auth_file . "\n";
if (file_exists($auth_file)) {
echo "FOUND class-zoho-crm-auth.php at: " . $auth_file . "\n";
// Check if load_env_variables method exists
$file_contents = file_get_contents($auth_file);
if (strpos($file_contents, 'load_env_variables') !== false) {
echo "load_env_variables method exists in auth class\n";
} else {
echo "WARNING: load_env_variables method not found in auth class\n";
}
// Try to instantiate the class
try {
require_once($auth_file);
if (class_exists('HVAC_Zoho_CRM_Auth')) {
$auth = new HVAC_Zoho_CRM_Auth();
echo "Successfully instantiated HVAC_Zoho_CRM_Auth class\n";
// Check configuration status
$status = $auth->get_configuration_status();
echo "\nConfiguration status:\n";
foreach ($status as $key => $value) {
echo "- " . $key . ": " . ($value ? 'Yes' : 'No') . "\n";
}
} else {
echo "ERROR: HVAC_Zoho_CRM_Auth class not found after including file\n";
}
} catch (Exception $e) {
echo "ERROR: Could not instantiate HVAC_Zoho_CRM_Auth: " . $e->getMessage() . "\n";
}
} else {
echo "WARNING: class-zoho-crm-auth.php not found.\n";
}
// Check WordPress options
echo "\nChecking WordPress options for Zoho data:\n";
$options = [
'hvac_zoho_access_token' => get_option('hvac_zoho_access_token'),
'hvac_zoho_token_expiry' => get_option('hvac_zoho_token_expiry'),
'hvac_zoho_refresh_token' => get_option('hvac_zoho_refresh_token'),
];
foreach ($options as $key => $value) {
echo "- " . $key . ": " . (!empty($value) ? 'Set (length: ' . strlen($value) . ')' : 'Not set') . "\n";
}
// Check log file
$log_dir = dirname(__FILE__) . '/includes/logs';
$log_file = $log_dir . '/zoho-debug.log';
echo "\nChecking for log directory at: " . $log_dir . "\n";
if (file_exists($log_dir)) {
echo "FOUND log directory at: " . $log_dir . "\n";
echo "Checking for log file at: " . $log_file . "\n";
if (file_exists($log_file)) {
echo "FOUND log file at: " . $log_file . "\n";
echo "Log file size: " . filesize($log_file) . " bytes\n";
echo "Last few log entries:\n";
// Display last 10 lines of the log file
$log_contents = file_get_contents($log_file);
$log_lines = explode("\n", $log_contents);
$last_lines = array_slice($log_lines, -10);
foreach ($last_lines as $line) {
echo $line . "\n";
}
} else {
echo "WARNING: Log file not found. This means no logging has occurred yet.\n";
}
} else {
echo "WARNING: Log directory not found. Creating directory...\n";
if (mkdir($log_dir, 0755, true)) {
echo "Successfully created log directory.\n";
} else {
echo "ERROR: Could not create log directory. Check permissions.\n";
}
}
echo "\n=== Environment Check Complete ===\n";
echo "If you continue to experience issues, please share this output with support.\n";
EOF
# Create the deployment script
cat > ${TMP_DIR}/deploy.sh << 'EOF'
#!/bin/bash
# Deploy Zoho CRM integration fixes
# Copy files to their correct locations
echo "Copying class-zoho-crm-auth.php..."
cp -f includes/zoho/class-zoho-crm-auth.php ${PLUGIN_PATH}/includes/zoho/
echo "Copying class-zoho-admin.php..."
cp -f includes/admin/class-zoho-admin.php ${PLUGIN_PATH}/includes/admin/
echo "Copying check-zoho-env.php..."
cp -f check-zoho-env.php ${PLUGIN_PATH}/
# Create logs directory if it doesn't exist
echo "Creating logs directory if needed..."
mkdir -p ${PLUGIN_PATH}/includes/logs
chmod 755 ${PLUGIN_PATH}/includes/logs
# Set proper permissions
echo "Setting file permissions..."
chmod 644 ${PLUGIN_PATH}/includes/zoho/class-zoho-crm-auth.php
chmod 644 ${PLUGIN_PATH}/includes/admin/class-zoho-admin.php
chmod 755 ${PLUGIN_PATH}/check-zoho-env.php
# Create logs directory if it doesn't exist
mkdir -p ${PLUGIN_PATH}/includes/logs
chmod 755 ${PLUGIN_PATH}/includes/logs
echo "Clearing WordPress cache..."
wp cache flush --path=${REMOTE_DIR} 2>/dev/null || echo "Cache flush failed, but continuing..."
echo "Deployment completed successfully!"
EOF
chmod +x ${TMP_DIR}/deploy.sh
echo -e "${YELLOW}3. Uploading files to staging server${NC}"
# Upload files to staging server
scp -r ${TMP_DIR}/* ${STAGING_USER}@${STAGING_HOST}:~/ || {
echo -e "${RED}Error: Failed to upload files to staging server${NC}"
rm -rf ${TMP_DIR}
exit 1
}
echo -e "${GREEN}Files uploaded successfully.${NC}"
# Execute deployment script on server
echo -e "${YELLOW}4. Executing deployment script on staging server${NC}"
ssh ${STAGING_USER}@${STAGING_HOST} "cd ~/ && PLUGIN_PATH=${PLUGIN_PATH} bash ./deploy.sh" || {
echo -e "${RED}Error: Failed to execute deployment script${NC}"
rm -rf ${TMP_DIR}
exit 1
}
# Clean up temporary files
echo -e "${YELLOW}5. Cleaning up temporary files${NC}"
rm -rf ${TMP_DIR}
ssh ${STAGING_USER}@${STAGING_HOST} "rm -rf ~/includes ~/check-zoho-env.php ~/deploy.sh"
echo -e "${GREEN}========================================"
echo -e "Zoho CRM integration fixes deployed successfully!"
echo -e "========================================${NC}"
echo -e "${YELLOW}To test the connection:${NC}"
echo -e "1. Log in to the WordPress admin panel"
echo -e "2. Navigate to 'HVAC Community Events' > 'Zoho CRM Sync'"
echo -e "3. Click 'Test Connection' to verify the integration"
echo -e ""
echo -e "${YELLOW}If you need to diagnose issues further:${NC}"
echo -e "Access the diagnostic tool at: https://wordpress-974670-5399585.cloudwaysapps.com/wp-content/plugins/hvac-community-events/check-zoho-env.php?run_check=1"
echo -e ""
echo -e "${YELLOW}If you need to restore the original files:${NC}"
echo -e "ssh ${STAGING_USER}@${STAGING_HOST}"
echo -e "cp ${PLUGIN_PATH}/includes/backup-$(date +%Y%m%d)/class-zoho-crm-auth.php.bak ${PLUGIN_PATH}/includes/zoho/class-zoho-crm-auth.php"
echo -e "cp ${PLUGIN_PATH}/includes/backup-$(date +%Y%m%d)/class-zoho-admin.php.bak ${PLUGIN_PATH}/includes/admin/class-zoho-admin.php"
echo -e ""
exit 0