__('Security check failed.', 'activity-log-pro'))); } // Check user capabilities if (!current_user_can('manage_options')) { wp_send_json_error(array('message' => __('You do not have permission to perform this action.', 'activity-log-pro'))); } // Check if integration ID is provided if (!isset($_POST['integration_id']) || empty($_POST['integration_id'])) { wp_send_json_error(array('message' => __('Integration ID is required.', 'activity-log-pro'))); } // Check if file is uploaded if (!isset($_FILES['integration_file']) || empty($_FILES['integration_file']['tmp_name'])) { wp_send_json_error(array('message' => __('No file was uploaded.', 'activity-log-pro'))); } // Get integration ID $integration_id = sanitize_text_field(wp_unslash($_POST['integration_id'])); // Validate file type $file_name = isset($_FILES['integration_file']['name']) ? sanitize_file_name(wp_unslash($_FILES['integration_file']['name'])) : ''; if (empty($file_name)) { wp_send_json_error(array('message' => __('Invalid file name.', 'activity-log-pro'))); } $file_type = wp_check_filetype(basename($file_name), array('php' => 'text/php')); if (!$file_type['ext']) { wp_send_json_error(array('message' => __('Invalid file type. Only PHP files are allowed.', 'activity-log-pro'))); } // Set the destination path directly in the integrations directory $destination = ACTLOGPRO_PLUGIN_DIR . 'integrations/class-alp-' . $integration_id . '-integration.php'; // Load the filesystem helper require_once ACTLOGPRO_PLUGIN_DIR . 'includes/class-alp-filesystem.php'; // Create a validation callback for the expected class $expected_class = 'ACTLOGPRO_' . ucfirst($integration_id) . '_Integration'; $validation_callback = function($content) use ($expected_class) { // Use regex to find the class declaration with more flexibility for whitespace $pattern = '/class\s+' . preg_quote($expected_class, '/') . '\s+/i'; if (!preg_match($pattern, $content)) { /* Translators: %s is the name of the expected integration class that should be in the file */ return new WP_Error('invalid_class', sprintf(__('Invalid integration file. The file does not contain the expected integration class "%s".', 'activity-log-pro'), $expected_class )); } return true; }; // Handle the file upload using our filesystem helper with proper validation if (!isset($_FILES['integration_file']) || !is_array($_FILES['integration_file'])) { wp_send_json_error(array('message' => __('No file was uploaded.', 'activity-log-pro'))); } // Sanitize and validate the uploaded file data $uploaded_file = array( 'name' => isset($_FILES['integration_file']['name']) ? sanitize_file_name($_FILES['integration_file']['name']) : '', 'type' => isset($_FILES['integration_file']['type']) ? sanitize_mime_type($_FILES['integration_file']['type']) : '', 'tmp_name' => isset($_FILES['integration_file']['tmp_name']) ? sanitize_text_field($_FILES['integration_file']['tmp_name']) : '', 'error' => isset($_FILES['integration_file']['error']) ? absint($_FILES['integration_file']['error']) : UPLOAD_ERR_NO_FILE, 'size' => isset($_FILES['integration_file']['size']) ? absint($_FILES['integration_file']['size']) : 0, ); // Validate file upload if ($uploaded_file['error'] !== UPLOAD_ERR_OK) { wp_send_json_error(array('message' => __('File upload failed.', 'activity-log-pro'))); } // Validate file type if ($uploaded_file['type'] !== 'text/x-php' && $uploaded_file['type'] !== 'application/x-php') { $file_extension = pathinfo($uploaded_file['name'], PATHINFO_EXTENSION); if (strtolower($file_extension) !== 'php') { wp_send_json_error(array('message' => __('Only PHP files are allowed.', 'activity-log-pro'))); } } // Validate file size (max 1MB) if ($uploaded_file['size'] > 1048576) { wp_send_json_error(array('message' => __('File size exceeds the maximum allowed limit of 1MB.', 'activity-log-pro'))); } $result = ACTLOGPRO_Filesystem::handle_uploaded_file($uploaded_file, $destination, array($validation_callback)); // Check for errors if (is_wp_error($result)) { wp_send_json_error(array('message' => $result->get_error_message())); } // Return success wp_send_json_success(array('message' => __('Integration file uploaded successfully.', 'activity-log-pro'))); } /** * Handle integration management (activation/deactivation). * * @since 1.0.0 */ public function handle_integration_management() { // Check nonce // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'actlogpro_ajax_nonce')) { wp_send_json_error(array('message' => __('Security check failed.', 'activity-log-pro'))); } // Check user capabilities if (!current_user_can('manage_options')) { wp_send_json_error(array('message' => __('You do not have permission to perform this action.', 'activity-log-pro'))); } // Check if integration ID is provided if (!isset($_POST['integration_id']) || empty($_POST['integration_id'])) { wp_send_json_error(array('message' => __('Integration ID is required.', 'activity-log-pro'))); } // Check if action is provided if (!isset($_POST['integration_action']) || empty($_POST['integration_action'])) { wp_send_json_error(array('message' => __('Action is required.', 'activity-log-pro'))); } // Get integration ID and action $integration_id = sanitize_text_field(wp_unslash($_POST['integration_id'])); $action = sanitize_text_field(wp_unslash($_POST['integration_action'])); // Get active integrations $active_integrations = get_option('actlogpro_active_integrations', array()); // Perform action if ($action === 'activate') { // Check if integration file exists $integration_file_path = ACTLOGPRO_PLUGIN_DIR . 'integrations/class-alp-' . $integration_id . '-integration.php'; $integration_file_exists = file_exists($integration_file_path); // For premium integrations, also check premium plugin directory if (!$integration_file_exists) { $is_premium_integration = ($integration_id === 'woocommerce' || $integration_id === 'yoast'); if ($is_premium_integration && defined('ACTLOGPRO_PREMIUM_PLUGIN_DIR')) { $premium_integration_file_path = ACTLOGPRO_PREMIUM_PLUGIN_DIR . 'integrations/class-alp-' . $integration_id . '-integration.php'; $integration_file_exists = file_exists($premium_integration_file_path); } } if (!$integration_file_exists) { wp_send_json_error(array( 'message' => __('Integration file not found.', 'activity-log-pro'), 'status' => 'not_installed', 'error_code' => 'file_not_found' )); } // Handle premium integrations differently $is_premium_integration = ($integration_id === 'woocommerce' || $integration_id === 'yoast'); // Remove from user deactivated list since user is manually activating $user_deactivated_integrations = get_option('actlogpro_user_deactivated_integrations', array()); $key = array_search($integration_id, $user_deactivated_integrations); if ($key !== false) { unset($user_deactivated_integrations[$key]); update_option('actlogpro_user_deactivated_integrations', array_values($user_deactivated_integrations)); } if ($is_premium_integration && ACTLOGPRO_Premium_Helper::is_premium_enabled()) { // For premium integrations when premium is active, use the extension interface if (class_exists('ACTLOGPRO_Extension_Interface')) { // Ensure premium features are registered by triggering the action do_action('actlogpro_register_premium_features'); $feature_id = $integration_id . '_integration'; // Check if the feature is now registered if (!ACTLOGPRO_Extension_Interface::is_premium_feature_available($feature_id) && !isset(ACTLOGPRO_Extension_Interface::get_premium_features()[$feature_id])) { wp_send_json_error(array( // translators: %s is the feature ID 'message' => sprintf(__('Premium feature "%s" is not registered. Please ensure the premium plugin is properly activated.', 'activity-log-pro'), $feature_id), 'debug_info' => array( 'feature_id' => $feature_id, 'registered_features' => array_keys(ACTLOGPRO_Extension_Interface::get_premium_features()), 'premium_enabled' => ACTLOGPRO_Premium_Helper::is_premium_enabled() ) )); } $result = ACTLOGPRO_Extension_Interface::set_premium_feature_status($feature_id, true); if ($result) { // Also add to active integrations for consistency if (!in_array($integration_id, $active_integrations)) { $active_integrations[] = $integration_id; update_option('actlogpro_active_integrations', $active_integrations); } wp_send_json_success(array('message' => __('Integration activated successfully.', 'activity-log-pro'))); } else { wp_send_json_error(array( 'message' => __('Failed to activate premium integration.', 'activity-log-pro'), 'debug_info' => array( 'feature_id' => $feature_id, 'feature_exists' => isset(ACTLOGPRO_Extension_Interface::get_premium_features()[$feature_id]), 'all_features' => array_keys(ACTLOGPRO_Extension_Interface::get_premium_features()) ) )); } } else { wp_send_json_error(array('message' => __('Extension interface not available.', 'activity-log-pro'))); } } else { // For non-premium integrations or when premium is not active, use the regular method if (!in_array($integration_id, $active_integrations)) { $active_integrations[] = $integration_id; update_option('actlogpro_active_integrations', $active_integrations); } wp_send_json_success(array('message' => __('Integration activated successfully.', 'activity-log-pro'))); } } elseif ($action === 'deactivate') { // Handle premium integrations differently $is_premium_integration = ($integration_id === 'woocommerce' || $integration_id === 'yoast'); // Track user deactivations to prevent auto-reactivation $user_deactivated_integrations = get_option('actlogpro_user_deactivated_integrations', array()); if (!in_array($integration_id, $user_deactivated_integrations)) { $user_deactivated_integrations[] = $integration_id; update_option('actlogpro_user_deactivated_integrations', $user_deactivated_integrations); } if ($is_premium_integration && ACTLOGPRO_Premium_Helper::is_premium_enabled()) { // For premium integrations when premium is active, use the extension interface if (class_exists('ACTLOGPRO_Extension_Interface')) { // Ensure premium features are registered by triggering the action do_action('actlogpro_register_premium_features'); $feature_id = $integration_id . '_integration'; $result = ACTLOGPRO_Extension_Interface::set_premium_feature_status($feature_id, false); if ($result) { // Also remove from active integrations for consistency $key = array_search($integration_id, $active_integrations); if ($key !== false) { unset($active_integrations[$key]); $new_active_integrations = array_values($active_integrations); update_option('actlogpro_active_integrations', $new_active_integrations); } wp_send_json_success(array('message' => __('Integration deactivated successfully.', 'activity-log-pro'))); } else { wp_send_json_error(array( 'message' => __('Failed to deactivate premium integration.', 'activity-log-pro'), 'debug_info' => array( 'feature_id' => $feature_id, 'feature_exists' => isset(ACTLOGPRO_Extension_Interface::get_premium_features()[$feature_id]), 'all_features' => array_keys(ACTLOGPRO_Extension_Interface::get_premium_features()) ) )); } } else { wp_send_json_error(array('message' => __('Extension interface not available.', 'activity-log-pro'))); } } else { // For non-premium integrations or when premium is not active, use the regular method $key = array_search($integration_id, $active_integrations); if ($key !== false) { unset($active_integrations[$key]); update_option('actlogpro_active_integrations', array_values($active_integrations)); } wp_send_json_success(array('message' => __('Integration deactivated successfully.', 'activity-log-pro'))); } } else { wp_send_json_error(array('message' => __('Invalid action.', 'activity-log-pro'))); } } } // Initialize the integration handler new ACTLOGPRO_Integration_Handler();