مستندات'; $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); });