مستندات';
$links[] = 'پشتیبانی';
return $links;
}
add_filter(
'plugin_action_links_' . plugin_basename(__FILE__),
'xcrm_plugin_action_links'
);
function xcrm_plugin_action_links($links) {
$links[] = 'داشبورد';
$links[] = 'تنظیمات';
return $links;
}
// کلاس اصلی پلاگین
class XCRM {
private static $instance = null;
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->init_hooks();
}
private function init_hooks() {
add_action('init', [$this, 'init']);
add_action('admin_menu', [$this, 'add_admin_menu']);
add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']);
add_action('wp_enqueue_scripts', [$this, 'enqueue_frontend_scripts']);
add_action('admin_notices', [$this, 'show_wizard_notice']);
add_action('plugins_loaded', [$this, 'init_woocommerce']);
add_action('init', [$this, 'init_gravityforms']);
add_action('wp_ajax_xcrm_save_wizard', [$this, 'save_wizard']);
add_action('wp_ajax_xcrm_verify_register_otp', [$this, 'verify_register_otp']);
add_action('wp_ajax_xcrm_login', [$this, 'login']);
add_action('wp_ajax_xcrm_verify_login_2fa', [$this, 'verify_login_2fa']);
add_action('wp_ajax_xcrm_logout', [$this, 'logout']);
add_action('wp_ajax_xcrm_install_sdk', [$this, 'install_sdk']);
add_action('wp_ajax_xcrm_recheck_sdk', [$this, 'recheck_sdk']);
add_action('wp_ajax_xcrm_search_contacts', [$this, 'ajax_search_contacts']);
add_action('wp_ajax_xcrm_get_journey', [$this, 'ajax_get_journey']);
add_action('wp_ajax_xcrm_get_product_behavior', [$this, 'ajax_get_product_behavior']);
add_action('wp_ajax_xcrm_get_customer_acquisition', [$this, 'ajax_get_customer_acquisition']);
add_action('wp_ajax_xcrm_get_revenue_data', [$this, 'ajax_get_revenue_data']);
add_action('wp_ajax_xcrm_get_opportunity_data', [$this, 'ajax_get_opportunity_data']);
add_action('wp_ajax_xcrm_get_abandoned_data', [$this, 'ajax_get_abandoned_data']);
add_action('wp_ajax_xcrm_get_traffic_data', [$this, 'ajax_get_traffic_data']);
add_action('wp_ajax_xcrm_get_behavior_data', [$this, 'ajax_get_behavior_data']);
add_action('wp_ajax_xcrm_sync_users', [$this, 'ajax_sync_users']);
add_action('wp_ajax_xcrm_get_user_data', [$this, 'ajax_get_user_data']);
add_action('wp_ajax_xcrm_get_data_readiness', [$this, 'ajax_get_data_readiness']);
add_action('wp_ajax_xcrm_toggle_demo_mode', [$this, 'ajax_toggle_demo_mode']);
add_action('wp_ajax_xcrm_get_pipeline_stages', [$this, 'ajax_get_pipeline_stages']);
add_action('wp_ajax_xcrm_get_pipelines', [$this, 'ajax_get_pipelines']);
add_action('wp_ajax_xcrm_get_groups', [$this, 'ajax_get_groups']);
add_action('wp_ajax_xcrm_accept_consent', [$this, 'ajax_accept_consent']);
add_action('admin_init', [$this, 'register_settings']);
add_action('admin_init', [$this, 'verify_api_key_daily']);
add_action('user_register', [$this, 'sync_new_user'], 10, 2);
add_action('profile_update', [$this, 'sync_updated_user'], 10, 2);
add_action('wp_login', [$this, 'track_login'], 10, 2);
add_action('user_register', [$this, 'track_signup'], 10, 2);
}
public function init_woocommerce() {
if (class_exists('WooCommerce')) {
xcrm_register_adapter(new XCRM_WooCommerce_Adapter());
}
}
public function init_gravityforms() {
new XCRM_GravityForms();
}
public function init() {
xcrm_adapter_manager()->init_all();
}
public function add_admin_menu() {
add_menu_page(
'پیشخوان XForosh',
'پیشخوان XForosh',
'manage_options',
'xcrm',
[$this, 'render_admin_page'],
'dashicons-groups',
30
);
add_submenu_page(
'xcrm',
'منابع درآمد',
'منابع درآمد',
'manage_options',
'xcrm-stats-revenue',
[$this, 'render_stats_revenue']
);
add_submenu_page(
'xcrm',
'فرصت فروش',
'فرصت فروش',
'manage_options',
'xcrm-stats-opportunity',
[$this, 'render_stats_opportunity']
);
add_submenu_page(
'xcrm',
'سبدهای رهاشده',
'سبدهای رهاشده',
'manage_options',
'xcrm-stats-abandoned',
[$this, 'render_stats_abandoned']
);
add_submenu_page(
'xcrm',
'منابع ترافیک',
'منابع ترافیک',
'manage_options',
'xcrm-stats-traffic',
[$this, 'render_stats_traffic']
);
add_submenu_page(
'xcrm',
'رفتار مشتریان',
'رفتار مشتریان',
'manage_options',
'xcrm-stats-behavior',
[$this, 'render_stats_behavior']
);
add_submenu_page(
'xcrm',
'Customer Journey',
'Customer Journey',
'manage_options',
'xcrm-stats-journey',
[$this, 'render_stats_journey']
);
add_submenu_page(
'xcrm',
'مسیر ورود مشتری',
'مسیر ورود مشتری',
'manage_options',
'xcrm-stats-acquisition',
[$this, 'render_stats_acquisition']
);
add_submenu_page(
'xcrm',
'تنظیمات',
'تنظیمات',
'manage_options',
'xcrm-settings',
[$this, 'render_settings_page']
);
}
public function render_admin_page() {
if ($this->show_wizard()) {
$this->render_wizard();
return;
}
include XCRM_PLUGIN_DIR . 'admin/views/main.php';
}
private function check_api_key() {
$api_key = get_option('xcrm_api_key', '');
if (empty($api_key)) {
wp_safe_redirect(admin_url('admin.php?page=xcrm'));
exit;
}
}
public function render_stats_revenue() {
$this->check_api_key();
include XCRM_PLUGIN_DIR . 'admin/views/stats/revenue.php';
}
public function render_stats_opportunity() {
$this->check_api_key();
include XCRM_PLUGIN_DIR . 'admin/views/stats/opportunity.php';
}
public function render_stats_abandoned() {
$this->check_api_key();
include XCRM_PLUGIN_DIR . 'admin/views/stats/abandoned.php';
}
public function render_stats_traffic() {
$this->check_api_key();
include XCRM_PLUGIN_DIR . 'admin/views/stats/traffic.php';
}
public function render_stats_behavior() {
$this->check_api_key();
include XCRM_PLUGIN_DIR . 'admin/views/stats/behavior.php';
}
public function render_stats_journey() {
$this->check_api_key();
include XCRM_PLUGIN_DIR . 'admin/views/stats/journey.php';
}
public function render_stats_acquisition() {
$this->check_api_key();
include XCRM_PLUGIN_DIR . 'admin/views/stats/acquisition.php';
}
public function render_settings_page() {
$this->check_api_key();
include XCRM_PLUGIN_DIR . 'admin/views/settings.php';
}
public function register_settings() {
register_setting('xcrm_settings', 'xcrm_sync_user', [
'sanitize_callback' => function($value) {
return $value ? 1 : 0;
},
]);
}
public function enqueue_admin_scripts($hook) {
if (strpos($hook, 'xcrm') === false) {
return;
}
wp_enqueue_style(
'xcrm-admin',
XCRM_PLUGIN_URL . 'admin/css/admin.css',
[],
XCRM_VERSION
);
wp_enqueue_script(
'xcrm-admin',
XCRM_PLUGIN_URL . 'admin/js/admin.js',
['jquery'],
XCRM_VERSION,
true
);
if ($this->show_wizard()) {
wp_enqueue_style(
'xcrm-wizard',
XCRM_PLUGIN_URL . 'admin/css/wizard.css',
[],
XCRM_VERSION
);
wp_enqueue_script(
'xcrm-wizard',
XCRM_PLUGIN_URL . 'admin/js/wizard.js',
['jquery'],
XCRM_VERSION,
true
);
wp_localize_script('xcrm-wizard', 'xcrm_wizard', [
'nonce' => wp_create_nonce('xcrm_wizard_nonce'),
]);
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only page slug for asset loading, not form processing.
$page = isset($_GET['page']) ? sanitize_key(wp_unslash($_GET['page'])) : '';
$stats_nonce = wp_create_nonce('xcrm_stats_nonce');
$sdk_nonce = wp_create_nonce('xcrm_sdk_nonce');
$sync_nonce = wp_create_nonce('xcrm_sync_nonce');
$page_scripts = [
'xcrm' => 'main.js',
'xcrm-settings' => 'settings.js',
'xcrm-stats-revenue' => 'stats-revenue.js',
'xcrm-stats-opportunity'=> 'stats-opportunity.js',
'xcrm-stats-abandoned' => 'stats-abandoned.js',
'xcrm-stats-traffic' => 'stats-traffic.js',
'xcrm-stats-behavior' => 'stats-behavior.js',
'xcrm-stats-journey' => 'stats-journey.js',
'xcrm-stats-acquisition'=> 'stats-acquisition.js',
];
if (isset($page_scripts[$page])) {
wp_enqueue_script(
'xcrm-page',
XCRM_PLUGIN_URL . 'admin/js/pages/' . $page_scripts[$page],
['jquery'],
XCRM_VERSION,
true
);
wp_localize_script('xcrm-page', 'xcrmPage', [
'statsNonce' => $stats_nonce,
'sdkNonce' => $sdk_nonce,
'syncNonce' => $sync_nonce,
]);
}
}
public function enqueue_frontend_scripts() {
if (!get_option(XCRM_CONSENT_OPTION, false)) {
return;
}
wp_register_script(
'xcrm-sdk',
XCRM_PLUGIN_URL . 'assets/js/xcrm.min.js',
[],
XCRM_VERSION,
true
);
wp_enqueue_script('xcrm-sdk');
$public_company_id = get_option('xcrm_public_company_id', '');
$nonce = wp_create_nonce('xcrm_user_data_nonce');
$ajax_url = admin_url('admin-ajax.php?action=xcrm_get_user_data');
$debug = (defined('XCRM_DEBUG') && XCRM_DEBUG);
$config = wp_json_encode([
'cpid' => $public_company_id,
'user-url' => $ajax_url,
'api-nonce' => $nonce,
'debug' => $debug,
'requireConsent'=> false,
]);
wp_add_inline_script('xcrm-sdk', 'window.xcrmConfig = ' . $config . ';', 'before');
}
public function show_wizard_notice() {
if (!$this->show_wizard()) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only page slug check, not form processing.
if (isset($_GET['page']) && $_GET['page'] === 'xcrm') {
return;
}
$admin_url = admin_url('admin.php?page=xcrm');
?>
XForosh: برای شروع کار با افزونه، مراحل راهاندازی را تکمیل کنید.
شروع راهاندازی
'دسترسی غیرمجاز']);
}
$first_name = sanitize_text_field(wp_unslash($_POST['first_name'] ?? ''));
$last_name = sanitize_text_field(wp_unslash($_POST['last_name'] ?? ''));
$email = sanitize_email(wp_unslash($_POST['email'] ?? ''));
$phone = sanitize_text_field(wp_unslash($_POST['phone'] ?? ''));
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Passwords must not be sanitized; wp_unslash() is the correct handling.
$password = wp_unslash($_POST['password'] ?? '');
$consent = isset($_POST['consent']) && $_POST['consent'] === '1';
if (strlen($password) < 8) {
wp_send_json_error([
'message' => 'رمز عبور باید حداقل ۸ کاراکتر باشد'
]);
}
if (!$consent) {
wp_send_json_error([
'message' => 'برای ادامه باید با جمعآوری داده موافقت کنید'
]);
}
update_option('xcrm_data_consent', true);
$response = xcrm_auth()->register_send_otp([
'full_name' => $first_name . ' ' . $last_name,
'email' => $email,
'phone' => $phone,
'password' => $password,
'user_type' => 'CEO',
]);
if (isset($response['success']) && $response['success']) {
update_option('xcrm_register_token', $response['data']['token'] ?? '');
update_option('xcrm_register_phone', $phone);
update_option('xcrm_register_first_name', $first_name);
update_option('xcrm_register_last_name', $last_name);
update_option('xcrm_register_email', $email);
wp_send_json_success([
'message' => $response['message'] ?? 'کد تایید ارسال شد',
'requires_otp' => true
]);
} else {
$error_msg = XCRM_API::get_instance()->get_error_message($response);
wp_send_json_error([
'message' => $error_msg
]);
}
}
public function verify_register_otp() {
check_ajax_referer('xcrm_wizard_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$code = sanitize_text_field(wp_unslash($_POST['code'] ?? ''));
$token = get_option('xcrm_register_token', '');
if (empty($token) || empty($code)) {
wp_send_json_error([
'message' => 'اطلاعات نامعتبر'
]);
}
$response = xcrm_auth()->register_confirm_otp([
'token' => $token,
'code' => $code,
]);
if (isset($response['success']) && $response['success']) {
$jwt = $response['data']['tokens']['access'] ?? '';
$refresh = $response['data']['tokens']['refresh'] ?? '';
update_option('xcrm_jwt_token', $jwt);
update_option('xcrm_jwt_refresh', $refresh);
$this->fetch_and_save_api_key($jwt);
$user_id = get_current_user_id();
$first_name = get_option('xcrm_register_first_name', '');
$last_name = get_option('xcrm_register_last_name', '');
$email = get_option('xcrm_register_email', '');
$phone = get_option('xcrm_register_phone', '');
wp_update_user([
'ID' => $user_id,
'first_name' => $first_name,
'last_name' => $last_name,
'user_email' => $email,
]);
update_user_meta($user_id, 'xcrm_phone', $phone);
update_option('xcrm_wizard_completed', true);
update_option('xcrm_admin_user', $user_id);
delete_option('xcrm_register_token');
delete_option('xcrm_register_phone');
delete_option('xcrm_register_first_name');
delete_option('xcrm_register_last_name');
delete_option('xcrm_register_email');
wp_send_json_success([
'message' => 'ثبتنام با موفقیت انجام شد'
]);
} else {
$error_msg = XCRM_API::get_instance()->get_error_message($response);
wp_send_json_error([
'message' => $error_msg
]);
}
}
public function login() {
check_ajax_referer('xcrm_wizard_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$phone = sanitize_text_field(wp_unslash($_POST['phone'] ?? ''));
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Passwords must not be sanitized; wp_unslash() is the correct handling.
$password = wp_unslash($_POST['password'] ?? '');
$consent = isset($_POST['consent']) && $_POST['consent'] === '1';
if (empty($phone) || empty($password)) {
wp_send_json_error([
'message' => 'لطفاً تمام فیلدها را پر کنید'
]);
}
if (!$consent) {
wp_send_json_error([
'message' => 'برای ادامه باید با جمعآوری داده موافقت کنید'
]);
}
update_option('xcrm_data_consent', true);
$response = xcrm_auth()->login([
'phone' => $phone,
'password' => $password,
]);
if (isset($response['success']) && $response['success']) {
$data = $response['data'] ?? [];
if (!empty($data['requires_2fa'])) {
update_option('xcrm_login_2fa_token', $data['otp_token'] ?? '');
update_option('xcrm_login_2fa_type', $data['otp_type'] ?? 'PHONE');
wp_send_json_success([
'requires_2fa' => true,
'otp_type' => $data['otp_type'] ?? 'PHONE',
'message' => 'کد تایید دو مرحلهای ارسال شد'
]);
} else {
$jwt = $data['tokens']['access'] ?? '';
$refresh = $data['tokens']['refresh'] ?? '';
update_option('xcrm_jwt_token', $jwt);
update_option('xcrm_jwt_refresh', $refresh);
$this->fetch_and_save_api_key($jwt);
$user_id = get_current_user_id();
update_option('xcrm_wizard_completed', true);
update_option('xcrm_admin_user', $user_id);
wp_send_json_success([
'message' => 'ورود موفقیتآمیز بود'
]);
}
} else {
$error_msg = XCRM_API::get_instance()->get_error_message($response);
wp_send_json_error([
'message' => $error_msg
]);
}
}
public function verify_login_2fa() {
check_ajax_referer('xcrm_wizard_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$code = sanitize_text_field(wp_unslash($_POST['code'] ?? ''));
$token = get_option('xcrm_login_2fa_token', '');
if (empty($token) || empty($code)) {
wp_send_json_error([
'message' => 'اطلاعات نامعتبر'
]);
}
$response = xcrm_auth()->login_confirm_2fa([
'token' => $token,
'code' => $code,
]);
if (isset($response['success']) && $response['success']) {
$jwt = $response['data']['tokens']['access'] ?? '';
$refresh = $response['data']['tokens']['refresh'] ?? '';
update_option('xcrm_jwt_token', $jwt);
update_option('xcrm_jwt_refresh', $refresh);
$this->fetch_and_save_api_key($jwt);
$user_id = get_current_user_id();
update_option('xcrm_wizard_completed', true);
update_option('xcrm_admin_user', $user_id);
delete_option('xcrm_login_2fa_token');
delete_option('xcrm_login_2fa_type');
wp_send_json_success([
'message' => 'ورود موفقیتآمیز بود'
]);
} else {
$error_msg = XCRM_API::get_instance()->get_error_message($response);
wp_send_json_error([
'message' => $error_msg
]);
}
}
private function fetch_and_save_api_key($jwt) {
$response = xcrm_auth()->create_api_key($jwt, [
'api_key_type' => 'wordpress',
]);
if (isset($response['success']) && $response['success'] && isset($response['data']['raw_key'])) {
$api_key = $response['data']['raw_key'];
update_option('xcrm_api_key', $api_key);
}
$jwt_data = $this->decode_jwt($jwt);
if ($jwt_data) {
if (isset($jwt_data['company_id'])) {
update_option('xcrm_company_id', $jwt_data['company_id']);
}
if (isset($jwt_data['company_pid'])) {
update_option('xcrm_public_company_id', $jwt_data['company_pid']);
}
// ست کردن URL شرکت
if (isset($jwt_data['company_id'])) {
$site_url = home_url();
xcrm_client()->update_company($jwt, $jwt_data['company_id'], [
'website' => $site_url,
]);
}
}
}
public function decode_jwt($jwt) {
$parts = explode('.', $jwt);
if (count($parts) !== 3) {
return false;
}
$payload = base64_decode(strtr($parts[1], '-_', '+/'));
return json_decode($payload, true);
}
public function logout() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$this->do_logout();
wp_send_json_success([
'message' => 'با موفقیت از حساب خارج شدید'
]);
}
public function install_sdk() {
check_ajax_referer('xcrm_sdk_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
if ($this->is_sdk_script_present()) {
update_option('xcrm_sdk_installed', true);
wp_send_json_error([
'message' => 'SDK قبلاً نصب شده است. برای به روز رسانی صفحه را بروزرسانی کنید'
]);
}
$sdk_path = XCRM_PLUGIN_DIR . 'assets/js/xcrm.min.js';
if (file_exists($sdk_path)) {
update_option('xcrm_sdk_installed', true);
wp_send_json_success([
'message' => 'SDK با موفقیت نصب شد'
]);
} else {
wp_send_json_error([
'message' => 'فایل SDK یافت نشد'
]);
}
}
private function is_sdk_script_present() {
$installed = get_option('xcrm_sdk_installed', false);
if ($installed) {
return true;
}
$sdk_path = XCRM_PLUGIN_DIR . 'assets/js/xcrm.min.js';
return file_exists($sdk_path);
}
private function add_sdk_to_theme($sdk_link) {
update_option('xcrm_sdk_link', $sdk_link);
}
public function recheck_sdk() {
check_ajax_referer('xcrm_sdk_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
if ($this->is_sdk_script_present()) {
update_option('xcrm_sdk_installed', true);
wp_send_json_success([
'message' => 'SDK در قالب شناسایی شد و وضعیت بروزرسانی شد'
]);
} else {
update_option('xcrm_sdk_installed', false);
wp_send_json_error([
'message' => 'SDK در قالب یافت نشد'
]);
}
}
public function ajax_search_contacts() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$query = sanitize_text_field(wp_unslash($_GET['q'] ?? ''));
if (strlen($query) < 2) {
wp_send_json_error([
'message' => 'حداقل ۲ کاراکتر وارد کنید'
]);
}
$response = xcrm_stats()->search_contacts($query);
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error([
'message' => $response['error'] ?? 'خطا در جستجو'
]);
}
}
public function ajax_get_revenue_data() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$response = xcrm_stats()->get_revenue_sources();
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error(['message' => $response['error'] ?? 'خطا']);
}
}
public function ajax_get_opportunity_data() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$response = xcrm_stats()->get_sales_opportunities();
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error(['message' => $response['error'] ?? 'خطا']);
}
}
public function ajax_get_abandoned_data() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$response = xcrm_stats()->get_abandoned_carts();
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error(['message' => $response['error'] ?? 'خطا']);
}
}
public function ajax_get_traffic_data() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$response = xcrm_stats()->get_traffic_sources();
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error(['message' => $response['error'] ?? 'خطا']);
}
}
public function ajax_get_behavior_data() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$response = xcrm_stats()->get_customer_behavior();
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error(['message' => $response['error'] ?? 'خطا']);
}
}
public function ajax_get_journey() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$contact_id = intval($_GET['contact_id'] ?? 0);
if (!$contact_id) {
wp_send_json_error([
'message' => 'شناسه مشتری نامعتبر است'
]);
}
$response = xcrm_stats()->get_customer_journey($contact_id);
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error([
'message' => $response['error'] ?? 'خطا در دریافت اطلاعات'
]);
}
}
public function ajax_get_product_behavior() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$product_id = intval($_GET['product_id'] ?? 0);
if (!$product_id) {
wp_send_json_error([
'message' => 'شناسه محصول نامعتبر است'
]);
}
$response = xcrm_stats()->get_product_behavior($product_id);
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error([
'message' => $response['error'] ?? 'خطا در دریافت اطلاعات'
]);
}
}
public function ajax_get_customer_acquisition() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$customer_id = intval($_GET['customer_id'] ?? 0);
if (!$customer_id) {
wp_send_json_error([
'message' => 'شناسه مشتری نامعتبر است'
]);
}
$response = xcrm_stats()->get_customer_acquisition($customer_id);
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error([
'message' => $response['error'] ?? 'خطا در دریافت اطلاعات'
]);
}
}
public function ajax_sync_users() {
check_ajax_referer('xcrm_sync_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
if (!get_option(XCRM_CONSENT_OPTION, false)) {
wp_send_json_error(['message' => 'ابتدا با جمعآوری داده موافقت کنید']);
}
$offset = intval($_POST['offset'] ?? 0);
$batch_size = 10;
$args = [
'offset' => $offset,
'number' => $batch_size,
'fields' => ['ID'],
];
$users = get_users($args);
$total_users = count_users()['total_users'];
$synced = 0;
$skipped = 0;
foreach ($users as $user) {
$client_id = get_user_meta($user->ID, 'xcrm_client_id', true);
$client_pid = get_user_meta($user->ID, 'xcrm_client_pid', true);
if (!empty($client_id) && !empty($client_pid)) {
$skipped++;
continue;
}
$user_data = get_userdata($user->ID);
$full_name = trim($user_data->first_name . ' ' . $user_data->last_name);
if (empty($full_name)) {
$full_name = $user_data->display_name;
}
$response = xcrm_client()->register([
'full_name' => $full_name,
'first_name' => $user_data->first_name,
'last_name' => $user_data->last_name,
'CUID' => (string) $user->ID,
'email' => $user_data->user_email,
'phone' => get_user_meta($user->ID, 'xcrm_phone', true) ?: '',
'source' => 'wordpress',
]);
if (isset($response['success']) && $response['success']) {
if (isset($response['data']['id'])) {
update_user_meta($user->ID, 'xcrm_client_id', $response['data']['id']);
}
if (isset($response['data']['PID'])) {
update_user_meta($user->ID, 'xcrm_client_pid', $response['data']['PID']);
}
$synced++;
}
}
$next_offset = $offset + $batch_size;
$has_more = $next_offset < $total_users;
$percent = $total_users > 0 ? round(($next_offset / $total_users) * 100) : 100;
if ($percent > 100) $percent = 100;
wp_send_json_success([
'message' => "همگامسازی: {$synced} ارسال شد، {$skipped} رد شد",
'offset' => $next_offset,
'has_more' => $has_more,
'percent' => $percent,
]);
}
public function track_login($user_login, $user) {
if (!get_option(XCRM_CONSENT_OPTION, false)) {
return;
}
if (!is_a($user, 'WP_User')) {
return;
}
if (user_can($user, 'manage_options')) {
return;
}
$company_pid = get_option('xcrm_company_id', '');
$client_pid = get_user_meta($user->ID, 'xcrm_client_pid', true);
if (empty($client_pid)) {
return;
}
$event = [
'company_pid' => (int) $company_pid,
'luid' => '',
'session_id' => '',
'event_name' => 'login',
'event_time' => gmdate('c'),
'device' => ['platform' => 'web', 'os' => ['name' => '', 'version' => ''], 'browser' => ['name' => '', 'version' => ''], 'manufacturer' => '', 'model' => '', 'carrier' => ''],
'location' => ['ip' => $this->get_client_ip(), 'country' => '', 'city' => ''],
'marketing' => ['channel' => '', 'utm' => ['source' => '', 'medium' => '', 'campaign' => ''], 'campaign_id' => '', 'journey_id' => ''],
'dynamic' => [
'event_properties' => [
'method' => 'wordpress',
'email' => $user->user_email,
'phone' => get_user_meta($user->ID, 'xcrm_phone', true) ?: '',
'success' => true,
'ip_address' => $this->get_client_ip(),
],
'user_attributes' => [
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => $user->user_email,
'client_pid' => $client_pid ? (string) $client_pid : null,
],
],
];
try {
xcrm_events()->track('login', $event);
} catch (\Throwable $e) {
}
}
public function track_signup($user_id, $userdata = []) {
if (!get_option(XCRM_CONSENT_OPTION, false)) {
return;
}
$user = get_userdata($user_id);
if (!$user || is_wp_error($user)) {
return;
}
if (user_can($user, 'manage_options')) {
return;
}
$client_pid = get_user_meta($user_id, 'xcrm_client_pid', true);
if (empty($client_pid)) {
return;
}
$company_pid = get_option('xcrm_company_id', '');
$event = [
'company_pid' => (int) $company_pid,
'luid' => '',
'client_pid' => (string) $client_pid,
'session_id' => '',
'event_name' => 'signup',
'event_time' => gmdate('c'),
'device' => ['platform' => 'web', 'os' => ['name' => '', 'version' => ''], 'browser' => ['name' => '', 'version' => ''], 'manufacturer' => '', 'model' => '', 'carrier' => ''],
'location' => ['ip' => $this->get_client_ip(), 'country' => '', 'city' => ''],
'marketing' => ['channel' => '', 'utm' => ['source' => '', 'medium' => '', 'campaign' => ''], 'campaign_id' => '', 'journey_id' => ''],
'dynamic' => [
'event_properties' => [
'method' => 'wordpress',
'email' => $user->user_email,
'phone' => get_user_meta($user_id, 'xcrm_phone', true) ?: '',
],
'user_attributes' => [
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => $user->user_email,
'client_pid' => (string) $client_pid,
],
],
];
try {
xcrm_events()->track('signup', $event);
} catch (\Throwable $e) {
}
}
private function get_client_ip() {
$keys = ['HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'];
foreach ($keys as $key) {
if (!empty($_SERVER[$key])) {
$ip = sanitize_text_field(wp_unslash($_SERVER[$key]));
$parts = explode(',', $ip);
return trim($parts[0]);
}
}
return '';
}
public function sync_new_user($user_id, $userdata = []) {
if (!get_option(XCRM_CONSENT_OPTION, false)) {
return;
}
if (!get_option('xcrm_sync_user')) {
return;
}
$client_id = get_user_meta($user_id, 'xcrm_client_id', true);
$client_pid = get_user_meta($user_id, 'xcrm_client_pid', true);
if (!empty($client_id) && !empty($client_pid)) {
return;
}
$user = get_userdata($user_id);
if (!$user || is_wp_error($user)) {
return;
}
$full_name = trim($user->first_name . ' ' . $user->last_name);
if (empty($full_name)) {
$full_name = $user->display_name;
}
try {
$response = xcrm_client()->register([
'full_name' => $full_name,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'CUID' => (string) $user_id,
'email' => $user->user_email,
'phone' => get_user_meta($user_id, 'xcrm_phone', true) ?: '',
'source' => 'wordpress',
]);
} catch (\Throwable $e) {
return;
}
if (isset($response['success']) && $response['success']) {
if (isset($response['data']['id'])) {
update_user_meta($user_id, 'xcrm_client_id', $response['data']['id']);
}
if (isset($response['data']['PID'])) {
update_user_meta($user_id, 'xcrm_client_pid', $response['data']['PID']);
}
}
}
public function sync_updated_user($user_id, $old_user_data) {
if (!get_option(XCRM_CONSENT_OPTION, false)) {
return;
}
$user = get_userdata($user_id);
if (!$user || is_wp_error($user)) {
return;
}
$client_id = get_user_meta($user_id, 'xcrm_client_id', true);
$full_name = trim($user->first_name . ' ' . $user->last_name);
if (empty($full_name)) {
$full_name = $user->display_name;
}
$user_data = [
'full_name' => $full_name,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'CUID' => (string) $user_id,
'email' => $user->user_email,
'phone' => get_user_meta($user_id, 'xcrm_phone', true) ?: '',
];
try {
if (empty($client_id)) {
$user_data['source'] = 'wordpress';
$response = xcrm_client()->register($user_data);
if (isset($response['success']) && $response['success']) {
if (isset($response['data']['id'])) {
update_user_meta($user_id, 'xcrm_client_id', $response['data']['id']);
}
if (isset($response['data']['PID'])) {
update_user_meta($user_id, 'xcrm_client_pid', $response['data']['PID']);
}
}
} else {
$response = xcrm_client()->update($client_id, $user_data);
}
} catch (\Throwable $e) {
}
}
public function ajax_get_user_data() {
if (!is_user_logged_in()) {
status_header(404);
nocache_headers();
wp_send_json([], 404);
return;
}
check_ajax_referer('xcrm_user_data_nonce', 'nonce');
$user = wp_get_current_user();
$client_pid = get_user_meta($user->ID, 'xcrm_client_pid', true);
wp_send_json([
'client_pid' => $client_pid ? (string) $client_pid : null,
'CUID' => (string) $user->ID,
'name' => $user->display_name,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => $user->user_email,
'phone' => get_user_meta($user->ID, 'xcrm_phone', true) ?: '',
'gender' => get_user_meta($user->ID, 'xcrm_gender', true) ?: '',
'city' => get_user_meta($user->ID, 'xcrm_city', true) ?: '',
'country' => get_user_meta($user->ID, 'xcrm_country', true) ?: '',
]);
}
public function ajax_get_data_readiness() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$response = xcrm_stats()->get_data_readiness();
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error([
'message' => $response['error'] ?? 'خطا در دریافت وضعیت آمادگی',
]);
}
}
public function ajax_toggle_demo_mode() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$current = get_option('xcrm_use_fake_data', false);
$new_value = !$current;
update_option('xcrm_use_fake_data', $new_value);
wp_send_json_success([
'use_fake_data' => $new_value,
]);
}
public function ajax_get_pipeline_stages() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$pipeline_id = intval($_GET['pipeline_id'] ?? 0);
if (!$pipeline_id) {
wp_send_json_error(['message' => 'شناسه پایپلاین نامعتبر است']);
}
$response = xcrm_pipelines()->get_stages($pipeline_id);
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error([
'message' => $response['error'] ?? 'خطا در دریافت مراحل',
]);
}
}
public function ajax_get_pipelines() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$response = xcrm_pipelines()->get_pipelines();
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error([
'message' => $response['error'] ?? 'خطا در دریافت فرایندهای فروش',
]);
}
}
public function ajax_get_groups() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
$response = xcrm_pipelines()->get_groups();
if (isset($response['success']) && $response['success']) {
wp_send_json_success($response['data']);
} else {
wp_send_json_error([
'message' => $response['error'] ?? 'خطا در دریافت گروهها',
]);
}
}
public function ajax_accept_consent() {
check_ajax_referer('xcrm_stats_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'دسترسی غیرمجاز']);
}
update_option('xcrm_data_consent', true);
wp_send_json_success([
'message' => 'موافقت ثبت شد',
]);
}
public function verify_api_key_daily() {
$api_key = get_option('xcrm_api_key', '');
if (empty($api_key)) {
return;
}
$last_check = get_transient('xcrm_api_key_last_check');
if ($last_check !== false) {
return;
}
$response = xcrm_auth()->verify_api_key();
set_transient('xcrm_api_key_last_check', true, DAY_IN_SECONDS);
if (isset($response['success']) && $response['success'] && isset($response['data']['valid'])) {
if ($response['data']['valid'] === false) {
$this->do_logout();
}
} elseif (isset($response['http_code']) && $response['http_code'] === 401) {
$this->do_logout();
} elseif (isset($response['error'])) {
}
}
private function do_logout() {
delete_option('xcrm_api_key');
delete_option('xcrm_jwt_token');
delete_option('xcrm_jwt_refresh');
delete_option('xcrm_wizard_completed');
delete_option('xcrm_admin_user');
delete_option('xcrm_company_id');
delete_option('xcrm_public_company_id');
delete_option('xcrm_sync_user');
delete_option('xcrm_use_fake_data');
delete_option('xcrm_sdk_installed');
delete_option('xcrm_sdk_version');
delete_option('xcrm_sdk_link');
}
}
// راهاندازی پلاگین
function xcrm() {
return XCRM::get_instance();
}
// بارگذاری API
require_once XCRM_PLUGIN_DIR . 'api/class-xcrm-api.php';
require_once XCRM_PLUGIN_DIR . 'api/api-loader.php';
require_once XCRM_PLUGIN_DIR . 'admin/user-meta.php';
// بارگذاری اداپتورها
require_once XCRM_PLUGIN_DIR . 'adapters/class-xcrm-adapter.php';
require_once XCRM_PLUGIN_DIR . 'adapters/class-xcrm-woocommerce.php';
require_once XCRM_PLUGIN_DIR . 'adapters/class-xcrm-gravityforms.php';
// اجرای پلاگین
xcrm();
// فعالسازی پلاگین
register_activation_hook(__FILE__, function() {
delete_option('xcrm_wizard_completed');
add_option('xcrm_sync_user', 0);
});