- Implement singleton pattern for HVAC_Enhanced_Settings to prevent duplicate initialization - Fix jQuery selector error by checking for valid hash selectors before using $(href) - Add default email templates with professional copy for trainer notifications - Update plugin version to 1.0.1 for cache busting - Remove duplicate Enhanced Settings initialization from HVAC_Community_Events - Add force cache refresh suffix to admin scripts This resolves the duplicate content issue on email templates page and fixes JavaScript errors in the admin interface. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
910 lines
No EOL
38 KiB
PHP
910 lines
No EOL
38 KiB
PHP
<?php
|
|
/**
|
|
* Zoho CRM Admin Interface
|
|
*
|
|
* @package HVACCommunityEvents
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Zoho CRM Admin Class
|
|
*/
|
|
class HVAC_Zoho_Admin {
|
|
|
|
/**
|
|
* Instance of this class
|
|
*
|
|
* @var HVAC_Zoho_Admin
|
|
*/
|
|
private static $instance = null;
|
|
|
|
/**
|
|
* Get instance of this class
|
|
*
|
|
* @return HVAC_Zoho_Admin
|
|
*/
|
|
public static function instance() {
|
|
if (null === self::$instance) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Initialize the admin interface
|
|
*/
|
|
private 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_action('wp_ajax_hvac_zoho_save_credentials', array($this, 'save_credentials'));
|
|
add_action('wp_ajax_hvac_zoho_flush_rewrite_rules', array($this, 'flush_rewrite_rules_ajax'));
|
|
// Add simple test handler
|
|
add_action('wp_ajax_hvac_zoho_simple_test', array($this, 'simple_test'));
|
|
// Add OAuth callback handler - only use one method to prevent duplicates
|
|
add_action('init', array($this, 'add_oauth_rewrite_rule'), 5);
|
|
add_filter('query_vars', array($this, 'add_oauth_query_vars'), 10, 1);
|
|
add_action('template_redirect', array($this, 'handle_oauth_template_redirect'));
|
|
|
|
// Ensure rewrite rules are flushed when plugin is activated
|
|
register_activation_hook(HVAC_PLUGIN_FILE, array($this, 'flush_rewrite_rules_on_activation'));
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
// Only load on Zoho admin page
|
|
if ($hook !== 'hvac-community-events_page_hvac-zoho-sync') {
|
|
return;
|
|
}
|
|
|
|
wp_enqueue_script(
|
|
'hvac-zoho-admin',
|
|
HVAC_PLUGIN_URL . 'assets/js/zoho-admin.js',
|
|
array('jquery'),
|
|
HVAC_PLUGIN_VERSION,
|
|
true
|
|
);
|
|
|
|
wp_localize_script('hvac-zoho-admin', 'hvacZoho', array(
|
|
'ajaxUrl' => admin_url('admin-ajax.php'),
|
|
'nonce' => wp_create_nonce('hvac_zoho_nonce')
|
|
));
|
|
|
|
// Add inline test script for debugging
|
|
wp_add_inline_script('hvac-zoho-admin', '
|
|
console.log("Zoho admin script loaded");
|
|
jQuery(document).ready(function($) {
|
|
console.log("DOM ready, setting up click handler");
|
|
$(document).on("click", "#test-zoho-connection", function() {
|
|
console.log("Test button clicked - inline script");
|
|
});
|
|
});
|
|
');
|
|
|
|
wp_enqueue_style(
|
|
'hvac-zoho-admin',
|
|
HVAC_PLUGIN_URL . 'assets/css/zoho-admin.css',
|
|
array(),
|
|
HVAC_PLUGIN_VERSION
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Render admin page
|
|
*/
|
|
public function render_admin_page() {
|
|
$site_url = get_site_url();
|
|
|
|
// Debug logging
|
|
|
|
// More robust production detection
|
|
$parsed_url = parse_url($site_url);
|
|
$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
|
|
|
|
// Remove www prefix for comparison
|
|
$clean_host = preg_replace('/^www\./', '', $host);
|
|
|
|
// Check if this is production
|
|
$is_production = ($clean_host === 'upskillhvac.com');
|
|
|
|
// Double-check with string comparison as fallback
|
|
if (!$is_production) {
|
|
$is_production = (strpos($site_url, 'upskillhvac.com') !== false &&
|
|
strpos($site_url, 'staging') === false &&
|
|
strpos($site_url, 'test') === false &&
|
|
strpos($site_url, 'dev') === false &&
|
|
strpos($site_url, 'cloudwaysapps.com') === false);
|
|
}
|
|
|
|
// Set staging as opposite of production
|
|
$is_staging = !$is_production;
|
|
|
|
|
|
// Get stored credentials
|
|
$client_id = get_option('hvac_zoho_client_id', '');
|
|
$client_secret = get_option('hvac_zoho_client_secret', '');
|
|
$stored_refresh_token = get_option('hvac_zoho_refresh_token', '');
|
|
$has_credentials = !empty($client_id) && !empty($client_secret);
|
|
|
|
// Handle form submission
|
|
if (isset($_GET['credentials_saved'])) {
|
|
echo '<div class="notice notice-success is-dismissible"><p>Zoho CRM credentials saved successfully!</p></div>';
|
|
}
|
|
if (isset($_GET['oauth_success'])) {
|
|
echo '<div class="notice notice-success is-dismissible"><p>OAuth authorization completed successfully!</p></div>';
|
|
}
|
|
if (isset($_GET['oauth_error'])) {
|
|
echo '<div class="notice notice-error is-dismissible"><p>OAuth authorization failed. Please try again.</p></div>';
|
|
}
|
|
|
|
?>
|
|
<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>
|
|
<p><strong>OAuth Redirect URI:</strong> <?php echo esc_html($site_url . '/oauth/callback'); ?></p>
|
|
<p><em>Use this redirect URI in your Zoho OAuth app configuration.</em></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<!-- Credentials Configuration Section -->
|
|
<div class="hvac-zoho-credentials">
|
|
<h2>🔑 Zoho CRM Credentials</h2>
|
|
<form id="zoho-credentials-form" method="post">
|
|
<?php wp_nonce_field('hvac_zoho_credentials', 'hvac_zoho_nonce'); ?>
|
|
|
|
<table class="form-table">
|
|
<tr>
|
|
<th scope="row">
|
|
<label for="zoho_client_id">Client ID</label>
|
|
</th>
|
|
<td>
|
|
<input type="text" id="zoho_client_id" name="zoho_client_id"
|
|
value="<?php echo esc_attr($client_id); ?>"
|
|
class="regular-text"
|
|
placeholder="1000.XXXXXXXXXXXXXXXXXXXXXXXX" />
|
|
<p class="description">
|
|
Your Zoho OAuth Client ID from the Zoho Developer Console.
|
|
<a href="https://accounts.zoho.com/developerconsole" target="_blank">Get your Client ID</a>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">
|
|
<label for="zoho_client_secret">Client Secret</label>
|
|
</th>
|
|
<td>
|
|
<input type="password" id="zoho_client_secret" name="zoho_client_secret"
|
|
value="<?php echo esc_attr($client_secret); ?>"
|
|
class="regular-text"
|
|
placeholder="Enter your client secret" />
|
|
<p class="description">
|
|
Your Zoho OAuth Client Secret from the Zoho Developer Console.
|
|
<button type="button" id="toggle-secret" class="button button-small">Show</button>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">OAuth Redirect URI</th>
|
|
<td>
|
|
<code><?php echo esc_html($site_url . '/oauth/callback'); ?></code>
|
|
<p class="description">
|
|
Use this exact URL in your Zoho OAuth app configuration.
|
|
<button type="button" id="copy-redirect-uri" class="button button-small">Copy</button>
|
|
<button type="button" id="flush-rewrite-rules" class="button button-small">Flush Rules</button>
|
|
</p>
|
|
<?php
|
|
// Debug: Check if rewrite rule exists
|
|
$rewrite_rules = get_option('rewrite_rules');
|
|
$oauth_rule_exists = isset($rewrite_rules['^oauth/callback/?$']);
|
|
?>
|
|
<p class="description" style="color: <?php echo $oauth_rule_exists ? '#46b450' : '#dc3232'; ?>">
|
|
OAuth rewrite rule: <?php echo $oauth_rule_exists ? '✓ Active' : '✗ Missing (click Flush Rules)'; ?>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">Connection Status</th>
|
|
<td>
|
|
<?php if (!$has_credentials): ?>
|
|
<span class="dashicons dashicons-dismiss" style="color: #dc3232;"></span>
|
|
<span style="color: #dc3232;">No credentials configured</span>
|
|
<?php elseif (empty($stored_refresh_token)): ?>
|
|
<span class="dashicons dashicons-warning" style="color: #ffb900;"></span>
|
|
<span style="color: #ffb900;">Credentials set, OAuth authorization required</span>
|
|
<?php else: ?>
|
|
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
|
|
<span style="color: #46b450;">Connected and authorized</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<p class="submit">
|
|
<button type="submit" class="button button-primary" id="save-credentials">
|
|
Save Credentials
|
|
</button>
|
|
<?php if ($has_credentials && empty($stored_refresh_token)): ?>
|
|
<button type="button" class="button button-secondary" id="start-oauth" style="margin-left: 10px;">
|
|
🚀 Authorize with Zoho
|
|
</button>
|
|
<?php endif; ?>
|
|
</p>
|
|
</form>
|
|
</div>
|
|
|
|
<?php if ($has_credentials): ?>
|
|
<div class="hvac-zoho-status">
|
|
<h2>Connection Test</h2>
|
|
<p>Test your Zoho CRM connection to ensure everything is working properly.</p>
|
|
|
|
<?php if (empty($stored_refresh_token)): ?>
|
|
<div class="notice notice-warning">
|
|
<p><strong>⚠️ OAuth Authorization Required</strong></p>
|
|
<p>You have saved credentials but need to authorize the application with Zoho CRM.</p>
|
|
<p>Click "Authorize with Zoho" above to complete the setup.</p>
|
|
</div>
|
|
<?php else: ?>
|
|
<button class="button button-primary" id="test-connection">Test Connection</button>
|
|
<div id="connection-status"></div>
|
|
<?php endif; ?>
|
|
</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>
|
|
|
|
<script>
|
|
jQuery(document).ready(function($) {
|
|
// Toggle password visibility
|
|
$('#toggle-secret').on('click', function() {
|
|
var passwordField = $('#zoho_client_secret');
|
|
var toggleBtn = $(this);
|
|
|
|
if (passwordField.attr('type') === 'password') {
|
|
passwordField.attr('type', 'text');
|
|
toggleBtn.text('Hide');
|
|
} else {
|
|
passwordField.attr('type', 'password');
|
|
toggleBtn.text('Show');
|
|
}
|
|
});
|
|
|
|
// Copy redirect URI to clipboard
|
|
$('#copy-redirect-uri').on('click', function() {
|
|
var redirectUri = '<?php echo esc_js($site_url . '/oauth/callback'); ?>';
|
|
navigator.clipboard.writeText(redirectUri).then(function() {
|
|
$('#copy-redirect-uri').text('Copied!').prop('disabled', true);
|
|
setTimeout(function() {
|
|
$('#copy-redirect-uri').text('Copy').prop('disabled', false);
|
|
}, 2000);
|
|
});
|
|
});
|
|
|
|
// Flush rewrite rules
|
|
$('#flush-rewrite-rules').on('click', function() {
|
|
var button = $(this);
|
|
button.prop('disabled', true).text('Flushing...');
|
|
|
|
$.post(ajaxurl, {
|
|
action: 'hvac_zoho_flush_rewrite_rules'
|
|
}, function(response) {
|
|
if (response.success) {
|
|
button.text('Flushed!').css('color', '#46b450');
|
|
setTimeout(function() {
|
|
location.reload(); // Reload to update the status
|
|
}, 1000);
|
|
} else {
|
|
button.text('Error').css('color', '#dc3232');
|
|
setTimeout(function() {
|
|
button.prop('disabled', false).text('Flush Rules').css('color', '');
|
|
}, 2000);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Handle credentials form submission
|
|
$('#zoho-credentials-form').on('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
var formData = {
|
|
action: 'hvac_zoho_save_credentials',
|
|
zoho_client_id: $('#zoho_client_id').val(),
|
|
zoho_client_secret: $('#zoho_client_secret').val(),
|
|
nonce: $('input[name="hvac_zoho_nonce"]').val()
|
|
};
|
|
|
|
$('#save-credentials').prop('disabled', true).text('Saving...');
|
|
|
|
$.post(ajaxurl, formData, function(response) {
|
|
if (response.success) {
|
|
window.location.href = window.location.href + '&credentials_saved=1';
|
|
} else {
|
|
alert('Error saving credentials: ' + response.data.message);
|
|
$('#save-credentials').prop('disabled', false).text('Save Credentials');
|
|
}
|
|
});
|
|
});
|
|
|
|
// Handle OAuth authorization
|
|
$('#start-oauth').on('click', function() {
|
|
var clientId = $('#zoho_client_id').val();
|
|
var clientSecret = $('#zoho_client_secret').val();
|
|
|
|
if (!clientId || !clientSecret) {
|
|
alert('Please save your credentials first before starting OAuth authorization.');
|
|
return;
|
|
}
|
|
|
|
// Generate OAuth URL
|
|
var redirectUri = '<?php echo esc_js($site_url . '/oauth/callback'); ?>';
|
|
var scopes = 'ZohoCRM.settings.ALL,ZohoCRM.modules.ALL,ZohoCRM.users.ALL,ZohoCRM.org.ALL,ZohoCRM.bulk.READ';
|
|
var oauthUrl = 'https://accounts.zoho.com/oauth/v2/auth?' +
|
|
'scope=' + encodeURIComponent(scopes) +
|
|
'&client_id=' + encodeURIComponent(clientId) +
|
|
'&response_type=code' +
|
|
'&access_type=offline' +
|
|
'&redirect_uri=' + encodeURIComponent(redirectUri) +
|
|
'&prompt=consent';
|
|
|
|
// Open OAuth URL in the same window to handle callback properly
|
|
window.location.href = oauthUrl;
|
|
});
|
|
});
|
|
</script>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Simple test handler to isolate issues
|
|
*/
|
|
public function simple_test() {
|
|
|
|
wp_send_json_success(array('message' => 'Simple test works!'));
|
|
}
|
|
|
|
/**
|
|
* Save Zoho CRM credentials
|
|
*/
|
|
public function save_credentials() {
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(array('message' => 'Unauthorized access'));
|
|
return;
|
|
}
|
|
|
|
if (!check_ajax_referer('hvac_zoho_credentials', 'nonce', false)) {
|
|
wp_send_json_error(array('message' => 'Invalid nonce'));
|
|
return;
|
|
}
|
|
|
|
$client_id = sanitize_text_field($_POST['zoho_client_id']);
|
|
$client_secret = sanitize_text_field($_POST['zoho_client_secret']);
|
|
|
|
if (empty($client_id) || empty($client_secret)) {
|
|
wp_send_json_error(array('message' => 'Client ID and Client Secret are required'));
|
|
return;
|
|
}
|
|
|
|
// Validate Client ID format (should start with "1000.")
|
|
if (!preg_match('/^1000\.[A-Z0-9]+$/', $client_id)) {
|
|
wp_send_json_error(array('message' => 'Invalid Client ID format. Should start with "1000."'));
|
|
return;
|
|
}
|
|
|
|
// Save credentials
|
|
update_option('hvac_zoho_client_id', $client_id);
|
|
update_option('hvac_zoho_client_secret', $client_secret);
|
|
|
|
// Clear any existing refresh token since credentials changed
|
|
delete_option('hvac_zoho_refresh_token');
|
|
|
|
wp_send_json_success(array(
|
|
'message' => 'Credentials saved successfully',
|
|
'client_id_preview' => substr($client_id, 0, 10) . '...'
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Flush rewrite rules via AJAX
|
|
*/
|
|
public function flush_rewrite_rules_ajax() {
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(array('message' => 'Unauthorized access'));
|
|
return;
|
|
}
|
|
|
|
// Clear any cached rules first
|
|
wp_cache_delete('rewrite_rules', 'options');
|
|
|
|
// Add OAuth rewrite rules multiple ways
|
|
add_rewrite_rule('^oauth/callback/?$', 'index.php?hvac_oauth_callback=1', 'top');
|
|
add_rewrite_rule('oauth/callback/?$', 'index.php?hvac_oauth_callback=1', 'top');
|
|
|
|
// Force hard flush
|
|
flush_rewrite_rules(true);
|
|
|
|
// Clear cache again
|
|
wp_cache_delete('rewrite_rules', 'options');
|
|
|
|
// Add rules again and soft flush
|
|
$this->add_oauth_rewrite_rule();
|
|
flush_rewrite_rules(false);
|
|
|
|
// Force WordPress to regenerate rules
|
|
delete_option('rewrite_rules');
|
|
wp_cache_delete('rewrite_rules', 'options');
|
|
$wp_rewrite = $GLOBALS['wp_rewrite'];
|
|
$wp_rewrite->flush_rules(true);
|
|
|
|
// Verify the rule exists after flush
|
|
$rewrite_rules = get_option('rewrite_rules', array());
|
|
$oauth_rule_exists = isset($rewrite_rules['^oauth/callback/?$']) || isset($rewrite_rules['oauth/callback/?$']);
|
|
|
|
// Log for debugging
|
|
|
|
wp_send_json_success(array(
|
|
'message' => 'Rewrite rules flushed successfully',
|
|
'oauth_rule_exists' => $oauth_rule_exists,
|
|
'total_rules' => count($rewrite_rules),
|
|
'rules_sample' => array_slice(array_keys($rewrite_rules), 0, 5)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Flush rewrite rules on plugin activation
|
|
*/
|
|
public function flush_rewrite_rules_on_activation() {
|
|
$this->add_oauth_rewrite_rule();
|
|
flush_rewrite_rules();
|
|
}
|
|
|
|
/**
|
|
* Add OAuth query vars
|
|
*/
|
|
public function add_oauth_query_vars($vars) {
|
|
// Only add if not already present to avoid duplicates
|
|
if (!in_array('hvac_oauth_callback', $vars)) {
|
|
$vars[] = 'hvac_oauth_callback';
|
|
}
|
|
return $vars;
|
|
}
|
|
|
|
/**
|
|
* Add OAuth query vars to public query vars
|
|
*/
|
|
public function add_public_query_vars() {
|
|
global $wp;
|
|
// Check if already added to avoid duplicates
|
|
if (!in_array('hvac_oauth_callback', $wp->public_query_vars)) {
|
|
$wp->add_query_var('hvac_oauth_callback');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse OAuth request using parse_request hook
|
|
*/
|
|
public function parse_oauth_request($wp) {
|
|
|
|
// Check if this is an OAuth callback request
|
|
if (preg_match('#^/oauth/callback/?#', $_SERVER['REQUEST_URI'])) {
|
|
|
|
// Check if we have the code parameter
|
|
if (isset($_GET['code'])) {
|
|
$this->process_oauth_callback();
|
|
exit;
|
|
} else {
|
|
|
|
wp_die('OAuth callback missing authorization code');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add OAuth callback rewrite rule
|
|
*/
|
|
public function add_oauth_rewrite_rule() {
|
|
add_rewrite_rule('^oauth/callback/?$', 'index.php?hvac_oauth_callback=1', 'top');
|
|
|
|
// Also add alternative rule patterns
|
|
add_rewrite_rule('oauth/callback/?$', 'index.php?hvac_oauth_callback=1', 'top');
|
|
|
|
// Force flush if the rule doesn't exist
|
|
$rewrite_rules = get_option('rewrite_rules');
|
|
if (!$rewrite_rules || !isset($rewrite_rules['^oauth/callback/?$'])) {
|
|
// Set a flag to flush rules on next page load
|
|
update_option('hvac_oauth_rules_need_flush', true);
|
|
|
|
// Also try to flush immediately if we're in admin
|
|
if (is_admin()) {
|
|
flush_rewrite_rules(false);
|
|
}
|
|
}
|
|
|
|
// Check if we need to flush based on flag
|
|
if (get_option('hvac_oauth_rules_need_flush')) {
|
|
flush_rewrite_rules(false);
|
|
delete_option('hvac_oauth_rules_need_flush');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle OAuth template redirect
|
|
*/
|
|
public function handle_oauth_template_redirect() {
|
|
if (get_query_var('hvac_oauth_callback')) {
|
|
$this->process_oauth_callback();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process OAuth callback from Zoho
|
|
*/
|
|
public function process_oauth_callback() {
|
|
|
|
if (!isset($_GET['code'])) {
|
|
|
|
wp_die('OAuth callback missing authorization code');
|
|
}
|
|
|
|
|
|
// Get credentials from WordPress options
|
|
$client_id = get_option('hvac_zoho_client_id', '');
|
|
$client_secret = get_option('hvac_zoho_client_secret', '');
|
|
|
|
if (empty($client_id) || empty($client_secret)) {
|
|
wp_die('OAuth callback error: Missing client credentials. Please configure your Zoho CRM credentials first.');
|
|
}
|
|
|
|
// Exchange authorization code for tokens
|
|
$token_url = 'https://accounts.zoho.com/oauth/v2/token';
|
|
$redirect_uri = get_site_url() . '/oauth/callback';
|
|
|
|
$token_params = array(
|
|
'grant_type' => 'authorization_code',
|
|
'client_id' => $client_id,
|
|
'client_secret' => $client_secret,
|
|
'redirect_uri' => $redirect_uri,
|
|
'code' => $_GET['code']
|
|
);
|
|
|
|
$response = wp_remote_post($token_url, array(
|
|
'body' => $token_params,
|
|
'timeout' => 30
|
|
));
|
|
|
|
if (is_wp_error($response)) {
|
|
wp_redirect(admin_url('admin.php?page=hvac-zoho-sync&oauth_error=1&error_msg=' . urlencode($response->get_error_message())));
|
|
exit;
|
|
}
|
|
|
|
$body = wp_remote_retrieve_body($response);
|
|
$token_data = json_decode($body, true);
|
|
|
|
// Check for errors in response
|
|
if (isset($token_data['error'])) {
|
|
wp_redirect(admin_url('admin.php?page=hvac-zoho-sync&oauth_error=1&error_msg=' . urlencode($token_data['error'])));
|
|
exit;
|
|
}
|
|
|
|
if (!isset($token_data['access_token'])) {
|
|
|
|
wp_redirect(admin_url('admin.php?page=hvac-zoho-sync&oauth_error=1&error_msg=' . urlencode('No access token received')));
|
|
exit;
|
|
}
|
|
|
|
// Save tokens
|
|
update_option('hvac_zoho_access_token', $token_data['access_token']);
|
|
update_option('hvac_zoho_token_expires', time() + ($token_data['expires_in'] ?? 3600));
|
|
|
|
// Refresh token might not be returned on subsequent authorizations
|
|
if (isset($token_data['refresh_token']) && !empty($token_data['refresh_token'])) {
|
|
update_option('hvac_zoho_refresh_token', $token_data['refresh_token']);
|
|
} else {
|
|
$existing_refresh = get_option('hvac_zoho_refresh_token');
|
|
if (empty($existing_refresh)) {
|
|
// This is critical - we need a refresh token for long-term access
|
|
// Store a warning but still complete the flow
|
|
update_option('hvac_zoho_missing_refresh_token', true);
|
|
} else {
|
|
}
|
|
}
|
|
|
|
// Success - redirect to admin page with success message
|
|
wp_redirect(admin_url('admin.php?page=hvac-zoho-sync&oauth_success=1'));
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Handle OAuth callback from Zoho (legacy method)
|
|
*/
|
|
public function handle_oauth_callback() {
|
|
// This method is kept for backwards compatibility
|
|
// The main handling is now done in template_redirect
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Test Zoho connection
|
|
*/
|
|
public function test_connection() {
|
|
|
|
try {
|
|
check_ajax_referer('hvac_zoho_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(array('message' => 'Unauthorized access'));
|
|
return;
|
|
}
|
|
|
|
// Get credentials from WordPress options
|
|
$client_id = get_option('hvac_zoho_client_id', '');
|
|
$client_secret = get_option('hvac_zoho_client_secret', '');
|
|
|
|
// Check configuration before attempting connection
|
|
if (empty($client_id)) {
|
|
wp_send_json_error(array(
|
|
'message' => 'Configuration Error',
|
|
'error' => 'Client ID is not configured',
|
|
'details' => 'Please enter your Zoho CRM Client ID in the form above',
|
|
'help' => 'Get your Client ID from the Zoho Developer Console'
|
|
));
|
|
return;
|
|
}
|
|
|
|
if (empty($client_secret)) {
|
|
wp_send_json_error(array(
|
|
'message' => 'Configuration Error',
|
|
'error' => 'Client Secret is not configured',
|
|
'details' => 'Please enter your Zoho CRM Client Secret in the form above',
|
|
'help' => 'Get your Client Secret from the Zoho Developer Console'
|
|
));
|
|
return;
|
|
}
|
|
|
|
// Check if we have stored refresh token from previous OAuth
|
|
$stored_refresh_token = get_option('hvac_zoho_refresh_token');
|
|
|
|
if (empty($stored_refresh_token)) {
|
|
|
|
$site_url = get_site_url();
|
|
$redirect_uri = $site_url . '/oauth/callback';
|
|
$scopes = 'ZohoCRM.settings.ALL,ZohoCRM.modules.ALL,ZohoCRM.users.ALL,ZohoCRM.org.ALL,ZohoCRM.bulk.READ';
|
|
$auth_url = 'https://accounts.zoho.com/oauth/v2/auth?' . http_build_query(array(
|
|
'scope' => $scopes,
|
|
'client_id' => $client_id,
|
|
'response_type' => 'code',
|
|
'access_type' => 'offline',
|
|
'redirect_uri' => $redirect_uri,
|
|
'prompt' => 'consent'
|
|
));
|
|
|
|
wp_send_json_error(array(
|
|
'message' => 'OAuth Authorization Required',
|
|
'error' => 'No stored refresh token found',
|
|
'details' => 'You have valid credentials but need to complete OAuth authorization to get a fresh token',
|
|
'help' => 'Click the "Authorize with Zoho" button above to complete setup',
|
|
'next_steps' => array(
|
|
'1. Click the "Authorize with Zoho" button above',
|
|
'2. Sign in to your Zoho account',
|
|
'3. Grant permissions to the application',
|
|
'4. You will be redirected back and the refresh token will be saved automatically'
|
|
),
|
|
'auth_url' => $auth_url,
|
|
'credentials_status' => array(
|
|
'client_id' => substr($client_id, 0, 10) . '...',
|
|
'client_secret_exists' => true,
|
|
'refresh_token_exists' => false
|
|
)
|
|
));
|
|
return;
|
|
}
|
|
|
|
// We have a refresh token - test the actual API connection
|
|
require_once HVAC_PLUGIN_DIR . 'includes/zoho/class-zoho-crm-auth.php';
|
|
$auth = new HVAC_Zoho_CRM_Auth();
|
|
|
|
|
|
// Test API call
|
|
$response = $auth->make_api_request('/settings/modules', 'GET');
|
|
|
|
if (is_wp_error($response)) {
|
|
wp_send_json_error(array(
|
|
'message' => 'API Connection Failed',
|
|
'error' => $response->get_error_message(),
|
|
'details' => 'WordPress HTTP error occurred'
|
|
));
|
|
return;
|
|
}
|
|
|
|
if (isset($response['error'])) {
|
|
|
|
// Check if it's an invalid token error
|
|
if (strpos($response['error'], 'invalid') !== false || strpos($response['error'], 'expired') !== false) {
|
|
|
|
// Clear the invalid token and trigger OAuth
|
|
delete_option('hvac_zoho_refresh_token');
|
|
|
|
$auth_url = $auth->get_authorization_url();
|
|
$site_url = get_site_url();
|
|
$redirect_uri = $site_url . '/oauth/callback';
|
|
$scopes = 'ZohoCRM.settings.ALL,ZohoCRM.modules.ALL,ZohoCRM.users.ALL,ZohoCRM.org.ALL,ZohoCRM.bulk.READ';
|
|
$new_auth_url = 'https://accounts.zoho.com/oauth/v2/auth?' . http_build_query(array(
|
|
'scope' => $scopes,
|
|
'client_id' => $client_id,
|
|
'response_type' => 'code',
|
|
'access_type' => 'offline',
|
|
'redirect_uri' => $redirect_uri,
|
|
'prompt' => 'consent'
|
|
));
|
|
|
|
wp_send_json_error(array(
|
|
'message' => 'OAuth Authorization Required',
|
|
'error' => 'Refresh token expired or invalid',
|
|
'details' => 'The stored refresh token is no longer valid. Please re-authorize.',
|
|
'help' => 'Refresh the page and click "Authorize with Zoho" again',
|
|
'next_steps' => array(
|
|
'1. Refresh this page',
|
|
'2. Click the "Authorize with Zoho" button',
|
|
'3. Sign in to your Zoho account',
|
|
'4. Grant permissions to the application',
|
|
'5. You will be redirected back and the refresh token will be saved automatically'
|
|
),
|
|
'auth_url' => $new_auth_url,
|
|
'credentials_status' => array(
|
|
'client_id' => substr($client_id, 0, 10) . '...',
|
|
'client_secret_exists' => true,
|
|
'refresh_token_exists' => false
|
|
)
|
|
));
|
|
return;
|
|
}
|
|
|
|
wp_send_json_error(array(
|
|
'message' => 'Zoho API Error',
|
|
'error' => $response['error'],
|
|
'details' => isset($response['details']) ? $response['details'] : 'No additional details'
|
|
));
|
|
return;
|
|
}
|
|
|
|
// Success!
|
|
wp_send_json_success(array(
|
|
'message' => 'Connection successful!',
|
|
'modules' => isset($response['modules']) ? count($response['modules']) . ' modules available' : 'API connected',
|
|
'credentials_status' => array(
|
|
'client_id' => substr($client_id, 0, 10) . '...',
|
|
'client_secret_exists' => true,
|
|
'refresh_token_exists' => true,
|
|
'api_working' => true
|
|
)
|
|
));
|
|
} catch (Exception $e) {
|
|
wp_send_json_error(array(
|
|
'message' => 'Connection test failed due to exception',
|
|
'error' => $e->getMessage(),
|
|
'file' => $e->getFile() . ':' . $e->getLine()
|
|
));
|
|
} catch (Error $e) {
|
|
wp_send_json_error(array(
|
|
'message' => 'Connection test failed due to PHP error',
|
|
'error' => $e->getMessage(),
|
|
'file' => $e->getFile() . ':' . $e->getLine()
|
|
));
|
|
} catch (Throwable $e) {
|
|
wp_send_json_error(array(
|
|
'message' => 'Connection test failed due to fatal error',
|
|
'error' => $e->getMessage(),
|
|
'file' => $e->getFile() . ':' . $e->getLine()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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_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()
|
|
));
|
|
}
|
|
}
|
|
}
|
|
?>
|